Omar Hassan
Omar Hassan

Reputation: 747

AES Android Encryption C# decryption Padding is invalid and cannot be removed

I have a problem related to AES decryption on my server side. When encrypting data in the android client and sending it to the WCF server, the server always return an exception like

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed. at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count) at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at WindowsFormsApplication1.Form1.Decrypt(Byte[] p_EncryptedMsg, Byte[] p_key, Byte[] p_iv) in c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 76 at WindowsFormsApplication1.Form1.button1_Click(Object sender, EventArgs e) in c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 94}

my android encryption is

public static String enc(String message) {

    byte[] keyInBytes = KEY.getBytes();
    byte[] encryptedData = null;
    KeyGenerator kgen;
    try {
        kgen = KeyGenerator.getInstance("AES");
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(keyInBytes);

        kgen.init(256, secureRandom);

        SecretKey skey = kgen.generateKey();

        key = skey.getEncoded();

        try {
            encryptedData = encrypt(key, message.getBytes());
            Log.w("ENC ", new String(encryptedData));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    } catch (NoSuchAlgorithmException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    return Base64.encodeToString(encryptedData, Base64.DEFAULT);

    // return message;
}

private static byte[] encrypt(byte[] raw, byte[] testMessage)
        throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, /* "PBEWithSHA1And128BitAES-CBC-BC" */
    "AES");
    final byte[] iv = KEY.getBytes();

    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
    byte[] encrypted = cipher.doFinal(testMessage);
    try {
        decrypt(raw, encrypted);
    } catch (Exception e) {
        e.getMessage();
        // TODO: handle exception
    }
    return encrypted;
}

and my C# code is

public String Decrypt(byte[] p_EncryptedMsg, byte[] p_key, byte[] p_iv)
    {

         m_key = new byte[32];
        m_iv = new byte[16];
        Array.Clear(m_key, 0, 32);
        Array.Clear(m_iv, 0, 16);
        Array.Copy(p_key, m_key, p_key.Length > 32 ? 32 : p_key.Length);
        Array.Copy(p_iv, m_iv, p_iv.Length > 16 ? 16 : p_iv.Length);


        if (m_key == null || m_iv == null)
            throw new ArgumentNullException("Key or IV is equal to null");

        using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
        {

            aesProvider.Key = m_key;
            aesProvider.IV = m_iv;
            aesProvider.Mode = CipherMode.CBC;
            aesProvider.Padding = PaddingMode.PKCS7;
            using (MemoryStream memStream = new MemoryStream())
            {
                CryptoStream decStream = new CryptoStream(memStream,                aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
                decStream.Write(p_EncryptedMsg, 0, p_EncryptedMsg.Length);
                decStream.FlushFinalBlock();
                String res = System.Text.Encoding.Default.GetString(memStream.ToArray());
                return res;
            }
        }
    }

NOTE: I can encrypt and decrypt the text again correctly in the android side.

Upvotes: 0

Views: 2465

Answers (2)

Omar Hassan
Omar Hassan

Reputation: 747

i found that the problem happened as a result of using SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

as the server side take only the keyInBytes from me not the randomized one, so he can't generate the correct decryption key.

C# code example

using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
            {
                aesCryptoServiceProvider.Key = key;
                aesCryptoServiceProvider.IV = iv;
                aesCryptoServiceProvider.Mode = CipherMode.CBC;
                aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write);
                    cryptoStream.Write(p_EncryptedMsg, 0, encryptedMsg.Length);
                    cryptoStream.FlushFinalBlock();
                    return memoryStream.ToArray();
                }
            }

Upvotes: 0

Ameen
Ameen

Reputation: 2586

Well, one problem I see is that your CipherMode on the .Net side should be ECB to match the Java side. Give that a shot and see if that works.

Upvotes: 1

Related Questions