2011-06-30 64 views
3

我試圖使用RSA公鑰和Android應用程序對AES密鑰進行加密,然後使用PHP和phpseclib解密服務器上的AES密鑰。我已經過測試,以確保RSA加密/解密在兩個平臺上都可以通過加密靜態文本並在解密後檢查是否仍然可以獲得原始文本。根據測試,RSA代碼在每個平臺上單獨運行,但平臺之間似乎有區別。Java中的RSA加密,PHP中的解密

在Java中,我使用充氣城堡庫,並有下面的代碼:

RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
new BigInteger("00c897f9e401819e223ffbecc6f715a8d84dce9022762e0e2d54fa434787fcaf230d28bd0c3b6b39b5211f74ffc4871c421362ccfc07ae98b88fa9728f1e26b8210ebbf4981e45867fe810938294d0095d341b646b86dcbd4c246676c203cb1584d01eef0635299714d94fa12933ecd35e6c412573156d9e6e549b7804eb6e165660507d8748bcc8c60da10099bacb94d3f7b50b1883ee108489e0dd97ed7d28e564edd4ee5d6b4225f5c23cdaaf495c3fa08c3b82e1674946e4fa1e79b2493204d6953c261105ba5d0f8dcf3fcd39a51fbc18a5f58ffff169b1bed7ceeded2ae0e8e8e2238e8b77b324d1a482593b1a642e688c860e90d5a3de8515caf384133b", 16), 
new BigInteger("11", 16)); 
keyFactory = KeyFactory.getInstance("RSA", "BC"); 
//RSAPublicKeySpec rsaKeySpec = new RSAPublicKeySpec(rsaKey.MODULUS, new BigInteger("11", 16)); 
RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(pubKeySpec); 

//Set up the cipher to RSA encryption 
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC"); 
cipher.init(Cipher.ENCRYPT_MODE, pubKey); 

// make sure the Aes Key is less than a block size 
// otherwise major errors will occur 
if(AesKey.length * 8 > pubKey.getModulus().bitLength()) 
    return "Error: AesKey bigger than block size of RSA Key"; 

byte[] encryptedKey = cipher.doFinal(AesKey); 

// return result Base64 encoded 
return Base64.encodeToString(encryptedKey, Base64.DEFAULT); 

然後在PHP中,我使用下面的代碼來解密AES密鑰:

$AESkey = base64_decode($AES); 

$rsa = new Crypt_RSA(); 
$private = file_get_contents($_SERVER['DOCUMENT_ROOT'].'/PrivateData/private_key.pem'); 
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1); 
$rsa->loadKey($private); 
$AESkey = $rsa->decrypt($AESkey); 

當AES密鑰被服務器解密時,我總是得到以下錯誤:1911行C:\ xampp \ php \ PEAR \ phpseclib \ Crypt \ RSA.php中的解密錯誤。查看RSA.php中的代碼,我認爲這個錯誤與加密期間填充不正確有關,但我似乎無法弄清楚方法來解決它。

更新:我發現上述加密/解密代碼實際上是正確的。我遇到的問題是,在將數據從應用程序發送到PHP之前,我沒有對輸出進行網址編碼,因此一些信息丟失了。

+0

錯誤意味着前兩個高位字節一個是錯誤的,通常表示一個非常嚴重的錯誤,如私鑰不正確。可能會有一個排序問題?這是我會檢查的另一件事。 –

+0

我究竟該如何檢查?我有一種感覺,自己沒有任何問題,因爲我可以讓它工作,如果我在PHP中同時執行加密和解密,但我認爲這可能是一個問題,我如何將公鑰輸入到Java或者我在Java中使用的填充方案。 – UmangB

+0

檢查的一種方法是反轉密碼字節並查看解密是否成功。但最好的方法是找到一些已知的好測試向量,看看它們是如何被PHP端處理的。如果您可以在phpseclib中設置斷點來檢查中間值,這也會有所幫助。 –

回答

0

您使用的是哪個版本的phpseclib?根據不同的版本,下面可以幫助:

http://www.frostjedi.com/phpbb/viewtopic.php?p=118414#p118414

+0

我有最新的版本,包括鏈接中討論的修復程序。在做了一些進一步的測試之後,我確定這可能是java和php使用的不同字符集的問題。 Java默認使用UTF-8,PHP默認使用ISO-8859-1。我不知道如何在不丟失任何數據的情況下在兩者之間進行轉換。我也無法弄清楚如何讓php base 64解碼utf-8字符串。 – UmangB

+0

如果你沒有在Java中以String形式生成密碼,而是以ByteArray或其他方式生成密碼? – 2011-07-06 22:07:56

+0

實際上,在做了一堆測試和調試以找到解決方案之後,我發現加密是正確的,但android app和php之間發送的信息必須在進行base 64編碼或其他數據後進行url編碼弄亂了。 – UmangB