0

I use Crypto++ in C++ to encrypt a string. Now I want to decrypt this ciphertext with C# but it doesn't work.

My C++ Code to encrypted the string is as follow:

string encrypt(string data)
{
  // Key and IV setup
  std::string key = "0123456789abcdef";
  std::string iv = "aaaaaaaaaaaaaaaa";

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

  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;
}

To decrypt the code in C++ I can use this code

CryptoPP::AES::Decryption aesDecryption((byte *)key.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, (byte *)iv.c_str() );

CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedtext ) );
stfDecryptor.Put( reinterpret_cast<const unsigned char*>( result_string.c_str() ), result_string.size() );
stfDecryptor.MessageEnd()

But I need to decrypt the code in a C# application and therefor I use this methode:

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;

    // 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;
}

static byte[] GetBytes(string str)
{
  byte[] bytes = new byte[str.Length * sizeof(char)];
  System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
  return bytes;
}

If I try to decrypt the ciphertext, I get the message, that the specified initialization vector does not match the block size for this algorithm.

I do not know why this doesn't work and I hope that someone can help me.

n-3
  • 71
  • 2
  • 11
  • Have a look at the top 2 answers to this question: http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp – Rik Dec 09 '14 at 08:50
  • I try also your hint, but when I use the decryption with my code I get also the error that the iv is not correct. – n-3 Dec 09 '14 at 10:20
  • Are you sure you're using the same IV as when you're encrypting?Have you tried generating an IV using `RijndaelManaged.GenerateIV()` and using that? – Rik Dec 09 '14 at 10:25
  • I think so. You can see the key and iv in the first codeblock of my post. In the last one I'm using a config file to store the key: Why should I generate the IV? I think I must use the one from the C++ application. – n-3 Dec 09 '14 at 10:41
  • The IV should be the same as the one used in encryption, but it is supposed to be (pseudo-) random, so `"aaaaaaaaaaaaaaaa"` isn't terribly good. – Rik Dec 09 '14 at 10:57
  • Are you sure you are using the same string encoding as on the C++ end? – Rik Dec 09 '14 at 10:57
  • My current key and iv are just for testing to ensure, that the encryption and decryption works. But it doesn't. Maybe there is a problem in the encoding but I don't get it. – n-3 Dec 09 '14 at 11:16
  • Try setting your IV like this: `rijAlg.IV = new byte[]{ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 };` which ensures the IV has exactly 128 bits. – Rik Dec 09 '14 at 11:19
  • Perfect! This works. Now I have to figure out, why the lenght of the encrypted string is wrong. Maybe I write the file wrong, because I don't think that there is a problem to read the file with File.ReadAllBytes(path) and use it as the ciphertext. – n-3 Dec 09 '14 at 11:59

1 Answers1

0

Try setting your IV like this:

rijAlg.IV = new byte[]{ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 }; 

which ensures the IV has exactly 128 bits (and all a's, as in your c++ sample).

If this works, make sure that the IV is read correctly from the configuration. The value of ConfigurationManager.AppSettings["aes_iv"] is probably either empty, or does not have a length of 16.

Rik
  • 28,507
  • 14
  • 48
  • 67