RSA加密用Java,解密用PHP


RSA encryption in Java, decrypt in PHP

假设我有以下Java代码来生成公私对:

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知道公钥,它应该使用它来解密和验证消息。

我在SO上读了很多关于这个问题的帖子,但我已经意识到这是一个有点具体的问题,特别是如果使用不同的算法等。很抱歉,如果这可能是重复的。

任何反馈都非常感谢!

一个"RSA签名"通常不仅仅是"用私钥加密,用公钥解密",因为像pkcs# 1这样的公钥协议也指定了填充方案,所有的签名方案都将加密消息的摘要,而不是完整的消息。如果java的签名方案使用pkcs# 1中指定的签名填充方案,我找不到任何文档,但我怀疑它是。

如果是,您将转而使用PHP中的openssl_verify方法,这里有文档说明。如果签名无效或有效,这将分别返回0或1。

在Java不使用填充方案的情况下,您的问题是签名中加密的数据是消息的散列,而不是消息本身(您可以在Java代码中看到它使用SHA-1散列算法)。因此,在PHP端,您需要使用sha1方法将$raw_output设置为true来获取消息的sha1散列,并比较这些字符串以确保消息有效。

从代码片段

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

看起来您正在引用公钥,这将是错误的解密。再次检查?