简体   繁体   English

Java中的RSA加密,用PHP解密

[英]RSA encryption in Java, decrypt in PHP

Assume I have the following Java code to generate a Public-private keypair: 假设我有以下Java代码来生成Public-private密钥对:

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();

How would one go about and decrypt the file "sig" in PHP? 如何在PHP中解密并解密文件“sig”? I've read the post: https://stackoverflow.com/a/1662887/414414 which supplies a function to convert a DER file to PEM (Assume I also save the public key from Java). 我已阅读帖子: https//stackoverflow.com/a/1662887/414414 ,它提供了将DER文件转换为PEM (假设我还从Java保存公钥)。

I have tried something like: 我尝试过类似的东西:

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

It successfully decrypts the message, but it is many weird characters. 它成功解密了消息,但它是许多奇怪的字符。

Our scenario is a Java client that is sending messages to a PHP server, but encrypts the data with a private key. 我们的场景是一个Java客户端,它将消息发送到PHP服务器,但使用私钥加密数据。 PHP knows about the public key, which it should use to decrypt and validate the message. PHP知道公钥,它应该用来解密和验证消息。

I've read a lot of posts regarding this issue here on SO, but I've come to realize that this is a bit specific issue, especially if there's different algorithms in use, etc. So sorry if this may be a duplicate. 我已经在SO上阅读了很多关于这个问题的帖子,但我已经意识到这是一个特定的问题,特别是如果使用不同的算法等等。很抱歉,如果这可能是重复的。

Any feedbacks are greatly appreciated! 任何反馈都非常感谢!

an "RSA signature" is usually more than just "encrypt with private key, decrypt with public key", since Public key protocols like PKCS#1 also specify padding schemes, and all signature schemes will encrypt a digest of the message, instead of the full message. “RSA签名”通常不仅仅是“使用私钥加密,使用公钥解密”,因为像PKCS#1这样的公钥协议也指定了填充方案,并且所有签名方案都将加密消息的摘要,而不是完整的消息。 I cannot find any documentation if java's signature scheme uses the signature padding scheme specified in PKCS#1, but my suspicion is that it is. 如果java的签名方案使用PKCS#1中指定的签名填充方案,我找不到任何文档,但我怀疑它是。

If it is, you will instead want to use the openssl_verify method in PHP, documented here . 如果是,您将要使用PHP中的openssl_verify方法, 此处记录 This will return a 0 or 1 if the signature is invalid or valid, respectively. 如果签名无效或有效,则返回0或1。

In the event that Java does not use a padding scheme, your issue is that the data encrypted in the signature is a hash of the message, instead of the message itself (you can see in the Java code that it uses the SHA-1 hash algorithm). 如果Java不使用填充方案,您的问题是签名中加密的数据是消息的哈希值,而不是消息本身(您可以在Java代码中看到它使用SHA-1哈希算法)。 So on the PHP side, you will need to take the sha1 hash of your message using the sha1 method with $raw_output set to true, and compare those strings to ensure your message is valid. 因此,在PHP方面,您需要使用sha1方法获取消息的sha1哈希值,并将$raw_output设置为true,并比较这些字符串以确保消息有效。

From the snippet 从片段

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

It looks like you're referencing the public key, which would be the wrong one to decrypt. 看起来你正在引用公钥,这对于解密来说是错误的。 Double check ? 再检查一遍 ?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM