使用 Crypto 打印 RSA 解密字节字符串?

Printing RSA Decrypted byte string with Crypto?

我通过 shell 运行这些命令序列,它们运行良好:

fishgills@fishgills-Mac  ~  cat /tmp/secret_message
Helloo there.%
fishgills@fishgills-Mac  ~  openssl rsautl -encrypt -inkey ~/Documents/test_pub.pem  -pubin -in /tmp/secret_message -out /tmp/test.enc
fishgills@fishgills-Mac  ~  openssl rsautl -decrypt -inkey ~/Documents/test.pem -in /tmp/test.enc
Helloo there.%
fishgills@fishgills-Mac  ~ 

如您所见,一切正常。加密消息并能够解密它。

所以在 python 中,我正在尝试做同样的事情:

from Crypto.PublicKey import RSA

rsakey = RSA.importKey(open("/Users/fishgills/Documents/test.pem", 'rb').read())
raw_data = open("/tmp/test.enc", 'rb').read()
decrypted = rsakey.decrypt(raw_data)
print decrypted

程序的输出是:

fishgills@fishgills-Mac  ~  python main.py ~/Documents/test.pem
�%��u�9��炿��:og:_�Z��WF/��W �v��������a�Jw+�J�Th�N9`V���5t##Go0�
#��A2e*����a�����a�ň��ߘhQX��U�7AB��B�Q�X�l��    ����rkK����� �kKj��\u���PILT�@���Rj���0:��߰9˕�Helloo there.

您可以在其中看到消息...但是有一堆垃圾。 PyCrypto 文档说 decrypt 方法 returns 一个字节字符串,但我无法 decode 它正确,我得到这样的东西:

Traceback (most recent call last):
  File "main.py", line 9, in <module>
    print decrypted.decode("utf-8")
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xd7 in position 1: invalid continuation byte

谁能给我指出正确的方向?

OpenSSL 默认使用 PKCS#1 v1.5 填充。但是,正如 documentation for Crypto.PublicKey 所说:

Attention: this function [decrypt(self, ciphertext)] performs the plain, primitive RSA decryption (textbook). In real applications, you always need to use proper cryptographic padding, and you should not directly decrypt data with this method.

所以如果你想在Python中解密你的消息,你需要使用a module that takes this padding into account

def test_decrypt():
    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_v1_5
    key = RSA.importKey(open('test.pem').read())
    cipher = PKCS1_v1_5.new(key)
    return cipher.decrypt(open("test.enc", 'rb').read(),'** decryption error **')

test_decrypt()

(注意:根据 Python 文档,您最好使用 PKCS#1 OAEP 而不是 PKCS#1 v1.5。在 OpenSSL 中,您可以通过添加 -oaep到命令行选项。Python中的解密代码非常相似,您可以参考documentation中的示例代码。)