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

How is private key read out from a PKCS#11 module in openSSL?

问题的答案

How to use private key on a PKCS#11 module instead of perivate key file for mutual-authentication in 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) 中调用的 return 值返回什么 "key"?我无法想象密钥内容是从 HSM 中读出的,因为 PKCS#11 甚至不支持此操作。我还能得到什么?它只是元信息关于 HSM 中的密钥而不是密钥本身? SSL_CTX * ctx 如何知道以后应该如何使用这个 "key"?

鉴于 PKCS#11 引擎已正确加载,这是否意味着任何 RSA 函数都会自动委派给 HSM 以及 以及存储在上下文中的 "meta-key information" ?

请证实这个假设,或者让我知道我哪里错了。

总之,我发现了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 */ ;

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

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

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

另一方面,

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