0

我在服务器端遇到了与 AES 解密相关的问题。在android客户端加密数据并将其发送到WCF服务器时,服务器总是返回一个异常,如

System.Security.Cryptography.CryptographicException:填充无效且无法删除。在 System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count) 在 System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) 在 System.Security.Cryptography .CryptoStream.FlushFinalBlock() 在 WindowsFormsApplication1.Form1.Decrypt(Byte[] p_EncryptedMsg, Byte[] p_key, Byte[] p_iv) 在 c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1。 c:\users\omr\documents\visual studio 2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line 94}

我的安卓加密是

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

我的 C# 代码是

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

注意:我可以在 android 端再次正确加密和解​​密文本。

4

2 回答 2

1

好吧,我看到的一个问题是.Net 端的 CipherMode 应该是 ECB 以匹配 Java 端。试一试,看看是否有效。

于 2013-09-17T14:18:35.760 回答
0

我发现问题是由于使用 SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

由于服务器端只从我那里获取 keyInBytes 而不是随机的,所以他无法生成正确的解密密钥。

C# 代码示例

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();
                }
            }
于 2013-12-08T12:35:31.743 回答