Erstellen Sie ein selbstsigniertes Zertifikat mit einem Enddatum in der Vergangenheit

24

Ich möchte selbstsignierte Zertifikate mit beliebigen Start- und Enddaten erstellen, einschließlich Enddaten in der Vergangenheit . Ich würde es vorziehen, Standardtools zu verwenden, z. B. OpenSSL, aber alles, was die Arbeit erledigt, wäre großartig.

Die Frage zum Stapelüberlauf Wie wird ein openssl-Zertifikat mit einem Ablauf von weniger als einem Tag generiert? stellt eine ähnliche Frage, aber ich möchte, dass mein Zertifikat selbst signiert wird.

Falls Sie sich fragen, werden die Zertifikate für automatisierte Tests benötigt.

rlandster
quelle

Antworten:

32

In der Vergangenheit haben Sie zwei Möglichkeiten, Zertifikate zu erstellen. Entweder Fälschung der Zeit (1) (2) oder Festlegung des Zeitintervalls beim Signieren des Zertifikats (3).

1) Erstens, um die Zeit zu fälschen: Um ein Programm davon zu überzeugen, dass es sich um ein anderes Datum als das System handelt, werfen Sie einen Blick auf libfaketimeundfaketime

So installieren Sie es in Debian:

sudo apt-get install faketime

Sie würden dann faketimevor dem opensslBefehl verwenden.

Für Anwendungsbeispiele:

$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

Von man faketime:

Der gegebene Befehl wird verleitet, um zu glauben, dass die aktuelle Systemzeit die im Zeitstempel angegebene ist. Die Wanduhr läuft ab diesem Datum und dieser Uhrzeit weiter, sofern nicht anders angegeben (siehe erweiterte Optionen). Tatsächlich ist faketime ein einfacher Wrapper für libfaketime, der mithilfe des LD_PRELOAD-Mechanismus eine kleine Bibliothek lädt, die Systemaufrufe auf Funktionen wie time (2) und fstat (2) abfängt.

So können Sie beispielsweise in Ihrem Fall sehr gut ein Datum von 2008 definieren und dann ein Zertifikat mit einer Gültigkeit von 2 Jahren bis 2010 erstellen.

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

Nebenbei bemerkt, dieses Dienstprogramm kann in mehreren Unix-Versionen, einschließlich MacOS, als Wrapper für alle Arten von Programmen verwendet werden (nicht ausschließlich für die Befehlszeile).

Zur Verdeutlichung wurde die Zeit nur für die mit dieser Methode geladenen Binärdateien (und ihre untergeordneten Dateien) geändert, und die Fälschungszeit hat keinen Einfluss auf die aktuelle Zeit des restlichen Systems.

2) Wie @Wyzard feststellt, haben Sie auch das datefudgePaket, das in der Verwendung sehr ähnlich istfaketime .

B. Unterschiede, datefudgenicht beeinflussenfstatB. (dh die Erstellung der Dateizeit nicht verändern). Es hat auch eine eigene Bibliothek, datefudge.so, die mit LD_PRELOAD geladen wird.

Es gibt auch einen -s static timePunkt, an dem die referenzierte Zeit immer zurückgegeben wird, obwohl die Anzahl der Sekunden überschritten wurde.

$ datefudge --static "2007-04-01 10:23" sh -c "sleep 3; date -R"
Sun, 01 Apr 2007 10:23:00 +0100

3) Neben der Fälschung der Uhrzeit und noch einfacher können Sie beim Signieren auch den Start- und Endpunkt der Gültigkeit des Zertifikats festlegen das Zertifikat in OpenSSL .

Das Missverständnis der Frage, auf die Sie in Ihrer Frage verweisen, besteht darin, dass die Gültigkeit des Zertifikats nicht zum Zeitpunkt der Anforderung (bei der CSR-Anforderung) definiert wird, sondern beim Signieren.

Fügen Sie openssl cabeim Erstellen des selbstsignierten Zertifikats die Optionen -startdateund hinzu -enddate.

Das Datumsformat in diesen beiden Optionen wird laut OpenSL-Quellen unter angegeben openssl/crypto/x509/x509_vfy.c lautet laut OpenSL- ASN1_TIME oder ASN1UTCTime: Das Format muss entweder YYYYMMDDHHMMSSZ oder YYYYMMDDHHMMSSZ sein.

Zitat 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."
     */

Und aus dem CHANGE-Protokoll (2038-Fehler?) - Dieses Änderungsprotokoll ist nur eine zusätzliche Fußnote, da es nur diejenigen betrifft, die direkt die API verwenden.

Änderungen zwischen 1.1.0e und 1.1.1 [xx XXX xxxx]

*) Fügen Sie die ASN.1-Typen INT32, UINT32, INT64, UINT64 und Varianten mit dem Präfix Z hinzu. Diese sollen LONG und ZLONG ersetzen und größensicher sein. Von der Verwendung von LONG und ZLONG wird abgeraten und in OpenSSL 1.2.0 wird eine Veralterung erwartet.

Das Erstellen eines Zertifikats vom 1. Januar 2008 bis zum 1. Januar 2010 kann folgendermaßen erfolgen:

openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 200801010000Z -enddate 201001010000Z

oder

openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 0801010000Z -enddate 1001010000Z

-startdateund -enddateerscheinen in den opensslQuellen und im CHANGE-Protokoll; Wie @guntbert bemerkte, erscheinen sie zwar nicht auf der man opensslHauptseite, aber auch in 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).

Zitat openssl/CHANGE:

Änderungen zwischen 0.9.3a und 0.9.4 [09 Aug 1999]

*) Die fehlenden Argumente -startdate und -enddate für das Programm 'ca' wurden korrigiert.

PS Was die gewählte Antwort auf die Frage betrifft, die Sie von StackExchange referenzieren: Es ist im Allgemeinen eine schlechte Idee , die Systemzeit zu ändern, insbesondere in Produktionssystemen. und mit den Methoden in dieser Antwort benötigen Sie keine root-Rechte, wenn Sie sie verwenden.

Rui F Ribeiro
quelle
1
+1. Ich wusste, dass jemand mit etwas
Besserem
2
Es gibt auch ein ähnliches Programm namens datefudge.
Wyzard
@Wyzard Danke, in der Tat habe ich es in Debian gefunden; Interessanterweise heißt es im Handbuch, dass Systemaufrufe zwar auch auf Funktionen wie time (2) geändert werden, fstat (2) jedoch nicht beeinflusst wird.
Rui F Ribeiro
1
Beides faketimeund datefudgearbeiten wunderbar an meinem Debian-Jessie-System.
Rlandster
1
OTOH: +5, um herauszufinden, wo diese Daten festgelegt werden müssen!
guntbert
8

Ich bin fast überrascht, dass das Offensichtliche funktioniert: Nimmt man opensslals Argument die Anzahl der Tage, für die das Zertifikat gültig sein soll, so muss nur eine negative Zahl angegeben werden!

openssl req -x509 -newkey rsa:4096 \
    -keyout key.pem -out cert.pem -days -365

Beachten Sie, dass dies tatsächlich zu etwas sehr Seltsamem führt: Ein Zertifikat, dessen Ablaufzeitstempel vor dem Gültigkeitsbeginnszeitstempel liegt. Ich empfehle nicht wirklich, dass Sie dieses für Ihr automatisiertes Testen verwenden, da es sonderbar ist. Möglicherweise möchten Sie auch den Zeitstempel für den Gültigkeitsbeginn zurückdatieren.

Celada
quelle
Um fair zu sein, ich hatte keine Ahnung, dass Sie negative Tage verwenden könnten.
Rui F Ribeiro
Können Sie kein Startdatum angeben?
FreeSoftwareServers
@FreeSoftwareServers Im CSR können Sie nicht; Siehe den letzten Teil meiner Antwort.
Rui F Ribeiro
Interessanter noch: Findet der Code kein solches Zertifikat? Übrigens habe ich meine Antwort erweitert
Rui F Ribeiro
3

Oder Sie könnten so etwas wie dieses kurze Python-Programm verwenden ... (Vorbehalte gelten)

Es erstellt einen Schlüssel (test.key) und ein Zertifikat (test.crt) mit einer Anfangszeit von 10 Jahren in der Vergangenheit (-10 * 365 * 24 * 60 * 60 Sekunden ist -10 Jahre) und einer Ablaufzeit von 5 Jahren in der Vergangenheit (-5 * 365 * 24 * 60 * 60).

Bitte beachten Sie, dass es sich um ein minimales Demo-Programm handelt, sodass es keine Erweiterungen (z. B. basicConstraints) zulässt und feste Seriennummern verwendet.

#!/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))
Edheldil
quelle
Dem Code scheinen wichtige X.509-Standardfelder zu fehlen.
Rui F Ribeiro
2
Das ist sehr hilfreich. Dies erleichtert mir die programmgesteuerte Kontrolle über die Zertifikaterstellung.
Rlandster