วิธีสร้างใบรับรองที่ลงนามเองด้วย OpenSSL


1292

ฉันกำลังเพิ่มการสนับสนุน HTTPS ให้กับอุปกรณ์ Linux ที่ฝังอยู่ ฉันพยายามสร้างใบรับรองที่ลงชื่อด้วยตัวเองด้วยขั้นตอนเหล่านี้:

openssl req -new > cert.csr
openssl rsa -in privkey.pem -out key.pem
openssl x509 -in cert.csr -out cert.pem -req -signkey key.pem -days 1001
cat key.pem>>cert.pem

ใช้งานได้ แต่ฉันได้รับข้อผิดพลาดบางอย่างเช่น Google Chrome:

นี่อาจจะไม่ใช่เว็บไซต์ที่คุณกำลังมองหา!
ใบรับรองความปลอดภัยของเว็บไซต์ไม่น่าเชื่อถือ!

ฉันพลาดอะไรไปรึเปล่า? นี่เป็นวิธีที่ถูกต้องในการสร้างใบรับรองที่ลงชื่อด้วยตนเองหรือไม่


40
ใบรับรองที่ลงนามเองถือว่าไม่ปลอดภัยสำหรับอินเทอร์เน็ต Firefox จะถือว่าไซต์นั้นมีใบรับรองที่ไม่ถูกต้องในขณะที่ Chrome จะทำหน้าที่เหมือนกับการเชื่อมต่อนั้นเป็น HTTP ธรรมดา รายละเอียดเพิ่มเติม: gerv.net/security/self-signed-certs
user1202136

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

12
คุณไม่ควรใช้การตั้งค่า "หุ้น" OpenSSL เช่นนั้น นั่นเป็นเพราะคุณไม่สามารถวางชื่อ DNS ใน Subject Alternate Name (SAN) คุณต้องระบุไฟล์การกำหนดค่าด้วยalternate_namesส่วนและส่งต่อพร้อมกับ-configตัวเลือก นอกจากนี้การวางชื่อ DNS ในชื่อสามัญ (CN) นั้นถูกคัดค้าน (แต่ไม่ห้าม) ทั้ง IETF และฟอรัม CA / เบราว์เซอร์ ชื่อ DNS ใด ๆ ใน CN ต้องปรากฏใน SAN ด้วย ไม่มีวิธีที่จะหลีกเลี่ยงการใช้ SAN ดูคำตอบด้านล่าง
jww

5
นอกจากความคิดเห็นของ @jww ต่อพฤษภาคม 2560 Chrome ไม่ยอมรับ certs โดยไม่มี (emtpy) SAN อีกต่อไป: "ใบรับรองสำหรับไซต์นี้ไม่มีส่วนขยายชื่อสำรองของหัวเรื่องที่มีชื่อโดเมนหรือที่อยู่ IP"
GerardJP

6
วันนี้ตราบใดที่เว็บเซิร์ฟเวอร์ของคุณสามารถเข้าถึงได้โดย FQDN ที่พอร์ต 80 ผ่านอินเทอร์เน็ตคุณสามารถใช้ LetsEncrypt และรับ CA certs ฟรี (ใช้ได้ 90 วันสามารถต่ออายุอัตโนมัติ) ที่จะไม่ให้คำเตือนเกี่ยวกับเบราว์เซอร์ / ข้อความ www.letsencrypt.com
barny

คำตอบ:


2130

คุณสามารถทำได้ในคำสั่งเดียว:

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

คุณสามารถเพิ่ม-nodes(ย่อให้no DES) หากคุณไม่ต้องการปกป้องรหัสส่วนตัวของคุณด้วยข้อความรหัสผ่าน มิฉะนั้นจะแจ้งให้คุณใส่รหัสผ่าน "อย่างน้อย 4 ตัวอักษร"

daysพารามิเตอร์ (365) คุณสามารถแทนที่ด้วยหมายเลขใด ๆ ที่จะส่งผลกระทบต่อวันหมดอายุ จากนั้นจะแจ้งให้คุณทราบถึงสิ่งต่าง ๆ เช่น "ชื่อประเทศ" แต่คุณสามารถกดEnterและยอมรับค่าเริ่มต้นได้

เพิ่ม-subj '/CN=localhost'เพื่อระงับคำถามเกี่ยวกับเนื้อหาของใบรับรอง (แทนที่localhostด้วยโดเมนที่คุณต้องการ)

ใบรับรองที่ลงนามเองจะไม่ได้รับการตรวจสอบกับบุคคลที่สามใด ๆ เว้นแต่คุณจะนำเข้าใบรับรองไปยังเบราว์เซอร์ก่อนหน้า หากคุณต้องการความปลอดภัยเพิ่มเติมคุณควรใช้ใบรับรองที่ลงนามโดยผู้ออกใบรับรอง (CA)


8
สำหรับผู้ที่สนใจนี่คือเอกสารหากคุณต้องการตรวจสอบด้วยตัวเอง

17
การเซ็นชื่อกับบุคคลที่สามจะให้ความปลอดภัยมากขึ้นได้อย่างไร
James Mills

201
สำหรับคนอื่นที่ใช้สิ่งนี้ในระบบอัตโนมัตินี่คือพารามิเตอร์ทั่วไปทั้งหมดสำหรับหัวเรื่อง:-subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=www.example.com"
Alex S

17
@JamesMills ฉันหมายถึงลองคิดดู - ถ้าผู้ชายที่ดูร่มรื่นด้วย "ขนมฟรี" ที่เขียนไว้ที่ด้านข้างของรถตู้ของเขาเชิญให้คุณเข้ามาข้างในคุณจะคิดอย่างรอบคอบสองครั้งและระวัง แต่ - ถ้าคนที่คุณไว้วางใจ - เหมือนคนที่ไว้ใจจริง ๆทุกคนก็เป็นเหมือน "คนที่ไม่เชื่อเขาเป็นคนที่ถูกต้อง" คุณจะต้องรู้เรื่องขนมฟรี
BrainSlugs83

73
อย่าลืมใช้-sha256เพื่อสร้างใบรับรองที่ใช้SHA-256
Gea-Suan Lin

535

ฉันพลาดอะไรไปรึเปล่า? นี่เป็นวิธีที่ถูกต้องในการสร้างใบรับรองที่ลงชื่อด้วยตนเองหรือไม่

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

มันเป็นเรื่องยากเพราะเบราว์เซอร์ที่มีชุดของตัวเองของความต้องการและพวกเขามีข้อ จำกัด มากขึ้นกว่าIETF ข้อกำหนดที่ใช้โดยเบราว์เซอร์มีการบันทึกไว้ที่CA / Browser Forums (ดูข้อมูลอ้างอิงด้านล่าง) ข้อ จำกัด เกิดขึ้นในสองประเด็นสำคัญ: (1) แองเคอร์ที่เชื่อถือได้และ (2) ชื่อ DNS

เบราว์เซอร์สมัยใหม่ (เช่น warez ที่เราใช้ใน 2014/2015) ต้องการใบรับรองที่โยงกลับไปยังจุดยึดที่เชื่อถือได้และพวกเขาต้องการให้ชื่อ DNS ถูกนำเสนอในรูปแบบเฉพาะในใบรับรอง และเบราว์เซอร์กำลังเคลื่อนไหวต่อต้านใบรับรองเซิร์ฟเวอร์ที่ลงชื่อด้วยตนเอง

เบราว์เซอร์บางตัวไม่สามารถนำเข้าใบรับรองเซิร์ฟเวอร์ที่ลงนามด้วยตนเองได้อย่างง่ายดาย ที่จริงแล้วคุณไม่สามารถใช้เบราว์เซอร์บางตัวได้เช่นเบราว์เซอร์ของ Android ดังนั้นทางออกที่สมบูรณ์คือการเป็นผู้มีอำนาจของคุณเอง

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


นี่อาจจะไม่ใช่เว็บไซต์ที่คุณกำลังมองหา!
ใบรับรองความปลอดภัยของเว็บไซต์ไม่น่าเชื่อถือ!

นี่เป็นเพราะเบราว์เซอร์ใช้รายการจุดยึดความน่าเชื่อถือที่กำหนดไว้ล่วงหน้าเพื่อตรวจสอบใบรับรองเซิร์ฟเวอร์ ใบรับรองที่ลงนามเองไม่โยงกลับไปยังจุดยึดที่เชื่อถือได้

วิธีที่ดีที่สุดในการหลีกเลี่ยงปัญหานี้คือ:

  1. สร้างสิทธิ์ของคุณเอง (เช่นกลายเป็นCA )
  2. สร้างคำขอลงนามใบรับรอง (CSR) สำหรับเซิร์ฟเวอร์
  3. ลงชื่อ CSR ของเซิร์ฟเวอร์ด้วยคีย์ CA ของคุณ
  4. ติดตั้งใบรับรองเซิร์ฟเวอร์บนเซิร์ฟเวอร์
  5. ติดตั้งใบรับรอง CA บนไคลเอนต์

ขั้นตอนที่ 1 - สร้างสิทธิ์ของคุณเองเพียงแค่หมายถึงการสร้างใบรับรองที่ลงชื่อด้วยตัวเองด้วยCA: trueและการใช้คีย์ที่เหมาะสม นั่นหมายความว่าหัวเรื่องและผู้ออกเป็นนิติบุคคลเดียวกัน CA ถูกตั้งค่าเป็นจริงในข้อ จำกัด พื้นฐาน (ควรถูกทำเครื่องหมายว่าสำคัญ), การใช้คีย์คือkeyCertSignและcrlSign(ถ้าคุณใช้ CRL), และSubject Key Identifier (SKI) คือ เช่นเดียวกับAuthority Key Identifier (AKI)

หากต้องการเป็นผู้ออกใบรับรองของคุณเองโปรดดู * คุณจะลงนามในคำขอลงนามใบรับรองกับผู้ออกใบรับรองของคุณได้อย่างไร บน Stack Overflow จากนั้นนำเข้า CA ของคุณไปยัง Trust Store ที่ใช้โดยเบราว์เซอร์

ขั้นตอนที่ 2-4 ประมาณสิ่งที่คุณทำในขณะนี้สำหรับประชาชนหันหน้าไปทางเซิร์ฟเวอร์เมื่อคุณเกณฑ์บริการของแคลิฟอร์เนียเช่นStartcomหรือCAcert ขั้นตอนที่ 1 และ 5 อนุญาตให้คุณหลีกเลี่ยงสิทธิ์บุคคลที่สามและทำหน้าที่เป็นสิทธิ์ของคุณเอง (ใครจะไว้ใจได้ดีกว่าตัวคุณเอง)

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

ปัญหาของเบราว์เซอร์ (และตัวแทนผู้ใช้ที่คล้ายกันอื่น ๆ ) ที่ไม่เชื่อถือใบรับรองที่ลงนามด้วยตนเองจะเป็นปัญหาใหญ่ใน Internet of Things (IoT) ตัวอย่างเช่นจะเกิดอะไรขึ้นเมื่อคุณเชื่อมต่อกับเทอร์โมสแตทหรือตู้เย็นเพื่อตั้งโปรแกรม คำตอบคือไม่มีอะไรดีเท่าประสบการณ์ของผู้ใช้ที่เกี่ยวข้อง

WebAppSec Working Group ของ W3C เริ่มมองปัญหาแล้ว ดูตัวอย่างเช่นข้อเสนอ: การทำเครื่องหมายในฐานะที่เป็น HTTP ที่ไม่ปลอดภัย


วิธีสร้างใบรับรองที่ลงนามเองด้วย OpenSSL

คำสั่งด้านล่างและไฟล์กำหนดค่าสร้างใบรับรองแบบลงนามด้วยตนเอง (นอกจากนี้ยังแสดงวิธีสร้างคำขอเซ็นชื่อด้วย) พวกเขาแตกต่างจากคำตอบอื่น ๆ ในแง่หนึ่ง: ชื่อ DNS ที่ใช้สำหรับใบรับรอง self ลงนามอยู่ในชื่อเรื่องสำรองข้อมูล (SAN)และไม่ได้เป็นชื่อสามัญ (CN)

ชื่อ DNS จะถูกวางไว้ใน SAN ผ่านไฟล์การกำหนดค่าที่มีบรรทัดsubjectAltName = @alternate_names(ไม่มีวิธีที่จะทำผ่านบรรทัดคำสั่ง) จากนั้นมีalternate_namesส่วนหนึ่งในไฟล์กำหนดค่า (คุณควรปรับให้เหมาะกับรสนิยมของคุณ):

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# IP.1        = 127.0.0.1
# IP.2        = ::1

สิ่งสำคัญคือต้องใส่ชื่อ DNS ใน SAN ไม่ใช่ CN เพราะทั้ง IETF และ CA / เบราว์เซอร์ฟอรัมจะระบุวิธีปฏิบัติ พวกเขายังระบุว่าชื่อ DNS ใน CN นั้นเลิกใช้แล้ว (แต่ไม่ห้าม) หากคุณใส่ชื่อ DNS ใน CN จะต้องรวมอยู่ใน SAN ภายใต้นโยบาย CA / B ดังนั้นคุณไม่สามารถหลีกเลี่ยงการใช้ชื่อสำรองของหัวเรื่องได้

หากคุณไม่ใส่ชื่อ DNS ใน SAN ใบรับรองจะไม่ผ่านการตรวจสอบภายใต้เบราว์เซอร์และตัวแทนผู้ใช้อื่น ๆ ซึ่งเป็นไปตามแนวทาง CA / เบราว์เซอร์ฟอรัม

ที่เกี่ยวข้อง: เบราว์เซอร์ปฏิบัติตามนโยบาย CA / เบราว์เซอร์ฟอรัม ไม่ใช่นโยบายของ IETF นี่คือหนึ่งในเหตุผลที่ใบรับรองที่สร้างด้วย OpenSSL (ซึ่งตามหลัง IETF) บางครั้งไม่ได้ตรวจสอบภายใต้เบราว์เซอร์ (เบราว์เซอร์เป็นไปตาม CA / B) พวกเขาเป็นมาตรฐานที่แตกต่างกันพวกเขามีนโยบายการออกที่แตกต่างกันและข้อกำหนดการตรวจสอบที่แตกต่างกัน


สร้างใบรับรองที่ลงชื่อด้วยตนเอง (สังเกตเห็นการเพิ่ม-x509ตัวเลือก):

openssl req -config example-com.conf -new -x509 -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.cert.pem

สร้างคำขอเซ็น (สังเกตเห็นว่าไม่มี-x509ตัวเลือก):

openssl req -config example-com.conf -new -sha256 -newkey rsa:2048 -nodes \
    -keyout example-com.key.pem -days 365 -out example-com.req.pem

พิมพ์ใบรับรองที่ลงนามเอง :

openssl x509 -in example-com.cert.pem -text -noout

พิมพ์คำขอลงนาม :

openssl req -in example-com.req.pem -text -noout

ไฟล์การกำหนดค่า (ผ่าน-configตัวเลือก)

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because it's presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@example.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier    = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage    = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = example.com
DNS.2       = www.example.com
DNS.3       = mail.example.com
DNS.4       = ftp.example.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

คุณอาจต้องทำสิ่งต่อไปนี้สำหรับ Chrome มิฉะนั้นChrome อาจบ่นชื่อสามัญไม่ถูกต้อง (ERR_CERT_COMMON_NAME_INVALID ) ฉันไม่แน่ใจว่าความสัมพันธ์ระหว่างที่อยู่ IP ใน SAN และ CN ในกรณีนี้คืออะไร

# IPv4 localhost
# IP.1       = 127.0.0.1

# IPv6 localhost
# IP.2     = ::1

มีกฎอื่น ๆ ที่เกี่ยวข้องกับการจัดการชื่อ DNS ในใบรับรอง X.509 / PKIX อ้างถึงเอกสารเหล่านี้สำหรับกฎ:

RFC 6797 และ RFC 7469 อยู่ในรายการเนื่องจากมีข้อ จำกัด มากกว่าเอกสาร RFC และ CA / B อื่น ๆ RFCs 6797 และ 7469 ไม่อนุญาตให้ใช้ที่อยู่ IP เช่นกัน


4
เป็นไปได้ไหมที่จะใช้ไวด์การ์ดในalternate_namesส่วนนี้ โดเมนย่อยโดยเฉพาะ ฉันมีคำถามอ้างอิงคำตอบนี้ที่นี่: serverfault.com/questions/711596/…
LeonardChallis

3
ฉันเพิ่งตอบคำถามเฉพาะของเขา ฉันคิดว่าไม่เหมาะสมที่จะเพิ่มคำอธิบายความปลอดภัยที่ยาวนานเมื่อคำตอบนั้นง่ายมาก
Diego Woitasen

14
@diegows - คำตอบของคุณไม่สมบูรณ์หรือถูกต้อง เหตุผลที่มันไม่ถูกต้องที่มีการกล่าวถึงในการโพสต์ระยะเวลาที่คุณไม่ต้องการที่จะอ่าน :)
jww

1
ขอบคุณ! ฉันพบว่าโพสต์ของคุณมีประโยชน์มาก FYI ฉันเพิ่งเล่นกับ vault และพบว่ายืนยันใน IP.x 127.0.0.1 มากกว่า DNS.x 127 ... ฉันไม่ได้ตรวจสอบว่านี่เป็นมาตรฐานหรือไม่
Chomeh

4
ขอบคุณ @jww คุณกล่าวว่า"1. สร้างอำนาจของคุณเอง (เช่นกลายเป็นแคลิฟอร์เนีย)"จากนั้นกล่าวว่า"5. ติดตั้งใบรับรอง CA กับลูกค้า" หากรูทคีย์ถูกบุกรุกผู้ประสงค์ร้ายสามารถลงนามใบรับรองสำหรับโดเมนใด ๆ ด้วยคีย์นั้นและหากพวกเขาหลอกให้คุณไปที่เว็บไซต์ของตนตอนนี้พวกเขาสามารถโจมตีคนที่อยู่ตรงกลางได้ มีวิธีในการสร้างรูท CA หรือไม่เพื่อให้มันสามารถลงนาม CA ตัวกลางเท่านั้นและไม่ใช่ใบรับรอง? จากนั้นคุณสามารถป้องกัน CA ตัวกลางของคุณด้วยข้อ จำกัด ของชื่อ
Robin Zimmermann

408

นี่คือตัวเลือกที่อธิบายไว้ในคำตอบของ @ diegowsซึ่งมีรายละเอียดเพิ่มเติมจากเอกสาร :

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX
req

การร้องขอใบรับรอง PKCS # 10 และยูทิลิตี้การสร้างใบรับรอง

-x509

ตัวเลือกนี้แสดงผลใบรับรองที่ลงนามด้วยตนเองแทนการร้องขอใบรับรอง โดยปกติจะใช้ในการสร้างใบรับรองการทดสอบหรือรูต CA ที่ลงชื่อด้วยตนเอง

-newkey arg

ตัวเลือกนี้สร้างคำขอใบรับรองใหม่และคีย์ส่วนตัวใหม่ อาร์กิวเมนต์ใช้หนึ่งในหลายรูปแบบ อาร์เอส: nbitsที่nbitsเป็นจำนวนบิตสร้างคีย์ RSA nbitsในขนาด

-keyout filename

นี่ให้ชื่อไฟล์เพื่อเขียนคีย์ส่วนตัวที่สร้างขึ้นใหม่

-out filename

นี้ระบุชื่อไฟล์ที่ส่งออกไปยังเขียนหรือออกมาตรฐานโดยค่าเริ่มต้น

-days n

เมื่อใช้อ็อพชัน -x509สิ่งนี้จะระบุจำนวนวันที่จะรับรองใบรับรอง ค่าเริ่มต้นคือ 30 วัน

-nodes

หากระบุตัวเลือกนี้หากมีการสร้างคีย์ส่วนตัวจะไม่ถูกเข้ารหัส

เอกสารนี้มีรายละเอียดมากกว่าจริง ฉันเพิ่งสรุปได้ที่นี่


3
XXXในคำสั่งเดิมที่ควรจะแทนที่ด้วย 'จำนวนวันที่จะรับรองใบรับรองสำหรับ' ค่าเริ่มต้นคือ 30 วัน ตัวอย่างเช่น-days XXXกลายเป็น-days 365ถ้าคุณต้องการใบรับรองของคุณจะถูกต้องสำหรับ 365 วัน ดูเอกสารสำหรับข้อมูลเพิ่มเติม
นาธานโจนส์

ขอขอบคุณที่เพิ่มเอกสาร IBM ลิงก์นี้เกี่ยวกับการสร้างใบรับรองที่ลงนามเองโดยใช้คำสั่งซึ่งดูเหมือนกับคำตอบนี้
The Red Pea

314

ตั้งแต่ปี 2020 คำสั่งต่อไปนี้ตอบสนองความต้องการของคุณทั้งหมดรวมถึง SAN:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -extensions san -config \
  <(echo "[req]"; 
    echo distinguished_name=req; 
    echo "[san]"; 
    echo subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1
    ) \
  -subj "/CN=example.com"

ใน OpenSSL ≥ 1.1.1 สิ่งนี้สามารถย่อให้เป็น:

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout example.key -out example.crt -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:example.net,IP:10.0.0.1"

มันสร้างใบรับรองนั่นคือ

  • ใช้ได้กับโดเมนexample.comและexample.net(SAN)
  • ใช้ได้กับที่อยู่ IP 10.0.0.1(SAN)
  • ค่อนข้างแข็งแกร่ง (ณ ปี 2020) และ
  • ใช้ได้สำหรับ3650วัน (~ 10 ปี)

มันสร้างไฟล์ต่อไปนี้:

  • รหัสส่วนตัว: example.key
  • รับรอง: example.crt

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

หมายเหตุ # 1: พารามิเตอร์ Crypto

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

ในอนาคตคุณอาจต้องการใช้มากกว่า4096บิตสำหรับคีย์ RSA และอัลกอริทึมแฮชที่แรงกว่าsha256แต่ในปี 2020 เหล่านี้เป็นค่าที่มีเหตุผล มีความแข็งแรงเพียงพอในขณะที่เบราว์เซอร์สมัยใหม่รองรับ

หมายเหตุ # 2: พารามิเตอร์ " -nodes"

ในทางทฤษฎีคุณสามารถละทิ้ง-nodesพารามิเตอร์ (ซึ่งหมายถึง "ไม่มีการเข้ารหัส DES") ซึ่งในกรณีนี้example.keyจะถูกเข้ารหัสด้วยรหัสผ่าน อย่างไรก็ตามนี่แทบจะไม่เป็นประโยชน์สำหรับการติดตั้งเซิร์ฟเวอร์เพราะคุณจะต้องเก็บรหัสผ่านไว้บนเซิร์ฟเวอร์ด้วยหรือคุณต้องป้อนรหัสด้วยตนเองในการรีบูตแต่ละครั้ง

หมายเหตุ # 3: ดูเพิ่มเติม


1
ฉันไม่สามารถคิดออกว่าจะตำหนิอะไรใน arg / CN = localhost ที่กำลังขยายเป็น C: / Program Files / Git / CN = localhost ดังนั้นฉันจึงรันคำสั่งทั้งหมดใน cmd.exe ธรรมดาและทำงานได้ดี ในกรณีที่บางคนกำลังดิ้นรนกับอันนี้
Yuriy Pozniak

1
@ FrankankYu คุณแน่ใจหรือไม่ว่า rsa: 2048 จะเพียงพอใน 10 ปีจากนี้ เพราะนั่นเป็นช่วงเวลาที่มีผลบังคับใช้ ตามที่อธิบายไว้มันไม่สมเหตุสมผลที่จะใช้การหมดอายุแบบสั้นหรือการเข้ารหัสลับอ่อน คีย์ RSA 2048 บิตส่วนใหญ่มีอายุการใช้งานสูงสุด 1-3 ปี เกี่ยวกับ OpenSSL 1.1.1 ฉันยังคงมี sha256 อยู่ในนั้นดังนั้นจึงมีความชัดเจนและชัดเจนมากขึ้นหากคุณต้องการแฮชที่แข็งแกร่งขึ้น
VOG

1
@DaveFerguson ไม่ได้สร้างใบรับรอง//CN=localhostแทน/CN=localhostหรือ? การหลบหนีที่เหมาะสมจะช่วยได้ไหม ตัวอย่างเช่นการแทนที่/CN=localhostด้วยการ"/CN=localhost"แก้ปัญหาด้วยวิธีที่สะอาดหรือไม่?
VOG

4
1,000 + 1s สำหรับการสร้าง "หนึ่งซับ" ที่ใช้ SAN ที่ต้องการใหม่โดยไม่ต้องสร้างไฟล์กำหนดค่าที่ยืดยาวด้วยหม้อไอน้ำจำนวนมาก ทำได้ดี!
Joshua Pinter

1
@ ข้อควรระวังขอบคุณ! ฉันเพิ่งแก้ไขมันเป็นคำตอบ คำตอบนี้ถูกต้องสำหรับ Windows / MinGW หรือไม่
vog

143

ฉันไม่สามารถแสดงความคิดเห็นดังนั้นฉันจะใส่คำตอบนี้เป็นคำตอบแยกต่างหาก ฉันพบปัญหาเล็กน้อยเกี่ยวกับคำตอบเดียวที่ได้รับการยอมรับ:

  • สายการบินหนึ่งประกอบด้วยข้อความรหัสผ่านในกุญแจ
  • สายการบินเดียวใช้ SHA-1 ซึ่งในเบราว์เซอร์จำนวนมากแสดงคำเตือนในคอนโซล

นี่คือเวอร์ชันที่เรียบง่ายซึ่งจะลบวลีรหัสผ่านเพิ่มความปลอดภัยเพื่อยับยั้งคำเตือนและรวมถึงข้อเสนอแนะในความคิดเห็นเพื่อส่งผ่าน -subj เพื่อลบรายการคำถามแบบเต็ม:

openssl genrsa -out server.key 2048
openssl rsa -in server.key -out server.key
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=localhost'
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

แทนที่ 'localhost' ด้วยโดเมนใดก็ได้ที่คุณต้องการ คุณจะต้องรันคำสั่งสองคำสั่งแรกทีละคำเนื่องจาก OpenSSL จะถามรหัสผ่าน

ในการรวมสองไฟล์เข้ากับไฟล์. pem:

cat server.crt server.key > cert.pem

6
ฉันต้องการใบรับรอง dev สำหรับgithub.com/molnarg/node-http2และคำตอบนี้ดีที่สุด
Capaj

1
cat server.crt server.key >foo-cert.pemที่จะรวมใบรับรองและคีย์ในไฟล์เดียวไปนี้: ทำงานร่วมกับตัวอย่างในopenssl-1.0.2d/demos/ssl/
18446744073709551615

ใบรับรองที่ฉันสร้างขึ้นด้วยวิธีนี้ยังคงใช้ SHA1
user169771

1
Tks ใช้งานได้ดีในการสร้างใบรับรองที่ลงชื่อด้วยตัวเองFreeBSD 10 OpenLDAP 2.4ด้วยTLS
Thiago Pereira

2
แล้วไฟล์ key.pem ล่ะ?
quikchange

72

เบราว์เซอร์รุ่นใหม่จะโยนข้อผิดพลาดด้านความปลอดภัยสำหรับใบรับรองที่ลงชื่อด้วยตนเองอย่างดีหากพวกเขาไม่มี SAN (ชื่อสำรองของหัวเรื่อง) OpenSSL ไม่มีวิธีบรรทัดคำสั่งในการระบุสิ่งนี้ดังนั้นบทช่วยสอนของนักพัฒนาซอฟต์แวร์และบุ๊กมาร์กจึงล้าสมัยอย่างกะทันหัน

วิธีที่เร็วที่สุดในการเริ่มทำงานอีกครั้งคือไฟล์ conf แบบสั้นและแบบสแตนด์อะโลน:

  1. สร้างแฟ้มการกำหนดค่า OpenSSL (ตัวอย่าง: req.cnf)

    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    [req_distinguished_name]
    C = US
    ST = VA
    L = SomeCity
    O = MyCompany
    OU = MyDivision
    CN = www.company.com
    [v3_req]
    keyUsage = critical, digitalSignature, keyAgreement
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = www.company.com
    DNS.2 = company.com
    DNS.3 = company.net
    
  2. สร้างใบรับรองที่อ้างอิงถึงไฟล์กำหนดค่านี้

    openssl req -x509 -nodes -days 730 -newkey rsa:2048 \
     -keyout cert.key -out cert.pem -config req.cnf -sha256
    

ตัวอย่างการกำหนดค่าจากhttps://support.citrix.com/article/CTX135602


1
มันใช้งานได้สำหรับฉันหลังจากลบพารามิเตอร์สุดท้าย - ส่วนขยาย 'v3_req' ซึ่งทำให้เกิดข้อผิดพลาด ใช้ OpenSSL สำหรับ windows ในที่สุดฉันจัดการเพื่อแก้ไขปัญหานี้! ขอบคุณ
CGodo

1
@Kyopaxa คุณพูดถูก - พารามิเตอร์นั้นซ้ำซ้อนกับบรรทัดที่ 3 ของไฟล์ cnf; อัปเดต
rymo

2
ทางแข็ง ขอบคุณ -sha256ผมขอแนะนำให้เพิ่ม
cherouvim

5
ตอนนี้คุณสามารถระบุ SAN บนบรรทัดคำสั่งโดย-extension 'subjectAltName = DNS:dom.ain, DNS:oth.er'ดูที่github.com/openssl/openssl/pull/4986
Alexandre DuBreuil

2
ดูเหมือนว่าตัวเลือกนี้จะถูกเรียก-addextตอนนี้
Alexandr Zarubkin

67

ฉันขอแนะนำให้เพิ่มพารามิเตอร์-sha256เพื่อใช้อัลกอริทึมแฮช SHA-2 เนื่องจากเบราว์เซอร์หลักกำลังพิจารณาที่จะแสดง "ใบรับรอง SHA-1" ไม่ปลอดภัย

บรรทัดคำสั่งเดียวกันจากคำตอบที่ยอมรับ - @diegows ด้วย -sha256 ที่เพิ่มเข้ามา

openssl req -x509 -sha256 -newkey rsa: 2048 -keyout key.pem -out cert.pem -days XXX

ข้อมูลอื่น ๆ ในบล็อกความปลอดภัยของ Google

อัปเดตพฤษภาคม 2018 ดังที่ระบุไว้ในความคิดเห็นที่ใช้ SHA-2 ไม่ได้เพิ่มความปลอดภัยให้กับใบรับรองที่ลงนามด้วยตนเอง แต่ฉันยังคงแนะนำให้ใช้มันเป็นนิสัยที่ดีที่จะไม่ใช้ฟังก์ชันแฮชการเข้ารหัสลับที่ล้าสมัย / ไม่ปลอดภัย คำอธิบายแบบเต็มมีอยู่ในทำไมจึงดีสำหรับใบรับรองด้านบนใบรับรองเอนทิตีที่จะใช้ SHA-1 .


1
หากเป็นรหัสที่ลงนามเองมันจะสร้างข้อผิดพลาดของเบราว์เซอร์ต่อไปดังนั้นนี่ไม่สำคัญ
Mark

30
@ Mark มันสำคัญเพราะ SHA-2 มีความปลอดภัยมากขึ้น
Maris B.

1
การเปิดใบรับรองใน windows หลังจากเปลี่ยนชื่อ cert.pem เป็น cert.cer กล่าวว่าอัลกอริธึมลายนิ้วมือยังคงเป็น Sha1 แต่อัลกอริทึมแฮชลายเซ็นคือ sha256
ทำบาป

2
"การเข้ารหัสระดับโลก * การรับรองความถูกต้องเป็นศูนย์ = ความปลอดภัยเป็นศูนย์" gerv.net/security/self-signed-certs
x-yuri

4
โปรดทราบว่าอัลกอริธึมลายเซ็นที่ใช้กับใบรับรองที่ลงนามเองนั้นไม่เกี่ยวข้องในการตัดสินใจว่าเชื่อถือได้หรือไม่ certs รูท CA นั้นลงนามด้วยตนเอง และ ณ เดือนพฤษภาคม 2018 ยังคงมีใบรับรอง CA ที่รูทที่ใช้งานอยู่จำนวนมากที่ลงนาม SHA-1 เพราะมันไม่สำคัญว่าใบรับรองเชื่อถือตัวเองหรือไม่และใบรับรองนั้นตรวจสอบความน่าเชื่อถือนั้นอย่างไร คุณอาจเชื่อถือใบรับรอง root / self-signed สำหรับบุคคลที่ระบุว่าเป็นหรือไม่ ดูsecurity.stackexchange.com/questions/91913/ …
Andrew Henle

20

นี่คือสคริปต์ที่ฉันใช้บนกล่องโลคัลเพื่อตั้งค่า SAN (subjectAltName) ในใบรับรองที่ลงนามเอง

สคริปต์นี้ใช้ชื่อโดเมน (example.com) และสร้าง SAN สำหรับ * .example.com และ example.com ในใบรับรองเดียวกัน ส่วนด้านล่างนี้แสดงความคิดเห็น ตั้งชื่อสคริปต์ (เช่นgenerate-ssl.sh) และให้สิทธิ์ในการปฏิบัติการ ไฟล์จะถูกเขียนไปยังไดเรกทอรีเดียวกันกับสคริปต์

Chrome 58 ขึ้นไปกำหนดให้ SAN ต้องตั้งค่าในใบรับรองที่ลงชื่อด้วยตนเอง

#!/usr/bin/env bash

# Set the TLD domain we want to use
BASE_DOMAIN="example.com"

# Days for the cert to live
DAYS=1095

# A blank passphrase
PASSPHRASE=""

# Generated configuration file
CONFIG_FILE="config.txt"

cat > $CONFIG_FILE <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = CA
ST = BC
L = Vancouver
O = Example Corp
OU = Testing Domain
emailAddress = webmaster@$BASE_DOMAIN
CN = $BASE_DOMAIN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.$BASE_DOMAIN
DNS.2 = $BASE_DOMAIN
EOF

# The file name can be anything
FILE_NAME="$BASE_DOMAIN"

# Remove previous keys
echo "Removing existing certs like $FILE_NAME.*"
chmod 770 $FILE_NAME.*
rm $FILE_NAME.*

echo "Generating certs for $BASE_DOMAIN"

# Generate our Private Key, CSR and Certificate
# Use SHA-2 as SHA-1 is unsupported from Jan 1, 2017

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout "$FILE_NAME.key" -days $DAYS -out "$FILE_NAME.crt" -passin pass:$PASSPHRASE -config "$CONFIG_FILE"

# OPTIONAL - write an info to see the details of the generated crt
openssl x509 -noout -fingerprint -text < "$FILE_NAME.crt" > "$FILE_NAME.info"

# Protect the key
chmod 400 "$FILE_NAME.key"

สคริปต์นี้ยังเขียนไฟล์ข้อมูลเพื่อให้คุณสามารถตรวจสอบใบรับรองใหม่และตรวจสอบว่า SAN ได้รับการตั้งค่าอย่างเหมาะสม

                ...
                28:dd:b8:1e:34:b5:b1:44:1a:60:6d:e3:3c:5a:c4:
                da:3d
            Exponent: 65537 (0x10001)
    X509v3 extensions:
        X509v3 Subject Alternative Name: 
            DNS:*.example.com, DNS:example.com
Signature Algorithm: sha256WithRSAEncryption
     3b:35:5a:d6:9e:92:4f:fc:f4:f4:87:78:cd:c7:8d:cd:8c:cc:
     ...

หากคุณใช้ Apache คุณสามารถอ้างอิงใบรับรองด้านบนในไฟล์กำหนดค่าดังนี้:

<VirtualHost _default_:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/htdocs

    SSLEngine on
    SSLCertificateFile path/to/your/example.com.crt
    SSLCertificateKeyFile path/to/your/example.com.key
</VirtualHost>

อย่าลืมรีสตาร์ทเซิร์ฟเวอร์ Apache (หรือ Nginx หรือ IIS) เพื่อให้ใบรับรองใหม่มีผล


ใช้งานได้กับ macOS High Siera และ Chrome 58
Saqib Omer

ฉันยังไม่แน่ใจว่า CN มีผลต่อการตั้งค่าโดยรวมอย่างไร ฉันพยายามที่จะเรียกใช้สิ่งนี้localhostหรือ127.0.0.1:port#สิ่งที่สอดคล้องกันCNสำหรับสิ่งนี้
DJ2

@ DJ2 ฉันจะตั้ง BASE_DOMAIN =“ localhost”
Drakes

9

2017 หนึ่งซับ:

openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout server.pem \
-new \
-out server.pem \
-subj /CN=localhost \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
    <(printf '[SAN]\nsubjectAltName=DNS:localhost')) \
-sha256 \
-days 3650

ยังใช้งานได้ใน Chrome 57 ซึ่งให้ SAN โดยไม่ต้องมีไฟล์กำหนดค่าอื่น มันถูกนำมาจากคำตอบที่นี่

สิ่งนี้จะสร้างไฟล์. pem ไฟล์เดียวที่มีทั้งไพรเวตคีย์และใบรับรอง คุณสามารถย้ายไฟล์เหล่านี้ไปยังไฟล์. pem แยกกันได้หากต้องการ


2
สำหรับผู้ใช้ Linux คุณจะต้องเปลี่ยนเส้นทางนั้นสำหรับการกำหนดค่า เช่นในปัจจุบันอูบุนตู/etc/ssl/openssl.confทำงาน
วิภัตติ

สำหรับสายการบินหนึ่งที่ไม่ต้องการให้คุณระบุตำแหน่ง openssl.cnf ให้ดูที่: stackoverflow.com/a/41366949/19163
vog

7

ฉันไม่สามารถแสดงความคิดเห็นได้ดังนั้นฉันจึงเพิ่มคำตอบแยกต่างหาก ฉันพยายามสร้างใบรับรองแบบลงนามด้วยตนเองสำหรับ NGINX และมันง่าย แต่เมื่อฉันต้องการเพิ่มลงในรายการสีขาวของ Chrome ฉันมีปัญหา และทางออกของฉันคือการสร้างใบรับรองหลักและลงนามใบรับรองลูกโดยมัน

ดังนั้นทีละขั้นตอน สร้างไฟล์config_ssl_ca.cnf โปรดสังเกตว่าไฟล์กำหนดค่ามีตัวเลือกbasicConstraints = CA: จริงซึ่งหมายความว่าใบรับรองนี้ควรจะเป็นรูท

นี่เป็นวิธีปฏิบัติที่ดีเพราะคุณสร้างขึ้นเพียงครั้งเดียวและสามารถนำมาใช้ซ้ำได้

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=root region
localityName=root city
organizationName=root organisation
organizationalUnitName=roote department
commonName=root
emailAddress=root_email@root.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:true
subjectKeyIdentifier = hash
subjectAltName = @alternate_names

ไฟล์กำหนดค่าถัดไปสำหรับใบรับรองย่อยของคุณ

[ req ]
default_bits = 2048

prompt = no
distinguished_name=req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName=UA
stateOrProvinceName=Kyiv region
localityName=Kyiv
organizationName=market place
organizationalUnitName=market place department
commonName=FirstName LastName
emailAddress=email@market.localhost

[ alternate_names ]
DNS.1        = market.localhost
DNS.2        = www.market.localhost
DNS.3        = mail.market.localhost
DNS.4        = ftp.market.localhost

[ v3_req ]
keyUsage=digitalSignature
basicConstraints=CA:false
subjectAltName = @alternate_names
subjectKeyIdentifier = hash

ขั้นตอนแรก - สร้างรูทคีย์และใบรับรอง

openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt -days 365 -config config_ssl_ca.cnf

ขั้นตอนที่สองสร้างคีย์ย่อยและไฟล์ CSR - คำขอลงนามใบรับรอง เพราะความคิดคือการลงนามใบรับรองเด็กโดยรูทและได้รับใบรับรองที่ถูกต้อง

openssl genrsa -out market.key 2048
openssl req -new -sha256 -key market.key -config config_ssl.cnf -out market.csr

เปิดเทอร์มินัล Linux แล้วทำตามคำสั่ง echo 0

echo 1 > ca.srl
touch index.txt

ca.srlแฟ้มข้อความที่มีหมายเลขซีเรียต่อไปที่จะใช้ในฐานสิบหก จำเป็น ไฟล์นี้จะต้องมีอยู่และมีหมายเลขซีเรียลที่ถูกต้อง

ขั้นตอนสุดท้ายสร้างไฟล์ปรับแต่งอีกหนึ่งไฟล์แล้วเรียกมันว่าconfig_ca.cnf

# we use 'ca' as the default section because we're usign the ca command
[ ca ]
default_ca = my_ca

[ my_ca ]
#  a text file containing the next serial number to use in hex. Mandatory.
#  This file must be present and contain a valid serial number.
serial = ./ca.srl

# the text database file to use. Mandatory. This file must be present though
# initially it will be empty.
database = ./index.txt

# specifies the directory where new certificates will be placed. Mandatory.
new_certs_dir = ./

# the file containing the CA certificate. Mandatory
certificate = ./ca.crt

# the file contaning the CA private key. Mandatory
private_key = ./ca.key

# the message digest algorithm. Remember to not use MD5
default_md = sha256

# for how many days will the signed certificate be valid
default_days = 365

# a section with a set of variables corresponding to DN fields
policy = my_policy

# MOST IMPORTANT PART OF THIS CONFIG
copy_extensions = copy

[ my_policy ]
# if the value is "match" then the field value must match the same field in the
# CA certificate. If the value is "supplied" then it must be present.
# Optional means it may be present. Any fields not mentioned are silently
# deleted.
countryName = match
stateOrProvinceName = supplied
organizationName = supplied
commonName = supplied
organizationalUnitName = optional
commonName = supplied

คุณอาจถามว่าทำไมยากมากทำไมเราต้องสร้างอีกหนึ่งการกำหนดค่าเพื่อลงนามใบรับรองลูกโดยรูท คำตอบนั้นง่ายเพราะใบรับรองลูกจะต้องมีบล็อก SAN - ชื่อทางเลือกของหัวเรื่อง หากเราเซ็นชื่อในใบรับรองย่อยโดย utils "openssl x509" ใบรับรองหลักจะลบฟิลด์ SAN ในใบรับรองรอง ดังนั้นเราจึงใช้ "openssl ca" แทน "openssl x509" เพื่อหลีกเลี่ยงการลบฟิลด์ SAN เราสร้างไฟล์ config ใหม่และบอกให้คัดลอกทุกสาขาขยายcopy_extensions = สำเนา

openssl ca -config config_ca.cnf -out market.crt -in market.csr

โปรแกรมถามคำถามคุณ 2 ข้อ: 1. ลงชื่อใบรับรอง? พูดว่า "Y" 2. ได้รับการรับรองคำขอ 1 จาก 1 ใบรับรองยอมรับหรือไม่ พูดว่า "Y"

ในเทอร์มินัลคุณสามารถเห็นประโยคที่มีคำว่า "ฐานข้อมูล" หมายถึงไฟล์ index.txt ที่คุณสร้างโดยคำสั่ง "สัมผัส" มันจะมีข้อมูลทั้งหมดโดยใบรับรองทั้งหมดที่คุณสร้างโดยใช้ "openssl ca" util วิธีตรวจสอบใบรับรองใช้อย่างถูกต้อง:

openssl rsa -in market.key -check

หากคุณต้องการที่จะเห็นสิ่งที่อยู่ใน CRT:

openssl x509 -in market.crt -text -noout

หากคุณต้องการดูว่ามีอะไรอยู่ใน CSR:

openssl req -in market.csr -noout -text 

2
แม้ว่ากระบวนการนี้จะดูซับซ้อน แต่นี่เป็นสิ่งที่เราต้องการสำหรับโดเมน. dev เนื่องจากโดเมนนี้ไม่รองรับใบรับรองที่ลงชื่อด้วยตนเองและ Chrome และ Firefox กำลังบังคับใช้ HSTS สิ่งที่ฉันทำคือทำตามขั้นตอนนี้ซึ่งกำลังสร้าง CA สร้างใบรับรองและเซ็นชื่อกับ CA ของฉันและในตอนท้ายเชื่อใจ CA ของฉันในเบราว์เซอร์ ขอบคุณ
bajicdusko

1
คุณเป็นตำนานครับ บ้านเกิดของฉันขอบคุณ!
antsyawn

6

คุณมีขั้นตอนทั่วไปที่ถูกต้อง ไวยากรณ์สำหรับคำสั่งอยู่ด้านล่าง

openssl req -new -key {private key file} -out {output file}

อย่างไรก็ตามคำเตือนจะปรากฏขึ้นเนื่องจากเบราว์เซอร์ไม่สามารถยืนยันตัวตนได้โดยตรวจสอบความถูกต้องของใบรับรองด้วย Certificate Authority (CA) ที่เป็นที่รู้จัก

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

  1. สร้างรหัสส่วนตัว
  2. ใช้ไพรเวตคีย์นั้นเพื่อสร้างไฟล์ CSR
  3. ส่ง CSR ไปที่ CA (Verisign หรืออื่น ๆ )
  4. ติดตั้งได้รับใบรับรองจาก CA บนเว็บเซิร์ฟเวอร์
  5. เพิ่มใบรับรองอื่น ๆ ลงในห่วงโซ่การตรวจสอบความถูกต้องขึ้นอยู่กับประเภทใบรับรอง

ฉันมีรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ในโพสต์ที่การรักษาความปลอดภัยการเชื่อมต่อ: การสร้างใบรับรองความปลอดภัยด้วย OpenSSL


6

ซับหนึ่ง FTW ฉันชอบที่จะทำให้มันง่าย ทำไมไม่ใช้คำสั่งเดียวที่มีข้อโต้แย้งทั้งหมดที่จำเป็น? นี่คือวิธีที่ฉันชอบ - นี่สร้างใบรับรอง x509 และรหัส PEM:

openssl req -x509 \
 -nodes -days 365 -newkey rsa:4096 \
 -keyout self.key.pem \
 -out self-x509.crt \
 -subj "/C=US/ST=WA/L=Seattle/CN=example.com/emailAddress=someEmail@gmail.com"

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

>> เพิ่มเติมได้ที่นี่ <<


1
ข้อโต้แย้งทั้งหมดยกเว้นคำตอบของ SAN ... @ vog ครอบคลุมเช่นกัน (และลงวันที่ก่อนหน้านี้) (นี่มีฟิลด์ "เรื่อง" ที่สมบูรณ์ยิ่งขึ้นซึ่งกรอกในแม้ว่า ... ) (ไม่ใช่แฟนตัวยงของการหมดอายุหนึ่งปีเช่นกัน)
Gert van den Berg

6

รุ่นหนึ่งซับ 2017:

CentOS:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

อูบุนตู:

openssl req -x509 -nodes -sha256 -newkey rsa:2048 \
-keyout localhost.key -out localhost.crt \
-days 3650 \
-subj "/CN=localhost" \
-reqexts SAN -extensions SAN \
-config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=IP:127.0.0.1,DNS:localhost"))

แก้ไข: เพิ่มตัวเลือกเสริม Slash ไปที่ 'subj' สำหรับ Ubuntu


3

สร้างคีย์

ฉันใช้/etc/mysqlสำหรับการจัดเก็บใบรับรองเพราะมี/etc/apparmor.d/usr.sbin.mysqld/etc/mysql/*.pem r

sudo su -
cd /etc/mysql
openssl genrsa -out ca-key.pem 2048;
openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem -out server-req.pem;
openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem;
openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem -out client-req.pem;
openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem;

เพิ่มการกำหนดค่า

/etc/mysql/my.cnf

[client]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/client-cert.pem
ssl-key=/etc/mysql/client-key.pem

[mysqld]
ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

ในการตั้งค่าของฉันเซิร์ฟเวอร์ Ubuntu เข้าสู่: /var/log/mysql/error.log

หมายเหตุการติดตาม:

  • SSL error: Unable to get certificate from '...'

    MySQL อาจจะปฏิเสธการเข้าถึงแบบอ่านไปยังแฟ้มใบรับรองของคุณถ้ามันไม่ได้อยู่ในการกำหนดค่า ดังที่กล่าวไว้ในขั้นตอนก่อนหน้า ^ ให้บันทึกใบรับรองทั้งหมดของเราเป็น.pemไฟล์ใน/etc/mysql/ไดเรกทอรีซึ่งได้รับการอนุมัติโดยค่าเริ่มต้นโดย apparmor (หรือแก้ไข apparmor / SELinux ของคุณเพื่ออนุญาตการเข้าถึงทุกที่ที่คุณเก็บไว้)

  • SSL error: Unable to get private key

    รุ่นเซิร์ฟเวอร์ MySQL ของคุณอาจไม่รองรับrsa:2048รูปแบบเริ่มต้น

    สร้างการแปลงrsa:2048เป็นธรรมดาrsaด้วย:

    openssl rsa -in server-key.pem -out server-key.pem
    openssl rsa -in client-key.pem -out client-key.pem
    
  • ตรวจสอบว่าเซิร์ฟเวอร์ท้องถิ่นรองรับ SSL :

    mysql -u root -p
    mysql> show variables like "%ssl%";
    +---------------+----------------------------+
    | Variable_name | Value                      |
    +---------------+----------------------------+
    | have_openssl  | YES                        |
    | have_ssl      | YES                        |
    | ssl_ca        | /etc/mysql/ca-cert.pem     |
    | ssl_capath    |                            |
    | ssl_cert      | /etc/mysql/server-cert.pem |
    | ssl_cipher    |                            |
    | ssl_key       | /etc/mysql/server-key.pem  |
    +---------------+----------------------------+
    
  • การตรวจสอบการเชื่อมต่อกับฐานข้อมูลนั้นเป็นการเข้ารหัส SSL :

    กำลังตรวจสอบการเชื่อมต่อ

    เมื่อเข้าสู่ระบบอินสแตนซ์ MySQL คุณสามารถออกแบบสอบถาม:

    show status like 'Ssl_cipher';
    

    หากการเชื่อมต่อของคุณไม่ได้เข้ารหัสผลลัพธ์จะว่างเปล่า:

    mysql> show status like 'Ssl_cipher';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | Ssl_cipher    |       |
    +---------------+-------+
    1 row in set (0.00 sec)
    

    มิฉะนั้นจะแสดงสตริงที่มีความยาวไม่เป็นศูนย์สำหรับ Cypher ที่ใช้งาน:

    mysql> show status like 'Ssl_cipher';
    +---------------+--------------------+
    | Variable_name | Value              |
    +---------------+--------------------+
    | Ssl_cipher    | DHE-RSA-AES256-SHA |
    +---------------+--------------------+
    1 row in set (0.00 sec)
    
  • ต้องการ ssl สำหรับการเชื่อมต่อของผู้ใช้เฉพาะ ('require ssl'):

    • SSL

    บอกให้เซิร์ฟเวอร์อนุญาตเฉพาะการเชื่อมต่อที่เข้ารหัส SSL สำหรับบัญชี

    GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
      REQUIRE SSL;
    

    ในการเชื่อมต่อไคลเอ็นต์จะต้องระบุตัวเลือก --ssl-ca เพื่อตรวจสอบสิทธิ์ใบรับรองเซิร์ฟเวอร์และอาจระบุตัวเลือก --ssl-key และ --ssl-cert เพิ่มเติม หากไม่ได้ระบุอ็อพชัน --ssl-ca หรือ --ssl-capath ไคลเอ็นต์จะไม่ตรวจสอบความถูกต้องใบรับรองเซิร์ฟเวอร์


ลิงค์สำรอง: กวดวิชายาวในการเชื่อมต่อที่ปลอดภัย PHP กับ MySQL ด้วย SSL


-1; นี่เป็นคำถามที่ถามกันบ่อยๆและยังทำงานได้ไม่ดีในการทำให้ชัดเจนว่าคำพูดมาจากไหน
Mark Amery

สิ่งนี้แสดงการจัดเตรียม CA, เซิร์ฟเวอร์ / ไคลเอ็นต์ certs ที่ลงชื่อโดย CA กำหนดค่าให้อ่านโดย mysqld บนโฮสต์ที่มี apparmor มันเป็นตัวอย่างกรณีที่ค่อนข้างไร้ประโยชน์ของการโฮสต์ ca, เซิร์ฟเวอร์และไคลเอนต์ในเครื่องเดียวกันและอันตรายเปิดเผยอำนาจของ ca ที่กระบวนการ mysqld การตั้งค่านี้ไม่สมเหตุสมผลเลยนอกจากการทดสอบการกำหนดค่า ssl ในสภาพแวดล้อมการทดสอบ สำหรับการใช้งาน CA ภายในฉันจะแนะนำ gnuttls toolchain บน openssl help.ubuntu.com/community/GnuTLSและมีความเข้าใจที่ดีเกี่ยวกับ tls ก่อนที่จะทำงานกับกรณี mysqld + apparmor
ThorSummoner

3

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

เหตุผลหลักหนึ่งไม่ต้องการที่จะได้รับการลงนามในใบรับรองจากผู้ออกใบรับรองเป็นค่าใช้จ่าย - ค่าใช้จ่ายที่ไซแมนเทคระหว่าง $ 995 - $ 1,999 ต่อปีสำหรับใบรับรอง - เพียงแค่สำหรับใบรับรองไว้สำหรับเครือข่ายภายในไซแมนเทคค่าใช้จ่าย $ 399 ต่อปี ค่าใช้จ่ายนั้นง่ายต่อการพิสูจน์ว่าคุณกำลังประมวลผลการชำระเงินด้วยบัตรเครดิตหรือทำงานให้กับศูนย์กำไรของ บริษัท ที่ทำกำไรได้สูง เป็นมากกว่าที่หลาย ๆ คนสามารถจ่ายได้สำหรับโครงการส่วนบุคคลที่สร้างบนอินเทอร์เน็ตหรือสำหรับองค์กรที่ไม่แสวงหาผลกำไรที่ใช้งบประมาณน้อยหรือหากทำงานในศูนย์ต้นทุนขององค์กร - ศูนย์ต้นทุนพยายามทำมากกว่า มีน้อย

อีกทางเลือกหนึ่งคือใช้certbot (ดูเกี่ยวกับ certbot ) Certbot เป็นไคลเอนต์อัตโนมัติที่ใช้งานง่ายที่ดึงและปรับใช้ใบรับรอง SSL / TLS สำหรับเว็บเซิร์ฟเวอร์ของคุณ

หากคุณตั้งค่า certbot คุณสามารถเปิดใช้งานเพื่อสร้างและรักษาใบรับรองสำหรับคุณที่ออกโดยหน่วยงานออกใบรับรองLet's Encrypt

ฉันทำสิ่งนี้ในช่วงสุดสัปดาห์สำหรับองค์กรของฉัน ฉันติดตั้งแพคเกจที่จำเป็นสำหรับ certbot บนเซิร์ฟเวอร์ของฉัน (Ubuntu 16.04) จากนั้นเรียกใช้คำสั่งที่จำเป็นในการตั้งค่าและเปิดใช้งาน certbot อาจมีความต้องการปลั๊กอิน DNSสำหรับ certbot - ขณะนี้เรากำลังใช้DigitalOceanแม้ว่าอาจกำลังย้ายไปยังบริการอื่นในไม่ช้า

โปรดทราบว่าคำแนะนำบางอย่างไม่ถูกต้องนักและใช้เวลาเล็กน้อยกับ Google ในการคิด นี่ใช้เวลาพอสมควรในครั้งแรก แต่ตอนนี้ฉันคิดว่าฉันสามารถทำได้ในไม่กี่นาที

สำหรับ DigitalOcean สิ่งหนึ่งที่ฉันพยายามคือเมื่อฉันได้รับแจ้งให้ป้อนเส้นทางไปยังไฟล์ข้อมูลประจำตัว DigitalOcean ของคุณ INI สิ่งที่สคริปต์อ้างถึงคือหน้าแอปพลิเคชัน & APIและแท็บโทเค็น / คีย์ในหน้านั้น คุณต้องมีหรือสร้างโทเค็นการเข้าถึงส่วนบุคคล (อ่านและเขียน) สำหรับ API ของ DigitalOcean - นี่คือสตริงเลขฐานสิบหก 65 ตัวอักษร สตริงนี้จะต้องใส่ลงในไฟล์บนเว็บเซิร์ฟเวอร์ที่คุณใช้ certbot ไฟล์นั้นสามารถมีความคิดเห็นเป็นบรรทัดแรก (ความคิดเห็นเริ่มต้นด้วย #) บรรทัด seccond คือ:

dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff

เมื่อฉันคิดออกวิธีการตั้งค่าการอ่าน + เขียน token สำหรับ DigitalOcean API ของมันก็สวยง่ายต่อการใช้งาน certbot การติดตั้งใบรับรองสัญลักษณ์แทน โปรดทราบว่าไม่มีการตั้งค่าใบรับรองไวด์การ์ดหนึ่งอาจแทนแต่ละโดเมนและโดเมนย่อยที่ต้องการให้ใช้ใบรับรองแทน มันเป็นใบรับรองไวด์การ์ดที่จำเป็นต้องใช้ไฟล์ข้อมูลรับรอง INI ที่มีโทเค็นการเข้าถึงส่วนบุคคลจาก DigitalOcean

โปรดทราบว่าใบรับรองกุญแจสาธารณะ (หรือที่เรียกว่าใบรับรองตัวตนหรือใบรับรอง SSL) หมดอายุและจำเป็นต้องมีการต่ออายุ ดังนั้นคุณจะต้องต่ออายุใบรับรองของคุณตามระยะเวลา (ซ้ำ) เอกสาร certbot ครอบคลุมการต่ออายุใบรับรอง

แผนของฉันคือการเขียนสคริปต์เพื่อใช้คำสั่ง openssl เพื่อรับวันหมดอายุใบรับรองของฉันและเพื่อกระตุ้นการต่ออายุเมื่อเป็น 30 วันหรือน้อยกว่าจนกว่าจะหมดอายุ ฉันจะเพิ่มสคริปต์นี้ลงใน cron และเรียกใช้งานวันละครั้ง

นี่คือคำสั่งให้อ่านวันหมดอายุของใบรับรองของคุณ:

root@prod-host:~# /usr/bin/openssl x509 -enddate -noout -in path-to-certificate-pem-file
notAfter=May 25 19:24:12 2019 GMT
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.