Browse Source

Fingerprint string conversion, API stuff

Adam Ierymenko 5 years ago
parent
commit
b96ea5ae03
4 changed files with 62 additions and 13 deletions
  1. 15 0
      include/ZeroTierCore.h
  2. 38 0
      node/Fingerprint.hpp
  3. 7 0
      node/Identity.cpp
  4. 2 13
      node/Identity.hpp

+ 15 - 0
include/ZeroTierCore.h

@@ -299,7 +299,14 @@ typedef void ZT_Identity;
  */
 ZT_PACKED_STRUCT(struct _ZT_Fingerprint
 {
+	/**
+	 * Short address (only least significant 40 bits are used)
+	 */
 	uint64_t address;
+
+	/**
+	 * 384-bit hash of identity public key(s)
+	 */
 	uint8_t hash[48];
 });
 typedef struct _ZT_Fingerprint ZT_Fingerprint;
@@ -2142,6 +2149,14 @@ ZT_SDK_API int ZT_Identity_hasPrivate(const ZT_Identity *id);
  */
 ZT_SDK_API uint64_t ZT_Identity_address(const ZT_Identity *id);
 
+/**
+ * Get this identity's full fingerprint
+ *
+ * @param id Identity to query
+ * @return Pointer to fingerprint (remains valid as long as identity itself is valid)
+ */
+ZT_SDK_API const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id);
+
 /**
  * Delete an identity and free associated memory
  *

+ 38 - 0
node/Fingerprint.hpp

@@ -17,9 +17,12 @@
 #include "Constants.hpp"
 #include "TriviallyCopyable.hpp"
 #include "Address.hpp"
+#include "Utils.hpp"
 
 #include <algorithm>
 
+#define ZT_FINGERPRINT_STRING_BUFFER_LENGTH 96
+
 namespace ZeroTier {
 
 class Identity;
@@ -54,6 +57,41 @@ public:
 	 */
 	ZT_ALWAYS_INLINE void getAPIFingerprint(ZT_Fingerprint *fp) const noexcept { memcpy(fp,&_fp,sizeof(ZT_Fingerprint)); }
 
+	/**
+	 * @return Pointer to ZT_Fingerprint for API use
+	 */
+	ZT_ALWAYS_INLINE const ZT_Fingerprint *apiFingerprint() const noexcept { return &_fp; }
+
+	/**
+	 * Get a base32-encoded representation of this fingerprint
+	 *
+	 * @param s Base32 string
+	 */
+	ZT_ALWAYS_INLINE void toString(char s[ZT_FINGERPRINT_STRING_BUFFER_LENGTH])
+	{
+		uint8_t tmp[48 + 5];
+		address().copyTo(tmp);
+		memcpy(tmp + 5,_fp.hash,48);
+		Utils::b32e(tmp,sizeof(tmp),s,ZT_FINGERPRINT_STRING_BUFFER_LENGTH);
+		s[ZT_FINGERPRINT_STRING_BUFFER_LENGTH-1] = 0; // sanity check, ensure always zero terminated
+	}
+
+	/**
+	 * Set this fingerprint to a base32-encoded string
+	 *
+	 * @param s String to decode
+	 * @return True if string appears to be valid and of the proper length (no other checking is done)
+	 */
+	ZT_ALWAYS_INLINE bool fromString(const char *s)
+	{
+		uint8_t tmp[48 + 5];
+		if (Utils::b32d(s,tmp,sizeof(tmp)) != sizeof(tmp))
+			return false;
+		_fp.address = Address(tmp).toInt();
+		memcpy(_fp.hash,tmp + 5,48);
+		return true;
+	}
+
 	ZT_ALWAYS_INLINE void zero() noexcept { memoryZero(this); }
 	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _fp.address; }
 

+ 7 - 0
node/Identity.cpp

@@ -599,6 +599,13 @@ uint64_t ZT_Identity_address(const ZT_Identity *id)
 	return reinterpret_cast<const ZeroTier::Identity *>(id)->address().toInt();
 }
 
+const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id)
+{
+	if (!id)
+		return nullptr;
+	return reinterpret_cast<const ZeroTier::Identity *>(id)->fingerprint().apiFingerprint();
+}
+
 ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id)
 {
 	if (id)

+ 2 - 13
node/Identity.hpp

@@ -203,20 +203,9 @@ public:
 
 	ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _fp.hashCode(); }
 
-	ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept { return ((_address == id._address)&&(_fp == id._fp)); }
+	ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept { return (_fp == id._fp); }
 	ZT_ALWAYS_INLINE bool operator!=(const Identity &id) const noexcept { return !(*this == id); }
-	ZT_ALWAYS_INLINE bool operator<(const Identity &id) const noexcept
-	{
-		if (_address < id._address)
-			return true;
-		if (_address == id._address) {
-			if ((int)_type < (int)id._type)
-				return true;
-			if (_type == id._type)
-				return _fp < id._fp;
-		}
-		return false;
-	}
+	ZT_ALWAYS_INLINE bool operator<(const Identity &id) const noexcept { return (_fp < id._fp); }
 	ZT_ALWAYS_INLINE bool operator>(const Identity &id) const noexcept { return (id < *this); }
 	ZT_ALWAYS_INLINE bool operator<=(const Identity &id) const noexcept { return !(id < *this); }
 	ZT_ALWAYS_INLINE bool operator>=(const Identity &id) const noexcept { return !(*this < id); }