「証明書のCNは正しいのに、ブラウザーで名前のエラーが出るんです」
「.crtファイルを渡したのに、製品に読み込めないと言われました」
どちらも、証明書の中身を読めれば、すぐに原因が分かる相談です。前者はSAN、後者はファイル形式の問題であることがほとんどです。
第3回では、opensslとPowerShellで自己署名証明書を作りました。第4回では、その証明書の中身(X.509)を読み解きます。どの項目が何を意味し、どの拡張を見ればよいか、ファイル形式をどう見分けるかまでを押さえましょう。
証明書の構造
証明書の形式はITU-TのX.509で決まっており、インターネットでの使い方はRFC 5280が定めています。現在使われるのはバージョン3(v3)です。

中身は3つの部分からなります。
- tbsCertificate(to be signed、署名される部分):発行者、主体(持ち主)、有効期間、公開鍵、拡張など、証明書として主張したい内容がすべて入る
- 署名アルゴリズム
- 署名値:発行者である認証局(CA)が、tbsCertificateを自分の秘密鍵で署名した結果
検証する側は、発行者の公開鍵で署名値を確かめ、内容が書き換えられていないことと、確かにそのCAが発行したことを確認します(第2回の署名と同じ仕組み)。
つまり証明書とは、「この公開鍵の持ち主はこの名前だ」という内容に、CAが署名した文書です。署名の対象は①の全体なので、名前も期間も拡張もCAが保証しています。1ビットでも書き換えれば、署名の検証に失敗します。
基本の項目
| 項目 | openssl の表示 | 内容 | 例 |
|---|---|---|---|
| バージョン | Version | 拡張を持てるのは v3。現在はほぼすべて v3 | 3 (0x2) |
| シリアル番号 | Serial Number | 発行者ごとに一意の番号。失効もこの番号で指す | 61:ae:ba:e2:…(最大20バイト) |
| 署名アルゴリズム | Signature Algorithm | CA が署名に使った方式 | ecdsa-with-SHA256、sha256WithRSAEncryption |
| 発行者 | Issuer | 署名した CA の名前(DN) | CN=Example Issuing CA E1 |
| 有効期間 | Validity(Not Before/Not After) | この期間だけ有効。UTC で記録 | Sep 26 2026 〜 Apr 13 2027 GMT |
| 主体 | Subject | 持ち主の名前(DN) | CN=www.example.jp |
| 主体の公開鍵 | Subject Public Key Info | 公開鍵とそのアルゴリズム | EC P-256、RSA 2048ビット |
| 拡張 | X509v3 extensions | 名前(SAN)、用途、CA かどうか等 | Subject Alternative Name 等 |
- 公開CAのシリアル番号は、推測されないよう64ビット以上の乱数を含めることが決められている(第5回のBaseline Requirements)
- 有効期間はUTCで記録され、opensslはGMTで、Windowsの画面やPowerShellは現地時刻(日本では9時間進む)で表示する。期限を報告するときは、どちらの時刻かを添える
主体(DN)の書き方
主体(Subject)や発行者(Issuer)は、DN(識別名)という形式で書きます。
| 略号 | 属性の正式名 | 内容 | 例 |
|---|---|---|---|
| C | countryName | 国(ISO 3166 の2文字) | JP |
| ST | stateOrProvinceName | 都道府県 | Tokyo |
| L | localityName | 市区町村 | Chiyoda-ku |
| O | organizationName | 組織名。OV・EV で審査される | Example Corp. |
| OU | organizationalUnitName | 部署名。公開CAの証明書には2022年9月1日から入れられない | (入れない) |
| CN | commonName | 慣習で FQDN を書く。ホスト名の検証には使われない | www.example.jp |
同じ証明書でも、ツールによって見た目が変わります。
openssl の表示: C=JP, ST=Tokyo, L=Chiyoda-ku, O=Example Corp., CN=www.example.jp
Windows の表示: CN=www.example.jp, O=Example Corp., L=Chiyoda-ku, S=Tokyo, C=JP
opensslの-subjや設定ファイルにはST=と書きます(RFC 4514)。ただし、Windowsの画面とPowerShellは同じ属性をS=と表示し、並び順も逆(CNが先)です。また、DV証明書の主体はCN=だけのことが多く、C・ST・L・Oは入りません。
SAN:ホスト名の検証はSANだけ
冒頭の「CNは正しいのに名前のエラー」の答えがここです。
SAN(Subject Alternative Name、主体の別名)は、証明書を使えるホスト名やIPアドレスを列挙する拡張です。ブラウザーがアクセス先の名前と照合するのはSANだけで、CNは見ません。

SANが無いときにCNを使う逃げ道は、Chromeが2017年のChrome 58で廃止し、2023年のRFC 9525もCNを識別に使ってはならないと明記しました。公開CAの証明書には2012年からSANが必須です。
CNに正しい名前を書いても、SANに無ければNET::ERR_CERT_COMMON_NAME_INVALIDになります。
一方、opensslの-verify_hostnameなど一部のツールは、SANが無いと今もCNを見ます。「opensslでは通るのにブラウザーではエラー」なら、SANの書き忘れを疑いましょう。
ポイント
・名前の照合はSANだけ。ブラウザーもRFC 9525もCNを使わない
・名前が1つでもSANに書く。CNを入れるならSANの値と同じにする
・一部のツールはCNを見るため、ツールで通ってもブラウザーで失敗しうる
SANの書き方と一致のルール
SANに書いた値が、どの名前に一致するのかを整理します。

特にワイルドカードは誤解が多いところです。
*.example.jpはwww.example.jpやmail.example.jpに一致する- しかし
example.jp自身には一致しない。必要ならDNS:example.jpも並べて書く a.b.example.jpのような2階層下にも一致しない。ワイルドカードは左端の1ラベルだけを置き換える(RFC 9525)
実際にopensslで確かめると、2階層下の名前はエラーになります。
$ openssl x509 -in wc.crt -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:*.example.jp, DNS:example.jp, IP Address:192.0.2.10
$ openssl verify -CAfile root.crt -untrusted inter.crt -verify_hostname a.b.example.jp wc.crt
CN=*.example.jp
error 62 at 0 depth lookup: hostname mismatch
error wc.crt: verification failed
IPアドレスで開く管理画面などは、IP:型で書きます。ホスト名でも開くならDNS:も並べて書きます(IP:だけではホスト名での接続に一致しません)。公開CAのIPアドレス証明書は少なく、Let’s Encryptは2026年1月から有効期間約6日の短期証明書として提供しています。SANの決め方とワイルドカードの使いどころは第6回で扱います。
主な拡張① 用途と制約
| 拡張 | 意味 | サーバー証明書では | CA 証明書では |
|---|---|---|---|
| Basic Constraints | CA かどうか(CA:TRUE/FALSE)と、下に置ける階層の数(pathlen) | CA:FALSE(critical) | CA:TRUE。中間CA は pathlen:0 が多い |
| Key Usage | 鍵で行ってよい操作 | Digital Signature(RSA では Key Encipherment も入ることがある) | Certificate Sign、CRL Sign |
| Extended Key Usage(EKU) | 証明書の用途 | TLS Web Server Authentication(serverAuth) | 中間CA では発行できる用途を限定する |
| Name Constraints | 発行してよい名前の範囲 | 入れない | 社内CA を corp.example.jp 配下に限る等 |
- critical(重要)が付いた拡張を理解できない検証者は、その証明書を拒否しなければならない(RFC 5280)
- Chrome Root Programは公開CAの階層をサーバー認証専用にする方針で、2027年3月15日以降に発行するサーバー証明書のEKUはserverAuthだけに限られる。クライアント証明書(mTLS、第7回)には社内CA(第9回)を使う
主な拡張② 識別子・所在・ポリシー・CT
| 拡張 | 意味 | 使われ方 |
|---|---|---|
| Subject Key Identifier(SKI) | 自分の公開鍵の識別子 | CA 証明書では必須。チェーンを組む手がかり |
| Authority Key Identifier(AKI) | 発行者の公開鍵の識別子 | 親の SKI と照合する。同じ名前の CA が複数あっても区別できる |
| Authority Information Access(AIA) | 発行者の証明書の URL(CA Issuers)、OCSP の URL | 中間証明書の自動取得、失効の確認(第5回) |
| CRL Distribution Points(CDP) | 失効リスト(CRL)の URL | 失効の確認(第5回) |
| Certificate Policies | 発行の方針を示す OID | 2.23.140.1.2.1=DV、2.23.140.1.2.2=OV、2.23.140.1.1=EV |
| CT Precertificate SCTs | CT ログに登録した証拠(SCT) | Chrome・Safari・Firefox は SCT の足りない公開証明書を拒否(第5回) |
いまLet’s Encryptの証明書を読むと、AIAにはCA Issuersだけがあり、OCSPのURLがありません。2025年にOCSPを終了し、代わりにCDPを入れているためです(第5回)。
この表の6つと、前の表の4つが見分けられれば、実務で証明書を読むには十分です。
ファイル形式と拡張子
冒頭の「.crtを渡したのに読み込めない」の話です。

| 形式 | 中身 | 見分け方 | 主な使われ方 |
|---|---|---|---|
| PEM | DER を Base64 にした文字列(RFC 7468) | —–BEGIN CERTIFICATE—– で始まる | Apache、nginx、Linux 全般。複数の証明書を連結できる |
| DER | ASN.1 の構造をそのままバイナリにしたもの | 先頭が 16進で 30 82。テキストで開くと文字化け | Java、Windows の .cer(DER の場合) |
| PKCS#12(.pfx/.p12) | 証明書+チェーン+秘密鍵を1つにし、パスワードで暗号化 | バイナリ。開くとパスワードを聞かれる | Windows(IIS)、Azure、Java のキーストア |
| PKCS#7(.p7b) | 証明書とチェーンだけ。秘密鍵は入らない | —–BEGIN PKCS7—– またはバイナリ | 中間証明書の配布、Windows へのチェーンの取り込み |
拡張子は中身を保証しません。.crt・.cerはPEMのこともDERのこともあり、.pemに秘密鍵が入っていることもあります。先頭の1行(head -1、PowerShellではGet-Content -TotalCount 1)のBEGINの後ろの語(CERTIFICATE、PRIVATE KEY、PKCS7等)で判断します。
形式を変換する
$ openssl x509 -in server.crt -outform DER -out server.der # PEM → DER
$ openssl x509 -in server.der -inform DER -out server.pem # DER → PEM
$ openssl pkcs12 -export -inkey server.key -in server.crt \
-certfile inter.crt -out server.pfx # → PKCS#12
$ openssl pkcs12 -in server.pfx -noenc -out all.pem # PKCS#12 → PEM
$ openssl crl2pkcs7 -nocrl -certfile fullchain.pem -out chain.p7b # → PKCS#7
PS> certutil -encode server.der server.pem # DER → PEM(-decode で逆)
PS> Export-PfxCertificate -Cert Cert:\LocalMachine\My\<拇印> -FilePath server.pfx `
-Password (Read-Host -AsSecureString) # ストア → PKCS#12
変換の現場でよく引っかかるのが、次の3点です。
- 証明書と秘密鍵が組かどうかは、
openssl x509 -in server.crt -noout -pubkey | openssl sha256とopenssl pkey -in server.key -pubout | openssl sha256の値が一致するかで確かめる - OpenSSL 3のPKCS#12はAES-256で暗号化される。Windows Server 2016以前は読み込めず「パスワードが正しくない」と表示されるので、
-legacyを付けて作り直す - Windows標準の機能では、PEMの秘密鍵から.pfxを作れない。Windows上でCSRを作る(
certreq、第6回)か、PowerShell 7の[X509Certificate2]::CreateFromPemFile()を使う
中身を読む① openssl
$ openssl x509 -in server.crt -noout -text
Serial Number:
61:ae:ba:e2:5c:18:e5:03:b7:d2:6a:d8:87:49:26:83:dd:3c:00:e5
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=JP, O=Example CA Inc., CN=Example Issuing CA E1
Not Before: Sep 26 00:55:58 2026 GMT
Not After : Apr 13 00:55:58 2027 GMT
Subject: C=JP, ST=Tokyo, L=Chiyoda-ku, O=Example Corp., CN=www.example.jp
Public-Key: (256 bit)
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:www.example.jp, DNS:example.jp
(出力は要所のみの抜粋です)
読む順番は、次のとおりです。
- SANとSubject(誰の証明書か)
- Issuer(誰が発行したか)
- Not After(いつまでか、GMT)
- Basic ConstraintsとEKU(何に使えるか)
IssuerとSubjectが同じなら、自己署名(ルート証明書か、自分で作った証明書)です。
要点だけならopenssl x509 -in server.crt -noout -subject -issuer -dates -ext subjectAltName。-checkend 2592000を付けると、30日以内に期限が切れる場合に終了コード1を返すので、監視に使えます(第8回)。
中身を読む② Windows(PowerShell・certutil)
PS> $c = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new("C:\work\server.crt")
PS> $c | Format-List Subject, Issuer, NotBefore, NotAfter, Thumbprint
Subject : CN=www.example.jp, O=Example Corp., L=Chiyoda-ku, S=Tokyo, C=JP
Issuer : CN=Example Issuing CA E1, O=Example CA Inc., C=JP
NotBefore : 2026/09/26 9:55:58
NotAfter : 2027/04/13 9:55:58
Thumbprint : 1B2958866A114AC0EA9D7000EF51F137DBDA0614
PS> $c.Extensions | ForEach-Object { $_.Oid.FriendlyName; $_.Format($false) }
PS> Get-ChildItem Cert:\LocalMachine\My | Format-List Subject, DnsNameList, NotAfter, Thumbprint
PS> certutil -dump server.crt
X509Certificate2はWindows PowerShell 5.1でもPowerShell 7でも使える。時刻は現地時刻(JST)で、opensslのGMTより9時間進んで見える- 拡張は
ExtensionsのFormat()で文字にできる。日本語版ではSANが「サブジェクト代替名」、EKUが「拡張キー使用法」と表示される - サーバーに入っている証明書は
Cert:\ドライブで一覧でき、DnsNameListにSANのDNS名が出る。certutil -dumpはopensslの-textに近い全項目の表示 - 拇印(Thumbprint)は証明書全体のSHA-1の指紋で、証明書を指し示すための値。署名アルゴリズムとは関係なく、SHA-1でも問題ない
サーバーから証明書を取ってくる
最後に、動いているサーバーから証明書を取ってくる方法です。
$ openssl s_client -connect www.example.jp:443 -servername www.example.jp -showcerts </dev/null
Certificate chain
0 s:C=JP, ST=Tokyo, L=Chiyoda-ku, O=Example Corp., CN=www.example.jp
i:C=JP, O=Example CA Inc., CN=Example Issuing CA E1
v:NotBefore: Sep 26 00:55:58 2026 GMT; NotAfter: Apr 13 00:55:58 2027 GMT
1 s:C=JP, O=Example CA Inc., CN=Example Issuing CA E1
i:C=JP, O=Example CA Inc., CN=Example Root CA R1
Verify return code: 0 (ok)

- 0がサーバー証明書、1以降がサーバーの送った中間証明書。各番号のi:(発行者)が次の番号のs:(主体)と一致すれば、つながっている
-servername(SNI、第7回)を付けないと、別のサイトの証明書が返ることがある- 中間証明書が送られていないと
Verify return code: 21 (unable to verify the first certificate)になる(第5回・第10回)
Windowsでは、PowerShellで次のように取れます。
PS> $tcp = [System.Net.Sockets.TcpClient]::new("www.example.jp", 443)
PS> $ssl = [System.Net.Security.SslStream]::new($tcp.GetStream(), $false, { $true })
PS> $ssl.AuthenticateAsClient("www.example.jp")
PS> $c = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($ssl.RemoteCertificate)
PS> $c | Format-List Subject, Issuer, NotAfter
PS> [IO.File]::WriteAllBytes("C:\work\www.cer", $c.Export("Cert")); $ssl.Dispose(); $tcp.Dispose()
{ $true }は、検証を省いて証明書を受け取る指定です。中身を調べる目的に限って使いましょう。保存した.cerは、前の節の方法で読めます。
考えてみよう
- 社内で使っているサーバー証明書を1つ選び、
openssl x509 -textかcertutil -dumpで読んでください。SANには、利用者が実際に入力する名前(短い名前、別名、IPアドレス)がすべて入っていますか。 - 「証明書ファイル(.crt)を渡したのに、製品に読み込めない」と言われました。考えられる原因は何ですか。最初に何を確かめますか。
- 自作の監視スクリプトや古い機器が、SANではなくCNでホスト名を確かめていないでしょうか。どうやって確かめますか。
ヒント:この記事の「SANとCN」「ファイル形式と先頭の1行」「鍵と証明書の組の確認」が手がかりです。
まとめ
- 証明書は「公開鍵と名前の組」にCAが署名した文書。署名の対象は名前も期間も拡張も含む全体
- ホスト名の照合はSANだけ。CNに書いても、SANに無ければエラー
- ワイルドカードは左端の1ラベルだけ。ドメイン自身も2階層下も含まない
- 見るべき拡張はBasic Constraints・Key Usage・EKU・AIA・CDPなど10個ほど
- 拡張子は中身を保証しない。先頭の1行で形式を見分ける
- 期限はUTC(GMT)か現地時刻かを添えて報告する
次回は、証明書の発行者をどこまでさかのぼって信頼するのか、PKIと信頼の仕組みを扱います。
連載「証明書入門」全11回
- なぜ証明書が必要か
- 暗号の基礎
- openssl・PowerShellで試す
- X.509証明書の中身(この記事)
- PKIと信頼の仕組み
- 証明書の種類と発行
- TLSの仕組み
- ライフサイクルと自動化
- 社内PKIとクラウド
- 証明書トラブルシュート
- 証明書の設計演習


コメント