Importing a private key from a string using Crypto++ - c++

So first I create a signing object like so:
CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Signer signer;
I generate them like so:
CryptoPP::AutoSeededRandomPool prng; //Create a random number
signer.AccessKey().Initialize(prng, CryptoPP::ASN1::secp256r1());
I also validate the generated keys to check everything is fine:
signer.AccessKey().Validate(prng, 3))
These are then exported to a string:
std::string key;
CryptoPP::StringSink pss(key);
signer.AccessKey().Save(pss);
However when it comes to loading these keys back up:
CryptoPP::StringSink ss(key);
signer.AccessKey().Load(ss);
I receive and exception:
BER decode error
Just to note the signing object is blank upon attempting to load could this be it?
I'm not sure what I'm doing wrong I believe it's the method for loading the key back into the Access key and I should be importing the key to the StringSink differently but I'm not sure. Please could I have some help trying to load my keys.

This is correct:
std::string p_key;
CryptoPP::StringSink pss(p_key);
signer.AccessKey().Save(pss);
This looks like the problem assuming p_key and key are the same:
CryptoPP::StringSink ss(key);
signer.AccessKey().Load(ss);
Use as StringSource when loading, not a StringSink:
CryptoPP::StringSource ss(key);
signer.AccessKey().Load(ss);
All sources and sinks are interchangeable. You can use a FileSource instead of a StringSource; and a FileSink instead of a StringSink. But you can't replace a source with a sink (or vice versa).
StringSource and StringSink are part of pipelines in Crypto++. Pipelines and Keys and Formats from the Crypto++ wiki may be useful for you. But the code you showed is clean (other than the typo) so you may not need them.

Related

crypto++ rsa key into buffer

i started to make an encrypt decrypt file with rsa but i want to save the keys into a buffer like string and etc so i can work with it
i know i can save the key into file like this
AutoSeededRandomPool rng;
RSA::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 2048);
RSA::PublicKey publicKey(privateKey);
Base64Encoder privkeysink(new FileSink("C:\\1\\privkey.txt"));
privateKey.DEREncode(privkeysink);
privkeysink.MessageEnd();
Base64Encoder pubkeysink(new FileSink("C:\\1\\pubkey.txt"));
publicKey.DEREncode(pubkeysink);
pubkeysink.MessageEnd();
but i don't think it a good idea to save to file and then read the file,
is there any way to do it directly?
AutoSeededRandomPool rng;
RSA::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(rng, 2048);
Base64Encoder privkeysink(new FileSink("C:\\1\\privkey.txt"));
privateKey.DEREncode(privkeysink);
privkeysink.MessageEnd();
...
You kinda have two things going on. First, how to create and use an RSA key. Second, how do you save the key. In between, you seemed to have added an extra step of reloading a key.
The creation of the key looks fine (which you are doing):
privateKey.GenerateRandomWithKeySize(rng, 2048);
When you want to save it, simply save it (which you are doing):
privateKey.DEREncode(FileSink("privkey.der", true).Ref());
There's no need to reload it. Its still good after you save it. In this case, simply use it (you are adding extra steps here):
RSAES_OAEP_SHA_Decryptor dec(privateKey);
If the key is persisted to disk and you need to reload it, then:
privateKey.BERDecode(FileSource("privkey.der").Ref());
Or even:
RSAES_OAEP_SHA_Decryptor dec;
dec.AccessKey().BERDecode(FileSource("privkey.der").Ref());
I want to save the keys into a buffer like string
This kind of confuses me because I'm not sure what you goal is based on round tripping the key from a file. Recall you can use the key directly:
RSAES_OAEP_SHA_Decryptor dec(privateKey);
But if you want to save it to an in-memory buffer, then:
string buff;
privateKey.DEREncode(StringSink(buff).Ref());
Or:
ByteQueue queue;
privateKey.DEREncode(queue);
And you can still use the pipeline if you like:
privateKey.DEREncode(Base64Encoder(new FileSink("privkey.der")).Ref());
A related wiki page is Keys and Formats.

Saving key and iv to file AES implementation Crypto++

So I am using the Crypto++ Library to encrypt a file. I need to save the key and iv for future use. I am following this tutorial. Here is my function :
void AESUtil::encrypt(string filename,bool savekeys,string savefilename){
AutoSeededRandomPool rnd;
// Generate a random key
byte key[AES::DEFAULT_KEYLENGTH];
rnd.GenerateBlock(key, AES::DEFAULT_KEYLENGTH);
// Generate a random IV
byte iv[AES::BLOCKSIZE];
rnd.GenerateBlock(iv, AES::BLOCKSIZE);
Binary b;
string plaintext = b.decoder(filename);
unsigned char *ciphertext= new unsigned char[plaintext.size()+1];
ciphertext[plaintext.size()]='\0';
if(savekeys){
ofstream("key.bin", ios::binary).write((char*)key, sizeof(key));
}
CFB_Mode<AES>::Encryption cfbEncryption(key, AES::DEFAULT_KEYLENGTH, iv);
cfbEncryption.ProcessData(ciphertext,reinterpret_cast<const unsigned char*>(plaintext.c_str()),plaintext.size()+1);
ofstream outfile(savefilename.c_str());
outfile.write((char*)ciphertext,sizeof(ciphertext));
}
The files contain data in �/���� format. I want to know the best method to save the key and iv programmatically which are a byte array to a file and the ciphertext which is a unsigned char* to a separate file.
The key could be saved in a separate file. Normally the key is established between sender / receiver in advance, or it is encrypted using a public key of the receiver. Note that it doesn't make sense to save the key next to the ciphertext, as it would provide no protection whatsoever. The handling of keys is called key management and entire books have been written about it.
The IV is a different animal. The IV should be randomly generated. For CFB it should at least be unique and identical at both sides. Usually the IV is simply prefixed to the ciphertext, it doesn't have to be kept secret.
Your key and iv variables are the key and IV used to encrypt the plain text.
You didn't fill either; you're actually using an array filled with 0 bytes as both the key and IV for your encryption.
The IV is public information. You don't need to hide it. Save it the way you want.
The KEY is what you must keep safe. To do that you may decide how much effort you want to put on it to hide it from the external factors.
I have some keys that I don't care to leave them as a "plain text" in the binary code. (NO SECURITY, but my mom can't figure out what to do, but a beginner in reverse engineer will laugh at it.)
Some keys I do a play with the bytes, like inverting parts, separating them, XOR with something. (Very unsafe, but better than nothing, a programmer with decent knowledge in reverse engineering will be able to spend some time and eventually break the security)
Some other cases I use 3rd party advanced obfuscation... If possible, depending on what you want, you may even replace your encryption engine with some "white-box" cryptography. Then you will have your keys very well protected. But this is usually hard/expensive. It doesn't seem to be your case. (Yes, even a very advanced assembly guru will not be happy to start reverse engineer this case.)
Another solution, if you don't need the key on your binary, is to give it to the system's password manager. On Windows, it's called "Data Protection API", and on Mac, it's called "Keychain". Take a look at these, and then you will understand why this is considered security. But it's because all the passwords here are encrypted with the "user password" so nothing is stored "on disk". A turned-off device in this scenario is considered very secure.

crypto++ saving key to a byte queue and back to a key

I want to license my software using RSA encryption. My software has several executables and I plan to have each check the signature of a common license file before they proceed to do what it is they do. My goal is not to make it impossible to circumvent the licensing protection, just make it very difficult. I know that no one can make it impossible.
The executables currently run in a Windows environment, but they will only be released to work in a Linux environment.
My current plan is to put the public key within each executable for signature verification. The programs already have a 'safe' encrypted area in which to put the key.
My question for this post is, does my implementation method make sense? Is there another alternative? The alternative to have the public key in a separate file would allow a hacker to replace that file and use their own license file and signature. That doesn't seem as safe.
Additionally I've been reading through the crypto++ documentation and running the example code to try and accomplish this task. I cannot get any code to work that puts the key into a non-file sink and back again. All the examples write and read to files. I need to be able to save and load from a string or a byte queue. A simple attempt to do this is below, but when it runs I get this error, when r2.BERDecodePrivateKey() executes:
Unhandled exception at 0x7630c41f in MyRSA.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x002ef32c..
#include <osrng.h>
#include "rsa.h"
using CryptoPP::RSA;
#include <queue.h>
using CryptoPP::ByteQueue;
int myCode_key2ByteQueueToKey(void)
{
////////////////////////////////////////////////////////////////////////
// Generate the keys
AutoSeededRandomPool rnd;
CryptoPP::RSA::PrivateKey r1;
r1.GenerateRandomWithKeySize(rnd, 2048);
CryptoPP::RSA::PublicKey rsaPublic(r1);
////////////////////////////////////////////////////////////////////////
// Put the 'inner' part of the key into a ByteQueue - whatever that is.
ByteQueue queue;
r1.DEREncodePublicKey(queue);
////////////////////////////////////////////////////////////////////////
// Copy the byte queued inner key into another key
CryptoPP::RSA::PrivateKey r2;
r2.BERDecodePrivateKey(queue, false /*optParams*/, queue.MaxRetrievable());
////////////////////////////////////////////////////////////////////////
// Validate the key made the trip in and out of a byte queue ok.
if(!r1.Validate(rnd, 3)) printf("Validation of oringal key failed.\n");
if(!r2.Validate(rnd, 3)) printf("Validation of reloaded key failed.\n");
if(r1.GetModulus() != r2.GetModulus() ||
r1.GetPublicExponent() != r2.GetPublicExponent() ||
r1.GetPrivateExponent() != r2.GetPrivateExponent())
{
printf("Key didn't survive round trip in and out of a byte queue.");
}
return 0;
}
I do not have a fix for the above code. There's something I don't understand about library and as a result something's missing, but I've got to get a move on.
I thought I'd post an alternative I've found. Its an example on the Crypto++ wiki that puts the keys into strings (and not files) and back again. The round trip is shown to work.
http://www.cryptopp.com/wiki/BERDecode
Instead of
CryptoPP::RSA::PrivateKey
it uses
CryptoPP::RSAES_OAEP_SHA_Decryptor
and similarly for the public key. This allows the use of a member function AccessKey() which isn't available for the PrivateKey class.
If anyone has a fix for the original code, I urge you to please post it as it would help me better understand this library.
So basically you do this:
Generate 2048 bits private key
Encode a public key in DER format from the exponents of your private key to your bytequeue
Try to decode it as a private key from the bytequeue <-- here is the error
Validate the key...
You cannot decode a public key to a private key, some encoding flags differs.
As for CryptoPP::RSAES_OAEP_SHA_Decryptor
it's a good practice to use it for key generation as it is aware of safe primes.
It is also simpler to use for general decryption task as it includes everything you need in one object.
See http://www.cryptopp.com/wiki/Keys_and_Formats#High_Level_Objects
Hope it helped even it's a late answer ;)

Load PEM encoded private RSA key in Crypto++

Often times, user will have PEM encoded RSA private keys. Crypto++ requires that these keys be in DER format to load. I've been asking people to manually convert their PEM files to DER beforehand using openssl like this:
openssl pkcs8 -in in_file.pem -out out_file.der -topk8 -nocrypt -outform der
That works fine, but some people don't understand how to do that nor do they want to. So I would like to convert PEM files to DER files automatically within the program.
Is it as simple as striping the "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" from the PEM or is some other transformation required as well? I've been told that between those markers that it's just b64 encoded DER. Here's some code that demonstrates the issue:
// load the private key
CryptoPP::RSA::PrivateKey PK;
CryptoPP::ByteQueue bytes;
try
{
CryptoPP::FileSource File( rsa.c_str(), true, new CryptoPP::Base64Decoder() );
File.TransferTo( bytes );
bytes.MessageEnd();
// This line Causes BERDecodeError when a PEM encoded file is used
PK.Load( bytes );
}
catch ( CryptoPP::BERDecodeErr )
{
// Convert PEM to DER and try to load the key again
}
I'd like to avoid making system calls to openssl and do the transformation entirely in Crypto++ so that users can provide either format and things "just work". Thanks for any advice.
Yes, it's a DER stream encoded with Base64. Note though, in addition to striping both BEGIN and END markers, in case of RSA key format you also need to strip any flags that may be inserted between the BEGIN marker and the encoded data. Only the remaining part can be successfully Base64 decoded. It appears that you feed the full certificate file to the decoder and that needs fixing.
... I would like to convert PEM files to DER files automatically within the program.
In July 2014, a PEM Pack was provided for the Crypto++ library. The PEM Pack is a partial implementation of message encryption which allows you to read and write PEM encoded keys and parameters, including encrypted private keys. The additional files include support for RSA, DSA, EC, ECDSA keys and Diffie-Hellman parameters.
Its an add-on to the library, and not part of the library proper. You download a ZIP and add five source files to the library. Then you build the library (Crypto++ automatically picks them up). The ZIP contains five additional source files, a script to create test keys using OpenSSL, a C++ program to test reading and writing the keys, and a script to verify the keys written by Crypto++ using OpenSSL.
Here's how you would use it:
CryptoPP::RSA::PrivateKey pk;
CryptoPP::FileSource file("<rsa-key-file.pem>", true);
CryptoPP::PEM_Load(file, pk);
CryptoPP::AutoSeededRandomPool prng;
bool = pk.Validate(prng, 3);
if (! valid)
throw ...
If the keys is encrypted, then here's how you would load it. The PEM Pack re-implement's OpenSSL's EVP_BytesToKey, so the key derivation will work and you can interop:
CryptoPP::RSA::PrivateKey pk;
CryptoPP::FileSource file("<rsa-key-file.pem>", true);
std::string pass = "<super secret password>";
CryptoPP::PEM_Load(file, pk, pass.data(), pass.size());
CryptoPP::AutoSeededRandomPool prng;
bool = pk.Validate(prng, 3);
if (! valid)
throw ...
There's also a PEM_Save, so you can write the keys directly from Crypto++. For example:
// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...;
CryptoPP::FileSink file("<rsa-key-file.pem>", true);
CryptoPP::PEM_Save(file, pk);
And PEM_Save for an encrypted key (or key you intend to encrypt):
// Generate it or load it from somewhere
CryptoPP::RSA::PrivateKey pk = ...;
CryptoPP::FileSink file("<rsa-key-file.pem>", true);
std::string pass = "<super secret password>";
CryptoPP::PEM_Save(file, pk, "AES-128-CBC", pass.data(), pass.size());
PEM_Load does not need an algorithm because its encoded in the encapsulated header. PEM_Save needs an algorithm because there is no default algorithm.
I know this is an old question but other's might find this useful. Once you strip the markers you're left with the 'inner' key material. According to http://www.cryptopp.com/wiki/Keys_and_Formats#BER_and_DER_Encoding you can use BERDecodePrivateKey to load this. So, to load an openssl key that has had its markers stripped you can do something like
bool LoadKey(RandomNumberGenerator& rng, const std::string& file,
RSA::PrivateKey& key)
{
ByteQueue q;
FileSource KeyFile(file.c_str(), true, new Base64Decoder);
KeyFile.TransferTo(q);
key.BERDecodePrivateKey(q,false,0); // last 2 params unused
return key.Validate(rng, 2);
}

crypto++ RSA and "invalid ciphertext"

Well, I've been going through my personal hell these days
I am having some trouble decrypting a message that was encrypted using
RSA and I'm always failing with a "RSA/OAEP-MGF1(SHA-1): invalid
ciphertext"
I have a private key encoded in base64 and I load it:
RSA::PrivateKey private_key;
StringSource file_pk(PK,true,new Base64Decoder);
private_key.Load( file_pk );
I then proceed to decode the message by doing:
RSAES_OAEP_SHA_Decryptor decryptor(private_key);
AutoSeededRandomPool rng;
string result;
StringSource(ciphertext, true,
new PK_DecryptorFilter(rng, decryptor,
new StringSink(result)
)
);
As far as I can tell, the message should be being parsed without any
problems. ciphertext is an std::string, so no \0 at the end that could
do something unexpected.
I just though of something, and what if the private key is incorrect
but can be loaded anyway without throwing a BER decode error. What
would that throw when decrypting?
Hope that anyone can shed some light on this.
Cheers
If the key was actually corrupted, the Load function should have failed. However you can ask the key to self-test itself, which should detect any corruption, by calling Validate, like:
bool key_ok = private_key.Validate(rng, 3);
The second parameter (here, 3) specifies how much checking to be done. For RSA, this will cause it to run all available tests, even the slow/expensive ones.
Another reason the decoding might fail is if the key simply is not the one that was used to encrypt the original message.
Obviously the ciphertext input must be completely identical to what was originally produced on the encrypting side. For debugging, one good way to check this would be to feed the ciphertext at both sides into a hash function (conveniently already available to you, of course) and comparing the outputs. If you hex or base64 encoded the ciphertext for transmission you must undo that before you give it to the RSA decryptor.