Gostaria de criar certificados autoassinados dinamicamente com datas de início e término arbitrárias, incluindo datas de término nopassado. Eu preferiria usar ferramentas padrão, por exemplo, OpenSSL, mas qualquer coisa que dê conta do recado seria ótima.
A questão do Stack OverflowComo gerar certificado openssl com validade inferior a um dia?faz uma pergunta semelhante, mas quero que meu certificado seja autoassinado.
Caso você esteja se perguntando, os certificados são necessários para testes automatizados.
Responder1
Você tinha duas maneiras de criar certificados no passado. Ou falsificando o tempo (1)(2), ou definindo o intervalo de tempo ao assinar o certificado (3).
1) Primeiramente, sobre falsificar a hora: para fazer um programa pensar que está em uma data diferente da do sistema, dê uma olhada libfaketime
efaketime
Para instalá-lo no Debian:
sudo apt-get install faketime
Você usaria então faketime
antes do openssl
comando.
Para exemplos de uso:
$faketime 'last friday 5 pm' /bin/date
Fri Apr 14 17:00:00 WEST 2017
$faketime '2008-12-24 08:15:42' /bin/date
Wed Dec 24 08:15:42 WET 2008
De man faketime
:
O comando fornecido será levado a acreditar que a hora atual do sistema é aquela especificada no carimbo de data/hora. O relógio de parede continuará a funcionar a partir desta data e hora, salvo indicação em contrário (ver opções avançadas). Na verdade, faketime é um wrapper simples para libfaketime, que usa o mecanismo LD_PRELOAD para carregar uma pequena biblioteca que intercepta chamadas do sistema para funções como time(2) e fstat(2).
Então, por exemplo, no seu caso, você pode muito bem definir uma data de 2008, e criar então um certificado com validade de 2 anos até 2010.
faketime '2008-12-24 08:15:42' openssl ...
Como observação lateral, este utilitário pode ser usado em diversas versões de Unix, incluindo MacOS, como um wrapper para qualquer tipo de programa (não exclusivo da linha de comando).
Como esclarecimento, apenas os binários carregados com este método (e seus filhos) têm seu horário alterado, e o horário falso não afeta o horário atual do restante do sistema.
2) Como afirma @Wyzard, você também tem o datefudge
pacote que é muito semelhante em uso ao faketime
.
Como diferenças, datefudge
não influencia fstat
(ou seja, não altera o horário de criação do arquivo). Também possui uma biblioteca própria, datefudge.so, que carrega usando LD_PRELOAD.
Ele também possui um -s
static time
local onde o tempo referenciado é sempre retornado, independentemente de quantos segundos extras se passaram.
$ datefudge --static "2007-04-01 10:23" sh -c "sleep 3; date -R"
Sun, 01 Apr 2007 10:23:00 +0100
3) Além de falsificar o tempo, e de forma ainda mais simples, você também pode definir o ponto inicial e final da validade do certificado quandoassinandoo certificado em OpenSSL.
O equívoco da pergunta que você vincula em sua pergunta é que a validade do certificado não é definida no momento da solicitação (na solicitação CSR), mas no momento da assinatura.
Ao usar openssl ca
para criar o certificado autoassinado, adicione as opções -startdate
e -enddate
.
O formato de data nessas duas opções, de acordo com fontes do openssl em openssl/crypto/x509/x509_vfy.c
, é ASN1_TIME, também conhecido como ASN1UTCTime: o formato deve ser YYMMDDHHMMSSZ ou YYYYMMDDHHMMSSZ.
Citando openssl/crypto/x509/x509_vfy.c
:
int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; static const size_t generalizedtime_length = sizeof("YYYYMMDDHHMMSSZ") - 1; ASN1_TIME *asn1_cmp_time = NULL; int i, day, sec, ret = 0; /* * Note that ASN.1 allows much more slack in the time format than RFC5280. * In RFC5280, the representation is fixed: * UTCTime: YYMMDDHHMMSSZ * GeneralizedTime: YYYYMMDDHHMMSSZ * * We do NOT currently enforce the following RFC 5280 requirement: * "CAs conforming to this profile MUST always encode certificate * validity dates through the year 2049 as UTCTime; certificate validity * dates in 2050 or later MUST be encoded as GeneralizedTime." */
E do log de CHANGE (bug 2038?) - Este log de alterações é apenas uma nota de rodapé adicional, pois diz respeito apenas a quem usa diretamente a API.
Mudanças entre 1.1.0e e 1.1.1 [xx XXX xxxx]
*) Adicione os tipos ASN.1 INT32, UINT32, INT64, UINT64 e variantes prefixadas com Z. Eles se destinam a substituir LONG e ZLONG e a ter tamanho seguro. O uso de LONG e ZLONG é desencorajado e programado para descontinuação no OpenSSL 1.2.0.
Assim, a criação de um certificado de 1º de janeiro de 2008 a 1º de janeiro de 2010, pode ser feita da seguinte forma:
openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 200801010000Z -enddate 201001010000Z
ou
openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 0801010000Z -enddate 1001010000Z
-startdate
e -enddate
aparecem nas openssl
fontes e no log CHANGE; como observou @guntbert, embora não apareçam na man openssl
página principal, também aparecem em man ca
:
-startdate date this allows the start date to be explicitly set. The format of the date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure). -enddate date this allows the expiry date to be explicitly set. The format of the date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure).
Citando openssl/CHANGE
:
Mudanças entre 0.9.3a e 0.9.4 [09 de agosto de 1999]
*) Corrija os argumentos -startdate e -enddate (que estavam faltando) no programa 'ca'.
PS Quanto à resposta escolhida doperguntavocê faz referência no StackExchange: geralmente é umpéssima ideiaalterar a hora do sistema, especialmente em sistemas de produção; e com os métodos desta resposta você não precisa de privilégios de root ao usá-los.
Responder2
Fico quase surpreso ao descobrir que o óbvio funciona: enquanto openssl
toma como argumento o número de dias durante os quais o certificado deve ser válido, basta fornecer um número negativo!
openssl req -x509 -newkey rsa:4096 \
-keyout key.pem -out cert.pem -days -365
Observe que isso na verdade resulta em algo muito estranho: um certificado cujo carimbo de data/hora de expiraçãoprecedeseu carimbo de data/hora de início de validade. Na verdade, não recomendo que você use isso para testes automatizados, pois é estranho. Você provavelmente também deseja uma maneira de retroagir o carimbo de data e hora de início de validade.
Responder3
Ou você pode usar algo como este pequeno programa python ... (ressalvas se aplicam)
Ele cria uma chave (test.key) e um certificado (test.crt) com tempo de início de 10 anos atrás (-10*365*24*60*60 segundos é -10 anos) e tempo de expiração de 5 anos atrás (-5*365*24*60*60).
Por favor note que é um programa de demonstração mínimo, por isso não se preocupa em definir nenhuma extensão (por exemplo, basicConstraints) e usa serial fixa.
#!/usr/bin/env python
from OpenSSL import crypto
key = crypto.PKey()
key.generate_key(crypto.TYPE_RSA, 2048)
cert = crypto.X509()
cert.get_subject().CN = "Test"
cert.set_serial_number(666)
cert.gmtime_adj_notBefore(-10*365*24*60*60)
cert.gmtime_adj_notAfter(-5*365*24*60*60)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(key)
cert.sign(key, 'sha384')
open("test.crt", "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
open("test.key", "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key))
Responder4
Passo 1.Instale o tempo falso
sudo apt-get install faketime
Passo 2.Gere o certificado expirado um dia antes da data atual.
faketime 'last friday 5 pm' /bin/bash -c 'openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 6 -nodes'
Etapa 3Verifique a data de validade do certificado
openssl x509 -noout -text -in cert.pem