解密时c#“Bad Data”异常 - 使用Base64编码进行传输

时间:2013-07-15 13:53:24

标签: c# android encryption cryptography

我遇到过一些加密问题,但是看不清楚我做错了什么。我正在尝试使用Android上的RSA加密AESkey并使用C#解密服务器端,但不断收到“错误数据”异常。

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

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

“错误数据”例外 在以下方案中将抛出此异常。

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

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

我通过GET从服务器上获取公钥,然后返回RSACryptoServiceProvider.ToXMLString(false);并为私钥使用相同的密钥库,因此无法将其视为1。

据我所知,c#decrypter不对加密数据的大小做任何假设。可能我的设置块大小为8但是在我知道加密的AESkey的大小之后。

我一直在寻找解决方案而找不到解决方案,所以如果有任何帮助,我将不胜感激。抱歉,如果我是愚蠢的,并且错过了一些简单的事情,但是如果我是的话,我会看到我的眼罩,并且无法看到它。

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#Decrypt

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[]);
    }

1 个答案:

答案 0 :(得分:0)

无法一次向RSA操作提供几个字节。

此外,代码似乎不太可能执行适当数量的base 64迭代(如您在android中为base 64定义NO_PADDING,使用1而不是常量)。通常,RSA加密的输出不会是3个字节的倍数,因此至少有一个块不在标记范围内。

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

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