WSSE認証に利用する認証用文字列を作成します。(HTTPのX-WSSEヘッダを使用した認証)

WSSE認証は、HTTPのX-WSSEヘッダを使用した認証方式です。認証文字列は、ユーザー名とSHA1ハッシュされたパスワードで構成されるためパスワードが平文で流れる基本認証よりセキュアな認証が行えます。

WSSE認証は、はてなでよく使われています。HTTPSの場合は、通信自体が暗号化されるので不要ですがHTTP上でセキュアな認証という場合に使えます。

はてなサービスにおけるWSSE認証
http://developer.hatena.ne.jp/ja/documents/auth/apis/wsse

X-WSSEヘッダは以下の4つにより構成されます。

・Username
 ユーザー名

・Nonce
 HTTPリクエスト毎に生成したセキュリティ・トークン。40Byte程度のランダムな値を使っておけば良いと思います。
 乱数を作ります。(System.Random, RNGCryptoServiceProvider) - tekkの日記 C#,VB.NET

・Created
 Nonceが作成された日時をISO-8601表記で記述したもの ex("2011-02-20T22:34:57Z"

・PasswordDigest
 Nonce+Created+パスワードをもとにSHA1アルゴリズムでダイジェスト化して生成された文字列を、Base64エンコードした文字列


X-WSSE: UsernameToken Username="tekk", PasswordDigest="9+aSsprBebWjLabUCJ3GhuAK8
/8=", Nonce="KQWjQSHncGhgrTnUADq9JqGi+oksUTg/MMazyKdQUDNLSeeuWz/ZbQ==", Created=
"2011-02-20T22:52:02Z"

以下、サンプルコードです。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace MakeWSSEHeader
{
class Program
{
static void Main(string[] args)
{

const string USER_NAME = "tekk";
const string PASS_WORD = "tekkpw";

// nonce security token
byte[] nonce = MakeRandomBytes(40);

// created ISO-8601 formatting
string created = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssZ");

// password sha1 digest (nonce+created+password)
List lstByte = new List();

lstByte.AddRange(nonce);
lstByte.AddRange(System.Text.Encoding.UTF8.GetBytes(created));
lstByte.AddRange(System.Text.Encoding.UTF8.GetBytes(PASS_WORD));

SHA1Managed sha1 = new SHA1Managed();

byte[] passwordDigest = sha1.ComputeHash(lstByte.ToArray());

// Build WSSE Header
string format = "X-WSSE: UsernameToken Username=\"{0}\", PasswordDigest=\"{1}\", Nonce=\"{2}\", Created=\"{3}\"";
string wsseHeader = String.Format(format,
USER_NAME,
Convert.ToBase64String(passwordDigest),
Convert.ToBase64String(nonce), created);

Console.WriteLine(wsseHeader);
Console.ReadLine();

}

static byte[] MakeRandomBytes(int makebytes)
{

RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();

Byte[] rndBuffer = new Byte[makebytes];
rnd.GetBytes(rndBuffer);

return rndBuffer;

}


}
}