Search Unity

[Android] CryptographicException: Bad PKCS7 padding. Invalid length 0.

Discussion in 'Scripting' started by Qbit86, Sep 8, 2016.

  1. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Sometimes (but not always) I get this exception on Android device (but not in Editor), built with Unity 5.3.6f1.
    Code (csharp):
    1. CryptographicException: Bad PKCS7 padding. Invalid length 0.
    2.   at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position)
    3.   at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
    4.   at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
    5.   at System.Security.Cryptography.CryptoStream.FlushFinalBlock ()
    6.   ...
    I'm using `AesManaged { Mode = CipherMode.CFB, Padding = PaddingMode.PKCS7 }` with properly specified key and iv for symmetric cryptography.

    The code looks like:
    Code (csharp):
    1. using (var decryptor = _aes.CreateDecryptor(_aesKeyBuffer, _aesIVBuffer))
    2. using (var memoryStream = new MemoryStream())
    3. using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
    4. {
    5.     cryptoStream.Write(paddedCiphertext.Array, paddedCiphertext.Offset, paddedCiphertext.Count);
    6.     cryptoStream.Flush();
    7.     // http://stackoverflow.com/questions/18783182/aes-encrypt-memorystream-toarray-empty
    8.     cryptoStream.FlushFinalBlock();
    9.     byte[] plaintextArray = memoryStream.ToArray();
    10.     ...
    11. }
    Any ideas?
     
  2. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    When I use another approach, still get the same exception (with another trace):
    Code (csharp):
    1. CryptographicException: Bad PKCS7 padding. Invalid length 0.
    2.   at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position)
    3.   at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
    4.   at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
    5.   at System.Security.Cryptography.CryptoStream.Read (System.Byte[] buffer, Int32 offset, Int32 count)
    6.   at System.IO.BinaryReader.ReadBytes (Int32 count)
    7.   ...
    Code (csharp):
    1. using (var decryptor = _aes.CreateDecryptor(_aesKeyBuffer, _aesIVBuffer))
    2. using (var memoryStream = new MemoryStream(paddedCiphertext.Array, paddedCiphertext.Offset, paddedCiphertext.Count))
    3. using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
    4. {
    5.     using (var reader = new BinaryReader(cryptoStream))
    6.     {
    7.         byte[] plaintextArray = reader.ReadBytes(paddedCiphertext.Count);
    8.         ...
    9.     }
    10. }
    Works fine in Windows Editor. Looks like a bug in Mono crypto. Can anyone confirm this?
     
  3. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Fixed by replacing `AesManaged` with equivalent `Rijndael` (BlockSize = 16 bytes, KeySize = 32 bytes). The error has gone. Mono cryptography is just broken.

    Remind me please, why we are still stuck to out-of-date, suboptimal, and buggy version of Mono?
     
    Cambesa likes this.
  4. yurykorzun

    yurykorzun

    Joined:
    Oct 29, 2015
    Posts:
    41
    I have the same issue in 2017.3.1, works fine in 5.6.5
     
  5. yurykorzun

    yurykorzun

    Joined:
    Oct 29, 2015
    Posts:
    41
    It appears that not every encryption mode is supported by .net 2.0 subset, switching to full .net 2.0 api compatibility or choosing a different encryption mode might work.
     
    Jushik likes this.
  6. Jushik

    Jushik

    Joined:
    Oct 11, 2016
    Posts:
    6
    Same issue, but in editor too. 2018.2.10f1. But...But... My unit tests are passes: one test encrypts, another decrypts.
     
  7. Jushik

    Jushik

    Joined:
    Oct 11, 2016
    Posts:
    6
    AesCryptoServiceProvider not supported by .net 2.0 subset.
    AesManaged supported.
    I tried DES then. For DES "Bad PKCS7 padding. Invalid lengh x" exception was fixed by specifying padding in encryptor and decryptor methods for DesCryptoServiseProvider.
     
  8. Jushik

    Jushik

    Joined:
    Oct 11, 2016
    Posts:
    6
    Nope. It is not fixed. Encrypt -> Decrypt -> (change some data) -> Encrypt -> Decrypt(Bad PKCS7 Exception).
     
  9. Nickromancer

    Nickromancer

    Joined:
    Jul 31, 2016
    Posts:
    92
    I confirm the problem still exist in 2021.2.x.
     
  10. canyon_gyh

    canyon_gyh

    Joined:
    Aug 15, 2018
    Posts:
    48
    I get the other error,when do Decrypt.
    Error is : CryptographicException: Bad PKCS7 padding. Invalid length 154.
    at System.Security.Cryptography.CryptoStream.Read

    my code is:

    upload_2022-3-28_9-30-5.png

    some one say:
    Removed the call to CryptoStream.FlushFinalBlock() in the Encrypt method.
    I will try
     
    Last edited: Mar 28, 2022
  11. duong2179

    duong2179

    Joined:
    Dec 21, 2019
    Posts:
    1
    Can anyone please share a solution? I am running into the same issue. What makes me curious is that it is a sometimes issue and doesn't happen on the editor (or maybe not enough lucky to see it appear on the editor?). My code is pasted below:

    Code (CSharp):
    1.  
    2. private const string KeyString = "my-32-byte-secret-key-go-here...";
    3.  
    4. public static byte[] EncryptToByte(string plainText)
    5. {
    6.     byte[] cipherData;
    7.     Aes aes = Aes.Create();
    8.     aes.Key = Encoding.UTF8.GetBytes(KeyString);
    9.     aes.GenerateIV();
    10.     aes.Mode = CipherMode.CBC;
    11.     aes.Padding = PaddingMode.PKCS7;
    12.     ICryptoTransform cipher = aes.CreateEncryptor(aes.Key, aes.IV);
    13.  
    14.     using (MemoryStream ms = new MemoryStream())
    15.     {
    16.         using (CryptoStream cs = new CryptoStream(ms, cipher, CryptoStreamMode.Write))
    17.         {
    18.             using (StreamWriter sw = new StreamWriter(cs))
    19.             {
    20.                 sw.Write(plainText);
    21.             }
    22.         }
    23.         cipherData = ms.ToArray();
    24.     }
    25.  
    26.     byte[] combinedData = new byte[aes.IV.Length + cipherData.Length];
    27.     Array.Copy(aes.IV, 0, combinedData, 0, aes.IV.Length);
    28.     Array.Copy(cipherData, 0, combinedData, aes.IV.Length, cipherData.Length);
    29.     return combinedData;
    30. }
    31.  
    32. public static string DecryptFromByte(byte[] combinedData)
    33. {
    34.     string plainText;
    35.     Aes aes = Aes.Create();
    36.     aes.Key = Encoding.UTF8.GetBytes(KeyString);
    37.     byte[] iv = new byte[aes.BlockSize / 8];
    38.     byte[] cipherText = new byte[combinedData.Length - iv.Length];
    39.     Array.Copy(combinedData, iv, iv.Length);
    40.     Array.Copy(combinedData, iv.Length, cipherText, 0, cipherText.Length);
    41.     aes.IV = iv;
    42.     aes.Mode = CipherMode.CBC;
    43.     aes.Padding = PaddingMode.PKCS7;
    44.     ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
    45.  
    46.     using (MemoryStream ms = new MemoryStream(cipherText))
    47.     {
    48.         using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read))
    49.         {
    50.             using (StreamReader sr = new StreamReader(cs))
    51.             {
    52.                 plainText = sr.ReadToEnd();
    53.             }
    54.         }
    55.         return plainText;
    56.     }
    57. }
    58.  
     
    Fep310, mdrunk and Wolkenkind like this.