如何从 openSSL 中的 PKCS#11 模块中读出私钥?

mic*_*ael 1 openssl cryptography pkcs#11 hsm private-key

问题的答案

如何在 PKCS#11 模块上使用私钥而不是 perivate 密钥文件在 OpenSSL 中进行相互身份验证?

非常清楚地解释了使用存储在智能卡或 HSM(硬件安全模块)上而不是普通文件上的私钥建立 SSL 连接所需的步骤。其实我想用python做同样的事情,但首先我必须了解背后的原理。所以暂时忘记python:

假设密钥已经存在于 HSM 上的“SecureToken”下。所以

  1. 我首先必须从引擎加载私钥:

    EVP_PKEY* key = ENGINE_load_private_key(e, "SecureToken", NULL, &cb_data);

  2. 然后必须打电话

    SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);

现在,我有一个带有 PKCS#11 接口的 HSM,我可以将其作为 openSSL 引擎加载。慢慢地我对原理有了更好的了解,但是,私钥如何离开模块仍然是个谜:为了将私钥始终保存在模块内,这就是我完全使用 HSM 的原因。

具体来说:我从 1) 中调用的返回值中返回什么作为“键”?我无法想象密钥内容是从 HSM 中读出的,因为 PKCS#11 甚至不支持此操作。我还能得到什么?它只是有关HSM 中密钥的元信息而不是密钥本身吗?并且 SSL_CTX * ctx 稍后如何知道,该“密钥”将如何使用?

鉴于 PKCS#11 引擎已正确加载,这是否意味着任何 RSA 函数都会与存储在上下文中的“元密钥信息”一起自动委托给 HSM ?

请确认这个假设或让我知道我错在哪里。

无论如何,我发现了 EVP_PKEY 是什么:

    struct evp_pkey_st {
        int type;
        int save_type;
        int references;
        const EVP_PKEY_ASN1_METHOD *ameth;
        ENGINE *engine;
        union {
            char *ptr;
    # ifndef OPENSSL_NO_RSA
            struct rsa_st *rsa;     /* RSA */
    # endif
    # ifndef OPENSSL_NO_DSA
            struct dsa_st *dsa;     /* DSA */
    # endif
    # ifndef OPENSSL_NO_DH
            struct dh_st *dh;       /* DH */
    # endif
    # ifndef OPENSSL_NO_EC
            struct ec_key_st *ec;   /* ECC */
    # endif
        } pkey;
        int save_parameters;
        STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
    } /* EVP_PKEY */ ;
Run Code Online (Sandbox Code Playgroud)

这个结构的关键在哪里?如果 2) 中参数的 pkey 尚未从引擎加载(在我根本不使用引擎的情况下)怎么办?

eri*_*son 5

私钥不会离开模块。密文(或哈希)发送给模块进行解密(或签名),返回明文(或签名)。

您拥有的“键”不是编码键参数的大整数集合。相反,它是一个指向处理与模块交互的引擎的指针,该模块安全地包含该信息。

另一方面,关联的证书或公钥可以从模块中导出。这表示私钥的算法和大小,证书可以在字段和扩展中携带额外的元数据。