Crie um certificado autoassinado com data de término no passado

Crie um certificado autoassinado com data de término no passado

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 libfaketimeefaketime

Para instalá-lo no Debian:

sudo apt-get install faketime

Você usaria então faketimeantes do opensslcomando.

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 datefudgepacote que é muito semelhante em uso ao faketime.

Como diferenças, datefudgenã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 timelocal 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 capara criar o certificado autoassinado, adicione as opções -startdatee -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

-startdatee -enddateaparecem nas opensslfontes e no log CHANGE; como observou @guntbert, embora não apareçam na man opensslpá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 openssltoma 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

Datas de validade do certificado – Captura de tela

informação relacionada