问题
I have a string which I encrypt with the following mehtod in C++ using Crypto++:
std::ifstream t(filename); //File to be encrypt
std::stringstream buffer;
buffer << t.rdbuf();
ofstream combined_file2(filename2); //Encrypted file
combined_file2 << encrypt(buffer.str());
string encrypt(string data)
{
// Key and IV setup
std::string key = "0123456789abcdef";
std::string iv = "aaaaaaaaaaaaaaaa";
//Alternative
//byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE];
//memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
//memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE);
std::string plaintext = data;
std::string ciphertext;
// Create Cipher Text
CryptoPP::AES::Encryption aesEncryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte *)iv.c_str());
//Alternative
//CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
//CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length() + 1);
stfEncryptor.MessageEnd();
return ciphertext;
}
When I try to decrypt the file in my C# Application, I get the message, that the length of the data is invalid. I think that the lenght of th byte array isn't a multiple of 16, so I get the error. I try to use a padding, but it is not working right.
Here is how I decrypt the file:
string plaintext = Decrypt(File.ReadAllBytes(path));
private static string Decrypt(byte[] cipherText)
{
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
byte[] Key = GetBytes(ConfigurationManager.AppSettings["aes_key"]);
byte[] IV = GetBytes(ConfigurationManager.AppSettings["aes_iv"]);
// Declare the string used to hold the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
//rijAlg.IV = IV;
//for testing
rijAlg.IV = new byte[] { 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 };
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
How can I solve the problem? Is there any function to do the padding, or maybe padding is the wrong way?
回答1:
Based on the comment:
In C++ I save a file combined_file2 << encrypt(buffer.str()); which I read in my C# program string plaintext = Decrypt(File.ReadAllBytes(path));
I don't think embedded NULLs is causing problems from the encrypt
function since its returning a string
, and that includes an explicit length.
However, an embedded NULL and the way the file is being written to disk in C++ (or read from disk in C#) will be a problem since this will stop at the first embedded NULL: combined_file2 << encrypt(buffer.str())
.
Perhaps something like the following would be helpful:
StringSource ss(ciphertext, true /*pumpAll*/);
FileSink fs("my-encrypted-file.bin", true /*binary*/);
ss.TransferTo(fs);
If you are using a C++ stream, then use the write
method on the stream object:
ofstream combined_file2;
...
combined_file2.write(ciphertext.data(), ciphertext.size());
来源:https://stackoverflow.com/questions/27385456/aes-padding-and-writing-the-ciphertext-to-a-disk-file