验证错误代码 = 20:无法获取本地颁发者证书 [英] Verify errorcode = 20 : unable to get local issuer certificate

查看:24
本文介绍了验证错误代码 = 20:无法获取本地颁发者证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在服务器中有一个证书链:

I have a certificate chain in server:

Certificate chain
 0 s:/******/O=Foobar International BV/OU****
   i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****

 1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5

 2 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

我的本​​地根 CA 证书是:

And my local root CA certificate is:

   s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/****
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=**** - G5

我正在使用此代码段来验证证书:

And I am using this snippet to verify the certificate:

//gcc -lssl -lcrypto -o certverify certverify.c 

#include <openssl/ssl.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <string.h>

int main() {

  const char ca_bundlestr[] = "./ca-bundle.pem";
  const char cert_filestr[] = "./cert-file.pem";

  BIO              *certbio = NULL;
  BIO               *outbio = NULL;
  X509          *error_cert = NULL;
  X509                *cert = NULL;
  X509_NAME    *certsubject = NULL;
  X509_STORE         *store = NULL;
  X509_STORE_CTX  *vrfy_ctx = NULL;
  int ret;

  /* ---------------------------------------------------------- *
   * These function calls initialize openssl for correct work.  *
   * ---------------------------------------------------------- */
  OpenSSL_add_all_algorithms();
  ERR_load_BIO_strings();
  ERR_load_crypto_strings();

  /* ---------------------------------------------------------- *
   * Create the Input/Output BIO's.                             *
   * ---------------------------------------------------------- */
  certbio = BIO_new(BIO_s_file());
  outbio  = BIO_new_fp(stdout, BIO_NOCLOSE);

  /* ---------------------------------------------------------- *
   * Initialize the global certificate validation store object. *
   * ---------------------------------------------------------- */
  if (!(store=X509_STORE_new()))
     BIO_printf(outbio, "Error creating X509_STORE_CTX object
");

  /* ---------------------------------------------------------- *
   * Create the context structure for the validation operation. *
   * ---------------------------------------------------------- */
  vrfy_ctx = X509_STORE_CTX_new();

  /* ---------------------------------------------------------- *
   * Load the certificate and cacert chain from file (PEM).     *
   * ---------------------------------------------------------- */
  ret = BIO_read_filename(certbio, cert_filestr);
  if (! (cert = PEM_read_bio_X509(certbio, NULL, 0, NULL))) {
    BIO_printf(outbio, "Error loading cert into memory
");
    exit(-1);
  }

  ret = X509_STORE_load_locations(store, ca_bundlestr, NULL);
  if (ret != 1)
    BIO_printf(outbio, "Error loading CA cert or chain file
");

  /* ---------------------------------------------------------- *
   * Initialize the ctx structure for a verification operation: *
   * Set the trusted cert store, the unvalidated cert, and any  *
   * potential certs that could be needed (here we set it NULL) *
   * ---------------------------------------------------------- */
  X509_STORE_CTX_init(vrfy_ctx, store, cert, NULL);

  /* ---------------------------------------------------------- *
   * Check the complete cert chain can be build and validated.  *
   * Returns 1 on success, 0 on verification failures, and -1   *
   * for trouble with the ctx object (i.e. missing certificate) *
   * ---------------------------------------------------------- */
  ret = X509_verify_cert(vrfy_ctx);
  BIO_printf(outbio, "Verification return code: %d
", ret);

  if(ret == 0 || ret == 1)
  BIO_printf(outbio, "Verification result text: %s
",
             X509_verify_cert_error_string(vrfy_ctx->error));

  /* ---------------------------------------------------------- *
   * The error handling below shows how to get failure details  *
   * from the offending certificate.                            *
   * ---------------------------------------------------------- */
  if(ret == 0) {
    /*  get the offending certificate causing the failure */
    error_cert  = X509_STORE_CTX_get_current_cert(vrfy_ctx);
    certsubject = X509_NAME_new();
    certsubject = X509_get_subject_name(error_cert);
    BIO_printf(outbio, "Verification failed cert:
");
    X509_NAME_print_ex(outbio, certsubject, 0, XN_FLAG_MULTILINE);
    BIO_printf(outbio, "
");
  }

  /* ---------------------------------------------------------- *
   * Free up all structures                                     *
   * ---------------------------------------------------------- */
  X509_STORE_CTX_free(vrfy_ctx);
  X509_STORE_free(store);
  X509_free(cert);
  BIO_free_all(certbio);
  BIO_free_all(outbio);
  exit(0);
}

但此代码返回以下输出:

But this code return following output:

Verification return code: 0
Verification result text: unable to get issuer certificate
Verification failed cert:
countryName               = US
organizationName          = Symantec Corporation
organizationalUnitName    = Symantec Trust Network
commonName                = Symantec Class 3 Secure Server CA - G4

这里有什么问题?

推荐答案

您的根 CA 使用的公钥可能与链中的第一个中间 CA(在主机证书下方)相同,并且您可能没有根 CA用于信任最后一个链证书.这样的设置不是很常见,但确实会发生.不幸的是,OpenSSL 在此设置方面存在问题,并且只会尝试验证最长的链,即使较短的链已经提供了必要的信任.

Your root CA uses probably the same public key as the first intermediate CA in chain (below the host certificate) and you have probably no root-CA which can be used to trust the last chain certificate. Such setups are not very common, but actually happen. Unfortunately OpenSSL has problems with this setup and will only try to verify the longest chain, even if a shorter chain provides already the necessary trust.

对于这个 OpenSSL 问题有一个错误条目,但 OpenSSL 开发人员中没有人关心过它.如果您正在寻找 X509_V_FLAG_TRUSTED_FIRST,也可以找到补丁.看起来 OpenSSL 1.0.2(尚未发布)也会有这个选项.

There is a bug entry for this OpenSSL problem, but nobody from the OpenSSL developers ever took care of it. You can also find a patch if you are looking for X509_V_FLAG_TRUSTED_FIRST. It looks like that OpenSSL 1.0.2 (not yet released) will have this option too.

据我了解,只有 OpenSSL 存在这种问题,即既不是 NSS(Firefox,桌面上的 Chrome)也不是 SChannel(微软).

From my understanding only OpenSSL has this kind of problem, i.e. neither NSS (Firefox, Chrome on Desktop) nor SChannel (Microsoft).

这篇关于验证错误代码 = 20:无法获取本地颁发者证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆