Openssl

創建結束日期在過去的自簽名證書

  • May 22, 2020

我想動態創建具有任意開始和結束日期的自簽名證書,包括過去的結束日期。我更喜歡使用標準工具,例如 OpenSSL,但任何能完成工作的東西都會很棒。

Stack Overflow 問題如何生成有效期少於 1 天的 openssl 證書?問了一個類似的問題,但我希望我的證書是自簽名的。

如果您想知道,自動化測試需要證書。

過去,您有兩種創建證書的方法。偽造時間 (1)(2),或在簽署證書時定義時間間隔 (3)。

1)首先,關於偽造時間:讓一個程序認為它與系統的日期不同,看看libfaketimefaketime

在 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
  1. 除了偽造時間,更簡單的說,您還可以在 OpenSSL 中籤署證書時定義證書有效期的起點和終點。

您在問題中連結到的問題的誤解是證書有效性不是在請求時(在 CSR 請求中)定義的,而是在簽名時定義的。

用於openssl ca創建自簽名證書時,添加選項-startdate-enddate.

根據 openssl 來源,這兩個選項中的日期格式openssl/crypto/x509/x509_vfy.c是 ASN1_TIME aka 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 中棄用。

因此,創建一個從 2008 年 1 月 1 日到 2010 年 1 月 1 日的證書,可以這樣完成:

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 Aug 1999 $$ *) 修復 ‘ca’ 程序的 -startdate 和 -enddate(缺少)參數。

PS 至於您從 StackExchange 引用的問題的選擇答案:更改系統時間通常是一個*壞主意,尤其是在生產系統中;*並且使用此答案中的方法,您在使用它們時不需要root權限。

引用自:https://unix.stackexchange.com/questions/359225