Translating AesManaged to new universal app CryptographicEngine

1

I've this old code snipped that should be translated to use the new CryptographicEngine. But I'm overwhelmed by the possibilities of the new API.

Can someone plz help me?

    private AesManaged GetAes(string textkey)
    {
        var aes = new AesManaged();
        aes.IV = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        var key = System.Text.Encoding.UTF8.GetBytes(textkey);
        aes.Key = key;
        return aes;
    }

    private string DecryptValue(string input, string textkey)
    {
        var bytes = Convert.FromBase64String(input);
        var decryptedString = new StringBuilder();
        var aes = GetAes(textkey);
        var decryptor = aes.CreateDecryptor();
        using (MemoryStream msDecrypt = new MemoryStream(bytes))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    while (!srDecrypt.EndOfStream)
                    {
                        decryptedString.Append(srDecrypt.ReadLine());
                    }
                }
            }
        }
        return decryptedString.ToString();
    }

This is what I've tried so far. But there seems to be something wrong with it. I'm always getting

Exception = {System.Exception: Data error (cyclic redundancy check). (Exception from HRESULT: 0x80070017) at Windows.Security.Cryptography.Core.CryptographicEngine.Decrypt(CryptographicKey key, IBuffer data, IBuffer iv) at ...

    private string DecryptValue(string input, string textkey)
    {
        // Load the alghorithm providers
        var symmetricKeyProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);

        // Create the symmetric key that is used to encrypt the string from random keystring
        var cryptoKey = symmetricKeyProvider.CreateSymmetricKey(CryptographicBuffer.DecodeFromBase64String(textkey));

        // Decode the input Base64 string
        var buffer = CryptographicBuffer.DecodeFromBase64String(input);

        // Declare new byte array
        byte[] dectryptedBytes;

        // Decrypt the IBuffer back to byte array
        CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(cryptoKey, buffer, null), out dectryptedBytes);

        // Get string back from the byte array
        var decryptedString = Encoding.UTF8.GetString(dectryptedBytes, 0, dectryptedBytes.Length);

        // Return plain text
        return decryptedString;
    }
c#
cryptography
aes
win-universal-app
asked on Stack Overflow Aug 21, 2015 by André Fiedler • edited Aug 21, 2015 by André Fiedler

2 Answers

1

Ok, I finally I got it. If someone is interested, here's the solution:

    private string DecryptValue(string input, string textkey)
    {
        // Declare the static initialization vector
        var iv = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        // Convert the properties to required buffers
        var pwBuffer = CryptographicBuffer.ConvertStringToBinary(textkey, BinaryStringEncoding.Utf8);
        var saltBuffer = CryptographicBuffer.CreateFromByteArray(iv);
        var buffer = CryptographicBuffer.DecodeFromBase64String(input);

        // Load the alghorithm providers
        var symmetricKeyProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC");

        // Create the symmetric key that is used to encrypt the string from IV
        var cryptoKey = symmetricKeyProvider.CreateSymmetricKey(pwBuffer);

        // Decrypt the IBuffer back to byte array
        var resultBuffer = CryptographicEngine.Decrypt(cryptoKey, buffer, saltBuffer);

        // Get string back from the byte array
        var decryptedString = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, resultBuffer);

        // Return plain text
        return decryptedString;
    }
answered on Stack Overflow Aug 21, 2015 by André Fiedler
0

I made a small enhancement to my last solution. It seems that AES_CBC adds some padding to the given string if the string length isn't a multiple of the block size. [1]

The padding is a control char \u0010 that will be appended to the end of the string. So we have to remove it after decoding:

private string DecryptValue(string input, string textkey)
{
    // Declare the static initialization vector
    var iv = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    // Convert the properties to required buffers
    var pwBuffer = CryptographicBuffer.ConvertStringToBinary(textkey, BinaryStringEncoding.Utf8);
    var saltBuffer = CryptographicBuffer.CreateFromByteArray(iv);
    var buffer = CryptographicBuffer.DecodeFromBase64String(input);

    // Load the alghorithm providers
    var symmetricKeyProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC");

    // Create the symmetric key that is used to encrypt the string from IV
    var cryptoKey = symmetricKeyProvider.CreateSymmetricKey(pwBuffer);

    // Decrypt the IBuffer back to byte array
    var resultBuffer = CryptographicEngine.Decrypt(cryptoKey, buffer, saltBuffer);

    // Get string back from the byte array
    var decryptedString = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, resultBuffer);

    // Remove padding when using CBC mode
    decryptedString = decryptedString.TrimEnd("\u0010".ToCharArray());

    // Return plain text
    return decryptedString;
}

[1] https://security.stackexchange.com/a/29999

answered on Stack Overflow Aug 25, 2015 by André Fiedler • edited Mar 17, 2017 by Community

User contributions licensed under CC BY-SA 3.0