发送c# AES加密字符串到CyptoPP c++程序解密
Send C# AES encrypted string to CyptoPP C++ program to decrypt
我试图通过tcp连接从c#程序发送加密字符串到c++程序。当c++程序试图解密字符串时,它会在crypto++中崩溃。我可以在调试器中看到字符串大部分被解码,但没有正确终止。例如,如果我发送"Hello world",它会被解密为"Hello world%%@#$@#"(最后是垃圾)
下面是我加密 的方法 //Create byte arrays to hold original, encrypted, and decrypted data.
byte[] dataToEncrypt = ByteConverter.GetBytes(data);
byte[] key = new byte[16];
for (int i = 0; i < 16; ++i)
{
key[i] = 1;
}
byte[] iv = new byte[16];
for (int i = 0; i < 16; ++i)
{
iv[i] = 1;
}
RijndaelManaged myRijndael = new RijndaelManaged();
myRijndael.Key = key;
myRijndael.IV = iv;
byte[] encrypted = encryptStringToBytes_AES(data, myRijndael.Key, myRijndael.IV);
// sends the byte array via active tcp connection
_transport.SendEncryptedData(encrypted);
static byte[] encryptStringToBytes_AES(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the stream used to encrypt to an in memory
// array of bytes.
MemoryStream msEncrypt = null;
// Declare the RijndaelManaged object
// used to encrypt the data.
RijndaelManaged aesAlg = null;
try
{
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encrypto to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return msEncrypt.ToArray();
}
下面是c++端使用Crypto++
进行解密 byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ];
byte iv[ CryptoPP::AES::BLOCKSIZE ];
::memset( key, 0x01, CryptoPP::AES::DEFAULT_KEYLENGTH );
::memset( iv, 0x01, CryptoPP::AES::BLOCKSIZE );
std::string decryptedtext;
CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, iv );
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
// CRASHES IN .PUT(...)
stfDecryptor.Put( reinterpret_cast<const unsigned char*>(data ), len + 1);
stfDecryptor.MessageEnd();
你的问题是两件事中的一件,也许两者都有。
-
c#流编写器没有输出空字节。当c++代码读入数据时,字符串不会以空结束。我还没有测试你给出的代码,但这似乎是预期的行为。
-
假设的填充方法(或缺乏填充方法)可能在c#实现和Crypto++实现之间有所不同。CBC模式下的AES只能对块大小的倍数进行加密或解密。在AES中,块大小为128位或16字节
维基百科对各种分组密码模式有很好的解释。CBC的典型填充是PKCS7,在这里有描述。
我对这两个实现的内部都不太了解,不知道填充的默认方法是什么,或者他们是否把这个留给用户。