如何从 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" 下。所以
我首先要从引擎加载私钥:
EVP_PKEY* key = ENGINE_load_private_key(e, "SecureToken", NULL,
&cb_data);
然后必须调用
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 密钥可以从模块中导出。这表示私钥的算法和大小,证书可以在字段和扩展中携带额外的元数据。
问题的答案
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" 下。所以
我首先要从引擎加载私钥:
EVP_PKEY* key = ENGINE_load_private_key(e, "SecureToken", NULL, &cb_data);
然后必须调用
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 密钥可以从模块中导出。这表示私钥的算法和大小,证书可以在字段和扩展中携带额外的元数据。