Identity.hpp 9.0 KB

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