SHA256withRSA sign from PHP check with JAVA

For my current project, I have to send a signature from PHP to a Java application. I am using Crypt / RSA right now to sign my data.

For the test, I sign only "abc" with the following code:

$rsa = new Crypt_RSA(); $plaintext = 'abc'; $rsa->loadKey("MIICXgIBAAKBgQDjh+hNsqJe566JO0Sg7Iq5H1AdkauACdd8QMLp9YNY0HPslVH0 rXaOFo0zgH0Ktu/Ku3lS1lfxbFQAY8b6ywZKvu4eoxlnEwuBwy09CG+3ZiVLBjCj TZHA/KOkpVLa+tA6KsoP6zv/xI/ACkSCxPGR0q3SiRuhXV/6tacoKxUYnwIDAQAB AoGBAIC00GOjONYWmFRoglnFdHNjkx4m2KyE5LAUsi1GBBapU+nwTXvq47VcbGNF u3XkJaC4i9igBv86GApgZp5XWia86On/Lz9NR4fB2EFP6Ydy84GfCDNNvkism4BR aA+eYdNiQ3Wfyi98ZpUi+rPsoI6Cid4eSkCC4poTUaqzMkiBAkEA9Gn1oIlUEoVI q/u5Y9vflXRDt95AA9AokJkQj7XTNjsz8ypU8TO6D6ZykpcbK6zjU0UJsQiC3dKj AgmAR2VzYwJBAO5RETMAyDnR+5g+MtHpwGqGdY4dq0j4y4CsdtOYKWwSTh3VQy+C eghJoyPRfIpulw2Mk/l+occEI0ohJl0+UJUCQQDSZtjVLwMZwnUx4EvSw/ewL9sP 0Jpo7evNtoaEQDEncUWiYeGnljDowg/FU6FHMtiq2TajmMEXdflvioBMdfAjAkEA 3TB60SbJr/i4Fo6sJm5ZO8W+eAALiTf50VzBERTqZTb8L+5PZFoqn2SROV5mxClu o5G1idzBlHC/vD7WV7bNnQJAd0FrxaMBurJ4Uv/B8TDP+eeBdB7d9rKw0+TVlcel cbpIz6BIP6+nmsgy6dbDRnx0eC/MgF2EU0wrCu1DK0PyWA=="); $rsa->setHash("sha256"); $signature = $rsa->sign($plaintext); $signature_encoding = mb_convert_encoding($signature, "UTF-8"); error_log("signature encoded in UTF-8 :" . $signature_encoding); $encoded_sign = base64_encode($signature_encoding); error_log("encoded sign for abc: " . $encoded_sign); 

I can verify the signature from php code. But when it comes to validation from JAVA, I have not been successful. Here is the java code that performs the validation operation:

 public boolean verify(String signed, String data, PubKey pubKey) throws Exception{ PublicKey publicKey = jceProvider.generateRSAPublicKeyFromX509( base64.decode(pubKey.getEncodedKey()) ); byte[] signature = base64.decode(signed); byte[] verifier = data.getBytes(Charset.forName("UTF-8")); return jceProvider.verify(signature, verifier, publicKey); } public class JCEProvider { public boolean verify (byte[] signature, byte[] verifier, PublicKey publicKey) throws Exception{ Signature rsaSignature = Signature.getInstance("SHA256withRSA"); rsaSignature.initVerify(publicKey); rsaSignature.update(verifier); return rsaSignature.verify(signature); } 

I do not think that this is because of the keys, I can already check this with PHP, as I said. There is something that I am missing about PHP coding or byte streams, but I'm lost at the moment.

Any help would be appreciated.

+7
source share
3 answers

I use openssl, as Whity already mentioned. Here is my striped pattern example. Keep in mind any character encoding, line termination, etc. This changes the binary representation of your text data.

PHP-RSA_SHA256-Sign:

 <?php $data = "For my current project I have to send a signature from PHP to Java application. I am using Crypt/RSA right now for signing my data."; $private_key = <<<EOD -----BEGIN RSA PRIVATE KEY----- MIIBOgIBAAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6zxqlVzz0wy2j4kQVUC4Z RZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQJAL151ZeMKHEU2c1qdRKS9 sTxCcc2pVwoAGVzRccNX16tfmCf8FjxuM3WmLdsPxYoHrwb1LFNxiNk1MXrxjH3R 6QIhAPB7edmcjH4bhMaJBztcbNE1VRCEi/bisAwiPPMq9/2nAiEA3lyc5+f6DEIJ h1y6BWkdVULDSM+jpi1XiV/DevxuijMCIQCAEPGqHsF+4v7Jj+3HAgh9PU6otj2n Y79nJtCYmvhoHwIgNDePaS4inApN7omp7WdXyhPZhBmulnGDYvEoGJN66d0CIHra I2SvDkQ5CmrzkW5qPaE2oO7BSqAhRZxiYpZFb5CI -----END RSA PRIVATE KEY----- EOD; $binary_signature = ""; $algo = "SHA256"; openssl_sign($data, $binary_signature, $private_key, $algo); print(base64_encode($binary_signature) ."\n"); ?> 

Base64 encoded binary signature output:

OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX + / QX1 + SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw ==

JAVA-RSA_SHA256-Verification:

 import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Base64; public class RsaVerify { public static void main(String args[]){ String publicKey = // "-----BEGIN PUBLIC KEY-----"+ "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANDiE2+Xi/WnO+s120NiiJhNyIButVu6"+ "zxqlVzz0wy2j4kQVUC4ZRZD80IY+4wIiX2YxKBZKGnd2TtPkcJ/ljkUCAwEAAQ=="; // "-----END PUBLIC KEY-----"; byte[] data = "For my current project I have to send a signature from PHP to Java application. I am using Crypt/RSA right now for signing my data.".getBytes(); byte[] signature = Base64.decodeBase64("OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX+/qX1+SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw=="); try { System.out.println(verify(data, signature, publicKey)); } catch (GeneralSecurityException e) { e.printStackTrace(); } } private static boolean verify(byte[] data, byte[] signature, String publicKey) throws GeneralSecurityException{ X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(pubKey); sig.update(data); return sig.verify(signature); } } 
+6
source

phpseclib by default uses the more secure PSS add-on. Java probably uses the PKCS # 1 add-on. Therefore, if you have to go the phpseclib route (which I would recommend doing) ... do the following:

 $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); 
+3
source

I think you need to improve your PHP solution. According to http://php.net/manual/en/function.openssl-get-md-methods.php you can directly use [47] => sha256WithRSAEncryption from PHP, it is also possible to call openssl from the command line:

 openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt 
+1
source

All Articles