diff --git a/Identity.cpp b/Identity.cpp index e4787293..81be116b 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -42,15 +42,50 @@ namespace data IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type) { memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey)); - if (type == SIGNING_KEY_TYPE_ECDSA_SHA256_P256) + if (type != SIGNING_KEY_TYPE_DSA_SHA1) { + size_t excessLen = 0; + uint8_t * excessBuf = nullptr; + switch (type) + { + case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: + { + size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64 + memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH); + break; + } + case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: + { + size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96 + memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP384_KEY_LENGTH); + break; + } + case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: + { + memcpy (m_StandardIdentity.signingKey, signingKey, 128); + size_t excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132 - 128 + excessBuf = new uint8_t[excessLen]; + memcpy (excessBuf, signingKey + 128, excessLen); + break; + } + default: + LogPrint ("Signing key type ", (int)type, " is not supported"); + } memcpy (m_StandardIdentity.signingKey + 64, signingKey, 64); + // fill certificate m_StandardIdentity.certificate.type = CERTIFICATE_TYPE_KEY; - m_ExtendedLen = 4; // 4 bytes extra - m_StandardIdentity.certificate.length = htobe16 (4); + m_StandardIdentity.certificate.length = htobe16 (m_ExtendedLen); + // fill extended buffer + m_ExtendedLen = 4 + excessLen; // 4 bytes extra + excess length m_ExtendedBuffer = new uint8_t[m_ExtendedLen]; - *(uint16_t *)m_ExtendedBuffer = htobe16 (SIGNING_KEY_TYPE_ECDSA_SHA256_P256); + *(uint16_t *)m_ExtendedBuffer = htobe16 (type); *(uint16_t *)(m_ExtendedBuffer + 2) = htobe16 (CRYPTO_KEY_TYPE_ELGAMAL); + if (excessLen && excessBuf) + { + memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen); + delete[] excessBuf; + } + // calculate ident hash uint8_t buf[DEFAULT_IDENTITY_SIZE + 4]; ToBuffer (buf, DEFAULT_IDENTITY_SIZE + 4); CryptoPP::SHA256().CalculateDigest(m_IdentHash, buf, GetFullLen ()); @@ -188,6 +223,13 @@ namespace data return be16toh (*(const uint16_t *)m_ExtendedBuffer); // signing key return SIGNING_KEY_TYPE_DSA_SHA1; } + + CryptoKeyType IdentityEx::GetCryptoKeyType () const + { + if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer) + return be16toh (*(const uint16_t *)(m_ExtendedBuffer + 2)); // crypto key + return CRYPTO_KEY_TYPE_ELGAMAL; + } void IdentityEx::CreateVerifier () const { @@ -198,8 +240,26 @@ namespace data m_Verifier = new i2p::crypto::DSAVerifier (m_StandardIdentity.signingKey); break; case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: - m_Verifier = new i2p::crypto::ECDSAP256Verifier (m_StandardIdentity.signingKey + 64); - break; + { + size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64 + m_Verifier = new i2p::crypto::ECDSAP256Verifier (m_StandardIdentity.signingKey + padding); + break; + } + case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: + { + size_t padding = 128 - i2p::crypto::ECDSAP384_KEY_LENGTH; // 32 = 128 - 96 + m_Verifier = new i2p::crypto::ECDSAP384Verifier (m_StandardIdentity.signingKey + padding); + break; + } + case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: + { + uint8_t signingKey[i2p::crypto::ECDSAP521_KEY_LENGTH]; + memcpy (signingKey, m_StandardIdentity.signingKey, 128); + size_t excessLen = i2p::crypto::ECDSAP521_KEY_LENGTH - 128; // 4 = 132- 128 + memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types + m_Verifier = new i2p::crypto::ECDSAP521Verifier (signingKey); + break; + } default: LogPrint ("Signing key type ", (int)keyType, " is not supported"); } @@ -211,6 +271,7 @@ namespace data memcpy (m_PrivateKey, keys.privateKey, 256); // 256 memcpy (m_SigningPrivateKey, keys.signingPrivateKey, 20); // 20 - DSA delete m_Signer; + m_Signer = nullptr; CreateSigner (); return *this; } @@ -221,6 +282,7 @@ namespace data memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256 memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, 128); // 128 delete m_Signer; + m_Signer = nullptr; CreateSigner (); return *this; } @@ -234,6 +296,7 @@ namespace data memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); ret += signingPrivateKeySize; delete m_Signer; + m_Signer = nullptr; CreateSigner (); return ret; } @@ -257,27 +320,55 @@ namespace data void PrivateKeys::CreateSigner () { - if (m_Public.GetSigningKeyType () == SIGNING_KEY_TYPE_ECDSA_SHA256_P256) - m_Signer = new i2p::crypto::ECDSAP256Signer (m_SigningPrivateKey); - else - m_Signer = new i2p::crypto::DSASigner (m_SigningPrivateKey); + switch (m_Public.GetSigningKeyType ()) + { + case SIGNING_KEY_TYPE_DSA_SHA1: + m_Signer = new i2p::crypto::DSASigner (m_SigningPrivateKey); + break; + case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: + m_Signer = new i2p::crypto::ECDSAP256Signer (m_SigningPrivateKey); + break; + case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: + m_Signer = new i2p::crypto::ECDSAP384Signer (m_SigningPrivateKey); + break; + case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: + m_Signer = new i2p::crypto::ECDSAP521Signer (m_SigningPrivateKey); + break; + default: + LogPrint ("Signing key type ", (int)m_Public.GetSigningKeyType (), " is not supported"); + } } PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type) { - if (type == SIGNING_KEY_TYPE_ECDSA_SHA256_P256) + if (type != SIGNING_KEY_TYPE_DSA_SHA1) { PrivateKeys keys; auto& rnd = i2p::context.GetRandomNumberGenerator (); + // signature + uint8_t signingPublicKey[i2p::crypto::ECDSAP521_KEY_LENGTH]; // 132 bytes is max key size now + switch (type) + { + case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: + i2p::crypto::CreateECDSAP256RandomKeys (rnd, keys.m_SigningPrivateKey, signingPublicKey); + break; + case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: + i2p::crypto::CreateECDSAP384RandomKeys (rnd, keys.m_SigningPrivateKey, signingPublicKey); + break; + case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: + i2p::crypto::CreateECDSAP521RandomKeys (rnd, keys.m_SigningPrivateKey, signingPublicKey); + break; + default: + LogPrint ("Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); + return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1 + } + keys.CreateSigner (); // encryption uint8_t publicKey[256]; CryptoPP::DH dh (i2p::crypto::elgp, i2p::crypto::elgg); dh.GenerateKeyPair(rnd, keys.m_PrivateKey, publicKey); - // signature - uint8_t signingPublicKey[64]; - i2p::crypto::CreateECDSAP256RandomKeys (rnd, keys.m_SigningPrivateKey, signingPublicKey); - keys.m_Public = IdentityEx (publicKey, signingPublicKey, SIGNING_KEY_TYPE_ECDSA_SHA256_P256); - keys.CreateSigner (); + // identity + keys.m_Public = IdentityEx (publicKey, signingPublicKey, type); return keys; } return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1 diff --git a/Identity.h b/Identity.h index d947077c..223134e6 100644 --- a/Identity.h +++ b/Identity.h @@ -102,11 +102,14 @@ namespace data Keys CreateRandomKeys (); const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes - + const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1; + const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA384_P384 = 2; + const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA512_P521 = 3; typedef uint16_t SigningKeyType; + typedef uint16_t CryptoKeyType; class IdentityEx { @@ -131,6 +134,7 @@ namespace data size_t GetSignatureLen () const; bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; SigningKeyType GetSigningKeyType () const; + CryptoKeyType GetCryptoKeyType () const; private: diff --git a/Signature.h b/Signature.h index fbc02c4e..1ea386f9 100644 --- a/Signature.h +++ b/Signature.h @@ -87,67 +87,150 @@ namespace crypto publicKey.GetPublicElement ().Encode (signingPublicKey, DSA_PUBLIC_KEY_LENGTH); } - - const size_t ECDSAP256_PUBLIC_KEY_LENGTH = 64; - const size_t ECDSAP256_PUBLIC_KEY_HALF_LENGTH = ECDSAP256_PUBLIC_KEY_LENGTH/2; - const size_t ECDSAP256_SIGNATURE_LENGTH = 64; - const size_t ECDSAP256_PRIVATE_KEY_LENGTH = ECDSAP256_SIGNATURE_LENGTH/2; - class ECDSAP256Verifier: public Verifier - { + template + class ECDSAVerifier: public Verifier + { public: - ECDSAP256Verifier (const uint8_t * signingKey) + template + ECDSAVerifier (Curve curve, const uint8_t * signingKey) { - m_PublicKey.Initialize (CryptoPP::ASN1::secp256r1(), - CryptoPP::ECP::Point (CryptoPP::Integer (signingKey, ECDSAP256_PUBLIC_KEY_HALF_LENGTH), - CryptoPP::Integer (signingKey + ECDSAP256_PUBLIC_KEY_HALF_LENGTH, ECDSAP256_PUBLIC_KEY_HALF_LENGTH))); - } + m_PublicKey.Initialize (curve, + CryptoPP::ECP::Point (CryptoPP::Integer (signingKey, keyLen/2), + CryptoPP::Integer (signingKey + keyLen/2, keyLen/2))); + } bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { - CryptoPP::ECDSA::Verifier verifier (m_PublicKey); - return verifier.VerifyMessage (buf, len, signature, ECDSAP256_SIGNATURE_LENGTH); + typename CryptoPP::ECDSA::Verifier verifier (m_PublicKey); + return verifier.VerifyMessage (buf, len, signature, keyLen); // signature length } - size_t GetPublicKeyLen () const { return ECDSAP256_PUBLIC_KEY_LENGTH; }; - size_t GetSignatureLen () const { return ECDSAP256_SIGNATURE_LENGTH; }; + size_t GetPublicKeyLen () const { return keyLen; }; + size_t GetSignatureLen () const { return keyLen; }; // signature length = key length private: - CryptoPP::ECDSA::PublicKey m_PublicKey; - }; + typename CryptoPP::ECDSA::PublicKey m_PublicKey; + }; - class ECDSAP256Signer: public Signer + template + class ECDSASigner: public Signer { public: - ECDSAP256Signer (const uint8_t * signingPrivateKey) + template + ECDSASigner (Curve curve, const uint8_t * signingPrivateKey, size_t keyLen) { - m_PrivateKey.Initialize (CryptoPP::ASN1::secp256r1(), CryptoPP::Integer (signingPrivateKey, ECDSAP256_PRIVATE_KEY_LENGTH)); + m_PrivateKey.Initialize (curve, CryptoPP::Integer (signingPrivateKey, keyLen/2)); // private key length } void Sign (CryptoPP::RandomNumberGenerator& rnd, const uint8_t * buf, int len, uint8_t * signature) const { - CryptoPP::ECDSA::Signer signer (m_PrivateKey); + typename CryptoPP::ECDSA::Signer signer (m_PrivateKey); signer.SignMessage (rnd, buf, len, signature); } private: - CryptoPP::ECDSA::PrivateKey m_PrivateKey; + typename CryptoPP::ECDSA::PrivateKey m_PrivateKey; }; - inline void CreateECDSAP256RandomKeys (CryptoPP::RandomNumberGenerator& rnd, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + template + inline void CreateECDSARandomKeys (CryptoPP::RandomNumberGenerator& rnd, Curve curve, + size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { - CryptoPP::ECDSA::PrivateKey privateKey; - CryptoPP::ECDSA::PublicKey publicKey; - privateKey.Initialize (rnd, CryptoPP::ASN1::secp256r1()); + typename CryptoPP::ECDSA::PrivateKey privateKey; + typename CryptoPP::ECDSA::PublicKey publicKey; + privateKey.Initialize (rnd, curve); privateKey.MakePublicKey (publicKey); - privateKey.GetPrivateExponent ().Encode (signingPrivateKey, ECDSAP256_PRIVATE_KEY_LENGTH); + privateKey.GetPrivateExponent ().Encode (signingPrivateKey, keyLen/2); auto q = publicKey.GetPublicElement (); - q.x.Encode (signingPublicKey, ECDSAP256_PUBLIC_KEY_HALF_LENGTH); - q.y.Encode (signingPublicKey + ECDSAP256_PUBLIC_KEY_HALF_LENGTH, ECDSAP256_PUBLIC_KEY_HALF_LENGTH); + q.x.Encode (signingPublicKey, keyLen/2); + q.y.Encode (signingPublicKey + keyLen/2, keyLen/2); + } + +// ECDSA_SHA256_P256 + const size_t ECDSAP256_KEY_LENGTH = 64; + class ECDSAP256Verifier: public ECDSAVerifier + { + public: + + ECDSAP256Verifier (const uint8_t * signingKey): + ECDSAVerifier (CryptoPP::ASN1::secp256r1(), signingKey) + { + } + }; + + class ECDSAP256Signer: public ECDSASigner + { + public: + + ECDSAP256Signer (const uint8_t * signingPrivateKey): + ECDSASigner (CryptoPP::ASN1::secp256r1(), signingPrivateKey, ECDSAP256_KEY_LENGTH) + { + } + }; + + inline void CreateECDSAP256RandomKeys (CryptoPP::RandomNumberGenerator& rnd, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (rnd, CryptoPP::ASN1::secp256r1(), ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey); } + +// ECDSA_SHA384_P384 + const size_t ECDSAP384_KEY_LENGTH = 96; + class ECDSAP384Verifier: public ECDSAVerifier + { + public: + + ECDSAP384Verifier (const uint8_t * signingKey): + ECDSAVerifier (CryptoPP::ASN1::secp384r1(), signingKey) + { + } + }; + + class ECDSAP384Signer: public ECDSASigner + { + public: + + ECDSAP384Signer (const uint8_t * signingPrivateKey): + ECDSASigner (CryptoPP::ASN1::secp384r1(), signingPrivateKey, ECDSAP384_KEY_LENGTH) + { + } + }; + + inline void CreateECDSAP384RandomKeys (CryptoPP::RandomNumberGenerator& rnd, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (rnd, CryptoPP::ASN1::secp384r1(), ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey); + } + +// ECDSA_SHA512_P521 + const size_t ECDSAP521_KEY_LENGTH = 132; + class ECDSAP521Verifier: public ECDSAVerifier + { + public: + + ECDSAP521Verifier (const uint8_t * signingKey): + ECDSAVerifier (CryptoPP::ASN1::secp521r1(), signingKey) + { + } + }; + + class ECDSAP521Signer: public ECDSASigner + { + public: + + ECDSAP521Signer (const uint8_t * signingPrivateKey): + ECDSASigner (CryptoPP::ASN1::secp521r1(), signingPrivateKey, ECDSAP521_KEY_LENGTH) + { + } + }; + + inline void CreateECDSAP521RandomKeys (CryptoPP::RandomNumberGenerator& rnd, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) + { + CreateECDSARandomKeys (rnd, CryptoPP::ASN1::secp521r1(), ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey); + } + } }