*http://www.madboa.com/geek/openssl/ *Paul Heinlein *Initial publication: June 13, 2004 初版: 2004年 6月 13日 *Most recent revision: December 19, 2006 最新版: 2006年 12月 19日 *openssl コマンドは OpenSSL ライブラリに含まれるコマンドで、様々な暗号に関する作業ができます。この HOWTO ではこのコマンドを紹介します。 {{outline}} !!!概要 openssl コマンドは、様々な暗号に関する作業ができる OpenSSL ライブラリに付属のコマンドです。スクリプトやその場限りのコマンド入力作業で役に立ちます。 openssl コマンド使用法のドキュメントはいくぶん分散しがちですが、この文書は実用的な使用法を提供することを目的としています。OpenSSL のインストールについては完了し、パスが通っていることを前提とします。 この文書では実用的な使用例しか提供しません。暗号化の理論や概念には触れません。MD5ハッシュがわからなければ、この文書はまったく役に立たないでしょう。openssl を使ってファイルのハッシュを作りたいのであれば、この文書がそうです。 この文書では新しい使用例をどんどん追加していくつもりです。必要な情報がなくても、しばらく後に見てみてもいいでしょう。 !!OpenSSL のバージョンを知りたい version を指示しましょう。 $ openssl version OpenSSL 0.9.8b 04 May 2006 -a オプションをつけるともっと情報を得られます。 $ openssl version -a OpenSSL 0.9.8b 04 May 2006 built on: Fri Sep 29 18:45:58 UTC 2006 platform: debian-i386-i686/cmov options: bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) blowfish(idx) compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O3 -march=i686 -Wa,--noexecstack -g -Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM OPENSSLDIR: "/usr/lib/ssl" !!使用できる命令を知りたい 3つのコマンドが利用可能なコマンド一覧を表示しますが、役に立つものはひとつも無いと思います。無効なコマンド(help や -h)が最も役に立ちます。 $ openssl help openssl:Error: 'help' is an invalid command. Standard commands asn1parse ca ciphers crl crl2pkcs7 dgst dh dhparam dsa dsaparam ec ecparam enc engine errstr gendh gendsa genrsa nseq ocsp passwd pkcs12 pkcs7 pkcs8 prime rand req rsa rsautl s_client s_server s_time sess_id smime speed spkac 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 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 rc2 rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb rc4 rc4-40 !!いわゆる shell での"標準コマンド"のオプションには何が使えますか? どのサブコマンドでも同じ手が使えます。 $ openssl dgst -h unknown option '-h' options are -c to output the digest with separating colons -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) -signature file signature to verify -binary output in binary form -engine e use engine e, possibly a hardware device. -md5 to use the md5 message digest algorithm (default) -md4 to use the md4 message digest algorithm -md2 to use the md2 message digest algorithm -sha1 to use the sha1 message digest algorithm -sha to use the sha message digest algorithm -sha256 to use the sha256 message digest algorithm -sha512 to use the sha512 message digest algorithm -mdc2 to use the mdc2 message digest algorithm -ripemd160 to use the ripemd160 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 での結果を示します。 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 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 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 指定の暗号化アルゴリズムでのスピードも測定できます。 *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 ' \ -to 'Her Fullname ' \ -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 ' \ -to 'Her Fullname ' \ -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). !!!コメント募集 この文書に関するコメントや提案は大歓迎です。著者 まで送ってください。 この文書は Creative Commons License での使用を許諾しています。