ตรวจสอบห่วงโซ่ใบรับรองโดยใช้ openssl ตรวจสอบ


129

ฉันกำลังสร้างห่วงโซ่ใบรับรองของตัวเองโดยมีส่วนประกอบต่อไปนี้:

Root Certificate - Intermediate Certificate - User Certificate

Root Cert คือใบรับรองที่ลงนามด้วยตนเองใบรับรองระดับกลางลงนามโดย Root และ User โดย Intermediate

ตอนนี้ฉันต้องการตรวจสอบว่าใบรับรองผู้ใช้มีจุดยึดโดยใบรับรองหลักหรือไม่

กับ

openssl verify -verbose -CAfile RootCert.pem Intermediate.pem

การตรวจสอบก็โอเค ในขั้นตอนต่อไปฉันตรวจสอบใบรับรองผู้ใช้ด้วย

openssl verify -verbose -CAfile Intermediate.pem UserCert.pem

และการตรวจสอบจะแสดง

error 20 at 0 depth lookup:unable to get local issuer certificate

เกิดอะไรขึ้น?

คำตอบ:


166

จากverifyเอกสารประกอบ:

หากพบใบรับรองซึ่งเป็นผู้ออกใบรับรองจะถือว่าเป็น CA หลัก

กล่าวอีกนัยหนึ่ง root CA ต้องเซ็นชื่อด้วยตนเองเพื่อยืนยันว่าจะทำงานได้ นี่คือสาเหตุที่คำสั่งที่สองของคุณไม่ทำงาน ลองสิ่งนี้แทน:

openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem

จะตรวจสอบห่วงโซ่ทั้งหมดของคุณในคำสั่งเดียว


2
ฉันกำลังโหวตคำตอบนี้เนื่องจากฉันเพิ่งต้องทำสิ่งนี้และหลังจากลองใช้ตัวเลือกต่างๆที่แสดงโดยman verifyฉันพบว่า-untrustedพารามิเตอร์เป็นพารามิเตอร์ที่ถูกต้องที่จะใช้เมื่อระบุใบรับรองระดับกลาง
Anthony Geoghegan

ฉันคิดว่าคำตอบที่สอง: stackoverflow.com/a/31205833/173062แม่นยำกว่า - มันส่งผ่านห่วงโซ่ของใบรับรองไปยังพารามิเตอร์ -CAfile
Glenjamin

2
-untrustedไม่ตรวจสอบว่าห่วงโซ่ใบรับรองถูกต้องหรือไม่ โปรดพิจารณาที่จะส่งคำสั่งทั้งระดับกลางและระดับรากตาม-CAfileที่คำถามอื่นแนะนำ
Envek

2
ใช้ -untrusted สำหรับ Intermediate.pem หากเป็นไปได้ว่าสิ่งต่อไปนี้จะเกิดขึ้น: mail.python.org/pipermail/cryptography-dev/2016-August/…
Greg Smethells

2
นั่นไม่ใช่สิ่งที่ OP ขอ แต่ในกรณีที่คุณต้องการตรวจสอบว่าไม่ใช่เครือข่ายที่ลงนามด้วยตนเองให้ใช้ไฟล์ CA ของระบบ / เบราว์เซอร์แทนของคุณเอง ตัวอย่างเช่นบน OS X ที่มี openssl จากการใช้ homebrew:openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
Greg Dubicki

50

นั่นเป็นหนึ่งในงานที่ถูกต้องตามกฎหมายสำหรับcat:

openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem

ปรับปรุง:

เกร็กเป็นจุด Smethells ออกในความคิดเห็นที่คำสั่งนี้โดยปริยายไว้ใจ Intermediate.pem ฉันขอแนะนำให้อ่านส่วนแรกของการอ้างอิงของโพสต์ Greg (ส่วนที่สองเป็นเรื่องเกี่ยวกับ pyOpenSSL โดยเฉพาะและไม่เกี่ยวข้องกับคำถามนี้)

ในกรณีที่โพสต์หายไปฉันจะพูดถึงย่อหน้าสำคัญ:

น่าเสียดายที่ใบรับรอง "ระดับกลาง" ที่เป็นรูท / เซ็นชื่อด้วยตนเอง จะถือว่าเป็น CA ที่เชื่อถือได้เมื่อใช้คำสั่งที่แนะนำที่ระบุไว้ด้านบน:

$ openssl ตรวจสอบ -CAfile <(cat geotrust_global_ca.pem rogue_ca.pem) fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem: ตกลง

ดูเหมือนว่า openssl จะหยุดการตรวจสอบ chain ทันทีที่พบใบรับรองหลักซึ่งอาจเป็น Intermediate.pem หากมีการลงนามด้วยตนเอง ในกรณีนั้นจะไม่พิจารณา RootCert.pem ดังนั้นตรวจสอบให้แน่ใจว่า Intermediate.pem มาจากแหล่งที่เชื่อถือได้ก่อนที่จะใช้คำสั่งด้านบน


สิ่งนี้จะตรวจสอบใบรับรองระดับกลางกับใบรับรองหลักจริงหรือไม่
augurar

มัน. ฉันเพิ่งรันคำสั่งอีกครั้งด้วยห่วงโซ่ที่ฉันรู้ว่าถูกต้อง (มันให้บริการปริมาณการใช้งานการผลิตสำหรับนายจ้างของฉัน) และอีกครั้งกับใบรับรองรูทอื่นที่ไม่เกี่ยวข้อง ดูเค้าหลักฐาน
Peter

8
คำเตือน: ไม่ไม่ใช้นี้ถ้า Intermediate.pem เป็นที่ทุกคนที่ไม่น่าเชื่อถือ อ่านข้อมูลเพิ่มเติมได้ที่นี่: mail.python.org/pipermail/cryptography-dev/2016-August/…
Greg Smethells

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

1
@somenickname ดูความคิดเห็นของ Tony ตัวเลือกที่ไม่ไว้วางใจนั้นดีกว่าอยู่แล้ว ฉันขอแนะนำให้คุณถามคำถามของคุณเองหากคุณต้องการความช่วยเหลือเพิ่มเติม ความคิดเห็นไม่ใช่สถานที่ที่เหมาะสมในการแก้ไขปัญหาของคุณ
ปีเตอร์

18

ปัญหาคือopenssl -verifyไม่ได้ทำงาน

ดังที่ Priyadi กล่าวไว้ให้openssl -verifyหยุดที่ใบรับรองที่ลงนามด้วยตนเองครั้งแรกดังนั้นคุณจึงไม่ได้ตรวจสอบห่วงโซ่จริงๆเนื่องจากใบรับรองระดับกลางมักจะลงนามด้วยตนเอง

ฉันคิดว่าคุณต้องแน่ใจ 101% ว่าไฟล์ใบรับรองนั้นถูกต้องก่อนที่คุณจะพยายามติดตั้งในบริการเว็บที่มีประสิทธิผล สูตรนี้ที่นี่ดำเนินการตรวจสอบก่อนเที่ยวบินนี้

โปรดทราบว่าคำตอบของ Peter ถูกต้องอย่างไรก็ตามผลลัพธ์ของopenssl -verifyไม่มีเงื่อนงำที่ทุกอย่างจะได้ผลในภายหลัง ใช่อาจพบปัญหาบางอย่าง แต่ก็ไม่ใช่ทั้งหมด

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

#!/bin/bash
# This Works is placed under the terms of the Copyright Less License,
# see file COPYRIGHT.CLL.  USE AT OWN RISK, ABSOLUTELY NO WARRANTY. 
#
# COPYRIGHT.CLL can be found at http://permalink.de/tino/cll
# (CLL is CC0 as long as not covered by any Copyright)

OOPS() { echo "OOPS: $*" >&2; exit 23; }

PID=
kick() { [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; }
trap 'kick' 0

serve()
{
kick
PID=
openssl s_server -key "$KEY" -cert "$CRT" "$@" -www &
PID=$!
sleep .5    # give it time to startup
}

check()
{
while read -r line
do
    case "$line" in
    'Verify return code: 0 (ok)')   return 0;;
    'Verify return code: '*)    return 1;;
#   *)  echo "::: $line :::";;
    esac
done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/)
OOPS "Something failed, verification output not found!"
return 2
}

ARG="${1%.}"
KEY="$ARG.key"
CRT="$ARG.crt"
BND="$ARG.bundle"

for a in "$KEY" "$CRT" "$BND"
do
    [ -s "$a" ] || OOPS "missing $a"
done

serve
check && echo "!!! =========> CA-Bundle is not needed! <========"
echo
serve -CAfile "$BND"
check
ret=$?
kick

echo
case $ret in
0)  echo "EVERYTHING OK"
    echo "SSLCertificateKeyFile $KEY"
    echo "SSLCertificateFile    $CRT"
    echo "SSLCACertificateFile  $BND"
    ;;
*)  echo "!!! =========> something is wrong, verification failed! <======== ($ret)";;
esac

exit $ret

โปรดทราบว่าผลลัพธ์ที่ตามมาEVERYTHING OKคือการตั้งค่า Apache เนื่องจากคนที่ใช้NginXหรือhaproxyโดยปกติสามารถอ่านและเข้าใจสิ่งนี้ได้อย่างสมบูรณ์เช่นกัน;)

มีGitHub Gistซึ่งอาจมีการอัปเดตบางอย่าง

ข้อกำหนดเบื้องต้นของสคริปต์นี้:

  • คุณมีข้อมูลราก CA ที่เชื่อถือได้/etc/ssl/certsตามปกติเช่นบน Ubuntu
  • สร้างไดเร็กทอรีDIRที่คุณจัดเก็บ 3 ไฟล์:
    • DIR/certificate.crt ซึ่งมีใบรับรอง
    • DIR/certificate.key ซึ่งมีรหัสลับสำหรับบริการเว็บของคุณ (ไม่มีข้อความรหัสผ่าน)
    • DIR/certificate.bundleซึ่งประกอบด้วย CA-Bundle เกี่ยวกับวิธีการเตรียมชุดดูด้านล่าง
  • ตอนนี้เรียกใช้สคริปต์: ./check DIR/certificate(ซึ่งถือว่าสคริปต์มีชื่อcheckอยู่ในไดเร็กทอรีปัจจุบัน)
  • CA-Bundle is not neededมีกรณีที่ไม่น่าเป็นที่ผลสคริปต์ ซึ่งหมายความว่าคุณ (อ่าน/etc/ssl/certs/:) เชื่อถือใบรับรองการลงนามแล้ว แต่สิ่งนี้ไม่น่าเกิดขึ้นอย่างมากใน WWW
  • สำหรับพอร์ตทดสอบ 4433 นี้ต้องไม่ได้ใช้งานบนเวิร์กสเตชันของคุณ และควรรันสิ่งนี้ในสภาพแวดล้อมที่ปลอดภัยเท่านั้นเนื่องจากจะเปิดพอร์ต 4433 ต่อสาธารณะในไม่ช้าซึ่งอาจเห็นการเชื่อมต่อต่างประเทศในสภาพแวดล้อมที่ไม่เป็นมิตร

จะสร้างcertificate.bundleไฟล์ได้อย่างไร?

ใน WWW เครือข่ายความไว้วางใจมักจะมีลักษณะดังนี้:

  • ใบรับรองที่เชื่อถือได้จาก /etc/ssl/certs
  • ใบรับรองระดับกลางที่ไม่รู้จักอาจมีการลงนามข้ามโดย CA อื่น
  • ใบรับรองของคุณ ( certificate.crt)

ตอนนี้การประเมินจะเกิดขึ้นจากล่างขึ้นบนนั่นหมายความว่าอันดับแรกใบรับรองของคุณจะถูกอ่านจากนั้นจึงจำเป็นต้องมีใบรับรองระดับกลางที่ไม่รู้จักจากนั้นอาจจะต้องใช้ใบรับรองการเซ็นชื่อข้ามจากนั้น/etc/ssl/certsจึงได้รับการปรึกษาเพื่อค้นหาใบรับรองที่เชื่อถือได้ที่เหมาะสม

ca-bundle จะต้องประกอบขึ้นตามลำดับการประมวลผลที่ถูกต้องซึ่งหมายความว่าใบรับรองที่จำเป็นอันดับแรก (ใบรับรองระดับกลางที่ลงนามในใบรับรองของคุณ) จะมาเป็นอันดับแรกในกลุ่ม จากนั้นต้องใช้ใบรับรองการลงนามข้ามกัน

โดยปกติแล้ว CA ของคุณ (หน่วยงานที่ลงนามในใบรับรองของคุณ) จะให้ไฟล์ ca-bundle-file ที่เหมาะสมดังกล่าวอยู่แล้ว หากไม่เป็นเช่นนั้นคุณต้องเลือกใบรับรองระดับกลางที่จำเป็นทั้งหมดและcatรวมกันเป็นไฟล์เดียว (บน Unix) ใน Windows คุณสามารถเปิดโปรแกรมแก้ไขข้อความ (เช่นnotepad.exe) และวางใบรับรองลงในไฟล์ได้โดยอันดับแรกต้องอยู่ด้านบนและทำตามรายการอื่น ๆ

ยังมีอีกสิ่งหนึ่ง ไฟล์ต้องอยู่ในรูปแบบ PEM CA บางรายการออกรูปแบบ DER (ไบนารี) PEM สามารถมองเห็นได้ง่าย: ASCII สามารถอ่านได้ สำหรับวิธีการแปลงบางสิ่งเป็น PEM โปรดดูวิธีการแปลง. crt เป็น. pemและทำตามถนนอิฐสีเหลือง

ตัวอย่าง:

คุณมี:

  • intermediate2.crt ใบรับรองระดับกลางซึ่งลงนามในไฟล์ certificate.crt
  • intermediate1.crt ใบรับรองระดับกลางอื่นซึ่งร้องเพลง intermediate2.crt
  • crossigned.crt ซึ่งเป็นใบรับรองการลงนามไขว้จาก CA อื่นซึ่งลงนาม intermediate1.crt
  • crossintermediate.crtซึ่งเป็นสื่อกลางอื่นจาก CA อื่นที่ลงนามcrossigned.crt(คุณอาจไม่เคยเห็นสิ่งนี้)

จากนั้นค่าที่เหมาะสมcatจะมีลักษณะดังนี้:

cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle

และคุณจะทราบได้อย่างไรว่าไฟล์ใดที่จำเป็นหรือไม่และอยู่ในลำดับใด

ทดลองจนกว่าคำตอบcheckจะบอกคุณว่าทุกอย่างเรียบร้อยดี มันเป็นเหมือนเกมปริศนาคอมพิวเตอร์เพื่อไขปริศนา ทุกๆ เดียว เวลา. แม้สำหรับมืออาชีพ แต่คุณจะดีขึ้นทุกครั้งที่ต้องทำสิ่งนี้ ดังนั้นคุณไม่ได้อยู่คนเดียวกับความเจ็บปวดทั้งหมดนั้นแน่นอน มันคือ SSL รู้ไหม SSL อาจเป็นหนึ่งในการออกแบบที่แย่ที่สุดที่ฉันเคยเห็นในการดูแลระบบมืออาชีพกว่า 30 ปี เคยสงสัยไหมว่าทำไม crypto ถึงไม่กลายเป็นกระแสหลักในช่วง 30 ปีที่ผ่านมา? นั่นเป็นเหตุผลว่าทำไม 'Nuff กล่าวว่า.


ถึงผู้โหวตกรุณาอธิบายว่ามีอะไรผิดปกติกับคำตอบของฉัน ขอบคุณ
Tino

2
ฉันเป็นหนึ่งในผู้ลงคะแนน สิ่งที่ทำให้เกิดการโหวตลดคือ "และคุณจะทราบได้อย่างไรว่าไฟล์ใดที่จำเป็นหรือไม่และอยู่ในลำดับใดลองทดสอบจนกว่าเครื่องหมายจะบอกคุณว่าทุกอย่างเรียบร้อยดี" ฉันไม่คิดว่า SSL เป็นกรณีพิเศษ ปัญหาเช่นนี้ควรมีแนวทางแก้ไข
ychaouche

2
@ychaouche ขอบคุณ! เช่นคุณฉันชอบสิ่งที่ไม่เหมาะสม คำถามคือ "มีอะไรผิดปกติ" และทำอย่างไรกับ "openssl ตรวจสอบ" ในขณะที่เราอยู่ใน stackoverflow ฉันจึงอธิบายสิ่งนั้นตามด้วยคำตอบแบบเป็นโปรแกรม (จึงเป็นตัวกำหนด) ใช่ / ไม่ใช่ คุณยังสามารถใช้เพื่อตรวจสอบ Bundle ใหม่โดยอัตโนมัติก่อนที่จะติดตั้งลงในเวอร์ชันที่ใช้งานจริง สิ่งนี้ตอบคำถามได้ครบถ้วน สิ่งที่คุณไม่ชอบคือฉันบอกเกี่ยวกับความไม่พอใจใน "จะสร้างชุดรวมที่เหมาะสมได้อย่างไร" ในขณะที่ฉันคิดว่าไม่มีคำตอบสั้น ๆ สำหรับสิ่งนั้นการตอบคำถามนี้จะไม่ตรงประเด็นในบริบทที่นี่
Tino

6
"ดังที่ Priyadi กล่าวถึง openssl - ยืนยันการหยุดที่ใบรับรองที่ลงนามด้วยตนเองครั้งแรกดังนั้นคุณจึงไม่ได้ตรวจสอบความถูกต้องของห่วงโซ่อย่างแท้จริงเนื่องจากใบรับรองระดับกลางมักจะลงนามด้วยตนเอง" เห็นได้ชัดว่าใบรับรองระดับกลางไม่เคยลงนามด้วยตนเอง (ถ้าเป็นใบรับรองหลัก) และจุดรวมของการตรวจสอบคือการตรวจสอบว่าคุณได้รวมใบรับรองทั้งหมดในเครือไปจนถึงใบรับรองหลักที่เชื่อถือได้ นี่คือสิ่งที่ openssl ตรวจสอบได้อย่างแม่นยำ อย่างไรก็ตาม openssl มีแนวโน้มที่จะค่อนข้างอนุรักษ์นิยมกับนโยบายที่เชื่อถือได้ ...
Timo

4
"บ่อยครั้งที่ใบรับรองระดับกลางลงนามด้วยตนเอง" สิ่งนี้ไม่ถูกต้องและความสับสนในคำศัพท์เช่นนี้ทำให้ยากสำหรับผู้มาใหม่ที่จะเข้าใจหัวข้อที่จริงแล้วค่อนข้างง่ายเมื่ออธิบายอย่างถูกวิธี จาก RFC 5280: "[... ] ใบรับรอง CA อาจแบ่งออกได้อีกเป็นสามประเภท: ใบรับรองข้ามใบรับรองที่ออกเองและใบรับรองที่ลงนามด้วยตนเองใบรับรองข้ามคือใบรับรอง CA ที่ผู้ออกและหัวเรื่องต่างกัน . Cross-certificate อธิบายถึงความสัมพันธ์ที่เชื่อถือได้ระหว่าง CA ทั้งสอง [... ] ".
Dr. Jan-Philip Gehrcke

8

ฉันต้องทำการตรวจสอบใบรับรอง Letsencrypt และฉันทำแบบนี้:

  1. ดาวน์โหลดรากใบรับรองและกลางใบรับรองจากห่วงโซ่ letsencrypt ของความไว้วางใจ
  2. ออกคำสั่งนี้:

    $ openssl verify -CAfile letsencrypt-root-cert/isrgrootx1.pem.txt -untrusted letsencrypt-intermediate-cert/letsencryptauthorityx3.pem.txt /etc/letsencrypt/live/sitename.tld/cert.pem 
    /etc/letsencrypt/live/sitename.tld/cert.pem: OK
    

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

5

หลังจากใช้เวลาทั้งวันในปัญหาเดียวกันโดยไม่มีความรู้มาก่อนเกี่ยวกับใบรับรอง SSL ฉันดาวน์โหลดCERTivity Keystores Managerและนำเข้าที่เก็บคีย์ของฉันไปที่นั่นและได้รับการแสดงภาพที่ชัดเจนของห่วงโซ่ใบรับรอง

ภาพหน้าจอ:

ใส่คำอธิบายภาพที่นี่


1
openssl verifyไม่พยายามที่จะตอบคำถามซึ่งเป็นเรื่องเกี่ยวกับวิธีการใช้
binki

ใช่ แต่เครื่องมือประเภทนี้สามารถให้คุณเห็นภาพที่จำเป็นสำหรับสิ่งนั้น ๆ หากคุณไม่เข้าใจข้อมูลที่เป็นความลับของเครื่องมือบรรทัดคำสั่ง openssl :) ดังนั้นนี่คือการโหวตเพิ่มของฉันอาจมีบางสิ่งออนไลน์ที่ทำเช่นนั้นเช่นกัน
David 天宇 Wong

2

ถ้าคุณเพียงต้องการที่จะตรวจสอบว่าผู้ออกหลักทรัพย์ของUserCert.pem จริง Intermediate.pemทำดังต่อไปนี้ (ใช้ตัวอย่างเช่นOpenSSL 1.1.1):

openssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pem

และคุณจะได้รับ:

UserCert.pem: OK

หรือ

UserCert.pem: verification failed

มีคำสั่งที่เทียบเท่าสำหรับopenssl verify -no-CAfile -no-CApath -partial_chain -trusted Intermediate.pem UserCert.pemใน Python 3.7 หรือไม่
โบโกตา

-5

คุณสามารถตรวจสอบห่วงโซ่ใบรับรองได้อย่างง่ายดายด้วย openssl fullchain จะรวมใบรับรอง CA ดังนั้นคุณควรดูรายละเอียดเกี่ยวกับ CA และใบรับรองนั้นเอง

openssl x509 -in fullchain.pem -text -noout


4
1) ทั้งหมดนี้ไม่มีคำอธิบายใด ๆ 2) นี่คือคำตอบสำหรับคำถามที่ผู้ถามไม่ได้ถามโดยไม่มีบริบทใด ๆ
Shadur
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.