如何在Python中以编程方式传递密码短语

6
我正在使用request库来自动化API和微服务。我试过在get请求中传递URL、证书(证书文件和密钥文件的路径)。运行程序后,它要求输入PEM密码。请参考下面的命令提示符行。
>>> r = requests.get("https://foo.example.com/api/user/bill", cert=("client.crt", "client.key"))
Enter PEM pass phrase:
>>>

如何在程序中以编程方式传递密码短语,以避免在程序中手动输入PEM密码短语的干预?

2
自动注入密码不会增加任何安全性。您应考虑从密钥中删除密码。 - Klaus D.
4个回答

5

requests库目前不支持受密码保护的PEM文件。

一种选择是将其转换为pkcs12文件,并使用来自https://pypi.org/project/requests-pkcs12/ 的requests-pkcs12库。

另一个选择是将其转换为不带密码的pkcs12文件,然后再转换为PEM文件。

以下是如何进行转换:

# Password protected PEM to pkcs12
openssl pkcs12 -export -out cert.p12 -in cert.pem -inkey key.pem -passin pass:supersecret -passout pass:supersecret
# pkcs12 to PEM without password
openssl pkcs12 -in cert.p12 -out cert_without_pwd.pem -nodes -password supersecret

openssl pkcs12 -in cert.p12 -out cert_without_pwd.pem -nodes -password pass:supersecret - Tanmoy Banerjee

4
import requests
from urllib3.util.ssl_ import create_urllib3_context
from requests.adapters import HTTPAdapter

cert_path = "path/to/certfile.crt"
private_key_path = "path/to/private_certificate_file.pem"
passphrase_key = "someSecretKey"

class SSLAdapter(HTTPAdapter):    
    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context()
        context.load_cert_chain(certfile=cert_path, keyfile=private_key_path, password=passphrase_key)
        kwargs['ssl_context'] = context
        return super().init_poolmanager(*args, **kwargs)

session = requests.Session()
session.verify = False # If you don't want to validate server's public certificate
session.mount("https://", SSLAdapter())
response = session.post(url)
print(response.json())

最近我也遇到了同样的问题,即我有一个加密的私有证书,而且我必须在 Python 的 REST API 调用期间使用口令密钥对其进行解密。我想分享我的代码来回答这个问题。这段代码对我来说是有效的。


这样更好。这样我可以在运行时提供密码。 - bosari
1
我运行了这段完全相同的代码,但是我删除了session.verify = False这一行,它就正常工作了。非常感谢你,Shubham。 - angelacpd

2
在撰写本文时(2018年8月),看起来你很不走运。有一个自2013年9月以来就存在的请求跟踪问题正好解决了这个问题。列出了几种解决方法,其中包括使用不同的库或生成没有密码保护的新密钥。

据我所知,目前无法指定用于验证的客户端证书的密码。

这是一个问题,因为您通常总是希望对包含私钥的.pem文件进行密码保护。openssl甚至不允许您创建没有密码的文件。


1

我想你正在寻找请求模块中的“verify”选项。

请查看链接

尝试以下步骤:

  • 将密语保存在PEM文件中,例如:test.pem
  • 使用以下代码:

r = requests.get("https://foo.example.com/api/user/bill", cert=("client.crt", "client.key"), verify="test.pem")

requests.exceptions.SSLError: HTTPSConnectionPool(host='URL', port=443): Max retries exceeded with url: /info (Caused by SSLError(SSLError(0, u'unknown error (_ssl.c:2825)'),)) 谢谢Dinesh,我尝试了你提供的代码,但是得到了上述响应。 - Anup Patil
还尝试将https替换为http,但出现以下错误:requests.exceptions.ConnectionError: HTTPConnectionPool(host='URL', port=80): Max retries exceeded with url: /info (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x03001770>: Failed to establish a new connection: [Errno 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond',)) - Anup Patil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接