From 1a9576de9dbb1910cb8462e513938d45ef7b5a23 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 18 Dec 2014 14:49:19 +0100 Subject: [PATCH] Use libsecp256k1's RFC6979 implementation --- src/Makefile.am | 2 -- src/crypto/rfc6979_hmac_sha256.cpp | 47 ------------------------------ src/crypto/rfc6979_hmac_sha256.h | 36 ----------------------- src/key.cpp | 45 +++++++++++++--------------- src/test/crypto_tests.cpp | 35 ---------------------- 5 files changed, 21 insertions(+), 144 deletions(-) delete mode 100644 src/crypto/rfc6979_hmac_sha256.cpp delete mode 100644 src/crypto/rfc6979_hmac_sha256.h diff --git a/src/Makefile.am b/src/Makefile.am index bc2b1aff9..5a5b9cc3d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -209,14 +209,12 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha256.cpp \ crypto/sha512.cpp \ crypto/hmac_sha256.cpp \ - crypto/rfc6979_hmac_sha256.cpp \ crypto/hmac_sha512.cpp \ crypto/ripemd160.cpp \ crypto/common.h \ crypto/sha256.h \ crypto/sha512.h \ crypto/hmac_sha256.h \ - crypto/rfc6979_hmac_sha256.h \ crypto/hmac_sha512.h \ crypto/sha1.h \ crypto/ripemd160.h diff --git a/src/crypto/rfc6979_hmac_sha256.cpp b/src/crypto/rfc6979_hmac_sha256.cpp deleted file mode 100644 index a8c971c3b..000000000 --- a/src/crypto/rfc6979_hmac_sha256.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "crypto/rfc6979_hmac_sha256.h" - -#include - -#include - -static const unsigned char zero[1] = {0x00}; -static const unsigned char one[1] = {0x01}; - -RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false) -{ - memset(V, 0x01, sizeof(V)); - memset(K, 0x00, sizeof(K)); - - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K); - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K); - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); -} - -RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256() -{ - memset(V, 0x01, sizeof(V)); - memset(K, 0x00, sizeof(K)); -} - -void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen) -{ - if (retry) { - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K); - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); - } - - while (outputlen > 0) { - CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); - size_t len = std::min(outputlen, sizeof(V)); - memcpy(output, V, len); - output += len; - outputlen -= len; - } - - retry = true; -} diff --git a/src/crypto/rfc6979_hmac_sha256.h b/src/crypto/rfc6979_hmac_sha256.h deleted file mode 100644 index f3a54a5d1..000000000 --- a/src/crypto/rfc6979_hmac_sha256.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_RFC6979_HMAC_SHA256_H -#define BITCOIN_RFC6979_HMAC_SHA256_H - -#include "crypto/hmac_sha256.h" - -#include -#include - -/** The RFC 6979 PRNG using HMAC-SHA256. */ -class RFC6979_HMAC_SHA256 -{ -private: - unsigned char V[CHMAC_SHA256::OUTPUT_SIZE]; - unsigned char K[CHMAC_SHA256::OUTPUT_SIZE]; - bool retry; - -public: - /** - * Construct a new RFC6979 PRNG, using the given key and message. - * The message is assumed to be already hashed. - */ - RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen); - - /** - * Generate a byte array. - */ - void Generate(unsigned char* output, size_t outputlen); - - ~RFC6979_HMAC_SHA256(); -}; - -#endif // BITCOIN_RFC6979_HMAC_SHA256_H diff --git a/src/key.cpp b/src/key.cpp index 2235c271d..d8319db1a 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -6,7 +6,6 @@ #include "arith_uint256.h" #include "crypto/hmac_sha512.h" -#include "crypto/rfc6979_hmac_sha256.h" #include "eccryptoverify.h" #include "pubkey.h" #include "random.h" @@ -74,23 +73,28 @@ CPubKey CKey::GetPubKey() const { return result; } +extern "C" +{ +static int secp256k1_nonce_function_test_case(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int attempt, const void *data) +{ + const uint32_t *test_case = static_cast(data); + uint256 nonce; + secp256k1_nonce_function_rfc6979(nonce.begin(), msg32, key32, attempt, NULL); + nonce = ArithToUint256(UintToArith256(nonce) + *test_case); + memcpy(nonce32, nonce.begin(), 32); + return 1; +} +} + bool CKey::Sign(const uint256 &hash, std::vector& vchSig, uint32_t test_case) const { if (!fValid) return false; vchSig.resize(72); - RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); - do { - uint256 nonce; - prng.Generate((unsigned char*)&nonce, 32); - nonce = ArithToUint256(UintToArith256(nonce) + test_case); - int nSigLen = 72; - int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce); - nonce = uint256(); - if (ret) { - vchSig.resize(nSigLen); - return true; - } - } while(true); + int nSigLen = 72; + int ret = secp256k1_ecdsa_sign(hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), test_case == 0 ? secp256k1_nonce_function_rfc6979 : secp256k1_nonce_function_test_case, test_case == 0 ? NULL : &test_case); + assert(ret); + vchSig.resize(nSigLen); + return true; } bool CKey::VerifyPubKey(const CPubKey& pubkey) const { @@ -101,7 +105,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const { std::string str = "Bitcoin key verification\n"; GetRandBytes(rnd, sizeof(rnd)); uint256 hash; - CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash); + CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin()); std::vector vchSig; Sign(hash, vchSig); return pubkey.Verify(hash, vchSig); @@ -112,15 +116,8 @@ bool CKey::SignCompact(const uint256 &hash, std::vector& vchSig) return false; vchSig.resize(65); int rec = -1; - RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); - do { - uint256 nonce; - prng.Generate((unsigned char*)&nonce, 32); - int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, &vchSig[1], begin(), (unsigned char*)&nonce, &rec); - nonce = uint256(); - if (ret) - break; - } while(true); + int ret = secp256k1_ecdsa_sign_compact(hash.begin(), &vchSig[1], begin(), secp256k1_nonce_function_rfc6979, NULL, &rec); + assert(ret); assert(rec != -1); vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); return true; diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 47bfd710c..d5e595cd8 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/rfc6979_hmac_sha256.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" @@ -248,38 +247,4 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); } -void TestRFC6979(const std::string& hexkey, const std::string& hexmsg, const std::vector& hexout) -{ - std::vector key = ParseHex(hexkey); - std::vector msg = ParseHex(hexmsg); - RFC6979_HMAC_SHA256 rng(&key[0], key.size(), &msg[0], msg.size()); - - for (unsigned int i = 0; i < hexout.size(); i++) { - std::vector out = ParseHex(hexout[i]); - std::vector gen; - gen.resize(out.size()); - rng.Generate(&gen[0], gen.size()); - BOOST_CHECK(out == gen); - } -} - -BOOST_AUTO_TEST_CASE(rfc6979_hmac_sha256) -{ - TestRFC6979( - "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f00", - "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", - boost::assign::list_of - ("4fe29525b2086809159acdf0506efb86b0ec932c7ba44256ab321e421e67e9fb") - ("2bf0fff1d3c378a22dc5de1d856522325c65b504491a0cbd01cb8f3aa67ffd4a") - ("f528b410cb541f77000d7afb6c5b53c5c471eab43e466d9ac5190c39c82fd82e")); - - TestRFC6979( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - boost::assign::list_of - ("9c236c165b82ae0cd590659e100b6bab3036e7ba8b06749baf6981e16f1a2b95") - ("df471061625bc0ea14b682feee2c9c02f235da04204c1d62a1536c6e17aed7a9") - ("7597887cbd76321f32e30440679a22cf7f8d9d2eac390e581fea091ce202ba94")); -} - BOOST_AUTO_TEST_SUITE_END()