diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-10-26 02:28:22 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-11-20 17:22:06 +0100 |
commit | 3060e360980f3e80db1d903085d759338ab27f4a (patch) | |
tree | 51edcb62faa2ffba00905cb03d3724c333450162 /src/crypto | |
parent | a8f5087e5318211b58b0c87ebd4e036e6c6721e5 (diff) |
Add the RFC6979 PRNG
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/rfc6979_hmac_sha256.cpp | 47 | ||||
-rw-r--r-- | src/crypto/rfc6979_hmac_sha256.h | 36 |
2 files changed, 83 insertions, 0 deletions
diff --git a/src/crypto/rfc6979_hmac_sha256.cpp b/src/crypto/rfc6979_hmac_sha256.cpp new file mode 100644 index 0000000000..3f935abfea --- /dev/null +++ b/src/crypto/rfc6979_hmac_sha256.cpp @@ -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; +} diff --git a/src/crypto/rfc6979_hmac_sha256.h b/src/crypto/rfc6979_hmac_sha256.h new file mode 100644 index 0000000000..e67ddcf8fe --- /dev/null +++ b/src/crypto/rfc6979_hmac_sha256.h @@ -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 |