สร้างใบรับรองที่ลงชื่อด้วยตนเองพร้อมวันที่สิ้นสุดในอดีต


24

ผมอยากจะสร้างใบรับรองลงนามด้วยตนเองในการบินด้วยโดยพลการที่เริ่มต้นและสิ้นสุดวันที่รวมทั้งสิ้นวันที่ในอดีตที่ผ่านมา ฉันต้องการใช้เครื่องมือมาตรฐานเช่น OpenSSL แต่สิ่งใดก็ตามที่ทำให้งานสำเร็จลุล่วงได้ดี

คำถาม Stack Overflow วิธีสร้างใบรับรอง openssl ที่หมดอายุน้อยกว่าหนึ่งวัน ถามคำถามที่คล้ายกัน แต่ฉันต้องการให้ใบรับรองของฉันลงนามด้วยตนเอง

ในกรณีที่คุณสงสัยใบรับรองจำเป็นสำหรับการทดสอบอัตโนมัติ

คำตอบ:


32

คุณมีวิธีสร้างใบรับรองสองวิธีในอดีต แกล้งทำเวลา (1) (2) หรือกำหนดช่วงเวลาเมื่อลงชื่อใบรับรอง (3)

1) ประการแรกเกี่ยวกับการแกล้งเวลา: เพื่อให้โปรแกรมหนึ่งคิดว่าเป็นวันที่ที่แตกต่างจากระบบให้ดูlibfaketimeและfaketime

วิธีติดตั้งใน 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 เป็น wrapper ง่าย ๆ สำหรับ libfaketime ซึ่งใช้กลไก LD_PRELOAD เพื่อโหลดไลบรารี่ขนาดเล็กที่ขัดขวางการเรียกของระบบไปยังฟังก์ชั่นเช่นเวลา (2) และ fstat (2)

ตัวอย่างเช่นในกรณีของคุณคุณสามารถกำหนดวันที่ปี 2008 ได้เป็นอย่างดีและสร้างใบรับรองที่มีความถูกต้อง 2 ปีจนถึงปี 2010

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

ในฐานะที่เป็นหมายเหตุด้านข้างยูทิลิตี้นี้สามารถใช้งานได้ใน Unix หลายรุ่นรวมถึง MacOS เพื่อใช้เป็นโปรแกรมเสริมสำหรับโปรแกรมประเภทใดก็ได้ (ไม่รวมถึงบรรทัดคำสั่ง)

เพื่อความชัดเจนเฉพาะไบนารีที่โหลดด้วยวิธีนี้ (และลูก ๆ ) เท่านั้นที่มีการเปลี่ยนแปลงเวลาและเวลาปลอมไม่ส่งผลกระทบต่อเวลาปัจจุบันของระบบที่เหลือ

2) ในฐานะที่เป็นรัฐ @Wyzard คุณยังมีแพคเกจซึ่งเป็นที่คล้ายกันมากในการใช้งานเพื่อdatefudgefaketime

เนื่องจากความแตกต่าง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 หรือ YYYYMMMMDDHHMMSSZ

การอ้างอิง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."
     */

และจากบันทึก CHANGE (ข้อผิดพลาด 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

ดังนั้นการสร้างใบรับรองจากวันที่ 1 มกราคม 2008 ถึงวันที่ 1 มกราคมของปี 2010 สามารถทำได้ดังนี้:

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 ส.ค. 2542]

*) แก้ไข -startdate และ -enddate (ซึ่งหายไป) อาร์กิวเมนต์ของโปรแกรม 'ca'

PS สำหรับคำตอบที่เลือกของคำถามที่คุณอ้างอิงจาก StackExchange: โดยทั่วไปแล้วมันเป็นความคิดที่ดีที่จะเปลี่ยนเวลาของระบบโดยเฉพาะในระบบที่ใช้งานจริง และด้วยวิธีการต่าง ๆ ในคำตอบนี้คุณไม่จำเป็นต้องมีสิทธิ์ใช้งานรูทเมื่อใช้งาน


1
+1 ผมรู้ว่าคนที่จะมาพร้อมกับสิ่งที่ดีกว่าสิ่งที่ผมเขียน :)
Celada

2
datefudgeนอกจากนี้ยังมีโปรแกรมที่คล้ายกันเรียกว่า
Wyzard

@ Wyzard ขอบคุณจริง ๆ ฉันพบมันใน Debian; น่าสนใจมากพอคู่มือระบุว่าแม้ว่ามันจะเปลี่ยนการเรียกของระบบไปยังฟังก์ชั่นเช่นเวลา (2) แต่ก็ไม่ได้มีผลต่อ fstat (2)
Rui F Ribeiro

1
ทั้งคู่faketimeและdatefudgeทำงานอย่างสวยงามบนระบบเจสซี Debian ของฉัน
rlandster

1
OTOH: +5 สำหรับการค้นหาตำแหน่งที่จะตั้งวันที่เหล่านั้น!
guntbert

8

ฉันเกือบจะประหลาดใจที่พบว่าสิ่งที่ชัดเจนใช้งานได้: ในขณะที่opensslใช้อาร์กิวเมนต์เป็นจำนวนวันที่ใบรับรองควรถูกต้องเพียงระบุจำนวนลบ!

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

โปรดทราบว่าสิ่งนี้ส่งผลให้เกิดสิ่งที่แปลกมาก: ใบรับรองที่มีการประทับเวลาหมดอายุนำหน้าการประทับเวลาเริ่มต้นของการมีผลบังคับใช้ ฉันไม่แนะนำให้คุณใช้สิ่งนี้ในการทดสอบอัตโนมัติเนื่องจากมันแปลก คุณอาจต้องการวิธีการแก้ไขการประทับเวลาเริ่มต้นที่ถูกต้องเช่นกัน


เพื่อความยุติธรรมฉันไม่รู้เลยว่าคุณสามารถใช้วันในเชิงลบได้
Rui F Ribeiro

คุณไม่สามารถระบุวันที่เริ่มต้นได้หรือไม่?
FreeSoftwareServers

@FreeSoftwareServers ใน CSR คุณไม่สามารถทำได้ ดูส่วนสุดท้ายของคำตอบของฉัน
Rui F Ribeiro

ยิ่งไปกว่านั้น interstingly, barf รหัสการค้นหาใบรับรองดังกล่าวจะไม่? btw ฉันขยายคำตอบของฉัน
Rui F Ribeiro

3

หรือคุณสามารถใช้โปรแกรมหลามสั้น ๆ นี้ ...

มันสร้างคีย์ (test.key) และใบรับรอง (test.crt) ที่มีเวลาเริ่มต้น 10 ปีที่ผ่านมา (-10 * 365 * 24 * 60 * 60 วินาทีคือ -10 ปี) และเวลาหมดอายุ 5 ปีที่ผ่านมา (-5 * 365 * 24 * 60 * 60)

โปรดทราบว่ามันเป็นโปรแกรมสาธิตขั้นต่ำดังนั้นจึงไม่จำเป็นต้องตั้งค่าส่วนขยายใด ๆ (เช่นข้อ จำกัด พื้นฐาน) และใช้อนุกรมแบบคงที่

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

รหัสดูเหมือนจะไม่มีฟิลด์มาตรฐาน X.509 ที่จำเป็น
Rui F Ribeiro

2
สิ่งนี้มีประโยชน์มาก มันทำให้ฉันควบคุมการเขียนโปรแกรมได้ง่ายขึ้น
rlandster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.