From ab1cd3f5cf2ba0888cf18d8474e58cd33156e931 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Nov 2017 15:01:07 -0500 Subject: [PATCH] ECIES for GOST R 34.10 --- libi2pd/CryptoKey.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++- libi2pd/CryptoKey.h | 36 ++++++++++++++++++++++++- libi2pd/Identity.cpp | 9 +++++++ libi2pd/Identity.h | 1 + 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index a0858b91..ffe1591a 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -1,5 +1,6 @@ #include #include "Log.h" +#include "Gost.h" #include "CryptoKey.h" namespace i2p @@ -65,7 +66,7 @@ namespace crypto { if (m_Curve && m_PrivateKey) return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx); - return false;; + return false; } void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub) @@ -86,6 +87,65 @@ namespace crypto BN_free (x); BN_free (y); EC_GROUP_free (curve); } + + ECIESGOSTR3410Encryptor::ECIESGOSTR3410Encryptor (const uint8_t * pub) + { + auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA); + m_PublicKey = EC_POINT_new (curve->GetGroup ()); + BIGNUM * x = BN_bin2bn (pub, 32, nullptr); + BIGNUM * y = BN_bin2bn (pub + 32, 32, nullptr); + if (!EC_POINT_set_affine_coordinates_GFp (curve->GetGroup (), m_PublicKey, x, y, nullptr)) + LogPrint (eLogError, "ECICS GOST R 34.10 invalid public key"); + BN_free (x); BN_free (y); + } + + ECIESGOSTR3410Encryptor::~ECIESGOSTR3410Encryptor () + { + if (m_PublicKey) EC_POINT_free (m_PublicKey); + } + + void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) + { + if (m_PublicKey) + ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx); + } + + ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv) + { + m_PrivateKey = BN_bin2bn (priv, 32, nullptr); + } + + ECIESGOSTR3410Decryptor::~ECIESGOSTR3410Decryptor () + { + if (m_PrivateKey) BN_free (m_PrivateKey); + } + + bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) + { + if (m_PrivateKey) + return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx); + return false; + } + + + void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub) + { + auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA); + EC_POINT * p = nullptr; + BIGNUM * key = nullptr; + GenerateECIESKeyPair (curve->GetGroup (), key, p); + bn2buf (key, priv, 32); + RAND_bytes (priv + 32, 224); + BN_free (key); + BIGNUM * x = BN_new (), * y = BN_new (); + EC_POINT_get_affine_coordinates_GFp (curve->GetGroup (), p, x, y, NULL); + bn2buf (x, pub, 32); + bn2buf (y, pub + 32, 32); + RAND_bytes (priv + 64, 192); + EC_POINT_free (p); + BN_free (x); BN_free (y); + } + } } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index f08a15b2..a2cfdd87 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -24,6 +24,7 @@ namespace crypto virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) = 0; // 512 bytes encrypted, 222 bytes data }; +// ElGamal class ElGamalEncryptor: public CryptoKeyEncryptor // for destination { public: @@ -48,6 +49,8 @@ namespace crypto uint8_t m_PrivateKey[256]; }; +// ECIES P256 + class ECIESP256Encryptor: public CryptoKeyEncryptor { public: @@ -77,7 +80,38 @@ namespace crypto BIGNUM * m_PrivateKey; }; - void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); + void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); + +// ECIES GOST R 34.10 + + class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor + { + public: + + ECIESGOSTR3410Encryptor (const uint8_t * pub); + ~ECIESGOSTR3410Encryptor (); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + + private: + + EC_POINT * m_PublicKey; + }; + + + class ECIESGOSTR3410Decryptor: public CryptoKeyDecryptor + { + public: + + ECIESGOSTR3410Decryptor (const uint8_t * priv); + ~ECIESGOSTR3410Decryptor (); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + + private: + + BIGNUM * m_PrivateKey; + }; + + void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub); } } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 054a6a06..42eae215 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -453,6 +453,9 @@ namespace data case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return std::make_shared(key); break; + case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: + return std::make_shared(key); + break; default: LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)GetCryptoKeyType ()); }; @@ -601,6 +604,9 @@ namespace data case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return std::make_shared(key); break; + case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: + return std::make_shared(key); + break; default: LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType); }; @@ -669,6 +675,9 @@ namespace data case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: i2p::crypto::CreateECIESP256RandomKeys (priv, pub); break; + case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: + i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub); + break; default: LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); } diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index a95997e8..b0c6f48a 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -54,6 +54,7 @@ namespace data const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 65280; // TODO: change to actual code + const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1;