来自JAVA的PHP验证SHA256withRSA签名

时间:2012-06-20 09:03:09

标签: java php cryptography

对于我当前的项目,我必须从PHP发送签名到Java应用程序。我现在正在使用Crypt / RSA来签署我的数据。

对于测试我只使用以下代码签署“abc”:

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

我可以从php代码验证签名。但是当谈到从JAVA进行验证时,我并没有成功。以下是执行验证操作的java代码:

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

    }

我不认为这是因为密钥,我已经可以通过PHP验证它了,正如我之前所说的那样。有些东西我错过了PHP编码或字节流,但我暂时迷失了。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:8)

我正在使用像Whity这样的openssl。这是我的条纹示例。请注意任何字符编码,行结尾等。这会导致文本数据的二进制表示更改。

<强> PHP-RSA_SHA256-注册

<?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编码二进制签名的输出是:

  

OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX + / + QX1 == SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw

<强> JAVA-RSA_SHA256-验证

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

答案 1 :(得分:3)

默认情况下,phpseclib使用更安全的PSS填充。 Java可能正在使用PKCS#1填充。所以,如果你要去phpseclib路线(我建议你这样做)......这样做:

$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);

答案 2 :(得分:1)

我认为你需要改进你的PHP解决方案。 根据{{​​3}},您可以直接使用[47] =&gt; sha256与PHP的RSAE加密,也许可以从命令行调用openssl:

openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt