rla*_*ter 30 openssl certificates
我想动态创建具有任意开始和结束日期的自签名证书,包括过去的结束日期。我更喜欢使用标准工具,例如 OpenSSL,但任何能完成工作的东西都会很棒。
Stack Overflow 问题如何生成不到一天到期的 openssl 证书?问了一个类似的问题,但我希望我的证书是自签名的。
如果您想知道,自动化测试需要证书。
Rui*_*iro 39
过去您有两种创建证书的方法。要么伪造时间(1)(2),要么在签署证书时定义时间间隔(3)。
1)首先,关于伪造时间:让一个程序认为它与系统在不同的日期,看看libfaketime
和faketime
要在 Debian 中安装它:
sudo apt-get install faketime
Run Code Online (Sandbox Code Playgroud)
然后您将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
Run Code Online (Sandbox Code Playgroud)
来自man faketime
:
给定的命令将被欺骗相信当前系统时间是时间戳中指定的时间。除非另有说明,挂钟将从此日期和时间继续运行(请参阅高级选项)。实际上,faketime 是 libfaketime 的一个简单包装器,它使用 LD_PRELOAD 机制加载一个小型库,该库拦截对 time(2) 和 fstat(2) 等函数的系统调用。
因此,例如,在您的情况下,您可以很好地定义 2008 年的日期,然后创建有效期为 2 年至 2010 年的证书。
faketime '2008-12-24 08:15:42' openssl ...
Run Code Online (Sandbox Code Playgroud)
附带说明一下,该实用程序可以在包括 MacOS 在内的多个 Unix 版本中用作任何类型程序的包装器(不限于命令行)。
作为澄清,只有使用此方法加载的二进制文件(及其子文件)才会更改时间,并且假时间不会影响系统其余部分的当前时间。
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
Run Code Online (Sandbox Code Playgroud)
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
:
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
或者
openssl ca -config /path/to/myca.conf -in req.csr -out ourdomain.pem \
-startdate 0801010000Z -enddate 1001010000Z
Run Code Online (Sandbox Code Playgroud)
-startdate
并且-enddate
确实出现在openssl
源和更改日志中;正如@guntbert 所指出的,虽然它们没有出现在man openssl
主页中,但它们也出现在man ca
:
Run Code Online (Sandbox Code Playgroud)-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 权限。
Cel*_*ada 10
我几乎惊讶地发现显而易见的事情是有效的:而openssl
将证书应该有效的天数作为参数,只需提供一个负数!
openssl req -x509 -newkey rsa:4096 \
-keyout key.pem -out cert.pem -days -365
Run Code Online (Sandbox Code Playgroud)
请注意,这实际上会导致一些非常奇怪的事情:证书的到期时间戳在其有效期开始时间戳之前。我实际上不建议您将其用于自动化测试,因为它很奇怪。您可能还需要一种方法来回溯有效期开始的时间戳。
或者你可以使用类似这个简短的 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))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
20515 次 |
最近记录: |