2015-06-23 19 views
5

Tôi đang sử dụng SHA256 và RSA để ký thư trên máy tính Ubuntu của tôi bằng OpenSSL. Mục tiêu của tôi là xác minh thư này trên Android bằng cách sử dụng Java của Android.Tin nhắn đã ký bằng OpenSSL; không thể xác minh bằng Android Java

lệnh sau đã được sử dụng trên ubuntu:

openssl genrsa -out private.pem 1024 
openssl rsa -in private.pem -out public.pem -outform PEM -pubout 
echo 'foobar' > data.txt 
openssl dgst -sha256 <data.txt> hash 
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash > signature 
openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der 
openssl enc -base64 -in signature -out base64_signature 

bây giờ tôi đã tạo ra các phím ký tin nhắn, tạo ra một tập tin .der cho khóa công khai rằng sẽ có thể được truy cập trong Java và mã hóa thông điệp với Base64. Sau đó tôi đặt khóa công khai .der trên thiết bị của tôi và tải thành công khóa vào lớp PublicKey.

Phương pháp này được sử dụng để xác minh thông điệp:

public static boolean verify(PublicKey publicKey,String data,String verification){ 
    java.security.Signature sig; 
    try { 
     sig = java.security.Signature.getInstance("SHA256WithRSA"); 
     sig.initVerify(publicKey); 
     try { 
      sig.update(verification.getBytes()); 
     } catch (Exception e) { 
      ... 
     } 

     if (!sig.verify(Base64.decode(data, Base64.DEFAULT))) { 
      return false; 
     } 
     return true; 
    } 
    catch .... 
    return false; 
} 

Các tham số khi gọi phương pháp:

verify(PublicKey, Base64 encoded data in a String that is to be verified, "foobar"); 

Rõ ràng việc xác minh thất bại, nhưng tôi không thể hiểu tại sao. Tôi đoán nó phải làm một cái gì đó với mã hóa (?).


Cập nhật! Vì vậy, tôi quản lý để viết kết quả của Base64.decode(data, Base64.DEFAULT)) vào một tệp và so sánh nó với tệp chữ ký gốc bằng cách sử dụng một trình chỉnh sửa. Hoàn toàn khác!

+0

Mã hóa văn bản có thể là một vấn đề. Bạn có thể kiểm tra điều đó bằng cách tạo một SAH256 MessageDigest của 'verify' đã sử dụng của bạn và so sánh đầu ra với hàm băm OpenSSL. Bạn cũng có thể kiểm tra "nội dung" chữ ký của bạn bằng cách giải mã nó bằng Java với RSA/ECB/NoPadding. – Robert

Trả lời

6

Java tạo và hy vọng nhận được chữ ký ở dạng hơi khác. Thông điệp băm phải được mã hóa trong DER, sau đó được đệm bằng PKCS # 1 và chỉ sau đó được ký bằng khóa riêng. Và Openssl có một lệnh cho điều đó (vì nó thực sự là một quy trình chuẩn). Thay vì

openssl dgst -sha256 <data.txt> hash 
openssl rsautl -sign -inkey private.pem -keyform PEM -in hash > signature 

bạn làm

openssl dgst -sha256 -binary -sign private.pem data.txt > signature 

Cũng lưu ý:

  • data.txt của bạn có chứa một dòng mới, đừng quên nó trong String verification biến
  • sig.update(verification.getBytes()) nên chỉ ra một cách rõ ràng charset - bộ ký tự giống nhau, được sử dụng để điền vào tệp data.txt e, ví dụ: sig.update(verification.getBytes("UTF-8"))

Phần còn lại của lệnh/mã của bạn có vẻ OK.


UPD - để trả lời @GilCol về sự khác biệt:

Các padding là như nhau cho cả hai ký tin nhắn (PKCS # 1). Nhưng các thông điệp khác nhau.

Khi bạn sử dụng openssl dgst -sha256 <data.txt> hash, hash sẽ chứa (tùy thuộc vào phiên bản openssl):

(stdin)= aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f 

hoặc

aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f 

Đây là văn bản chỉ đơn giản và nó là thông điệp mà bạn sẽ tiến hành ký sử dụng openssl rsautl -sign .... Chúng ta có thể thấy rằng với openssl rsautl -verify ...:

# raw message as-is - we can see the padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -raw -hexdump 
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff 00 61 ...............a # 
00c0 - 65 63 30 37 30 36 34 35-66 65 35 33 65 65 33 62 ec070645fe53ee3b # 
00d0 - 33 37 36 33 30 35 39 33-37 36 31 33 34 66 30 35 3763059376134f05 # your plain-text message 
00e0 - 38 63 63 33 33 37 32 34-37 63 39 37 38 61 64 64 8cc337247c978add # 
00f0 - 31 37 38 62 36 63 63 64-66 62 30 30 31 39 66 0a 178b6ccdfb0019f. # we can even see newline char (0a) at the end 

# strip the padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -pkcs -hexdump 
0000 - 61 65 63 30 37 30 36 34-35 66 65 35 33 65 65 33 aec070645fe53ee3 
0010 - 62 33 37 36 33 30 35 39-33 37 36 31 33 34 66 30 b3763059376134f0 
0020 - 35 38 63 63 33 33 37 32-34 37 63 39 37 38 61 64 58cc337247c978ad 
0030 - 64 31 37 38 62 36 63 63-64 66 62 30 30 31 39 66 d178b6ccdfb0019f 
0040 - 0a            . 

Nếu bạn sử dụng openssl dgst -sha256 -binary <data.txt> hash để có được băm trong hệ nhị phân dưới dạng (tinh khiết), và sau đó ký tên, kết quả sẽ tốt hơn, nhưng vẫn không đúng:

# raw message as-is - we can see the same padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -raw -hexdump 
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00d0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff 00 ................ 
00e0 - ae c0 70 64 5f e5 3e e3-b3 76 30 59 37 61 34 f0 ..pd_.>..v0Y7a4. # the hash - now in binary form 
00f0 - 58 cc 33 72 47 c9 78 ad-d1 78 b6 cc df b0 01 9f X.3rG.x..x...... # 

# strip the padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -pkcs -hexdump 
0000 - ae c0 70 64 5f e5 3e e3-b3 76 30 59 37 61 34 f0 ..pd_.>..v0Y7a4. # just the hash, nothing else 
0010 - 58 cc 33 72 47 c9 78 ad-d1 78 b6 cc df b0 01 9f X.3rG.x..x...... # 

Nhưng khi bạn sử dụng openssl dgst -sha256 -sign ..., thông báo là khác nhau - bây giờ nó là cấu trúc chuẩn ASN.1 cho các thông báo tiêu hóa (băm). Hãy xem:

# raw message as-is - we can see the same padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -raw -hexdump 
0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff ................ 
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff 00 30 31 30 .............010 # 
00d0 - 0d 06 09 60 86 48 01 65-03 04 02 01 05 00 04 20 ...`.H.e....... # the message - it's different 
00e0 - ae c0 70 64 5f e5 3e e3-b3 76 30 59 37 61 34 f0 ..pd_.>..v0Y7a4. # <- we can see the hash (in binary form) starting at this line 
00f0 - 58 cc 33 72 47 c9 78 ad-d1 78 b6 cc df b0 01 9f X.3rG.x..x...... # 

# strip the padding 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -pkcs -hexdump 
0000 - 30 31 30 0d 06 09 60 86-48 01 65 03 04 02 01 05 010...`.H.e..... 
0010 - 00 04 20 ae c0 70 64 5f-e5 3e e3 b3 76 30 59 37 .. ..pd_.>..v0Y7 
0020 - 61 34 f0 58 cc 33 72 47-c9 78 ad d1 78 b6 cc df a4.X.3rG.x..x... 
0030 - b0 01 9f           ... 

# parse the message and show the underlying ASN.1 structure 
$ openssl rsautl -in signature -pubin -inkey public.pem -verify -pkcs -asn1parse 
    0:d=0 hl=2 l= 49 cons: SEQUENCE   
    2:d=1 hl=2 l= 13 cons: SEQUENCE   
    4:d=2 hl=2 l= 9 prim: OBJECT   :sha256    # type of hash 
    15:d=2 hl=2 l= 0 prim: NULL    
    17:d=1 hl=2 l= 32 prim: OCTET STRING  
     0000 - ae c0 70 64 5f e5 3e e3-b3 76 30 59 37 61 34 f0 ..pd_.>..v0Y7a4. # the hash in binary form 
     0010 - 58 cc 33 72 47 c9 78 ad-d1 78 b6 cc df b0 01 9f X.3rG.x..x...... # and no extra newline chars 

Như bạn có thể thấy, chỉ có signature tập tin cuối cùng có cấu trúc ASN.1 đúng đắn, trước hai người chỉ là "một số tùy ý" viết, ký kết với khóa bí mật RSA.

+0

Cảm ơn bạn, nó đã giải quyết được vấn đề của tôi. Tôi cũng tìm thấy chủ đề này: http://stackoverflow.com/questions/13419201/why-are-the-rsa-sha256-signatures-i-generate-with-openssl-and-java-different Nhưng tôi vẫn không ' t hiểu sự khác biệt về mật mã giữa các lệnh đó. Là padding khác nhau hoặc những gì? – GilCol

+0

@GilCol Tôi đã cập nhật câu trả lời của mình. – Roman

+0

Bạn vừa mới cứu mạng tôi với lời giải thích này, cảm ơn bạn! – GregaMohorko

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