type 1 (P-384) identities

This commit is contained in:
Adam Ierymenko 2019-08-20 13:32:23 -07:00
parent 6e771607c0
commit 83d723eb79
No known key found for this signature in database
GPG key ID: 1657198823E52A61
15 changed files with 467 additions and 591 deletions

View file

@ -40,7 +40,8 @@ namespace ZeroTier {
namespace {
// These can't be changed without a new identity type. They define the
// parameters of the hashcash hashing/searching algorithm.
// parameters of the hashcash hashing/searching algorithm for type 0
// identities.
#define ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN 17
#define ZT_IDENTITY_GEN_MEMORY 2097152
@ -86,9 +87,9 @@ struct _Identity_generate_cond
{
inline _Identity_generate_cond() {}
inline _Identity_generate_cond(unsigned char *sb,char *gm) : digest(sb),genmem(gm) {}
inline bool operator()(const C25519::Pair &kp) const
inline bool operator()(const uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN]) const
{
_computeMemoryHardHash(kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
_computeMemoryHardHash(pub,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
return (digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN);
}
unsigned char *digest;
@ -100,71 +101,44 @@ struct _Identity_generate_cond
void Identity::generate(const Type t)
{
uint8_t digest[64];
_type = t;
_hasPrivate = true;
char *const genmem = new char[ZT_IDENTITY_GEN_MEMORY];
switch(t) {
case C25519: {
C25519::Pair kp;
do {
kp = C25519::generateSatisfying(_Identity_generate_cond(digest,genmem));
_address.setTo(digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
} while (_address.isReserved());
memcpy(_k.t0.pub.data,kp.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
memcpy(_k.t0.priv.data,kp.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
_type = C25519;
_hasPrivate = true;
} break;
case P384: {
do {
ECC384GenerateKey(_k.t1.pub,_k.t1.priv);
_computeMemoryHardHash(_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE,digest,genmem);
if (digest[0] >= ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)
continue;
_address.setTo(digest + 59,ZT_ADDRESS_LENGTH);
} while (_address.isReserved());
_type = P384;
_hasPrivate = true;
} break;
}
do {
C25519::generateSatisfying(_Identity_generate_cond(digest,genmem),_pub.c25519,_priv.c25519);
_address.setTo(digest + 59,ZT_ADDRESS_LENGTH); // last 5 bytes are address
} while (_address.isReserved());
delete [] genmem;
if (t == P384)
ECC384GenerateKey(_pub.p384,_priv.p384);
}
bool Identity::locallyValidate() const
{
if (_address.isReserved())
return false;
uint8_t digest[64];
char *genmem = nullptr;
try {
uint8_t digest[64];
genmem = new char[ZT_IDENTITY_GEN_MEMORY];
switch(_type) {
case C25519:
_computeMemoryHardHash(_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
break;
case P384:
_computeMemoryHardHash(_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE,digest,genmem);
break;
default:
return false;
}
_computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
delete [] genmem;
unsigned char addrb[5];
_address.copyTo(addrb,5);
return (
(digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN)&&
(digest[59] == addrb[0])&&
(digest[60] == addrb[1])&&
(digest[61] == addrb[2])&&
(digest[62] == addrb[3])&&
(digest[63] == addrb[4]));
return ((_address == Address(digest + 59,ZT_ADDRESS_LENGTH))&&(!_address.isReserved())&&(digest[0] < ZT_IDENTITY_GEN_HASHCASH_FIRST_BYTE_LESS_THAN));
} catch ( ... ) {
if (genmem) delete [] genmem;
return false;
}
return false;
}
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
{
switch(_type) {
case C25519: {
char *p = buf;
Utils::hex10(_address.toInt(),p);
@ -172,16 +146,17 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
*(p++) = ':';
*(p++) = '0';
*(p++) = ':';
Utils::hex(_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN,p);
Utils::hex(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,p);
p += ZT_C25519_PUBLIC_KEY_LEN * 2;
if ((_hasPrivate)&&(includePrivate)) {
*(p++) = ':';
Utils::hex(_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN,p);
Utils::hex(_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN,p);
p += ZT_C25519_PRIVATE_KEY_LEN * 2;
}
*p = (char)0;
return buf;
} break;
case P384: {
char *p = buf;
Utils::hex10(_address.toInt(),p);
@ -189,38 +164,43 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
*(p++) = ':';
*(p++) = '1';
*(p++) = ':';
Utils::hex(_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE,p);
p += ZT_ECC384_PUBLIC_KEY_SIZE * 2;
int el = Utils::b32e((const uint8_t *)(&_pub),ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,p,(unsigned int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
if (el <= 0) return nullptr;
p += el;
if ((_hasPrivate)&&(includePrivate)) {
*(p++) = ':';
Utils::hex(_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE,p);
p += ZT_ECC384_PRIVATE_KEY_SIZE * 2;
el = Utils::b32e((const uint8_t *)(&_pub),ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE,p,(unsigned int)(ZT_IDENTITY_STRING_BUFFER_LENGTH - (uintptr_t)(p - buf)));
if (el <= 0) return nullptr;
p += el;
}
*p = (char)0;
return buf;
} break;
}
return nullptr;
}
bool Identity::fromString(const char *str)
{
_hasPrivate = false;
if (!str) {
_address.zero();
return false;
}
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
if (!Utils::scopy(tmp,sizeof(tmp),str)) {
_address.zero();
return false;
}
_hasPrivate = false;
int fno = 0;
char *saveptr = (char *)0;
for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) {
for(char *f=Utils::stok(tmp,":",&saveptr);((f)&&(fno < 4));f=Utils::stok((char *)0,":",&saveptr)) {
switch(fno++) {
case 0:
_address = Address(Utils::hexStrToU64(f));
if (_address.isReserved()) {
@ -228,6 +208,7 @@ bool Identity::fromString(const char *str)
return false;
}
break;
case 1:
if ((f[0] == '0')&&(!f[1])) {
_type = C25519;
@ -238,47 +219,56 @@ bool Identity::fromString(const char *str)
return false;
}
break;
case 2:
switch(_type) {
case C25519:
if (Utils::unhex(f,_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
if (Utils::unhex(f,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN) != ZT_C25519_PUBLIC_KEY_LEN) {
_address.zero();
return false;
}
break;
case P384:
if (Utils::unhex(f,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE) != ZT_ECC384_PUBLIC_KEY_SIZE) {
if (Utils::b32d(f,(uint8_t *)(&_pub),ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE) != (ZT_C25519_PUBLIC_KEY_LEN + ZT_ECC384_PUBLIC_KEY_SIZE)) {
_address.zero();
return false;
}
break;
}
break;
case 3:
switch(_type) {
case C25519:
if (Utils::unhex(f,_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
_address.zero();
return false;
} else {
_hasPrivate = true;
}
break;
case P384:
if (Utils::unhex(f,_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE) != ZT_ECC384_PRIVATE_KEY_SIZE) {
_address.zero();
return false;
} else {
_hasPrivate = true;
}
break;
if (strlen(f) > 1) {
switch(_type) {
case C25519:
if (Utils::unhex(f,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN) != ZT_C25519_PRIVATE_KEY_LEN) {
_address.zero();
return false;
} else {
_hasPrivate = true;
}
break;
case P384:
if (Utils::b32d(f,(uint8_t *)(&_priv),ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE) != (ZT_C25519_PRIVATE_KEY_LEN + ZT_ECC384_PRIVATE_KEY_SIZE)) {
_address.zero();
return false;
} else {
_hasPrivate = true;
}
break;
}
break;
}
break;
default:
_address.zero();
return false;
}
}
if (fno < 3) {
_address.zero();
return false;