From a81cd96805ce6b65cca3a40ebbd3b2eb428abb7b Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 26 Dec 2012 21:10:49 +0100 Subject: Only create signatures with even S, and verification mode to check. To fix a minor malleability found by Sergio Lerner (reported here: https://bitcointalk.org/index.php?topic=8392.msg1245898#msg1245898) The problem is that if (R,S) is a valid ECDSA signature for a given message and public key, (R,-S) is also valid. Modulo N (the order of the secp256k1 curve), this means that both (R,S) and (R,N-S) are valid. Given that N is odd, S and N-S have a different lowest bit. We solve the problem by forcing signatures to have an even S value, excluding one of the alternatives. This commit just changes the signing code to always produce even S values, and adds a verification mode to check it. This code is not enabled anywhere yet. Existing tests in key_tests.cpp verify that the produced signatures are still valid. --- src/script.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/script.h') diff --git a/src/script.h b/src/script.h index 03afe8b652..fd5b12921e 100644 --- a/src/script.h +++ b/src/script.h @@ -32,9 +32,10 @@ enum enum { SCRIPT_VERIFY_NONE = 0, - SCRIPT_VERIFY_P2SH = (1U << 0), - SCRIPT_VERIFY_STRICTENC = (1U << 1), - SCRIPT_VERIFY_NOCACHE = (1U << 2), + SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts + SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys + SCRIPT_VERIFY_EVEN_S = (1U << 2), // enforce even S values in signatures (depends on STRICTENC) + SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it) }; enum txnouttype @@ -665,8 +666,8 @@ public: } }; -bool IsCanonicalPubKey(const std::vector &vchPubKey); -bool IsCanonicalSignature(const std::vector &vchSig); +bool IsCanonicalPubKey(const std::vector &vchPubKey, unsigned int flags); +bool IsCanonicalSignature(const std::vector &vchSig, unsigned int flags); bool EvalScript(std::vector >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType); bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); -- cgit v1.2.3