2012-06-20 22 views
7

Đối với dự án hiện tại của tôi, tôi phải gửi chữ ký từ ứng dụng PHP đến Java. Tôi đang sử dụng Crypt/RSA ngay bây giờ để ký dữ liệu của mình.SHA256withRSA đăng nhập từ PHP xác minh từ JAVA

Đối với thử nghiệm tôi ký tên chỉ là "abc" với đoạn mã sau:

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

tôi có thể xác minh chữ ký từ mã php. Nhưng khi nói đến việc xác minh từ JAVA, tôi đã không thành công. Đây là mã java thực hiện thao tác xác minh:

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

    } 

Tôi không nghĩ đó là do khóa, tôi có thể xác minh nó từ PHP như tôi đã nói trước đây. Có một cái gì đó mà tôi bỏ lỡ về mã hóa PHP hoặc dòng byte nhưng tôi bị mất cho thời điểm này.

Mọi trợ giúp sẽ được đánh giá cao.

+0

Có vẻ như bạn đang ký nó với khóa công khai, sau đó xác minh nó với khóa công khai. Bạn cần phải xác minh nó bằng khóa riêng. – Polynomial

+0

thanks @Polynomial nhưng chuỗi dài đó là khóa riêng của tôi 1024 byte. – LostMohican

+2

Xin vui lòng cho tôi biết bạn đã không đăng * khóa * thực * riêng của bạn trên StackOverflow ... – Polynomial

Trả lời

5

Tôi đang sử dụng openssl như Whity đã đề cập. Đây là ví dụ của tôi. Hãy nhận biết về bất kỳ mã hóa ký tự, dòng kết thúc, vv Kết quả này trong biểu diễn nhị phân đã thay đổi của dữ liệu văn bản của bạn.

PHP-RSA_SHA256-Đăng:

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

?> 

Kết quả của mã hóa base64 chữ ký nhị phân là:

OnqiWnFQ2nAjOa1S57Du9jDpVr4Wp2nLdMk2FX +/qX1 + SAHpVsW1JvQYqQUDlxvbTOE9vg6dlU6i3omR7KipLw ==

Java- RSA_SHA256-Xác minh:

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

thanks @Sascha bạn đã cứu ngày của tôi :) bạn biết bạn không thể nhìn thấy SHA256 trong hướng dẫn sử dụng của php? http://us3.php.net/manual/en/openssl.signature-algos.php – LostMohican

+1

Hôm nay, bạn đã có thể;) –

1

Tôi nghĩ bạn cần cải thiện giải pháp PHP của mình. Theo http://php.net/manual/en/function.openssl-get-md-methods.php bạn có thể sử dụng trực tiếp [47] => sha256WithRSAEncryption từ PHP, có lẽ gọi openssl từ dòng lệnh cũng có thể:

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

cảm ơn @Whity nhưng tôi không thể tìm thấy bất kỳ cách nào để chèn khóa vào phương thức thông báo:/ – LostMohican

+0

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

3

phpseclib sử dụng đệm PSS bảo mật hơn theo mặc định. Java có thể đang sử dụng vùng đệm PKCS # 1. Vì vậy, nếu bạn đã đi các tuyến đường phpseclib (mà tôi muốn khuyên bạn nên làm) ... làm điều này:

$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); 
+0

Tôi không biết tại sao nhưng kết quả dấu hiệu của phpseclib s thay đổi mỗi lần tôi cố gắng! – LostMohican

+0

Chúng phù hợp với tôi khi chế độ chữ ký được đặt thành CRYPT_RSA_SIGNATURE_PKCS1. Sử dụng chế độ chữ ký mặc định mà họ không khớp nhưng đó là do chế độ đó có đệm ngẫu nhiên. –

Các vấn đề liên quan