1

我正在尝试通过从 C# 程序到 C++ 程序的 tcp 连接发送加密字符串。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();
        }

这是使用 Crypto++ 解密的 C++ 端

     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();
4

1 回答 1

1

您的问题是由于两件事中的一件,也许两者兼而有之。

  1. C# 流编写器没有写出空字节。当 C++ 代码读入数据时,字符串不是以空值结尾的。我尚未测试您提供的代码,但这似乎是预期的行为。

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

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

我不太了解这两种实现的内部结构,无法知道填充的默认方法是什么,或者它们是否将其留给用户。

于 2011-12-05T20:27:35.880 回答