Создать самоподписанный сертификат с конечной датой в прошлом

Создать самоподписанный сертификат с конечной датой в прошлом

Я хотел бы создавать самоподписанные сертификаты «на лету» с произвольными датами начала и окончания, включая даты окончания впрошлоеЯ бы предпочел использовать стандартные инструменты, например OpenSSL, но все, что справится с этой задачей, было бы замечательно.

Вопрос Stack OverflowКак сгенерировать сертификат openssl со сроком действия менее одного дня?задает аналогичный вопрос, но я хочу, чтобы мой сертификат был самоподписанным.

Если вам интересно, сертификаты необходимы для автоматизированного тестирования.

решение1

В прошлом у вас было два способа создания сертификатов: либо подделывать время (1)(2), либо определять временной интервал при подписании сертификата (3).

1) Во-первых, о подделке времени: чтобы заставить одну программу думать, что она находится в другой дате, чем система, посмотрите libfaketimeиfaketime

Чтобы установить его в Debian:

sudo apt-get install faketime

Затем вы должны использовать faketimeперед opensslкомандой.

Примеры использования:

$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

От man faketime:

Данная команда будет обманута, заставив поверить, что текущее системное время — это время, указанное в метке времени. Настенные часы продолжат работать с этой даты и времени, если не указано иное (см. дополнительные параметры). На самом деле faketime — это простая оболочка для libfaketime, которая использует механизм LD_PRELOAD для загрузки небольшой библиотеки, которая перехватывает системные вызовы таких функций, как time(2) и fstat(2).

Так, например, в вашем случае вы вполне можете указать дату 2008 год и создать сертификат со сроком действия 2 года до 2010 года.

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

Кстати, эту утилиту можно использовать в нескольких версиях Unix, включая MacOS, в качестве оболочки для любого типа программ (не только для командной строки).

В качестве пояснения: время изменяется только у двоичных файлов, загруженных с помощью этого метода (и их дочерних файлов), а поддельное время не влияет на текущее время остальной части системы.

2) Как утверждает @Wyzard, у вас также есть datefudgeпакет, который по использованию очень похож на faketime.

Как отличия, datefudgeне влияет fstat(т.е. не меняет время создания файла). Также имеет свою собственную библиотеку datefudge.so, которую загружает с помощью LD_PRELOAD.

Также имеется функция, -s static timeв которой всегда возвращается указанное время, независимо от того, сколько дополнительных секунд прошло.

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

3) Помимо подделки времени, и что еще проще, вы также можете определить начальную и конечную точку действия сертификата, когдаподписаниесертификат в OpenSSL.

Ошибочное понимание вопроса, на который вы ссылаетесь в своем вопросе, заключается в том, что действительность сертификата определяется не во время запроса (при запросе CSR), а при его подписании.

При использовании openssl caдля создания самоподписанного сертификата добавьте параметры -startdateи -enddate.

Формат даты в этих двух вариантах, согласно источникам openssl по адресу openssl/crypto/x509/x509_vfy.c, — ASN1_TIME, он же ASN1UTCTime: формат должен быть либо YYMMDDHHMMSSZ, либо YYYYMMDDHHMMSSZ.

Цитата 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."
     */

А из журнала изменений (ошибка 2038?) - этот журнал изменений является просто дополнительной сноской, поскольку касается только тех, кто использует API напрямую.

Изменения между 1.1.0e и 1.1.1 [xx XXX xxxx]

*) Добавьте типы ASN.1 INT32, UINT32, INT64, UINT64 и варианты с префиксом Z. Они предназначены для замены LONG и ZLONG и для обеспечения безопасности размера. Использование LONG и ZLONG не рекомендуется и запланировано к прекращению в OpenSSL 1.2.0.

Таким образом, создание сертификата с 1 января 2008 года по 1 января 2010 года можно осуществить следующим образом:

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

или

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

-startdateи -enddateпоявляются в opensslисточниках и журнале ИЗМЕНЕНИЙ; как заметил @guntbert, хотя они и не появляются на главной man opensslстранице, они также появляются в 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).

Цитата openssl/CHANGE:

Изменения между 0.9.3a и 0.9.4 [09 августа 1999]

*) Исправлены аргументы -startdate и -enddate (которые отсутствовали) в программе «ca».

PS Что касается выбранного ответавопросВы ссылаетесь на StackExchange: это, как правило,плохая идеядля изменения системного времени, особенно в производственных системах; и с помощью методов, описанных в этом ответе, вам не нужны права root при их использовании.

решение2

Я почти удивлен, обнаружив, что очевидная вещь работает: в то время как opensslв качестве аргумента принимается количество дней, в течение которых сертификат должен быть действителен, просто укажите отрицательное число!

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

Обратите внимание, что на самом деле это приводит к чему-то очень странному: сертификату, срок действия которого истекаетпредшествуетего метка времени начала действия. Я на самом деле не рекомендую вам использовать это для автоматизированного тестирования, так как это странно. Вероятно, вам также нужен способ датировать метку времени начала действия задним числом.

решение3

Или вы можете использовать что-то вроде этой короткой программы на Python... (с оговорками)

Он создает ключ (test.key) и сертификат (test.crt) со временем начала действия 10 лет назад (-10*365*24*60*60 секунд составляет -10 лет) и временем истечения срока действия 5 лет назад (-5*365*24*60*60).

Обратите внимание, что это минимальная демонстрационная программа, поэтому она не устанавливает никаких расширений (например, basicConstraints) и использует фиксированный последовательный номер.

#!/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))

решение4

Шаг 1.Установить фейктайм

sudo apt-get install faketime

Шаг 2.Сгенерировать просроченный сертификат за день до текущей даты.

faketime 'last friday 5 pm' /bin/bash -c 'openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 6 -nodes'

Шаг 3Проверьте дату действия сертификата

openssl x509 -noout -text -in cert.pem

Срок действия сертификата - Скриншот

Связанный контент