9

現在のプロジェクトでは、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エンコーディングやバイトストリームについて私が見逃していることがありますが、今のところ迷っています。

どんな助けでもいただければ幸いです。

4

3 に答える 3

11

すでに述べた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);
    }
}
于 2012-06-20T11:59:23.087 に答える
3

phpseclibは、デフォルトでより安全なPSSパディングを使用します。JavaはおそらくPKCS#1パディングを使用しています。したがって、phpseclibルートに移動する場合(これを実行することをお勧めします)...これを実行します:

$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
于 2012-06-20T13:47:18.777 に答える
1

PHPソリューションを改善する必要があると思います。http://php.net/manual/en/function.openssl-get-md-methods.phpによると、直接使用できます[47] => PHPからsha256WithRSAEncryption、おそらくコマンドラインからopensslを呼び出すことも可能です。

openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt 
于 2012-06-20T09:48:28.780 に答える