我遇到了一些加密问题,看不出我做错了什么。我正在尝试在 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/