Membuat sertifikat yang ditandatangani sendiri dengan openssl yang berfungsi di Chrome 58


52

Pada Chrome 58, ia tidak lagi menerima sertifikat yang ditandatangani sendiri yang bergantung pada Common Name: https://productforums.google.com/forum/#!topic/chrome/zVo3M8CgKzQ;context-place=topicsearchin/chrome/category $ 3Atas% 7Csort: relevansi% 7Cspell: false

Sebaliknya itu membutuhkan penggunaan Subject Alt Name. Saya sebelumnya telah mengikuti panduan ini tentang cara membuat sertifikat yang ditandatangani sendiri: https://devcenter.heroku.com/articles/ssl-certificate-self yang bekerja sangat baik karena saya memerlukan server.crtdan server.keyfile untuk apa yang saya lakukan. Saya sekarang perlu membuat sertifikat baru yang mencakup SANnamun semua upaya saya untuk melakukannya belum berfungsi dengan Chrome 58.

Inilah yang telah saya lakukan:

Saya mengikuti langkah-langkah pada artikel Heroku yang disebutkan di atas untuk menghasilkan kunci. Saya kemudian menulis file konfigurasi OpenSSL baru:

[ 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

Kemudian dihasilkan server.crtdengan perintah berikut:

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

Saya menggunakan Mac, jadi saya membuka server.crtfile dengan Keychain, menambahkannya ke Sertifikat Sistem saya. Saya kemudian mengaturnya Always Trust.

Dengan pengecualian file konfigurasi untuk menetapkan nilai SAN, ini adalah langkah-langkah serupa yang saya gunakan di versi Chrome sebelumnya untuk menghasilkan dan memercayai sertifikat yang ditandatangani sendiri.

Namun, setelah ini saya masih mendapatkan ERR_CERT_COMMON_NAME_INVALIDdi Chrome 58.

Jawaban:


62

Solusi saya:

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

Status: Berfungsi untuk saya


2
banyak menggunakan subkulit. Saya pikir Anda dapat menyederhanakannya sedikit:-config <(cat /System/Library/OpenSSL/openssl.cnf ; printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')
jrwren

1
Saya tidak lagi mendapatkan kesalahan Nama Alt Subjek, tetapi sekarang saya mendapatkan kesalahan tentang nama umum, dan mengatur sertifikat yang diunduh ke "selalu percaya" tidak berfungsi. Adakah pikiran? @bcardarella
rugbert

2
Dengan pembaruan ke Chrome 59, sertifikat menunjukkan kesalahan seperti ini: Ada masalah dengan rantai sertifikat situs (net :: ERR_CERT_COMMON_NAME_INVALID).
theHarsh

1
Saya berubah dev.company.namemenjadi localhostdan ini berfungsi untuk melayani situs pengembangan lokal dari localhost. Di macOS saya juga harus menambahkan sertifikat ke Keychain dan mengatur SSL ke "Always Trust".
Daniel M.

1
Sejauh ini solusi paling sederhana dan tidak perlu bermain-main dengan sslconf atau menginstal CA.
bp.

16

Di Windows, simpan skrip ini di folder SSL Anda sebagai makeCERT.bat. Ini akan membuat file-file ini: 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

Ini solusi yang cocok untuk saya:

Buat kunci CA dan sertifikat

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

Buat 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

Buat file konfigurasi v3.ext

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

[alt_names]
DNS.1 = server.berlin

Buat kunci server

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

Buat server cert

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

Tambahkan cert dan kunci ke file situs Apache2, HTTPS (port 443)

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

Salin server_rootCA.pem dari server ke mesin Anda ..

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

.. dan menambahkannya ke browser Chromium

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

ANDA SEMUA DILAKUKAN!

PS Alih-alih membuat CA & server cert pasangan fungsional (sesuai instruksi di atas) Anda cukup menonaktifkan header HSTS di konfigurasi server HTTP Anda. Ini akan mencegah Chromium dari menegakkan HTTPS dan akan memungkinkan pengguna untuk mengeklik "Lanjutan → melanjutkan ke your.url (tidak aman)" tanpa harus mendapatkan dan menginstal sertifikat CA (server_rootCA.pem) khusus Anda. Dengan kata lain - harus menonaktifkan HSTS akan memungkinkan situs Anda dilihat publik melalui HTTP dan / atau koneksi HTTPS tidak aman (waspadalah!).

Untuk Apache2 tambahkan berikut ini ke file situs, HTTP (port 80)

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

Diuji pada Debian / Apache2.4 + Debian / Chromium 59

https://ram.k0a1a.net/self-signed_https_cert_after_chrome_58


Menuju rute otoritas CA root yang kemudian menandatangani sertifikat individu adalah satu-satunya cara saya mendapatkan chrome untuk sepenuhnya mengotentikasi; juga memiliki keuntungan bahwa saya hanya perlu membuat orang memasang satu sertifikat. Terima kasih
geoff

4
Bisakah seseorang tolong jelaskan kepada saya mengapa semua orang di daerah ini tampaknya menggunakan bashism seperti -config <( cat server_rootCA.csr.cnf )bukan -config server_rootCA.csr.cnf?
Caesar

dapatkah Anda memperbarui jawaban Anda yang berkaitan dengan header apache yang dapat mem-bypass masalah ini (saya tidak keberatan ini hanya untuk situs lokal untuk pengembangan dan saya akan mencari solusi generik tanpa harus membuat sertifikat baru setiap kali). Bisakah Anda menunjukkan di mana dalam definisi virtual host ini harus pergi. Saya telah mencoba beberapa alternatif dan masih tidak dapat mengakses situs melalui https. Terima kasih
Nikos M.

12

Ada beberapa jawaban hebat yang memberikan contoh cara agar ini berfungsi, tetapi tidak ada yang menjelaskan di mana ada yang salah dalam upaya Anda. OpenSSL dapat menjadi sangat tidak intuitif beberapa kali sehingga layak untuk dilalui.

Pertama, sebagai tambahan, OpenSSL default untuk mengabaikan nilai-nilai nama berbeda apa pun yang Anda berikan dalam konfigurasi. Jika Anda ingin menggunakannya, Anda harus menambahkan prompt = no ke konfigurasi Anda. Selain itu, perintah yang ditulis hanya menghasilkan permintaan sertifikat, bukan sertifikat itu sendiri, sehingga -daysperintah tidak melakukan apa-apa.

Jika Anda membuat permintaan sertifikat menggunakan perintah yang Anda berikan dan memeriksa hasilnya, Nama Alt Subjek ada:

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

Tetapi jika Anda membuat sertifikat menggunakan perintah di tautan heroku dan memeriksa hasilnya, Nama Alt Subjek tidak ada:

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

Alasannya adalah bahwa secara default OpenSSL tidak menyalin ekstensi dari permintaan ke sertifikat. Biasanya, sertifikat akan dibuat / ditandatangani oleh CA berdasarkan permintaan dari pelanggan, dan beberapa ekstensi dapat memberikan sertifikat lebih banyak kekuatan daripada yang dimaksudkan CA jika mereka mempercayai secara membuta ekstensi yang ditentukan dalam permintaan.

Ada cara untuk memberi tahu OpenSSL untuk menyalin ekstensi, tetapi IMHO itu lebih berfungsi daripada hanya memberikan ekstensi dalam file konfigurasi ketika Anda menghasilkan sertifikat.

Jika Anda mencoba menggunakan file konfigurasi yang ada, itu tidak akan berfungsi karena bagian tingkat atas ditandai [req]sehingga pengaturan itu hanya berlaku untuk perintah req, bukan perintah x509. Tidak perlu memiliki penanda bagian tingkat atas, jadi Anda bisa menghapus baris pertama itu, dan kemudian akan berfungsi dengan baik untuk menghasilkan permintaan atau sertifikat.

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

Sebagai alternatif, Anda dapat menggunakan -x509argumen ke reqperintah untuk menghasilkan sertifikat yang ditandatangani sendiri dalam satu perintah, daripada terlebih dahulu membuat permintaan dan kemudian sertifikat. Dalam hal ini tidak perlu untuk menghapus [req]baris bagian, karena bagian itu dibaca dan digunakan oleh perintah req.

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

Untuk rekap, berikut adalah file konfigurasi yang dimodifikasi yang digunakan dalam perintah di atas:

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
Ini adalah satu-satunya penjelasan yang membantu saya memahami mengapa sertifikat keluar tanpa SAN (dalam kasus saya, saya perlu memasukkan x509_extensions dalam file konfigurasi)
Daniel Beardsmore

2

Solusi saya adalah mempertahankan yang utama openssl.cnfseperti itu dan pada akhirnya menambahkan bagian baru seperti di [ cert_www.example.com ]mana www.example.com adalah situs web yang ingin saya buat sertifikat, dan di dalamnya, masukkan yang subjectAltNamesaya perlukan (dan ada yang lain). Tentu saja bagian itu dapat dinamai apa pun yang Anda inginkan.

Setelah itu, saya dapat menjalankan openssl reqperintah seperti sebelumnya, cukup menambahkan -extensions cert_www.example.comkontennya untuk diambil dan saya tambahkan -subjuntuk menambahkan secara langsung semua info DN.

Jangan lupa memverifikasi konten sertifikat setelah dibuat dan sebelum digunakan, dengan openssl x509 -text


1

Script Bash dengan config yang dibuat

Sebagai skrip shell yang seharusnya bekerja lintas platform dengan bash. Mengasumsikan HOSTNAMEenv ditetapkan untuk shell atau menyediakan nama host yang Anda pilih, misalnyaself_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"

Yang di atas kurang lebih menyuntikkan info file konfigurasi minimum telanjang openssl kebutuhan.

Catatan, termasuk ekstra DNS:localhostsebagai SAN untuk memungkinkan pengujian melalui localhost lebih mudah. Hapus bit ekstra dari skrip jika Anda tidak menginginkannya.

Kredit

Jawaban bcardarella luar biasa (tidak dapat berkomentar / memilih karena perwakilannya tidak mencukupi). Namun, jawabannya menggunakan lokasi file config openssl yang ada khusus platform ... karenanya:

Bekerja untukku

Jelas, seseorang hanya perlu menemukan file konfigurasi openssl untuk platform Anda sendiri dan mengganti lokasi yang benar.

Uji

Untuk cara menguji, impor test.cert.pemke otoritas chrome di chrome://settings/certificates, dan:

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

Dan setelah pengujian

kill $openssl_pid
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.