0

I'm trying to decrypt an encrypted base64-encoded string with C#. I have encrypted the string using the following online tool: http://encode-decode.com/aes256-encrypt-online/

For example, when I encrypt the text 'abcd' with the key 'zzzz', I get the following base64 string: 3crNVWxmpkE+UjT3lPoi0g==

What I'm not getting is... this is only 16 bytes of data, while the IV itself should already be 16 bytes. As a result, I'm trying to add padding, but the cypher is complaining about the padding. I feel like I'm missing something. See my decryption function below:

public static string Decrypt(string cipherText, string keyString)
{
    int Keysize = 256;
    var key = Encoding.UTF8.GetBytes(keyString);
    if (key.Length < 16)
    {
        var keycopy = new byte[16];
        Array.Copy(key, 0, keycopy, 15 - key.Length, key.Length);
        key = keycopy;
    }
    // Get the complete stream of bytes that represent:
    // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
    var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
    // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
    var iv = cipherTextBytesWithSaltAndIv.Take(8).ToArray();
    if (iv.Length < 16)
    {
        var ivcopy = new byte[16];
        Array.Copy(iv, 0, ivcopy, 15 - iv.Length, iv.Length);
        iv = ivcopy;
    }

    // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
    var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip(8).Take(cipherTextBytesWithSaltAndIv.Length - 8).ToArray();
    if (cipherTextBytes.Length < 16)
    {
        var cipherTextBytescopy = new byte[16];
        Array.Copy(cipherTextBytes, 0, cipherTextBytescopy, 15 - cipherTextBytes.Length, cipherTextBytes.Length);
        cipherTextBytes = cipherTextBytescopy;
    }

    try
    {
        using (var rijndaelManaged = new RijndaelManaged { Key = key, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
        using (var memoryStream = new MemoryStream(cipherTextBytes))
        using (var cryptoStream = new CryptoStream(memoryStream,
                       rijndaelManaged.CreateDecryptor(key, iv),
                       CryptoStreamMode.Read))
        {
            return new StreamReader(cryptoStream).ReadToEnd();
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
        return null;
    }
    // You may want to catch more exceptions here...
}
Salih Karagoz
  • 2,189
  • 2
  • 22
  • 35
Bart van der Drift
  • 1,287
  • 12
  • 30
  • 2
    Why assume the IV is at the beginning? Perhaps the IV is always zero and is implicit. Since the web page includes no documentation perhaps it's not a good source of test data. – President James K. Polk Jul 13 '17 at 11:58
  • 1
    The IV is critical to CBC and its not stated what it is, nor what padding is used nor how the key is expanded to a correct length. Better to find some C# code that produces base64 ciphertext and play with that. – Alex K. Jul 13 '17 at 11:59
  • The problem is that our customer is sending me the encrypted data, and refers to this tool to say "look, they can decrypt my string, so you should be able to do it too" – Bart van der Drift Jul 13 '17 at 12:03
  • How are they providing you with the IV? – Alex K. Jul 13 '17 at 12:04
  • They are not :-( – Bart van der Drift Jul 13 '17 at 12:09
  • 1
    Well as you say the output of that tool does not seem to be long enough to include the IV, your going to have to ask the 3rd party what IV they are using. – Alex K. Jul 13 '17 at 12:25
  • 1
    AES don't define how the IV should be passed along together with the message, so don't expect it to add that to the message for you (if it did, it would be in a proprietary way anyway). But - AES DO expect a binary key of fixed length - not an arbitrary ASCII string. The site don't state how it makes that key from the text string - 'zzzz' is not a valid AES key. – Ebbe M. Pedersen Jul 13 '17 at 14:04

0 Answers0