我遇到了一些Crypto問題,無法查看我做錯了什麼。我試圖在Android上使用RSA加密AESkey,並使用C#解密它的服務器端,但仍然收到「Bad Data」異常。c#解密時出現「Bad Data」異常 - 使用Base64編碼進行傳輸
我使用Base64encoding將加密密鑰從客戶端移動到服務器,並注意到使用JSON POST請求從客戶端(Android應用程序)移動它之後,密鑰中有一些「\ u000a」使得加密數據長度941導致一個「數據大到解密」時被刪除帶來的長度爲920,允許80個8字節的迭代,讓我到我現在在哪裏與壞數據問題。
我已檢查密鑰長度和算法是否正確,並且都設置爲2048位密鑰並使用PKCS1Padding。
「錯誤數據」異常 在以下情況下將拋出此異常。
a)用於解密的RSA私鑰與用於加密的RSA公鑰不匹配。
b)傳遞給Decrypt()方法的二進制數據不正確。如果應用程序代碼對加密數據的長度進行了假設,或者傳入的數據與從Encrypt()方法返回的確切字節不匹配,則可能會發生這種情況。
我得到的公共密鑰在android上從服務器拉一個GET返回RSACryptoServiceProvider.ToXMLString(false);並使用相同的密鑰庫的私鑰,所以不能看到它是1.
而據我所知,c#解密器是不作任何關於加密數據的大小的假設。可能我的設置塊大小爲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#解密
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[]);
}
「_I通過使用GET從服務器拉它來獲取android上的公鑰。_「你正在使用TLS(https),對嗎?在這種情況下,你已經有了一個安全的通信通道,並且根本不需要這個額外的加密技術 – ntoskrnl
即使它可能更容易,最終的實現可能會很好地使用Https,但是我真的想要這個加密/解密工作,它一直在困擾我一段時間,並且恨不能修復它 – user2583070
如果你不使用TLS來獲取公共所有這些加密技術都是無用的,因爲它很容易受到中間人攻擊.TLS通過簽名證書解決了這個問題。這裏有一些關於這個問題的討論:http://blogs.msdn.com/b/ ericlippert/archive/2011/09/27/keep-it-secret-keep-it-safe.aspx如果你不關心MITM漏洞,你可以使用Diffie-Hellman,這比RSA簡單得多。 – ntoskrnl