トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

OpenSSL Command-Line HOWTO 20080516

  • Initial publication: June 13, 2004

初版: 2004年 6月 13日

  • Most recent revision: December 19, 2006

最新版: 2006年 12月 19日

  • openssl コマンドは OpenSSL ライブラリに含まれるコマンドで、様々な暗号に関する作業ができます。この HOWTO ではこのコマンドを紹介します。

概要

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 のダイジェスト認証を追加できる?

ApacheHTTPダイジェスト認証は特殊な形式でパスワードを保存しなければなりません。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 での使用を許諾しています。