Tạo chứng chỉ tự ký với openssl hoạt động trong Chrome 58


52

Kể từ Chrome 58, nó không còn chấp nhận các certs tự ký mà dựa vào Common Name: https://productforums.google.com/forum/#!topic/chrome/zVo3M8CgKzQ;context-place=topicsearchin/chrom/c Category $ 3ACanary% 7Csort: mức độ liên quan% 7Cspell: sai

Thay vào đó, nó đòi hỏi phải sử dụng Subject Alt Name. Trước đây tôi đã làm theo hướng dẫn này về cách tạo chứng chỉ tự ký: https://devcenter.heroku.com/articles/ssl-cert ve- chính nó hoạt động rất tốt vì tôi yêu cầu server.crtserver.keycác tệp cho những gì tôi đang làm. Bây giờ tôi cần tạo các certs mới bao gồm SANtuy nhiên tất cả những nỗ lực của tôi để làm như vậy không hoạt động với Chrome 58.

Đây là những gì tôi đã làm:

Tôi đã làm theo các bước trên bài viết Heroku đã đề cập ở trên để tạo khóa. Sau đó tôi đã viết một tệp cấu hình OpenSSL mới:

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = san
extensions          = san
[ req_distinguished_name ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

Sau đó tạo server.crtlệnh bằng lệnh sau:

openssl req \
-new \
-key server.key \
-out server.csr \
-config config.cnf \
-sha256 \
-days 3650

Tôi đang dùng Mac, vì vậy tôi đã mở server.crttệp bằng Keychain, thêm nó vào Chứng chỉ hệ thống của mình. Sau đó tôi đặt nó thành Always Trust.

Ngoại trừ tệp cấu hình để đặt giá trị SAN, đây là các bước tương tự tôi đã sử dụng trong các phiên bản trước của Chrome để tạo và tin tưởng vào chứng chỉ tự ký.

Tuy nhiên, sau này tôi vẫn nhận được ERR_CERT_COMMON_NAME_INVALIDtrong Chrome 58.

Câu trả lời:


62

Giải pháp của tôi:

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

Tình trạng: Làm việc cho tôi


2
sử dụng tuyệt vời của subshell. Tôi nghĩ bạn có thể đơn giản hóa nó một chút:-config <(cat /System/Library/OpenSSL/openssl.cnf ; printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')
jrwren

1
Tôi không còn gặp phải lỗi Tên chủ đề, nhưng bây giờ tôi gặp lỗi về tên chung và đặt chứng chỉ đã tải xuống thành "luôn tin tưởng" không hoạt động. Có suy nghĩ gì không? @bcardarella
rugbert

2
Với bản cập nhật cho Chrome 59, chứng chỉ hiển thị một lỗi như thế này: Có vấn đề với chuỗi chứng chỉ của trang web (net :: ERR_CERT_COMMON_NAME_INVALID).
theHarsh

1
Tôi đã thay đổi dev.company.nameđến localhostvà điều này đã làm việc phục vụ cho khu vực phát triển địa phương từ localhost. Trên macOS, tôi cũng phải thêm chứng chỉ vào Keychain và đặt SSL thành "Luôn tin tưởng".
Daniel M.

1
Đó là giải pháp đơn giản nhất và không yêu cầu bắt vít với sslconf hoặc cài đặt CA.
bp.

16

Trong Windows, lưu tập lệnh này trong thư mục SSL của bạn dưới dạng makeCERT.bat. Nó sẽ tạo ra các tập tin này: example.cnf, example.crt, example.key

@echo off

REM IN YOUR SSL FOLDER, SAVE THIS FILE AS: makeCERT.bat
REM AT COMMAND LINE IN YOUR SSL FOLDER, RUN: makecert
REM IT WILL CREATE THESE FILES: example.cnf, example.crt, example.key
REM IMPORT THE .crt FILE INTO CHROME Trusted Root Certification Authorities
REM REMEMBER TO RESTART APACHE OR NGINX AFTER YOU CONFIGURE FOR THESE FILES

REM PLEASE UPDATE THE FOLLOWING VARIABLES FOR YOUR NEEDS.
SET HOSTNAME=example
SET DOT=com
SET COUNTRY=US
SET STATE=KS
SET CITY=Olathe
SET ORGANIZATION=IT
SET ORGANIZATION_UNIT=IT Department
SET EMAIL=webmaster@%HOSTNAME%.%DOT%

(
echo [req]
echo default_bits = 2048
echo prompt = no
echo default_md = sha256
echo x509_extensions = v3_req
echo distinguished_name = dn
echo:
echo [dn]
echo C = %COUNTRY%
echo ST = %STATE%
echo L = %CITY%
echo O = %ORGANIZATION%
echo OU = %ORGANIZATION_UNIT%
echo emailAddress = %EMAIL%
echo CN = %HOSTNAME%.%DOT%
echo:
echo [v3_req]
echo subjectAltName = @alt_names
echo:
echo [alt_names]
echo DNS.1 = *.%HOSTNAME%.%DOT%
echo DNS.2 = %HOSTNAME%.%DOT%
)>%HOSTNAME%.cnf

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout %HOSTNAME%.key -days 3560 -out %HOSTNAME%.crt -config %HOSTNAME%.cnf

13

Đây là một giải pháp phù hợp với tôi:

Tạo khóa CA và chứng chỉ

# openssl genrsa -out server_rootCA.key 2048
# openssl req -x509 -new -nodes -key server_rootCA.key -sha256 -days 3650 -out server_rootCA.pem

Tạo server_rootCA.csr.cnf

# server_rootCA.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=DE
ST=Berlin
L=NeuKoelln
O=Weisestrasse
OU=local_RootCA
emailAddress=ikke@server.berlin
CN = server.berlin

Tạo tập tin cấu hình v3.ext

# v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = server.berlin

Tạo khóa máy chủ

# openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server_rootCA.csr.cnf )

Tạo chứng chỉ máy chủ

# openssl x509 -req -in server.csr -CA server_rootCA.pem -CAkey server_rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile v3.ext

Thêm chứng chỉ và khóa vào tệp trang web Apache2, phần HTTPS (cổng 443)

SSLCertificateFile    /etc/apache2/ssl/server.crt
SSLCertificateKeyFile    /etc/apache2/ssl/server.key

Sao chép server_rootCA.pem từ máy chủ vào máy của bạn ..

# scp you@server.berlin:~/server_rootCA.pem .

.. và thêm nó vào trình duyệt Chromium

Chromium -> Setting -> (Advanced) Manage Certificates -> Import -> 'server_rootCA.pem'

BẠN ĐÃ LÀM XONG!

PS Thay vì tạo cặp chứng chỉ CA & máy chủ chức năng (theo hướng dẫn ở trên), bạn có thể chỉ cần vô hiệu hóa các tiêu đề HSTS trong cấu hình máy chủ HTTP của mình. Điều này sẽ ngăn Chromium thực thi HTTPS và sẽ cho phép người dùng nhấp vào Nâng cao → tiến tới your.url (không an toàn) mà không cần phải lấy và cài đặt chứng chỉ CA (server_rootCA.pem) tùy chỉnh của bạn. Nói cách khác - việc phải vô hiệu hóa HSTS sẽ cho phép trang web của bạn được xem công khai qua HTTP và / hoặc kết nối HTTPS không an toàn (hãy cẩn thận!).

Đối với Apache2, hãy thêm phần sau vào tệp trang web, phần HTTP (cổng 80)

Header unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=0;includeSubDomains"

Đã thử nghiệm trên Debian / Apache2.4 + Debian / Chromium 59

https://ram.k0a1a.net/elf-sign_https_cert_after_chrome_58


Đi theo con đường của một cơ quan CA gốc mà sau đó ký các certs riêng lẻ là cách duy nhất mà tôi có thể nhận được chrome để xác thực hoàn toàn; cũng có lợi thế là tôi chỉ cần mọi người cài đặt một chứng chỉ duy nhất. Cảm ơn
geoff

4
Ai đó có thể vui lòng giải thích cho tôi tại sao tất cả mọi người trong khu vực này dường như sử dụng bashism như -config <( cat server_rootCA.csr.cnf )thay vì chỉ -config server_rootCA.csr.cnf?
Caesar

bạn có thể vui lòng cập nhật câu trả lời của mình liên quan đến các tiêu đề apache có thể bỏ qua vấn đề này không Bạn có thể chỉ ra nơi bên trong một máy chủ ảo định nghĩa những thứ này sẽ đi. Tôi đã thử một vài lựa chọn thay thế và vẫn không thể truy cập trang web thorugh https. Cảm ơn
Nikos M.

12

Có một số câu trả lời tuyệt vời đưa ra ví dụ về cách làm cho điều này hoạt động, nhưng không có câu trả lời nào giải thích được sự cố xảy ra trong nỗ lực của bạn. OpenSSL có thể khá không trực quan một số lần vì vậy nó đáng để đi qua.

Đầu tiên, như một bên, OpenSSL mặc định bỏ qua mọi giá trị tên phân biệt mà bạn cung cấp trong cấu hình. Nếu bạn muốn sử dụng chúng, bạn phải thêm prompt = no vào cấu hình của bạn. Ngoài ra, lệnh như được viết chỉ tạo ra một yêu cầu chứng chỉ chứ không phải chính chứng chỉ, vì vậy -dayslệnh không làm gì cả.

Nếu bạn tạo yêu cầu chứng chỉ của mình bằng lệnh này, bạn đã đưa ra và kiểm tra kết quả, Tên Alt chủ đề sẽ xuất hiện:

$ openssl req -new -key server.key -out server.csr -config config.cnf -sha256
$ openssl req -text -noout -in server.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name:
                DNS:dev.mycompany.com
    Signature Algorithm: sha256WithRSAEncryption
         ...

Nhưng sau đó nếu bạn tạo chứng chỉ bằng lệnh trong liên kết heroku và kiểm tra kết quả, Tên Alt của chủ đề bị thiếu:

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
$ openssl x509 -text -noout -in server.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            89:fd:75:26:43:08:04:61
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Validity
            Not Before: Jan 21 04:27:21 2018 GMT
            Not After : Jan 21 04:27:21 2019 GMT
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         ...

Lý do là theo mặc định OpenSSL không sao chép các phần mở rộng từ yêu cầu sang chứng chỉ. Thông thường, chứng chỉ sẽ được tạo / ký bởi CA dựa trên yêu cầu từ khách hàng và một số tiện ích mở rộng có thể cấp cho chứng chỉ nhiều quyền lực hơn CA dự định nếu họ tin tưởng một cách mù quáng vào các tiện ích mở rộng được xác định trong yêu cầu.

Có nhiều cách để yêu cầu OpenSSL sao chép các phần mở rộng, nhưng IMHO nó hoạt động nhiều hơn là chỉ cung cấp các phần mở rộng trong tệp cấu hình khi bạn tạo chứng chỉ.

Nếu bạn đã cố gắng sử dụng tệp cấu hình hiện tại của mình, nó sẽ không hoạt động vì phần cấp cao nhất được đánh dấu [req]để các cài đặt đó chỉ áp dụng cho lệnh req chứ không phải lệnh x509. Không cần thiết phải có điểm đánh dấu phần cấp cao nhất, vì vậy bạn chỉ cần xóa dòng đầu tiên đó và sau đó nó sẽ hoạt động tốt cho cả việc tạo yêu cầu hoặc chứng chỉ.

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt -extfile config.cnf

Thay phiên, bạn có thể sử dụng -x509đối số cho reqlệnh để tạo chứng chỉ tự ký trong một lệnh, thay vì trước tiên tạo yêu cầu và sau đó là chứng chỉ. Trong trường hợp này, không cần thiết phải loại bỏ [req]dòng phần, vì phần đó được đọc và sử dụng bởi lệnh req.

$ openssl req -x509 -sha256 -days 365 -key server.key -out server.crt -config config.cnf

Tóm lại, đây là tập tin cấu hình đã sửa đổi được sử dụng trong các lệnh trên:

default_bits        = 2048
distinguished_name  = dn
x509_extensions     = san
req_extensions      = san
extensions          = san
prompt              = no
[ dn ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

2
Đây là lời giải thích duy nhất giúp tôi hiểu lý do tại sao chứng chỉ xuất hiện mà không có SAN (trong trường hợp của tôi, tôi cần đưa x509_extensions vào tệp cấu hình)
Daniel Beardsmore

2

Giải pháp của tôi là giữ nguyên phần chính openssl.cnfvà cuối cùng là thêm một phần mới như [ cert_www.example.com ]www.example.com là trang web mà tôi muốn tạo chứng chỉ, và trong đó, hãy đặt phần subjectAltNametôi cần (và còn gì nữa không). Tất nhiên phần có thể được đặt tên bất cứ điều gì bạn muốn.

Sau đó, tôi có thể chạy openssl reqlệnh như trước đây, chỉ cần thêm -extensions cert_www.example.comnội dung của nó sẽ được chọn và tôi thêm -subjđể thêm trực tiếp tất cả thông tin DN.

Đừng quên xác minh nội dung chứng chỉ sau khi tạo và trước khi sử dụng, với openssl x509 -text


1

Bash script với config nướng trong

Là một kịch bản shell nên hoạt động trên các nền tảng với bash. Giả sử HOSTNAMEenv được đặt cho trình bao hoặc cung cấp tên máy chủ bạn chọn, ví dụ:self_signed_cert.sh test

set -e

if [ -z "$1" ]; then
  hostname="$HOSTNAME"
else
  hostname="$1"
fi

local_openssl_config="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = san_self_signed
[ req_distinguished_name ]
CN=$hostname
[ san_self_signed ]
subjectAltName = DNS:$hostname, DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign
extendedKeyUsage = serverAuth, clientAuth, timeStamping
"

openssl req \
  -newkey rsa:2048 -nodes \
  -keyout "$hostname.key.pem" \
  -x509 -sha256 -days 3650 \
  -config <(echo "$local_openssl_config") \
  -out "$hostname.cert.pem"
openssl x509 -noout -text -in "$hostname.cert.pem"

Nhiều hơn hoặc ít hơn các nhu cầu thông tin tập tin cấu hình tối thiểu trần mở.

Lưu ý, bao gồm thêm DNS:localhostdưới dạng SAN để cho phép thử nghiệm qua localhost dễ dàng hơn. Xóa bit thừa đó khỏi tập lệnh nếu bạn không muốn.

tín dụng

Câu trả lời của bcardarella là tuyệt vời (không thể bình luận / bỏ phiếu do không đủ đại diện). Tuy nhiên, câu trả lời sử dụng vị trí tệp cấu hình openssl hiện có dành riêng cho nền tảng ... do đó:

Làm việc cho tôi

Rõ ràng, người ta chỉ cần tìm tệp cấu hình openssl cho nền tảng cụ thể của riêng bạn và thay thế vị trí chính xác.

Kiểm tra

Để biết cách kiểm tra, hãy nhập test.cert.pemvào cơ quan có thẩm quyền của chrome chrome://settings/certificatesvà:

openssl s_server -key test.key.pem -cert test.cert.pem -accept 20443 -www &
openssl_pid=$!
google-chrome https://localhost:20443

Và sau khi thử nghiệm

kill $openssl_pid
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.