【问题标题】:How to create x X.509 certificate without direct access to the private key?如何在不直接访问私钥的情况下创建 x X.509 证书?
【发布时间】:2020-04-10 09:27:08
【问题描述】:

使用 HSM 我可以下载 RSA 4096 的公钥,并且可以使用 HSM 使用我无法下载的相应私钥加密 blob。 我正在尝试查找有关如何使用 HSM api 自己构建 X509 证书的参考。我可以在 python 中找到下面的示例,包装 openssl 库。 它几乎可以做所有事情,但是

from OpenSSL import crypto, SSL
from socket import gethostname
from pprint import pprint
from time import gmtime, mktime

CERT_FILE = "selfsigned.crt"
KEY_FILE = "private.key"

def create_self_signed_cert():

    # create a key pair
    k = crypto.PKey()
    k.generate_key(crypto.TYPE_RSA, 1024)

    # create a self-signed cert
    cert = crypto.X509()
    cert.get_subject().C = "UK"
    cert.get_subject().ST = "London"
    cert.get_subject().L = "London"
    cert.get_subject().O = "Dummy Company Ltd"
    cert.get_subject().OU = "Dummy Company Ltd"
    cert.get_subject().CN = gethostname()
    cert.set_serial_number(1000)
    cert.gmtime_adj_notBefore(0)
    cert.gmtime_adj_notAfter(10*365*24*60*60)
    cert.set_issuer(cert.get_subject())
    cert.set_pubkey(k)
    cert.sign(k, 'sha1')

    open(CERT_FILE, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
    open(KEY_FILE, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))

create_self_signed_cert()

大多数情况下,我希望可以替换该行

   cert.sign(k, 'sha1')

通过“证书”结构的“导出”对我的 HSM 的 API 进行相应调用。有可能吗?

【问题讨论】:

  • 如果它可能的,那不是完全违背了拥有证书的目的吗?
  • 一点也不。您使用私钥生成证书。在您拥有某种凭据的基于硬件的设备中进行加密,而不是在您计算机上的文件上进行加密实际上是您想要的方式。通常 OpenSSL 或其他桌面将支持与 HSM 透明对话的引擎。就我而言,希望能够以编程方式完成。

标签: python openssl x509


【解决方案1】:

所以经过一天的研究,我在Adding a signature to a certificate 找到了满意的答案。虽然似乎有一些 Python 示例说明了如何使用 pyasn1 通过 Python 构建证书,但最健壮的似乎是 java 中使用 boucycastle 库的示例。我还在How to generate certificate if private key is in HSM?(主要是第 3 点和第 4 点)找到了如何将其与 openssl 结合的有力答案,但这种方法远远超出了我的能力。

【讨论】:

    【解决方案2】:

    当您希望其他人(例如您的 HSM)为您签署证书时,执行此操作的标准方法是生成 Certificate Signing Request (CSR) 并将 CSR 发送给签名者。 CSR 可以包含您在制作证书时可以设置的所有字段,这些值将反映在生成的证书中。

    虽然您可以使用您正在使用的 OpenSSL 库执行此操作,但请参阅 X509Req,他们的文档(我引用)“强烈建议”您改用 cryptography 库。 (它们由同一组人维护。)

    在密码库中,您可以使用 CertificateSigningRequestBuilder 来创建 CSR。引用他们的文档:

    >>> from cryptography import x509
    >>> from cryptography.hazmat.primitives import hashes
    >>> from cryptography.hazmat.primitives.asymmetric import rsa
    >>> from cryptography.x509.oid import AttributeOID, NameOID
    >>> private_key = rsa.generate_private_key(
    ...     public_exponent=65537,
    ...     key_size=2048,
    ... )
    >>> builder = x509.CertificateSigningRequestBuilder()
    >>> builder = builder.subject_name(x509.Name([
    ...     x509.NameAttribute(NameOID.COMMON_NAME, u'cryptography.io'),
    ... ]))
    >>> builder = builder.add_extension(
    ...     x509.BasicConstraints(ca=False, path_length=None), critical=True,
    ... )
    >>> builder = builder.add_attribute(
    ...     AttributeOID.CHALLENGE_PASSWORD, b"changeit"
    ... )
    >>> request = builder.sign(
    ...     private_key, hashes.SHA256()
    ... )
    >>> isinstance(request, x509.CertificateSigningRequest)
    True
    

    以通常用于发送 CSR 的格式呈现 CSR:

    >>> from cryptography.hazmat.primitives import serialization
    >>> request.public_bytes(serialization.Encoding.PEM)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-02
      • 2018-09-05
      • 1970-01-01
      • 2011-07-09
      • 2013-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多