如何在 PyCrypto 中使用加密的 RSA 私钥? [英] How to use encrypted RSA private key with PyCrypto?

查看:58
本文介绍了如何在 PyCrypto 中使用加密的 RSA 私钥?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 OpenSSL 生成一个密钥,提供来自标准输入的密码:

openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096

密钥看起来像:

-----开始加密私钥--XXX...-----结束加密私钥-----

我的 Python 代码如下所示:

from Crypto.PublicKey 导入 RSA# ...f = open('private-key.pem', 'r')r = RSA.importKey(f.read(), passphrase='some-pass')f.close()

但我得到了一个例外:

 文件/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py",第 665 行,在 importKey 中返回 self._importKeyDER(der)_importKeyDER 中的文件/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py",第 588 行引发 ValueError("不支持 RSA 密钥格式")ValueError: 不支持 RSA 密钥格式

怎么了?

是否可以生成加密的 RSA 密钥,将其存储在文件中,然后与 PyCrypto 一起使用?是否可以使用 OpenSSL 做到这一点?支持哪些格式?

导入公钥工作正常,但未加密.

解决方案

假设 #1

查看源代码后,我想,我解开了这个谜.对于使用密码加密的 PEM 密钥,导入的工作方式是将 PEM 解密为 DER,然后调用 importKeyDER 函数.如果提供的密码不正确,生成的 DER 表示的格式也将不正确,您将收到您提供的异常.为了确认这一点,我在下面进行了两个快速测试:

<预><代码>>>>从 Crypto.PublicKey 导入 RSA>>>f = open('/private-key.pem','r')>>>r=RSA.importKey(f.read(),passphrase='foo')回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中文件/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py",第 665 行,在 importKey 中返回 self._importKeyDER(der)_importKeyDER 中的文件/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py",第 588 行引发 ValueError("不支持 RSA 密钥格式")ValueError: 不支持 RSA 密钥格式>>>f = open('/private-key.pem','r')>>>r=RSA.importKey(f.read(),passphrase='')>>>r<_RSAobj @0xb7237b2c n(4096),e,d,p,q,u,private>

在收到作者的 PEM 后,我意识到假设 #1 不适用于他的案例.我还是想把它留在这里,作为导入失败的一个可能原因,让其他用户知道.

假设 #2 - 这是作者的情况.

RSA.py 在 PEM 文件中查找以下内容以确定应用于 PEM 的加密类型:

 Proc-Type: 4,ENCRYPTED

当使用openssl genrsa ..."命令生成密钥时,此字符串以明文形式存在于 PEM 中,但是当使用opensl genpkey ..."时,Proc-Type"不存在.

如果未找到Proc-Type",RSA.py 甚至不会尝试解密 PEM:

 # 加密的 PEM 格式if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):DEK = lines[2].split(b(':'))....

所以,我此时的结论是 PyCrypto v 2.6.1 不支持openssl genpkey"生成的密钥.

重要更新

它确实适用于 PyCrypto 的最新版本 2.7a1.你可以从这里下载:http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz

<预><代码>>>>f = open('key.pem','r')>>>r = RSA.importKey(f.read(), passphrase='123456')>>>r<_RSAobj @0xb6f342ec n(2048),e,d,p,q,u,private>

I am generating a key with OpenSSL, providing the password from stdin:

openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096

The key then looks like:

-----BEGIN ENCRYPTED PRIVATE KEY-----
XXX...
-----END ENCRYPTED PRIVATE KEY-----

My Python code looks like:

from Crypto.PublicKey import RSA
# ...
f = open('private-key.pem', 'r')
r = RSA.importKey(f.read(),  passphrase='some-pass')
f.close()

but I am getting an exception:

  File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 665, in importKey
    return self._importKeyDER(der)
  File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 588, in _importKeyDER
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported

What's wrong?

Is it possible to generate an encrypted RSA key, store it in a file and later use it with PyCrypto? Is it possible to do it with OpenSSL? What formats are supported?

Importing the public key works fine, however it is not encrypted.

解决方案

Hypothesis #1

After looking to the source code, I think, I solved the mystery. The way how import works for PEM keys encrypted with a password is that the PEM gets decrypted to DER and after that importKeyDER function is called. If provided password is not correct, the format of generated DER representation will not be correct too and you would get an exception that you've provided. To confirm that, I ran two quick tests below:

>>> from Crypto.PublicKey import RSA
>>> f = open('<some-path>/private-key.pem','r')
>>> r=RSA.importKey(f.read(),passphrase='foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 665, in importKey
    return self._importKeyDER(der)
  File "/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 588, in    _importKeyDER
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported
>>> f = open('<some-path>/private-key.pem','r')
>>> r=RSA.importKey(f.read(),passphrase='<valid-pass-phrase>')
>>> r
<_RSAobj @0xb7237b2c n(4096),e,d,p,q,u,private>

After receiving the PEM from the author, I've realized that Hypothesis #1 is not valid for his case. I still want to keep it here as one possible reason of import failure, so other users are aware.

Hypothesis #2 - this is the author's case.

RSA.py looks for the following in PEM file to determine what kind of encryption was applied to PEM:

 Proc-Type: 4,ENCRYPTED

When key is generated using "openssl genrsa ..." command, this string is present in PEM in clear, however when "opensl genpkey ..." is used the "Proc-Type" is not present.

RSA.py doesn't even try to decrypt the PEM if the "Proc-Type" is not found:

  # The encrypted PEM format
  if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
     DEK = lines[2].split(b(':'))
     ....

So, my conclusion at this time is that keys generated by "openssl genpkey" are not supported by PyCrypto v 2.6.1.

Important Update

It does work in PyCrypto's latest version 2.7a1. You can download it from here: http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz

>>> f = open('key.pem','r')
>>> r = RSA.importKey(f.read(),  passphrase='123456')
>>> r
<_RSAobj @0xb6f342ec n(2048),e,d,p,q,u,private>

这篇关于如何在 PyCrypto 中使用加密的 RSA 私钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆