2013-03-14 164 views
5

假設我有以下的Java代碼來生成公私密鑰對:RSA加密,解密PHP

KeyPairGenerator generator = KeyPairGenerator.getInstance ("RSA"); 
SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 

generator.initialize (1024, random); 

KeyPair pair = generator.generateKeyPair(); 
RSAPrivateKey priv = (RSAPrivateKey)pair.getPrivate(); 
RSAPublicKey pub = (RSAPublicKey)pair.getPublic(); 

// Sign a message 
Signature dsa = Signature.getInstance("SHA1withRSA"); 
dsa.initSign (priv); 
dsa.update ("Hello, World".getBytes(), 0, "Hello, World".length()); 

byte[] out = dsa.sign(); 
/* save the signature in a file */ 
FileOutputStream sigfos = new FileOutputStream("sig"); 
sigfos.write(out); 
sigfos.close(); 

一個人怎麼會去和PHP解密文件「SIG」?我讀過帖子:https://stackoverflow.com/a/1662887/414414,它提供了一個函數來將DER文件轉換爲PEM(假設我也從Java保存公鑰)。

我已經試過類似:

$key = openssl_pkey_get_public ("file://pub_key.pem"); 
$data = null; 
openssl_public_decrypt (file_get_contents ("sig"), $data, $key); 
echo $data, "\n"; 

它成功地解密消息,但它是許多奇怪的字符。

我們的場景是一個Java客戶端發送消息到PHP服務器,但用私鑰加密數據。 PHP知道它應該用來解密和驗證消息的公鑰。

我已經閱讀了很多關於這個問題的帖子,所以我已經意識到這是一個有點特定的問題,尤其是如果有不同的算法在使用等等。所以對不起,如果這可能是一個副本。

任何反饋都非常感謝!

+2

「它成功解密了郵件,但它是很多奇怪的字符。」 - 你能更具體一點嗎?難道它只是一個編碼問題? – 2013-03-14 14:18:56

+1

解碼後的消息是否與原始文本類似,還是完全亂碼? – 2013-03-14 14:19:27

+0

你想驗證Java和PHP之間發送的消息,還是加密它們?或兩者? – 2013-03-14 16:34:41

回答

3

由於像PKCS#1這樣的公鑰協議也指定了填充方案,並且所有簽名方案都將加密消息的摘要,所以「RSA簽名」通常不僅僅是「用私鑰加密,用公鑰解密」 ,而不是完整的信息。如果java的簽名方案使用PKCS#1中指定的簽名填充方案,我找不到任何文檔,但我懷疑它是。

如果是,您將改爲使用PHP中的openssl_verify方法,記錄爲here。如果簽名無效或有效,這將分別返回0或1。

如果Java不使用填充方案,則問題是簽名中加密的數據是消息的散列,而不是消息本身(您可以在Java代碼中看到它使用SHA-1哈希算法)。所以在PHP方面,您需要使用sha1 method$raw_output設置爲true,並將這些字符串進行比較以確保您的消息有效,從而獲得消息的sha1哈希值。

+0

非常感謝!由於簽名將基於各種HTTP標頭及其值,我可以將它們放在服務器端,檢查簽名是否有效:'openssl_verify(「Hello,World」,file_get_contents('sig'),$ PUBKEY)'。這工作;-) – DavidS 2013-03-14 18:44:28

+0

我想我得到了同樣的問題....但openssl_verify()不適合我.... [問題鏈接](http://stackoverflow.com/questions/16370046/use -php-openssl-verify-function-to-verify-signature-and-data-created-by-androi)請幫忙,在此先感謝 – shanwu 2013-05-06 12:22:47

-1

從片段

$key = openssl_pkey_get_public ("file://pub_key.pem"); 

它看起來像你引用的公開密鑰,這將是一個錯誤解密。再檢查一遍 ?

+0

這是簽名驗證,所以使用公鑰似乎對我來說是正確的。 – Henrik 2013-03-14 14:23:26

+0

是簽名驗證,是的,所以服務器永遠不應該知道私鑰。 – DavidS 2013-03-14 18:44:54