【问题标题】:How to pass Passphrase programmatically in Python如何在 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 密码的人工干预?

【问题讨论】:

  • 自动注入密码不会增加任何安全性。您应该考虑从密钥中删除密码。

标签: python python-2.7 python-requests


【解决方案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 调用期间使用密码密钥来解密它。我只是想分享我的代码来回答这个问题。这段代码对我有用。

      【讨论】:

      • 这样更好。这样我可以在运行时提供密码。
      猜你喜欢
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      • 2015-03-17
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多