/ libi2pd / Identity.cpp
Identity.cpp
  1  /*
  2  * Copyright (c) 2013-2026, The PurpleI2P Project
  3  *
  4  * This file is part of Purple i2pd project and licensed under BSD3
  5  *
  6  * See full license text in LICENSE file at top of project tree
  7  */
  8  
  9  #include "Crypto.h"
 10  #include "I2PEndian.h"
 11  #include "Log.h"
 12  #include "Timestamp.h"
 13  #include "CryptoKey.h"
 14  #include "Identity.h"
 15  
 16  namespace i2p
 17  {
 18  namespace data
 19  {
 20      std::vector<IdentHash> ExtractIdentHashes (std::string_view hashes)
 21      {
 22          std::vector<IdentHash> idents;
 23          if (!hashes.empty ())
 24          {
 25              size_t pos = 0, comma;
 26              do
 27              {
 28                  comma = hashes.find (',', pos);
 29                  i2p::data::IdentHash ident;
 30                  if (ident.FromBase64 (hashes.substr (pos, comma != std::string_view::npos ? comma - pos : std::string_view::npos)))
 31                      idents.push_back (ident);
 32                  pos = comma + 1;
 33              }
 34              while (comma != std::string_view::npos);
 35          }
 36          return idents;
 37      }
 38  
 39  	Identity& Identity::operator=(const Keys& keys)
 40  	{
 41  		// copy public and signing keys together
 42  		memcpy (publicKey, keys.publicKey, sizeof (publicKey));
 43  		memcpy (signingKey, keys.signingKey, sizeof (signingKey));
 44  		memset (certificate, 0, sizeof (certificate));
 45  		return *this;
 46  	}
 47  
 48  	size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
 49  	{
 50  		if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
 51  		memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
 52  		return DEFAULT_IDENTITY_SIZE;
 53  	}
 54  
 55  	IdentHash Identity::Hash () const
 56  	{
 57  		IdentHash hash;
 58  		SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
 59  		return hash;
 60  	}
 61  
 62  	IdentityEx::IdentityEx ():
 63  		m_ExtendedLen (0)
 64  	{
 65  	}
 66  
 67  	IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
 68  	{
 69  		uint8_t randomPaddingBlock[32];
 70  		RAND_bytes (randomPaddingBlock, 32);
 71  		if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
 72  		{
 73  			memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32);
 74  			for (int i = 0; i < 7; i++) // 224 bytes
 75  				memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32);
 76  		}
 77  		else
 78  		{
 79  			if (publicKey)
 80  				memcpy (m_StandardIdentity.publicKey, publicKey, 256);
 81  			else
 82  				for (int i = 0; i < 8; i++) // 256 bytes
 83  					memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32);
 84  		}
 85  		if (type != SIGNING_KEY_TYPE_DSA_SHA1)
 86  		{
 87  			size_t excessLen = 0;
 88  			uint8_t * excessBuf = nullptr;
 89  			switch (type)
 90  			{
 91  				case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
 92  				{
 93  					size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
 94  					RAND_bytes (m_StandardIdentity.signingKey, padding);
 95  					memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
 96  					break;
 97  				}
 98  				case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
 99  				{
100  					size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96
101  					RAND_bytes (m_StandardIdentity.signingKey, padding);
102  					memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP384_KEY_LENGTH);
103  					break;
104  				}
105  				case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
106  				{
107  					memcpy (m_StandardIdentity.signingKey, signingKey, 128);
108  					excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132 - 128
109  					excessBuf = new uint8_t[excessLen];
110  					memcpy (excessBuf, signingKey + 128, excessLen);
111  					break;
112  				}
113  				case SIGNING_KEY_TYPE_RSA_SHA256_2048:
114  				case SIGNING_KEY_TYPE_RSA_SHA384_3072:
115  				case SIGNING_KEY_TYPE_RSA_SHA512_4096:
116  					LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
117  				break;
118  				case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
119  				case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
120  				{
121  					size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
122  					for (int i = 0; i < 3; i++) // 96 bytes
123  						memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32);
124  					memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
125  					break;
126  				}
127  				case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
128  				{
129  					// 256
130  					size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64
131  					RAND_bytes (m_StandardIdentity.signingKey, padding);
132  					memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH);
133  					break;
134  				}
135  				case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
136  				{
137  					// 512
138  					// no padding, key length is 128
139  					memcpy (m_StandardIdentity.signingKey, signingKey, i2p::crypto::GOSTR3410_512_PUBLIC_KEY_LENGTH);
140  					break;
141  				}
142  #if OPENSSL_PQ
143  				case SIGNING_KEY_TYPE_MLDSA44:
144  				{
145  					memcpy (m_StandardIdentity, signingKey, 384);
146  					excessLen = i2p::crypto::MLDSA44_PUBLIC_KEY_LENGTH - 384;
147  					excessBuf = new uint8_t[excessLen];
148  					memcpy (excessBuf, signingKey + 384, excessLen);
149  					cryptoType = 0xFF; // crypto key is not used
150  					break;
151  				}
152  #endif
153  				default:
154  					LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported");
155  			}
156  			m_ExtendedLen = 4 + excessLen; // 4 bytes extra + excess length
157  			// fill certificate
158  			m_StandardIdentity.certificate[0] = CERTIFICATE_TYPE_KEY;
159  			htobe16buf (m_StandardIdentity.certificate + 1, m_ExtendedLen);
160  			// fill extended buffer
161  			htobe16buf (m_ExtendedBuffer, type);
162  			htobe16buf (m_ExtendedBuffer + 2, cryptoType);
163  			if (excessLen && excessBuf)
164  			{
165  				if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE)
166  				{
167  					auto newBuf = new uint8_t[m_ExtendedLen];
168  					memcpy (newBuf, m_ExtendedBuffer, 4);
169  					memcpy (newBuf + 4, excessBuf, excessLen);
170  					m_ExtendedBufferPtr = newBuf;
171  				}
172  				else
173  					memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen);
174  				delete[] excessBuf;
175  			}
176  			// calculate ident hash
177  			RecalculateIdentHash();
178  		}
179  		else // DSA-SHA1
180  		{
181  			memcpy (m_StandardIdentity.signingKey, signingKey, sizeof (m_StandardIdentity.signingKey));
182  			memset (m_StandardIdentity.certificate, 0, sizeof (m_StandardIdentity.certificate));
183  			m_IdentHash = m_StandardIdentity.Hash ();
184  			m_ExtendedLen = 0;
185  		}
186  		CreateVerifier ();
187  	}
188  
189  	void IdentityEx::RecalculateIdentHash(uint8_t * buf)
190  	{
191  		bool dofree = buf == nullptr;
192  		size_t sz = GetFullLen();
193  		if(!buf)
194  			buf = new uint8_t[sz];
195  		ToBuffer (buf, sz);
196  		SHA256(buf, sz, m_IdentHash);
197  		if(dofree)
198  			delete[] buf;
199  	}
200  
201  	IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
202  		m_ExtendedLen (0)
203  	{
204  		FromBuffer (buf, len);
205  	}
206  
207  	IdentityEx::IdentityEx (const IdentityEx& other):
208  		m_ExtendedLen (0)
209  	{
210  		*this = other;
211  	}
212  
213  	IdentityEx::IdentityEx (const Identity& standard):
214  		m_ExtendedLen (0)
215  	{
216  		*this = standard;
217  	}
218  
219  	IdentityEx::~IdentityEx ()
220  	{
221  		if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE)
222  			delete[] m_ExtendedBufferPtr;
223  	}
224  
225  	IdentityEx& IdentityEx::operator=(const IdentityEx& other)
226  	{
227  		memcpy (&m_StandardIdentity, &other.m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
228  		m_IdentHash = other.m_IdentHash;
229  
230  		size_t oldLen = m_ExtendedLen;
231  		m_ExtendedLen = other.m_ExtendedLen;
232  		if (m_ExtendedLen > 0)
233  		{
234  			if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE)
235  			{
236  				if (oldLen > MAX_EXTENDED_BUFFER_SIZE)
237  				{
238  					if (m_ExtendedLen > oldLen)
239  					{
240  						delete[] m_ExtendedBufferPtr;
241  						m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen];
242  					}
243  				}
244  				else
245  					m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen];
246  				memcpy (m_ExtendedBufferPtr, other.m_ExtendedBufferPtr, m_ExtendedLen);
247  			}
248  			else
249  			{
250  				if (oldLen > MAX_EXTENDED_BUFFER_SIZE) delete[] m_ExtendedBufferPtr;
251  				memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen);
252  			}
253  		}
254  		m_Verifier = nullptr;
255  		CreateVerifier ();
256  
257  		return *this;
258  	}
259  
260  	IdentityEx& IdentityEx::operator=(const Identity& standard)
261  	{
262  		m_StandardIdentity = standard;
263  		m_IdentHash = m_StandardIdentity.Hash ();
264  		m_ExtendedLen = 0;
265  
266  		m_Verifier = nullptr;
267  		CreateVerifier ();
268  
269  		return *this;
270  	}
271  
272  	size_t IdentityEx::FromBuffer (const uint8_t * buf, size_t len)
273  	{
274  		if (len < DEFAULT_IDENTITY_SIZE)
275  		{
276  			LogPrint (eLogError, "Identity: Buffer length ", len, " is too small");
277  			return 0;
278  		}
279  		memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
280  
281  		size_t oldLen = m_ExtendedLen;
282  		m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1);
283  		if (m_ExtendedLen)
284  		{
285  			if (m_ExtendedLen + DEFAULT_IDENTITY_SIZE <= len)
286  			{
287  				if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE)
288  				{
289  					if (oldLen > MAX_EXTENDED_BUFFER_SIZE)
290  					{
291  						if (m_ExtendedLen > oldLen)
292  						{
293  							delete[] m_ExtendedBufferPtr;
294  							m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen];
295  						}
296  					}
297  					else
298  						m_ExtendedBufferPtr = new uint8_t[m_ExtendedLen];
299  					memcpy (m_ExtendedBufferPtr, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen);
300  				}
301  				else
302  					memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen);
303  			}
304  			else
305  			{
306  				LogPrint (eLogError, "Identity: Certificate length ", m_ExtendedLen, " exceeds buffer length ", len - DEFAULT_IDENTITY_SIZE);
307  				m_ExtendedLen = 0;
308  				return 0;
309  			}
310  		}
311  		else
312  			m_ExtendedLen = 0;
313  		SHA256(buf, GetFullLen (), m_IdentHash);
314  
315  		m_Verifier = nullptr;
316  		CreateVerifier ();
317  
318  		return GetFullLen ();
319  	}
320  
321  	size_t IdentityEx::ToBuffer (uint8_t * buf, size_t len) const
322  	{
323  		const size_t fullLen = GetFullLen();
324  		if (fullLen > len) return 0; // buffer is too small and may overflow somewhere else
325  		memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
326  		if (m_ExtendedLen > 0)
327  		{
328  			if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE)
329  				memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBufferPtr, m_ExtendedLen);
330  			else
331  				memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen);
332  		}
333  		return fullLen;
334  	}
335  
336  	size_t IdentityEx::FromBase64(std::string_view s)
337  	{
338  		std::vector<uint8_t> buf(s.length ()); // binary data can't exceed base64
339  		auto len = Base64ToByteStream (s, buf.data(), buf.size ());
340  		return FromBuffer (buf.data(), len);
341  	}
342  
343  	std::string IdentityEx::ToBase64 () const
344  	{
345  		const size_t bufLen = GetFullLen();
346  		std::vector<uint8_t> buf(bufLen);
347  		size_t l = ToBuffer (buf.data(), bufLen);
348  		return i2p::data::ByteStreamToBase64 (buf.data(), l);
349  	}
350  
351  	size_t IdentityEx::GetSigningPublicKeyLen () const
352  	{
353  		if (m_Verifier)
354  			return m_Verifier->GetPublicKeyLen ();
355  		return 128;
356  	}
357  
358  	const uint8_t * IdentityEx::GetSigningPublicKeyBuffer () const
359  	{
360  		auto keyLen = GetSigningPublicKeyLen ();
361  		if (keyLen > 128) return nullptr; // P521 or PQ
362  		return m_StandardIdentity.signingKey + 128 - keyLen;
363  	}
364  
365  	size_t IdentityEx::GetSigningPrivateKeyLen () const
366  	{
367  		if (m_Verifier)
368  			return m_Verifier->GetPrivateKeyLen ();
369  		return GetSignatureLen ()/2;
370  	}
371  
372  	size_t IdentityEx::GetSignatureLen () const
373  	{
374  		if (m_Verifier)
375  			return m_Verifier->GetSignatureLen ();
376  		return i2p::crypto::DSA_SIGNATURE_LENGTH;
377  	}
378  	bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
379  	{
380  		if (m_Verifier)
381  			return m_Verifier->Verify (buf, len, signature);
382  		return false;
383  	}
384  
385  	SigningKeyType IdentityEx::GetSigningKeyType () const
386  	{
387  		if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 2)
388  			return bufbe16toh (m_ExtendedLen <= MAX_EXTENDED_BUFFER_SIZE ? m_ExtendedBuffer : m_ExtendedBufferPtr); // signing key
389  		return SIGNING_KEY_TYPE_DSA_SHA1;
390  	}
391  
392  	bool IdentityEx::IsRSA () const
393  	{
394  		auto sigType = GetSigningKeyType ();
395  		return sigType <= SIGNING_KEY_TYPE_RSA_SHA512_4096 && sigType >= SIGNING_KEY_TYPE_RSA_SHA256_2048;
396  	}
397  
398  	CryptoKeyType IdentityEx::GetCryptoKeyType () const
399  	{
400  		if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4)
401  			return bufbe16toh (m_ExtendedLen <= MAX_EXTENDED_BUFFER_SIZE ? m_ExtendedBuffer + 2 : m_ExtendedBufferPtr + 2); // crypto key
402  		return CRYPTO_KEY_TYPE_ELGAMAL;
403  	}
404  
405  	i2p::crypto::Verifier * IdentityEx::CreateVerifier (SigningKeyType keyType)
406  	{
407  		switch (keyType)
408  		{
409  			case SIGNING_KEY_TYPE_DSA_SHA1:
410  				return new i2p::crypto::DSAVerifier ();
411  			case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
412  				return new i2p::crypto::ECDSAP256Verifier ();
413  			case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
414  				return new i2p::crypto::ECDSAP384Verifier ();
415  			case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
416  				return new i2p::crypto::ECDSAP521Verifier ();
417  			case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
418  				return new i2p::crypto::EDDSA25519Verifier ();
419  			case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
420  				return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA);
421  			case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
422  				return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512);
423  			case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
424  				return new i2p::crypto::RedDSA25519Verifier ();
425  #if OPENSSL_PQ
426  			case SIGNING_KEY_TYPE_MLDSA44:
427  				return new i2p::crypto::MLDSA44Verifier ();
428  #endif
429  			case SIGNING_KEY_TYPE_RSA_SHA256_2048:
430  			case SIGNING_KEY_TYPE_RSA_SHA384_3072:
431  			case SIGNING_KEY_TYPE_RSA_SHA512_4096:
432  				LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported");
433  			break;
434  			default:
435  				LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
436  		}
437  		return nullptr;
438  	}
439  
440  	void IdentityEx::CreateVerifier ()
441  	{
442  		if (!m_Verifier)
443  		{
444  			auto verifier = CreateVerifier (GetSigningKeyType ());
445  			if (verifier)
446  			{
447  				auto keyLen = verifier->GetPublicKeyLen ();
448  				if (keyLen <= 128)
449  					verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen);
450  #if OPENSSL_PQ
451  				else if (keyLen > 384)
452  				{
453  					// for post-quantum
454  					uint8_t * signingKey = new uint8_t[keyLen];
455  					memcpy (signingKey, m_StandardIdentity, 384);
456  					size_t excessLen = keyLen - 384;
457  					memcpy (signingKey + 384, m_ExtendedBufferPtr + 4, excessLen); // right after signing and crypto key types
458  					verifier->SetPublicKey (signingKey);
459  					delete[] signingKey;
460  				}
461  #endif
462  				else
463  				{
464  					// for P521
465  					uint8_t * signingKey = new uint8_t[keyLen];
466  					memcpy (signingKey, m_StandardIdentity.signingKey, 128);
467  					size_t excessLen = keyLen - 128;
468  					memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
469  					verifier->SetPublicKey (signingKey);
470  					delete[] signingKey;
471  				}
472  			}
473  			m_Verifier.reset (verifier);
474  		}
475  	}
476  
477  	std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key)
478  	{
479  		switch (keyType)
480  		{
481  			case CRYPTO_KEY_TYPE_ELGAMAL:
482  				return std::make_shared<i2p::crypto::ElGamalEncryptor>(key);
483  			break;
484  			case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
485  			case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
486  			case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
487  			case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
488  				return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetEncryptor>(key);
489  			break;
490  			case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
491  				return std::make_shared<i2p::crypto::ECIESP256Encryptor>(key);
492  			break;
493  			default:
494  				LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType);
495  		};
496  		return nullptr;
497  	}
498  
499  	std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (const uint8_t * key) const
500  	{
501  		if (!key) key = GetEncryptionPublicKey (); // use publicKey
502  		return CreateEncryptor (GetCryptoKeyType (), key);
503  	}
504  
505  	size_t GetIdentityBufferLen (const uint8_t * buf, size_t len)
506  	{
507  		if (len < DEFAULT_IDENTITY_SIZE) return 0;
508  		size_t l = DEFAULT_IDENTITY_SIZE + bufbe16toh (buf + DEFAULT_IDENTITY_SIZE - 2);
509  		if (l > len) return 0;
510  		return l;
511  	}
512  
513  	PrivateKeys& PrivateKeys::operator=(const Keys& keys)
514  	{
515  		m_Public = std::make_shared<IdentityEx>(Identity (keys));
516  		memcpy (m_PrivateKey, keys.privateKey, 256); // 256
517  		size_t keyLen = m_Public->GetSigningPrivateKeyLen ();
518  		m_SigningPrivateKey.resize (keyLen);
519  		memcpy (m_SigningPrivateKey.data (), keys.signingPrivateKey, keyLen);
520  		m_OfflineSignature.resize (0);
521  		m_TransientSignatureLen = 0;
522  		m_TransientSigningPrivateKeyLen = 0;
523  		m_Signer = nullptr;
524  		CreateSigner ();
525  		return *this;
526  	}
527  
528  	PrivateKeys& PrivateKeys::operator=(const PrivateKeys& other)
529  	{
530  		m_Public = std::make_shared<IdentityEx>(*other.m_Public);
531  		memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256
532  		m_OfflineSignature = other.m_OfflineSignature;
533  		m_TransientSignatureLen = other.m_TransientSignatureLen;
534  		m_TransientSigningPrivateKeyLen = other.m_TransientSigningPrivateKeyLen;
535  		m_SigningPrivateKey = other.m_SigningPrivateKey;
536  		m_Signer = nullptr;
537  		CreateSigner ();
538  		return *this;
539  	}
540  
541  	size_t PrivateKeys::GetFullLen () const
542  	{
543  		size_t ret = m_Public->GetFullLen () + GetPrivateKeyLen () + m_Public->GetSigningPrivateKeyLen ();
544  		if (IsOfflineSignature ())
545  			ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen;
546  		return ret;
547  	}
548  
549  	size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len)
550  	{
551  		m_Public = std::make_shared<IdentityEx>();
552  		size_t ret = m_Public->FromBuffer (buf, len);
553  		auto cryptoKeyLen = GetPrivateKeyLen ();
554  		if (!ret || ret + cryptoKeyLen > len) return 0; // overflow
555  		memcpy (m_PrivateKey, buf + ret, cryptoKeyLen);
556  		ret += cryptoKeyLen;
557  		size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
558  		if (signingPrivateKeySize + ret > len) return 0; // overflow
559  		m_SigningPrivateKey.resize (signingPrivateKeySize);
560  		memcpy (m_SigningPrivateKey.data (), buf + ret, signingPrivateKeySize);
561  		ret += signingPrivateKeySize;
562  		m_Signer = nullptr;
563  		// check if signing private key is all zeros
564  		bool allzeros = true;
565  		for (size_t i = 0; i < signingPrivateKeySize; i++)
566  			if (m_SigningPrivateKey[i])
567  			{
568  				allzeros = false;
569  				break;
570  			}
571  		if (allzeros)
572  		{
573  			// offline information
574  			const uint8_t * offlineInfo = buf + ret;
575  			uint32_t expires = bufbe32toh (buf + ret); ret += 4; // expires timestamp
576  			if (expires < i2p::util::GetSecondsSinceEpoch ())
577  			{
578  				LogPrint (eLogError, "Identity: Offline signature expired");
579  				return 0;
580  			}
581  			SigningKeyType keyType = bufbe16toh (buf + ret); ret += 2; // key type
582  			std::unique_ptr<i2p::crypto::Verifier> transientVerifier (IdentityEx::CreateVerifier (keyType));
583  			if (!transientVerifier) return 0;
584  			auto keyLen = transientVerifier->GetPublicKeyLen ();
585  			if (keyLen + ret > len) return 0;
586  			transientVerifier->SetPublicKey (buf + ret); ret += keyLen;
587  			if (m_Public->GetSignatureLen () + ret > len) return 0;
588  			if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
589  			{
590  				LogPrint (eLogError, "Identity: Offline signature verification failed");
591  				return 0;
592  			}
593  			ret += m_Public->GetSignatureLen ();
594  			m_TransientSignatureLen = transientVerifier->GetSignatureLen ();
595  			// copy offline signature
596  			size_t offlineInfoLen = buf + ret - offlineInfo;
597  			m_OfflineSignature.resize (offlineInfoLen);
598  			memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen);
599  			// override signing private key
600  			m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen ();
601  			if (m_TransientSigningPrivateKeyLen + ret > len) return 0;
602  			if (m_TransientSigningPrivateKeyLen > 128) m_SigningPrivateKey.resize (m_TransientSigningPrivateKeyLen);
603  			memcpy (m_SigningPrivateKey.data (), buf + ret, m_TransientSigningPrivateKeyLen);
604  			ret += m_TransientSigningPrivateKeyLen;
605  			CreateSigner (keyType);
606  		}
607  		else
608  			CreateSigner (m_Public->GetSigningKeyType ());
609  		return ret;
610  	}
611  
612  	size_t PrivateKeys::ToBuffer (uint8_t * buf, size_t len) const
613  	{
614  		size_t ret = m_Public->ToBuffer (buf, len);
615  		auto cryptoKeyLen = GetPrivateKeyLen ();
616  		memcpy (buf + ret, m_PrivateKey, cryptoKeyLen);
617  		ret += cryptoKeyLen;
618  		size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
619  		if(ret + signingPrivateKeySize > len) return 0; // overflow
620  		if (IsOfflineSignature ())
621  			memset (buf + ret, 0, signingPrivateKeySize);
622  		else
623  			memcpy (buf + ret, m_SigningPrivateKey.data (), signingPrivateKeySize);
624  		ret += signingPrivateKeySize;
625  		if (IsOfflineSignature ())
626  		{
627  			// offline signature
628  			auto offlineSignatureLen = m_OfflineSignature.size ();
629  			if (ret + offlineSignatureLen > len) return 0;
630  			memcpy (buf + ret, m_OfflineSignature.data (), offlineSignatureLen);
631  			ret += offlineSignatureLen;
632  			// transient private key
633  			if (ret + m_TransientSigningPrivateKeyLen > len) return 0;
634  			memcpy (buf + ret, m_SigningPrivateKey.data (), m_TransientSigningPrivateKeyLen);
635  			ret += m_TransientSigningPrivateKeyLen;
636  		}
637  		return ret;
638  	}
639  
640  	size_t PrivateKeys::FromBase64(std::string_view s)
641  	{
642  		std::vector<uint8_t> buf(s.length ());
643  		size_t l = i2p::data::Base64ToByteStream (s, buf.data (), buf.size ());
644  		return FromBuffer (buf.data (), l);
645  	}
646  
647  	std::string PrivateKeys::ToBase64 () const
648  	{
649  		std::vector<uint8_t> buf(GetFullLen ());
650  		size_t l = ToBuffer (buf.data (), buf.size ());
651  		return i2p::data::ByteStreamToBase64 (buf.data (), l);
652  	}
653  
654  	void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const
655  	{
656  		if (!m_Signer)
657  			CreateSigner();
658  		m_Signer->Sign (buf, len, signature);
659  	}
660  
661  	void PrivateKeys::CreateSigner () const
662  	{
663  		if (IsOfflineSignature ())
664  			CreateSigner (bufbe16toh (m_OfflineSignature.data () + 4)); // key type
665  		else
666  			CreateSigner (m_Public->GetSigningKeyType ());
667  	}
668  
669  	void PrivateKeys::CreateSigner (SigningKeyType keyType) const
670  	{
671  		if (m_Signer) return;
672  		if (keyType == SIGNING_KEY_TYPE_DSA_SHA1)
673  			m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey.data (), m_Public->GetStandardIdentity ().signingKey));
674  		else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ())
675  			m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey.data (), m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check
676  		else
677  		{
678  			// public key is not required
679  			auto signer = CreateSigner (keyType, m_SigningPrivateKey.data ());
680  			if (signer) m_Signer.reset (signer);
681  		}
682  	}
683  
684  	i2p::crypto::Signer * PrivateKeys::CreateSigner (SigningKeyType keyType, const uint8_t * priv)
685  	{
686  		switch (keyType)
687  		{
688  			case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
689  				return new i2p::crypto::ECDSAP256Signer (priv);
690  			break;
691  			case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
692  				return new i2p::crypto::ECDSAP384Signer (priv);
693  			break;
694  			case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
695  				return new i2p::crypto::ECDSAP521Signer (priv);
696  			break;
697  			case SIGNING_KEY_TYPE_RSA_SHA256_2048:
698  			case SIGNING_KEY_TYPE_RSA_SHA384_3072:
699  			case SIGNING_KEY_TYPE_RSA_SHA512_4096:
700  				LogPrint (eLogError, "Identity: RSA signing key type ", (int)keyType, " is not supported");
701  			break;
702  			case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
703  				return new i2p::crypto::EDDSA25519Signer (priv, nullptr);
704  			break;
705  			case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
706  				return new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, priv);
707  			break;
708  			case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
709  				return new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, priv);
710  			break;
711  			case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
712  				return new i2p::crypto::RedDSA25519Signer (priv);
713  			break;
714  #if OPENSSL_PQ
715  			case SIGNING_KEY_TYPE_MLDSA44:
716  				return new i2p::crypto::MLDSA44Signer (priv);
717  			break;
718  #endif
719  			default:
720  				LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
721  		}
722  		return nullptr;
723  	}
724  
725  	size_t PrivateKeys::GetSignatureLen () const
726  	{
727  		return IsOfflineSignature () ? m_TransientSignatureLen : m_Public->GetSignatureLen ();
728  	}
729  
730  	size_t PrivateKeys::GetPrivateKeyLen () const
731  	{
732  		return i2p::crypto::GetCryptoPrivateKeyLen (m_Public->GetCryptoKeyType ());
733  	}
734  
735  	uint8_t * PrivateKeys::GetPadding()
736  	{
737  		if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
738  			return m_Public->GetEncryptionPublicKeyBuffer() + 256;
739  		else
740  			return nullptr; // TODO: implement me
741  	}
742  
743  	std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> PrivateKeys::CreateDecryptor (const uint8_t * key) const
744  	{
745  		if (!key) key = m_PrivateKey; // use privateKey
746  		return CreateDecryptor (m_Public->GetCryptoKeyType (), key);
747  	}
748  
749  	std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> PrivateKeys::CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key)
750  	{
751  		if (!key) return nullptr;
752  		switch (cryptoType)
753  		{
754  			case CRYPTO_KEY_TYPE_ELGAMAL:
755  				return std::make_shared<i2p::crypto::ElGamalDecryptor>(key);
756  			break;
757  			case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
758  			case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
759  			case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
760  			case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
761  				return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key);
762  			break;
763  			case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
764  				return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key);
765  			break;
766  			default:
767  				LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType);
768  		};
769  		return nullptr;
770  	}
771  
772  	PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType, bool isDestination)
773  	{
774  		if (type != SIGNING_KEY_TYPE_DSA_SHA1)
775  		{
776  			PrivateKeys keys;
777  			// signature
778  			std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type));
779  			std::vector<uint8_t> signingPublicKey(verifier->GetPublicKeyLen ());
780  			keys.m_SigningPrivateKey.resize (verifier->GetPrivateKeyLen ());
781  			GenerateSigningKeyPair (type, keys.m_SigningPrivateKey.data (), signingPublicKey.data ());
782  			// encryption
783  			uint8_t publicKey[256];
784  			if (isDestination)
785  				RAND_bytes (keys.m_PrivateKey, 256);
786  			else
787  				GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
788  			// identity
789  			keys.m_Public = std::make_shared<IdentityEx> (isDestination ? nullptr : publicKey, signingPublicKey.data (), type, cryptoType);
790  
791  			keys.CreateSigner ();
792  			return keys;
793  		}
794  		return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
795  	}
796  
797  	void PrivateKeys::GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub)
798  	{
799  		switch (type)
800  		{
801  			case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
802  				i2p::crypto::CreateECDSAP256RandomKeys (priv, pub);
803  			break;
804  			case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
805  				i2p::crypto::CreateECDSAP384RandomKeys (priv, pub);
806  			break;
807  			case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
808  				i2p::crypto::CreateECDSAP521RandomKeys (priv, pub);
809  			break;
810  			case SIGNING_KEY_TYPE_RSA_SHA256_2048:
811  			case SIGNING_KEY_TYPE_RSA_SHA384_3072:
812  			case SIGNING_KEY_TYPE_RSA_SHA512_4096:
813  				LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
814  				[[fallthrough]];
815  				// no break here
816  			case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
817  				i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
818  			break;
819  			case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
820  				i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, priv, pub);
821  			break;
822  			case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
823  				i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub);
824  			break;
825  			case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
826  				i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub);
827  			break;
828  #if OPENSSL_PQ
829  			case SIGNING_KEY_TYPE_MLDSA44:
830  				i2p::crypto::CreateMLDSA44RandomKeys (priv, pub);
831  			break;
832  #endif
833  			default:
834  				LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
835  				i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
836  		}
837  	}
838  
839  	void PrivateKeys::GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub)
840  	{
841  		switch (type)
842  		{
843  			case CRYPTO_KEY_TYPE_ELGAMAL:
844  				i2p::crypto::GenerateElGamalKeyPair(priv, pub);
845  			break;
846  			case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
847  				i2p::crypto::CreateECIESP256RandomKeys (priv, pub);
848  			break;
849  			case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
850  			case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
851  			case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
852  			case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
853  				i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub);
854  			break;
855  			default:
856  				LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported");
857  		}
858  	}
859  
860  	PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const
861  	{
862  		PrivateKeys keys (*this);
863  		std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type));
864  		if (verifier)
865  		{
866  			size_t pubKeyLen = verifier->GetPublicKeyLen ();
867  			keys.m_TransientSigningPrivateKeyLen = verifier->GetPrivateKeyLen ();
868  			keys.m_TransientSignatureLen = verifier->GetSignatureLen ();
869  			keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
870  			keys.m_SigningPrivateKey.resize (verifier->GetPrivateKeyLen ());
871  			htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
872  			htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
873  			GenerateSigningKeyPair (type, keys.m_SigningPrivateKey.data (), keys.m_OfflineSignature.data () + 6); // public key
874  			Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
875  			// recreate signer
876  			keys.m_Signer = nullptr;
877  			keys.CreateSigner (type);
878  		}
879  		return keys;
880  	}
881  
882  	Keys CreateRandomKeys ()
883  	{
884  		Keys keys;
885  		// encryption
886  		i2p::crypto::GenerateElGamalKeyPair(keys.privateKey, keys.publicKey);
887  		// signing
888  		i2p::crypto::CreateDSARandomKeys (keys.signingPrivateKey, keys.signingKey);
889  		return keys;
890  	}
891  
892  	IdentHash CreateRoutingKey (const IdentHash& ident, bool nextDay)
893  	{
894  		uint8_t buf[41]; // ident + yyyymmdd
895  		memcpy (buf, (const uint8_t *)ident, 32);
896  		if (nextDay)
897  			i2p::util::GetNextDayDate ((char *)(buf + 32));
898  		else
899  			i2p::util::GetCurrentDate ((char *)(buf + 32));
900  		IdentHash key;
901  		SHA256(buf, 40, key);
902  		return key;
903  	}
904  
905  	XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
906  	{
907  		XORMetric m;
908  
909  		const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
910  		m.metric_ll[0] = hash1[0] ^ hash2[0];
911  		m.metric_ll[1] = hash1[1] ^ hash2[1];
912  		m.metric_ll[2] = hash1[2] ^ hash2[2];
913  		m.metric_ll[3] = hash1[3] ^ hash2[3];
914  
915  		return m;
916  	}
917  }
918  }