Add the RFC6979 PRNG
This commit is contained in:
parent
a8f5087e53
commit
3060e36098
4 changed files with 121 additions and 0 deletions
|
@ -206,12 +206,14 @@ crypto_libbitcoin_crypto_a_SOURCES = \
|
||||||
crypto/sha256.cpp \
|
crypto/sha256.cpp \
|
||||||
crypto/sha512.cpp \
|
crypto/sha512.cpp \
|
||||||
crypto/hmac_sha256.cpp \
|
crypto/hmac_sha256.cpp \
|
||||||
|
crypto/rfc6979_hmac_sha256.cpp \
|
||||||
crypto/hmac_sha512.cpp \
|
crypto/hmac_sha512.cpp \
|
||||||
crypto/ripemd160.cpp \
|
crypto/ripemd160.cpp \
|
||||||
crypto/common.h \
|
crypto/common.h \
|
||||||
crypto/sha256.h \
|
crypto/sha256.h \
|
||||||
crypto/sha512.h \
|
crypto/sha512.h \
|
||||||
crypto/hmac_sha256.h \
|
crypto/hmac_sha256.h \
|
||||||
|
crypto/rfc6979_hmac_sha256.h \
|
||||||
crypto/hmac_sha512.h \
|
crypto/hmac_sha512.h \
|
||||||
crypto/sha1.h \
|
crypto/sha1.h \
|
||||||
crypto/ripemd160.h
|
crypto/ripemd160.h
|
||||||
|
|
47
src/crypto/rfc6979_hmac_sha256.cpp
Normal file
47
src/crypto/rfc6979_hmac_sha256.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright (c) 2014 The Bitcoin 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 <string.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
36
src/crypto/rfc6979_hmac_sha256.h
Normal file
36
src/crypto/rfc6979_hmac_sha256.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (c) 2014 The Bitcoin 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 <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/** 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
|
|
@ -2,6 +2,7 @@
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "crypto/rfc6979_hmac_sha256.h"
|
||||||
#include "crypto/ripemd160.h"
|
#include "crypto/ripemd160.h"
|
||||||
#include "crypto/sha1.h"
|
#include "crypto/sha1.h"
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/assign/list_of.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(crypto_tests)
|
BOOST_AUTO_TEST_SUITE(crypto_tests)
|
||||||
|
@ -246,4 +248,38 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
|
||||||
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
|
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestRFC6979(const std::string& hexkey, const std::string& hexmsg, const std::vector<std::string>& hexout)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> key = ParseHex(hexkey);
|
||||||
|
std::vector<unsigned char> 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<unsigned char> out = ParseHex(hexout[i]);
|
||||||
|
std::vector<unsigned char> 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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
Loading…
Reference in a new issue