From 74f060294123687538cb85e7a639e79f93d31671 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Tue, 15 Jul 2014 21:53:35 +0400 Subject: [PATCH] Generate only signatures with even S values It's helpful against a minor malleability issue found by Sergio Lerner, check this thread for additional information https://bitcointalk.org/index.php?topic=8392.msg1245898#msg1245898 --- src/key.cpp | 27 ++++++++++++++++++++++++--- src/key.h | 1 + 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index d9c2832..381d346 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -285,14 +285,28 @@ CPubKey CKey::GetPubKey() const bool CKey::Sign(uint256 hash, std::vector& vchSig) { + vchSig.clear(); + ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); + if (sig==NULL) + return false; + // Force even S value in order to prevent signature modification issues. + if (BN_is_odd(sig->s)) { + const EC_GROUP *group = EC_KEY_get0_group(pkey); + CBigNum order; + EC_GROUP_get_order(group, &order, NULL); + BN_sub(sig->s, &order, sig->s); + } unsigned int nSize = ECDSA_size(pkey); vchSig.resize(nSize); // Make sure it is big enough - if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey)) - { + unsigned char *pos = &vchSig[0]; + nSize = i2d_ECDSA_SIG(sig, &pos); + ECDSA_SIG_free(sig); + vchSig.resize(nSize); // Shrink to fit actual size + // Testing our new signature + if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) { vchSig.clear(); return false; } - vchSig.resize(nSize); // Shrink to fit actual size return true; } @@ -306,6 +320,13 @@ bool CKey::SignCompact(uint256 hash, std::vector& vchSig) ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); if (sig==NULL) return false; + // Force even S value in order to prevent signature modification issues. + if (BN_is_odd(sig->s)) { + const EC_GROUP *group = EC_KEY_get0_group(pkey); + CBigNum order; + EC_GROUP_get_order(group, &order, NULL); + BN_sub(sig->s, &order, sig->s); + } vchSig.clear(); vchSig.resize(65,0); int nBitsR = BN_num_bits(sig->r); diff --git a/src/key.h b/src/key.h index 427a4be..51130f7 100644 --- a/src/key.h +++ b/src/key.h @@ -12,6 +12,7 @@ #include "serialize.h" #include "uint256.h" #include "hash.h" +#include "bignum.h" #include // for EC_KEY definition -- 1.7.1