2013-10-23 14 views
6

Theo như tôi hiểu, tôi sẽ có thể sử dụng RSA để đảm bảo tính xác thực hoặc quyền riêng tư, như tôi muốn. Trong trường hợp của tôi, tôi muốn đảm bảo tính xác thực để tôi mã hóa dữ liệu bằng khóa riêng và cho phép bất kỳ ai giải mã nó bằng khóa công cộng. Dữ liệu không thực sự bí mật nhưng tôi cần đảm bảo rằng nó được tạo bởi chủ sở hữu của khóa công khai (và riêng tư).Giải mã bằng khóa công cộng RSA với PyCrypto

Khi tôi cố gắng giải mã bằng PyCrypto, tôi nhận được Không có khóa riêng tư lỗi từ PyCrypto. Mã này là:

def _decrypt_rsa(decrypt_key_file, cipher_text): 
    from Crypto.PublicKey import RSA 
    from base64 import b64decode 

    key = open(decrypt_key_file, "r").read() 
    rsakey = RSA.importKey(key) 
    raw_cipher_data = b64decode(cipher_text) 
    decrypted = rsakey.decrypt(raw_cipher_data) 
    return decrypted 

Tôi đang gọi nó bằng đường dẫn đến tệp khóa công khai (ở định dạng OpenSSH.) Dữ liệu được mã hóa không được tạo bởi tôi và không được thực hiện bằng Python nhưng PHP. Trong PHP có một hàm openssl_public_decrypt giải mã dữ liệu này dễ dàng.

Hoàn toàn có thể giải mã bằng khóa công khai với PyCrypto không?

+1

Bạn đã hoàn tác. Khóa công khai được sử dụng để mã hóa và khóa riêng được sử dụng để giải mã. – jchysk

+1

Giải mã công khai giống như mã hóa. Vấn đề của bạn có thể được sửa theo cách này: 'decrypted = rsakey.encrypt (raw_cipher_data, 0)' – Helio

+0

Nếu nguồn thực sự đã được mã hóa bằng khóa riêng, thì chúng đã ký hiệu quả dữ liệu. Một số công cụ, như Java, cho phép bạn làm điều này. Để giải mã chữ ký, bạn có thể sử dụng khóa công khai (hoặc phần công khai của khóa riêng). Xem: https://stackoverflow.com/questions/48280670/pycrypto-how-to-view-raw-rsa-signature-data –

Trả lời

5

Điều đó hoàn toàn không an toàn, bởi vì bạn đang sử dụng RSA thô không có đệm.

Đơn đăng ký của bạn cần chữ ký, vì vậy bạn không nên xử lý việc mã hóa và giải mã. Ví dụ, PKCS # 1 v1.5 là một giao thức tốt, mặc dù chữ ký là một phần dữ liệu phải được nối thêm vào những gì bạn muốn chứng minh tính xác thực của.

Để xác minh PKCS # 1 v1.5 chữ ký trong Python, bạn làm:

from Crypto.PublicKey import RSA 
from Crypto.Signature import PKCS1_v1_5 
from Crypto.Hash import SHA 

rsa_key = RSA.importKey(open(verification_key_file, "rb").read()) 
verifier = PKCS1_v1_5.new(rsa_key) 
h = SHA.new(data_to_verify) 
if verifier.verify(h, signature_received_with_the_data): 
    print "OK" 
else: 
    print "Invalid" 

Tôi rất muốn giới thiệu để thay đổi mã PHP để nó tạo ra một chữ ký như vậy.

+0

Cảm ơn đề xuất của bạn, tôi sẽ không nghi ngờ gì nữa. Bạn có thể giải thích về những gì không an toàn khi sử dụng khóa công khai để giải mã một đoạn dữ liệu không bí mật để chứng minh tính xác thực không? Bạn đang nói nó có thể bị giả mạo bởi vì tôi không có đệm? – sergiopereira

+0

Một người không có khóa bí mật vẫn có thể giả mạo thứ gì đó giống như thông báo hợp lệ đến từ chủ sở hữu thực sự. Đó là do thực tế rằng RSA là một thuật toán khá dễ uốn nếu không được kết hợp với một padding đã được chứng minh. Những gì bạn mô tả thực sự là một chữ ký với cái gọi là khôi phục tin nhắn đầy đủ: một ví dụ là tiêu chuẩn ISO 9796-1, mà là hoàn toàn bị hỏng. – SquareRootOfTwentyThree

+0

không nên "nhập" là "importKey"? –

0

Chức năng của bạn là chính xác. Bạn chỉ cần cho nó đường dẫn đến khóa riêng của bạn để giải mã thay vì khóa công khai của bạn. Khóa công khai là để mã hóa, khóa riêng là để giải mã.

def _decrypt_rsa(decrypt_key_file, cipher_text): 
    ''' 
    Decrypt RSA encrypted package with private key 
    :param decrypt_key_file: Private key 
    :param cipher_text: Base64 encoded string to decrypt 
    :return: String decrypted 
    ''' 
    from Crypto.PublicKey import RSA 
    from base64 import b64decode 

    key = open(decrypt_key_file, "r").read() 
    rsakey = RSA.importKey(key) 
    #optionally could use OAEP 
    #from Crypto.Cipher import PKCS1_OAEP 
    #rsakey = PKCS1_OAEP.new(rsakey) 
    raw_cipher_data = b64decode(cipher_text) 
    decrypted = rsakey.decrypt(raw_cipher_data) 
    return decrypted 
+1

Sau đó, tôi sẽ không thể đảm bảo ai đã mã hóa tin nhắn. Tôi đã kết thúc theo đề xuất trong câu trả lời được chấp nhận và thay vào đó chúng tôi đã chuyển sang sử dụng chữ ký. Ngoài ra, vấn đề của tôi liên quan đến mã thông báo OAuth và cuối cùng chúng tôi đã chuyển sang JWT, sử dụng chữ ký. – sergiopereira

+0

Đúng, bạn sẽ không thể xác định tính xác thực trừ khi người gửi nó đã ký tin nhắn bằng khóa riêng của họ và bạn đã có khóa công khai mà họ đã xác minh riêng là của họ. Với JWT, bạn vẫn có thể sử dụng RSA để ký với một thuật toán như RS512.Nếu bạn tập trung vào việc đảm bảo tính xác thực của người gửi, bạn nên tập trung vào thuộc tính của tổ chức phát hành. – jchysk

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