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

Posted

技术标签:

【中文标题】如何在 Python 中以编程方式传递密码【英文标题】:How to pass Passphrase programmatically in Python 【发布时间】:2019-01-23 02:17:59 【问题描述】:

我正在使用请求库来自动化 API/微服务。我尝试在获取请求中传递 URL、证书(证书文件和密钥文件的路径)。

运行程序后,它会询问 PEM 密码。请参考下面的命令提示行。

>>> r = requests.get("https://foo.example.com/api/user/bill", cert=("client.crt", "client.key"))
Enter PEM pass phrase:
>>>

如何在程序中以编程方式传递密码以避免在程序中输入 PEM 密码的人工干预?

【问题讨论】:

自动注入密码不会增加任何安全性。您应该考虑从密钥中删除密码。 【参考方案1】:

在撰写本文时(2018 年 8 月),您似乎运气不佳。有一个open issue on the requests tracker from September 2013 可以解决这种情况。列出了几种解决方法,涉及使用不同的库,或在没有密码的情况下生成新密钥。

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

这有点问题,因为您通常总是希望使用密码保护包含私钥的 .pem 文件。 openssl 甚至不会让你创建一个没有密码的。

【讨论】:

【参考方案2】:

请求库还不支持受密码保护的 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

【讨论】:

【参考方案3】:

我认为,您正在请求模块中寻找“verify”选项。

查看link

尝试以下步骤:

将密码保存在 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): 最大重试次数超出 url: /info (由 SSLError(SSLError(0, u'unknown error (_ssl .c:2825)'),)) 感谢 Dinesh,尝试使用您提供的代码并得到上述响应 还尝试将 https 替换为 http 并得到以下错误:requests.exceptions.ConnectionError: HTTPConnectionPool(host='URL', port=80): Max retries exceeded with url: /info(由NewConnectionError(': 无法建立新连接: [Errno 10060] 连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立连接失败,因为连接主机未能响应',))【参考方案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 调用期间使用密码密钥来解密它。我只是想分享我的代码来回答这个问题。这段代码对我有用。

【讨论】:

这样更好。这样我可以在运行时提供密码。

以上是关于如何在 Python 中以编程方式传递密码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux Mint 中以编程方式发送密钥(模拟密钥输入)?

如何在 Windows 中以编程方式切换用户

如何在kivymd python的MDDataTable中以编程方式取消选中复选框

如何在 swift Xcode 中以编程方式绑定/配对蓝牙 LE 设备?

在 Swift 中以编程方式制作 Segue

如何在 python3.5 中以编程方式运行 ansible-playbook 时设置额外的变量?(Ansible 版本 - 2.8)