Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Security.Cryptography vs PCLCrypto

We are in the process of gutting a lot of shared functionality in our system and porting it to PCL libraries. I am having an issue using PCLCrypto. I am taking some existing data in our database, and trying to decrypt it with the same algorithm. I get the value back, but there are 16 extra bytes at the end that are just garbage.

See Code below: Old Algorithm using System.Security.Cryptography

public static string SymmetricEncrypt(this string plaintext, string key, SymmetricAlgorithm algorithm)
{
    byte[] keyBuffer = Convert.FromBase64String(key.Hash(HashAlgorithm.MD5));
    byte[] plainTextBuffer = Encoding.UTF8.GetBytes(plaintext);

   var symmetricAlgorithm = new AesCryptoServiceProvider();
    symmetricAlgorithm.Key = keyBuffer;
    symmetricAlgorithm.Mode = CipherMode.ECB;

    var encryptor = symmetricAlgorithm.CreateEncryptor();
    byte[] cipherBuffer = encryptor.TransformFinalBlock(plainTextBuffer, 0, plainTextBuffer.Length);
    symmetricAlgorithm.Clear();

    return Convert.ToBase64String(cipherBuffer);
}


 public static string SymmetricDecrypt(this string cipherText, string key, SymmetricAlgorithm algorithm)
    {
        byte[] keyBuffer = Convert.FromBase64String(key.Hash(HashAlgorithm.MD5));
        byte[] cipherTextBuffer = Convert.FromBase64String(cipherText);
        var symmetricAlgorithm = new AesCryptoServiceProvider();
        symmetricAlgorithm.Key = keyBuffer;
        symmetricAlgorithm.Mode = CipherMode.ECB;

        var decryptor = symmetricAlgorithm.CreateDecryptor();
        byte[] plainTextBuffer = decryptor.TransformFinalBlock(cipherTextBuffer, 0, cipherTextBuffer.Length);
        symmetricAlgorithm.Clear();

        return Encoding.Default.GetString(plainTextBuffer);
    }

Decryption using PCLCrypto

public static string SymmetricDecrypt(this string cipherText, string key, SymmetricAlgorithm algorithm) {
    byte[] keyBuffer = Convert.FromBase64String(key.Hash(HashAlgorithm.MD5));
    byte[] cipherTextBuffer = Convert.FromBase64String(cipherText);

    ISymmetricKeyAlgorithmProvider symmetricAlgorithm = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(PCLCrypto.SymmetricAlgorithm.AesEcb);

    var symmetricKey = symmetricAlgorithm.CreateSymmetricKey(keyBuffer);
    var decryptor = WinRTCrypto.CryptographicEngine.CreateDecryptor(symmetricKey);
   byte[] plainTextBuffer = decryptor.TransformFinalBlock(cipherTextBuffer, 0, cipherTextBuffer.Length);
    return UTF8Encoding.UTF8.GetString(plainTextBuffer, 0, plainTextBuffer.Length);
}

Using the old version: plainTextBuffer is 16 bytes, new version it is 32 bytes.

Help!

like image 488
Chris Kooken Avatar asked Aug 19 '15 19:08

Chris Kooken


1 Answers

This sounds like a padding issue.

Looking at the source for the base class SymmetricAlgorithm in .NET, which is the base of the AesCryptoServiceProvider, the default padding is PaddingMode.PKCS7. You don't appear to have defined a padding mode, so I would assume the default still applies.

Whilst I haven't used the PCLCrypto library before, having a quick look at github there are a couple of AesEcb algorithms: AesEcb and AesEcbPkcs7. The absence of a padding mode from the name of AesEcb would imply to me that it has no padding (and thus hasn't removed any padding), which would be the equivalent of PaddingMode.None in the .NET libraries.

Try using the PCLCrypto.SymmetricAlgorithm.AesEcbPkcs7 algorithm in PCLCrypto and see if this removes the padding that you are seeing at the end of the output.

Update

I've just tested this, and it appears to work correctly and remove the padding you would be seeing:

public static string SymmetricDecrypt(this string cipherText, string key, SymmetricAlgorithm algorithm) {
    byte[] keyBuffer = Convert.FromBase64String(key.Hash(HashAlgorithm.MD5));
    byte[] cipherTextBuffer = Convert.FromBase64String(cipherText);

    ISymmetricKeyAlgorithmProvider symmetricAlgorithm = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(PCLCrypto.SymmetricAlgorithm.AesEcbPkcs7);

    var symmetricKey = symmetricAlgorithm.CreateSymmetricKey(keyBuffer);
    var decryptor = WinRTCrypto.CryptographicEngine.CreateDecryptor(symmetricKey);
   byte[] plainTextBuffer = decryptor.TransformFinalBlock(cipherTextBuffer, 0, cipherTextBuffer.Length);
    return UTF8Encoding.UTF8.GetString(plainTextBuffer, 0, plainTextBuffer.Length);
}

The only change was changing the algorithm from PCLCrypto.SymmetricAlgorithm.AesEcb to PCLCrypto.SymmetricAlgorithm.AesEcbPkcs7

like image 146
nemuca Avatar answered Sep 28 '22 21:09

nemuca