diff --git a/src/Makefile.am b/src/Makefile.am index 8253c4ab14..c9adf859f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -86,6 +86,7 @@ BITCOIN_CORE_H = \ core_io.h \ crypter.h \ db.h \ + eccryptoverify.h \ ecwrapper.h \ hash.h \ init.h \ @@ -220,6 +221,7 @@ libbitcoin_common_a_SOURCES = \ core/transaction.cpp \ core_read.cpp \ core_write.cpp \ + eccryptoverify.cpp \ ecwrapper.cpp \ hash.cpp \ key.cpp \ diff --git a/src/eccryptoverify.cpp b/src/eccryptoverify.cpp new file mode 100644 index 0000000000..0a904f44ba --- /dev/null +++ b/src/eccryptoverify.cpp @@ -0,0 +1,63 @@ +#include "eccryptoverify.h" + +namespace { + +int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { + while (c1len > c2len) { + if (*c1) + return 1; + c1++; + c1len--; + } + while (c2len > c1len) { + if (*c2) + return -1; + c2++; + c2len--; + } + while (c1len > 0) { + if (*c1 > *c2) + return 1; + if (*c2 > *c1) + return -1; + c1++; + c2++; + c1len--; + } + return 0; +} + +/** Order of secp256k1's generator minus 1. */ +const unsigned char vchMaxModOrder[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 +}; + +/** Half of the order of secp256k1's generator minus 1. */ +const unsigned char vchMaxModHalfOrder[32] = { + 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, + 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 +}; + +const unsigned char vchZero[1] = {0}; +} // anon namespace + +namespace eccrypto { + +bool Check(const unsigned char *vch) { + return vch && + CompareBigEndian(vch, 32, vchZero, 0) > 0 && + CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0; +} + +bool CheckSignatureElement(const unsigned char *vch, int len, bool half) { + return vch && + CompareBigEndian(vch, len, vchZero, 0) > 0 && + CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; +} + +} // namespace eccrypto diff --git a/src/eccryptoverify.h b/src/eccryptoverify.h new file mode 100644 index 0000000000..7740e31db1 --- /dev/null +++ b/src/eccryptoverify.h @@ -0,0 +1,19 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_EC_CRYPTO_VERIFY_H +#define BITCOIN_EC_CRYPTO_VERIFY_H + +#include +#include +class uint256; + +namespace eccrypto { + +bool Check(const unsigned char *vch); +bool CheckSignatureElement(const unsigned char *vch, int len, bool half); + +} // eccrypto namespace +#endif diff --git a/src/key.cpp b/src/key.cpp index c466e84f26..925b80ba0f 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -5,6 +5,7 @@ #include "key.h" #include "crypto/sha2.h" +#include "eccryptoverify.h" #include "random.h" #ifdef USE_SECP256K1 @@ -30,60 +31,10 @@ public: static CSecp256k1Init instance_of_csecp256k1; #endif - -int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { - while (c1len > c2len) { - if (*c1) - return 1; - c1++; - c1len--; - } - while (c2len > c1len) { - if (*c2) - return -1; - c2++; - c2len--; - } - while (c1len > 0) { - if (*c1 > *c2) - return 1; - if (*c2 > *c1) - return -1; - c1++; - c2++; - c1len--; - } - return 0; -} - -/** Order of secp256k1's generator minus 1. */ -const unsigned char vchMaxModOrder[32] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 -}; - -/** Half of the order of secp256k1's generator minus 1. */ -const unsigned char vchMaxModHalfOrder[32] = { - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, - 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 -}; - -const unsigned char vchZero[1] = {0}; - } // anon namespace bool CKey::Check(const unsigned char *vch) { - return CompareBigEndian(vch, 32, vchZero, 0) > 0 && - CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0; -} - -bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { - return CompareBigEndian(vch, len, vchZero, 0) > 0 && - CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; + return eccrypto::Check(vch); } void CKey::MakeNewKey(bool fCompressedIn) { diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 3625972ebf..e1e242882f 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -9,6 +9,7 @@ #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" +#include "eccryptoverify.h" #include "key.h" #include "script/script.h" #include "uint256.h" @@ -122,7 +123,7 @@ bool static IsLowDERSignature(const valtype &vchSig) { // If the S value is above the order of the curve divided by two, its // complement modulo the order could have been used instead, which is // one byte shorter when encoded correctly. - if (!CKey::CheckSignatureElement(S, nLenS, true)) + if (!eccrypto::CheckSignatureElement(S, nLenS, true)) return error("Non-canonical signature: S value is unnecessarily high"); return true;