aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-10-26 02:28:22 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2014-11-20 17:22:06 +0100
commit3060e360980f3e80db1d903085d759338ab27f4a (patch)
tree51edcb62faa2ffba00905cb03d3724c333450162 /src/crypto
parenta8f5087e5318211b58b0c87ebd4e036e6c6721e5 (diff)
Add the RFC6979 PRNG
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/rfc6979_hmac_sha256.cpp47
-rw-r--r--src/crypto/rfc6979_hmac_sha256.h36
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