发送c# AES加密字符串到CyptoPP c++程序解密

Send C# AES encrypted string to CyptoPP C++ program to decrypt

本文关键字:CyptoPP c++ 程序 解密 字符串 AES 加密 发送      更新时间:2023-10-16

我试图通过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();

你的问题是两件事中的一件,也许两者都有。

  1. c#流编写器没有输出空字节。当c++代码读入数据时,字符串不会以空结束。我还没有测试你给出的代码,但这似乎是预期的行为。

  2. 假设的填充方法(或缺乏填充方法)可能在c#实现和Crypto++实现之间有所不同。CBC模式下的AES只能对块大小的倍数进行加密或解密。在AES中,块大小为128位或16字节

维基百科对各种分组密码模式有很好的解释。CBC的典型填充是PKCS7,在这里有描述。

我对这两个实现的内部都不太了解,不知道填充的默认方法是什么,或者他们是否把这个留给用户。