O OpenSSL é o conjunto de ferramentas padrão da indústria para a gestão de certificados TLS/SSL. Quer esteja a gerar certificados autoassinados para desenvolvimento, a criar Certificate Signing Requests para produção, ou a depurar problemas de certificados, o OpenSSL é essencial. Este guia aborda a gestão prática de certificados SSL/TLS na perspetiva de um programador sénior.
Porque compreender o OpenSSL
Todos os programadores devem conhecer o OpenSSL porque:
- Desenvolvimento local: Certificados autoassinados para testes HTTPS
- Implementações em produção: Geração de CSR para certificados de CA
- Depuração: Verificar certificados e ligações
- Auditorias de segurança: Inspecionar cadeias de certificados e validade
- Automação: Criar scripts para a gestão de certificados
Noções básicas de certificados
Conceitos-chave
- Chave privada: Chave secreta, nunca partilhar (
.key) - Chave pública: Derivada da chave privada, segura para partilhar
- CSR: Certificate Signing Request, enviada para a CA (
.csr) - Certificado: Chave pública assinada com metadados (
.crt, .pem) - CA: Certificate Authority, entidade assinante de confiança
- Cadeia: Certificados de CA que ligam à CA raiz
Formatos de ficheiro
| Extensão | Formato | Contém |
|---|
.pem | Codificado em Base64 | Chaves, certificados, ou ambos |
.crt | Normalmente PEM | Apenas certificado |
.key | Normalmente PEM | Apenas chave privada |
.der | Binário | Certificado |
.p12/.pfx | Binário | Pacote com chave + certificado |
Gerar certificados autoassinados
Certificado autoassinado rápido
# Gerar chave e certificado num único comando
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout server.key \
-out server.crt \
-days 365 \
-subj "/CN=localhost/O=Development/C=US"
Com Subject Alternative Names (SAN)
Os browsers modernos exigem SAN para localhost:
# Criar ficheiro de configuração
cat > san.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = localhost
O = Development
C = US
[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = *.localhost
DNS.3 = myapp.local
IP.1 = 127.0.0.1
IP.2 = ::1
EOF
# Gerar certificado
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout server.key \
-out server.crt \
-days 365 \
-config san.cnf \
-extensions v3_req
Criar uma Certificate Authority local
Para ambientes de desenvolvimento que necessitam de vários certificados:
Passo 1: Criar CA
##!/bin/bash
OUTPUT_FOLDER=./certs
CA_DOMAIN="ca.local"
COMPANY="MyCompany"
COUNTRY="US"
mkdir -p $OUTPUT_FOLDER
# Configuração da CA
cat > $OUTPUT_FOLDER/ca.cnf << EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_req
prompt = no
encrypt_key = no
[req_distinguished_name]
CN = $CA_DOMAIN
O = $COMPANY
C = $COUNTRY
[v3_req]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = critical, CA:TRUE, pathlen:3
keyUsage = critical, cRLSign, keyCertSign
nsCertType = sslCA, emailCA
EOF
# Gerar certificado da CA
openssl req -x509 -sha256 -days 3650 -newkey rsa:4096 -nodes \
-config $OUTPUT_FOLDER/ca.cnf \
-keyout $OUTPUT_FOLDER/ca.key \
-out $OUTPUT_FOLDER/ca.crt
echo "CA certificate created: $OUTPUT_FOLDER/ca.crt"
Passo 2: Assinar certificados com a CA
##!/bin/bash
DOMAIN=$1 # p. ex., myapp.local
OUTPUT_FOLDER=./certs
# Configuração do certificado do servidor
cat > $OUTPUT_FOLDER/$DOMAIN.cnf << EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_ca
prompt = no
encrypt_key = no
default_bits = 4096
[req_distinguished_name]
CN = $DOMAIN
O = MyCompany
C = US
[v3_req]
basicConstraints = critical, CA:FALSE
[v3_ca]
basicConstraints = critical, CA:FALSE
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:$DOMAIN, DNS:*.$DOMAIN
EOF
# Gerar CSR
openssl req -new -sha256 \
-keyout $OUTPUT_FOLDER/$DOMAIN.key \
-out $OUTPUT_FOLDER/$DOMAIN.csr \
-config $OUTPUT_FOLDER/$DOMAIN.cnf
# Assinar com a CA
openssl x509 -req -sha256 -days 365 \
-in $OUTPUT_FOLDER/$DOMAIN.csr \
-CA $OUTPUT_FOLDER/ca.crt \
-CAkey $OUTPUT_FOLDER/ca.key \
-CAcreateserial \
-out $OUTPUT_FOLDER/$DOMAIN.crt \
-extensions v3_ca \
-extfile $OUTPUT_FOLDER/$DOMAIN.cnf
# Criar cadeia completa
cat $OUTPUT_FOLDER/$DOMAIN.crt $OUTPUT_FOLDER/ca.crt > $OUTPUT_FOLDER/$DOMAIN.fullchain.crt
# Limpeza
rm $OUTPUT_FOLDER/$DOMAIN.csr $OUTPUT_FOLDER/$DOMAIN.cnf
echo "Certificate created: $OUTPUT_FOLDER/$DOMAIN.crt"
Passo 3: Confiar no certificado da CA
Linux (CentOS/RHEL):
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/myca.crt
sudo update-ca-trust
Linux (Ubuntu/Debian):
sudo cp ca.crt /usr/local/share/ca-certificates/myca.crt
sudo update-ca-certificates
Linux (openSUSE):
sudo cp ca.crt /usr/share/pki/trust/anchors/myca.crt
sudo update-ca-certificates --force
macOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.crt
Firefox: Navegue para about:preferences → Privacidade e Segurança → Ver Certificados → Autoridades → Importar
Chrome: Navegue para chrome://settings/certificates → Autoridades → Importar
Gerar CSR para produção
Criar CSR para assinatura pela CA
# Gerar chave privada
openssl genrsa -out example.com.key 4096
# Gerar CSR
openssl req -new -key example.com.key -out example.com.csr \
-subj "/CN=example.com/O=My Company/L=New York/ST=NY/C=US"
# Verificar CSR
openssl req -text -noout -verify -in example.com.csr
CSR com SAN
# Criar configuração
cat > csr.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
CN = example.com
O = My Company
L = New York
ST = NY
C = US
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = api.example.com
EOF
# Gerar CSR com SAN
openssl req -new -key example.com.key -out example.com.csr -config csr.cnf
Inspecionar certificados
Ver detalhes do certificado
# Ver certificado local
openssl x509 -text -noout -in certificate.crt
# Ver certificado remoto
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
openssl x509 -text -noout
# Verificar data de expiração
openssl x509 -enddate -noout -in certificate.crt
# Ver cadeia de certificados
openssl s_client -connect example.com:443 -showcerts
Verificar se o certificado e a chave correspondem
# Comparar módulo
openssl x509 -modulus -noout -in certificate.crt | md5sum
openssl rsa -modulus -noout -in private.key | md5sum
# Ambos devem corresponder
Verificar a cadeia de certificados
# Verificar contra a CA
openssl verify -CAfile ca.crt server.crt
# Verificar cadeia completa
openssl verify -CAfile ca-bundle.crt -untrusted intermediate.crt server.crt
Converter entre formatos
PEM para DER
openssl x509 -outform der -in certificate.pem -out certificate.der
DER para PEM
openssl x509 -inform der -in certificate.der -out certificate.pem
Criar pacote PKCS12
# Combinar chave e certificado num .p12
openssl pkcs12 -export \
-out certificate.p12 \
-inkey private.key \
-in certificate.crt \
-certfile ca.crt
# Extrair de .p12
openssl pkcs12 -in certificate.p12 -out extracted.pem -nodes
Testar ligações SSL
Testar servidor HTTPS
# Teste básico de ligação
openssl s_client -connect example.com:443
# Com SNI (obrigatório para a maioria dos servidores)
openssl s_client -connect example.com:443 -servername example.com
# Testar versão TLS específica
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
# Verificar cifras suportadas
openssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384'
Testar SMTP com STARTTLS
openssl s_client -connect mail.example.com:587 -starttls smtp
Utilizar certificados
Nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
}
Node.js
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
ca: fs.readFileSync('ca.crt') // Opcional: para verificação de certificado de cliente
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Secure!');
}).listen(443);
Docker Compose
services:
nginx:
image: nginx:alpine
volumes:
- ./certs/server.crt:/etc/nginx/ssl/server.crt:ro
- ./certs/server.key:/etc/nginx/ssl/server.key:ro
environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0 # Apenas para desenvolvimento!
Principais conclusões
- SAN é obrigatório: Os browsers modernos precisam de Subject Alternative Names
- CA local para equipas: Partilhe uma CA, gere vários certificados
- Nunca faça commit de chaves: Adicione
*.key ao .gitignore - Teste ligações: Use
openssl s_client para depuração - Faça corresponder chave e certificado: Verifique o módulo antes de implementar
- Automatize a renovação: Acompanhe a validade, crie scripts para regeneração
O OpenSSL é a base da gestão TLS/SSL — dominar estes comandos poupa horas de depuração e permite fluxos de trabalho de desenvolvimento seguros.