Translating AesManaged to new universal app CryptographicEngine

好久不见. 提交于 2019-12-11 10:31:19

问题


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

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



回答2:


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



来源:https://stackoverflow.com/questions/32137015/translating-aesmanaged-to-new-universal-app-cryptographicengine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!