2
Vote

CryptoStream in WP 8.1 RT

description

I use following code in a common library for WP8.1 RT and iOS (Android is not yet been tested).
Encoding work fine in all platforms, but in WP app, decoding always fail with an exception "Data error (cyclic redundancy check). (Exception from HRESULT: 0x80070017)".
A stream encoded by WP is correctly decoded by iOS, of course, a stream encoded by iOS is correctly decoded by iOS.
The only way that I found for to make decoding working in WP is read all encoded stream in a buffer and use CryptographicEngine.Decrypt instead of CryptoStream as show in DecodeWP method.
Is that a CryptoStream implementation bug or a limitation of WinRT runtime?
There is a way to use CryptoStream method also in WP app? Input stream can be very huge, and I don't want load it all in memory.

Thanks in advance
FP
private byte[] GetHash(string data)
{
    IHashAlgorithmProvider objAlgProv = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Md5);
    return objAlgProv.HashData(System.Text.UTF8Encoding.UTF8.GetBytes(data));
}

public async Task Encode(System.IO.Stream input, System.IO.Stream output, string password)
{
    byte[] keyHash = GetHash(password);
    ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
    ICryptographicKey symetricKey = aes.CreateSymmetricKey(keyHash);

    using (CryptoStream cryptoStream = new CryptoStream(output, WinRTCrypto.CryptographicEngine.CreateEncryptor(symetricKey), CryptoStreamMode.Write))
    {
        await input.CopyToAsync(cryptoStream);
    }
}

public async Task Decode(System.IO.Stream input, System.IO.Stream output, string password)
{
    try
    {
        byte[] keyHash = GetHash(password);
        ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
        ICryptographicKey symetricKey = aes.CreateSymmetricKey(keyHash);

        using (CryptoStream cryptoStream = new CryptoStream(input, WinRTCrypto.CryptographicEngine.CreateDecryptor(symetricKey), CryptoStreamMode.Read))
        {
            await cryptoStream.CopyToAsync(output);
        }

    }
    catch (Exception ex)
    {
        throw ex; //Data error (cyclic redundancy check). (Exception from HRESULT: 0x80070017)
    }
}

public async Task DecodeWP(System.IO.Stream input, System.IO.Stream output, string password)
{
    byte[] keyHash = GetHash(password);
    ISymmetricKeyAlgorithmProvider aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
    ICryptographicKey symetricKey = aes.CreateSymmetricKey(keyHash);

    byte[] inputBuffer = new byte[input.Length];
    input.Read(inputBuffer, 0, inputBuffer.Length);
    byte[] outputBuffer = WinRTCrypto.CryptographicEngine.Decrypt(symetricKey, inputBuffer, null);
    await output.WriteAsync(outputBuffer, 0, outputBuffer.Length);
}

comments

AArnott wrote Nov 28, 2014 at 8:48 PM

First observation: you shouldn't use MD5 to convert a password to a cryptograph key. You should use a secure key-derivation function (also available in PCLCrypto).

Can WP8.1 decode a stream also encoded by WP8.1? Since WinRT is missing streaming cryptographic APIs, I had to implement padding myself, and I very well may have a bug there. If I do, it seems decryption would fail no matter who encrypted it. Is that what you're seeing?

Also consider moving this discussion to https://github.com/aarnott/pclcrypto. This site is dead and has been moved to that new URL.

MrWolfPST wrote Nov 28, 2014 at 9:59 PM

Hi, thank you for response
Yes you are right, I will change the key generation from password in the final version of the apps, I have not found a valid example and then I have temporarily chosen MD5.
Again, yes you are right, also stream encoded by WP fails on decodification.
If it can be usefull, in my first implementation I have used AesEcbPkcs7, and both encoding that decoding work fine in WP app, but I was obliged to change because AesCbcPkcs7 is the only implemented by iOS.
Now I copy my question on project's github page, if I and my team can help you in some way to find the problem, don't esitate contact me.

Thank you angain, and compliments for the excelent work.
Regards
FP

AArnott wrote Nov 30, 2014 at 5:15 AM

Good info. Especially the part about how Ecb works but Cbc doesn't. Can you please add it to the github issue?