Tạo chứng chỉ tự ký với ngày kết thúc trong quá khứ


24

Tôi muốn tạo chứng chỉ tự ký một cách nhanh chóng với ngày bắt đầu và ngày kết thúc tùy ý, bao gồm cả ngày kết thúc trong quá khứ . Tôi thích sử dụng các công cụ tiêu chuẩn, ví dụ OpenSSL, nhưng bất cứ điều gì hoàn thành công việc sẽ rất tuyệt.

Câu hỏi về Stack Overflow Làm thế nào để tạo chứng chỉ openssl khi hết hạn dưới một ngày? hỏi một câu hỏi tương tự, nhưng tôi muốn chứng chỉ của mình được tự ký.

Trong trường hợp bạn đang tự hỏi, các chứng chỉ là cần thiết để kiểm tra tự động.

Câu trả lời:


32

Bạn có hai cách tạo chứng chỉ trong quá khứ. Hoặc giả mạo thời gian (1) (2) hoặc xác định khoảng thời gian khi ký chứng chỉ (3).

1) Thứ nhất, về việc giả mạo thời gian: để làm cho một chương trình nghĩ rằng đó là một ngày khác với hệ thống, hãy xem libfaketimefaketime

Để cài đặt nó trong Debian:

sudo apt-get install faketime

Sau đó, bạn sẽ sử dụng faketimetrướcopenssl lệnh.

Ví dụ về việc sử dụng:

$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

Từ man faketime:

Lệnh đã cho sẽ bị lừa tin rằng thời gian hệ thống hiện tại là thời gian được chỉ định trong dấu thời gian. Đồng hồ treo tường sẽ tiếp tục chạy từ ngày và giờ này trừ khi được chỉ định khác (xem các tùy chọn nâng cao). Trên thực tế, faketime là một trình bao bọc đơn giản cho libfaketime, sử dụng cơ chế LD_PRELOAD để tải một thư viện nhỏ chặn các cuộc gọi hệ thống đến các chức năng như thời gian (2) và fstat (2).

Vì vậy, ví dụ, trong trường hợp của bạn, bạn có thể xác định rất rõ ngày tháng năm 2008 và tạo chứng chỉ có hiệu lực trong 2 năm cho đến năm 2010.

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

Là một lưu ý phụ, tiện ích này có thể được sử dụng trong một số phiên bản Unix, bao gồm MacOS, như một trình bao bọc cho bất kỳ loại chương trình nào (không dành riêng cho dòng lệnh).

Để làm rõ, chỉ có các tệp nhị phân được tải bằng phương thức này (và con cái của chúng) có thời gian thay đổi và thời gian giả không ảnh hưởng đến thời gian hiện tại của phần còn lại của hệ thống.

2) Như @Wyzard tuyên bố, bạn cũng có datefudgegói sử dụng rất giống với faketime.

Như sự khác biệt, datefudgekhông ảnh hưởng fstat(tức là không thay đổi thời gian tạo tập tin). Nó cũng có thư viện riêng của nó, datefudge.so, nó tải bằng LD_PRELOAD.

Nó cũng có một -s static timethời gian mà thời gian được tham chiếu luôn được trả về mặc dù đã thêm bao nhiêu giây nữa.

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

3) Bên cạnh việc giả mạo thời gian và thậm chí đơn giản hơn, bạn cũng có thể xác định điểm bắt đầu và điểm kết thúc hiệu lực của chứng chỉ khi chứng chỉ trong OpenSSL.

Quan niệm sai lầm về câu hỏi bạn liên kết đến trong câu hỏi của bạn, đó là tính hợp lệ của chứng chỉ không được xác định tại thời điểm yêu cầu (tại yêu cầu CSR), nhưng khi ký tên.

Khi sử dụng openssl cađể tạo chứng chỉ tự ký, hãy thêm các tùy chọn -startdate-enddate.

Định dạng ngày trong hai tùy chọn đó, theo các nguồn openssl tại openssl/crypto/x509/x509_vfy.c, là ASN1_TIME hay còn gọi là ASN1UTCTime: định dạng phải là YYMMDDHHMMSSZ hoặc YYYYMMDDHHMMSSZ.

Trích dẫn 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."
     */

Và từ nhật ký CHANGE (lỗi 2038?) - Nhật ký thay đổi này chỉ là một chú thích bổ sung, vì nó chỉ liên quan đến những người sử dụng trực tiếp API.

Thay đổi giữa 1.1.0e và 1.1.1 [xx XXX xxxx]

*) Thêm các loại ASN.1 INT32, UINT32, INT64, UINT64 và các biến thể có tiền tố Z. Chúng có nghĩa là thay thế LONG và ZLONG và để có kích thước an toàn. Việc sử dụng LONG và ZLONG không được khuyến khích và lên kế hoạch cho việc phản đối trong OpenSSL 1.2.0.

Vì vậy, việc tạo chứng chỉ từ ngày 1 tháng 1 năm 2008 đến ngày 1 tháng 1 năm 2010, có thể được thực hiện như sau:

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

hoặc là

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

-startdate-enddatexuất hiện trong các opensslnguồn và nhật ký THAY ĐỔI; như @guntbert lưu ý, trong khi chúng không xuất hiện trên man openssltrang chính , chúng cũng xuất hiện trong 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).

Trích dẫn openssl/CHANGE:

Thay đổi giữa 0.9.3a và 0.9.4 [09 tháng 8 năm 1999]

*) Khắc phục các đối số -startdate và -enddate (đã bị thiếu) cho chương trình 'ca'.

PS Đối với câu trả lời được chọn của câu hỏi mà bạn tham khảo từ StackExchange: nói chung là một ý tưởng tồi để thay đổi thời gian hệ thống, đặc biệt là trong các hệ thống sản xuất; và với các phương thức trong câu trả lời này, bạn không cần quyền root khi sử dụng chúng.


1
+1. Tôi biết ai đó sẽ đi cùng với một cái gì đó tốt hơn những gì tôi đã viết :)
Celada

2
Cũng có một chương trình tương tự được gọi là datefudge.
Wyzard

@Wyzard Cảm ơn, thực sự tôi đã tìm thấy nó trong Debian; đủ thú vị, hướng dẫn sử dụng nói rằng mặc dù nó cũng thay đổi các cuộc gọi hệ thống thành các chức năng như thời gian (2), nhưng nó không ảnh hưởng đến fstat (2).
Rui F Ribeiro

1
Cả hai faketimedatefudgehoạt động tốt trên hệ thống jessie Debian của tôi.
rlandster

1
OTOH: +5 để tìm nơi đặt những ngày đó!
guntbert

8

Tôi gần như ngạc nhiên khi thấy rằng điều hiển nhiên hoạt động: trong khi đó openssllà một đối số số ngày mà chứng chỉ phải hợp lệ, chỉ cung cấp một số âm!

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

Lưu ý rằng điều này thực sự dẫn đến một điều rất kỳ lạ: một chứng chỉ có dấu thời gian hết hạn trước dấu thời gian bắt đầu có hiệu lực của nó. Tôi thực sự không khuyên bạn nên sử dụng điều này cho thử nghiệm tự động của mình, vì nó thật kỳ lạ. Bạn có thể muốn một cách để ngày trở lại dấu thời gian bắt đầu hợp lệ là tốt.


Chà, công bằng mà nói, tôi không biết bạn có thể sử dụng những ngày tiêu cực.
Rui F Ribeiro

Bạn có thể không chỉ định ngày bắt đầu?
FreeSoftwareServers

@FreeSoftwareServers Trong CSR bạn không thể; xem phần cuối câu trả lời của tôi
Rui F Ribeiro

Thêm nữa, liệu mã vạch có tìm được chứng chỉ đó không? btw, tôi đã mở rộng câu trả lời của mình
Rui F Ribeiro

3

Hoặc bạn có thể sử dụng một cái gì đó giống như chương trình python ngắn này ... (áp dụng hãy cẩn thận)

Nó tạo ra một khóa (test.key) và chứng chỉ (test.crt) với thời gian khởi động 10 năm trong quá khứ (-10 * 365 * 24 * 60 * 60 giây là -10 năm) và thời gian hết hạn 5 năm trong quá khứ (-5 * 365 * 24 * 60 * 60).

Xin lưu ý rằng đó là một chương trình trình diễn tối thiểu, do đó, không cần thiết lập bất kỳ tiện ích mở rộng nào, (ví dụ: basicConstraint) và sử dụng nối tiếp cố định.

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

mã dường như thiếu các trường tiêu chuẩn X.509 cần thiết.
Rui F Ribeiro

2
Điều này rất hữu ích. Nó cho phép tôi kiểm soát chương trình dễ dàng hơn trong việc tạo chứng chỉ.
rlandster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.