5

假设我有以下 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 上阅读了很多关于这个问题的帖子,但我已经意识到这是一个有点具体的问题,特别是如果使用不同的算法等。如果这可能是重复的,很抱歉。

非常感谢任何反馈!

4

2 回答 2

3

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

如果是,您将改为使用openssl_verifyPHP 中的方法,在此处记录。如果签名无效或有效,这将分别返回 0 或 1。

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

于 2013-03-14T16:34:07.413 回答
-1

从片段

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

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

于 2013-03-14T14:19:43.070 回答