|
@@ -36,39 +36,54 @@
|
|
#include "Salsa20.hpp"
|
|
#include "Salsa20.hpp"
|
|
#include "Utils.hpp"
|
|
#include "Utils.hpp"
|
|
|
|
|
|
-// Mask for second byte in hashcash criterion -- making it require
|
|
|
|
-// 13 0 bits at the start of the hash.
|
|
|
|
-#define ZT_IDENTITY_SHA_BYTE1_MASK 0xf8
|
|
|
|
|
|
+// These can't be changed without a new identity type. They define the
|
|
|
|
+// parameters of the hashcash hashing/searching algorithm.
|
|
|
|
+#define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 5
|
|
|
|
+#define ZT_IDENTITY_GEN_MEMORY 8388608
|
|
|
|
|
|
namespace ZeroTier {
|
|
namespace ZeroTier {
|
|
|
|
|
|
|
|
+static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *sha512digest)
|
|
|
|
+{
|
|
|
|
+ unsigned char genmem[ZT_IDENTITY_GEN_MEMORY];
|
|
|
|
+
|
|
|
|
+ // Step 1: hash key to generate Salsa20 key and nonce
|
|
|
|
+ SHA512::hash(sha512digest,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);
|
|
|
|
+ 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);
|
|
|
|
+}
|
|
|
|
+
|
|
struct _Identity_generate_cond
|
|
struct _Identity_generate_cond
|
|
{
|
|
{
|
|
_Identity_generate_cond() throw() {}
|
|
_Identity_generate_cond() throw() {}
|
|
- _Identity_generate_cond(char *sb) throw() : sha512buf(sb) {}
|
|
|
|
|
|
+ _Identity_generate_cond(unsigned char *sb) throw() : sha512digest(sb) {}
|
|
|
|
|
|
inline bool operator()(const C25519::Pair &kp) const
|
|
inline bool operator()(const C25519::Pair &kp) const
|
|
throw()
|
|
throw()
|
|
{
|
|
{
|
|
- SHA512::hash(sha512buf,kp.pub.data,kp.pub.size());
|
|
|
|
-
|
|
|
|
- if ((!sha512buf[0])&&(!(sha512buf[1] & ZT_IDENTITY_SHA_BYTE1_MASK)))
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
|
|
+ _computeMemoryHardHash(kp.pub.data,kp.pub.size(),sha512digest);
|
|
|
|
+ return (sha512digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN);
|
|
}
|
|
}
|
|
|
|
|
|
- char *sha512buf;
|
|
|
|
|
|
+ unsigned char *sha512digest;
|
|
};
|
|
};
|
|
|
|
|
|
void Identity::generate()
|
|
void Identity::generate()
|
|
{
|
|
{
|
|
- char sha512buf[64];
|
|
|
|
|
|
+ unsigned char sha512digest[64];
|
|
|
|
|
|
C25519::Pair kp;
|
|
C25519::Pair kp;
|
|
do {
|
|
do {
|
|
- kp = C25519::generateSatisfying(_Identity_generate_cond(sha512buf));
|
|
|
|
- _address.setTo(sha512buf + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
|
|
|
|
|
|
+ kp = C25519::generateSatisfying(_Identity_generate_cond(sha512digest));
|
|
|
|
+ _address.setTo(sha512digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
|
|
} while (_address.isReserved());
|
|
} while (_address.isReserved());
|
|
|
|
|
|
_publicKey = kp.pub;
|
|
_publicKey = kp.pub;
|
|
@@ -81,18 +96,20 @@ bool Identity::locallyValidate() const
|
|
{
|
|
{
|
|
if (_address.isReserved())
|
|
if (_address.isReserved())
|
|
return false;
|
|
return false;
|
|
- char sha512buf[64];
|
|
|
|
- char addrb[5];
|
|
|
|
|
|
+
|
|
|
|
+ unsigned char sha512digest[64];
|
|
|
|
+ _computeMemoryHardHash(_publicKey.data,_publicKey.size(),sha512digest);
|
|
|
|
+
|
|
|
|
+ unsigned char addrb[5];
|
|
_address.copyTo(addrb,5);
|
|
_address.copyTo(addrb,5);
|
|
- SHA512::hash(sha512buf,_publicKey.data,_publicKey.size());
|
|
|
|
|
|
+
|
|
return (
|
|
return (
|
|
- (!sha512buf[0])&&
|
|
|
|
- (!(sha512buf[1] & ZT_IDENTITY_SHA_BYTE1_MASK))&&
|
|
|
|
- (sha512buf[59] == addrb[0])&&
|
|
|
|
- (sha512buf[60] == addrb[1])&&
|
|
|
|
- (sha512buf[61] == addrb[2])&&
|
|
|
|
- (sha512buf[62] == addrb[3])&&
|
|
|
|
- (sha512buf[63] == addrb[4]));
|
|
|
|
|
|
+ (sha512digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
|
|
|
|
+ (sha512digest[59] == addrb[0])&&
|
|
|
|
+ (sha512digest[60] == addrb[1])&&
|
|
|
|
+ (sha512digest[61] == addrb[2])&&
|
|
|
|
+ (sha512digest[62] == addrb[3])&&
|
|
|
|
+ (sha512digest[63] == addrb[4]));
|
|
}
|
|
}
|
|
|
|
|
|
std::string Identity::toString(bool includePrivate) const
|
|
std::string Identity::toString(bool includePrivate) const
|
|
@@ -145,7 +162,7 @@ bool Identity::fromString(const char *str)
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (fno < 4)
|
|
|
|
|
|
+ if (fno < 3)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
return true;
|
|
return true;
|