【问题标题】:How do/can I generate a PKCS#12 file using python and the cryptography module?如何/如何使用 python 和密码学模块生成 PKCS#12 文件?
【发布时间】:2019-07-07 17:43:17
【问题描述】:

如何/如何使用 python 和cryptography 模块生成 PKCS#12 文件?

使用该模块为私钥生成 .pem 文件的内容非常简单:

keyPEMBytes = privateKey.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.TraditionalOpenSSL,
    encryption_algorithm=serialization.NoEncryption())

也很容易为相关证书生成 .cer/.pem 文件的内容:

certBytes = certificate.public_bytes(encoding=serialization.Encoding.PEM)

但我需要将它们(和它们的链)打包在一个 .p12(PKCS12 文件)上。所述模块文档how to parse/consume PKCS12 formats,但没有(我能找到)关于如何生成它们的信息。

我对 PKI 东西的理解是偶然的,所以也许我只是没有在文档中搜索正确的关键字?

可以在 Linux 上使用命令行创建 .p12 文件

openssl pkcs12 -export -out myIdentity.p12 -inkey myPrivKey.pem -in myCert.crt -certfile myCertChain.crt

所以我可以用 subprocess/cmd 来包装这样的调用,并弄乱临时文件/管道。我希望把它全部保存在内存/python中。

我应该考虑一个不同的 python TLS 库,可以做到这一点吗?

【问题讨论】:

    标签: python python-3.x pkcs#12 python-cryptography


    【解决方案1】:

    也许代码here 可能有用?它不是密码学模块——它是 chilkat,但它可以完成这项工作。

    import sys
    import chilkat
    
    #  First load our certificate into a certificate object,
    #  and then get it as a cert chain object.
    cert = chilkat.CkCert()
    
    success = cert.LoadFromFile("qa_data/rsaes-oaep/cert.pem")
    if (success != True):
        print(cert.lastErrorText())
        sys.exit()
    
    #  This is the certificate PEM that we loaded:
    
    #  -----BEGIN CERTIFICATE-----
    #  MIIDozCCAougAwIBAgIJAMRwugDmvniwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
    #  BAYTAlVTMQswCQYDVQQIDAJJTDEQMA4GA1UEBwwHV2hlYXRvbjEhMB8GA1UECgwY
    #  SW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRcwFQYDVQQDDA5DaGlsa2F0V2lkZ2V0
    #  czAeFw0xNzA0MTgxMzQxNDVaFw0yMjA0MTcxMzQxNDVaMGgxCzAJBgNVBAYTAlVT
    #  MQswCQYDVQQIDAJJTDEQMA4GA1UEBwwHV2hlYXRvbjEhMB8GA1UECgwYSW50ZXJu
    #  ZXQgV2lkZ2l0cyBQdHkgTHRkMRcwFQYDVQQDDA5DaGlsa2F0V2lkZ2V0czCCASIw
    #  DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXhMR7TNHSaHgrEGvAmHNqw/8xV
    #  5TcngVO//yHBniDHas5b2zm0AkhY5EW9dn0wTWHivoRZC2soH7/bxRi4uYUaxgve
    #  YLXw6DO2MHSpuTvhSG3+AjsBDa9kXegn9XT1MdPHk9PrHR0sKXGuimkLf4r+Q1oM
    #  iGlhbUyRATwVlmo6AndgniDnj2RFBYV8E8SQ+7SnLPJdXZRDbLNVY/DY6D9stRAY
    #  rHuz/WBlVW7TQVuWwe7Cd9bfFqjqzLwLksKevWvHGteYDGeiCi+uvMMNfp/Br79Y
    #  zJYF/YpTJYE0POBiMwth1FUIYKpZf/O2eUd6RW9h6hocC5QWU9LAq+7kKFMCAwEA
    #  AaNQME4wHQYDVR0OBBYEFKBCsni1BfOyH3dSoY8yL4mDeNbpMB8GA1UdIwQYMBaA
    #  FKBCsni1BfOyH3dSoY8yL4mDeNbpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
    #  BQADggEBAF2iV69ma5XegVWpxbc0gui63RE8NjW2dBW0fa4a4fwNH2f8oetZEjw4
    #  kscx7p4ESxyPtDUkLNplAth+D8NNh9IQDWIld+FZrJsis4tkpVcpMsbmB2CW8fL2
    #  IVnVznAN+/PMYEAkeSOnovUGlREHZZu4b9rMVm89+aoCQ9z+byjW9kLKHyvLnUai
    #  uEHp+0EVFP91CRSIcTCXsW1c5yZ8k5bqL0HlauuOO4TA3IegyYM9xBubmcxg8cRO
    #  2F1k+Ge1lu3e+WY+lihaO0p762dF6g/SUMMrFneCPdIhvt4u7Esc9FDxE3xZEq3x
    #  cS5sHTxtTM0LVBi378/x5m1hln5hSJU=
    #  -----END CERTIFICATE-----
    
    #  Get it as a certificate chain.
    # certChain is a CkCertChain
    certChain = cert.GetCertChain()
    if (cert.get_LastMethodSuccess() != True):
        print(cert.lastErrorText())
        sys.exit()
    
    #  Next, load the corresponding private key from a PEM.
    privKey = chilkat.CkPrivateKey()
    success = privKey.LoadPemFile("qa_data/rsaes-oaep/privateKey.pem")
    if (success != True):
        print(privKey.lastErrorText())
    
        sys.exit()
    
    #  This is the private key PEM:
    
    #  -----BEGIN RSA PRIVATE KEY-----
    #  MIIEpAIBAAKCAQEAxeExHtM0dJoeCsQa8CYc2rD/zFXlNyeBU7//IcGeIMdqzlvb
    #  ObQCSFjkRb12fTBNYeK+hFkLaygfv9vFGLi5hRrGC95gtfDoM7YwdKm5O+FIbf4C
    #  OwENr2Rd6Cf1dPUx08eT0+sdHSwpca6KaQt/iv5DWgyIaWFtTJEBPBWWajoCd2Ce
    #  IOePZEUFhXwTxJD7tKcs8l1dlENss1Vj8NjoP2y1EBise7P9YGVVbtNBW5bB7sJ3
    #  1t8WqOrMvAuSwp69a8ca15gMZ6IKL668ww1+n8Gvv1jMlgX9ilMlgTQ84GIzC2HU
    #  VQhgqll/87Z5R3pFb2HqGhwLlBZT0sCr7uQoUwIDAQABAoIBAGCP5LWDIWzpLFHa
    #  or6gCqKZjyo6nFFO4Ohqn+jsH+slBTTQVGmTMy302uhBbYnnwUtMJ+ZTwaO3/85T
    #  Q5otwrJ2f0CZcx42AkoB1SGJFVBoPj0WoCYE/JWjZ8P7g+dgI8GR+cyHRjzPKSZF
    #  o1thdgrwyxMtXH/4QCsF89FLQ4xwCJUkj+w0KBkX8isWcBJnKip81MK8rxhgMJ6v
    #  5+DBVvlvm4BRz0hva7HB3TaZgo9ZWZdoSJQ/l33yfIL8H0EJjC6uJ/Bn77JtDzcv
    #  1oUF02Ebu8/Re7RpUqdTIb1GamrOCjuZN66SrCOsh9rRzueU3UTLzjb9FDv8FQDA
    #  5Dm59KECgYEA6zJ2LaiUywth80rAC34jEF85aC3vyKK0MxYELLB9Nw6MNFD1PZly
    #  YkOcI2kxVV+1KqtRYFlfEpCL4flqVnqjVj5jTCCOXqO6RjnPLoupf0yLpj60raO6
    #  Ouw5EDGjfUDBQtkCQNOx0nZLftVy30Ck/V2gVw9sEgWQV0YRavuymKMCgYEA12HB
    #  eHHSo/dK7keiIK7RRQu2ibALXWXsGq9lUbnQAunKRCa3qQtc8OwGRZsdj9u8HwCB
    #  zDu5QIbaQCa1SyDz1CsOysOfTYNhh1SZ4GLiu7/b0v5ktgdtosT9niowo08Y4ZU+
    #  lA8p2eriylznacNOkA8O1g8m1etHqV+cVKUMvJECgYEApoeVO6DosZd+pCfiMIEA
    #  TMBPwl78L6BcXOuSyx2vmwMW7JgB/LqgTck3Ta9Wue9JNEwXE1RUR63HDZpu24p8
    #  Cj2kSyumAoaFBuI5uugyfCrzmiM+BNAvtTa69Kdg7feinzVOLh52AuG1dLmnW0HH
    #  UIoxVFNcHqqH1/OJs6lBfGcCgYEAkQXhn5gEnSMF8SuKnzcW8cbRQiSnglv+fnlb
    #  X4wd49hHuVvYjpp4GkDSeEvZu+PY54cP3tTYB/rFOizWJaAqjdHwQ9c0jJzKLrVo
    #  Zw4uXPzypz9j0K1vxQmfO8Bsv4mi10IGwOr04yalTlz/9NbtL1L0Sm4pWCD0P7eB
    #  K/12dgECgYBXNV5NcLpZhpjo8q05xAiFuwC2e29qYyVwcFVhYdYguutRKImZtjSE
    #  dndNAxa7EDL9NRc5SjX4NHAZoImADRSbgc2rIq2ePY8WORaR+iKsVx7PJGHSiXTL
    #  30X9E3com8ctyTsZTnlJ4Dm7SefkN0NKzqwjxXxZLaUteWBPUt+YAg==
    #  -----END RSA PRIVATE KEY-----
    
    #  Create a PFX object instance, and add the private key + cert chain.
    pfx = chilkat.CkPfx()
    success = pfx.AddPrivateKey(privKey,certChain)
    if (success != True):
        print(pfx.lastErrorText())
    
        sys.exit()
    
    #  Finally, write the PFX w/ a password.
    success = pfx.ToFile("pfxPassword","qa_output/sample.pfx")
    if (success != True):
        print(pfx.lastErrorText())
        sys.exit()
    
    print("Success.")
    

    【讨论】:

      【解决方案2】:

      如您所述,cryptography 可以使用load_key_and_certificates 解析 PKCS12(至少是 99.99% 的人使用的子集),但目前不支持序列化为 PKCS12。

      我是该项目的核心开发人员之一,总的来说,cryptography 的功能集是由用户提交的问题驱动的,这些问题解释了他们的用例和对特定功能的需求。我建议在跟踪器上写一些东西以供讨论。听起来您的需求将由一个大致如下所示的简单 API 满足:

      from cryptography.hazmat.primitives.serialization.pkcs12 import generate_pkcs12
      
      pem_pkcs12 = generate_pkcs12(
          BestAvailableEncryption(b"somepassword"), 
          key, 
          [cert1, cert2]
      )
      

      更新:此功能在 pyca/cryptography 3.0 中实现:

      https://cryptography.io/en/latest/hazmat/primitives/asymmetric/serialization.html?highlight=pkcs12#cryptography.hazmat.primitives.serialization.pkcs12.serialize_key_and_certificates

      【讨论】:

        【解决方案3】:

        #假设你已经创建了 server.key 和 server.pem

        import sys
        import os
        from OpenSSL import crypto
        
        try:
          PFX_Passcode = os.environ['PFX_Passcode']
        except KeyError:
          sys.exit('One or more required environment variables not set, required: PFX_Passcode')
        
        with open('server.key', "r") as f:
          privkeydata = f.read()
        with open('server.pem', 'r') as f:
          certdata = f.read()
        cert = crypto.load_certificate(crypto.FILETYPE_PEM, certdata)
        privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkeydata)
        p12 = crypto.PKCS12()
        p12.set_privatekey(privkey)
        p12.set_certificate(cert)
        p12data = p12.export(PFX_Passcode)
        with open('server.pfx', 'wb') as pfxfile:
          pfxfile.write(p12data)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-21
          • 1970-01-01
          • 2016-11-17
          • 2010-10-07
          • 2020-09-16
          • 2021-02-16
          • 2011-06-08
          • 2012-09-19
          相关资源
          最近更新 更多