OpenSSL error - unable to get local issuer certificate

前端 未结 2 1526
-上瘾入骨i
-上瘾入骨i 2021-02-20 05:58

I have a simple chain setup and can successfully verify in this case:

$ openssl version
OpenSSL 1.0.2m  2 Nov 2017
$ openssl verify -CAfile chain.pem cert.pem
ce         


        
2条回答
  •  Happy的楠姐
    2021-02-20 06:51

    (This answer extracted from X509_verify_cert at crypto/x509/x509_vfy.c:204, in openssl-1.0.2m)

    The OpenSSL verify application verifies a certificate in the following way: It builds the certificate chain starting with the target certificate, and tracing the issuer chain, searching any untrusted certificates supplied along with the target cert first. Upon failing to find an untrusted issuer cert, OpenSSL switches to the trusted certificate store and continues building the chain. This process stops when

    1. an issuer is not found in the trusted store.
    2. a self-signed certificate is encountered.
    3. the max-verify depth is encountered.

    At this point we have a chain that may end prematurely (if we failed to find an issuer, or if we exceeded the verify depth).

    OpenSSL then scans over each trusted certificate on the chain looking for SSLv3 extensions that specify the purpose of the trusted certificate. If the trusted certificate has the right "trust" attributes for the "purpose" of the verification operation (or has the anyExtendedKeyUsage attribute) the chain is trusted. (Forgive the hand-wave on trust attributes, that part of the code was difficult to read.)

    So lets test it out. First, let's repro the OP's error cases:

    #
    echo "Making Root CA..."
    openssl req -newkey rsa:4096 -nodes -keyout ca-key.pem -sha384 -x509 -days 365 -out ca-crt.pem -subj /C=XX/ST=YY/O=RootCA
    
    echo "Making Intermediate CA..."
    openssl req -newkey rsa:3072 -nodes -keyout int-key.pem -new -sha384 -out int-csr.pem -subj /C=XX/ST=YY/O=IntermediateCA
    openssl x509 -req -days 360 -in int-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt.pem
    
    echo "Making User Cert..."
    openssl req -newkey rsa:2048 -nodes -keyout usr-key.pem -new -sha256 -out usr-csr.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b
    openssl x509 -req -days 360 -in usr-csr.pem -CA int-crt.pem -CAkey int-key.pem -CAcreateserial -out usr-crt.pem
    
    echo ""
    echo "Making Chain..."
    cat ca-crt.pem int-crt.pem > chain.pem
    
    echo ""
    echo "Verfying UserCert via RootCA..."
    openssl verify -CAfile ca-crt.pem usr-crt.pem
    
    echo ""
    echo "Verfying UserCert via IntermediateCA..."
    openssl verify -CAfile int-crt.pem usr-crt.pem
    
    echo ""
    echo "Verfying UserCert via chain..."
    openssl verify -CAfile chain.pem usr-crt.pem
    

    yields

    [... Skipping OpenSSL KeyGen / CertGen verbosity ...]
    Making Chain...
    
    Verfying UserCert via RootCA...
    usr-crt.pem: C = XX, ST = YY, O = LockCmpXchg8b
    error 20 at 0 depth lookup:unable to get local issuer certificate
    
    Verfying UserCert via IntermediateCA...
    usr-crt.pem: C = XX, ST = YY, O = IntermediateCA
    error 2 at 1 depth lookup:unable to get issuer certificate
    
    Verfying UserCert via chain...
    usr-crt.pem: OK
    

    Now, lets use the -addtrust option of openssl x509 to make sure we have one of the acceptable trust attributes on the intermediate CA (call this one IntermediateCAWithTrust; we'll use it to sign AnotherUserCert.):

    echo ""
    echo "Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)"
    echo ""
    
    echo "Making IntermediateCAWithTrust..."
    openssl req -newkey rsa:3072 -nodes -keyout int-key2.pem -new -sha384 -out int-csr2.pem -subj /C=XX/ST=YY/O=IntermediateCAWithTrust
    openssl x509 -req -days 360 -in int-csr2.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt2.pem -addtrust anyExtendedKeyUsage
    
    echo "Making AnotherUser Cert..."
    openssl req -newkey rsa:2048 -nodes -keyout usr-key2.pem -new -sha256 -out usr-csr2.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b_2
    openssl x509 -req -days 360 -in usr-csr2.pem -CA int-crt2.pem -CAkey int-key2.pem -CAcreateserial -out usr-crt2.pem
    
    echo ""
    echo "Verfying AnotherUserCert via IntermediateCAWithTrust..."
    openssl verify -CAfile int-crt2.pem usr-crt2.pem
    

    This yields

    Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)
    
    Making IntermediateCAWithTrust...
    [... Snip more OpenSSL generation output ...]
    Making AnotherUser Cert...
    [... Snip more OpenSSL generation output ...]
    
    Verfying AnotherUserCert via IntermediateCAWithTrust...
    usr-crt2.pem: OK
    

    Hey look! we just successfully verified AnotherUserCert via the IntermediateCAWithTrust, even though we didn't supply the whole chain. The key to this difference is that any one of the trusted certificates in the chain had an appropriate trust attribute for the verify operation.

    Looking a little closer (via openssl x509 -in ca-crt.pem -noout -text), our CA certificate has

            X509v3 Basic Constraints:
                CA:TRUE
    

    which I would imagine OpenSSL treats as a general "may verify for any purpose" extension. The new IntermediateCAWithTrust does not have X509v3 Basic Constraints, but instead has

    Trusted Uses:
      Any Extended Key Usage
    No Rejected Uses.
    

    For more info in the -addtrust option, and the types of trust attributes that can be added, see https://www.openssl.org/docs/manmaster/man1/x509.html#TRUST_SETTINGS

    Near the bottom of that page is a concise summary of the preceding discussion:

    The basicConstraints extension CA flag is used to determine whether the certificate can be used as a CA. If the CA flag is true then it is a CA, if the CA flag is false then it is not a CA. All CAs should have the CA flag set to true.

    If the basicConstraints extension is absent then the certificate is considered to be a "possible CA" other extensions are checked according to the intended use of the certificate. A warning is given in this case because the certificate should really not be regarded as a CA: however it is allowed to be a CA to work around some broken software.

    So, in short, make sure your intermediate CAs are properly CAs (in their X509v3 Basic Constraints). This seems an excellent tutorial (and it explicitly generates the intermediate CA as a CA): https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html

    As a backup plan, you can always supply the whole chain, or you can make your intermediate CAs with the -addtrust hack.

提交回复
热议问题