Adam Ierymenko 5 лет назад
Родитель
Сommit
1c7e1da4d1
4 измененных файлов с 30 добавлено и 16 удалено
  1. 8 8
      node/Identity.cpp
  2. 9 6
      node/Identity.hpp
  3. 1 2
      node/MIMC52.cpp
  4. 12 0
      node/Tests.cpp

+ 8 - 8
node/Identity.cpp

@@ -105,7 +105,7 @@ bool Identity::generate(const Type t)
 				ECC384GenerateKey(_pub.p384,_priv.p384);
 				ECC384GenerateKey(_pub.p384,_priv.p384);
 				Utils::storeBigEndian(_pub.t1mimc52,mimc52Delay(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE));
 				Utils::storeBigEndian(_pub.t1mimc52,mimc52Delay(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE));
 				_computeHash();
 				_computeHash();
-				_address.setTo(_hash.data());
+				_address.setTo(_fp.data());
 				if (!_address.isReserved())
 				if (!_address.isReserved())
 					break;
 					break;
 			}
 			}
@@ -130,12 +130,12 @@ bool Identity::locallyValidate() const
 				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);
 				_computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
 				delete [] genmem;
 				delete [] genmem;
-				return ((_address == Address(digest + 59))&&(!_address.isReserved())&&(digest[0] < 17));
+				return ((_address == Address(digest + 59))&&(digest[0] < 17));
 			} catch ( ... ) {}
 			} catch ( ... ) {}
 			break;
 			break;
 
 
 		case P384:
 		case P384:
-			if ((_address == Address(_hash.data()))&&(!_address.isReserved())) {
+			if (_address == Address(_fp.data())) {
 				// The most significant 8 bits of the MIMC proof included with v1 identities can be used to store a multiplier
 				// The most significant 8 bits of the MIMC proof included with v1 identities can be used to store a multiplier
 				// that can indicate that more work than the required minimum has been performed. Right now this is never done
 				// that can indicate that more work than the required minimum has been performed. Right now this is never done
 				// but it could have some use in the future. There is no harm in doing it, and we'll accept any round count
 				// but it could have some use in the future. There is no harm in doing it, and we'll accept any round count
@@ -303,7 +303,7 @@ char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_
 
 
 bool Identity::fromString(const char *str)
 bool Identity::fromString(const char *str)
 {
 {
-	_hash.zero();
+	_fp.zero();
 	_hasPrivate = false;
 	_hasPrivate = false;
 
 
 	if (!str) {
 	if (!str) {
@@ -438,7 +438,7 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
 
 
 int Identity::unmarshal(const uint8_t *data,const int len) noexcept
 int Identity::unmarshal(const uint8_t *data,const int len) noexcept
 {
 {
-	_hash.zero();
+	_fp.zero();
 	_hasPrivate = false;
 	_hasPrivate = false;
 
 
 	if (len < (ZT_ADDRESS_LENGTH + 1))
 	if (len < (ZT_ADDRESS_LENGTH + 1))
@@ -504,15 +504,15 @@ void Identity::_computeHash()
 {
 {
 	switch(_type) {
 	switch(_type) {
 		default:
 		default:
-			_hash.zero();
+			_fp.zero();
 			break;
 			break;
 
 
 		case C25519:
 		case C25519:
-			SHA384(_hash.data(),_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
+			SHA384(_fp.data(),_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
 			break;
 			break;
 
 
 		case P384:
 		case P384:
-			SHA384(_hash.data(),&_pub,sizeof(_pub));
+			SHA384(_fp.data(),&_pub,sizeof(_pub));
 			break;
 			break;
 	}
 	}
 }
 }

+ 9 - 6
node/Identity.hpp

@@ -41,7 +41,10 @@ namespace ZeroTier {
  * and Ed25519 and type 1 identities that include both a 25519 key pair and a NIST P-384
  * and Ed25519 and type 1 identities that include both a 25519 key pair and a NIST P-384
  * key pair. Type 1 identities use P-384 for signatures but use both key pairs at once
  * key pair. Type 1 identities use P-384 for signatures but use both key pairs at once
  * (hashing both keys together) for key agreement with other type 1 identities, and can
  * (hashing both keys together) for key agreement with other type 1 identities, and can
- * agree with type 0 identities by only using the Curve25519 component.
+ * agree with type 0 identities using only Curve25519.
+ *
+ * Type 1 identities are better in many ways but type 0 will remain the default until
+ * 1.x nodes are pretty much dead in the wild.
  */
  */
 class Identity : public TriviallyCopyable
 class Identity : public TriviallyCopyable
 {
 {
@@ -121,7 +124,7 @@ public:
 	 *
 	 *
 	 * @return Hash of public key(s)
 	 * @return Hash of public key(s)
 	 */
 	 */
-	ZT_ALWAYS_INLINE const Fingerprint &fingerprint() const noexcept { return _hash; }
+	ZT_ALWAYS_INLINE const Fingerprint &fingerprint() const noexcept { return _fp; }
 
 
 	/**
 	/**
 	 * Compute a hash of this identity's public and private keys.
 	 * Compute a hash of this identity's public and private keys.
@@ -198,11 +201,11 @@ public:
 	 */
 	 */
 	explicit ZT_ALWAYS_INLINE operator bool() const noexcept { return (_address); }
 	explicit ZT_ALWAYS_INLINE operator bool() const noexcept { return (_address); }
 
 
-	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _hash.hashCode(); }
+	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _fp.hashCode(); }
 
 
 	ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept
 	ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept
 	{
 	{
-		return ((_address == id._address)&&(_type == id._type)&&(memcmp(_hash.data(),id._hash.data(),ZT_SHA384_DIGEST_LEN) == 0));
+		return ((_address == id._address)&&(_type == id._type)&&(memcmp(_fp.data(),id._fp.data(),ZT_SHA384_DIGEST_LEN) == 0));
 	}
 	}
 	ZT_ALWAYS_INLINE bool operator!=(const Identity &id) const noexcept { return !(*this == id); }
 	ZT_ALWAYS_INLINE bool operator!=(const Identity &id) const noexcept { return !(*this == id); }
 	ZT_ALWAYS_INLINE bool operator<(const Identity &id) const noexcept
 	ZT_ALWAYS_INLINE bool operator<(const Identity &id) const noexcept
@@ -213,7 +216,7 @@ public:
 			if ((int)_type < (int)id._type)
 			if ((int)_type < (int)id._type)
 				return true;
 				return true;
 			if (_type == id._type)
 			if (_type == id._type)
-				return memcmp(_hash.data(),id._hash.data(),ZT_SHA384_DIGEST_LEN) < 0;
+				return memcmp(_fp.data(),id._fp.data(),ZT_SHA384_DIGEST_LEN) < 0;
 		}
 		}
 		return false;
 		return false;
 	}
 	}
@@ -229,7 +232,7 @@ private:
 	void _computeHash();
 	void _computeHash();
 
 
 	Address _address;
 	Address _address;
-	Fingerprint _hash;
+	Fingerprint _fp;
 	ZT_PACKED_STRUCT(struct { // do not re-order these fields
 	ZT_PACKED_STRUCT(struct { // do not re-order these fields
 		uint8_t c25519[ZT_C25519_PRIVATE_KEY_LEN];
 		uint8_t c25519[ZT_C25519_PRIVATE_KEY_LEN];
 		uint8_t p384[ZT_ECC384_PRIVATE_KEY_SIZE];
 		uint8_t p384[ZT_ECC384_PRIVATE_KEY_SIZE];

+ 1 - 2
node/MIMC52.cpp

@@ -42,8 +42,7 @@ ZT_ALWAYS_INLINE uint64_t mulmod52(uint64_t a,uint64_t b,const uint64_t m) noexc
 	// It seems to be the fastest method on systems with a good double precision FPU.
 	// It seems to be the fastest method on systems with a good double precision FPU.
 	return ((a * b) - (((uint64_t)(((double)a * (double)b) / (double)m) - 1ULL) * m)) % m;
 	return ((a * b) - (((uint64_t)(((double)a * (double)b) / (double)m) - 1ULL) * m)) % m;
 #else
 #else
-	// This is significantly slower on systems with a good FPU but will work any others. It supports 63 bits
-	// of precision even though we use only 52.
+	// This can be used as a fallback for any systems without FPU or with FPU precision issues.
 	int64_t res = 0;
 	int64_t res = 0;
 	for(;;) {
 	for(;;) {
 		if (a & 1ULL)
 		if (a & 1ULL)

+ 12 - 0
node/Tests.cpp

@@ -1024,6 +1024,12 @@ extern "C" const char *ZTT_benchmarkCrypto()
 			}
 			}
 			int64_t end = now();
 			int64_t end = now();
 			ZT_T_PRINTF("%.4f ms/generation (average, can vary quite a bit)" ZT_EOL_S,(double)(end - start) / 5.0);
 			ZT_T_PRINTF("%.4f ms/generation (average, can vary quite a bit)" ZT_EOL_S,(double)(end - start) / 5.0);
+			ZT_T_PRINTF("[crypto] Benchmarking V0 Identity full validation... ");
+			start = now();
+			for(long i=0;i<10;++i)
+				foo = (uint8_t)id.locallyValidate();
+			end = now();
+			ZT_T_PRINTF("%.4f μs/validation" ZT_EOL_S,((double)(end - start) * 1000.0) / 10.0);
 			ZT_T_PRINTF("[crypto] Benchmarking V1 Identity generation... ");
 			ZT_T_PRINTF("[crypto] Benchmarking V1 Identity generation... ");
 			start = now();
 			start = now();
 			for(long i=0;i<5;++i) {
 			for(long i=0;i<5;++i) {
@@ -1032,6 +1038,12 @@ extern "C" const char *ZTT_benchmarkCrypto()
 			}
 			}
 			end = now();
 			end = now();
 			ZT_T_PRINTF("%.4f ms/generation (relatively constant time)" ZT_EOL_S,(double)(end - start) / 5.0);
 			ZT_T_PRINTF("%.4f ms/generation (relatively constant time)" ZT_EOL_S,(double)(end - start) / 5.0);
+			ZT_T_PRINTF("[crypto] Benchmarking V1 Identity full validation... ");
+			start = now();
+			for(long i=0;i<100;++i)
+				foo = (uint8_t)id.locallyValidate();
+			end = now();
+			ZT_T_PRINTF("%.4f μs/validation" ZT_EOL_S,((double)(end - start) * 1000.0) / 100.0);
 		}
 		}
 	} catch (std::exception &e) {
 	} catch (std::exception &e) {
 		ZT_T_PRINTF(ZT_EOL_S "[crypto] Unexpected exception: %s" ZT_EOL_S,e.what());
 		ZT_T_PRINTF(ZT_EOL_S "[crypto] Unexpected exception: %s" ZT_EOL_S,e.what());