Search code examples
c++public-key-encryptioncrypto++elliptic-curve

Use previously generated private key in ECIES


I wan to encrypt /decrypt data using ECIES , I am using cryptopp for this.

AutoSeededRandomPool prng;

//get private key generated
ECIES<ECP>::Decryptor d0(prng, ASN1::secp256r1());
PrintPrivateKey(d0.GetKey());

//get public key 
ECIES<ECP>::Encryptor e0(d0);
PrintPublicKey(e0.GetKey());

//encrypt the message
string em0; // encrypted message
StringSource ss1 (message, true, new PK_EncryptorFilter(prng, e0, new StringSink(em0) ) );

//decrypt the message   
string dm0; // decrypted message
StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, d1, new StringSink(dm0) ) );

Everything else is fine but I want to do the above same thing using already generated 'private key' and not randomly generated 'private key' unlike the case above. How can I do this?

I have tried the following code but it just simply crashes

AutoSeededRandomPool prng;

std::string  privatekeyString="02C200102C180F9E6A4E7A2F58B5BE86BC179478";

CryptoPP::HexDecoder decoder;
decoder.Put((byte*)privatekeyString.data(), privatekeyString.size());
decoder.MessageEnd();

ECIES<ECP> ::Decryptor d0;
d0.AccessKey().AccessGroupParameters().Initialize(ASN1::secp128r1());

crash point

//load private key  
d0.AccessKey().Load(decoder);
PrintPrivateKey(d0.GetKey());

//get public key    
ECIES<ECP>::Encryptor e0(d0);
PrintPublicKey(e0.GetKey());

string em0; // encrypted message
StringSource ss1(message, true, new PK_EncryptorFilter(prng, e0, new StringSink(em0) ) );
cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

string dm0; // decrypted message
StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, d0, new StringSink(dm0) ) );
cout <<"decrypted msg: "<< dm0<<"  and its length: "<<dm0.length() <<   endl;

Edit 2

In response to @jww answer I managed to decode the message with the private key as:

  try
  {
    AutoSeededRandomPool prng;

    std::string exponent="AsIAECwYD55qTnovWLW+hrwXlHg=";
    StringSource ss(exponent, true /*pumpAll*/, new CryptoPP::HexDecoder);


    Integer x;
    x.Decode(ss, ss.MaxRetrievable(), Integer::UNSIGNED);
    // cout << "Exponent: " << std::hex << x << endl;

    ECIES<ECP>::Decryptor decryptor;
    decryptor.AccessKey().Initialize(ASN1::secp128r1(), x);

    bool valid = decryptor.AccessKey().Validate(prng, 3);
    if(!valid)
    {
        cout<<"Exponent is not valid for P-128"<<endl;
        return;
    }
      //  throw  Exception(CryptoPP::Exception::OTHER_ERROR, "Exponent is not valid for P-256");

    // Or: decryptor.AccessKey().ThrowIfInvalid(prng, 3);

    cout << "Exponent is valid for P-128" << endl;

    PrintPrivateKey(decryptor.GetKey());


    //get public key
    ECIES<ECP>::Encryptor encryptor(decryptor);
    PrintPublicKey(encryptor.GetKey());



    string em0; // encrypted message
    StringSource ss1(message, true, new PK_EncryptorFilter(prng, encryptor, new StringSink(em0) ) );
    cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

    string dm0; // decrypted message
    StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, decryptor, new StringSink(dm0) ) );
    cout <<"decrypted msg: "<< dm0<<"  and its length: "<<dm0.length() << endl;

}
catch(const CryptoPP::Exception& ex)
{
    std::cerr << ex.what() << endl;
}

But when I try to encrypt the message using public key I got error

CryptoPP::CryptoMaterial::InvalidMaterial: CryptoMaterial: this object contains invalid values

Here is my code:

std::string     public_point="AsIAEFjzIcX+Kvhe8AmLoGUc8aYAEAwf5ecREGZ2u4RLxQuav/A=";
StringSource ss(public_point, true, new CryptoPP::HexDecoder);

ECIES<ECP>::Encryptor encryptor;
    encryptor.AccessKey().AccessGroupParameters().Initialize(ASN1::secp128r1());

ECP::Point point;
encryptor.GetKey().GetGroupParameters().GetCurve().DecodePoint(point, ss, ss.MaxRetrievable());
cout << "X: " << std::hex << point.x << endl;
cout << "Y: " << std::hex << point.y << endl;

encryptor.AccessKey().SetPublicElement(point);


encryptor.AccessKey().ThrowIfInvalid(prng, 3);

PrintPublicKey(encryptor.GetKey());



string em0; // encrypted message
StringSource ss1(message, true, new PK_EncryptorFilter(prng, encryptor, new StringSink(em0) ) );
cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

Solution

  • As jww suggested I have successfully completed encryption and decryption. Below are the code snippets if anyone wants.

    Decryption

    string decrypt(std::string encryptedMessage ,  std::string   privateKeyExponent)
    {
        string decryptedMessage;
        try
        {
            AutoSeededRandomPool prng;
    
            //since the 'privateKeyExponent' is in base-64 format use Base64Decoder
            StringSource ss(privateKeyExponent, true /*pumpAll*/, new CryptoPP::Base64Decoder);
    
            Integer x;
            x.Decode(ss, ss.MaxRetrievable(), Integer::UNSIGNED);
    
            ECIES<ECP>::Decryptor decryptor;
    
            //curve used is secp256k1
            //make decryptor's access key using decoded private exponent's value
            decryptor.AccessKey().Initialize(ASN1::secp256k1(), x);
    
            //check whether decryptor's access key is valid or not
            bool valid = decryptor.AccessKey().Validate(prng, 3);
            if(!valid)
               decryptor.AccessKey().ThrowIfInvalid(prng, 3);
    
            cout << "Exponent is valid for P-256k1" << endl;
    
            //decrypt the message using private key
            StringSource ss2 (encryptedMessage, true, new PK_DecryptorFilter(prng, decryptor, new StringSink(decryptedMessage) ) );
            cout <<"decrypted msg: "<< decryptedMessage<<"  and its length: "<<decryptedMessage.length() << endl;
    
        }
        catch(const CryptoPP::Exception& ex)
        {
            std::cerr << ex.what() << endl;
        }
        return decryptedMessage;
    }
    

    Encryption

    string encrypt(std::string message ,  std::string  compressedPublicKeyPoint)
    {
        string encryptedMessage;
        try
        {
            AutoSeededRandomPool prng;
    
            //public key is a point consisting of "public key point x" and "public key point y"
            //compressed public key also known as "public-point" formed using point-compression of public key
    
    
            //since the key is in base-64 format use Base64Decoder
            StringSource ss(compressedPublicKeyPoint, true, new CryptoPP::Base64Decoder);
         ECIES<ECP>::Encryptor encryptor;
    
            //curve used is secp256k1
            encryptor.AccessKey().AccessGroupParameters()
           .Initialize(ASN1::secp256k1());
    
            //get point on the used curve
            ECP::Point point;
            encryptor.GetKey().GetGroupParameters().GetCurve().DecodePoint(point, ss, ss.MaxRetrievable());
            cout << "X: " << std::hex << point.x << endl;
            cout << "Y: " << std::hex << point.y << endl;
    
            //set encryptor's public element
            encryptor.AccessKey().SetPublicElement(point);
    
            //check whether the encryptor's access key thus formed is valid or not
            encryptor.AccessKey().ThrowIfInvalid(prng, 3);
    
            // encrypted message
            StringSource ss1(message, true, new PK_EncryptorFilter(prng, encryptor, new StringSink(encryptedMessage) ) );
            cout<<"encrypted msg: "<<encryptedMessage<<"  and its length: "<<encryptedMessage.length()<<endl;
        }
        catch(const CryptoPP::Exception& ex)
        {
            std::cerr << ex.what() << endl;
        }
    
        return encryptedMessage;
    }