10

如何/如何使用 python 和密码模块生成 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 文件)上。所述模块记录了如何解析/使用 PKCS12 格式,但没有(我能找到)关于如何生成它们的信息。

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

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

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

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

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

4

3 回答 3

12

如您所述,可以使用load_key_and_certificatescryptography解析 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

于 2019-02-16T11:57:18.897 回答
2

也许这里的代码可能有用?它不是密码学模块——它是 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.")
于 2019-02-15T21:11:02.870 回答
1

#这假设您已经创建了 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)
于 2021-01-06T19:05:53.367 回答