最近、次の2つのWebサイトの指示に従って、Swift IOSでXMPPストリームに対してMD5認証を機能させることができました(CC-MD5関数を使用しました)実際のハッシュ用のAppleのCommonCryptoCライブラリの例):
http://wiki.xmpp.org/web/SASLandDIGEST-MD5
http://www.deusty.com/2007/09/example-please.html
他のハッシュSASL認証スキーム、特にSCRAM-SHA1を機能させる方法についても同様の説明を探しています。公式の RFC5802 ドキュメントを見つけましたが、理解するのに多くの問題があります(XMPPに固有のものでもありません)。実際のハッシュ以外の目的でライブラリを使用しないXMPP認証に固有の、より簡単な説明または簡単で読み取り可能なコード(C、PHP、C++、Javascript、Java)をいただければ幸いです。
プロセスを理解することに興味があり、iosXMPP-Frameworkを使用するつもりはありません。どんな助けでもいただければ幸いです。
このメカニズムがどのように機能するかの基本的な概要は次のとおりです。
必要な暗号化アルゴリズムは、SHA-1、HMACとSHA-1、および PBKDF2 とSHA-1です。ゼロから実装することはお勧めしませんので、言語/フレームワークでの使用方法を調べる必要があります。
normalizedPassword
になります。これは、UTF8エンコーディングに同じパスワードのバリエーションを含めることができないようにするためです。clientNonce
になります。initialMessage
は"n=" .. username .. ",r=" .. clientNonce
です(文字列の連結には..
を使用しています)。クライアントはGS2ヘッダー("n,,"
)をinitialMessageの前に付加し、結果をbase64でエンコードします。これを最初のメッセージとして送信します。
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1">
biwsbj1yb21lbyxyPTZkNDQyYjVkOWU1MWE3NDBmMzY5ZTNkY2VjZjMxNzhl
</auth>
サーバーはチャレンジで応答します。チャレンジのデータはbase64でエンコードされています。
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
cj02ZDQ0MmI1ZDllNTFhNzQwZjM2OWUzZGNlY2YzMTc4ZWMxMmIzOTg1YmJkNGE4ZTZmODE0YjQyMmFiNzY2NTczLHM9UVNYQ1IrUTZzZWs4YmY5MixpPTQwOTY=
</challenge>
クライアントbase64はそれをデコードします:
r=6d442b5d9e51a740f369e3dcecf3178ec12b3985bbd4a8e6f814b422ab766573,s=QSXCR+Q6sek8bf92,i=4096
クライアントはこれを解析します:
r=
これはserverNonce
です。クライアントは、最初のメッセージで送信したclientNonce
で始まることを確認する必要があります。s=
これはsalt
、base64でエンコードされています(はい、これはbase64で2回エンコードされています!)i=
これは反復回数i
です。クライアントは以下を計算します:
clientFinalMessageBare = "c=biws,r=" .. serverNonce
saltedPassword = PBKDF2-SHA-1(normalizedPassword, salt, i)
clientKey = HMAC-SHA-1(saltedPassword, "Client Key")
storedKey = SHA-1(clientKey)
authMessage = initialMessage .. "," .. serverFirstMessage .. "," .. clientFinalMessageBare
clientSignature = HMAC-SHA-1(storedKey, authMessage)
clientProof = clientKey XOR clientSignature
serverKey = HMAC-SHA-1(saltedPassword, "Server Key")
serverSignature = HMAC-SHA-1(serverKey, authMessage)
clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)
クライアントbase64はclientFinalMessage
をエンコードし、応答として送信します。
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
Yz1iaXdzLHI9NmQ0NDJiNWQ5ZTUxYTc0MGYzNjllM2RjZWNmMzE3OGVjMTJiMzk4NWJiZDRhOGU2ZjgxNGI0MjJhYjc2NjU3MyxwPXlxbTcyWWxmc2hFTmpQUjFYeGFucG5IUVA4bz0=
</response>
すべてがうまくいけば、サーバーから<success>
応答が返されます。
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289
</success>
これをデコードしたBase64には次のものが含まれます。
v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=
クライアントは、v
の値がserverSignature
のbase64エンコーディングであることを確認する必要があります。
これはアルゴリズムの基本バージョンです。次のように拡張できます。
ハッシュストレージ。サーバーが常に同じsalt
とi
の値を送信する場合、クライアントはユーザーのパスワードの代わりにsaltedPassword
のみを保存できます。これは、クライアントが毎回すべてのキーストレッチを行う必要がないため、より安全で(クライアントはパスワードを保存する必要がなく、ソルトハッシュを逆にするのが難しいため)、より高速です。
サーバーはハッシュストレージを使用することもできます。サーバーはsalt
、i
、storedKey
、およびserverKey
のみを保存できます。詳細については ここ 。
いくつかの一般的な落とし穴:
salt
の長さについては何も想定しないでください(ただし、ナンスを生成する場合は、十分な長さで暗号的にランダムであることを確認してください)。salt
はbase64でエンコードされており、任意のデータを含めることができます(埋め込まれたNUL
s)。initialMessage
のauthMessage
部分にはGS2ヘッダーが含まれていません(ほとんどの場合、これは"n,,"
です)。実装をテストする場合は、RFCの例のすべての中間結果を次に示します。
ユーザー名:user
パスワード:pencil
クライアントはランダムナンスを生成しますfyko+d2lbbFgONRv9qkxdawL
最初のメッセージ:n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
サーバーはランダムナンスを生成します3rfcNHYJY1ZVvWVs7j
サーバーの応答:r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
塩(16進数):4125c247e43ab1e93c6dff76
クライアントの最終メッセージはむき出しです:c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
塩味のパスワード(16進数):1d96ee3a529b5a5f9e47c01f229a2cb8a6e15f7d
クライアントキー(16進数):e234c47bf6c36696dd6d852b99aaa2ba26555728
保存されたキー(16進数):e9d94660c39d65c38fbad91c358f14da0eef2bd6
認証メッセージ:n=user,r=fyko+d2lbbFgONRv9qkxdawL,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096,c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
クライアントの署名(16進数):5d7138c486b0bfabdf49e3e2da8bd6e5c79db613
クライアントプルーフ(16進数):bf45fcbf7073d93d022466c94321745fe1c8e13b
サーバーキー(16進数):0fe09258b3ac852ba502cc62ba903eaacdbf7d31
サーバー署名(16進数):ae617da6a57c4bbb2e0286568dae1d251905b0a4
クライアントの最終メッセージ:c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=
サーバーの最終メッセージ:v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
サーバーのサーバー署名(16進数):ae617da6a57c4bbb2e0286568dae1d251905b0a4