c# "Bad Data"解密时出现异常 - 使用 Base64 编码进行传输

标签 c# android encryption cryptography

我遇到了一些加密问题,看不出我做错了什么。我正在尝试在 Android 上使用 RSA 加密 AESkey 并使用 C# 在服务器端解密它,但不断收到“Bad Data”异常。

我使用 Base64encoding 将加密的 key 从客户端移动到服务器,并注意到在使用 JSON POST 请求从客户端(Android App)移动它之后, key 中有许多“\u000a”使加密数据长度941 导致“数据太大而无法解密”,当删除时,长度增加到 920,允许 80 个 8 字节迭代,并让我到达现在遇到 Bad Data 问题的位置。

我已检查 key 长度和算法是否正确,并且都设置为 2048 位 key 并使用 PKCS1Padding。

“坏数据”异常 在以下场景会抛出该异常。

a) 用于解密的RSA私钥与用于加密的RSA公钥不匹配。

b) 传递给 Decrypt() 方法的二进制数据不正确。如果应用程序代码对加密数据的长度做出假设,或者传入的数据与从 Encrypt() 方法返回的确切字节不匹配,则可能会发生这种情况。

我通过使用返回 RSACryptoServiceProvider.ToXMLString(false) 的 GET 从服务器中提取它来获取 android 上的公钥;并为私钥使用相同的 keystore ,因此看不到它是 1。

据我所知,c# 解密器并未对加密数据的大小做出任何假设。可能我将 block 大小设置为 8,但那是在我知道加密的 AES key 的大小之后。

我一直在四处寻找解决方案,但找不到,因此非常感谢您提供任何帮助。抱歉,如果我太蠢而错过了一些简单的东西,但如果我是,我会戴上眼罩,只是看不到它。

Java 加密

private byte[] encryptRSA(byte [] data) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
        //instance of singleton PublicKey
        AppPublicKey currKey = AppPublicKey.getInstance();
        Log.d("ENCRYPT.MOD: ", currKey.getModBytes().toString());

        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(new BigInteger(1,currKey.getModBytes()), new BigInteger(1,currKey.getExpBytes()));
        KeyFactory keyFactory =  KeyFactory.getInstance("RSA");

        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] cipherData = cipher.doFinal(data);
        Log.d("RSAENCRYPTION: ",Base64.encodeToString(cipherData, 1));
        return cipherData;

 }

C#解密

public string DecryptString(string inputString, int dwKeySize)
    {
        // TODO: Add Proper Exception Handlers
        CspParameters cp = new CspParameters();
        cp.KeyContainerName = "real_Keystore";

        RSACryptoServiceProvider rsaCryptoServiceProvider
                                 = new RSACryptoServiceProvider(dwKeySize,cp);

        int base64BlockSize = 8;               
        int iterations = inputString.Length / base64BlockSize;


        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < iterations; i++)
        {
            byte[] encryptedBytes = Convert.FromBase64String(
                 inputString.Substring(base64BlockSize * i, base64BlockSize));

            //Array.Reverse(encryptedBytes);
            arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(
                                encryptedBytes, false));
        }
        return Encoding.UTF32.GetString(arrayList.ToArray(
                                  Type.GetType("System.Byte")) as byte[]);
    }

最佳答案

一次向 RSA 操作提供几个字节是不可能的。

此外,代码似乎不太可能执行正确数量的 base 64 迭代(因为您在 android 中为 base 64 定义了 NO_PADDING,使用 1 而不是常量).通常 RSA 加密的输出不会是 3 字节的倍数,所以你至少偏离了标记的一个 block 。

您可能想要更仔细地了解您正在使用的 API 函数,并花一些时间研究 .NET 上的 RSA 示例。通常 RSA 仅用于加密少量数据(例如对称数据加密 key ),因此您应该能够一次性解码所有 base64 数据。

请在调试器中测试您的输入和输出。加密/解密问题通常需要比较加密/解密算法的确切输入和输出。

关于c# "Bad Data"解密时出现异常 - 使用 Base64 编码进行传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17655950/

相关文章:

c# - 如何引用 LINQ 中使用保留字命名的字段?

android - 更改 Activity 期间在 Android 中的效果

java - Android 将数字的数字相加

java - ActionScript3 和 Java 加密/解密

c# - Full Framework 和 .NET Core 的 xml 架构编译的不同行为

c# - INotifyDataErrorInfo 和绑定(bind)异常

Java 7 不支持应该支持的密码

java - 在 SecretKey 上调用 .getEncoded() 返回 null

c# - 如何在 NUnit 中对文件权限进行单元测试?

Android 后退按钮在后台后无法按预期工作