11と12のリビジョン間の差分
2019-05-08 17:20:23時点のリビジョン11
サイズ: 29235
コメント:
2019-05-08 17:32:40時点のリビジョン12
サイズ: 29316
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 1: 行 1:
## page was renamed from certificate/俺々SSLサーバー証明書の作り方

俺々SSLサーバー証明書の作り方

  • 「ぼくがかんがえたさいきょうの」自己署名証明書の基本的な作り方について解説する。
  • どれくらい「さいきょう」かというと、可能な限り実在する認証局(Certification Authority)で行ってるパラメータの再現を目指す。
  • とは言え、このパラメータはEV(Extended Validatation)はおろか、OV(Organization Validation)のパラメータは含まない。
  • これは証明書のパラメータというよりは、ブラウザ側の問題であるためである。
  • そのあたりも含め、俺々認証局を作るのにも必要な基本的な技術を解説する。
  • もちろん実運用的には、イントラネット内に閉じた環境のSSLサーバー証明書の運用など、実務でも使うことがある。
  • サーバー証明書内で閉じない内容があるので、以下の点(拡張)については対応しない。
    • X509v3 Certificate Policies
    • X509v3 CRL Distribution Points
    • Authority Information Access
    • X509v3 Certificate Extension(oid=1.3.6.1.4.1.11129.2.4.2, Signed Certificate Timestamp)
  • 以下の拡張についてはEV、OVに関わる部分なので調査だけはしてみた。
    • X509v3 Certificate Policies
  • 対インターネット向けなら、Let's Encryptはもちろんのこと、年額1000円~2000円程度の認証局があるので、そちらを利用されたし。

ディスティングイッシュ名(Distinguished Name)を決める

  • DN(Distinguished Name)は「属性=属性値」をつなげた「識別子」のことである。
  • いわゆる俺々SSLサーバー証明書の場合、コモンネーム(CN)以外は本質的に必要ない。
  • 実運用上は管理責任の明確化のために、組織名(O)や部門名(OU)を加えるべきと考える。
  • またその場合、国名(C)、都道府県(ST)、市区町村(L)を含めるべきかと。
  • また、ワイルドカード証明書を作りたい場合も、同一手順で問題無い。
  • SAN(Subject Alternative Name・あるいは複数指定する場合は SANs / Name → Names)を行いたい場合は、もう少し手順が必要となる。
  • ここではSANするために、自身のドメイン(下記例に対して ninth-nine.com のこと)を付与してみる:-)。
  • SAN自体はDNに含まれない(「拡張」として付与)。

属性名

略号

設定例

備考

国名(Country name)

C

JP

都道府県名(STate or province name)

ST

市区町村(Locality name)

L

組織名(Organization name)

O

部門名(Organization Unit name)

OU

コモンネーム(Common Name)

CN

*.ninth-nine.com

メールアドレス(emailAddress)

emailAddress

上記をまとめたのが下記の通りとなる。省略した項目は項目名から省略する(一切残さない)。

/C=JP/CN=*.ninth-nine.com

カスタムopenssl.cnfの準備

OS標準のopenssl.cnfは微妙に微妙なので、カスタマイズしたものを用意する。-configオプションにして指定する。 このファイルは典型的な ini ファイルなので、以下の構造を持つ。

[セクション名]
項目 = 値
 :

関連セクション・項目一覧

req セクション(必須)

項目名

意味

オプション

必須

備考

distinguished_name

セクション名

ディスティングイッシュ名セクションの指定

なし

必須

attributes

セクション名

属性セクションの指定

なし

オプション

通常不要

x509_extensions

セクション名

署名拡張セクションの指定

-extensions セクション名

オプション

req_extensions

セクション名

要求拡張セクションの指定

-reqexts セクション名

オプション

本件では不要

default_md

sha1 / sha256 等

署名アルゴリズムの指定

-sha / -sha256 等

オプション

指定が無い場合 -sha などに解釈

default_bits

数字

ビット数

なし

必須

何の?公開鍵暗号アルゴリズムによる

default_keyfile

パス名

秘密鍵のファイル名

-keyout パス名

オプション

指定が無い場合標準出力へ

RANDFILE

パス名

乱数シードのファイル名

-rand パス名

オプション

厳密には RANDFILE と -rand は違う

input_password

パスワード

指定された秘密鍵のパスワード

-passin パスワード

オプション

事前に秘密鍵は作らないので不要

output_password

パスワード

保存する秘密鍵のパスワード

-passout パスワード

オプション

パスワード保護しないので指定しない

encrypt_rsa_key

no

秘密鍵を3DES暗号化するかどうか

-nodes

オプション

encrypt_key と同義(compat)

encrypt_key

no

秘密鍵を3DES暗号化するかどうか

-nodes

オプション

3DES以外の選択肢無し

prompt

no

プロンプトを表示するかどうか

なし

オプション

string_mask

default

特定フィールドの文字列型で使用

なし

必須

utf8only

pkix

nombstr

WARNING

MASK:値

utf8

yes

UTF8 文字列を解釈する

-utf8

オプション

未指定の場合 ASCII

distinguished_name セクション(必須)

-subj ~オプションで必要な項目を指定するため、本セクションでの指定は無い。 ただし、セクション名自体は存在する必要がある。

x509_extensions セクション(オプション)

項目名

意味

備考

subjectKeyIdentifier

hash

authorityKeyIdentifier

keyid

keyid:always

issuer

basicConstraints

CA:FALSE

CA機能無し

CA:TRUE

CA機能有り

pathlen:0~

認証チェインの深さ(0 は子供のみ、1 は孫まで、2 ...)

nsCertType

client

クライアント証明書

server

サーバー証明書

email

メール証明書(S/MIME)

objsign

オブジェクト(コード)サイニング

sslCA

認証局

emailCA

メール認証局

objCA

オブジェクトサイニング認証局

keyUsage

digitalSignature

デジタル署名

nonRepudiation

否認不可

keyEncipherment

鍵交換

dataEncipherment

データ交換

keyAgreement

keyCertSign

cRLSign

encipherOnly

暗号化のみ

decipherOnly

複合化のみ

extendedKeyUsage

serverAuth

SSL/TLS Web Server Authentication.

clientAuth

SSL/TLS Web Client Authentication.

codeSigning

Code signing.

emailProtection

E-mail Protection (S/MIME).

timeStamping

Trusted Timestamping

msCodeInd

Microsoft Individual Code Signing (authenticode)

msCodeCom

Microsoft Commercial Code Signing (authenticode)

msCTLSign

Microsoft Trust List Signing

msSGC

Microsoft Server Gated Crypto

msEFS

Microsoft Encrypted File System

nsSGC

Netscape Server Gated Crypto

subjectAltName

DNS.n:ドメイン名

「拡張」で指定する値には「,」(カンマ)や「 」(空白)などを「直接」含めることができない。 下記の例のように間接的に指定する方法があるが、SANsの指定の場合、ドメイン名しか使わないので、セクション分けまでする必要は無い(どちらも同じ意味ではあるが)。

subjectAltName = DNS.1:*.ninth-nine.com, DNS.2:ninth-nine.com

subjectAltName = @altnames

[altnames]
DNS.1          = *.ninth-nine.com
DNS.2          = ninth-nine.com

設定ファイル(例)

[req]
distinguished_name = distinguished_name
x509_extensions    = x509_extensions
string_mask        = utf8only

[distinguished_name]

[x509_extensions]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints       = critical,CA:FALSE
nsCertType             = server
keyUsage               = digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth
nsComment              = "OpenSSL Generated Certificate"
subjectAltName         = DNS.1:*.ninth-nine.com, DNS.2:ninth-nine.com

自己署名証明書の作り方(RSA)

opensslコマンドのオプションは長いので複数行に分割している。実際の実行は、1行(改行無し)で記述すること。

openssl req
   -newkey rsa:2048
   -sha256
   -nodes
   -subj   "/C=JP/CN=*.ninth-nine.com"
   -out    "/ssl/*.ninth-nine.com/*.ninth-nine.com,rsa2048-sha256,201601-201912,0.crt"
   -keyout "/ssl/*.ninth-nine.com/*.ninth-nine.com,rsa2048-sha256,201601-201912,0.key"
   -x509
     -startdate "160101000000Z"
     -enddate   "191231235959Z"
   -config 設定ファイル
  • 古いopensslコマンドだと-sha256オプションでエラーになることがある。その場合は-sha1で代用すること。ただし、本ケースで全くお勧めしない。

  • -startdate ~ -enddate ~は全ての環境でエラーになる。#パッチを当てられない環境では-days ~オプションに置き換えること。

実行結果例(RSA)

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 13066507578601016103 (0xb5558f69d5768b27)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, CN=*.ninth-nine.com
        Validity
            Not Before: Jan  1 00:00:00 2016 GMT
            Not After : Dec 31 23:59:59 2019 GMT
        Subject: C=JP, CN=*.ninth-nine.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:9e:c3:6e:6c:84:97:9a:17:d7:46:05:69:d2:7d:
                    65:0b:87:11:6e:65:af:dd:bf:b3:92:fe:df:32:b3:
                    84:c6:22:30:64:d0:90:17:93:6d:7e:77:4b:0a:86:
                    51:1b:c4:57:55:3b:e0:1c:63:e9:b3:d8:dd:bb:d8:
                    ae:58:3d:4b:34:98:4e:73:a5:9c:72:bb:18:51:df:
                    5b:f8:48:b3:3f:21:7f:73:9e:98:96:46:af:7d:29:
                    08:d5:8f:a8:0e:fc:18:6a:f1:09:4d:b6:36:17:76:
                    1f:0a:f4:9f:bb:b2:ea:50:9c:06:3c:30:58:76:b4:
                    27:e4:97:3c:bb:13:3b:24:d0:d1:a2:b5:08:29:ba:
                    da:f4:fa:fc:15:1e:73:11:1e:6b:9b:07:14:25:cd:
                    6b:6d:28:d0:45:85:63:69:3f:78:a7:bf:73:cd:98:
                    c1:c0:ba:79:a3:08:64:37:70:12:2e:11:b0:d7:34:
                    38:bd:cf:fc:d0:f5:f4:21:21:77:5b:36:d9:fd:cb:
                    ea:67:8c:7c:83:1e:62:6d:d1:50:e9:bb:70:c3:36:
                    46:c6:31:c0:a5:63:5a:92:4b:fe:3c:7f:de:39:ed:
                    08:ca:51:3a:f7:c7:b4:e1:b3:a5:d5:7f:b1:9c:27:
                    25:fc:6c:93:b6:84:4e:30:d8:eb:02:3a:24:c2:cc:
                    b9:25
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                67:E8:B1:6F:D0:19:1A:B7:39:45:4A:83:60:39:89:73:D6:D1:0D:FD
            X509v3 Authority Key Identifier:
                keyid:67:E8:B1:6F:D0:19:1A:B7:39:45:4A:83:60:39:89:73:D6:D1:0D:FD

            X509v3 Basic Constraints: critical
                CA:FALSE
            Netscape Cert Type:
                SSL Server
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Alternative Name:
                DNS:*.ninth-nine.com, DNS:ninth-nine.com
    Signature Algorithm: sha256WithRSAEncryption
         06:f2:8e:7d:cd:78:37:b7:34:ca:fe:b2:47:13:a7:02:98:fe:
         78:8a:e3:02:d8:15:45:12:75:6b:30:7a:15:c1:0d:e1:22:55:
         56:e2:42:18:ca:d2:0d:c6:29:ac:b7:e3:e0:96:ca:58:5f:8a:
         06:de:bf:68:cb:d0:f2:a4:49:6f:33:9e:f3:0d:c9:4c:28:9a:
         59:d7:28:78:11:44:f5:b1:6f:b2:ad:00:d9:e3:53:42:f4:d5:
         5e:1a:43:43:2b:f5:f9:94:bb:d6:cd:36:a2:b8:71:b7:17:e9:
         0c:83:29:6f:d8:16:43:24:45:8d:44:a8:5c:97:27:63:36:1e:
         94:75:c1:3c:f0:d8:b4:9b:64:1f:cf:c8:f9:b7:e2:19:6a:ff:
         1b:f9:b5:75:82:08:3c:43:bf:23:28:1e:4b:11:ba:52:bb:ff:
         d9:62:3b:7b:06:ef:6c:c6:63:4f:a8:41:ae:17:87:74:93:28:
         68:94:0b:e7:01:79:43:43:cd:0a:ca:d4:84:94:bb:c2:89:3c:
         6e:35:97:97:05:72:55:c9:9f:07:c4:79:82:8e:c7:60:4b:52:
         a0:97:cd:22:6e:40:61:10:d4:84:14:d4:4d:24:c1:e7:25:08:
         4b:97:a9:d2:dd:50:62:c7:ac:24:5a:c3:41:ba:ee:72:e8:1d:
         6a:c5:1a:dc

自己署名証明書の作り方(ECDSA)

opensslコマンドのオプションは長いので複数行に分割している。実際の実行は、1行(改行無し)で記述すること。

openssl req
   -newkey ec:<(openssl ecparam -name prime256v1)
   -sha256
   -nodes
   -subj   "/C=JP/CN=*.ninth-nine.com"
   -out    "/ssl/*.ninth-nine.com/*.ninth-nine.com,prime256v1-sha256,201601-201912,0.crt"
   -keyout "/ssl/*.ninth-nine.com/*.ninth-nine.com,prime256v1-sha256,201601-201912,0.key"
   -x509
     -startdate "160101000000Z"
     -enddate   "191231235959Z"
   -config 設定ファイル
  • 古いopensslコマンドだと-sha256オプションでエラーになることがある。その場合は-sha1で代用すること。ただし、あまりお勧めしない。

  • -startdate ~ -enddate ~は全ての環境でエラーになる。#パッチを当てられない環境では-days ~オプションに置き換えること。

  • <(コマンド) というイディオム(実行結果をテンポラリファイル名で渡してくれる機能)は zsh/bash 拡張なので、それ以外のシェル(sh/ash/ksh/csh/tcsh 等)では指定しないこと。

実行結果例(ECDSA)

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 15898934856903028020 (0xdca45d0424c7ed34)
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=JP, CN=*.ninth-nine.com
        Validity
            Not Before: Jan  1 00:00:00 2016 GMT
            Not After : Dec 31 23:59:59 2019 GMT
        Subject: C=JP, CN=*.ninth-nine.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:03:38:d7:62:50:7b:9b:0b:2d:9f:45:67:6d:8e:
                    af:e1:55:d6:1e:30:65:cd:97:0a:29:15:38:7a:2d:
                    fa:da:f1:48:e8:5b:b6:16:04:c7:6c:6f:0e:18:bb:
                    cf:e8:aa:82:66:66:89:79:bd:b8:94:e2:68:d1:43:
                    5b:1e:d4:49:dd
                ASN1 OID: prime256v1
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                32:98:80:2B:82:8F:F2:6F:4D:D5:D7:08:D9:0F:E5:CB:A0:E4:DA:99
            X509v3 Authority Key Identifier:
                keyid:32:98:80:2B:82:8F:F2:6F:4D:D5:D7:08:D9:0F:E5:CB:A0:E4:DA:99

            X509v3 Basic Constraints: critical
                CA:FALSE
            Netscape Cert Type:
                SSL Server
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Alternative Name:
                DNS:*.ninth-nine.com, DNS:ninth-nine.com
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:21:00:c1:a5:7a:be:fb:cb:d7:ba:77:87:92:85:8e:
         bc:0a:f8:79:4e:30:f5:0c:2c:e8:54:c8:7c:4a:d5:8c:2d:38:
         9a:02:20:19:f8:83:b9:71:0e:bf:ba:9d:13:08:38:b6:93:78:
         f2:c2:0a:8d:75:58:fe:ae:38:94:cd:04:fa:01:fe:80:a1

Appendix

X509v3 Certificate Policies に関する考察

シマンテックの Global ID/Server ID EV SSL(要は Symantec Class 3 EV SSL CA - G3 ね)証明書を分析した結果についてメモっておく。

X509v3 Certificate Policies:
    Policy: 2.16.840.1.113733.1.7.23.6
      CPS: https://d.symcb.com/cps
      User Notice:
        Explicit Text: https://d.symcb.com/rpa

※なお、この設定を入れたところでEV SSL証明書にはならんので注意。DV SSL証明書扱いとなります。

先の設定ファイルの x509_extentions セクションに下記のように設定を追加してやると、上記と同じ結果が得られる。

[x509_extensions]
certificatePolicies    = @policies

[policies]
policyIdentifier       = 2.16.840.1.113733.1.7.23.6
CPS.1                  = https://d.symcb.com/cps
userNotice.1           = @notice

[notice]
explicitText           = https://d.symcb.com/rpa
  • 色々試したところ certificatePolicies の行に「直接」必要なパラメータを埋め込むことはできず「@セクション名」で取り込む必要があった。
  • policyIdentifierの一覧についてはEV証明書の特定が詳しい。

パッチ

  • FreeBSD 10.3-RELEASEの openssl コマンド(1.0.1s)に以下のパッチを当てる。
  • このパッチはreq(1)に-startdate-enddateオプションを与えるパッチである。

  • パッチを当てられないほとんどの環境では-startdate ~ -enddate ~オプションの代わりに-days ~オプションを指定すること。

   1 Index: crypto/openssl/apps/req.c
   2 ===================================================================
   3 --- crypto/openssl/apps/req.c   (revision 298785)
   4 +++ crypto/openssl/apps/req.c   (working copy)
   5 @@ -126,6 +126,8 @@
   6   * -x509        - output a self signed X509 structure instead.
   7   * -asn1-kludge - output new certificate request in a format that some CA's
   8   *                require.  This format is wrong
   9 + * -startdate  - notBefore field
  10 + * -enddate    - notAfter field
  11   */
  12 
  13  static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn,
  14 @@ -179,6 +181,7 @@
  15      int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0;
  16      char *infile, *outfile, *prog, *keyfile = NULL, *template =
  17          NULL, *keyout = NULL;
  18 +    char *startdate=NULL,*enddate=NULL;
  19  #ifndef OPENSSL_NO_ENGINE
  20      char *engine = NULL;
  21  #endif
  22 @@ -364,6 +367,14 @@
  23              if (--argc < 1)
  24                  goto bad;
  25              req_exts = *(++argv);
  26 +        } else if (strcmp(*argv,"-startdate") == 0) {
  27 +            if (--argc < 1)
  28 +                 goto bad;
  29 +            startdate= *(++argv);
  30 +        } else if (strcmp(*argv,"-enddate") == 0) {
  31 +            if (--argc < 1)
  32 +                 goto bad;
  33 +            enddate= *(++argv);
  34          } else if ((md_alg = EVP_get_digestbyname(&((*argv)[1]))) != NULL) {
  35              /* ok */
  36              digest = md_alg;
  37 @@ -428,6 +439,10 @@
  38          BIO_printf(bio_err,
  39                     " -days          number of days a certificate generated by -x509 is valid for.\n");
  40          BIO_printf(bio_err,
  41 +                   " -startdate     certificate validity notBefore - YYMMDDHHMMSSZ.\n");
  42 +        BIO_printf(bio_err,
  43 +                   " -enddate       certificate validity notAfter - YYMMDDHHMMSSZ.\n");
  44 +        BIO_printf(bio_err,
  45                     " -set_serial    serial number to use for a certificate generated by -x509.\n");
  46          BIO_printf(bio_err,
  47                     " -newhdr        output \"NEW\" in the header lines\n");
  48 @@ -796,13 +811,26 @@
  49                  if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
  50                      goto end;
  51              }
  52 -
  53 +            if (startdate == NULL) {
  54 +                if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
  55 +                    goto end;
  56 +            } else {
  57 +                if (!ASN1_UTCTIME_set_string(X509_get_notBefore(x509ss), startdate)) {
  58 +                    BIO_printf(bio_err, "start date is invalid, it should be YYMMDDHHMMSSZ\n");
  59 +                    goto end;
  60 +                }
  61 +            }
  62 +            if (enddate == NULL) {
  63 +                if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL))
  64 +                    goto end;
  65 +            } else {
  66 +                if (!ASN1_UTCTIME_set_string(X509_get_notAfter(x509ss), enddate)) {
  67 +                    BIO_printf(bio_err, "end date is invalid, it should be YYMMDDHHMMSSZ\n");
  68 +                    goto end;
  69 +                }
  70 +            }
  71              if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
  72                  goto end;
  73 -            if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
  74 -                goto end;
  75 -            if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL))
  76 -                goto end;
  77              if (!X509_set_subject_name
  78                  (x509ss, X509_REQ_get_subject_name(req)))
  79                  goto end;

参考文献

certificate/俺々SSLサーバー証明書の作り方 (最終更新日時 2019-05-08 17:32:40 更新者 NorikatsuShigemura)