mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 20:43:44 +02:00
Small fix, docs, warning removal.
This commit is contained in:
parent
1c7baa544b
commit
c7f3f3add9
1 changed files with 28 additions and 10 deletions
|
@ -32,7 +32,7 @@ namespace {
|
||||||
|
|
||||||
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
// This is the memory-intensive hash function used to compute v0 identities from v0 public keys.
|
||||||
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
#define ZT_V0_IDENTITY_GEN_MEMORY 2097152
|
||||||
void _computeMemoryHardHash(const void *const publicKey,unsigned int publicKeyBytes,void *const digest,void *const genmem) noexcept
|
void identityV0ProofOfWorkFrankenhash(const void *const publicKey,unsigned int publicKeyBytes,void *const digest,void *const genmem) noexcept
|
||||||
{
|
{
|
||||||
// Digest publicKey[] to obtain initial digest
|
// Digest publicKey[] to obtain initial digest
|
||||||
SHA512(digest,publicKey,publicKeyBytes);
|
SHA512(digest,publicKey,publicKeyBytes);
|
||||||
|
@ -66,12 +66,12 @@ void _computeMemoryHardHash(const void *const publicKey,unsigned int publicKeyBy
|
||||||
s20.crypt20(digest,digest,64);
|
s20.crypt20(digest,digest,64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct _v0_identity_generate_cond
|
struct identityV0ProofOfWorkCriteria
|
||||||
{
|
{
|
||||||
ZT_INLINE _v0_identity_generate_cond(unsigned char *sb,char *gm) noexcept : digest(sb),genmem(gm) {}
|
ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *sb,char *gm) noexcept : digest(sb),genmem(gm) {}
|
||||||
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN]) const noexcept
|
ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN]) const noexcept
|
||||||
{
|
{
|
||||||
_computeMemoryHardHash(pub,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
|
identityV0ProofOfWorkFrankenhash(pub,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
|
||||||
return (digest[0] < 17);
|
return (digest[0] < 17);
|
||||||
}
|
}
|
||||||
unsigned char *digest;
|
unsigned char *digest;
|
||||||
|
@ -79,18 +79,23 @@ struct _v0_identity_generate_cond
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a simpler memory-intensive hash function for V1 identity generation.
|
// This is a simpler memory-intensive hash function for V1 identity generation.
|
||||||
bool _v1_identity_generate_cond(const void *in,const unsigned int len)
|
// It's not quite as intensive as the V0 frankenhash, is a little more orderly in
|
||||||
|
// its design, but remains relatively resistant to GPU acceleration due to memory
|
||||||
|
// requirements for efficient computation.
|
||||||
|
bool identityV1ProofOfWorkCriteria(const void *in,const unsigned int len)
|
||||||
{
|
{
|
||||||
uint64_t b[98304]; // 768 KiB
|
uint64_t b[98304]; // 768 KiB of working memory
|
||||||
uint64_t polykey[4];
|
uint64_t polykey[4];
|
||||||
|
|
||||||
SHA512(b,in,len);
|
SHA512(b,in,len);
|
||||||
|
|
||||||
|
// Poly1305 key, used in final hash at the end.
|
||||||
polykey[0] = b[0];
|
polykey[0] = b[0];
|
||||||
polykey[1] = b[1];
|
polykey[1] = b[1];
|
||||||
polykey[2] = b[2];
|
polykey[2] = b[2];
|
||||||
polykey[3] = b[3];
|
polykey[3] = b[3];
|
||||||
|
|
||||||
|
// Put bits in hash in LE byte order on BE machines.
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
b[0] = Utils::swapBytes(b[0]);
|
b[0] = Utils::swapBytes(b[0]);
|
||||||
b[1] = Utils::swapBytes(b[1]);
|
b[1] = Utils::swapBytes(b[1]);
|
||||||
|
@ -102,6 +107,11 @@ bool _v1_identity_generate_cond(const void *in,const unsigned int len)
|
||||||
b[7] = Utils::swapBytes(b[7]);
|
b[7] = Utils::swapBytes(b[7]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Memory-intensive work: fill 'b' with pseudo-random bits generated from
|
||||||
|
// a reduced-round instance of Speck128 using a CBC-like construction.
|
||||||
|
// Then sort the resulting integer array in ascending numerical order.
|
||||||
|
// The sort requires that we compute and cache the whole data set, or at
|
||||||
|
// least that this is the most efficient implementation.
|
||||||
Speck128<24> s16;
|
Speck128<24> s16;
|
||||||
s16.initXY(b[4],b[5]);
|
s16.initXY(b[4],b[5]);
|
||||||
for(unsigned long i=0;i<(98304-8);) {
|
for(unsigned long i=0;i<(98304-8);) {
|
||||||
|
@ -130,6 +140,7 @@ bool _v1_identity_generate_cond(const void *in,const unsigned int len)
|
||||||
}
|
}
|
||||||
std::sort(b,b + 98304);
|
std::sort(b,b + 98304);
|
||||||
|
|
||||||
|
// Put bits in little-endian byte order if this is a BE machine.
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
for(unsigned int i=0;i<98304;i+=8) {
|
for(unsigned int i=0;i<98304;i+=8) {
|
||||||
b[i] = Utils::swapBytes(b[i]);
|
b[i] = Utils::swapBytes(b[i]);
|
||||||
|
@ -143,7 +154,14 @@ bool _v1_identity_generate_cond(const void *in,const unsigned int len)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Use poly1305 to compute a very fast digest of 'b'. This doesn't have to be
|
||||||
|
// cryptographic per se, just have good hashing properties.
|
||||||
poly1305(b,b,sizeof(b),polykey);
|
poly1305(b,b,sizeof(b),polykey);
|
||||||
|
|
||||||
|
// Criterion: add two 64-bit components of poly1305 hash, must be zero mod 180.
|
||||||
|
// As with the rest of this bits are used in little-endian byte order. The value
|
||||||
|
// of 180 was set empirically to result in about one second per new identity on
|
||||||
|
// one CPU core of a typical desktop or server in 2020.
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
const uint64_t finalHash = Utils::swapBytes(b[0]) + Utils::swapBytes(b[1]);
|
const uint64_t finalHash = Utils::swapBytes(b[0]) + Utils::swapBytes(b[1]);
|
||||||
#else
|
#else
|
||||||
|
@ -168,7 +186,7 @@ bool Identity::generate(const Type t)
|
||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||||
do {
|
do {
|
||||||
C25519::generateSatisfying(_v0_identity_generate_cond(digest,genmem),_pub.c25519,_priv.c25519);
|
C25519::generateSatisfying(identityV0ProofOfWorkCriteria(digest,genmem),_pub.c25519,_priv.c25519);
|
||||||
_address.setTo(digest + 59);
|
_address.setTo(digest + 59);
|
||||||
} while (_address.isReserved());
|
} while (_address.isReserved());
|
||||||
delete[] genmem;
|
delete[] genmem;
|
||||||
|
@ -182,7 +200,7 @@ v1_pow_new_keys:
|
||||||
C25519::generate(_pub.c25519,_priv.c25519);
|
C25519::generate(_pub.c25519,_priv.c25519);
|
||||||
ECC384GenerateKey(_pub.p384,_priv.p384);
|
ECC384GenerateKey(_pub.p384,_priv.p384);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (_v1_identity_generate_cond(&_pub,sizeof(_pub)))
|
if (identityV1ProofOfWorkCriteria(&_pub,sizeof(_pub)))
|
||||||
break;
|
break;
|
||||||
if (++_pub.nonce == 0) // endian-ness doesn't matter, just change the nonce each time
|
if (++_pub.nonce == 0) // endian-ness doesn't matter, just change the nonce each time
|
||||||
goto v1_pow_new_keys;
|
goto v1_pow_new_keys;
|
||||||
|
@ -211,13 +229,13 @@ bool Identity::locallyValidate() const noexcept
|
||||||
case C25519: {
|
case C25519: {
|
||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
char *genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
char *genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
|
||||||
_computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
|
identityV0ProofOfWorkFrankenhash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
|
||||||
delete[] genmem;
|
delete[] genmem;
|
||||||
return ((_address == Address(digest + 59)) && (digest[0] < 17));
|
return ((_address == Address(digest + 59)) && (digest[0] < 17));
|
||||||
}
|
}
|
||||||
|
|
||||||
case P384:
|
case P384:
|
||||||
return ( (_address == Address(_fp.hash())) && _v1_identity_generate_cond(&_pub,sizeof(_pub)) );
|
return ((_address == Address(_fp.hash())) && identityV1ProofOfWorkCriteria(&_pub,sizeof(_pub)) );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue