トップ 一覧 検索 ヘルプ RSS ログイン

OpenSSL Command-Line HOWTOの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
*http://www.madboa.com/geek/openssl/
*Paul Heinlein <heinlein@madboa.com>

*Initial publication: June 13, 2004 
*初版: 2004年 6月 13日
*Last updated on September 13, 2016
*最新版: 2016年 9月 13日
*openssl コマンドは OpenSSL ライブラリに含まれるコマンドで、様々な暗号に関する作業ができます。この HOWTO ではこのコマンドを紹介します。

{{outline}}
!!!概要
openssl コマンドは、様々な暗号に関する作業ができる OpenSSL ライブラリに付属のコマンドです。スクリプトやその場限りのコマンド入力作業で役に立ちます。

openssl コマンド使用法のドキュメントはいくぶん分散しがちですが、この文書は実用的な使用法を提供することを目的としています。OpenSSL のインストールについては完了し、パスが通っていることを前提とします。

この文書では実用的な使用例しか提供しません。暗号化の理論や概念には触れません。MD5ハッシュがわからなければ、この文書はまったく役に立たないでしょう。openssl を使ってファイルのハッシュを作りたいのであれば、この文書がそうです。

この文書では新しい使用例をどんどん追加していくつもりです。必要な情報がなくても、しばらく後に見てみてもいいでしょう。

!!OpenSSL のバージョンを知りたい
version を指示しましょう。

 $ openssl version
 OpenSSL 1.0.1e-fips 11 Feb 2013

-a オプションをつけるともっと情報を得られます。

 $ openssl version -a
 OpenSSL 1.0.1e-fips 11 Feb 2013
 built on: Thu Jul 23 19:06:35 UTC 2015
 platform: linux-x86_64
 options:  bn(64,64) md2(int) rc4(16x,int) des(idx,cisc,16,int)
           idea(int) blowfish(idx)
 compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT
 -DDSO_DLFCN -DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -DTERMIO
 -Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions
 -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic
 -Wa,--noexecstack -DPURIFY -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT
 -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM
 -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM
 -DWHIRLPOOL_ASM -DGHASH_ASM
 OPENSSLDIR: "/etc/pki/tls"
 engines:  rdrand dynamic

!!使用できる命令を知りたい
3つのコマンドが利用可能なコマンド一覧を表示しますが、役に立つものはひとつも無いと思います。無効なコマンド(help や -h)が最も役に立ちます。

 $ openssl help
 openssl:Error: 'help' is an invalid command.
 
 Standard commands
 asn1parse         ca                ciphers           cms
 crl               crl2pkcs7         dgst              dh
 dhparam           dsa               dsaparam          ec
 ecparam           enc               engine            errstr
 gendh             gendsa            genpkey           genrsa
 nseq              ocsp              passwd            pkcs12
 pkcs7             pkcs8             pkey              pkeyparam
 pkeyutl           prime             rand              req
 rsa               rsautl            s_client          s_server
 s_time            sess_id           smime             speed
 spkac             ts                verify            version
 x509
 
 Message Digest commands (see the `dgst' command for more details)
 md2               md4               md5               rmd160
 sha               sha1
 
 Cipher commands (see the `enc' command for more details)
 aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb
 aes-256-cbc       aes-256-ecb       base64            bf
 bf-cbc            bf-cfb            bf-ecb            bf-ofb
 camellia-128-cbc  camellia-128-ecb  camellia-192-cbc  camellia-192-ecb
 camellia-256-cbc  camellia-256-ecb  cast              cast-cbc
 cast5-cbc         cast5-cfb         cast5-ecb         cast5-ofb
 des               des-cbc           des-cfb           des-ecb
 des-ede           des-ede-cbc       des-ede-cfb       des-ede-ofb
 des-ede3          des-ede3-cbc      des-ede3-cfb      des-ede3-ofb
 des-ofb           des3              desx              idea
 idea-cbc          idea-cfb          idea-ecb          idea-ofb
 rc2               rc2-40-cbc        rc2-64-cbc        rc2-cbc
 rc2-cfb           rc2-ecb           rc2-ofb           rc4
 rc4-40            seed              seed-cbc          seed-cfb
 seed-ecb          seed-ofb          zlib

!!いわゆる shell での"標準コマンド"のオプションには何が使えますか?

どのサブコマンドでも同じ手が使えます。

 $ openssl dgst -h
 unknown option '-h'
 options are
 -c              to output the digest with separating colons
 -r              to output the digest in coreutils format
 -d              to output debug info
 -hex            output as hex dump
 -binary         output in binary form
 -sign   file    sign digest using private key in file
 -verify file    verify a signature using public key in file
 -prverify file  verify a signature using private key in file
 -keyform arg    key file format (PEM or ENGINE)
 -out filename   output to filename rather than stdout
 -signature file signature to verify
 -sigopt nm:v    signature parameter
 -hmac key       create hashed MAC with key
 -mac algorithm  create MAC (not neccessarily HMAC)
 -macopt nm:v    MAC algorithm parameters or key
 -engine e       use engine e, possibly a hardware device.
 -md4            to use the md4 message digest algorithm
 -md5            to use the md5 message digest algorithm
 -ripemd160      to use the ripemd160 message digest algorithm
 -sha            to use the sha message digest algorithm
 -sha1           to use the sha1 message digest algorithm
 -sha224         to use the sha224 message digest algorithm
 -sha256         to use the sha256 message digest algorithm
 -sha384         to use the sha384 message digest algorithm
 -sha512         to use the sha512 message digest algorithm
 -whirlpool      to use the whirlpool message digest algorithm


古臭いやり方ですが OpenSSL の man も使えます。

!!使用可能な暗号化方法の一覧が欲しい。
ciphers オプションを使いましょう。ciphers(1) マニュアルも、とても役に立ちます。

*使用可能な暗号化方法の一覧
 openssl ciphers -v

*TLSv1 の暗号化方法の一覧
 openssl ciphers -v -tls1

*高度(128ビット以上)暗号化方法の一覧
 openssl ciphers -v 'HIGH'

*高度(128ビット以上)かつAES方式の暗号化方法の一覧
 openssl ciphers -v 'AES+HIGH'

!!!ベンチマーク(スピード測定)

!!システムのスピードを測定するには?
OpenSSL開発者は一連のスピード測定用のコードを openssl コマンドに用意しました。
speed オプションで使用できます。一定の作業をどれぐらいの時間で完了するかではなく、一定の時間内にどれぐらい暗号化操作を実行できるかを測定します。遅いシステムでも早いシステムでも同じ時間をかけるのは、極めてまっとうな測定方法ではないでしょうか。

全てのスピードを測定するにはオプションなしで実行してください。

 openssl speed

2つの結果が得られます。
最初の数値はそれぞれのアルゴリズムで毎秒何バイトを処理できるかを示します。
2つ目の数値は署名と検証のサイクルに必要な秒数を示します。
ここでは 2.16GHz の Intel Core 2 での結果を示します。
ここでは 2.70GHz Intel Xeon E5 での結果を示します。

 The 'numbers' are in 1000s of bytes per second processed.
 type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
 md2               1736.10k     3726.08k     5165.04k     5692.28k     5917.35k
 mdc2                 0.00         0.00         0.00         0.00         0.00 
 md4              18799.87k    65848.23k   187776.43k   352258.73k   474622.63k
 md5              16807.01k    58256.45k   160439.13k   287183.53k   375220.91k
 hmac(md5)        23601.24k    74405.08k   189993.05k   309777.75k   379431.59k
 sha1             16774.59k    55500.39k   142628.69k   233247.74k   288382.98k
 rmd160           13854.71k    40271.23k    87613.95k   124333.06k   141781.67k
 rc4             227935.60k   253366.06k   261236.94k   259858.09k   194928.50k
 des cbc          48478.10k    49616.16k    49765.21k    50106.71k    50034.01k
 des ede3         18387.39k    18631.02k    18699.26k    18738.18k    18718.72k
 idea cbc             0.00         0.00         0.00         0.00         0.00 
 rc2 cbc          19247.24k    19838.12k    19904.51k    19925.33k    19834.98k
 rc5-32/12 cbc        0.00         0.00         0.00         0.00         0.00 
 blowfish cbc     79577.50k    83067.03k    84676.78k    84850.01k    85063.00k
 cast cbc         45362.14k    48343.34k    49007.36k    49202.52k    49225.73k
 aes-128 cbc      58751.94k    94443.86k   111424.09k   116704.26k   117997.57k
 aes-192 cbc      53451.79k    82076.22k    94609.83k    98496.85k    99150.51k
 aes-256 cbc      49225.21k    72779.84k    82266.88k    85054.81k    85762.05k
 sha256            9359.24k    22510.83k    40963.75k    51710.29k    56014.17k
 sha512            7026.78k    28121.32k    54330.79k    86190.76k   104270.51k
 md2               2540.48k     5184.66k     6989.57k     7651.67k     7872.51k
 mdc2                 0.00         0.00         0.00         0.00         0.00
 md4              83248.41k   261068.18k   624212.82k   940529.32k  1128846.68k
 md5              62411.57k   184768.36k   408835.75k   586930.52k   678061.98k
 hmac(md5)        48713.62k   148265.56k   359626.67k   563050.68k   670255.79k
 sha1             68829.72k   195087.40k   431001.51k   623344.42k   729505.79k
 rmd160           38598.59k    96226.86k   183336.45k   235962.71k   257526.44k
 rc4             480093.57k   678565.35k   783765.42k   818297.51k   838205.99k
 des cbc          69500.17k    71184.75k    71491.50k    71641.77k    72010.15k
 des ede3         26433.63k    26717.01k    26772.99k    26788.18k    26907.57k
 idea cbc         95690.28k    99334.17k   100835.40k   100787.54k   100900.86k
 seed cbc         76871.40k    77238.46k    77736.50k    77452.97k    77545.47k
 rc2 cbc          48984.63k    49589.03k    50188.07k    50103.98k    50066.77k
 rc5-32/12 cbc        0.00         0.00         0.00         0.00         0.00
 blowfish cbc    122583.30k   129550.92k   130876.67k   131111.94k   131394.22k
 cast cbc        109471.38k   114523.31k   115934.46k   116200.45k   116331.86k
 aes-128 cbc     128352.23k   138604.76k   141173.42k   142832.25k   142682.79k
 aes-192 cbc     107703.93k   114456.79k   117716.65k   118847.36k   118784.00k
 aes-256 cbc      93374.87k    99521.51k   101198.51k   101382.49k   101635.41k
 camellia-128 cbc    99270.57k   150412.42k   170346.33k   176311.91k   177913.86k
 camellia-192 cbc    85896.60k   117356.52k   128556.97k   132759.72k   133425.83k
 camellia-256 cbc    87351.27k   117695.15k   128972.03k   132130.47k   133455.87k
 sha256           52372.61k   117766.12k   204825.69k   249974.10k   270914.90k
 sha512           41278.19k   165820.37k   258298.69k   365981.70k   419864.58k
 whirlpool        24803.02k    53047.07k    87593.90k   104570.54k   111159.98k
 aes-128 ige     128441.31k   132981.88k   133269.08k   133738.15k   133966.51k
 aes-192 ige     107831.37k   111507.07k   111800.66k   112156.67k   112219.48k
 aes-256 ige      94382.07k    96351.17k    96750.68k    96958.46k    97446.44k
 ghash           888644.92k  1452788.80k  1696788.74k  1763055.96k  1799086.49k
                   sign    verify    sign/s verify/s
 rsa  512 bits 0.000522s 0.000042s   1915.8  23969.9
 rsa 1024 bits 0.002321s 0.000109s    430.8   9191.1
 rsa 2048 bits 0.012883s 0.000329s     77.6   3039.6
 rsa 4096 bits 0.079055s 0.001074s     12.6    931.3
 rsa  512 bits 0.000049s 0.000004s  20547.1 248266.2
 rsa 1024 bits 0.000194s 0.000011s   5146.0  90735.4
 rsa 2048 bits 0.001194s 0.000037s    837.3  27277.1
 rsa 4096 bits 0.008560s 0.000137s    116.8   7324.5
                   sign    verify    sign/s verify/s
 dsa  512 bits 0.000380s 0.000472s   2629.3   2117.9
 dsa 1024 bits 0.001031s 0.001240s    969.6    806.2
 dsa 2048 bits 0.003175s 0.003744s    314.9    267.1
 dsa  512 bits 0.000048s 0.000046s  20667.7  21701.8
 dsa 1024 bits 0.000113s 0.000126s   8831.9   7951.8
 dsa 2048 bits 0.000362s 0.000430s   2762.0   2322.9
                               sign    verify    sign/s verify/s
  256 bit ecdsa (nistp256)   0.0001s   0.0004s   9856.1   2524.4
  384 bit ecdsa (nistp384)   0.0002s   0.0008s   5103.6   1191.7
  521 bit ecdsa (nistp521)   0.0004s   0.0018s   2679.0    550.3
                              op      op/s
  256 bit ecdh (nistp256)   0.0003s   3063.8
  384 bit ecdh (nistp384)   0.0007s   1447.3
  521 bit ecdh (nistp521)   0.0015s    666.2

指定の暗号化アルゴリズムでのスピードも測定できます。

*rsaの測定
 openssl speed rsa

*2CPUシステムでの同じテスト
 openssl speed rsa -multi 2

!!暗号化通信のスピードを測定するには?
s_time オプションで暗号化通信のスピードを測定できます。
何も指定しないと30秒間実行します。
どの暗号化方式でもSSLバージョンでも、SSL接続の新規接続と再利用での1秒あたりの接続数を測定します。

 openssl s_time -connect remote.host:443

s_time は他に様々なオプションを指定できます。

*毎回新しい接続を生成しながら test.html を取得するテスト
 openssl s_time -connect remote.host:443 -www /test.html -new

*SSLv3と高暗号化を条件に追加
 openssl s_time \
  -connect remote.host:443 -www /test.html -new \
  -ssl3 -cipher HIGH
*様々な暗号化方法を10秒間のテストで相対的に比較する。
 IFS=":"
 for c in $(openssl ciphers -ssl3 RSA); do
   echo $c
   openssl s_time -connect remote.host:443 \
     -www / -new -time 10 -cipher $c 2>&1 | \
     grep bytes
   echo
 done

SSLが使えるwebサーバがなければ、s_server オプションを使ってサーバを代行できます。

*あるサーバで ssl サーバを立ち上げます。(デフォルトで4433番ポート)
 openssl s_server -cert mycert.pem -www

*2番目のホストで(上と同じサーバでもかまいません) s_time を実行します。
 openssl s_time -connect myhost:4433 -www / -new -ssl3

!!!証明書
!!自己署名証明書を作りたい。
まず最初に、鍵ファイルを暗号化するかどうかを決定する必要があります。暗号化する場合はパスフレーズで守られます。

良い点としては、パスフレーズで守ることは安全だと言うことです。鍵ファイルを盗もうとする人にとっては価値がありません。悪い点としては、web サーバや LDAP サーバを起動するたびにパスフレーズを入力する必要がある、ということです。

セキュリティに強迫観念を持つ自分の精神に反しますが、自分は暗号化しないほうがいいと思います。そうすると鍵ファイルを使用するサービスが開始するときにパスフレーズを手入力する必要はありません。(あとで鍵ファイルの暗号化を解除するのはそんなに難しくはありません)

以下の例は秘密鍵と公開署名を持つ mycert.pem というファイルを作成します。
公開署名は365日の有効期限を持ちます。また、鍵ファイルは(-nodesオプションを使って)暗号化されていません。

 openssl req \
   -x509 -nodes -days 365 \
   -newkey rsa:1024 -keyout mycert.pem -out mycert.pem

このコマンド起動では、たくさんの質問に答える必要があります。国、州、都市名など。問題になる質問は「Common Name」です。これにはホスト名かみんなが使うCNAMEを入力しましょう。ここが重要です。ホスト名が mybox.mydomain.com で、みんなが使用する名称が www.mydomain.com なら、「Common Name」の質問には「www.mydomain.com」を答えてください。

質問への入力が完了したなら、全ての答えをスクリプトに -subj オプションで与えることもできます。下の例には地理情報を加えた例を示しますが、これらの中で重要なのはホスト名(CN)だけです。

 openssl req \
   -x509 -nodes -days 365 \
   -subj '/C=US/ST=Oregon/L=Portland/CN=www.madboa.com' \
   -newkey rsa:1024 -keyout mycert.pem -out mycert.pem

!!VeriSign用の署名要求はどうやって作る?
一般に証明書発行業者として認知されている VeriSign のような会社に署名を申請することは複雑で官僚的な作業です。署名要求を出す前に全ての必要な書類を用意する必要があります。

自己署名証明書のレシピの場合と同じように、秘密鍵をパスフレーズで保護するかどうかを決める必要があります。下の例は保護しない例です。mykey.pem という秘密鍵ファイルと myreq.pem という署名要求ファイルの2つのファイルが生成されます。

 openssl req \
  -new -newkey rsa:1024 -nodes \
  -keyout mykey.pem -out myreq.pem

すでに鍵ファイルがあり、その鍵ファイルで署名要求を出す場合はもう少し簡単です。

 openssl req -new -key mykey.pem -out myreq.pem

同様に、鍵ファイルの目的情報をコマンドオプションで指定できます。

 openssl req \
  -new -newkey rsa:1024 -nodes \
  -subj '/CN=www.mydom.com/O=My Dom, Inc./C=US/ST=Oregon/L=Portland' \
  -keyout mykey.pem -out myreq.pem

VeriSign のような組織を相手に交渉するときには、署名要求を作成するときに入力する情報が正確かどうかには特別に注意してください。個人的な経験ですが「and」と「&」のような些細な違いでも処理が止まってしまいます。

署名要求の内容をもう一度確かめることもできます。

 # 署名を検証
 openssl req -in myreq.pem -noout -verify -key mykey.pem

 # 情報を表示
 openssl req -in myreq.pem -noout -text

秘密鍵ファイルは安全な場所に保存してください。VeriSign が送り返してくる署名を使うために必要です。通常、署名要求は VeriSign のオンライン申請画面に貼り付けることが多いでしょう。

!!新しい署名のテストはどうしたらいい?
s_server オプションが簡単かつ効果的なテスト方法です。下の例では、秘密鍵と署名を mycert.pem というファイルにまとめたとします。

最初に、署名が使用されるマシンでサーバを起動します。デフォルトでサーバは4433番ポートで要求を待ちます。-accept オプションでポート番号を変更できます。

 openssl s_server -cert mycert.pem -www

サーバが文句を言わずに起動したら、署名は実際に使える可能性は高いでしょう。

ブラウザを使ってテストサーバ https://yourserver:4433/ をテストできます。古きよき http は使えないので https を使うことをお忘れなく。使用できる暗号化方式と今回の接続についての統計情報についてのページが見れるはずです。ほとんどの最近のブラウザで証明書を検証できるでしょう。

!!接続先の署名を取得するには?
openssl と sed を使って、シェルから1行コマンドか簡単なスクリプトを使って接続先の署名を取得できます。

 #!/bin/sh
 #
 # usage: retrieve-cert.sh remote.host.name [port]
 #
 REMHOST=$1
 REMPORT=${2:-443}
 
 echo |\
 openssl s_client -connect ${REMHOST}:${REMPORT} 2>&1 |\
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

!!署名から情報を取得するには?
SSLの署名にはたくさんの情報が入っています。発行者、有効期間、目的、そして暗号の肝の情報。x509サブコマンドが情報取得の入り口です。下の例では検証したい署名が cert.pem というファイルに入っているものとします。

-text オプションで全ての情報を表示します。

 openssl x509 -text -in cert.pem

そのほかのオプションではもっと目的を絞ったデータを提供します。

*発行者は誰?
 openssl x509 -noout -in cert.pem -issuer

*発行先は?
 openssl x509 -noout -in cert.pem -subject

*有効期間は?
 openssl x509 -noout -in cert.pem -dates

*上記を一度に
 openssl x509 -noout -in cert.pem -issuer -subject -dates

*ハッシュ値は?
 openssl x509 -noout -in cert.pem -hash

*md5指紋情報は?
 openssl x509 -noout -in cert.pem -fingerprint

!!PKCS#12署名の変換は?
PKCS#12 ファイルは他のいろいろなアプリケーションで取り込んだり出力したりできます。マイクロソフトのIISでも使用できます。pfx拡張子がよく使われます。

PKCS#12署名を作成するには、秘密鍵と署名が必要です。変換作業中に「出力パスワード」を入力する機会があり、署名を暗号化することもできます。(入力しなければパスワードはかかりません)。

*秘密鍵と自己署名証明書が入ったファイルを作成する。
 openssl req \
   -x509 -nodes -days 365 \
   -newkey rsa:1024 -keyout mycert.pem -out mycert.pem
*mycert.pem をPKCS#12 形式で mycert.pfx に出力。
 openssl pkcs12 -export \
   -out mycert.pfx -in mycert.pem \
   -name "My Certificate"

もし PKCS#12 形式のファイルが届いて暗号化を解除できるパスワードがわかっているなら、標準のPEM形式に変換できます。

* 証明書をパスフレーズなしに変換
 openssl pkcs12 -in mycert.pfx -out mycert.pem -nodes

*上記と同じだが、新しいパスフレーズの入力プロンプトが出る
 openssl pkcs12 -in mycert.pfx -out mycert.pem

!!!証明書の検証
OpenSSL ライブラリを使用するプログラムは、署名発行業者(CA)の署名を検証することができます。

!!署名はどうやって検証したらいい?
署名を検証するには verify オプションが使えます。

 openssl verify cert.pem

もし OpenSSL が署名や署名発行業者やその他の情報(日付、署名連鎖など)を認識できたなら、OKのメッセージが出るだけです。

 $ openssl verify remote.site.pem
 remote.site.pem: OK

何か足りなければ、簡単な説明つきでいくつかエラーメッセージが表示されます。

 error 10 at 0 depth lookup:certificate has expired. Certificates are typically issued for a limited period of time; usually just one year, and openssl will complain if a certificate has expired.
 
 error 18 at 0 depth lookup:self signed certificate. Unless you make an exception, OpenSSL won’t verify a self-signed certificate.

!!OpenSSL はどのCAを認識しますか?
OpenSSL がコンパイルされたとき、「OpenSSL用ファイル」で調整されています。
(configure スクリプトでの --openssldir オプションです。)
これがシステムが信頼するCAの情報が入っているディレクトリです。 

デフォルトでは /usr/local/ssl ですが、ほとんどの場合は別の場所に保存しています。たとえば、/usr/share/ssl (Red Hat/Fedora), /etc/ssl (Gentoo), /usr/lib/ssl (Debian), そして /System/Library/OpenSSL (Macintosh OS X)

自分の OpenSSL がどのディレクトリを使うか(OPENSSLDIR)を調べるには version オプションを使います。

 openssl version -d

表示されたディレクトリにある certs というディレクトリには3種類のファイルが少なくともひとつはあるはずです。

cert.pem という大きなファイルは、VeriSign や Thawte のような認知されているCAからのたくさんの証明書のコレクションから構成されています。

certs サブディレクトリには .pem の拡張子の小さなファイルがいくつかありますが、それぞれが単独CAからの1つの証明書です。

certs サブディレクトリには 052eae11.0 といったおかしなシンボリックリンクもあります。それぞれの .pem ファイルにリンクしています。

おかしな名前のファイルの最初の部分はリンク先の .pem ファイルの指紋の文字列です。拡張子は連番です。複数の証明書が同じハッシュ値を持つことは理論的にはありえるからです。

例として、自分の Gentoo Linux では、f73e89fd.0 という vsignss.pem へのシンボリックリンクが存在します。もちろんその証明書のハッシュ値はそのシンボリックリンクと同じはずです。

 $ openssl x509 -noout -hash -in vsignss.pem
 f73e89fd

プログラムが外部の証明書を扱う場合、本当にその証明書が cert.pem か証明書のハッシュ値から導かれる証明書のどちらかに見つかるかどうかチェックするべきでしょう。
見つかったならその証明書は正当なものと考えられます。

たとえば Sendmail のように自分が信頼する証明書の場所を指定できるものもありますが、Pine のように指定できないものもあることに注意してください。

!!証明書を認識・検証するには?
上記の certs ディレクトリに証明書を配置すると、その証明書は信頼されるようになります。次にハッシュ値のシンボリックリンクを作成します。以下はそれを実行するスクリプトです。

 #!/bin/sh
 #
 # usage: certlink.sh filename [filename ...]
 
 for CERTFILE in $*; do
   # make sure file exists and is a valid cert
   test -f "$CERTFILE" || continue
   HASH=$(openssl x509 -noout -hash -in "$CERTFILE")
   test -n "$HASH" || continue
 
   # use lowest available iterator for symlink
   for ITER in 0 1 2 3 4 5 6 7 8 9; do
     test -f "${HASH}.${ITER}" && continue
     ln -s "$CERTFILE" "${HASH}.${ITER}"
     test -L "${HASH}.${ITER}" && break
   done
 done

!!!コマンドラインでのクライアント・サーバ
s_client と s_server オプションを使うとSSLが有効になったサーバやクライアントをコマンドで起動できます。他の使い方もこの文書の中に散見できますが、この章はこのオプションの説明専用です。

この章では対象となるプロトコル、SMTP, HTTP その他の知識を前提としています。プロとろるの説明についてはここでは対象外です。

!!暗号化SMTPサーバに接続するためには?
s_client オプションを指定すれば暗号化SMTPサーバをテストだけでなく使うこともできます。

暗号化SMTPサーバは安全な通信路を3種類までサポートしています。25 (TLS), 465 (SSL), and 587 (TLS) です。リリース 0.9.7 の頃、openssl コマンドは SMTP サーバとの通信時に STARTTLS の機能を追加されました。

 # 25番ポートの通信制御レベル暗号化と587番ポートでは同じ文法を使ってください。
 openssl s_client -connect remote.host:25 -starttls smtp

 # port 465番ポートSSL
 openssl s_client -connect remote.host:465

RFC821 によれば、(明確には書いてありませんが) 改行記号にはCRLFの2バイトを使用するよう提案しています。ほとんどのメールプログラムはこれを無視して改行記号としてLFでもCRLFでも受け付けますが、Qmailは受け付けません。RFC821に準拠しつつQmail とも通信を行うなら、-crlfオプションを使いましょう。

 openssl s_client -connect remote.host:25 -crlf -starttls smtp

!!暗号化(なんとか)サーバに接続するには?
SSLが使えるいろいろな種類のサーバへの接続は上記の手順と本質的に変わりません。この文書を書いている現在、openssl のコマンド入力TLSではSMTPサーバしかサポートしていませんので、その他のプロトコルでは普通のSSLしか使えません。

 # https: SSL暗号化HTTP
 openssl s_client -connect remote.host:443

 # ldaps: SSL暗号化LDAP
 openssl s_client -connect remote.host:636

 # imaps: SSL暗号化IMAP
 openssl s_client -connect remote.host:993

 # pop3s: SSL暗号化POP-3
 openssl s_client -connect remote.host:995

!!コマンド入力でSSLサーバを起動するには?
s_server オプションを使うと、SSL暗号化が有効になったサーバをコマンド入力で起動できますが、テストやデバッグだけに使ったほうがいいでしょう。運用に耐えられるレベルの品質を求めるなら、Stunnel を代わりに使いましょう。

s_server オプションは証明書が手元にあるときにはたくさんのことができますが、なければ制限がかかります。

 # -www オプションはHTTPで接続しに来て要求を送ったクライアントに
 # HTML形式でステータスを送り返します。
 openssl s_server -cert mycert.pem -www

 # -WWW オプションは簡単な web サーバをエミュレーションします。
 # ページは現在ディレクトリからの相対パスとして検索されます。
 # この例ではデフォルトの4433番ポートではなく、https ポートで
 # 待ち受けます。
 openssl s_server -accept 443 -cert mycert.pem -WWW

!!!指紋(ダイジェスト)
dgst オプションでダイジェスト値を生成することは openssl が直接役に立つ作業です。
ダイジェスト値を計算することは多いので、同じことを行う別のバイナリが用意されています。

!!MD5ダイジェストやSHA1ダイジェストを生成するには?
ダイジェスト値は dgst オプションで生成できます。

 # MD5 ダイジェスト
 openssl dgst -md5 filename

 # SHA1 ダイジェスト
 openssl dgst -sha1 filename

MD5ダイジェストは一般的に使われている md5sum コマンドの出力と形式は違いますが結果は同じです。

 $ openssl dgst -md5 foo-2.23.tar.gz
 MD5(foo-2.23.tar.gz)= 81eda7985e99d28acd6d286aa0e13e07
 $ md5sum foo-2.23.tar.gz
 81eda7985e99d28acd6d286aa0e13e07  foo-2.23.tar.gz

同じことがSHA1ダイジェストでも言えます。

 $ openssl dgst -sha1 foo-2.23.tar.gz
 SHA1(foo-2.23.tar.gz)= e4eabc78894e2c204d788521812497e021f45c08
 $ sha1sum foo-2.23.tar.gz
 e4eabc78894e2c204d788521812497e021f45c08  foo-2.23.tar.gz

!!ダイジェスト値にはどうやって署名する?
ダイジェスト値が他の誰かに改竄されていないことを保障したいなら、自分の秘密鍵で署名することができます。次の例は foo-1.23.tar.gz ファイルの SHA1 ダイジェスト値に証明する場合です。

 # 署名済みダイジェスト値のファイル名は foo-1.23.tar.gz.sha1 
 openssl dgst -sha1 \
   -sign mykey.pem
   -out foo-1.23.tar.gz.sha1 \
   foo-1.23.tar.gz

!!どうやったらダイジェスト値の署名を検証できる?
署名済みのダイジェスト値を検証するには、ダイジェスト値の元のファイル、署名付きダイジェスト値、そして署名をした人の公開鍵が必要です。

# foo-1.23.tar.gz を検証するには foo-1.23.tar.gz.sha1 と pubkey.pem を使う
 openssl dgst -sha1 \
   -verify pubkey.pem \
   -signature foo-1.23.tar.gz.sha1 \
   foo-1.23.tar.gz

!!どうやって Apache のダイジェスト認証を追加できる?
Apache のHTTPダイジェスト認証は特殊な形式でパスワードを保存しなければなりません。Apache についてくる htdigest コマンドが使えますが、ファイルに書き込むだけで標準出力は使えません。近くにいない人のパスワードを用意するときには、その人が信頼できる機械でダイジェスト値を生成してからメール経由で結果をパスワードのデータベースに登録したほうがよい場合もあります。

パスワードのデータベースは比較的簡単です。コロン区切りのユーザー名、(AuthNameで指定された)認証領域名、そして前の2項目とパスワードのMD5ダイジェスト値です。
下のスクリプトではhtdigest の出力を複製していますが結果は標準出力を使っています。dgstオプションは標準入力を使うことを利用しています。

 #!/bin/bash
 
 echo "Create an Apache-friendly Digest Password Entry"
 echo "-----------------------------------------------"
 
 # get user input, disabling tty echoing for password
 read -p "Enter username: " UNAME
 read -p "Enter Apache AuthName: " AUTHNAME
 read -s -p "Enter password: " PWORD; echo
 
 printf "\n%s:%s:%s\n" \
   "$UNAME" \
   "$AUTHNAME" \
   $(printf "${UNAME}:${AUTHNAME}:${PWORD}" | openssl dgst -md5)

!!他にはどんなダイジェスト計算方法がありますか?
list-message-digest-commands オプションを使うと、使っているOpenSSLで使用できるダイジェスト計算方法の一覧が取得できます。

 openssl list-message-digest-commands

!!!暗号化・復号化
!!base64化するには?
enc -base64 オプションが使えます。

 # file.txt の内容をbase64化します
 openssl enc -base64 -in file.txt

 # 上記と同じ処理ですが file.txt.enc に出力します
 openssl enc -base64 -in file.txt -out file.txt.enc

コマンドですぐに文字列をbase64化できます。

 $ echo "encode me" | openssl enc -base64
 ZW5jb2RlIG1lCg==

echo は改行コードを付加する事に注意してください。パスワードや認証コードをbase64化するときには -n オプションを使って避けることもできます。

 $ echo -n "encode me" | openssl enc -base64
 ZW5jb2RlIG1l

-d (decode) で解除できます

 $ echo "ZW5jb2RlIG1lCg==" | openssl enc -base64 -d
 encode me

!!ファイルを暗号化するには?
単にファイルを暗号化するだけなら、GPGのようなツールを使ったほうがいいでしょう。
それでも秘密鍵・証明書の仕組みを使わないでファイルを暗号化したい場合もあるかもしれません。
パスワードを覚えるだけにしたい場合です。
パスワードだけというわけにはいきませんが、もうひとつ暗号化方法も覚えられれば役に立てます。

暗号化方法を選ぶには enc(1) man マニュアルを読んでください。簡単に(そして正確に)言うと、openssl を使った2つの方法のいずれかで暗号化方法の一覧を取得できます。

 # 'Cipher commands' の下に暗号化方法の一覧があります
 openssl -h

 # または、1行に1項目形式で
 openssl list-cipher-commands

暗号化方法が決まったら、base64文字列化するかどうかを決める必要があります。
そうすれば暗号化したデータを電子メールに貼り付けることができるようになります。
そうしなければバイナリ出力になります。

 # file.txt を256ビットAESのCBCモードで暗号化して file.enc に出力
 openssl enc -aes-256-cbc -salt -in file.txt -out file.enc

 # 同じ暗号化処理ですが、電子メールなどに使うためbase64文字列化します。
 openssl enc -aes-256-cbc -a -salt -in file.txt -out file.enc

file.enc ファイルを復号化するには、暗号化方法とパスフレーズが必要です

 # バイナリファイル file.enc を復号化
 openssl enc -d -aes-256-cbc -in file.enc

 # base64文字列ファイルを復号化
 openssl enc -d -aes-256-cbc -a -in file.enc

暗号化や複合化のときのパスフレーズの入力を毎回しなくてもよいようにしたいなら、
openssl(1) のマニュアルの PASS PHRASE ARGUMENTS の章に情報があります。
パスワードのパラメータ指定は簡単です。

 # コマンド入力でパスワードを指定
 openssl enc -aes-256-cbc -salt -in file.txt \
   -out file.enc -pass pass:mySillyPassword

 # パスワードをファイルで指定
 openssl enc -aes-256-cbc -salt -in file.txt \
   -out file.enc -pass file:/path/to/secret/password.txt

!!!エラー
!!SSLのエラーメッセージを理解するには?
システムのログを掘り返すとOpenSSLや暗号化に関する証拠となるエラーメッセージを見つけるでしょう。

 sshd[31784]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)
 sshd[770]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106)

何がおかしいのかを突き止める最初のステップは、errstr オプションを使ってエラー番号を理解することです。エラー番号は「error:」と「:lib」の間にあるコードで、この場合は「0407006A」です。

 $ openssl errstr 0407006A
 error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01

OpenSSL を開発ドキュメントも含めて全てインストールしたなら、そこから調べ始めることができます。
この例では「RSA_padding_add_PKCS1_type_1(3) man マニュアルを見ると PKCS #1 の署名に involves block methods for signatures. もちろんその後に、このようなエラーを受け取った原因を調べるには、自分のプログラムのソースコードを穴が開くほど調べなければなりません。

!!!秘密鍵
!!RSA秘密鍵を生成するには?
genrsa オプションを使いましょう。

 # デフォルトでは512ビット鍵を生成し、標準出力に送ります
 openssl genrsa

 # 1024ビット鍵を mykey.pem に保存します
 openssl genrsa -out mykey.pem 1024

 # 上記と同じですがパスフレーズで暗号化します
 openssl genrsa -des3 -out mykey.pem 1024

!!RSA公開鍵を生成するには?
rsa オプションを使ってRSA秘密鍵から公開鍵を作ってください。

 openssl rsa -in mykey.pem -pubout

!!DSA秘密鍵を作るには?
DSA鍵を作るにはパラメータを記述したファイルが必要ですし、DSAの検証処理はRSAのそれより遅いので、RSAほど使われていません。

ひとつだけDSA鍵を作りたいのなら、dsaparam サブコマンドを使って1ステップでできます。

 # dsakey.pem ファイルを作ります
 openssl dsaparam -noout -out dsakey.pem -genkey 1024

もし逆に、いくつかDSA鍵を作りたいのなら、共有パラメータファイルを作ったほうがいいでしょう。パラメータを構築するのには時間がかかりますが、一度完了するとDSA鍵の生成は素早く行われます。

 # dsaparam.pem にパラメータを生成
 openssl dsaparam -out dsaparam.pem 1024

 # 最初の鍵を生成
 openssl gendsa -out key1.pem dsaparam.pem

 # 2番目、...
 openssl gendsa -out key2.pem dsaparam.pem

!!楕円曲線暗号の鍵を作るには?
OpenSSLのバージョン0.9.8には楕円曲線暗号(Elliptic Curve, EC)のコードが追加されました。EC鍵の生成に関しては ecparam オプションを使います。

 openssl ecparam -out key.pem -name prime256v1 -genkey

 # openssl コマンドは上記の -name オプションで指定できる
 # EC のパラメータ指定一覧表示機能があります。
 openssl ecparam -list_curves

!!秘密鍵のパスフレーズを解除するには?
暗号化サーバ起動時に毎回パスフレーズを入力するのに疲れてしまったんでしょう。
秘密鍵の暗号を解除すると
秘密鍵を作ったときに指定した署名アルゴリズムによって決まる rsa か dsa のオプションを使うと、秘密鍵のパスフレーズを解除できます。

RSA秘密鍵を使って key.pem というファイルに保存した場合、以下のようにして newkey.pem というファイルに暗号を解除した秘密鍵を保存します。

 # 最後のパスフレーズ入力を要求されます
 openssl rsa -in key.pem -out newkey.pem

同じファイルに秘密鍵と公開鍵を入れたいときもあるでしょう。mycert.pem というファイルに保存されているなら、暗号解除した newcert.pem というファイルを2ステップで作成できます。

 # パスフレーズをもう一度入力する必要があります。
 openssl rsa -in mycert.pem -out newcert.pem
 openssl x509 -in mycert.pem >>newcert.pem

!!!パスワードハッシュ
passwd オプションを使うと、伝統的な /etc/passwd 形式や新しい /etc/shadow ファイル、Apache のパスワードファイルなどのパスワードのダイジェスト値を生成できます。

!!crypt 形式のパスワードのハッシュ値を生成するには?
簡単にハッシュ値を生成できます。

 $ openssl passwd MySecret
 8E4vqBR4UOYF.

既存のパスワードの salt を知っているなら、同じハッシュ値を生成できます。

 $ openssl passwd -salt 8E MySecret
 8E4vqBR4UOYF.

!!shadow 形式のパスワードのハッシュ値を生成するには?
最近のUnix では8文字の salt を使用した(crypt の2文字と比べて)より安全な MD5 に基づいたハッシュ値を使用します。-1 オプションを使用して簡単に生成できます。

 $ openssl passwd -1 MySecret
 $1$sXiKzkus$haDZ9JpVrRHBznY5OxB82.

このフォーマットでの salt は2番目と3番目の$記号の間の8文字からなり、この例では sXiKzkus です。salt とパスワードがわかっていれば同じハッシュ値が得られます。

 $ openssl passwd -1 -salt sXiKzkus MySecret
 $1$sXiKzkus$haDZ9JpVrRHBznY5OxB82.

!!!素数
現在の暗号化の技術は素数の生成と判定に大きく依存しているので、OpenSSL ライブラリが素数を扱うコードを持っていても驚くにはあたりません。
0.9.7e 以降では prime (素数)オプションが openssl コマンドに追加されました。 

!!素数かどうかを判定するには?
prime オプションの後ろに数値を指定しなさい。openssl からの返り値は10進数でなく16進数であることに注意してください。

 $ openssl prime 119054759245460753
 1A6F7AC39A53511 is not prime

16進数を直接指定できます。

 $ openssl prime -hex 2f
 2F is prime

!!どうしたら素数を生成できますか?
openssl にいくつか数値を与えて何が残るかを見ます。数値を生成するのに seq コマンドは十分使えます。

 # 開始と終了を指定
 AQUO=10000
 ADQUEM=10100
 for N in $(seq $AQUO $ADQUEM); do
   # bcコマンドで16進数から10進数に変換
   openssl prime $N | awk '/is prime/ {print "ibase=16;"$1}' | bc
 done

!!!乱数
!!ランダムな値を生成するには?
rand オプションを使ってランダムなバイナリやbase64文字列を取得できます。

 # 128ビットのランダムなbase64文字列データを標準出力に
 openssl rand -base64 128

 # 1024ビットのランダムなバイナリデータをファイルに出力
 openssl rand -out random-data.bin 1024

 # openssl に暗号の種としてランダムと言えるブラウザキャッシュを与える
 cd $(find ~/.mozilla/firefox -type d -name Cache)
 openssl rand -rand $(find . -type f -printf '%f:') -base64 1024

/dev/urandom デバイスと GNU の head コマンドがある Unix 機では、よりよい乱雑度で同じようなことができます。

 # 32バイトを /dev/urandom から取得し base64文字列で出力
 head -c 32 /dev/urandom | openssl enc -base64

!!!S/MIME
S/MIME は、特に電子メールで安全にMIMEデータを送受信するための標準規格です。
S/MIME の自動処理が組み込まれた電子メールのクライアントはまだ少ないですが、
openssl はコマンドは smime オプションを使うと S/MIME サービスを提供できます。

smime(1) man マニュアルには良い例がたくさんあることを知っておいてください。

!!署名付き S/MIME メッセージを検証するには?
署名されたメッセージを検証するのはとても簡単です。
メールクライアントで署名付きメッセージをファイルに保存してください。
この場合では msg.txt というファイルに保存したとします。

 openssl smime -verify -in msg.txt

送信者の証明書が、あなたの openssl が信頼するCA(証明書発行機関)によって署名されているなら、メールのヘッダとメッセージの内容と、最後に検証が成功したとの行が表示されます。

メッセージが誰かに改竄されているなら、ダイジェスト値や署名が受け取ったものと違うとの結果が表示されます。

 Verification failure
 23016:error:21071065:PKCS7 routines:PKCS7_signatureVerify:digest failure:pk7_doit.c:804:
 23016:error:21075069:PKCS7 routines:PKCS7_verify:signature failure:pk7_smime.c:265:

同様に、送信者の証明書が OpenSSL に認識されなければ同じようなエラーが表示されます。

 Verification failure
 9544:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify
error:pk7_smime.c:222:Verify error:self signed certificate

ほとんどの電子メールクライアントはメッセージに追加する署名に公開証明書を付加します。
コマンドラインでは自分で証明書を確認できます。
smime -pk7out オプションを使って PKCS#7 証明書データを pkcs7 オプションに与えます。
辺に感じるかもしれませんが動作するのです。

 openssl smime -pk7out -in msg.txt | \
 openssl pkcs7 -text -noout -print_certs

これからずっと使うために相手の証明書をコピーしておくためには、上記の最初の部分を使います。

 openssl smime -pk7out -in msg.txt -out her-cert.pem

使うときには OpenSSL のデータとして取り込んでおいてもいいし、
指定した時だけ使うように別の場所に保存しておいてもいいでしょう。

 openssl smime -verify -in msg.txt -CAfile /path/to/her-cert.pem

!!S/MIME メッセージを暗号化するには?
誰かが自分の証明書をあなたに送ってきて、その人に暗号化メッセージを送ってほしいと依頼されたとしましょう。
her-cert.pem ファイルに相手の証明書を保存し、
my-message.txt にあなたの回答メッセージを保存しました。

標準だが多少弱い RC2-40 の暗号化をするには、
openssl にメッセージと証明書の場所を指定するだけです。

 openssl smime her-cert.pem -encrypt -in my-message.txt

もし相手がより強いSSLに対応していることがわかっているなら、
トリプルDESのようにもっと強い暗号方式も指定できます。

 openssl smime her-cert.pem -encrypt -des3 -in my-message.txt

デフォルトでは、メールヘッダも含んだ暗号化されたメッセージは標準出力に送られます。
-out オプションやシェルのリダイレクトを使ってファイルに保存してください。
直接 sendmail にパイプで出力するのも面白いでしょう。

 openssl smime her-cert.pem \
   -encrypt \
   -des3 \
   -in my-message.txt \
   -from 'Your Fullname <you@youraddress.com>' \
   -to 'Her Fullname <her@heraddress.com>' \
   -subject 'My encrypted reply' |\
 sendmail her@heraddress.com

!!S/MIME メッセージに署名するには?
メッセージ全体を暗号化する必要がないけれど、受信者がメッセージの内容が正しいかを確認できるように署名したい場合にも、暗号化と似ている方法を取ります。違う点は、受信者の証明書では署名はできませんから、自分の秘密鍵と証明書が必要だという点です。

 openssl smime \
   -sign \
   -signer /path/to/your-cert.pem \
   -in my-message.txt \
   -from 'Your Fullname <you@youraddress.com>' \
   -to 'Her Fullname <her@heraddress.com>' \
   -subject 'My signed reply' |\
 sendmail her@heraddress.com

!!!より深く理解するには
全てのマニュアルを読んだり、どのように関連しているかを理解するには時間がかかりますが、OpenSSL の man マニュアルは手始めに最適です。
asn1parse(1), ca(1), ciphers(1), config(5), crl(1), crl2pkcs7(1), dgst(1), dhparam(1), dsa(1), dsaparam(1), ec(1), ecparam(1), enc(1), errstr(1), gendsa(1), genpkey(1), genrsa(1), nseq(1), ocsp(1), openssl(1), passwd(1), pkcs12(1), pkcs7(1), pkcs8(1), pkey(1), pkeyparam(1), pkeyutl(1), rand(1), req(1), rsa(1), rsautl(1), s_client(1), s_server(1), s_time(1), sess_id(1), smime(1), speed(1), spkac(1), ts(1), tsget(1), verify(1), version(1), x509(1), x509v3_config(5).

!!!コメント募集
この文書に関するコメントや提案は大歓迎です。著者 <heinlein@madboa.com> まで送ってください。

この文書は Creative Commons License での使用を許諾しています。