web-dev-qa-db-ja.com

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

最後に、キーをHTTPSサーバーに渡すときにNode.jsで取得します。

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)

Certファイルにcert.pemのみを残し、ca属性をca-cert.pemにすると、次のようになります。

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ハンドシェイク中にWebサーバーから受信したチェーン内の最初の証明書の発行者)のローカル証明書を見つけることができません。

それが何を意味するのか分かりません。

このエラーは、証明書のパスまたはチェーンが壊れており、証明書ファイルがないことを意味します。

- https://wiki.zimbra.com/wiki/Fix_depth_lookup:unable_to_get_issuer_certificate

更新

もう少し助け:

この問題は通常、「ローカル発行者証明書を取得できません」または「自己署名証明書」などのログメッセージによって示されます。証明書が検証される場合、ルートCAはOpenSSLによって「信頼」される必要があります。これは通常、CA証明書をディレクトリまたはファイルに配置し、関連するプログラムがそれを読み取るように設定する必要があることを意味しますOpenSSLプログラム「verify」は同様の動作をし、同様のエラーメッセージを発行します。詳細については、verify(1)プログラムのマニュアルページを確認してください。

しかし、まだあまり役に立ちません。

Node.jsは1.0.2mではなく1.0.2lを使用しているように見えますが、大したことではないようです。

$ node -pe process.versions | grep openssl
  openssl: '1.0.2l'

更新2

奇妙なことに、Node.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)

しかし、ブラウザーにアクセスすると、「注意して続行」ページが表示されず、Node.jsで要求を正常に記録できます。たぶんそれはいくらか助けになります。助けてください:D

9
Lance Pollard

(openssl-1.0.2mのX509_verify_certcrypto/x509/x509_vfy.c:204から抽出したこの回答)

OpenSSL verifyアプリケーションは、次の方法で証明書を検証します。ターゲット証明書から開始し、発行者チェーンをトレースして、最初にターゲット証明書とともに提供された信頼できない証明書を検索します。信頼できない発行者証明書が見つからない場合、OpenSSLは信頼できる証明書ストアに切り替え、チェーンの構築を続けます。このプロセスは次の場合に停止します

  1. 発行者が信頼できるストアに見つかりません。
  2. 自己署名証明書が見つかりました。
  3. 最大検証深度に遭遇しました。

この時点で、途中で終了するチェーンがあります(発行者が見つからなかった場合、または検証の深さを超えた場合)。

OpenSSLは、チェーン上の信頼できる各証明書をスキャンして、信頼できる証明書の目的を指定するSSLv3拡張機能を探します。信頼できる証明書に検証操作の「目的」に対する正しい「trust」属性がある(または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

次に、-addtrustopenssl x509オプションを使用して、中間CAに受け入れ可能な信頼属性の1つがあることを確認します(これを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

おいおい!チェーン全体を提供していなくても、IntermediateCAWithTrustを介してAnotherUserCertを正常に検証しました。この違いの鍵は、チェーン内の信頼できる証明書のいずれかが検証操作に適切な信頼属性を持っていたことです。

もう少し詳しく(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

そのページの下部近くには、前述の議論の簡潔な要約があります。

BasicConstraints拡張CAフラグは、証明書をCAとして使用できるかどうかを判断するために使用されます。 CAフラグがtrueの場合はCAであり、CAフラグがfalseの場合はCAではありません。すべてのCAのCAフラグをtrueに設定する必要があります。

BasicConstraints拡張が存在しない場合、証明書は「可能性のあるCA」であると見なされ、証明書の使用目的に従って他の拡張がチェックされます。この場合、証明書は実際にはCAと見なされるべきではないため、警告が表示されます。ただし、一部の破損したソフトウェアを回避するためにCAであることが許可されています。

つまり、要するに、中間CAが(X509v3 Basic Constraintsで)適切なCAであることを確認してください。これはすばらしいチュートリアルのようです(中間CAを明示的にCAとして生成します): https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html

バックアップ計画として、常にチェーン全体を提供するか、-addtrustハックを使用して中間CAを作成できます。

6
lockcmpxchg8b

https://letsencrypt.org/ は本当に使いやすく、無料です。また、ローカルHTTPポートでSSLなしでノードを実行し、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;
    }
}
0
Abdul Ahad