创建结束日期为过去的自签名证书

创建结束日期为过去的自签名证书

我想动态创建具有任意开始日期和结束日期的自签名证书,包括过去的。我更喜欢使用标准工具,例如 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 并确保大小安全。不鼓励使用 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

证书有效期 - 屏幕截图

相关内容