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

17

Gostaria de criar certificados auto-assinados rapidamente com datas de início e término arbitrárias, incluindo datas de término no passado . Eu preferiria usar ferramentas padrão, por exemplo, o OpenSSL, mas qualquer coisa que conclua o trabalho seria ótima.

A questão do Stack Overflow Como gerar O certificado openssl com validade inferior a um dia? faz uma pergunta semelhante, mas eu quero que meu certificado seja auto-assinado.

Caso você esteja se perguntando, os certificados são necessários para testes automatizados.

    
por rlandster 15.04.2017 / 20:40

3 respostas

24

Você tem duas maneiras de criar certificados no passado. Fingindo a hora (1) (2) ou definindo o intervalo de tempo ao assinar o certificado (3).

1) Em primeiro lugar, sobre falsificar o tempo: para fazer um programa pensar que está em uma data diferente do sistema, dê uma olhada em libfaketime e faketime

Para instalá-lo no Debian:

sudo apt-get install faketime

Você usaria faketime antes do comando openssl .

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 :

The given command will be tricked into believing that the current system time is the one specified in the timestamp. The wall clock will continue to run from this date and time unless specified otherwise (see advanced options). Actually, faketime is a simple wrapper for libfaketime, which uses the LD_PRELOAD mechanism to load a small library which intercepts system calls to functions such as time(2) and fstat(2).

Assim, por exemplo, no seu caso, você pode muito bem definir uma data de 2008 e criar um certificado com a validade de 2 anos até 2010.

faketime '2008-12-24 08:15:42' openssl ... 

Como uma nota lateral, este utilitário pode ser usado em várias versões Unix, incluindo MacOS, como um wrapper para qualquer tipo de programa (não exclusivo para a linha de comando).

Como esclarecimento, somente os binários carregados com esse método (e seus filhos) têm seu tempo alterado, e o tempo falso não afeta a hora atual do restante do sistema.

2) Como afirma @Wyzard, você também tem o pacote datefudge , que é muito similar em uso para faketime .

Como diferenças, datefudge não influencia fstat (ou seja, não altera a criação de tempo de arquivo). Ele também tem sua própria biblioteca, datefudge.so, que carrega usando LD_PRELOAD.

Ele também tem um -s static time , onde o tempo referenciado é sempre retornado, apesar de quantos segundos extras terem passado.

$ 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 ainda mais simplesmente, você também pode definir o ponto de partida e o ponto final de validade do certificado quando assinar o certificado no OpenSSL.

O equívoco da pergunta que você faz em sua pergunta é que a validade do certificado não é definida no momento da solicitação (na solicitação do CSR), mas ao assiná-la.

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 as fontes 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 no registro CHANGE (erro 2038?) - Este registro de alterações é apenas como uma nota de rodapé adicional, já que só diz respeito àqueles que usam diretamente a API.

Changes between 1.1.0e and 1.1.1 [xx XXX xxxx]

*) Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed with Z. These are meant to replace LONG and ZLONG and to be size safe. The use of LONG and ZLONG is discouraged and scheduled for deprecation in OpenSSL 1.2.0.

Portanto, criar um certificado de 1º de janeiro de 2008 a 1º de janeiro de 2010 pode ser feito como:

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 fontes openssl e no registro CHANGE; como @guntbert observou, embora eles não apareçam na página principal man openssl , eles 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 :

Changes between 0.9.3a and 0.9.4 [09 Aug 1999]

*) Fix -startdate and -enddate (which was missing) arguments to 'ca' program.

P.S. Quanto à resposta escolhida da pergunta referência do StackExchange: geralmente é uma má ideia alterar 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.

    
por 15.04.2017 / 21:36
7

Estou quase surpreso ao descobrir que a coisa óbvia funciona: enquanto openssl toma como argumento o número de dias para 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 realmente resulta em algo muito estranho: um certificado cujo timestamp de expiração precede seu registro de data e hora de início de validade. Eu não recomendo que você use isso para o seu teste automatizado, já que é estranho. Você provavelmente quer uma maneira de atualizar o registro de data e hora de início de validade também.

    
por 15.04.2017 / 20:48
2

Ou você poderia usar algo parecido com este programa de python curto ... (ressalvas se aplicam)

Cria uma chave (test.key) e um certificado (test.crt) com tempo de início de 10 anos no passado (-10 * 365 * 24 * 60 * 60 segundos é -10 anos) e tempo de expiração de 5 anos no passado (-5 * 365 * 24 * 60 * 60).

Por favor, note que é um programa de demonstração mínimo, por isso não se preocupa em definir extensões (por exemplo, basicConstraints) e usa serial fixo.

#!/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))
    
por 16.04.2017 / 04:24