From b96ea5ae032cfab1050df020d51409315e792d6b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 2 Mar 2020 15:13:34 -0800 Subject: [PATCH] Fingerprint string conversion, API stuff --- include/ZeroTierCore.h | 15 +++++++++++++++ node/Fingerprint.hpp | 38 ++++++++++++++++++++++++++++++++++++++ node/Identity.cpp | 7 +++++++ node/Identity.hpp | 15 ++------------- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/include/ZeroTierCore.h b/include/ZeroTierCore.h index 7adac1194..54bc60bd3 100644 --- a/include/ZeroTierCore.h +++ b/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 * diff --git a/node/Fingerprint.hpp b/node/Fingerprint.hpp index 35789994e..476ea10e3 100644 --- a/node/Fingerprint.hpp +++ b/node/Fingerprint.hpp @@ -17,9 +17,12 @@ #include "Constants.hpp" #include "TriviallyCopyable.hpp" #include "Address.hpp" +#include "Utils.hpp" #include +#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; } diff --git a/node/Identity.cpp b/node/Identity.cpp index e1a4ed976..3303f2522 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -599,6 +599,13 @@ uint64_t ZT_Identity_address(const ZT_Identity *id) return reinterpret_cast(id)->address().toInt(); } +const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) +{ + if (!id) + return nullptr; + return reinterpret_cast(id)->fingerprint().apiFingerprint(); +} + ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id) { if (id) diff --git a/node/Identity.hpp b/node/Identity.hpp index edf7dce8c..b40bb528e 100644 --- a/node/Identity.hpp +++ b/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); }