2013-07-15 66 views
2

我遇到了一些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[]); 
    } 
+0

「_I通過使用GET從服務器拉它來獲取android上的公鑰。_「你正在使用TLS(https),對嗎?在這種情況下,你已經有了一個安全的通信通道,並且根本不需要這個額外的加密技術 – ntoskrnl

+0

即使它可能更容易,最終的實現可能會很好地使用Https,但是我真的想要這個加密/解密工作,它一直在困擾我一段時間,並且恨不能修復它 – user2583070

+0

如果你不使用TLS來獲取公共所有這些加密技術都是無用的,因爲它很容易受到中間人攻擊.TLS通過簽名證書解決了這個問題。這裏有一些關於這個問題的討論:http://blogs.msdn.com/b/ ericlippert/archive/2011/09/27/keep-it-secret-keep-it-safe.aspx如果你不關心MITM漏洞,你可以使用Diffie-Hellman,這比RSA簡單得多。 – ntoskrnl

回答

0

它是不可能在同一時間到RSA操作養活幾個字節。

此外,代碼似乎不太可能執行正確數量的base 64迭代(因爲您在Android中爲base 64定義了NO_PADDING,使用1代替常量)。正常情況下,RSA加密的輸出不會是3個字節的倍數,所以至少要有一個標記。

您可能想仔細看看您正在使用的API函數,並花一些時間研究.NET上的RSA示例。通常,RSA僅用於加密少量數據(如對稱數據加密密鑰),因此您應該能夠一次解碼所有base64數據。

請在調試器中測試您的輸入和輸出。加密/解密問題通常要求比較加密/解密算法的確切輸入和輸出。

+0

請讓我知道這是否解決了您的問題。忘了歡迎你...歡迎來到Stackoverflow :) –

相關問題