SSL 证书验证和 C 中的间接 CRL

问题描述 投票:0回答:1

我正在尝试编写 C 代码来验证证书,包括检查 CRL 以检查它是否被撤销。

证书链

这是证书链,为了隐私和简洁而进行了编辑:

mycert.pem
    Subject: MyCompany
    Issuer: CA1
    Authority Information Access: https://.../ca1.pem
    CRL Distribution Points: https://.../crl.pem

ca1.pem
    Subject: CA1
    Issuer: Root
    Authority Information Access: https://.../root.pem
    CRL Distribution Points: :https://.../ca_crl.pem
    CRL Issuer: Root

root.pem
    Subject: Root
    Issuer: Root

验证这条链很简单:

$ cat root.pem ca1.pem > chain.pem
$ openssl verify -CAfile chain.pem mycert.pem
mycert.pem: OK

CRL

mycert.pem 和 ca1.pem 都有关联的 CRL:

crl.pem
    Issuer: CA2
    Authority Information Access: https://.../ca2.pem

ca_crl.pem
    Issuer: Root

crl.pem 由第二个互证书 (ca2.pem) 签名,具有相同的根证书:

ca2.pem
    Subject: CA2
    Issuer: Root
    Authority Information Access: https://.../root.pem
    CRL Distribution Points: https://.../ca_crl.pem

使用间接 CRL 验证 mycert.pem

我可以通过这种方式使用 openssl 验证 mycert.pem:

$ openssl verify -CAfile chain.pem -CRLfile ca_crl.pem -CRLfile crl.pem -untrusted ca2.pem -crl_check -extended_crl mycert.pem
mycert.pem: OK

(使用

-untrusted
作为我应该能够信任的证书很奇怪,但我发现一些帖子使用这种方法而不质疑它。如果这是错误的,请随时提及!)

使用 C 中的间接 CRL 验证 mycert.pem

我现在正在尝试将此命令翻译为 C 代码,但我无法使其工作。这是一段简单的代码,可以重现该命令的行为:

#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>

X509 *cert_load(const char *filename) {
    X509 *cert = NULL;
    FILE *fp   = fopen(filename, "r");
    if (fp) {
        cert = PEM_read_X509(fp, NULL, NULL, NULL);
        fclose(fp);
    }
    return cert;
}

X509_CRL *crl_load(const char *filename) {
    X509_CRL *crl = NULL;
    FILE     *fp  = fopen(filename, "r");
    if (fp) {
        crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
        fclose(fp);
    }
    return crl;
}

int main() {
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    int ret;
    X509_STORE     *store          = X509_STORE_new();
    X509_STORE_CTX *ctx            = X509_STORE_CTX_new();
    X509           *mycert         = cert_load("mycert.pem");
    X509           *ca1_cert       = cert_load("ca1.pem");
    X509           *ca2_cert       = cert_load("ca2.pem");
    X509           *root_cert      = cert_load("root.pem");
    X509_CRL       *crl            = crl_load("crl.pem");
    X509_CRL       *ca_crl         = crl_load("ca_crl.pem");
    STACK_OF(X509) *chain          = sk_X509_new_null();
    STACK_OF(X509) *untrusted      = sk_X509_new_null();

    if (!mycert || !ca1_cert || !ca2_cert || !root_cert || !crl || !ca_crl) {
        printf("Error loading certificates or CRL\n");
        return 1;
    }

    sk_X509_push(chain, ca1_cert);

    sk_X509_push(untrusted, ca2_cert);

    X509_STORE_add_crl(store, crl);
    X509_STORE_add_crl(store, ca_crl);

    // X509_V_FLAG_EXTENDED_CRL_SUPPORT: enable checking indirect CRL
    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL | X509_V_FLAG_EXTENDED_CRL_SUPPORT);

    X509_STORE_add_cert(store, root_cert);
    X509_STORE_CTX_init(ctx, store, mycert, chain);
    X509_STORE_CTX_set0_untrusted(ctx, untrusted);

    ret = X509_verify_cert(ctx);
    if (ret == 1) {
        printf("Verification successful\n");
    } else {
        int error = X509_STORE_CTX_get_error(ctx);
        printf("Verification failed: %s\n", X509_verify_cert_error_string(error));
    }

    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
    sk_X509_pop_free(chain, X509_free);
    sk_X509_pop_free(untrusted, X509_free);
    X509_free(mycert);
    X509_free(ca1_cert);
    X509_free(ca2_cert);
    X509_free(root_cert);
    X509_CRL_free(crl);
    X509_CRL_free(ca_crl);

    EVP_cleanup();
    ERR_free_strings();

    return ret;
}

运行上面的代码,我得到

KO: unable to get local issuer certificate

我尝试评论这一行:

X509_STORE_CTX_set0_untrusted(ctx, untrusted);
,它给出了
KO: unable to get certificate CRL

如果我也注释掉这一行:

X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL | X509_V_FLAG_EXTENDED_CRL_SUPPORT);
,则验证成功。

如何构建“不受信任”的链,使其依赖于根证书,并且 CRL 被视为对我的证书有效?

c ssl openssl certificate x509
1个回答
0
投票
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>

// Function to load a certificate from a file
X509 *cert_load(const char *filename) {
    X509 *cert = NULL;
    FILE *fp = fopen(filename, "r");
    if (fp) {
        cert = PEM_read_X509(fp, NULL, NULL, NULL);
        fclose(fp);
    } else {
        // Added error message if file cannot be opened
        fprintf(stderr, "Error opening certificate file %s\n", filename);
    }
    return cert;
}

// Function to load a CRL from a file
X509_CRL *crl_load(const char *filename) {
    X509_CRL *crl = NULL;
    FILE *fp = fopen(filename, "r");
    if (fp) {
        crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL);
        fclose(fp);
    } else {
        // Improved: Added error message if file cannot be opened
        fprintf(stderr, "Error opening CRL file %s\n", filename);
    }
    return crl;
}

int main() {
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    int ret;
    X509_STORE *store = X509_STORE_new();
    X509_STORE_CTX *ctx = X509_STORE_CTX_new();
    X509 *mycert = cert_load("mycert.pem");
    X509 *ca1_cert = cert_load("ca1.pem");
    X509 *ca2_cert = cert_load("ca2.pem");
    X509 *root_cert = cert_load("root.pem");
    X509_CRL *crl = crl_load("crl.pem");
    X509_CRL *ca_crl = crl_load("ca_crl.pem");
    STACK_OF(X509) *chain = sk_X509_new_null();
    STACK_OF(X509) *untrusted = sk_X509_new_null();

    // Check if all certificates and CRLs are loaded successfully
    if (!mycert || !ca1_cert || !ca2_cert || !root_cert || !crl || !ca_crl) {
        fprintf(stderr, "Error loading certificates or CRL\n");
        return 1;
    }

    sk_X509_push(chain, ca1_cert);
    sk_X509_push(untrusted, ca2_cert);

    X509_STORE_add_crl(store, crl);
    X509_STORE_add_crl(store, ca_crl);

    // Set flags for CRL checking
    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL | X509_V_FLAG_EXTENDED_CRL_SUPPORT);

    X509_STORE_add_cert(store, root_cert);
    X509_STORE_CTX_init(ctx, store, mycert, chain);
    X509_STORE_CTX_set0_untrusted(ctx, untrusted);

    ret = X509_verify_cert(ctx);
    if (ret == 1) {
        printf("Verification successful\n");
    } else {
        int error = X509_STORE_CTX_get_error(ctx);
        printf("Verification failed: %s\n", X509_verify_cert_error_string(error));
    }

    X509_STORE_CTX_free(ctx);
    X509_STORE_free(store);
    sk_X509_pop_free(chain, X509_free);
    sk_X509_pop_free(untrusted, X509_free);
    X509_free(mycert);
    // Free additional resources
    X509_free(ca1_cert);
    X509_free(ca2_cert);
    X509_free(root_cert);
    X509_CRL_free(crl);
    X509_CRL_free(ca_crl);

    return 0;
}

尝试这样的事情^

© www.soinside.com 2019 - 2024. All rights reserved.