Identity.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * Copyright (c)2019 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2026-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_IDENTITY_HPP
  14. #define ZT_IDENTITY_HPP
  15. #include "Address.hpp"
  16. #include "Buffer.hpp"
  17. #include "C25519.hpp"
  18. #include "Constants.hpp"
  19. #include "SHA512.hpp"
  20. #include "Utils.hpp"
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #define ZT_IDENTITY_STRING_BUFFER_LENGTH 384
  24. namespace ZeroTier {
  25. /**
  26. * A ZeroTier identity
  27. *
  28. * An identity consists of a public key, a 40-bit ZeroTier address computed
  29. * from that key in a collision-resistant fashion, and a self-signature.
  30. *
  31. * The address derivation algorithm makes it computationally very expensive to
  32. * search for a different public key that duplicates an existing address. (See
  33. * code for deriveAddress() for this algorithm.)
  34. */
  35. class Identity {
  36. public:
  37. Identity() : _privateKey((C25519::Private*)0)
  38. {
  39. }
  40. Identity(const Identity& id) : _address(id._address), _publicKey(id._publicKey), _privateKey((id._privateKey) ? new C25519::Private(*(id._privateKey)) : (C25519::Private*)0)
  41. {
  42. }
  43. Identity(const char* str) : _privateKey((C25519::Private*)0)
  44. {
  45. if (! fromString(str)) {
  46. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
  47. }
  48. }
  49. template <unsigned int C> Identity(const Buffer<C>& b, unsigned int startAt = 0) : _privateKey((C25519::Private*)0)
  50. {
  51. deserialize(b, startAt);
  52. }
  53. ~Identity()
  54. {
  55. if (_privateKey) {
  56. Utils::burn(_privateKey, sizeof(C25519::Private));
  57. delete _privateKey;
  58. }
  59. }
  60. inline Identity& operator=(const Identity& id)
  61. {
  62. _address = id._address;
  63. _publicKey = id._publicKey;
  64. if (id._privateKey) {
  65. if (! _privateKey) {
  66. _privateKey = new C25519::Private();
  67. }
  68. *_privateKey = *(id._privateKey);
  69. }
  70. else {
  71. delete _privateKey;
  72. _privateKey = (C25519::Private*)0;
  73. }
  74. return *this;
  75. }
  76. /**
  77. * Generate a new identity (address, key pair)
  78. *
  79. * This is a time consuming operation.
  80. */
  81. void generate();
  82. /**
  83. * Check the validity of this identity's pairing of key to address
  84. *
  85. * @return True if validation check passes
  86. */
  87. bool locallyValidate() const;
  88. /**
  89. * @return True if this identity contains a private key
  90. */
  91. inline bool hasPrivate() const
  92. {
  93. return (_privateKey != (C25519::Private*)0);
  94. }
  95. /**
  96. * Compute a SHA384 hash of this identity's address and public key(s).
  97. *
  98. * @param sha384buf Buffer with 48 bytes of space to receive hash
  99. */
  100. inline void publicKeyHash(void* sha384buf) const
  101. {
  102. uint8_t address[ZT_ADDRESS_LENGTH];
  103. _address.copyTo(address, ZT_ADDRESS_LENGTH);
  104. SHA384(sha384buf, address, ZT_ADDRESS_LENGTH, _publicKey.data, ZT_C25519_PUBLIC_KEY_LEN);
  105. }
  106. /**
  107. * Compute the SHA512 hash of our private key (if we have one)
  108. *
  109. * @param sha Buffer to receive SHA512 (MUST be ZT_SHA512_DIGEST_LEN (64) bytes in length)
  110. * @return True on success, false if no private key
  111. */
  112. inline bool sha512PrivateKey(void* sha) const
  113. {
  114. if (_privateKey) {
  115. SHA512(sha, _privateKey->data, ZT_C25519_PRIVATE_KEY_LEN);
  116. return true;
  117. }
  118. return false;
  119. }
  120. /**
  121. * Sign a message with this identity (private key required)
  122. *
  123. * @param data Data to sign
  124. * @param len Length of data
  125. */
  126. inline C25519::Signature sign(const void* data, unsigned int len) const
  127. {
  128. if (_privateKey) {
  129. return C25519::sign(*_privateKey, _publicKey, data, len);
  130. }
  131. throw ZT_EXCEPTION_PRIVATE_KEY_REQUIRED;
  132. }
  133. /**
  134. * Verify a message signature against this identity
  135. *
  136. * @param data Data to check
  137. * @param len Length of data
  138. * @param signature Signature bytes
  139. * @param siglen Length of signature in bytes
  140. * @return True if signature validates and data integrity checks
  141. */
  142. inline bool verify(const void* data, unsigned int len, const void* signature, unsigned int siglen) const
  143. {
  144. if (siglen != ZT_C25519_SIGNATURE_LEN) {
  145. return false;
  146. }
  147. return C25519::verify(_publicKey, data, len, signature);
  148. }
  149. /**
  150. * Verify a message signature against this identity
  151. *
  152. * @param data Data to check
  153. * @param len Length of data
  154. * @param signature Signature
  155. * @return True if signature validates and data integrity checks
  156. */
  157. inline bool verify(const void* data, unsigned int len, const C25519::Signature& signature) const
  158. {
  159. return C25519::verify(_publicKey, data, len, signature);
  160. }
  161. /**
  162. * Shortcut method to perform key agreement with another identity
  163. *
  164. * This identity must have a private key. (Check hasPrivate())
  165. *
  166. * @param id Identity to agree with
  167. * @param key Result parameter to fill with key bytes
  168. * @return Was agreement successful?
  169. */
  170. inline bool agree(const Identity& id, void* const key) const
  171. {
  172. if (_privateKey) {
  173. C25519::agree(*_privateKey, id._publicKey, key, ZT_SYMMETRIC_KEY_SIZE);
  174. return true;
  175. }
  176. return false;
  177. }
  178. /**
  179. * @return This identity's address
  180. */
  181. inline const Address& address() const
  182. {
  183. return _address;
  184. }
  185. /**
  186. * Serialize this identity (binary)
  187. *
  188. * @param b Destination buffer to append to
  189. * @param includePrivate If true, include private key component (if present) (default: false)
  190. * @throws std::out_of_range Buffer too small
  191. */
  192. template <unsigned int C> inline void serialize(Buffer<C>& b, bool includePrivate = false) const
  193. {
  194. _address.appendTo(b);
  195. b.append((uint8_t)0); // C25519/Ed25519 identity type
  196. b.append(_publicKey.data, ZT_C25519_PUBLIC_KEY_LEN);
  197. if ((_privateKey) && (includePrivate)) {
  198. b.append((unsigned char)ZT_C25519_PRIVATE_KEY_LEN);
  199. b.append(_privateKey->data, ZT_C25519_PRIVATE_KEY_LEN);
  200. }
  201. else {
  202. b.append((unsigned char)0);
  203. }
  204. }
  205. /**
  206. * Deserialize a binary serialized identity
  207. *
  208. * If an exception is thrown, the Identity object is left in an undefined
  209. * state and should not be used.
  210. *
  211. * @param b Buffer containing serialized data
  212. * @param startAt Index within buffer of serialized data (default: 0)
  213. * @return Length of serialized data read from buffer
  214. * @throws std::out_of_range Serialized data invalid
  215. * @throws std::invalid_argument Serialized data invalid
  216. */
  217. template <unsigned int C> inline unsigned int deserialize(const Buffer<C>& b, unsigned int startAt = 0)
  218. {
  219. delete _privateKey;
  220. _privateKey = (C25519::Private*)0;
  221. unsigned int p = startAt;
  222. _address.setTo(b.field(p, ZT_ADDRESS_LENGTH), ZT_ADDRESS_LENGTH);
  223. p += ZT_ADDRESS_LENGTH;
  224. if (b[p++] != 0) {
  225. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
  226. }
  227. memcpy(_publicKey.data, b.field(p, ZT_C25519_PUBLIC_KEY_LEN), ZT_C25519_PUBLIC_KEY_LEN);
  228. p += ZT_C25519_PUBLIC_KEY_LEN;
  229. unsigned int privateKeyLength = (unsigned int)b[p++];
  230. if (privateKeyLength) {
  231. if (privateKeyLength != ZT_C25519_PRIVATE_KEY_LEN) {
  232. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
  233. }
  234. _privateKey = new C25519::Private();
  235. memcpy(_privateKey->data, b.field(p, ZT_C25519_PRIVATE_KEY_LEN), ZT_C25519_PRIVATE_KEY_LEN);
  236. p += ZT_C25519_PRIVATE_KEY_LEN;
  237. }
  238. return (p - startAt);
  239. }
  240. /**
  241. * Serialize to a more human-friendly string
  242. *
  243. * @param includePrivate If true, include private key (if it exists)
  244. * @param buf Buffer to store string
  245. * @return ASCII string representation of identity
  246. */
  247. char* toString(bool includePrivate, char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
  248. /**
  249. * Deserialize a human-friendly string
  250. *
  251. * Note: validation is for the format only. The locallyValidate() method
  252. * must be used to check signature and address/key correspondence.
  253. *
  254. * @param str String to deserialize
  255. * @return True if deserialization appears successful
  256. */
  257. bool fromString(const char* str);
  258. /**
  259. * @return C25519 public key
  260. */
  261. inline const C25519::Public& publicKey() const
  262. {
  263. return _publicKey;
  264. }
  265. /**
  266. * @return C25519 key pair (only returns valid pair if private key is present in this Identity object)
  267. */
  268. inline const C25519::Pair privateKeyPair() const
  269. {
  270. C25519::Pair pair;
  271. pair.pub = _publicKey;
  272. if (_privateKey) {
  273. pair.priv = *_privateKey;
  274. }
  275. else {
  276. memset(pair.priv.data, 0, ZT_C25519_PRIVATE_KEY_LEN);
  277. }
  278. return pair;
  279. }
  280. /**
  281. * @return True if this identity contains something
  282. */
  283. inline operator bool() const
  284. {
  285. return (_address);
  286. }
  287. inline bool operator==(const Identity& id) const
  288. {
  289. return ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_C25519_PUBLIC_KEY_LEN) == 0));
  290. }
  291. inline bool operator<(const Identity& id) const
  292. {
  293. return ((_address < id._address) || ((_address == id._address) && (memcmp(_publicKey.data, id._publicKey.data, ZT_C25519_PUBLIC_KEY_LEN) < 0)));
  294. }
  295. inline bool operator!=(const Identity& id) const
  296. {
  297. return ! (*this == id);
  298. }
  299. inline bool operator>(const Identity& id) const
  300. {
  301. return (id < *this);
  302. }
  303. inline bool operator<=(const Identity& id) const
  304. {
  305. return ! (id < *this);
  306. }
  307. inline bool operator>=(const Identity& id) const
  308. {
  309. return ! (*this < id);
  310. }
  311. private:
  312. Address _address;
  313. C25519::Public _publicKey;
  314. C25519::Private* _privateKey;
  315. };
  316. } // namespace ZeroTier
  317. #endif