2012-06-20 17 views
7

Per il mio progetto corrente devo inviare una firma da PHP a Java. Sto usando Crypt/RSA adesso per firmare i miei dati.SHA256 con il segno RSA da PHP verifica da JAVA

Per prova ho firmo solo "abc" con codice seguente:

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

posso verificare la firma dal codice php. Ma quando si tratta di verificare da JAVA, non ho avuto successo. Ecco il codice Java che fa l'operazione di verifica:

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

    } 

io non credo che sia a causa di chiavi, posso già verificarlo da PHP, come ho detto prima. C'è qualcosa che mi manca della codifica PHP o dei flussi di byte, ma per il momento sono perso.

Qualsiasi aiuto sarebbe apprezzato.

+0

Sembra che si sta firmando con la chiave pubblica, quindi la verifica con la chiave pubblica. Devi verificarlo con la chiave privata. – Polynomial

+0

grazie a @Polynomial ma quella stringa lunga è la mia chiave privata 1024 byte. – LostMohican

+2

Ti prego di dirmi che non hai postato la tua * privata * chiave privata su StackOverflow ... – Polynomial

risposta

5

sto usando OpenSSL come Whity già accennato. Ecco il mio esempio di strisce verso il basso. Essere a conoscenza di qualsiasi codifica di carattere, fine riga, ecc. Ciò comporta la modifica della rappresentazione binaria dei dati di testo.

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

?> 

L'uscita base64 codificato firma binario è:

OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX +/+ QX1 SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw ==

JAVA RSA_SHA256-Verifica:

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

grazie @Sascha hai salvato la mia giornata :). Sai che non puoi vedere SHA256 nei manuali di php? http://us3.php.net/manual/en/openssl.signature-algos.php – LostMohican

+1

Oggi, è già possibile;) –

1

Penso che tu abbia bisogno di migliorare la tua soluzione PHP. Secondo http://php.net/manual/en/function.openssl-get-md-methods.php è possibile utilizzare direttamente [47] => sha256WithRSAEncryption da PHP, probabilmente chiamata OpenSSL da riga di comando è anche possibile:

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

grazie @Whity ma non ho trovato alcun modo per inserire una chiave per il metodo digest:/ – LostMohican

+0

Controllare http://stackoverflow.com/questions/10524198/what-version-of-openssl-is-needed-to-sign -with-sha256withrsaencryption –

3

phpseclib utilizza la protezione PSS più sicura per impostazione predefinita. Java sta probabilmente usando il padding PKCS # 1. Quindi, se si dovesse andare via phpseclib (che mi consiglia di fare) ... fare questo:

$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); 
+0

non so perché ma il risultato del segnale phpseclib è cambiato ogni volta che ho provato! – LostMohican

+0

Si adattano perfettamente a me quando la modalità di firma è impostata su CRYPT_RSA_SIGNATURE_PKCS1. Usando la modalità di firma di default non corrispondono, ma perché quella modalità esegue il riempimento casuale. –

Problemi correlati