2013-03-14 182 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