ようこそゲストさん

はんかくさい日報

2016/08/10(水) 新たな制御ボードの制作/開発作業

今回の作業に欠かせない道具ですが、高密度・小型化の影響で従来のものと物理的なインタフェースが全く異なるため、新規に自作することから始まりました。

左側が従来のもの、右側が自作したもの。
どういう道具かというと、制作/開発ターゲットになる制御基板に搭載するプログラム(これをファームウェアと言います)をパソコンから転送したり、起動・停止制御したりする道具です。
20160810_1.jpg20160810_2.jpg

このように接続し、埋め込むプログラムを制作していきます。
制御基板の企画やハードウェア設計から当方が手掛け、ある程度設計を終えていたので、1カ月で終われるといいのですが、無理っぽいです。。orz
ちなみに、市販はしていませんし、今のところ市販の予定はありません。
NTTで光回線ルータをレンタルするのと似たような感じです。
(話だけはありますが、どう商品化するのか・・・が問題ですね)
20160810_3.jpg

2016/08/06(土) プライベートCAの構築[FreeBSD] (3)

2016/08/06 3:40 サーバ運営・管理
このシリーズのその1 → プライベートCAの構築[FreeBSD] (1)
このシリーズのその2 → プライベートCAの構築[FreeBSD] (2)

自分メモですが、証明書の失効方法や、証明書には種類があるというお話です。

● 証明書の失効手続き
利用対象者が居なくなった場合とか、何らかの問題が起きた場合に発行した証明書を取り消したい(無効にしたい)場合があります。

そんな場合には、「証明書失効操作」を行います。
openssl ca -gencrl -revoke user.pem -out cert.crl
cert.crl が失効リストで、実際には証明書のシリアルナンバーと対応する証明書の失効日が暗号化(?)されて記述されたものが書き込まれるようです。
この cert.crl を各サーバ(Apache、OpenVPN等)の設定で参照するようにします。

これとは別に、証明書発行リストが以下のようにCA管理ディレクトリの index.txt に生成されます。
20160806_1.png
Vで始まる行は、現在有効な証明書、
Rで始まる行は、失効する証明書を示しています。

●証明書には種類がある。
多くの場合、ディジタル証明書といえば、サーバ証明書をさす場合が多いです。
Webサーバで https を行う場合や、電子メールサーバにて TLS 通信を行う場合は、必ず必要になるのでお馴染みの方も多いでしょう。

OpenVPN のクライアント側には、接続先のサーバ証明書(公開鍵のみ)のほかに、クライアント証明書というのが必要になります。
これを OpenSSL コマンドラインで発行するには、 FreeBSD では /etc/ssl/openssl.cnf の設定を一部変更する必要があります。
20160806_2.png

具体的には、[ usr_cert ] ブロックの nsCertType パラメータを
nsCertType = client, email, objsign
とする必要があります。
こうしないと、少なくとも OpenVPN は KU ERROR が発生したり、接続途上でダンマリを決め込んでしまい、クライアント側から上手く接続できません。

ですが、サーバ証明書の場合は、これでは逆に駄目で、
nsCertType  = server
とする必要があります。

2016/07/27(水) FreeBSD 10.3R 環境で dovecot 2.2.25 はそのままでは動作しない

2016/07/28 1:00 サーバ運営・管理
dovecot は、電子メール送受信サービスを実現する際に欠かせないサーバソフトウェアで、皆様が利用する多くのISPで採用されています。
弊社でも採用していますが、どうやら FreeBSD固有のバグがあるようです。
具体的には、
Last died with error (see error log for more information):
 kevent(EV_ADD, READ, 56) failed: Bad file descriptor
(実際は改行しません)

といったメッセージが起動時に発生し、サービスを全く提供出来なくなるという重篤な問題。
これは、日本語の情報がほぼ皆無ですが、以下のパッチで凌げます。(弊社でも確認済。)
#Ports でインストールする場合は、既にパッチが当たった状態でインストールされるので問題ありません。
画像をクリックすると見やすい大きさで表示されると思います。

20160728_1.png

20160728_2.png
〔参考URL〕 https://github.com/dovecot/core/commit/ffd8dc932516bc55bf01d91355540daab365e5e9

余りお勧めしませんが、次のバージョン 2.2.26 が出るのを待つ手もあります。

2016/07/17(日) プライベートCAの構築[FreeBSD] (2)

2016/07/17 3:32 サーバ運営・管理
前々回の記事 にて、プライベートCAの作り方のメモを書きました。

今度は、構築したプライベートCAを用いて、実際にサーバ証明書を発行するところまでメモしておきます。実際に発行する環境を整えるために、最初の一度だけ幾つか準備が必要です。

○ 準備その1- /etc/ssl/openssl.cnf の変更
以下のセクションを修正します。

[ usr_cert ]
basicConstraints=CA:false
(CA:true を CA:false に)

[ v3_ca ]
basicConstraints=CA:false
(CA:true を CA:false に)

これやらないと、証明書は発行できるものの、発行した証明書は不正証明書扱いになってしまいます。

○ 準備その2 - CA の公開証明書を pem 形式から der形式へ変換
# cd /root/BasekernelCA
# openssl x509 -in cacet.pem -inform PEM -out cacert.der -outform DER
ここで作成した der 形式の証明書ファイルを Webサイト公開ディレクトリ等に設置し、Webページからダウンロード出来るようにしておきます。

● いよいよサーバ証明書の発行
ここから先は、本物の認証局にサーバ証明書発行手続きをする際にもほぼ同じ手順が使用できます。但し、Unix系/Linux系のコマンドラインインタフェースが基本です。

○ 秘密鍵の生成
# openssl genrsa -out private.key 2048
この後生成する公開鍵とペアで使用されます。
ここでは 2048bit(256バイト) 長の秘密鍵を生成します。

一般的に「鍵長」とはこの秘密鍵の鍵長で、現在では 2048 bit 以上でないと、サーバ証明書発行を受け付けません。
また、-des3 や -aes128 などのパラメータを付加すると、パスフレーズ(パスワードと同じようなものだが、似て非なるもの)を付けることが出来ますが、サーバ用途においては却ってパスフレーズが邪魔になる(自動起動ができなくなる)ため、特に理由が無い限りは付けないほうがよいです。

○ CSR(署名申請書/Certificate Signing Request)の生成
# openssl req -new -sha512 -key private.key -out server.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Hokkaido
Locality Name (eg, city) []:Sapporo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Base Kernel Co,.Ltd.
Organizational Unit Name (eg, section) []:labo
Common Name (e.g. server FQDN or YOUR name) []:clione.basekernel.ne.jp
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
この手順で、当該の例では暗号化された CSR が server.csr ファイルに作成されます。
ここで・・・

Country Name - ここは日本なので、ISO3166 で規定され、日本を示す2レターコード JP を指定します。

State or Province Name - 日本では都道府県に該当し、米国では州、中共では省です。筆者の組織は北海道にありますので、そのまま Hokkaido とします。

Locality Name - 市区町村名。筆者の組織は札幌市にありますので、そのまま Sapporo とします。 Sapporo-shi や Sapporo City でも大丈夫なようですが、個人的には好みではありません。

Organization Name - 組織名。英語表記の正式名称を記述します。
本物の認証局に対し CSR を発行する際は、ドメイン登録情報と比較したときに、ここを一字一句間違えただけでも発行を拒絶されることがあります。

Organizational Unit Name - 組織内部署名。省略可能ですが、同一組織が複数のサーバ証明書を必要とする場合、ここに何等かの情報を記述し、区別する必要があります。

Common Name - サーバの場合は、サーバのFQDN 名、電子メール認証の場合は、証明対象の電子メールアドレスを記述します。

Email Address 以降は通常、省略します。

本物の認証局に証明書発行依頼をする際は、殆どの場合、この server.csr の中身(テキストファイルです)をコピー&ペーストする仕組みになっていると思います。

○ CA局による証明書(公開鍵)の発行
# openssl ca -out server.pem -infiles server.csr
この操作により、
Enter pass phrase for /root/BaseKernelCA/private/cakey.pem:
と、プライベートCAを生成するときに設定したパスワードを入力後、
下記のように確認が促され、
20160717.png

Sign the certificate? [y/n] の問いに y で署名処理、
1 out 1 certificate requests certified, commit?[y/n] の問いに y で登録処理
がなされ、証明書ファイル server.pem が作成されます。
このファイルの中身(暗号化されたテキストファイル)が証明書本体です。

2016/07/16(土) サトーパーツの端子台 ML-1800-S1-Pxx

2016/07/16 4:22 電子工作
プライベートCA関係の記事の予定でしたが、これも自分メモ。。

左側が32端子あるタイプの ML-1800-S1-P32 という型番の部品、
右側が 6端子あるタイプの ML-1800-S1-P6 という型番の部品。
DSCF5420.JPG

この端子台は、横にいくつでもレゴブロックのように連結することができます。
話には聞いていたし、どこかでそういう説明も見かけた記憶があるのですが、実際に見たことが無いし、メーカーのカタログ等に説明が無い。

と、いうことで、将来同じ疑問を持つかもしれない方々のために検証出来たので記録しておきます。
先ず、左端は簡単にカバーを外すことができます。
DSCF5422.JPG

カバーを外すと金属端子がむき出しになります。それを覆うためのカバーですね。
ここからが重要なのですが、この端子台は最小2端子単位で簡単に分解できます。
DSCF5423.JPG

なので、品番としては 32端子ものの ML-1800-S1-P32 が入手可能な端子数としては最大ですが、連結してあたかもひとつの大きな端子台として実装することができます。
これは 32端子ものと 6端子ものを合体させて、38端子を構成した様子です。
連結の際は、連結する側の左端のカバーを外します。
DSCF5424.JPG

ちなみに右端は常にこんな感じになります。
DSCF5425.JPG

連結のための凹部があります。

2016/07/15(金) プライベートCAの構築[FreeBSD] (1)

2016/07/15 4:35 サーバ運営・管理
現在、弊社サーバネットワーク内部のSSL通信に使用しているプライベートCAによるサーバ証明書が SHA-1 ベースのため、SHA-2 に移行すべく準備作業中です。
7年半前に構築したきりですので、構築手順を忘れています・・・orz
ということで、2回の記事に分けて投稿します。いつものメモです。

具体的には、弊社のVPN接続と電子メール送受信(TLS 又は SSL を使用している場合のみ)に影響があります。新しい証明書に入れ替えて頂く必要があります。

きちんとした正式認証局のものを使うべきだろう、、という声も聞こえてきそうですが、弊社暗号化通信サービスに閉じた用途ですし、逆に汎用的に使われては困るので、弊社プライベートCAでの運用としています。

● 先ずは、スクリプトの修正
Google先生の検索では、Linux ベースの CentOS の事例ばかりで、FreeBSD の事例はほぼ皆無。
ですが、ファイルの置き場所以外に大差ありません。
FreeBSD の場合は、 /usr/src/crypto/openssl/apps/CA.sh を編集します:
(63行目付近)
if [ -z "$DAYS" ] ; then DAYS="-days 395" ; fi  # 13 month
CADAYS="-days 14610"    # 40 years
REQ="$OPENSSL req $SSLEAY_CONFIG"
(71行目付近)
if [ -z "$CATOP" ] ; then CATOP=/root/BaseKernelCA ; fi
CADAYS はCAの有効日数。
CATOP はCAにて発行する証明書の管理トップディレクトリです。
共に適宜の値を指定します。

変更したら、
# chmod +x /usr/src/crypto/openssl/apps/CA.sh
として、スプリプトを実行可能状態にしておきます。

●次に /etc/ssl/openssl.cnf の修正
FreeBSD においては、opensslの設定ファイルは、/etc/ssl/openssl.cnf にあります。

このファイルは、セクション単位に設定項目がまとまっています。
セクション内の該当パラメータを以下のように修正します。
[ CA_default ]
dir             = /root/BaseKernelCA
default_days    = 7305
default_crl_days= 30
default_md      = sha512
policy          = policy_match

[ policy_match ]
countryName             = match
stateOrProvinceName     = supplied
organizationName        = supplied
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits            = 2048
default_md              = sha512

[ req_distinguished_name ]
countryName_default             = JP
stateOrProvinceName_default     = Hokkaido
0.organizationName_default      = Base Kernel Co., Ltd

[ usr_cert ]
basicConstraints=CA:true
nsCertType                      = server

[ v3_ca ]
basicConstraints = CA:true
nsCertType = sslCA, emailCA
この修正で、鍵長デフォルト 2,048bit、暗号化ハッシュ SHA-2(SHA512) に対応します。
修正したら、プライベートCAの構築です。(以下、一部テキスト伏字処理あり)
# /usr/src/crypto/openssl/apps/CA.sh -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 2048 bit RSA private key
...............................................................+++
.......................................+++
writing new private key to '/root/BaseKernelCA/private/./cakey.pem'
Enter PEM pass phrase:       (CAパスフレーズ入力)
Verifying - Enter PEM pass phrase: (もう一度同じCAパスフレーズ入力)
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]:      (JP でよいのでこのままリターン)
State or Province Name (full name) [Hokkaido]:(Hokkaido でよいのでこのままリターン)
Locality Name (eg, city) []:Sapporo
Organization Name (eg, company) [Base Kernel Co., Ltd]:
Organizational Unit Name (eg, section) []:Base Net
Common Name (eg, YOUR name) []:Base Kernel CA
Email Address []:hoge@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:   (このままリターン)
An optional company name []: (このままリターン)
Using configuration from /etc/ssl/openssl.cnf
Enter pass phrase for /root/BaseKernelCA/private/./cakey.pem:
Check that the request matches the signature
Signature ok
(以下省略)
実際には続いてこんな感じで詳細が出力されます:
20160715.png

この例では、/root/BasekernelCA/cacert.pem にCAの証明書が生成されます。
この証明書は、後でサーバ証明書を発行する際に、一緒にCA証明書として通知を行います。

また、この例では証明書の有効期間を 40年としていますが、こういうアホな証明書も発行できるということでご参考にどーぞ。

次の記事は、このプライベートCAを用いたサーバ証明書の発行方法です。
#以前は出来なかったんです。はい。確か、2036年くらいが限界でした。

2016/06/10(金) FreeBSD自身をコンパイルしてセルフ更新してみる

2016/06/10 1:25 サーバ運営・管理
(その1)
20160610_1.png
FreeBSD 9.3R , Athron64x2 3800+ Dual Core , DDR2 1024MByte , ATA100 80GB HDD
中古購入のため M/B 型番不明

(その2)
20160610_2.png
FreeBSD 10.1R , Athron64 3000+ , DDR 2048MByte , ATA100 80GB HDD
Asus A8V

(その2)のほうは、時間かかりすぎのような気がするのだが、、、
OSのバージョンも違うし、(その2)のほうは、役割上LANを4系統接続している状態だし、ハードウェアスペックも低いから単純な比較は出来ないけれど。。

それを差し引いてもねぇ。。です。どんなものでしょうか。

2016/06/02(木) ソフトウェア的なデバッグでは判らない不具合・・・

ソフトウェアの制作や開発作業をやっていると、一度や二度は不可解な問題に遭遇するものだが。。この件もそうでした。。。

何度チェックしてもコンピュータプログラム的には間違いがない。
だが、意図した動作にならない。
今回はディジタル信号で計測温度を取得する温度センサで、温度センサとやりとりする信号線の波形を観ないと原因が判らない。

こんなときはオシロスコープを使うのですが、どんなに安価なものでも20万円程度はする高価な測定機器で、業務上必要なのにもかかわらず、筆者の手元には未だに無いのです。
ほんと、腹立だしいのと情けないのと交錯する心境です。

ですが、使い古しのデジタルオシロスコープセットを貸してくれた同業者が居られたので、折角ですから、問題は既にハードウェア設計変更で解決してしまったのですが、原因を追ってみました。

具体的な機種名は一応伏せておきますが、15年くらい前にノート型パソコンとセットで発売された機種のようで、帯域10MHz、サンプリング周波数 100MHz のようです。
DSC_0222.JPG

波形が取れたら、原因はすぐわかりました。
「この温度センサーとこのハードウェアは直結できない」です。
具体的な話は専門分野な方々にしかわからない話になるので、コメントで質問していただければ、回答致します(^^)

やっぱり欲しいねぇ。。オシロスコープ。。。
今、手元にあるオシロスコープは返却しないといけませんからね。
今般の案件では問題ないけれど、無線周波数帯には使えないし、、

2016/05/09(月) 今更ながら dovecot-SASL による CRAM-MD5,DIGEST-MD5,SCRAM-SHA-1 SMTP認証のサポート

2016/05/09 6:17 サーバ運営・管理
昨日までの記事で、CRAM-MD5 と DIGEST-MD5 に対応が必要な案件があったことを記事にしました。
実はこれらの動作検証をするには、メールサーバが欠かせません。
実際に顧客に提供しているサーバはサービス停止を引き起こす障害が起きると、その対応となりますので、非公開のメールサーバをいじることになります。

ところが、手元のメールサーバ(dovecot + OpenLDAP + postfix) の構成にて、どのようにサポートしているのか(特にパスワード自体の管理方法)の情報が断片的かつごく少数しかありません。
弊社では、SMTP認証を dovecot-SASL に担当させ、電子メールアカウントやパスワードを OpenLDAP にて管理しています。

試行錯誤したところ、OpenLDAP には今まで通り平文管理(実際の格納形式は Base64)で、全種類いけることが判明しました。
こうなると簡単です。

dovecot.conf に
20160509_6.png
のような設定を行い、postfix 側は CRAM-MD5 や DIGEST-MD5 のための特別な設定は要りません。(厳密には、postfix側にセキュリティ的設定オプションがあるが、LOGIN 認証と PLAIN 認証をサポートするのであれば、デフォルトでいけるはず)

dovecot.conf に上記の設定を行ったあと再起動し、他ホストから SMTP を喋ってみると、サポートできていることが下記のように確認できます。
20160509_5.png

これで作業を進めることが出来ました。
昨今では、通信経路そのものを暗号化しようかという方向で、SMTP認証の CRAM-MD5や DIGEST-MD5 といった暗号化ハッシュ認証対応はどちらかというと消極的なISPが多いのですが、簡単にできるのが判っててサポートしないのは手抜きですので、近日中に全ての弊社メールサーバにて対応予定としたいと考えてます。

〔2016/05/16 追記〕上記は、2016/05/11 付でサポート開始しています。

SCRAM 認証は 2010年7月に RFC5802 として規定されましたが、現在どこまでサポートされているのかはよく知りません。
SHA-1 は MD5 と並んで広く使われている暗号化ハッシュ関数の名称ですが、脆弱性が指摘されていて、SSL サーバ証明書なんかがこの影響をもろに受け、SHA-2 へ移行しています。

2016/05/08(日) 今更ながら DIGEST-MD5 SMTP認証[RFC2831,RFC1321]/postfix 3.0.3 + dovecot 2.2.21

前記事に引き続き、これを実装する案件があったので実装記録です。
DIGEST-MD5 は、実装難易度などからサーバ側でのサポート割合が低いのですが、昨年からの POP before SMTP のサポート淘汰に伴い、この状況は変化しているようです。

DIGEST認証は、RFC2831 にて、従前から先行して使われていた HTTP における DIGEST認証と互換を持たせる形で規定されています。
日本語でのまともな資料がなく、仕様そのものも少し中途半端な感があります。

よって、CRAM-MD5 と異なり、サーバ側の動作環境で挙動が異なる場合が考えられるので、ここでは当方の環境である Postfix 3.0.3 + dovecot 2.2.21 における環境であることを明示しておきます。
〔2016/05/09 追記〕 Postfix 3.1.0 + dovecot 2.2.24 でも大丈夫でした。

DIGEST-MD5 によるSMTP認証は、以下のようなシーケンスを取ります。
20160509_1.png
[Client -> Server] AUTH DIGEST-MD5
[Server -> Client] 334 cmVhbG09ImV4YW1wbG...《以降省略》
[Client -> Server] dXNlcm5hbWU9ImluZm8uZXhhbXBsZS5jb20i...《以降省略》
[Server -> Client] 334 cnNwYXV0aD1mOTE2MGE0NzQ4MjE3MmNlMmMxNDk2NGFjZTUyN2VjOA==
[Client -> Server] ZjkxNjBhNDc0ODIxNzJjZTJjMTQ5NjRhY2U1MjdlYzg=
[Server -> Client] 235 Authentication successful.
認証途上でサーバとやりとりするデータは、必ず Base64エンコードして送受信します。
クライアント側では、Base64 デコードして処理しなければなりません。

DIGEST-MD5 における処理の要(かなめ)は、後述するレスポンス MD5 ハッシュの生成になります。
この部分はちょっと複雑です。
(対応した案件でもC言語のソースコードレベルで 150行前後の規模になってしまった)

順に処理を追ってみます。
1)サーバに対し、AUTH DIGEST-MD5 コマンドを発行すると、状態コード 334 で、Base64エンコードされた文字列が返される。先ずはこれをデコードする。
・図中のBase64文字列をデコードすると、下記の文字列が得られます。これを「チャレンジ」と言います。
realm="example.com",nonce="JQMKtdgbEhMra4GdAYmAjQ==",qop="auth",charset="utf-8",
algorithm="md5-sess"
・これらは、パラメータとその値です。
 表示都合上、改行入れていますが、実際には改行しません。
・ダブルクォーテーションで括ってある文字列については、ダブルクォーテーションを除去します。
・DIGEST-MD5 SMTP 認証の場合、qop="auth" と algorithm="md5-sess" になるので、ここではこの事例のみを扱います。
・認証フェーズで使用する文字コードは、通常 utf-8 です。
 このパラメータが無い場合は、iso-8859-1 と見なさなければなりません。
 しかし、通常の 7bit ASCII を使う限り、utf-8 と 7bit ASCII は同じで、文字コードとして 0x20 ~ 0x7e の間しか出てこないので全く意識していません。


2)レスポンス MD5ハッシュの生成
 2-1) RFC2831 で規定する A1 データ列を生成。
 RFC2831 では A1 データ列は以下のように規定されています。
A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
          ":", nonce-value, ":", cnonce-value, ":", authzid-value }
 ここで、
username-value = info.example.com   (ユーザ名を平文で)
realm-value    = サーバから与えられた realm の値を複写 (example.com)
passwd         = userpassword       (パスワードを平文で)
nonce-value    = サーバから与えられた nonce の値を複写(JQMKtdgbEhMra4GdAYmAjQ==)
cnonce-value   = lWF{[QuiRj}_L[PW   (クライアント側でランダム文字列を生成する) 
authzid-value  = サーバから与えられた authzid の値を複写
としますが、通常、authzid パラメータは与えられませんので、この場合はこうしろと規定されています。
A1 = { H( { username-value, ":", realm-value, ":", passwd } ),
           ":", nonce-value, ":", cnonce-value }
具体的には、まず username-value,realm-value,passwd を ':' で連結した文字列
info.example.com:example.com:userpassword
に対して、MD5ハッシュを算出し、
(ハッシュ値は以下の16バイトデータになります)
 20160509_2.png

この 16バイトデータと、nonce-value と cnonce-value を ':' で連結し、連結した文字列の MD5 ハッシュを算出しておきます。

算出値は
 20160509_3.png
となります。

 2-2) A2 データ列の生成
 RFC2831 では A2 データ列は以下のように規定されています。
A2 = { "AUTHENTICATE:", digest-uri-value }
 ここで、digest-uri-value は、サーバタイプ、ホスト名、サーバ名を '/' で連結した文字列で、サーバタイプは 'smtp'、ホスト名は DNS MXレコードで検索できるFQDN、サーバ名は通常省略します。
 ここで、ホスト名を 'mx.example.com' とすると A2 データ列は以下のようになります。
AUTHENTICATE:smtp/mx.example.com
 A2 データ列に関しても MD5ハッシュ値を算出しておきます。
 算出値は
 20160509_4.png
 となります。

 2-3) response ハッシュ値の算出
 RFC2831 では以下のように規定されています。
  HEX( KD ( HEX(H(A1)),
                 { nonce-value, ":" nc-value, ":", cnonce-value, ":", 
                   qop-value, ":", HEX(H(A2)) }))
KD は2つの文字列を':'で連結の意、
HEX はバイトデータ列を 16進文字列表記に変換、
H は、ハッシュ関数の意味で、ここでは MD5 になります。
ここで示している具体例だと、先ず
46a5d6ccc156d8ca8da970723d455d17:JQMKtdgbEhMra4GdAYmAjQ==:00000001:
lWF{[QuiRj}_L[PW:auth:e7280b0554e7e6636bd6a32ec6d5d2cf
※ 表示上、改行しているが、実際は絶対に改行を入れないこと。

のような連結文字列を生成し、この連結文字列に対して MD5ハッシュ値を16進数表記したものを得ます。
算出文字列は、
729303fe19230ab4d3733dd28ab2b0b2
となります。

 2-4) サーバに返すレスポンスデータ列の生成
 具体的には以下のような文字列を生成します。
username="info.example.com",realm="example.com",nonce="JQMKtdgbEhMra4GdAYmAjQ==",
cnonce="lWF{[QuiRj}_L[PW",nc=00000001,qop=auth,digest-uri="smtp/mx.example.com",
response=729303fe19230ab4d3733dd28ab2b0b2,charset="utf-8"
※ 表示上、改行しているが、実際は絶対に改行を入れないこと。

・qop パラメータにはダブルクォーテーションを付けないことに注意してください。
・realm パラメータ、nonce パラメータ、qop パラメータは、サーバから与えられた値をそのまま返します。
・realm 値は空文字列のことがあります。この場合もそのまま空文字列を返します。
 ただ、RFC2831 では「サーバのホスト名が入る」とされています。
・時折、digest-uri パラメータのホスト名に realm の値を設定するような事例を見かけますが、これは正しくありません。DNS のMX レコードに指定されるホスト名を使用すべきと観ています。RFC2831 に説明はあるのですが、今一つ明確ではありません。。
・nc 値は、事実上 00000001 固定です。サーバ側はこれをチェックしているため、00000001 以外の値だと認証エラーになります。

 上記文字列を Base64 エンコードすると、シーケンス図の中に書いてある文字列になります。この Base64エンコード文字列をサーバに返信します。これを「レスポンス」と言います。

3)認証確認
 DIGEST-MD5 はこれでユーザ認証処理完了ではなく、もう一度状態コード 334 で Base64 エンコードした文字列が送られてきます。
cnNwYXV0aD1mOTE2MGE0NzQ4MjE3MmNlMmMxNDk2NGFjZTUyN2VjOA==
を Base64デコードすると、
rspauth=f9160a47482172ce2c14964ace527ec8
が得られます。
この32バイト長の16進数文字列は、2)レスポンス MD5ハッシュの生成 で A2 データ列を
 A2 = { ":", digest-uri-value }
に変えて処理したものになります。

クライアント側は、肯定応答をするために同じように A2 データ列を上記のものに変更したレスポンスハッシュ値を算出し、サーバ側に送り返します。
このあたりは、RFC2831 に明確な記載がなく、当方の環境で確認した挙動です。

このレスポンスがあって、サーバは初めて状態コード 235 を返して認証フェーズを完了します。