証明書のフィールド
- 証明書の仕様はRFC5280で定義されています。
- 1988年にITUが公開鍵基盤(PKI)をX.509として規格化しました。このPKIの一部として証明書も規格化されました。
- インターネットで使用されるサーバ証明書やクライアント証明書はX.509証明書と呼ばれます。
- 今日ではバージョン3が使用されており、その内容はIETFのRFC 5280として公開されています。
- 証明書の内容のイメージを次に示します。
- 証明書の実質的な内容はTbsCertificateになります。
- Issuer(発行者)、Subject(サブジェクト)の値は、X.501識別名(DN: Distinguished Name)の形式であり、”CN=Taro Yamada, O=Kaisha, C=Japan”などの値となります。識別名の中に現れる”CN”, “O”などの値は相対識別名(RDN: Relative Distinguished Name)と呼ばれます。識別名・相対識別名の仕様はRFC4514, RFC4519で定義されています。
- バージョン3では任意のフィールドを追加できるよう「Extensions」(拡張機能)が設けられています。オブジェクト識別子(OID)と呼ばれる「世界的に重複しない一意な識別子(番号)」を使ってフィールドと値を追加できます。例えば、後述する「サブジェクト代替名(SAN: Subject Alternative Name)」を追加する場合、OIDとして”2.5.29.17″を使用して値を指定します。
- 拡張機能の各フィールドに対して「Criticalかどうか(critical/non-critical)」を指定できます。これはセキュリティのための仕組みであり、Criticalが指定されたフィールドは証明書の処理時に「無視してはいけないフィールド」として扱われます。(RFC5280を読むと、Criticalにすべき条件が記載されています。)
- TbsCertificateのTbsは”To Be Signed”の略で署名対象となる内容を示しています。TbsCertificateの内容をsignatureAlgorithmのアルゴリズムでデジタル署名した内容がsignatureValueになります。
- 証明書の内容はASN.1と呼ばれる言語で定義され、DER形式でバイナリデータ化されています。
- RFC5280でのASN.1を使った証明書の定義は次のようになっています。この例では「CertificateはtbsCertificate(TBSCertificate型), signatureAlgorithm(AlgorithmIdentifier型), signatureValue(BIT STRING型)で構成」「TBSCertificate型は、version, serialNumber, …で構成」という意味になります。12345678910111213141516171819Certificate ::= SEQUENCE {tbsCertificate TBSCertificate,signatureAlgorithm AlgorithmIdentifier,signatureValue BIT STRING }TBSCertificate ::= SEQUENCE {version [0] EXPLICIT Version DEFAULT v1,serialNumber CertificateSerialNumber,signature AlgorithmIdentifier,issuer Name,validity Validity,subject Name,subjectPublicKeyInfo SubjectPublicKeyInfo,issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,-- If present, version MUST be v2 or v3subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,-- If present, version MUST be v2 or v3extensions [3] EXPLICIT Extensions OPTIONAL-- If present, version MUST be v3 }
- ASN.1で定義された証明書の内容は、ASN.1の標準符号化規則の一つであるDERを使ってバイナリ形式のファイル(データ)に符号化されています。(この内容を、さらにBASE64でテキスト化したものがPEM形式です。)
- RFC5280でのASN.1を使った証明書の定義は次のようになっています。この例では「CertificateはtbsCertificate(TBSCertificate型), signatureAlgorithm(AlgorithmIdentifier型), signatureValue(BIT STRING型)で構成」「TBSCertificate型は、version, serialNumber, …で構成」という意味になります。
- 証明書のファイルは”.der”, “.pem”, “.crt”等が使われます。ファイルの拡張子の違いについては、こちらをご覧ください。
証明書の識別方法
- 証明書はシリアル番号(Serial Number)または拇印(Thumbprint)で識別できます。
それぞれの特徴は次の通りです。項目 シリアル番号
(Serial Number)拇印
(Thumbprint)取得方法 証明書のフィールドから取得 証明書のハッシュ値を計算 ユニーク範囲 認証局でユニーク
(別の認証局の場合は衝突の可能性あり)世界でユニーク ユニーク化 発行者の識別名(DN)+シリアル番号 拇印のみで一意 - シリアル番号は、認証局で発行されるユニークな番号であり、認証局の中でユニークです。逆に、異なる認証局で発行された証明書では、シリアル番号が衝突する場合があります。
- クライアント証明書を扱うサービスによっては、内部で複数の認証局(中間証明書)が使用される場合があり、当該サービスの中でシリアル番号が重複する場合があります。そのため、シリアル番号がユニークな条件をサービス側に確認することをお薦めします。
- 拇印(Thumbprint)は実行環境によっては使用できない場合があります。
- WindowsのPowerShell系コマンドレットでは、証明書の識別に拇印が使用されます。
- Windowsで証明書を開くと証明書のフィールドの一つとして「拇印」で表示されますが、これは他の項目とは異なり証明書の「プロパティ」です。
- リバースプロキシサーバでアプリに転送するフィールドとして拇印は選べない可能性があります。
クライアント証明書のユーザ情報
- クライアント証明書に紐づくユーザ情報はサブジェクト/サブジェクト代替名から取得できます。
- サブジェクト(Subject)は証明書の発行先となる実体を説明するフィールドで、組織/ユーザ/デバイス等の情報が定義されています。サーバ証明書の場合は発行先組織、クライアント証明書の場合は発行先ユーザの情報(ユーザ名、所属組織・部門、メールアドレス等)になります。
- サブジェクト代替名(SAN: Subject Alternative Name)は、サブジェクトの情報を補う、または完全に置き換えるためのフィールドです。サブジェクト代替名では、メールアドレス/DNS名/IPアドレス/URI/UserPrinciplName/別名などの複数の値を指定することができます。
- 発行先となるユーザ情報がサブジェクトやサブジェクト代替名のどこに定義されるかは認証局に確認してください。
- サブジェクトの値はX.501識別名(DN: Distinguished Name)形式になっています。
- メールアドレスはサブジェクト代替名で定義することが推奨されています。
- 以前はサブジェクトで定義されていましたが、RFC 3850から次のようにサブジェクト代替名で定義することが推奨されています。
3. Using Distinguished Names for Internet Mail
End-entity certificates MAY contain an Internet mail address as
described in [RFC-2822]. The address must be an "addr-spec" as
defined in Section 3.4.1 of that specification. The email address
SHOULD be in the subjectAltName extension, and SHOULD NOT be in the
subject distinguished name. - サブジェクトでメールアドレス(相対識別名E, EMAILADDRESS)を指定することもできますが、基になっている仕様(RFC)を確認できませんでした。
試しにサブジェクトにメールアドレスを指定すると”1.2.840.113549.1.9.1″になります。PKCS#9のRFC2985で定義されるOIDを使用するようです。 - サブジェクトで定義したメールアドレスはOID:1.2.840.113549.1.9.1の値として保持されていますが、実行環境によってはフィールド名がEやEMAILADDRESSになる場合があります。一般的なAPIでは、このような違いを吸収した値の取得が可能ですが、文字列化したサブジェクト値から正規表現等でメールアドレスを抽出するような処理では注意が必要です。
- 以前はサブジェクトで定義されていましたが、RFC 3850から次のようにサブジェクト代替名で定義することが推奨されています。
- サブジェクト代替名では、メールアドレス(rfc822Name)、UPN:User Principal Name(otherNameの一つ)、ディレクトリ名(directoryName)等からユーザ情報を取得できます。123456789101112SubjectAltName ::= GeneralNamesGeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralNameGeneralName ::= CHOICE {otherName [0] OtherName,rfc822Name [1] IA5String,dNSName [2] IA5String,x400Address [3] ORAddress,directoryName [4] Name,ediPartyName [5] EDIPartyName,uniformResourceIdentifier [6] IA5String,iPAddress [7] OCTET STRING,registeredID [8] OBJECT IDENTIFIER }