Como extrair a CA raiz e a CA subordinada de uma cadeia de certificados no Linux?

Como extrair a CA raiz e a CA subordinada de uma cadeia de certificados no Linux?

Eu tenho um certificado de entidade/servidor final que possui um certificado intermediário e raiz. Quando estou catno certificado da entidade final, vejo apenas uma tag BEGINe END. É o único certificado da entidade final.

Existe alguma maneira de visualizar o conteúdo do certificado intermediário e raiz. Eu preciso apenas do conteúdo BEGINe ENDda tag.

No Windows, posso ver a cadeia completa de certificados no "Caminho de certificação". Abaixo está o exemplo do certificado do Stack Exchange.

insira a descrição da imagem aqui

A partir daí posso realizar umVer certificadoe exportá-los. Posso fazer isso tanto para root quanto para intermediário no Windows. Estou procurando esse mesmo método no Linux.

insira a descrição da imagem aqui

Responder1

Em um site, você pode fazer:

openssl s_client -showcerts -verify 5 -connect stackexchange.com:443 < /dev/null

Isso mostrará a cadeia de certificados e todos os certificados que o servidor apresentou.

Agora, se eu salvar esses dois certificados em arquivos, posso usar openssl verify:

$ openssl verify -show_chain -untrusted dc-sha2.crt se.crt 
se.crt: OK
Chain:
depth=0: C = US, ST = NY, L = New York, O = "Stack Exchange, Inc.", CN = *.stackexchange.com (untrusted)
depth=1: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 High Assurance Server CA (untrusted)
depth=2: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA

A -untrustedopção é utilizada para fornecer o(s) certificado(s) intermediário(s); se.crté o certificado a ser verificado. O resultado profundidade = 2 veio do armazenamento de CA confiável do sistema.

Se você não tiver os certificados intermediários, não poderá realizar a verificação. É assim que o X.509 funciona.

Dependendo do certificado, ele pode conter um URI para obter o intermediário. Como exemplo, openssl x509 -in se.crt -noout -textcontém:

        Authority Information Access: 
            OCSP - URI:http://ocsp.digicert.com
            CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt

Esse URI "CA Issuers" aponta para o certificado intermediário (no formato DER, portanto, você precisa usá-lo openssl x509 -inform der -in DigiCertSHA2HighAssuranceServerCA.crt -out DigiCertSHA2HighAssuranceServerCA.pempara convertê-lo para uso posterior pelo OpenSSL).

Se você executar , openssl x509 -in /tmp/DigiCertSHA2HighAssuranceServerCA.pem -noout -issuer_hashobterá 244b5494, que poderá procurar no armazenamento CA raiz do sistema em /etc/ssl/certs/244b5494.0(basta anexar .0ao nome).

Não acho que exista um comando OpenSSL fácil e agradável para fazer tudo isso por você.

Responder2

dr - magia bash de um liner para despejar todos os certificados da cadeia

openssl s_client -showcerts -verify 5 -connect wikipedia.org:443 < /dev/null |
   awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}'
for cert in *.pem; do 
        newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
        echo "${newname}"; mv "${cert}" "${newname}" 
done

Explicação em 2 passos

Para despejar todos os certificados da cadeia no diretório atual como cert${chain_number}.pem:

openssl s_client -showcerts -verify 5 -connect your_host:443 < /dev/null |
 awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}' 

A faixa bônus para renomeá-los com seu nome comum:

for cert in *.pem; do 
   newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
   mv $cert $newname 
done

Responder3

Descobri que com a opção -verify 5openssl vai fundo na cadeia mostrando todo o certificado, mesmo aquele não incluído na implantação do seu certificado.

Se você realmente deseja entender qual cadeia é fornecida com seu certificado, execute:

openssl s_client -showcerts -partial_chain -connect YOUR_ENDPOINT:443 < /dev/null |less

Responder4

O procedimento acima não funcionou para mim quando eu estava usando um certificado Lets Encrypt Free Wildcard.

Para ser mais específico:
eu tenho um cluster Kubernetes + controlador de entrada configurado usando um certificado curinga gratuito Lets Encrypt para *.mydomain.dev, que hospeda os dois nomes de domínio a seguir:

  • grafana.meudominio.dev
  • prometheus.meudominio.dev

Eu tive que adicionar o sinalizador -servername seguindo este site:https://community.letsencrypt.org/t/where-can-i-download-the-trusted-root-ca-certificates-for-lets-encrypt/33241/2

export DOMAIN=grafana.mydomain.dev
openssl s_client -showcerts -verify 5 -connect $DOMAIN:443 -servername $DOMAIN < /dev/null 2> /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/){a++}; print}'

Eu também ajustei a cadeia para que ela me fornecesse o certificado completo + intermediário + raiz para a saída padrão e ocultasse o ruído stderr.

Na verdade... Ao testar descobri que isso não me dá a CA... openssl s_client -showcerts -verify 5 -connect letsencrypt.org:443 < /dev/null 2> /dev/null | awk '/BEGIN/,/END/{ if(/BEGIN/){a++}; print}'

curl https://letsencrypt.org/certs/isrgrootx1.pem Fornece um valor diferente (e ao testar algumas coisas, esse é o valor que funciona).

informação relacionada