Ошибка OpenSSL-невозможно получить сертификат локального эмитента
у меня есть простая настройка цепи и может успешно проверить в этом случае:
$ openssl version
OpenSSL 1.0.2m 2 Nov 2017
$ openssl verify -CAfile chain.pem cert.pem
cert.pem: OK
однако я получаю ошибки в таких случаях:
$ openssl verify -CAfile ca-cert.pem cert.pem
cert.pem: C = US...
error 2 at 1 depth lookup:unable to get issuer certificate
в частности не удалось получить сертификат эмитента.
также получить его здесь:
$ openssl verify chain.pem
chain.pem: C = US...
error 20 at 0 depth lookup:unable to get local issuer certificate
$ openssl verify cert.pem
cert.pem: C...
error 20 at 0 depth lookup:unable to get local issuer certificate
наконец, я получаю его в узле.js, когда я передаю ключи на сервер HTTPS:
events.js:193
throw er; // Unhandled 'error' event
^
Error: unable to get local issuer certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
Я попытался передать его с { key, cert, ca }
, но все равно та же ошибка.
интересно как приступить к отладке этого или что исправить, чтобы запустить сервер HTTPS.
если я использую pfx
файл я получаю следующее:
events.js:193
throw er; // Unhandled 'error' event
^
Error: self signed certificate in certificate chain
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
если я оставлю только сертификат.pem в файле сертификата и сделайте ca
атрибут быть ca-cert.Пем, он дает:
Error: unable to verify the first certificate
at TLSSocket.<anonymous> (_tls_wrap.js:1108:38)
at emitNone (events.js:105:13)
at TLSSocket.emit (events.js:207:7)
at TLSSocket._finishInit (_tls_wrap.js:638:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:468:38)
не знаю, что делать.
здесь они говорят:
OpenSSL не может найти локальный сертификат для эмитента (или эмитента первый сертификат в цепочке, полученный от веб-сервера во время рукопожатия TLS), с помощью которого можно проверить подпись(подписи).
не уверен, что это значит.
эта ошибка означает, что путь сертификата или цепочка нарушена, и вам не хватает файлов сертификатов.
- https://wiki.zimbra.com/wiki/Fix_depth_lookup:unable_to_get_issuer_certificate
обновление
немного больше помощи:
эта проблема обычно обозначается сообщениями журнала, говорящими что-то вроде "невозможно получить сертификат локального эмитента" или "самозаверяющий сертификат". Когда сертификат проверен, его корневой ЦС должен быть "доверенным" OpenSSL, это обычно означает, что сертификат ЦС должен быть помещен в каталог или файл и соответствующая программа, настроенная для его чтения. Программа OpenSSL "verify" ведет себя аналогичным образом и выдает аналогичные сообщения об ошибках: проверьте страницу руководства программы verify(1) для получения дополнительной информации.
- https://www.openssl.org/docs/faq.html#USER6
но все равно не очень поможет.
похоже на узел.js использует 1.0.2 l вместо 1.0.2 m, но не кажется большим сделка.
$ node -pe process.versions | grep openssl
openssl: '1.0.2l'
обновление 2
странно, я получаю это, когда делаю запрос от узла.js:
Uncaught Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
но когда я иду в браузер, я не вижу страницу "продолжить с осторожностью" и могу успешно зарегистрировать запрос в узле.js. Может, это немного поможет. Пожалуйста, помогите :г
2 ответов
(этот ответ извлечен из X509_verify_cert
at crypto/x509/x509_vfy.c:204
, в openssl-1.0.2 m)
OpenSSL verify
приложение проверяет сертификат следующим образом: оно строит цепочку сертификатов, начиная с целевого сертификата и отслеживая цепочку эмитента, сначала ищет любые ненадежные сертификаты, поставляемые вместе с целевым сертификатом. Не найдя сертификат ненадежного эмитента, OpenSSL переключается в хранилище доверенных сертификатов и продолжает построение цепочки. Этот процесс останавливается, когда
- эмитент не найден в хранилище доверенных.
- обнаружен самозаверяющий сертификат.
- обнаружена максимальная глубина проверки.
на данный момент у нас есть цепочка, которая может закончиться преждевременно (если мы не смогли найти эмитента или если мы превысили глубину проверки).
OpenSSL затем сканирует каждый доверенный сертификат в цепочке, ища расширения SSLv3, которые определяют цель доверенного сертификата. Если доверенный сертификат имеет правильные атрибуты " доверие "для" цели " операции проверки (или имеет anyExtendedKeyUsage
атрибут) цепочке доверяют. (Простите за махание рукой по атрибутам доверия, эту часть кода было трудно прочитать.)
так позволяет проверить его. Во-первых, давайте повторим случаи ошибок OP:
#
echo "Making Root CA..."
openssl req -newkey rsa:4096 -nodes -keyout ca-key.pem -sha384 -x509 -days 365 -out ca-crt.pem -subj /C=XX/ST=YY/O=RootCA
echo "Making Intermediate CA..."
openssl req -newkey rsa:3072 -nodes -keyout int-key.pem -new -sha384 -out int-csr.pem -subj /C=XX/ST=YY/O=IntermediateCA
openssl x509 -req -days 360 -in int-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt.pem
echo "Making User Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key.pem -new -sha256 -out usr-csr.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b
openssl x509 -req -days 360 -in usr-csr.pem -CA int-crt.pem -CAkey int-key.pem -CAcreateserial -out usr-crt.pem
echo ""
echo "Making Chain..."
cat ca-crt.pem int-crt.pem > chain.pem
echo ""
echo "Verfying UserCert via RootCA..."
openssl verify -CAfile ca-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via IntermediateCA..."
openssl verify -CAfile int-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via chain..."
openssl verify -CAfile chain.pem usr-crt.pem
доходность
[... Skipping OpenSSL KeyGen / CertGen verbosity ...]
Making Chain...
Verfying UserCert via RootCA...
usr-crt.pem: C = XX, ST = YY, O = LockCmpXchg8b
error 20 at 0 depth lookup:unable to get local issuer certificate
Verfying UserCert via IntermediateCA...
usr-crt.pem: C = XX, ST = YY, O = IntermediateCA
error 2 at 1 depth lookup:unable to get issuer certificate
Verfying UserCert via chain...
usr-crt.pem: OK
теперь, давайте использовать на openssl x509
чтобы убедиться, что у нас есть один из допустимых атрибутов доверия на промежуточном ЦС (вызовите этот IntermediateCAWithTrust
; мы будем использовать его для входа AnotherUserCert
.):
echo ""
echo "Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)"
echo ""
echo "Making IntermediateCAWithTrust..."
openssl req -newkey rsa:3072 -nodes -keyout int-key2.pem -new -sha384 -out int-csr2.pem -subj /C=XX/ST=YY/O=IntermediateCAWithTrust
openssl x509 -req -days 360 -in int-csr2.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt2.pem -addtrust anyExtendedKeyUsage
echo "Making AnotherUser Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key2.pem -new -sha256 -out usr-csr2.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b_2
openssl x509 -req -days 360 -in usr-csr2.pem -CA int-crt2.pem -CAkey int-key2.pem -CAcreateserial -out usr-crt2.pem
echo ""
echo "Verfying AnotherUserCert via IntermediateCAWithTrust..."
openssl verify -CAfile int-crt2.pem usr-crt2.pem
дает
Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)
Making IntermediateCAWithTrust...
[... Snip more OpenSSL generation output ...]
Making AnotherUser Cert...
[... Snip more OpenSSL generation output ...]
Verfying AnotherUserCert via IntermediateCAWithTrust...
usr-crt2.pem: OK
Эй, смотрите! мы только что успешно проверили AnotherUserCert через IntermediateCAWithTrust, хотя мы не поставляли всю цепочку. Ключ к этой разнице в том, что любой из доверенных сертификатов в цепочке имел соответствующий атрибут доверия для проверки работы.
глядя немного ближе (via openssl x509 -in ca-crt.pem -noout -text
), наш сертификат CA имеет
X509v3 Basic Constraints:
CA:TRUE
который я бы предположил, что OpenSSL рассматривает как общее расширение "может проверить для любой цели". Новый IntermediateCAWithTrust
нет X509v3 Basic Constraints
, а
Trusted Uses:
Any Extended Key Usage
No Rejected Uses.
для получения дополнительной информации в -addtrust
опция и типы атрибутов доверия, которые могут быть добавлены, см. https://www.openssl.org/docs/manmaster/man1/x509.html#TRUST_SETTINGS
рядом с в нижней части этой страницы приводится краткое резюме предшествующего обсуждения:
флаг CA расширения basicConstraints используется для определения сертификат можно использовать как CA. Если флаг CA является true, то это ЦС, если флаг ЦС является ложным, то это не ЦС. Все CAs должны иметь флаг CA установлен в true.
если расширение basicConstraints отсутствует, то сертификат считается "возможным CA" другие расширения проверяются в соответствии с предполагаемым использованием сертификата. Предупреждение в этом случае, потому что сертификат действительно не должны рассматриваться как A CA: однако разрешено быть CA, чтобы обойти некоторые сломанные программное обеспечение.
Итак, короче говоря, убедитесь, что ваш промежуточный CAs правильно CAs (в их X509v3 Basic Constraints
). Это кажется отличным учебником (и он явно генерирует промежуточный ЦС как ЦС): https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
как резервный план, вы можете всегда поставить всю цепь, или вы можете сделать ваше промежуточное КАС с -addtrust
рубить.
https://letsencrypt.org/ действительно прост в использовании и бесплатно. Кроме того, запустите узел без SSL на локальном HTTP-Порту и используйте nginx в качестве HTTPS-прокси.
sudo apt-get install certbot nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/letsencrypt/live/host.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/host.com/privkey.pem;
access_log /var/log/nginx/host.access.log;
error_log /var/log/nginx/host.error.log;
server_name _;
gzip on;
gzip_proxied any;
gzip_types text/css text/javascript text/xml text/plain application/javascript application/x-javascript application/json;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8080;
proxy_read_timeout 90s;
proxy_redirect http://localhost:8080 https://www.host.com;
}
}