Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSA encryption in Java, decrypt in PHP

Assume I have the following Java code to generate a Public-private keypair:

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? 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).

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. PHP knows about the public key, which it should use to decrypt and validate the message.

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.

Any feedbacks are greatly appreciated!

like image 785
DavidS Avatar asked Nov 04 '22 02:11

DavidS


1 Answers

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. 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.

If it is, you will instead want to use the openssl_verify method in PHP, documented here. This will return a 0 or 1 if the signature is invalid or valid, respectively.

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). 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.

like image 141
Peter Elliott Avatar answered Nov 09 '22 14:11

Peter Elliott