在 PKCS#11 中签署证书
Sign certificate in PKCS#11
为了在 OpenSSL 中签署证书,我使用 X509_sign()
函数通过向它提供请求(如 X509_REQ*
)、签名密钥和摘要。
现在我的签名密钥存储在 HSM 中,所以我无法提取它来签署证书。不幸的是,PKCS#11 没有提供等同于 X509_sign()
的功能。它所拥有的只是 C_Sign() / C_SignUpdate() / C_SignFinal()
对原始数据而非证书进行操作的函数族。
有人可以帮我提供示例 C/C++ 代码如何使用 PKCS#11 签署使用 OpenSSL 创建的证书吗?
下面的代码在 HSM 中对给定的 X509* 结构进行签名。为了清楚起见,省略了错误处理。
void signCertInHsm(X509* x509, unsigned long pkcs11SigningAlgo, CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE p11session, CK_OBJECT_HANDLE pkcs11PrivKeyHandle)
{
x509->cert_info->enc.modified = 1;
// set signature algorithm in the certificate
if (x509->cert_info->signature)
{
const int signingAlgoNid = pkcs11SignatureAlgorithmToNid(pkcs11SigningAlgo);
X509_ALGOR_set0(x509->cert_info->signature, OBJ_nid2obj(signingAlgoNid), V_ASN1_NULL, NULL);
}
if (x509->sig_alg)
{
const int signingAlgoNid = pkcs11SignatureAlgorithmToNid(pkcs11SigningAlgo);
X509_ALGOR_set0(x509->sig_alg, OBJ_nid2obj(signingAlgoNid), V_ASN1_NULL, NULL);
}
// DER-encode certificate
unsigned char *certDerBuf = NULL;
const size_t certDerLen = ASN1_item_i2d((ASN1_VALUE*)x509->cert_info, &certDerBuf, ASN1_ITEM_rptr(X509_CINF));
CK_MECHANISM mechanism = { pkcs11SigningAlgo, NULL_PTR, 0 };
p11->C_SignInit(p11session, &mechanism, pkcs11PrivKeyHandle);
// determine signature size
CK_ULONG signatureSize = 0;
p11->C_Sign(p11session, certDerBuf, certDerLen, NULL, &signatureSize);
// sign
if (x509->signature->data)
OPENSSL_free(x509->signature->data);
x509->signature->data = (unsigned char*)OPENSSL_malloc(signatureSize);
x509->signature->length = signatureSize;
p11->C_Sign(p11session, certDerBuf, certDerLen, x509->signature->data, &signatureSize);
x509->signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
x509->signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
OPENSSL_free(certDerBuf);
}
int pkcs11SignatureAlgorithmToNid(unsigned long algo)
{
switch(algo)
{
case CKM_SHA1_RSA_PKCS: return NID_sha1WithRSAEncryption;
case CKM_SHA256_RSA_PKCS: return NID_sha256WithRSAEncryption;
//... add more mappings that your app supports
default: throw std::invalid_argument("Not supported signature algorithm");
}
}
另一种通过 HSM 签署证书的方法是使用 X509_sign()
函数,但要实现您自己的签名回调。
可以在 https://github.com/OpenSC/libp11/blob/master/src/p11_pkey.c
中找到示例
pkcs11_pkey_method_rsa()
- 是如何添加自己的回调
pkcs11_try_pkey_rsa_sign(...)
- 签名是如何实现的(RSA)
为了在 OpenSSL 中签署证书,我使用 X509_sign()
函数通过向它提供请求(如 X509_REQ*
)、签名密钥和摘要。
现在我的签名密钥存储在 HSM 中,所以我无法提取它来签署证书。不幸的是,PKCS#11 没有提供等同于 X509_sign()
的功能。它所拥有的只是 C_Sign() / C_SignUpdate() / C_SignFinal()
对原始数据而非证书进行操作的函数族。
有人可以帮我提供示例 C/C++ 代码如何使用 PKCS#11 签署使用 OpenSSL 创建的证书吗?
下面的代码在 HSM 中对给定的 X509* 结构进行签名。为了清楚起见,省略了错误处理。
void signCertInHsm(X509* x509, unsigned long pkcs11SigningAlgo, CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE p11session, CK_OBJECT_HANDLE pkcs11PrivKeyHandle)
{
x509->cert_info->enc.modified = 1;
// set signature algorithm in the certificate
if (x509->cert_info->signature)
{
const int signingAlgoNid = pkcs11SignatureAlgorithmToNid(pkcs11SigningAlgo);
X509_ALGOR_set0(x509->cert_info->signature, OBJ_nid2obj(signingAlgoNid), V_ASN1_NULL, NULL);
}
if (x509->sig_alg)
{
const int signingAlgoNid = pkcs11SignatureAlgorithmToNid(pkcs11SigningAlgo);
X509_ALGOR_set0(x509->sig_alg, OBJ_nid2obj(signingAlgoNid), V_ASN1_NULL, NULL);
}
// DER-encode certificate
unsigned char *certDerBuf = NULL;
const size_t certDerLen = ASN1_item_i2d((ASN1_VALUE*)x509->cert_info, &certDerBuf, ASN1_ITEM_rptr(X509_CINF));
CK_MECHANISM mechanism = { pkcs11SigningAlgo, NULL_PTR, 0 };
p11->C_SignInit(p11session, &mechanism, pkcs11PrivKeyHandle);
// determine signature size
CK_ULONG signatureSize = 0;
p11->C_Sign(p11session, certDerBuf, certDerLen, NULL, &signatureSize);
// sign
if (x509->signature->data)
OPENSSL_free(x509->signature->data);
x509->signature->data = (unsigned char*)OPENSSL_malloc(signatureSize);
x509->signature->length = signatureSize;
p11->C_Sign(p11session, certDerBuf, certDerLen, x509->signature->data, &signatureSize);
x509->signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
x509->signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
OPENSSL_free(certDerBuf);
}
int pkcs11SignatureAlgorithmToNid(unsigned long algo)
{
switch(algo)
{
case CKM_SHA1_RSA_PKCS: return NID_sha1WithRSAEncryption;
case CKM_SHA256_RSA_PKCS: return NID_sha256WithRSAEncryption;
//... add more mappings that your app supports
default: throw std::invalid_argument("Not supported signature algorithm");
}
}
另一种通过 HSM 签署证书的方法是使用 X509_sign()
函数,但要实现您自己的签名回调。
可以在 https://github.com/OpenSC/libp11/blob/master/src/p11_pkey.c
中找到示例pkcs11_pkey_method_rsa()
- 是如何添加自己的回调
pkcs11_try_pkey_rsa_sign(...)
- 签名是如何实现的(RSA)