aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2014-12-01 14:57:49 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2014-12-01 14:57:58 +0100
commitf0877f8b6200dcf6df12df5e69d498d365f81f8b (patch)
treedc5f63386a9c0752a62301a815d6a976286a1b42
parent89151d9f29870cc9246f76baba75b75d3a7528d7 (diff)
parent4cdaa95a209808276992dc1eb0ed0773f7927073 (diff)
Merge pull request #5227
4cdaa95 Resize after succesful result (Pieter Wuille) 9d8604f Header define style cleanups (Pieter Wuille) a53fd41 Deterministic signing (Pieter Wuille) 3060e36 Add the RFC6979 PRNG (Pieter Wuille) a8f5087 Add HMAC-SHA256 (Pieter Wuille) 36fa4a7 Split up crypto/sha2 (Pieter Wuille)
-rw-r--r--src/Makefile.am16
-rw-r--r--src/crypto/hmac_sha256.cpp34
-rw-r--r--src/crypto/hmac_sha256.h32
-rw-r--r--src/crypto/hmac_sha512.cpp34
-rw-r--r--src/crypto/hmac_sha512.h32
-rw-r--r--src/crypto/rfc6979_hmac_sha256.cpp47
-rw-r--r--src/crypto/rfc6979_hmac_sha256.h36
-rw-r--r--src/crypto/sha2.h64
-rw-r--r--src/crypto/sha256.cpp189
-rw-r--r--src/crypto/sha256.h28
-rw-r--r--src/crypto/sha512.cpp (renamed from src/crypto/sha2.cpp)210
-rw-r--r--src/crypto/sha512.h28
-rw-r--r--src/hash.cpp1
-rw-r--r--src/hash.h2
-rw-r--r--src/key.cpp32
-rw-r--r--src/key.h8
-rw-r--r--src/pubkey.cpp1
-rw-r--r--src/script/interpreter.cpp2
-rw-r--r--src/test/crypto_tests.cpp83
-rw-r--r--src/test/key_tests.cpp23
-rw-r--r--src/test/script_tests.cpp3
21 files changed, 612 insertions, 293 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3ec9e2f85d..4c4f9f6937 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -203,10 +203,18 @@ libbitcoin_wallet_a_SOURCES = \
crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES)
crypto_libbitcoin_crypto_a_SOURCES = \
crypto/sha1.cpp \
- crypto/sha2.cpp \
+ 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/sha2.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
@@ -343,8 +351,10 @@ if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h
libbitcoinconsensus_la_SOURCES = \
core/transaction.cpp \
+ crypto/hmac_sha512.cpp \
crypto/sha1.cpp \
- crypto/sha2.cpp \
+ crypto/sha256.cpp \
+ crypto/sha512.cpp \
crypto/ripemd160.cpp \
eccryptoverify.cpp \
ecwrapper.cpp \
diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp
new file mode 100644
index 0000000000..435896538b
--- /dev/null
+++ b/src/crypto/hmac_sha256.cpp
@@ -0,0 +1,34 @@
+// 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/hmac_sha256.h"
+
+#include <string.h>
+
+CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen)
+{
+ unsigned char rkey[64];
+ if (keylen <= 64) {
+ memcpy(rkey, key, keylen);
+ memset(rkey + keylen, 0, 64 - keylen);
+ } else {
+ CSHA256().Write(key, keylen).Finalize(rkey);
+ memset(rkey + 32, 0, 32);
+ }
+
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c;
+ outer.Write(rkey, 64);
+
+ for (int n = 0; n < 64; n++)
+ rkey[n] ^= 0x5c ^ 0x36;
+ inner.Write(rkey, 64);
+}
+
+void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
+{
+ unsigned char temp[32];
+ inner.Finalize(temp);
+ outer.Write(temp, 32).Finalize(hash);
+}
diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h
new file mode 100644
index 0000000000..1fdee5a7cd
--- /dev/null
+++ b/src/crypto/hmac_sha256.h
@@ -0,0 +1,32 @@
+// 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_CRYPTO_HMAC_SHA256_H
+#define BITCOIN_CRYPTO_HMAC_SHA256_H
+
+#include "crypto/sha256.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for HMAC-SHA-512. */
+class CHMAC_SHA256
+{
+private:
+ CSHA256 outer;
+ CSHA256 inner;
+
+public:
+ static const size_t OUTPUT_SIZE = 32;
+
+ CHMAC_SHA256(const unsigned char* key, size_t keylen);
+ CHMAC_SHA256& Write(const unsigned char* data, size_t len)
+ {
+ inner.Write(data, len);
+ return *this;
+ }
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+};
+
+#endif // BITCOIN_CRYPTO_HMAC_SHA256_H
diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp
new file mode 100644
index 0000000000..940a93277c
--- /dev/null
+++ b/src/crypto/hmac_sha512.cpp
@@ -0,0 +1,34 @@
+// 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/hmac_sha512.h"
+
+#include <string.h>
+
+CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen)
+{
+ unsigned char rkey[128];
+ if (keylen <= 128) {
+ memcpy(rkey, key, keylen);
+ memset(rkey + keylen, 0, 128 - keylen);
+ } else {
+ CSHA512().Write(key, keylen).Finalize(rkey);
+ memset(rkey + 64, 0, 64);
+ }
+
+ for (int n = 0; n < 128; n++)
+ rkey[n] ^= 0x5c;
+ outer.Write(rkey, 128);
+
+ for (int n = 0; n < 128; n++)
+ rkey[n] ^= 0x5c ^ 0x36;
+ inner.Write(rkey, 128);
+}
+
+void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
+{
+ unsigned char temp[64];
+ inner.Finalize(temp);
+ outer.Write(temp, 64).Finalize(hash);
+}
diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h
new file mode 100644
index 0000000000..17d75021aa
--- /dev/null
+++ b/src/crypto/hmac_sha512.h
@@ -0,0 +1,32 @@
+// 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_CRYPTO_HMAC_SHA512_H
+#define BITCOIN_CRYPTO_HMAC_SHA512_H
+
+#include "crypto/sha512.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for HMAC-SHA-512. */
+class CHMAC_SHA512
+{
+private:
+ CSHA512 outer;
+ CSHA512 inner;
+
+public:
+ static const size_t OUTPUT_SIZE = 64;
+
+ CHMAC_SHA512(const unsigned char* key, size_t keylen);
+ CHMAC_SHA512& Write(const unsigned char* data, size_t len)
+ {
+ inner.Write(data, len);
+ return *this;
+ }
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+};
+
+#endif // BITCOIN_CRYPTO_HMAC_SHA512_H
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
diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h
deleted file mode 100644
index 329c6675ab..0000000000
--- a/src/crypto/sha2.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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_CRYPTO_SHA2_H
-#define BITCOIN_CRYPTO_SHA2_H
-
-#include <stdint.h>
-#include <stdlib.h>
-
-/** A hasher class for SHA-256. */
-class CSHA256
-{
-private:
- uint32_t s[8];
- unsigned char buf[64];
- size_t bytes;
-
-public:
- static const size_t OUTPUT_SIZE = 32;
-
- CSHA256();
- CSHA256& Write(const unsigned char* data, size_t len);
- void Finalize(unsigned char hash[OUTPUT_SIZE]);
- CSHA256& Reset();
-};
-
-/** A hasher class for SHA-512. */
-class CSHA512
-{
-private:
- uint64_t s[8];
- unsigned char buf[128];
- size_t bytes;
-
-public:
- static const size_t OUTPUT_SIZE = 64;
-
- CSHA512();
- CSHA512& Write(const unsigned char* data, size_t len);
- void Finalize(unsigned char hash[OUTPUT_SIZE]);
- CSHA512& Reset();
-};
-
-/** A hasher class for HMAC-SHA-512. */
-class CHMAC_SHA512
-{
-private:
- CSHA512 outer;
- CSHA512 inner;
-
-public:
- static const size_t OUTPUT_SIZE = 64;
-
- CHMAC_SHA512(const unsigned char* key, size_t keylen);
- CHMAC_SHA512& Write(const unsigned char* data, size_t len)
- {
- inner.Write(data, len);
- return *this;
- }
- void Finalize(unsigned char hash[OUTPUT_SIZE]);
-};
-
-#endif // BITCOIN_CRYPTO_SHA2_H
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
new file mode 100644
index 0000000000..8410e59305
--- /dev/null
+++ b/src/crypto/sha256.cpp
@@ -0,0 +1,189 @@
+// 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/sha256.h"
+
+#include "crypto/common.h"
+
+#include <string.h>
+
+// Internal implementation code.
+namespace
+{
+/// Internal SHA-256 implementation.
+namespace sha256
+{
+uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
+uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
+uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
+uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
+uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
+uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
+
+/** One round of SHA-256. */
+void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
+{
+ uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
+ uint32_t t2 = Sigma0(a) + Maj(a, b, c);
+ d += t1;
+ h = t1 + t2;
+}
+
+/** Initialize SHA-256 state. */
+void inline Initialize(uint32_t* s)
+{
+ s[0] = 0x6a09e667ul;
+ s[1] = 0xbb67ae85ul;
+ s[2] = 0x3c6ef372ul;
+ s[3] = 0xa54ff53aul;
+ s[4] = 0x510e527ful;
+ s[5] = 0x9b05688cul;
+ s[6] = 0x1f83d9abul;
+ s[7] = 0x5be0cd19ul;
+}
+
+/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
+void Transform(uint32_t* s, const unsigned char* chunk)
+{
+ uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
+ uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
+ Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
+ Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
+
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
+
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
+ Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
+ Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
+ Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
+ Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
+ Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
+
+ s[0] += a;
+ s[1] += b;
+ s[2] += c;
+ s[3] += d;
+ s[4] += e;
+ s[5] += f;
+ s[6] += g;
+ s[7] += h;
+}
+
+} // namespace sha256
+} // namespace
+
+
+////// SHA-256
+
+CSHA256::CSHA256() : bytes(0)
+{
+ sha256::Initialize(s);
+}
+
+CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
+{
+ const unsigned char* end = data + len;
+ size_t bufsize = bytes % 64;
+ if (bufsize && bufsize + len >= 64) {
+ // Fill the buffer, and process it.
+ memcpy(buf + bufsize, data, 64 - bufsize);
+ bytes += 64 - bufsize;
+ data += 64 - bufsize;
+ sha256::Transform(s, buf);
+ bufsize = 0;
+ }
+ while (end >= data + 64) {
+ // Process full chunks directly from the source.
+ sha256::Transform(s, data);
+ bytes += 64;
+ data += 64;
+ }
+ if (end > data) {
+ // Fill the buffer with what remains.
+ memcpy(buf + bufsize, data, end - data);
+ bytes += end - data;
+ }
+ return *this;
+}
+
+void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
+{
+ static const unsigned char pad[64] = {0x80};
+ unsigned char sizedesc[8];
+ WriteBE64(sizedesc, bytes << 3);
+ Write(pad, 1 + ((119 - (bytes % 64)) % 64));
+ Write(sizedesc, 8);
+ WriteBE32(hash, s[0]);
+ WriteBE32(hash + 4, s[1]);
+ WriteBE32(hash + 8, s[2]);
+ WriteBE32(hash + 12, s[3]);
+ WriteBE32(hash + 16, s[4]);
+ WriteBE32(hash + 20, s[5]);
+ WriteBE32(hash + 24, s[6]);
+ WriteBE32(hash + 28, s[7]);
+}
+
+CSHA256& CSHA256::Reset()
+{
+ bytes = 0;
+ sha256::Initialize(s);
+ return *this;
+}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
new file mode 100644
index 0000000000..bde1a59bed
--- /dev/null
+++ b/src/crypto/sha256.h
@@ -0,0 +1,28 @@
+// 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_CRYPTO_SHA256_H
+#define BITCOIN_CRYPTO_SHA256_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for SHA-256. */
+class CSHA256
+{
+private:
+ uint32_t s[8];
+ unsigned char buf[64];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 32;
+
+ CSHA256();
+ CSHA256& Write(const unsigned char* data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CSHA256& Reset();
+};
+
+#endif // BITCOIN_CRYPTO_SHA256_H
diff --git a/src/crypto/sha2.cpp b/src/crypto/sha512.cpp
index 613aac2d71..22c3103bed 100644
--- a/src/crypto/sha2.cpp
+++ b/src/crypto/sha512.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "crypto/sha2.h"
+#include "crypto/sha512.h"
#include "crypto/common.h"
@@ -11,124 +11,6 @@
// Internal implementation code.
namespace
{
-/// Internal SHA-256 implementation.
-namespace sha256
-{
-uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
-uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
-uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
-uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
-uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
-uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
-
-/** One round of SHA-256. */
-void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
-{
- uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
- uint32_t t2 = Sigma0(a) + Maj(a, b, c);
- d += t1;
- h = t1 + t2;
-}
-
-/** Initialize SHA-256 state. */
-void inline Initialize(uint32_t* s)
-{
- s[0] = 0x6a09e667ul;
- s[1] = 0xbb67ae85ul;
- s[2] = 0x3c6ef372ul;
- s[3] = 0xa54ff53aul;
- s[4] = 0x510e527ful;
- s[5] = 0x9b05688cul;
- s[6] = 0x1f83d9abul;
- s[7] = 0x5be0cd19ul;
-}
-
-/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
-void Transform(uint32_t* s, const unsigned char* chunk)
-{
- uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
- uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
-
- Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
- Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
- Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
- Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
- Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
- Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
- Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
- Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
- Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
- Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
- Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
- Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
- Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
- Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
- Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
- Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
-
- Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
-
- Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
-
- Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
-
- s[0] += a;
- s[1] += b;
- s[2] += c;
- s[3] += d;
- s[4] += e;
- s[5] += f;
- s[6] += g;
- s[7] += h;
-}
-
-} // namespace sha256
-
/// Internal SHA-512 implementation.
namespace sha512
{
@@ -249,8 +131,8 @@ void Transform(uint64_t* s, const unsigned char* chunk)
Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12));
Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13));
Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0(w0));
+ Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15));
+ Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0));
s[0] += a;
s[1] += b;
@@ -267,63 +149,6 @@ void Transform(uint64_t* s, const unsigned char* chunk)
} // namespace
-////// SHA-256
-
-CSHA256::CSHA256() : bytes(0)
-{
- sha256::Initialize(s);
-}
-
-CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
-{
- const unsigned char* end = data + len;
- size_t bufsize = bytes % 64;
- if (bufsize && bufsize + len >= 64) {
- // Fill the buffer, and process it.
- memcpy(buf + bufsize, data, 64 - bufsize);
- bytes += 64 - bufsize;
- data += 64 - bufsize;
- sha256::Transform(s, buf);
- bufsize = 0;
- }
- while (end >= data + 64) {
- // Process full chunks directly from the source.
- sha256::Transform(s, data);
- bytes += 64;
- data += 64;
- }
- if (end > data) {
- // Fill the buffer with what remains.
- memcpy(buf + bufsize, data, end - data);
- bytes += end - data;
- }
- return *this;
-}
-
-void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
-{
- static const unsigned char pad[64] = {0x80};
- unsigned char sizedesc[8];
- WriteBE64(sizedesc, bytes << 3);
- Write(pad, 1 + ((119 - (bytes % 64)) % 64));
- Write(sizedesc, 8);
- WriteBE32(hash, s[0]);
- WriteBE32(hash + 4, s[1]);
- WriteBE32(hash + 8, s[2]);
- WriteBE32(hash + 12, s[3]);
- WriteBE32(hash + 16, s[4]);
- WriteBE32(hash + 20, s[5]);
- WriteBE32(hash + 24, s[6]);
- WriteBE32(hash + 28, s[7]);
-}
-
-CSHA256& CSHA256::Reset()
-{
- bytes = 0;
- sha256::Initialize(s);
- return *this;
-}
-
////// SHA-512
CSHA512::CSHA512() : bytes(0)
@@ -380,32 +205,3 @@ CSHA512& CSHA512::Reset()
sha512::Initialize(s);
return *this;
}
-
-////// HMAC-SHA-512
-
-CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen)
-{
- unsigned char rkey[128];
- if (keylen <= 128) {
- memcpy(rkey, key, keylen);
- memset(rkey + keylen, 0, 128 - keylen);
- } else {
- CSHA512().Write(key, keylen).Finalize(rkey);
- memset(rkey + 64, 0, 64);
- }
-
- for (int n = 0; n < 128; n++)
- rkey[n] ^= 0x5c;
- outer.Write(rkey, 128);
-
- for (int n = 0; n < 128; n++)
- rkey[n] ^= 0x5c ^ 0x36;
- inner.Write(rkey, 128);
-}
-
-void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE])
-{
- unsigned char temp[64];
- inner.Finalize(temp);
- outer.Write(temp, 64).Finalize(hash);
-}
diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h
new file mode 100644
index 0000000000..5566d5db3e
--- /dev/null
+++ b/src/crypto/sha512.h
@@ -0,0 +1,28 @@
+// 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_CRYPTO_SHA512_H
+#define BITCOIN_CRYPTO_SHA512_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/** A hasher class for SHA-512. */
+class CSHA512
+{
+private:
+ uint64_t s[8];
+ unsigned char buf[128];
+ size_t bytes;
+
+public:
+ static const size_t OUTPUT_SIZE = 64;
+
+ CSHA512();
+ CSHA512& Write(const unsigned char* data, size_t len);
+ void Finalize(unsigned char hash[OUTPUT_SIZE]);
+ CSHA512& Reset();
+};
+
+#endif // BITCOIN_CRYPTO_SHA512_H
diff --git a/src/hash.cpp b/src/hash.cpp
index 2cca06ae23..aaca00ea2d 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "hash.h"
+#include "crypto/hmac_sha512.h"
inline uint32_t ROTL32(uint32_t x, int8_t r)
{
diff --git a/src/hash.h b/src/hash.h
index 75695160e6..5a34cdc5c3 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -7,7 +7,7 @@
#define BITCOIN_HASH_H
#include "crypto/ripemd160.h"
-#include "crypto/sha2.h"
+#include "crypto/sha256.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
diff --git a/src/key.cpp b/src/key.cpp
index a91ed1cc1d..acf62360a4 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -4,7 +4,8 @@
#include "key.h"
-#include "crypto/sha2.h"
+#include "crypto/hmac_sha512.h"
+#include "crypto/rfc6979_hmac_sha256.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"
@@ -71,19 +72,23 @@ CPubKey CKey::GetPubKey() const {
return result;
}
-bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
vchSig.resize(72);
- int nSigLen = 72;
- CKey nonce;
+ RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
- break;
+ uint256 nonce;
+ prng.Generate((unsigned char*)&nonce, 32);
+ nonce += test_case;
+ int nSigLen = 72;
+ int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce);
+ nonce = 0;
+ if (ret) {
+ vchSig.resize(nSigLen);
+ return true;
+ }
} while(true);
- vchSig.resize(nSigLen);
- return true;
}
bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
@@ -105,10 +110,13 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(65);
int rec = -1;
- CKey nonce;
+ RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32);
do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
+ uint256 nonce;
+ prng.Generate((unsigned char*)&nonce, 32);
+ int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), (unsigned char*)&nonce, &rec);
+ nonce = 0;
+ if (ret)
break;
} while(true);
assert(rec != -1);
diff --git a/src/key.h b/src/key.h
index 228cc42449..d85abe095c 100644
--- a/src/key.h
+++ b/src/key.h
@@ -122,8 +122,12 @@ public:
*/
CPubKey GetPubKey() const;
- //! Create a DER-serialized signature.
- bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig) const;
+ /**
+ * Create a DER-serialized signature.
+ * The test_case parameter tweaks the deterministic nonce, and is only for
+ * testing. It should be zero for normal use.
+ */
+ bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const;
/**
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 9c6f536f21..91979ff4dc 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -4,7 +4,6 @@
#include "pubkey.h"
-#include "crypto/sha2.h"
#include "eccryptoverify.h"
#ifdef USE_SECP256K1
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index a10cefcc0b..237c712870 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -8,7 +8,7 @@
#include "core/transaction.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
-#include "crypto/sha2.h"
+#include "crypto/sha256.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "script/script.h"
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 68232a2ff1..26708f5071 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -2,14 +2,19 @@
// Distributed under the MIT/X11 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/sha2.h"
+#include "crypto/sha256.h"
+#include "crypto/sha512.h"
+#include "crypto/hmac_sha256.h"
+#include "crypto/hmac_sha512.h"
#include "random.h"
#include "utilstrencodings.h"
#include <vector>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(crypto_tests)
@@ -48,6 +53,11 @@ void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(C
void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));}
void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));}
+void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ TestVector(CHMAC_SHA256(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
+}
+
void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
std::vector<unsigned char> key = ParseHex(hexkey);
TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
@@ -158,6 +168,43 @@ BOOST_AUTO_TEST_CASE(sha512_testvectors) {
"37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc");
}
+BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) {
+ // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+ TestHMACSHA256("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
+ TestHMACSHA256("4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddd",
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
+ TestHMACSHA256("0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579204669727374",
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "5468697320697320612074657374207573696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
+ "647320746f20626520686173686564206265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c676f726974686d2e",
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2");
+}
+
BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
// test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
@@ -201,4 +248,38 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
"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()
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index f9e35e0166..43b18ce61e 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -8,6 +8,7 @@
#include "script/script.h"
#include "uint256.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <string>
#include <vector>
@@ -162,6 +163,28 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(rkey1C == pubkey1C);
BOOST_CHECK(rkey2C == pubkey2C);
}
+
+ // test deterministic signing
+
+ std::vector<unsigned char> detsig, detsigc;
+ string strMsg = "Very deterministic message";
+ uint256 hashMsg = Hash(strMsg.begin(), strMsg.end());
+ BOOST_CHECK(key1.Sign(hashMsg, detsig));
+ BOOST_CHECK(key1C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.Sign(hashMsg, detsig));
+ BOOST_CHECK(key2C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(key1.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key1C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(detsigc == ParseHex("205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key2C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 6952f4c584..53411190eb 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -248,8 +248,9 @@ public:
{
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
std::vector<unsigned char> vchSig, r, s;
+ uint32_t iter = 0;
do {
- key.Sign(hash, vchSig);
+ key.Sign(hash, vchSig, iter++);
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
NegateSignatureS(vchSig);
}