web-dev-qa-db-ja.com

証明書のサブジェクトの別名を表示する方法は?

私が見つけた最も近い答えは、「grep」を使用することです。

> openssl x509 -text -noout -in cert.pem | grep DNS

これを行うより良い方法はありますか?私はコマンドラインのみを好みます。

ありがとう。

48
user180574

次のオプションを追加することにより、-textの出力を拡張のみに制限できることに注意してください。

-certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux

すなわち:

openssl x509 -text -noout -in cert.pem \
  -certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux

ただし、Subject Alternative Nameのみを取得するには、テキスト解析ロジックを適用する必要があります。

それだけでは不十分な場合は、opensslライブラリを使用して、探している特定のフィールドを抽出する小さなプログラムを作成する必要があると思います。 Subject Alternative Nameなどの拡張フィールドを抽出するなど、証明書を解析する方法を示すプログラムの例を次に示します。

https://zakird.com/2013/10/13/certificate-parsing-with-openssl

プログラミングのルートに行けば、opensslとCを使用する必要がないことに注意してください...好きな言語とASN.1パーサーライブラリを選択して使用できます。たとえば、Javaでは、 http://jac-asn1.sourceforge.net/ などを使用できます。

36
Raman

https://stackoverflow.com/a/13128918/169568 から取得

$ true | openssl s_client -connect example.com:443 | openssl x509 -noout -text | grep DNS:

$ true | openssl s_client -connect localhost:8443 | openssl x509 -noout -text | grep DNS:
depth=2 C = US, ST = NC, L = SomeCity, O = SomeCompany Security, OU = SomeOU, CN = SomeCN
verify error:num=19:self signed certificate in certificate chain
DONE
                DNS:localhost, DNS:127.0.0.1, DNS:servername1.somedom.com, DNS:servername2.somedom.local
21
ThorSummoner

私の解決策があります( openssl および sed を使用):

bash 最初

_sed -ne '
    s/^\( *\)Subject:/\1/p;
    /X509v3 Subject Alternative Name/{
        N;
        s/^.*\n//;
      :a;
        s/^\( *\)\(.*\), /\1\2\n\1/;
        ta;
        p;
        q;
    }' < <(openssl x509 -in cert.pem -noout -text)
_

書くことができます:

_sed -ne 's/^\( *\)Subject:/\1/p;/X509v3 Subject Alternative Name/{
    N;s/^.*\n//;:a;s/^\( *\)\(.*\), /\1\2\n\1/;ta;p;q; }' < <(
    openssl x509 -in cert.pem -noout -text )
_

次のようにレンダリングできます。

_         CN=www.example.com
                DNS:il0001.sample.com
                DNS:example.com
                DNS:demodomain.com
                DNS:testsite.com
                DNS:www.il0001.sample.com
                DNS:www.il0001.sample.com.vsite.il0001.sample.com
                DNS:www.example.com
                DNS:www.example.com.vsite.il0001.sample.com
                DNS:www.demodomain.com
                DNS:www.demodomain.com.vsite.il0001.sample.com
                DNS:www.testsite.com
                DNS:www.testsite.com.vsite.il0001.sample.com
_

ライブサーバーでも同じ

_sed -ne 's/^\( *\)Subject:/\1/p;/X509v3 Subject Alternative Name/{
    N;s/^.*\n//;:a;s/^\( *\)\(.*\), /\1\2\n\1/;ta;p;q; }' < <(
    openssl x509 -noout -text -in <(
        openssl s_client -ign_eof 2>/dev/null <<<$'HEAD / HTTP/1.0\r\n\r' \
            -connect google.com:443 ) )
_

5月出力:

_         C=US, ST=California, L=Mountain View, O=Google Inc, CN=*.google.com
                DNS:*.google.com
                DNS:*.Android.com
                DNS:*.appengine.google.com
                DNS:*.cloud.google.com
                DNS:*.gcp.gvt2.com
                DNS:*.google-analytics.com
                DNS:*.google.ca
                DNS:*.google.cl
                DNS:*.google.co.in
                DNS:*.google.co.jp
                DNS:*.google.co.uk
                DNS:*.google.com.ar
                DNS:*.google.com.au
                DNS:*.google.com.br
                DNS:*.google.com.co
                DNS:*.google.com.mx
                DNS:*.google.com.tr
                DNS:*.google.com.vn
                DNS:*.google.de
                DNS:*.google.es
                DNS:*.google.fr
                DNS:*.google.hu
                DNS:*.google.it
                DNS:*.google.nl
                DNS:*.google.pl
                DNS:*.google.pt
                DNS:*.googleadapis.com
                DNS:*.googleapis.cn
                DNS:*.googlecommerce.com
                DNS:*.googlevideo.com
                DNS:*.gstatic.cn
                DNS:*.gstatic.com
                DNS:*.gvt1.com
                DNS:*.gvt2.com
                DNS:*.metric.gstatic.com
                DNS:*.Urchin.com
                DNS:*.url.google.com
                DNS:*.youtube-nocookie.com
                DNS:*.youtube.com
                DNS:*.youtubeeducation.com
                DNS:*.ytimg.com
                DNS:Android.clients.google.com
                DNS:Android.com
                DNS:developer.Android.google.cn
                DNS:g.co
                DNS:goo.gl
                DNS:google-analytics.com
                DNS:google.com
                DNS:googlecommerce.com
                DNS:Urchin.com
                DNS:www.goo.gl
                DNS:youtu.be
                DNS:youtube.com
                DNS:youtubeeducation.com
_

POSIX シェル

< <(...)bashismであるため、同じコマンドを記述する必要があります。

_openssl x509 -in cert.pem -noout -text | sed -ne '
  s/^\( *\)Subject:/\1/p;
  /X509v3 Subject Alternative Name/{
      N;
      s/^.*\n//;
    :a;
      s/^\( *\)\(.*\), /\1\2\n\1/;
      ta;
      p;
      q;
  }'
_

そして

_printf 'HEAD / HTTP/1.0\r\n\r\n' |
    openssl s_client -ign_eof 2>/dev/null -connect google.com:443 |
    openssl x509 -noout -text |
    sed -ne 's/^\( *\)Subject:/\1/p;/X509v3 Subject Alternative Name/{
        N;s/^.*\n//;:a;s/^\( *\)\(.*\), /\1\2\n\1/;ta;p;q; }'
_
10
F. Hauri

Opensslの新しいバージョンには、subjectAltNameレコードのみを印刷できる '-ext'オプションがあります。 Debian 9.9で「OpenSSL 1.1.1b」を使用しています

openssl x509 -noout -ext subjectAltName -in cert.pem

それでも、出力を解析する必要があります。

変更は https://github.com/openssl/openssl/issues/3932 で行われました

4
Ely

Grepを使用した非常にシンプルなソリューション

openssl x509 -in /path/to/x509/cert -noout -text|grep -oP '(?<=DNS:|IP Address:)[^,]+'|sort -uV

Google証明書の場合、これは次を出力します。

Android.clients.google.com
Android.com
developer.Android.google.cn
g.co
goo.gl
google.com
googlecommerce.com
google-analytics.com
hin.com
Urchin.com
www.goo.gl
youtu.be
youtube.com
youtubeeducation.com
*.Android.com
*.appengine.google.com
*.cloud.google.com
*.gcp.gvt2.com
*.googleadapis.com
*.googleapis.cn
*.googlecommerce.com
*.googlevideo.com
*.google.ca
*.google.cl
*.google.com
*.google.com.ar
*.google.com.au
*.google.com.br
*.google.com.co
*.google.com.mx
*.google.com.tr
*.google.com.vn
*.google.co.in
*.google.co.jp
*.google.co.uk
*.google.de
*.google.es
*.google.fr
*.google.hu
*.google.it
*.google.nl
*.google.pl
*.google.pt
*.gstatic.cn
*.gstatic.com
*.gvt1.com
*.gvt2.com
*.metric.gstatic.com
*.Urchin.com
*.url.google.com
*.youtubeeducation.com
*.youtube.com
*.ytimg.com
*.google-analytics.com
*.youtube-nocookie.com
4
ThinGuy

awkを使用してSANに近づくと、上記のオプションをawkステートメントにパイプできます。

openssl x509 -in mycertfile.crt -text -noout \
  -certopt no_subject,no_header,no_version,no_serial,no_signame,no_validity,no_subject,no_issuer,no_pubkey,no_sigdump,no_aux \
 | awk '/X509v3 Subject Alternative Name/','/X509v3 Basic Constraints/'
1
RandomW

改善されたawkベースのソリューション(hat-tip:@RandomW):

openssl x509 -in certfile -text -noout \
  -certopt no_header,no_version,no_serial,no_signame,no_validity,no_issuer,no_pubkey,no_sigdump,no_aux \
| awk '/X509v3 Subject Alternative Name:/ {san=1;next} 
      san && /^ *X509v3/ {exit} 
      san { sub(/DNS:/,"",$1);print $1}'

ここにあるgrepおよびsedソリューションも同様に、リストを出力します。違いは、情報の検索場所をより厳密に制御できることです。出力形式が変更された場合、このバージョンはより堅牢で、変更をより適切に処理します。 「Subject Alternative Name」と次の「X509v3」セクションの間のテキストのみが出力され、オプションの先行する「DNS:」テキストはすべて削除されます。

Android.clients.google.com
Android.com
developer.Android.google.cn
g.co
goo.gl
...
0
Otheus

python代替を追加します。前提条件は、「DNS:」レコードを含む文字列があることです。

証明書の詳細(サブプロセス、OpenSSLモジュールなど)を取得します。dnsstringには、「openssl」出力の「DNS:」行が含まれています。証明書のテキスト出力からDNS名の文字列を取得する方法の例。

for idx, line in enumerate(certoutput.split()):
    if ' X509v3 Authority Key Identifier:' in line:
        dnsstring = certoutput.split()[idx + 1]

# Get a list
[x.replace('DNS:', '').replace(',', '') for x in dnsstring]

# Format to a comma separated string
', '.join([x.replace('DNS:', '').replace(',', '') for x in dnsstring])

コマンドラインの例:

true | \
  openssl s_client -showcerts -connect google.com:443 2>/dev/null | \
  openssl x509 -noout -text 2>/dev/null | grep " DNS:" | \
  python -c"import sys; print ', '.join([x.replace('DNS:', '').replace(',', '') for x in sys.stdin.readlines()[0].split()])"

出力:

*.google.com, *.Android.com, <etc>
0
sastorsl

たぶんこれで十分です:

openssl x509 -in cert.pem -noout -text -certopt ca_default,no_sigdump
0
NOZUONOHIGH

証明書のサブジェクトの別名を表示する方法は?

X509証明書には複数のSANがある場合があります。以下は SSL/TLSクライアント のOpenSSL wikiからのものです。名前をループして出力します。

X509*のような関数からSSL_get_peer_certificateをTLS接続から、d2i_X509をメモリから、またはPEM_read_bio_X509をファイルシステムから取得します。

void print_san_name(const char* label, X509* const cert)
{
    int success = 0;
    GENERAL_NAMES* names = NULL;
    unsigned char* utf8 = NULL;

    do
    {
        if(!cert) break; /* failed */

        names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
        if(!names) break;

        int i = 0, count = sk_GENERAL_NAME_num(names);
        if(!count) break; /* failed */

        for( i = 0; i < count; ++i )
        {
            GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
            if(!entry) continue;

            if(GEN_DNS == entry->type)
            {
                int len1 = 0, len2 = -1;

                len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                if(utf8) {
                    len2 = (int)strlen((const char*)utf8);
                }

                if(len1 != len2) {
                    fprintf(stderr, "  Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
                }

                /* If there's a problem with string lengths, then     */
                /* we skip the candidate and move on to the next.     */
                /* Another policy would be to fails since it probably */
                /* indicates the client is under attack.              */
                if(utf8 && len1 && len2 && (len1 == len2)) {
                    fprintf(stdout, "  %s: %s\n", label, utf8);
                    success = 1;
                }

                if(utf8) {
                    OPENSSL_free(utf8), utf8 = NULL;
                }
            }
            else
            {
                fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
            }
        }

    } while (0);

    if(names)
        GENERAL_NAMES_free(names);

    if(utf8)
        OPENSSL_free(utf8);

    if(!success)
        fprintf(stdout, "  %s: <not available>\n", label);

}
0
jww