mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30:46 +00:00 
			
		
		
		
	create offline keys
This commit is contained in:
		
							parent
							
								
									1fa3ba8b42
								
							
						
					
					
						commit
						1eb726c9bb
					
				
					 2 changed files with 98 additions and 38 deletions
				
			
		| 
						 | 
				
			
			@ -432,6 +432,9 @@ namespace data
 | 
			
		|||
		m_Public = std::make_shared<IdentityEx>(Identity (keys));
 | 
			
		||||
		memcpy (m_PrivateKey, keys.privateKey, 256); // 256
 | 
			
		||||
		memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ());
 | 
			
		||||
		m_OfflineSignature.resize (0);
 | 
			
		||||
		m_TransientSignatureLen = 0;
 | 
			
		||||
		m_TransientSigningPrivateKeyLen = 0;
 | 
			
		||||
		m_Signer = nullptr;
 | 
			
		||||
		CreateSigner ();
 | 
			
		||||
		return *this;
 | 
			
		||||
| 
						 | 
				
			
			@ -442,11 +445,22 @@ namespace data
 | 
			
		|||
		m_Public = std::make_shared<IdentityEx>(*other.m_Public);
 | 
			
		||||
		memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256
 | 
			
		||||
		memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_Public->GetSigningPrivateKeyLen ());
 | 
			
		||||
		m_OfflineSignature = other.m_OfflineSignature;
 | 
			
		||||
		m_TransientSignatureLen = other.m_TransientSignatureLen;
 | 
			
		||||
		m_TransientSigningPrivateKeyLen = other.m_TransientSigningPrivateKeyLen;
 | 
			
		||||
		m_Signer = nullptr;
 | 
			
		||||
		CreateSigner ();
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t PrivateKeys::GetFullLen () const 
 | 
			
		||||
	{ 
 | 
			
		||||
		size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); 
 | 
			
		||||
		if (IsOfflineSignature ())
 | 
			
		||||
			ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen;
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len)
 | 
			
		||||
	{
 | 
			
		||||
		m_Public = std::make_shared<IdentityEx>();
 | 
			
		||||
| 
						 | 
				
			
			@ -485,15 +499,16 @@ namespace data
 | 
			
		|||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			ret += m_Public->GetSignatureLen ();
 | 
			
		||||
			m_TransientSignatureLen = transientVerifier->GetSignatureLen ();
 | 
			
		||||
			// copy offline signature
 | 
			
		||||
			size_t offlineInfoLen = buf + ret - offlineInfo;
 | 
			
		||||
			m_OfflineSignature.resize (offlineInfoLen);
 | 
			
		||||
			memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen);
 | 
			
		||||
			// override signing private key 
 | 
			
		||||
			signingPrivateKeySize = transientVerifier->GetPrivateKeyLen ();
 | 
			
		||||
			if (signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0;
 | 
			
		||||
			memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize);
 | 
			
		||||
			ret += signingPrivateKeySize;
 | 
			
		||||
			m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen ();
 | 
			
		||||
			if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0;
 | 
			
		||||
			memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen);
 | 
			
		||||
			ret += m_TransientSigningPrivateKeyLen;
 | 
			
		||||
			CreateSigner (keyType);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -508,9 +523,23 @@ namespace data
 | 
			
		|||
		ret += 256;
 | 
			
		||||
		size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
 | 
			
		||||
		if(ret + signingPrivateKeySize > len) return 0; // overflow
 | 
			
		||||
		memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize);
 | 
			
		||||
		if (IsOfflineSignature ())
 | 
			
		||||
			memset (buf + ret, 0, signingPrivateKeySize);
 | 
			
		||||
		else
 | 
			
		||||
			memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize);
 | 
			
		||||
		ret += signingPrivateKeySize;
 | 
			
		||||
		// TODO: implement offline info
 | 
			
		||||
		if (IsOfflineSignature ())
 | 
			
		||||
		{
 | 
			
		||||
			// offline signature
 | 
			
		||||
			auto offlineSignatureLen = m_OfflineSignature.size ();
 | 
			
		||||
			if (ret + offlineSignatureLen > len) return 0;
 | 
			
		||||
			memcpy (buf + ret, m_OfflineSignature.data (), offlineSignatureLen);
 | 
			
		||||
			ret += offlineSignatureLen;
 | 
			
		||||
			// transient private key
 | 
			
		||||
			if (ret + m_TransientSigningPrivateKeyLen > len) return 0;
 | 
			
		||||
			memcpy (buf + ret, m_SigningPrivateKey, m_TransientSigningPrivateKeyLen);
 | 
			
		||||
			ret += m_TransientSigningPrivateKeyLen;
 | 
			
		||||
		}
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -589,7 +618,7 @@ namespace data
 | 
			
		|||
 | 
			
		||||
	size_t PrivateKeys::GetSignatureLen () const
 | 
			
		||||
	{
 | 
			
		||||
		return m_Public->GetSignatureLen ();
 | 
			
		||||
		return IsOfflineSignature () ? m_TransientSignatureLen : m_Public->GetSignatureLen ();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint8_t * PrivateKeys::GetPadding()
 | 
			
		||||
| 
						 | 
				
			
			@ -634,35 +663,7 @@ namespace data
 | 
			
		|||
			PrivateKeys keys;
 | 
			
		||||
			// signature
 | 
			
		||||
			uint8_t signingPublicKey[512]; // signing public key is 512 bytes max
 | 
			
		||||
			switch (type)
 | 
			
		||||
			{
 | 
			
		||||
				case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
 | 
			
		||||
					i2p::crypto::CreateECDSAP256RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
 | 
			
		||||
					i2p::crypto::CreateECDSAP384RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
 | 
			
		||||
					i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				case SIGNING_KEY_TYPE_RSA_SHA256_2048:
 | 
			
		||||
				case SIGNING_KEY_TYPE_RSA_SHA384_3072:
 | 
			
		||||
				case SIGNING_KEY_TYPE_RSA_SHA512_4096:
 | 
			
		||||
					LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
 | 
			
		||||
				// no break here
 | 
			
		||||
				case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
 | 
			
		||||
					i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
 | 
			
		||||
					i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
 | 
			
		||||
					i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
				break;
 | 
			
		||||
				default:
 | 
			
		||||
					LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
 | 
			
		||||
					return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
 | 
			
		||||
			}
 | 
			
		||||
			GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, signingPublicKey);
 | 
			
		||||
			// encryption
 | 
			
		||||
			uint8_t publicKey[256];
 | 
			
		||||
			GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
 | 
			
		||||
| 
						 | 
				
			
			@ -675,6 +676,39 @@ namespace data
 | 
			
		|||
		return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PrivateKeys::GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub)
 | 
			
		||||
	{
 | 
			
		||||
		switch (type)
 | 
			
		||||
		{
 | 
			
		||||
			case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
 | 
			
		||||
				i2p::crypto::CreateECDSAP256RandomKeys (priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			case SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
 | 
			
		||||
				i2p::crypto::CreateECDSAP384RandomKeys (priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
 | 
			
		||||
				i2p::crypto::CreateECDSAP521RandomKeys (priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			case SIGNING_KEY_TYPE_RSA_SHA256_2048:
 | 
			
		||||
			case SIGNING_KEY_TYPE_RSA_SHA384_3072:
 | 
			
		||||
			case SIGNING_KEY_TYPE_RSA_SHA512_4096:
 | 
			
		||||
				LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
 | 
			
		||||
			// no break here
 | 
			
		||||
			case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
 | 
			
		||||
				i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
 | 
			
		||||
				i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
 | 
			
		||||
				i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub);
 | 
			
		||||
			break;
 | 
			
		||||
			default:
 | 
			
		||||
				LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
 | 
			
		||||
				i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PrivateKeys::GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub)
 | 
			
		||||
	{
 | 
			
		||||
		switch (type)
 | 
			
		||||
| 
						 | 
				
			
			@ -694,6 +728,27 @@ namespace data
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const
 | 
			
		||||
	{
 | 
			
		||||
		PrivateKeys keys (*this);
 | 
			
		||||
		std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type));		
 | 
			
		||||
		if (verifier)
 | 
			
		||||
		{
 | 
			
		||||
			size_t pubKeyLen = verifier->GetPublicKeyLen ();
 | 
			
		||||
			keys.m_TransientSigningPrivateKeyLen = verifier->GetPrivateKeyLen ();
 | 
			
		||||
			keys.m_TransientSignatureLen = verifier->GetSignatureLen ();
 | 
			
		||||
			keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
 | 
			
		||||
			htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
 | 
			
		||||
			htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
 | 
			
		||||
			GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 4); // public  key
 | 
			
		||||
			Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6); // signature	
 | 
			
		||||
			// recreate signer
 | 
			
		||||
			keys.m_Signer = nullptr;
 | 
			
		||||
			keys.CreateSigner ();	
 | 
			
		||||
		}
 | 
			
		||||
		return keys;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Keys CreateRandomKeys ()
 | 
			
		||||
	{
 | 
			
		||||
		Keys keys;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,12 +144,12 @@ namespace data
 | 
			
		|||
			const uint8_t * GetPrivateKey () const { return m_PrivateKey; };
 | 
			
		||||
			const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
 | 
			
		||||
			size_t GetSignatureLen () const; // might not match identity
 | 
			
		||||
			bool IsOfflineSignature () const { return m_OfflineSignature.size () > 0; };
 | 
			
		||||
			bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; };
 | 
			
		||||
    		uint8_t * GetPadding();
 | 
			
		||||
			void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
 | 
			
		||||
			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
 | 
			
		||||
 | 
			
		||||
			size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); };
 | 
			
		||||
			size_t GetFullLen () const;
 | 
			
		||||
			size_t FromBuffer (const uint8_t * buf, size_t len);
 | 
			
		||||
			size_t ToBuffer (uint8_t * buf, size_t len) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -160,8 +160,11 @@ namespace data
 | 
			
		|||
 | 
			
		||||
			static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
 | 
			
		||||
			static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
 | 
			
		||||
			static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub); 
 | 
			
		||||
			static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
 | 
			
		||||
 | 
			
		||||
			PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const; 
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
 | 
			
		||||
			void CreateSigner () const;
 | 
			
		||||
| 
						 | 
				
			
			@ -174,6 +177,8 @@ namespace data
 | 
			
		|||
			uint8_t m_SigningPrivateKey[128]; // assume private key doesn't exceed 128 bytes
 | 
			
		||||
			mutable std::unique_ptr<i2p::crypto::Signer> m_Signer;
 | 
			
		||||
			std::vector<uint8_t> m_OfflineSignature; // non zero length, if applicable
 | 
			
		||||
			size_t m_TransientSignatureLen = 0;
 | 
			
		||||
			size_t m_TransientSigningPrivateKeyLen = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// kademlia
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue