#include <iostream>
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"
#include "hex.h"
#include "filters.h"
#ifndef ECC_ENCRYPTION_ALGORITHM_H_
#define ECC_ENCRYPTION_ALGORITHM_H_
#include<string>
class EccEncryption
{
public:
/// This method is used to generate keys for ECC encryption algorithm
///
/// \param[in] uiKeySize, length of key
/// \param[out] sPrivateKey, private key
/// \param[out] sPublicKey, public key
void GenerateEccKeys(unsigned int uiKeySize, std::string& sPrivateKey, std::string& sPublicKey);
/// This method is used to encrypt the input message using public key
///
/// \param[in] sPublicKey, public key generated by the first method
/// \param[out] sMsgToEncrypt, message to encryppt
/// \return the message encrypted using the input public key
std::string Encrypt(const std::string& sPublicKey, const std::string& sMsgToEncrypt);
/// This method is used to decrypt the input message using private key
///
/// \param[in] sPrivateKey, private key used to decrypt the cipher text
/// \param[in] sMsgToDecrypt, cipher text used to decrypt to get the plain text
/// \return decrypted plain text
std::string Decrypt(const std::string& sPrivateKey, const std::string& sMsgToDecrytp);
};
#endif
void EccEncryption::GenerateEccKeys(unsigned int uiKeySize, std::string& sPrivateKey, std::string& sPublicKey)
{
using namespace CryptoPP;
#if 0
// Random pool, the second parameter is the length of key
// 随机数池,第二个参数是生成密钥的长
AutoSeededRandomPool rnd(false, 256);
ECIES<ECP>::PrivateKey privateKey;
ECIES<ECP>::PublicKey publicKey;
// Generate private key
privateKey.Initialize(rnd, ASN1::secp256r1());
// Generate public key using private key
privateKey.MakePublicKey(publicKey);
#else
Integer p("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFh");
std::cout << "modulus:" << std::hex << p << std::endl;
// a、b为椭圆曲线参数
Integer a("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFCh");
std::cout << "a:" << std::hex << a << std::endl;
Integer b("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604Bh");
std::cout << "b:" << std::hex << b << std::endl;
// 计算基点G的两个参数x、y
Integer x("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296h");
std::cout << "x:" << std::hex << x << std::endl;
Integer y("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5h");
std::cout << "y:" << std::hex << y << std::endl;
Integer order("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551h");
std::cout << "order:" << std::hex << order << std::endl;
Integer r("100000000000000000000000000000000000000000000000151");
std::cout << "r:" << std::hex << r << std::endl;
Integer k("128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263h");
std::cout << "k:" << std::hex << k << std::endl;
Integer sin_k("6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F");
// 私有密钥
Integer d("76572944925670636209790912427415155085360939712345");
std::cout << "d:" << std::hex << d << std::endl;
// 椭圆曲线
ECP ec(p, a, b);
// 基点G
ECP::Point G(x, y);
std::cout << "G.y:" << std::hex << G.y << std::endl;
ECIES<ECP>::PrivateKey privateKey;
privateKey.Initialize(ec, G, order, x);
// Generate public key using private key
ECIES<ECP>::PublicKey publicKey;
#if 1
privateKey.MakePublicKey(publicKey);
#else
// Q为公开密钥
ECP::Point Q(ec.Multiply(k, G));
publicKey.Initialize(ec, G,order, Q);
#endif
#endif
ECIES<ECP>::Encryptor encryptor(publicKey);
HexEncoder pubEncoder(new StringSink(sPublicKey));
publicKey.DEREncode(pubEncoder);
pubEncoder.MessageEnd();
ECIES<ECP>::Decryptor decryptor(privateKey);
HexEncoder prvEncoder(new StringSink(sPrivateKey));
privateKey.DEREncode(prvEncoder);
prvEncoder.MessageEnd();
}
std::string EccEncryption::Encrypt(const std::string& sPublicKey, const std::string& sMsgToEncrypt)
{
using namespace CryptoPP;
// If to save the keys into a file, FileSource should be replace StringSource
StringSource pubString(sPublicKey, true, new HexDecoder);
ECIES<ECP>::Encryptor encryptor(pubString);
// Calculate the length of cipher text
size_t uiCipherTextSize = encryptor.CiphertextLength(sMsgToEncrypt.size());
std::string sCipherText;
sCipherText.resize(uiCipherTextSize);
RandomPool rnd;
encryptor.Encrypt(rnd, (byte*)(sMsgToEncrypt.c_str()), sMsgToEncrypt.size(), (byte*)(sCipherText.data()));
return sCipherText;
}
std::string EccEncryption::Decrypt(const std::string& sPrivateKey, const std::string& sMsgToDecrytp)
{
using namespace CryptoPP;
StringSource privString(sPrivateKey, true, new HexDecoder);
ECIES<ECP>::Decryptor decryptor(privString);
auto sPlainTextLen = decryptor.MaxPlaintextLength(sMsgToDecrytp.size());
std::string sDecryText;
sDecryText.resize(sPlainTextLen);
RandomPool rnd;
decryptor.Decrypt(rnd, (byte*)sMsgToDecrytp.c_str(), sMsgToDecrytp.size(), (byte*)sDecryText.data());
return sDecryText;
}
int test_ECIES_main()
{
std::string sStrToTest = std::string("Hello world. This is an example of Ecc encryption algorithm of Crypto++ open source library.");
EccEncryption ecc;
std::string sPrivateKey, sPublicKey;
ecc.GenerateEccKeys(1024, sPrivateKey, sPublicKey);
std::cout << "Generated private key is : " << std::endl;
std::cout << sPrivateKey << std::endl;
std::cout << "***********************************************************" << std::endl;
std::cout << "Generated public key is : " << std::endl;
std::cout << sPublicKey << std::endl;
std::cout << "***********************************************************" << std::endl;
std::cout << "The message to be encrypted is : " << std::endl;
std::cout << sStrToTest << std::endl;
std::cout << "***********************************************************" << std::endl;
std::string sEncryptResult = ecc.Encrypt(sPublicKey, sStrToTest);
std::cout << "The result of encrypt is : " << std::endl;
std::cout << sEncryptResult << std::endl;
std::cout << "***********************************************************" << std::endl;
std::string sDecryptResult = ecc.Decrypt(sPrivateKey, sEncryptResult);
std::cout << "The result of decrypt is : " << std::endl;
std::cout << sDecryptResult << std::endl;
std::cout << "***********************************************************" << std::endl;
return 0;
}