O problema é que openssl -verify
isso não funciona.
Como Priyadi mencionou , openssl -verify
para no primeiro certificado autoassinado, portanto, você realmente não verifica a cadeia, pois geralmente o certificado intermediário é autoassinado.
Suponho que você queira ter 101% de certeza de que os arquivos de certificado estão corretos antes de tentar instalá-los no serviço da web produtivo. Esta receita aqui executa exatamente essa verificação pré-vôo.
Observe que a resposta de Pedro está correta , no entanto, a saída de openssl -verify
não é nenhuma pista de que tudo realmente funciona depois. Sim, pode encontrar alguns problemas, mas não todos.
Aqui está um script que executa a tarefa de verificar uma cadeia de certificados antes de instalá-la no Apache. Talvez isso possa ser aprimorado com algumas das mágicas mais místicas do OpenSSL, mas eu não sou um guru do OpenSSL e os seguintes trabalhos:
#!/bin/bash
# This Works is placed under the terms of the Copyright Less License,
# see file COPYRIGHT.CLL. USE AT OWN RISK, ABSOLUTELY NO WARRANTY.
#
# COPYRIGHT.CLL can be found at http://permalink.de/tino/cll
# (CLL is CC0 as long as not covered by any Copyright)
OOPS() { echo "OOPS: $*" >&2; exit 23; }
PID=
kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; }
trap 'kick' 0
serve()
{
kick
PID=
openssl s_server -key "$KEY" -cert "$CRT" "$@" -www &
PID=$!
sleep .5 # give it time to startup
}
check()
{
while read -r line
do
case "$line" in
'Verify return code: 0 (ok)') return 0;;
'Verify return code: '*) return 1;;
# *) echo "::: $line :::";;
esac
done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/)
OOPS "Something failed, verification output not found!"
return 2
}
ARG="${1%.}"
KEY="$ARG.key"
CRT="$ARG.crt"
BND="$ARG.bundle"
for a in "$KEY" "$CRT" "$BND"
do
[ -s "$a" ] || OOPS "missing $a"
done
serve
check && echo "!!! =========> CA-Bundle is not needed! <========"
echo
serve -CAfile "$BND"
check
ret=$?
kick
echo
case $ret in
0) echo "EVERYTHING OK"
echo "SSLCertificateKeyFile $KEY"
echo "SSLCertificateFile $CRT"
echo "SSLCACertificateFile $BND"
;;
*) echo "!!! =========> something is wrong, verification failed! <======== ($ret)";;
esac
exit $ret
Observe que a saída posterior EVERYTHING OK
é a configuração do Apache, porque as pessoas que usam NginX
ou haproxy
geralmente também podem ler e entender isso perfeitamente;)
Existe uma GistHub Gist disso que pode ter algumas atualizações
Pré-requisitos deste script:
- Você tem os dados raiz da CA confiáveis,
/etc/ssl/certs
como de costume, por exemplo, no Ubuntu
- Crie um diretório
DIR
onde você armazena 3 arquivos:
DIR/certificate.crt
que contém o certificado
DIR/certificate.key
que contém a chave secreta do seu serviço da web (sem senha)
DIR/certificate.bundle
que contém o CA-Bundle. Sobre como preparar o pacote, veja abaixo.
- Agora execute o script:
./check DIR/certificate
(isso pressupõe que o script seja nomeado check
no diretório atual)
- Há um caso muito improvável de saída do script
CA-Bundle is not needed
. Isso significa que você (leia /etc/ssl/certs/
:) já confia no certificado de assinatura. Mas isso é altamente improvável na WWW.
- Para este teste, a porta 4433 deve ser não utilizada em sua estação de trabalho. E melhor executar isso apenas em um ambiente seguro, pois abre a porta 4433 em breve para o público, que pode ver conexões externas em um ambiente hostil.
Como criar o certificate.bundle
arquivo?
Na WWW, a cadeia de confiança geralmente se parece com isso:
- certificado confiável de
/etc/ssl/certs
- certificados intermediários desconhecidos, possivelmente com assinatura cruzada por outra CA
- seu certificado (
certificate.crt
)
Agora, a avaliação ocorre de baixo para cima, ou seja, primeiro, seu certificado é lido, então é necessário o certificado intermediário desconhecido, talvez o certificado de assinatura cruzada e, em seguida, /etc/ssl/certs
é consultado para encontrar o certificado confiável adequado.
O pacote CA deve ser formado exatamente na ordem de processamento correta, ou seja, o primeiro certificado necessário (o certificado intermediário que assina seu certificado) é o primeiro no pacote. Em seguida, é necessário o certificado de assinatura cruzada.
Normalmente, sua autoridade de certificação (a autoridade que assinou seu certificado) já fornecerá um arquivo CA-bundle adequado. Caso contrário, você precisará escolher todos os certificados intermediários necessários e cat
eles juntos em um único arquivo (no Unix). No Windows, você pode simplesmente abrir um editor de texto (como notepad.exe
) e colar os certificados no arquivo, o primeiro necessário na parte superior e os demais.
Há outra coisa. Os arquivos precisam estar no formato PEM. Algumas autoridades de certificação emitem o formato DER (um binário). O PEM é fácil de detectar: é legível em ASCII. Para informações sobre como converter algo em PEM, consulte Como converter .crt em .pem e siga a estrada de tijolos amarelos.
Exemplo:
Você tem:
intermediate2.crt
o certificado intermediário que assinou seu certificate.crt
intermediate1.crt
outro certificado intermediário, que chamuscava intermediate2.crt
crossigned.crt
que é um certificado de assinatura cruzada de outra CA, que assinou intermediate1.crt
crossintermediate.crt
que é outro intermediário da outra CA que assinou crossigned.crt
(você provavelmente nunca verá uma coisa dessas)
Então o apropriado cat
ficaria assim:
cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle
E como você pode descobrir quais arquivos são necessários ou não e em qual sequência?
Bem, experimente, até que o check
informe que está tudo bem. É como um jogo de quebra-cabeça de computador para resolver o enigma. Cada. Solteiro. Tempo. Mesmo para profissionais. Mas você vai melhorar cada vez que precisar fazer isso. Então você definitivamente não está sozinho com toda essa dor. É SSL, sabe? O SSL é provavelmente um dos piores projetos que já vi em mais de 30 anos de administração profissional de sistemas. Já se perguntou por que a criptografia não se tornou popular nos últimos 30 anos? É por isso. disse nuff.
man verify
, descobri que o-untrusted
parâmetro é o correto a ser usado ao especificar o certificado intermediário.