1

我正在使用 openssl (v.1.0.1k) 编写一个库,以根据颁发者证书和吊销列表验证证书。我的第一步是验证 CLR 来自发行人。我已验证证书和 CLR 已正确生成并使用以下命令行进行验证:

openssl crl -issuer -inform PEM -in root.crl.pem -noout -CAfile master_ca.crt
    verify OK ...

然而!我无法使用 X509_CRL_verify() 进行 CRL 验证。它总是报告:“期待:证书”

ERR_get_error() 的输出:

140239350716336:error:0906D06C:lib(9):func(109):reason(108):pem_lib.c:703:Expecting: CERTIFICATE
140239350716336:error:0D0C50A1:lib(13):func(197):reason(161):a_verify.c:200:

我想知道它是否有问题,因为我的证书是“受信任的”证书。我必须使用 PEM_read_bio_x509_AUX() 而不是普通的 PEM_read_bio_x509() 来加载证书。在验证受信任的证书之前,我还需要做些什么吗?

这是验证码:

int  verifyCRL( X509_CRL* crl, EVP_PKEY* issuer )
    {
        int rv = 0; 
        if ( issuer != NULL )
        {               
            if ( X509_CRL_verify( crl,issuer ) == 1 )
            {
                log_msg( 5, "CRL verify.. OK" );
                rv = 1;
            }
            else
            {
                log_msg( 0, "CRL verify.. FAILED" );
                print_ssl_errors();
            }
        }

这是颁发者证​​书:

-----BEGIN TRUSTED CERTIFICATE-----
MIIDHjCCAoegAwIBAgIJAIEOyY6V3s6CMA0GCSqGSIb3DQEBDQUAMIGfMQswCQYD
VQQGEwJVUzELMAkGA1UECAwCVVQxFzAVBgNVBAcMDlBsZWFzYW50IEdyb3ZlMSUw
IwYDVQQKDBxNYXN0ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRIwEAYDVQQLDAlN
YXN0ZXIgQ0ExETAPBgNVBAMMCHRlc3QuY29tMRwwGgYJKoZIhvcNAQkBFg1mcmVk
QHRlc3QuY29tMB4XDTE1MTIxMTIyNTU0MloXDTI1MTIwODIyNTU0MlowgZ8xCzAJ
BgNVBAYTAlVTMQswCQYDVQQIDAJVVDEXMBUGA1UEBwwOUGxlYXNhbnQgR3JvdmUx
JTAjBgNVBAoMHE1hc3RlciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAsM
CU1hc3RlciBDQTERMA8GA1UEAwwIdGVzdC5jb20xHDAaBgkqhkiG9w0BCQEWDWZy
ZWRAdGVzdC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALWSHVFCRRSn
mvT8XZHa4kUjMBncZ9RGkoDNt6QgvtaQmEqmywvwMBMk4v1iXE9by/0JfMng0LU7
cBwIOYpUGO2pliPHbniY7sERTSB/JcViPtpPmtaKFob1+rUT0bXr0rQYdIeNPHAy
UySkxauUzGWJ4e6tSDPqPGEUR8SRufi5AgMBAAGjYDBeMAkGA1UdIwQCMAAwDAYD
VR0TBAUwAwEB/zALBgNVHQ8EBAMCAf4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cHM6
Ly9saWNlbnNpbmcudGVzdC5jb20vc2VydmVyLmNybDANBgkqhkiG9w0BAQ0FAAOB
gQBbtP+kUklffVQPyfofvYLp1K4U4YH7QRSMEc0BvFHSwulhv7kXOvHVYQIw/+fC
5LiCLSEpim2h2Lszx5oDcEIcPgDp/n2dhrCXJKIZ+cia/xXdobpm8vIHlb3cc4dh
3L+gn0ZzJm6kbkLOcYv1bVsXa+bKiWrR21TKiE5jTxy52w==
-----END TRUSTED CERTIFICATE-----

和 CRL:

-----BEGIN X509 CRL-----
MIIBjjCB+AIBATANBgkqhkiG9w0BAQ0FADCBnzELMAkGA1UEBhMCVVMxCzAJBgNV
BAgMAlVUMRcwFQYDVQQHDA5QbGVhc2FudCBHcm92ZTElMCMGA1UECgwcTWFzdGVy
IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAGA1UECwwJTWFzdGVyIENBMREwDwYD
VQQDDAh0ZXN0LmNvbTEcMBoGCSqGSIb3DQEJARYNZnJlZEB0ZXN0LmNvbRcNMTUx
MjExMjI1NTQyWhcNMTcxMjEwMjI1NTQyWjAUMBICAQIXDTE1MTIxMTIyNTU0Mlqg
DjAMMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEBDQUAA4GBABu22UFiB1aW87egynsc
TZycZMgXUjXJhJq2825e274PX77pd00/yUYezom1X6HYuwRHTJj6/25QPm25lrXL
cy84aeLJgJMcKR79oHe0252Bo1y6a2VKgMet3/m58u2opNVOM4pPYh5FSPd2UgWw
//D3L6/+3wwQrDMj8kEbaJZi
-----END X509 CRL-----

哦,是的,我已经初始化了 openssl 堆栈:

SSL_load_error_strings();
SSL_library_init();libraries
OpenSSL_add_all_algorithms();

谢谢!

4

2 回答 2

0

您应该OpenSSL_add_all_algorithms();在验证证书之前。这是我用不同方式验证证书的代码,第一种方法是使用从根证书获取的公钥,另一种方法是使用根证书验证证书。

int CertificateChecker::X509_Verify(const unsigned char* certRoot, unsigned long rootCertLen, const unsigned char* cert , unsigned long certLen)
{
    int ret = -1;
    X509 *usrCert = NULL;
    X509 *rootCert = NULL;

    //rootCert = d2i_X509(NULL, (const unsigned char**)&certRoot, rootCertLen); //for cert with der format
    BIO* bio = BIO_new_mem_buf((void*)certRoot, -1);
    rootCert = PEM_read_bio_X509(bio, NULL, 0, NULL);
    BIO_free(bio);
    if( NULL == rootCert){
        printf("root cert d2i_X509 failed\n");
        return -1;
    }

    //usrCert = d2i_X509(NULL, (const unsigned char**)&cert,certLen);
    bio = BIO_new_mem_buf((void*)cert, -1);
    usrCert = PEM_read_bio_X509(bio, NULL, 0, NULL);
    BIO_free(bio);
    if(usrCert == NULL){
        printf(" usr Cert d2i_X509 failed\n");
        return -1;
    }
    OpenSSL_add_all_algorithms();
    //start. verify the Certificate with public key.
    EVP_PKEY * pubkey = X509_get_pubkey(rootCert);
    //verify. result less than or 0 means not verified or some error.
    ret = X509_verify(usrCert, pubkey);
    //free the public key.
    EVP_PKEY_free(pubkey);
    //end. verify the Certification with public key.

    //start. verify the Certificate with root certificate.
    X509_STORE_CTX *ctx = NULL;
    X509_STORE *certStore = NULL;

    certStore = X509_STORE_new();
    X509_STORE_add_cert(certStore, rootCert);
    ctx = X509_STORE_CTX_new();
    if (1 == X509_STORE_CTX_init(ctx,certStore,usrCert,NULL))
    {
        ret = X509_verify_cert(ctx);
        long nCode = X509_STORE_CTX_get_error(ctx);
        const char * pChError = X509_verify_cert_error_string(nCode);
        printf("\r\n err info: %s \r\n", pChError);
    }
    X509_STORE_CTX_cleanup(ctx);
    X509_STORE_CTX_free(ctx);
    X509_STORE_free(certStore);
    //end. verify the Certificate with root certificate.

    X509_free(usrCert);
    X509_free(rootCert);

    return ret;
}
于 2018-03-05T02:15:12.990 回答
0

经过几天的openssl代码挖掘后,我找到了一个似乎可行的答案。如果我将 CA 证书添加到 x509 存储,然后从 X509_get_by_subject() 中提取颁发者,我可以获得公钥并使用它来验证 CRL。这是生成的“工作”代码:

int verifyCRL( X509_CRL* crl, X509* ca )
    {
        int rv = 0; 
        X509_STORE *store;
        X509_STORE_CTX ctx;
        X509_OBJECT xobj;
        EVP_PKEY* pkey = NULL;

        log_msg( 5, "Verifying CRL issuer" );
        if ( issuer != NULL )
        {
            store = X509_STORE_new();
            X509_STORE_add_crl(store, crl );
            X509_STORE_add_cert(store, ca );
            X509_STORE_CTX_init(&ctx, store, NULL, NULL);

            // get the issuer
            X509_STORE_get_by_subject(&ctx, X509_LU_X509, X509_CRL_get_issuer(crl), &xobj);
            pkey = X509_get_pubkey(xobj.data.x509);
            X509_OBJECT_free_contents(&xobj);

            if ( pkey != NULL )
            {
                if ( X509_CRL_verify( crl,pkey ) == 1 )
                {
                    log_msg( 0, "CRL verify OK" );
                    rv = 1;
                }
                else
                {
                    log_msg( 0, "CRL verify issuer failed!" );
                }

            }
            else
                log_msg( 0, "Error, could not find CRL issuer public key" );        

            X509_STORE_CTX_cleanup(&ctx);
            X509_STORE_free(store);     
        }
        else
        {
            log_msg( 0, "Error!  CRL issuer not provided" );
        }

        return rv;
    }

我不确定为什么这是必要的,但它似乎提取了验证 CRL 签名所需的正确公钥。

于 2015-12-16T21:17:20.640 回答