SHA256withRSA sign from PHP verify from JAVA

14,553

Solution 1

I'm using openssl like Whity already mentioned. Here is my striped down example. Be aware of any character encoding, line ending, etc. This results in changed 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");

?>

The output of base64 encoded binary signature is:

OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX+/qX1+SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw==

JAVA-RSA_SHA256-Verify:

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

Solution 2

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

openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt 
Share:
14,553

Related videos on Youtube

LostMohican
Author by

LostMohican

Software Developer from London

Updated on July 14, 2022

Comments

  • LostMohican
    LostMohican almost 2 years

    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.

    For test I am signing just "abc" with 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 verifying from JAVA, i was not successfull. Here is the java code that does the verify 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 dont think it is because of keys, I can already verify it from PHP as I told before. There is something that I miss about PHP encoding or byte streams but I am lost for the moment.

    Any help would be appreciated.

    • Polynomial
      Polynomial almost 12 years
      Please tell me you didn't post your actual private key on StackOverflow...
    • LostMohican
      LostMohican almost 12 years
      :D ahah thats just a test key i have generated with openssl
  • LostMohican
    LostMohican almost 12 years
    thanks @Whity but I could not find any way to insert a key to the digest method : /
  • Boris Ivanov
    Boris Ivanov almost 12 years
  • LostMohican
    LostMohican almost 12 years
    thanks @Sascha you saved my day:) .you know you can not see SHA256 in php's own manuals? us3.php.net/manual/en/openssl.signature-algos.php
  • Marco Vinicius Castellari
    Marco Vinicius Castellari about 3 years
    Saved my life.!
  • keroles Monsef
    keroles Monsef about 2 years
    saved my life too !