From 343b7f44fc52e6f467b75100cb670b1a4ae48d75 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 7 Oct 2013 12:48:27 -0400 Subject: [PATCH] Old algo for ID derivation was not in fact memory-hard since Salsa20 is seekable, so take two. --- node/Identity.cpp | 54 +++++++++++++++++++++++++++---------- selftest-crypto-vectors.hpp | 4 +-- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/node/Identity.cpp b/node/Identity.cpp index 8dc192ca0..c46321e0f 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -38,26 +38,51 @@ // These can't be changed without a new identity type. They define the // parameters of the hashcash hashing/searching algorithm. + +// Hashcash halting criteria #define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 5 + +// Amount of memory for memory-hardness #define ZT_IDENTITY_GEN_MEMORY 8388608 +// Step distance for mixing genmem[] +#define ZT_IDENTITY_GEN_MEMORY_MIX_STEP 128 + namespace ZeroTier { // A memory-hard composition of SHA-512 and Salsa20 for hashcash hashing -static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *sha512digest,unsigned char *genmem) +static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem) { - // Step 1: hash key to generate Salsa20 key and nonce - SHA512::hash(sha512digest,publicKey,publicKeyBytes); + // Hash publicKey[] to obtain Salsa20 key + SHA512::hash(digest,publicKey,publicKeyBytes); - // Step 2: copy key into genmen[], zero rest, encrypt with Salsa20 - Salsa20 s20(sha512digest,256,((char *)sha512digest) + 32); - memcpy(genmem,publicKey,publicKeyBytes); - memset(genmem + publicKeyBytes,0,ZT_IDENTITY_GEN_MEMORY - publicKeyBytes); + // Generate genmem[] bytes of Salsa20 key stream + memset(genmem,0,ZT_IDENTITY_GEN_MEMORY); + Salsa20 s20(digest,256,(char *)digest + 32); s20.encrypt(genmem,genmem,ZT_IDENTITY_GEN_MEMORY); - // Step 3: hash the encrypted public key and the rest of the - // genmem[] bytes of Salsa20 key stream to yield the final hash. - SHA512::hash(sha512digest,genmem,ZT_IDENTITY_GEN_MEMORY); + // Do something to genmem[] that iteratively makes every value + // possibly dependent on every other value with a nontrivial + // probability. + for(unsigned int i=0;i>=8) + ++((unsigned char *)genmem)[(uintptr_t)x % ZT_IDENTITY_GEN_MEMORY]; + } else { + for(unsigned int k=0;k<8;++k,x>>=8) + --((unsigned char *)genmem)[(uintptr_t)x % ZT_IDENTITY_GEN_MEMORY]; + } + } + + // Mix in publicKey[] again, ensuring all entropy is used + for(unsigned int i=0;i