使用 OpenSSL 将 CRL 编号扩展添加到 CRL

Add CRL number extension to CRL using OpenSSL

对于某些客户端测试,我需要“即时”生成证书和吊销列表。我可以使用 OpenSSL 控制台命令和配置文件设置带有 CRL 编号扩展名的撤销列表。但是我无法在代码中完成这项工作。

以下是我的相关函数:

X509* g_certificate[MAX_CERTIFICATE_COUNT];
EVP_PKEY* g_certificateKeyPair[MAX_CERTIFICATE_COUNT];
X509_CRL* g_crl;

UINT16 GenerateCrl(UINT16 issuerCertificateIndex, UINT16 crlNumber, INT32 lastUpdate, INT32 nextUpdate)
{
    ASN1_TIME* lastUpdateTime = ASN1_TIME_new();
    ASN1_TIME* nextUpdateTime = ASN1_TIME_new();
    char crlNumberString[32];
    int result = 1;

    if (g_crl != NULL) X509_CRL_free(g_crl);
    g_crl = X509_CRL_new();

    result &= X509_CRL_set_version(g_crl, 1);
    result &= X509_CRL_set_issuer_name(g_crl, X509_get_subject_name(g_certificate[issuerCertificateIndex]));
    // there are multiple X509 certificate objects stored in memory, which I use to setup certificate chains

    ASN1_TIME_set(lastUpdateTime, time(NULL) + lastUpdate);
    ASN1_TIME_set(nextUpdateTime, time(NULL) + nextUpdate);
    result &= X509_CRL_set1_lastUpdate(g_crl, lastUpdateTime);
    result &= X509_CRL_set1_nextUpdate(g_crl, nextUpdateTime);
    ASN1_TIME_free(lastUpdateTime);
    ASN1_TIME_free(nextUpdateTime);

    _itoa_s((int)crlNumber, crlNumberString, 10);
    // my CRLs need to have the authority key identifier and CRL number extensions
    result &= SetCrlExtension(issuerCertificateIndex, NID_authority_key_identifier, "keyid:always");  // this does add the auth key id extension
    result &= SetCrlExtension(issuerCertificateIndex, NID_crl_number, crlNumberString);  // this does not add CRL number the extension

    result &= X509_CRL_sign(g_crl, g_certificateKeyPair[issuerCertificateIndex], EVP_sha256());

    return result;
}

INT16 SetCrlExtension(UINT16 issuerCertificateIndex, INT16 extensionNid, const char* extensionData)
{
    X509V3_CTX ctx;
    X509_EXTENSION* extension;
    lhash_st_CONF_VALUE conf;  // actually I have no idea what this is for, probably it is not required here
    int result = 1;

    X509V3_set_ctx(&ctx, g_certificate[issuerCertificateIndex], NULL, NULL, g_crl, 0);
    extension = X509V3_EXT_conf_nid(&conf, &ctx, extensionNid, (char*)extensionData);
    result &= X509_CRL_add_ext(g_crl, extension, -1);

    return result;
}

void SaveCrlAsPem(const char* fileName)
{
    FILE* f;

    fopen_s(&f, fileName, "wb");
    PEM_write_X509_CRL(f, g_crl);
    if (f != NULL) fclose(f);
}

例如

GenerateCrl(1, 1234, -3600, 36000);
SaveCrlAsPem("crl.pem"); 

应该会生成具有所述扩展名的 CRL。但它只包含权限密钥标识符扩展。其他一切都很好。我也以基本相同的方式添加证书扩展,没有任何问题。

那么我怎样才能获得附加到我的 CRL 的 CRL 编号?

您提到您可以从 OpenSSL 命令行设置 CRL number 扩展。那么您可能应该看看特定命令的源代码。

我没有使用过 CRL,但我相信您正在使用 ca 命令。在 apps/ca.c(来自 OpenSSL 1.1.1g)的源代码中查找 NID_crl_number 显示以下代码:

/* Add any extensions asked for */

if (crl_ext != NULL || crlnumberfile != NULL) {
    X509V3_CTX crlctx;
    X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
    X509V3_set_nconf(&crlctx, conf);

    if (crl_ext != NULL)
        if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
            goto end;
    if (crlnumberfile != NULL) {
        tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
        if (!tmpser)
            goto end;
        X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
        ASN1_INTEGER_free(tmpser);
        crl_v2 = 1;
        if (!BN_add_word(crlnumber, 1))
            goto end;
    }
}

所以,看来您可以使用 X509V3_EXT_CRL_add_nconfX509_CRL_add1_ext_i2d 来达到目的。请参考您正在使用的 OpenSSL 版本的apps/ca.c

另一种解决方案: 也许不是最好的方法,但您可以从代码中启动与进程相同的 OpenSSL 命令,并在可接受的情况下处理它们的输出。