Crypto++ generating AES key to a file - c++

I generate key to a file using the following function
std::filesystem::path create_key(std::filesystem::path folder_path)
{
CryptoPP::AutoSeededRandomPool prng;
CryptoPP::byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));
std::cout << "Size of key : " << sizeof(key) << std::endl;
std::cout << "Key before hex encode : " << (CryptoPP::byte*)&key << std::endl;
std::filesystem::path key_path = folder_path.concat("\key.aes");
// Key hex encoded to file
CryptoPP::StringSource key_s((CryptoPP::byte*)&key, sizeof(key), true,
new CryptoPP::HexEncoder(
new CryptoPP::FileSink(key_path.c_str())));
std::cout << key_path << "\n" << std::endl;
return key_path;
}
I use same function with few modifications for IV
I get the following results:
Size of key : 16
Key before hex encode : %
"C:\\Users\\User\\Desktop\\New folder\\key.aes"
Size of IV : 16
IV before hex encode : á▀┼┘ÅP⌐ûG→.JW╓‼Ñg79▓─G
"C:\\Users\\User\\Desktop\\New folder\\iv.aes"
Obviously after encoding the results look more readable ,
Does the key should use this characters ?
How can I read the the key and iv using crypto++
I have tried reversing the function :
CryptoPP::FileSource key(key_path.c_str(), sizeof(key), true,
new CryptoPP::HexDecoder(
new CryptoPP::StringSink((CryptoPP::byte*)&key),key_path.c_str()));
And use it by loading keys and IV but it didn't worked
I checked the key.aes file and found out it's created in ANSI encoding which make difference in few characters is there a way to make it utf-8
Console prints : ╢╘r#|ÿ┴♀[ÉB!±L↨SXêu:▄
Key.aes file : ¶Ôr#|˜Á[B!ñLS
converting key.aes file to utf-8 results : ¶Ôr#|˜Á[B!ñLS

This function is valid and works ,
No changes need to be added in my scenario.

Related

Encrypt and Decrypt a message using raw RSA algorithm in Crypto++?

I am using Crypto++ library for cryptography related works. And sub-part of task is to encrypt and decrypt a text. The message can be up to 256 character long containing alphanumeric number spaces dot and special characters.
This piece of code is working for text length is less than or equal to 8. But after that it fails to decrypt the encrypted text.
// g++ -std=c++1y crypto.cpp -I /home/shravan40/cryptopp/build -lcryptopp
#include <iostream>
#include <cryptopp/rsa.h>
#include <cryptopp/integer.h>
#include <cryptopp/osrng.h>
int main(){
// Keys
CryptoPP::Integer n("0xbeaadb3d839f3b5f"), e("0x11"), d("0x21a5ae37b9959db9");
CryptoPP::RSA::PrivateKey privKey;
privKey.Initialize(n, e, d);
CryptoPP::RSA::PublicKey pubKey;
pubKey.Initialize(n, e);
// Encryption
std::string message = "Shravan Kumar";
CryptoPP::Integer m((const byte *)message.data(), message.size());
std::cout << "m: " << m << std::endl;
// m: 126879297332596.
CryptoPP::Integer c = pubKey.ApplyFunction(m);
std::cout << "c: " << std::hex << c << std::endl;
// c: 3f47c32e8e17e291h
// Decryption
CryptoPP::AutoSeededRandomPool prng;
CryptoPP::Integer r = privKey.CalculateInverse(prng, c);
std::cout << "r: " << std::hex << r << std::endl;
// r: 736563726574h
std::string recovered;
recovered.resize(r.MinEncodedSize());
r.Encode((byte *)recovered.data(), recovered.size());
std::cout << "recovered: " << recovered << std::endl;
// recovered: Expected : (Shravan Kumar), Received -> y5��dqm0
return 0;
}
Richard Critten is correct in his comment that usually hybrid encryption is used (an asymmetric cipher such as RSA with a symmetric cipher such as AES).
For these kind of insecure examples though you are usually simply required to split up the plaintext into parts the same size as the modulus n. So in your case just put every 8 bytes / characters together and use it for a (big endian) number. As the input seems to be ASCII the highest bit of those 8 bytes will always be set to zero, so you should not have any problems encrypting/decrypting. The input for RSA must of course always be less than n.
You may of course have to think up a smart way of handling the last part of the string.
Notes:
In case it hasn't been told (yet): raw RSA without padding is not secure either. So it is not just the key size that would be a problem if this example would be implemented in the field.
I haven't got a clue what you're doing with regard to decryption. You should have a look at your textbook again I suppose.
Integer m((const byte *)message.data(), message.size());
If you use message.size()+1, then the message will include the trailing NULL. You can use it during decryption to determine where the recovered string ends. Otherwise, you are going to need to track length of the message.
You might also be interested in Raw RSA from the Crypto++ wiki. But as Maarten cautined, its tricky to get right and build into a scheme.
You might consider something using RSA encryption with OAEP or PKCS v1.5 padding. Also see RSA Encryption Schemes on the Crypto++ wiki.
I believe this is undefined behavior:
std::string recovered;
recovered.resize(r.MinEncodedSize());
r.Encode((byte *)recovered.data(), recovered.size());
I think you need to use &recovered[0] to get the non-const pointer. It may be causing your problem.

Decryption results in gibberish with Rijndael and 256 block size [duplicate]

This question already has an answer here:
256-bit Rijndael blocksize?
(1 answer)
Closed 7 years ago.
so i have some old messages encrypted with this old code:
'the ecryption algorithm with specific settings
Dim myRijndael As New RijndaelManaged
myRijndael.Padding = PaddingMode.Zeros
myRijndael.Mode = CipherMode.CBC
myRijndael.KeySize = 256
myRijndael.BlockSize = 256
'declared byte arrays for the message string and the key and IV for the encryption algorithm
Dim encrypted() As Byte
Dim toEncrypt() As Byte
Dim key() As Byte
Dim IV() As Byte
'populating the arryas with the needed bytes for the encryption algorithm
key = System.Text.Encoding.ASCII.GetBytes(prm_key)
IV = System.Text.Encoding.ASCII.GetBytes(prm_iv)
'the actual instance of the ecryption algorithm
Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)
'streams for the encrypted byte array
Dim msEncrypt As New MemoryStream()
Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
toEncrypt = System.Text.Encoding.ASCII.GetBytes(text_to_encrypt)
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
'make sure we have all the blocks
csEncrypt.FlushFinalBlock()
'turn encrypted stream into byte array
encrypted = msEncrypt.ToArray()
'return a base 64 string so we can upload it to the server
Return (Convert.ToBase64String(encrypted))
and i am trying to decrypt it with Crypto++
this is the code that i came up with:
std::string coded = "pCyWPA5Enc3F0NAkowrt206brSfMrOgKMTXI1pKhCUY=";
//std::string coded = "F9uvtbK3Ue67Gbe9si5yvDn8a50bYnTovjfWali+Xjo=";
std::string coded2;
std::string ciphertext;
std::string decryptedtext;
CryptoPP::StringSource sss(coded, true,
new CryptoPP::Base64Decoder(
new CryptoPP::StringSink(ciphertext)
) // Base64Decoder
); // StringSource
CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ),CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING);
stfDecryptor.Put( reinterpret_cast<const unsigned char*>( ciphertext.c_str() ), ciphertext.size() );
stfDecryptor.MessageEnd();
//
// Dump Decrypted Text
//
std::cout << "Decrypted Text: " << std::endl;
std::cout << decryptedtext;
std::cout << std::endl << std::endl;
but all i get in return is gibberish. The padding modes are set, the key is correct. I'm out of ideas.
The commented out "coded" string actually get decrypted, but it was encrypted with c++ and crypto++. The text is identical. so why are the Base64 encrypted stings different?
Im thinking that maybe since VB code encrypted bytes in ASCII that that might be the issue. but i don't know how to make crypto++ use ASCII encoding.
Can someone please point out the issue here?
AES uses a 128 bit block size. The VB code uses Rijndael with 256 bit block size.

Creation of ECDSA private key given curve and private exponent?

I am new to cryptopp and have been struggling for a while with the creation of private keys for ECDSA signing.
I have a hex encoded private exponent E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB. This is stored as a string.
I want to use this to sign a text block using ECDSA. My code looks a bit like this
string Sig::genSignature(const string& privKeyIn, const string& messageIn)
{
AutoSeededRandomPool prng;
ECDSA<ECP, SHA256>::PrivateKey privateKey;
privateKey.AccessGroupParameters().Initialize(ASN1::secp256r1());
privateKey.Load(StringSource(privKeyIn, true, NULL).Ref());
ECDSA<ECP, SHA256>::Signer signer(privateKey);
// Determine maximum size, allocate a string with that size
size_t siglen = signer.MaxSignatureLength();
string signature(siglen, 0x00);
// Sign, and trim signature to actual size
siglen = signer.SignMessage(prng, (const byte *) messageIn.data(), (size_t) messageIn.length(), (byte*)signature.data());
signature.resize(siglen);
cout << signature.data() << endl;
return signature;
}
This code generates the following error in Visual studio on the when I try to do privateKey.load(...)
First-chance exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.
Unhandled exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.
I am guessing I am doing something a bit stupid... any help would be great???
PS I had a similar issue using ECDH for GMAC generation but got round this by saving the key as a SECByteBlock but this 'trick' doesnt seem to work in this case.
DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr ...
You have a private exponent, and not a private key. So you should not call Load on it. That's causing the Crypto++ BERDecodeErr exception.
The answer is detailed on the ECDSA wiki page, but its not readily apparent. You need to perform the following to initialize the privateKey given the curve and exponent::
string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
exp.insert(0, "0x");
Integer x(exp.c_str());
privateKey.Initialize(ASN1::secp256r1(), x);
Prepending the "0x" ensures the Integer class will parse the ASCII string correctly. You can also append a "h" character to the string. You can see the parsing code for Integer class at Integer.cpp around line 2960 in the StringToInteger function.
Here's another way to do the same thing:
string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
HexDecoder decoder;
decoder.Put((byte*)exp.data(), exp.size());
decoder.MessageEnd();
Integer x;
x.Decode(decoder, decoder.MaxRetrievable());
privateKey.Initialize(ASN1::secp256r1(), x);
The HexDecoder will perform the ASCII to binary conversion for you. The buffer held by the HexDecoder will then be consumed by the Integer using its Decode (BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED) method.
And here is another way using HexDecoder (Crypto++ is as bad as scripting languages at times :)...
string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
StringSource ss(exp, true /*punpAll*/, new HexDecoder);
Integer x;
x.Decode(ss, ss.MaxRetrievable());
privateKey.Initialize(ASN1::secp256r1(), x);
After initializing the key, you should validate it:
bool result = privateKey.Validate( prng, 3 );
if( !result ) { /* Handle error */ }
This will output binary data:
cout << signature.data() << endl;
If you want something printable/readable, run it though a Crypto++ HexEncoder.
for others looking for this later
string genSignature(const string& privKeyIn, const string& messageIn)
{
CryptoPP::Integer secretNumber(genSecretNumber(privKeyIn, messageIn));
AutoSeededRandomPool secretNumberGenerator;
if (encryptBase::debug)
{
cout << "secret number: " << secretNumber << endl;
}
SecByteBlock message(convertHexStrToSecByteBlock(messageIn));
ECDSA<ECP, SHA256>::PrivateKey privateKey;
string exp(privKeyIn);
exp.insert(0, "0x");
Integer x(exp.c_str());
privateKey.Initialize(ASN1::secp256r1(), x);
AutoSeededRandomPool prng;
if (!privateKey.Validate(prng, 3))
{
cout << "unable to verify key" << endl;
return "failed to verify key";
}
ECDSA<ECP, SHA256>::Signer signer(privateKey);
size_t siglen = signer.MaxSignatureLength();
string signature(siglen, 0x00);
siglen = signer.SignMessage(secretNumberGenerator, message.BytePtr(), message.size(), (byte*)signature.data());
signature.resize(siglen);
string encoded;
HexEncoder encoder;
encoder.Put((byte *) signature.data(), signature.size());
encoder.MessageEnd();
word64 size = encoder.MaxRetrievable();
if (size)
{
encoded.resize(size);
encoder.Get((byte*)encoded.data(), encoded.size());
}
return encoded;
}

How to use a custom key in Crypto++

I have a question referring to the encryption code in this question:
Crypto++ encrypt and decrypt in two different c++ programs
If I want to use a custom key/iv, how can I do this?
If I want to use a custom key/iv, how can I do this?
Just plug it into a cipher with a mode. There are plenty of modes to choose from, but you should use an authenticated encryption mode like EAX, CCM or GCM. See Category:Mode for discussion of the modes in Crypto++.
The code below takes a password or secret, keys a cipher, and then encrypts and encodes a message. Next, it decodes the encrypted message. Finally it prints some of the parameters.
try {
// KDF parameters
string password = "Super secret password";
unsigned int iterations = 15000;
char purpose = 0; // unused by Crypto++
// 32 bytes of derived material. Used to key the cipher.
// 16 bytes are for the key, and 16 bytes are for the iv.
SecByteBlock derived(32);
// KDF function
PKCS5_PBKDF2_HMAC<SHA256> kdf;
kdf.DeriveKey(derived.data(), derived.size(), purpose, (byte*)password.data(), password.size(), NULL, 0, iterations);
// Encrypt a secret message
string plaintext = "Attack at dawn", ciphertext, recovered;
// Key the cipher
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), 16, derived.data() + 16, 16);
AuthenticatedEncryptionFilter ef(encryptor, new StringSink(ciphertext));
ef.Put((byte*)plaintext.data(), plaintext.size());
ef.MessageEnd();
// Key the cipher
EAX<AES>::Decryption decryptor;
decryptor.SetKeyWithIV(derived.data(), 16, derived.data() + 16, 16);
AuthenticatedDecryptionFilter df(decryptor, new StringSink(recovered));
df.Put((byte*)ciphertext.data(), ciphertext.size());
df.MessageEnd();
// Done with encryption and decryption
// Encode various parameters
HexEncoder encoder;
string key, iv, cipher;
encoder.Detach(new StringSink(key));
encoder.Put(derived.data(), 16);
encoder.MessageEnd();
encoder.Detach(new StringSink(iv));
encoder.Put(derived.data() + 16, 16);
encoder.MessageEnd();
encoder.Detach(new StringSink(cipher));
encoder.Put((byte*)ciphertext.data(), ciphertext.size());
encoder.MessageEnd();
// Print stuff
cout << "plaintext: " << plaintext << endl;
cout << "key: " << key << endl;
cout << "iv: " << iv << endl;
cout << "ciphertext: " << cipher << endl;
cout << "recovered: " << recovered << endl;
}
catch(CryptoPP::Exception& ex)
{
cerr << ex.what() << endl;
}
A run of the program produces the following output.
$ ./cryptopp-test.exe
plaintext: Attack at dawn
key: 7A8C7732898FB687669CB7DBEFBDD789
iv: 0AA980BABE72797E415C9B8979BF30EF
ciphertext: 197D0BD1A12577393AD1B1696B75D0FC6B8A142CF15B5F887AA965CE75F0
recovered: Attack at dawn
Even better, use an Integrated Encryption Scheme. Crypto++ provides two of them. The first is Elliptic Curve Integrated Encryption Scheme which operates over fields of elliptic curse. The second is Discrete Logarithm Integrated Encryption Scheme, which operates over the field of integers.
There's a number of non-obvious reason why its "even better", but the big one is its IND-CCA2. Other, more practical ones include: you can't reuse a security context because correct use is built into the system; and padding has been removed which greatly simplifies proofs and avoids potential oracles. The system is also predicated on Discrete Logs, which makes it a Diffie-Hellman based problem and its believed to be hard everywhere.

How to input string for encryption using arc4?

I was using the Crypto++ library to do my arc4 encryption. Reference from here but not fully explained: http://www.cryptopp.com/wiki/Stream_Cipher.
The following is my code:
string key = "key";
string msg = "hello";
ARC4 arc4((byte*)key.c_str(), sizeof((byte*)key.c_str()));
arc4.ProcessData((byte*)msg.c_str(), (byte*)msg.c_str(), sizeof((byte*)msg.c_str()));
arc4.ProcessData((byte*)msg.c_str(), (byte*)msg.c_str(), sizeof((byte*)msg.c_str()));
cout << msg << endl;
My message after encrypt and decrypt which is totally garbage then i could not read.
not decrypted back to "hello" in short.
So how can I encrypt and decrypt message with key as above?
Two problems. First, you need to use the string's size(), and not sizeof(). Second, you need to reset the arc4 object when decrypting. Otherwise, the cipher's state is continued from the previous encryption.
string key = "key";
string msg = "hello";
ARC4 arc4((byte*)key.data(), key.size());
arc4.ProcessData((byte*)msg.data(), (byte*)msg.data(), msg.size());
// Reset state
arc4.SetKey((byte*)key.data(), key.size());
arc4.ProcessData((byte*)msg.data(), (byte*)msg.data(), msg.size());
cout << msg << endl;