建立結束日期為過去的自簽名證書

建立結束日期為過去的自簽名證書

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

堆疊溢位問題如何產生有效期限小於一天的openssl憑證?問類似的問題,但我希望我的憑證是自簽署的。

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

答案1

過去有兩種建立證書的方法。偽造時間 (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

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 bug?) - 此變更日誌只是一個附加腳註,因為它只涉及那些直接使用 API 的人。

1.1.0e 和 1.1.1 之間的變更 [xx XXX xxxx]

*) 新增 ASN.1 類型 INT32、UINT32、INT64、UINT64 以及以 Z 為前綴的變體。不鼓勵使用 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 之間的變更 [1999 年 8 月 9 日]

*)修正「ca」程式的 -startdate 和 -enddate (缺少)參數。

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

證書有效期限 - 螢幕截圖

相關內容