aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hash.cpp41
-rw-r--r--src/hash.h10
-rw-r--r--src/test/hmac_tests.cpp125
3 files changed, 176 insertions, 0 deletions
diff --git a/src/hash.cpp b/src/hash.cpp
index bddd8abf38..7b054bd154 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -56,3 +56,44 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
return h1;
}
+
+int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len)
+{
+ unsigned char key[128];
+ if (len <= 128)
+ {
+ memcpy(key, pkey, len);
+ memset(key + len, 0, 128-len);
+ }
+ else
+ {
+ SHA512_CTX ctxKey;
+ SHA512_Init(&ctxKey);
+ SHA512_Update(&ctxKey, pkey, len);
+ SHA512_Final(key, &ctxKey);
+ memset(key + 64, 0, 64);
+ }
+
+ for (int n=0; n<128; n++)
+ key[n] ^= 0x5c;
+ SHA512_Init(&pctx->ctxOuter);
+ SHA512_Update(&pctx->ctxOuter, key, 128);
+
+ for (int n=0; n<128; n++)
+ key[n] ^= 0x5c ^ 0x36;
+ SHA512_Init(&pctx->ctxInner);
+ return SHA512_Update(&pctx->ctxInner, key, 128);
+}
+
+int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len)
+{
+ return SHA512_Update(&pctx->ctxInner, pdata, len);
+}
+
+int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx)
+{
+ unsigned char buf[64];
+ SHA512_Final(buf, &pctx->ctxInner);
+ SHA512_Update(&pctx->ctxOuter, buf, 64);
+ return SHA512_Final(pmd, &pctx->ctxOuter);
+}
diff --git a/src/hash.h b/src/hash.h
index 536ab71165..880468a2d2 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -123,4 +123,14 @@ inline uint160 Hash160(const std::vector<unsigned char>& vch)
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
+typedef struct
+{
+ SHA512_CTX ctxInner;
+ SHA512_CTX ctxOuter;
+} HMAC_SHA512_CTX;
+
+int HMAC_SHA512_Init(HMAC_SHA512_CTX *pctx, const void *pkey, size_t len);
+int HMAC_SHA512_Update(HMAC_SHA512_CTX *pctx, const void *pdata, size_t len);
+int HMAC_SHA512_Final(unsigned char *pmd, HMAC_SHA512_CTX *pctx);
+
#endif
diff --git a/src/test/hmac_tests.cpp b/src/test/hmac_tests.cpp
new file mode 100644
index 0000000000..92ca5e6aff
--- /dev/null
+++ b/src/test/hmac_tests.cpp
@@ -0,0 +1,125 @@
+#include <boost/test/unit_test.hpp>
+
+#include "hash.h"
+#include "util.h"
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(hmac_tests)
+
+typedef struct {
+ const char *pszKey;
+ const char *pszData;
+ const char *pszMAC;
+} testvec_t;
+
+// test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+static const testvec_t vtest[] = {
+ {
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
+ "0b0b0b0b",
+ "4869205468657265",
+ "87aa7cdea5ef619d4ff0b4241a1d6cb0"
+ "2379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4"
+ "be9d914eeb61f1702e696c203a126854"
+ },
+ {
+ "4a656665",
+ "7768617420646f2079612077616e7420"
+ "666f72206e6f7468696e673f",
+ "164b7a7bfcf819e2e395fbe73b56e0a3"
+ "87bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fd"
+ "caeab1a34d4a6b4b636e070a38bce737"
+ },
+ {
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddd",
+ "fa73b0089d56a284efb0f0756c890be9"
+ "b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807"
+ "b946a337bee8942674278859e13292fb"
+ },
+ {
+ "0102030405060708090a0b0c0d0e0f10"
+ "111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcd",
+ "b0ba465637458c6990e5a8c5f61d4af7"
+ "e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063"
+ "a5f19741120c4f2de2adebeb10a298dd"
+ },
+ {
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c61726765"
+ "72205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579"
+ "204669727374",
+ "80b24263c7c1a3ebb71493c1dd7be8b4"
+ "9b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e52"
+ "95e64f73f63f0aec8b915a985d786598"
+ },
+ {
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54686973206973206120746573742075"
+ "73696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b65"
+ "7920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a652064"
+ "6174612e20546865206b6579206e6565"
+ "647320746f2062652068617368656420"
+ "6265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c"
+ "676f726974686d2e",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffd"
+ "debd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15"
+ "134676fb6de0446065c97440fa8c6a58"
+ }
+};
+
+BOOST_AUTO_TEST_CASE(hmacsha512_testvectors)
+{
+ for (unsigned int n=0; n<sizeof(vtest)/sizeof(vtest[0]); n++)
+ {
+ vector<unsigned char> vchKey = ParseHex(vtest[n].pszKey);
+ vector<unsigned char> vchData = ParseHex(vtest[n].pszData);
+ vector<unsigned char> vchMAC = ParseHex(vtest[n].pszMAC);
+ unsigned char vchTemp[64];
+
+ HMAC_SHA512_CTX ctx;
+ HMAC_SHA512_Init(&ctx, &vchKey[0], vchKey.size());
+ HMAC_SHA512_Update(&ctx, &vchData[0], vchData.size());
+ HMAC_SHA512_Final(&vchTemp[0], &ctx);
+
+ BOOST_CHECK(memcmp(&vchTemp[0], &vchMAC[0], 64) == 0);
+
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()