为什么X509_CRL_verify()失败?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么X509_CRL_verify()失败?相关的知识,希望对你有一定的参考价值。

我正在使用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();

谢谢!

答案

经过几天的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签名所需的正确公钥。

另一答案

在验证证书之前,你应该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
");
        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
");
        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("
 err info: %s 
", 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;
}

以上是关于为什么X509_CRL_verify()失败?的主要内容,如果未能解决你的问题,请参考以下文章

WCF 错误:“X.509 证书 CN=localhost 链构建失败......”

IDX10501:签名验证失败。尝试的密钥:'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'

X509_NAME_oneline返回的免费字符串

将 X.509 证书的主题名称解析到缓冲区

X509Certificate2.Verify() 出错但证书正在工作

XMLDSig X509SerialNumber 太大而不能成为 int,XSD 验证失败