2008/08/13

[ColdFusion][OpenID]Association確立

今回は、Associationの確立方法について。

簡単に言ってしまうと、前々回に取得したOP EndPoint URLにhttpリクエスト(POST)を出せばオッケーなのですが、その際に、以下のパラメーターを送信する必要があります。

openid.ns
openid.mode
openid.assoc_type
openid.session_type
openid.dh_modulus
openid.dh_gen
openid.dh_consumer_public

リファレンスから、openid.nsは「http://specs.openid.net/auth/2.0」で、openid.modeは、「associate」というところまでは、わかったのですが、問題はここから。

次の、openid.assoc_typeは、特に推奨がなかったので、「HMAC-SHA1」をセット。

HMAC-SHA1を選択したので、openid.session_typeは「DH-SHA1」をセットしました。

ここからがやばかった。。。

openid.dh_modulusは、「base64(btwoc(g))」と書かれているのですが、これっていったい何??

base64の部分は、btwoc(g)で得た文字列か数字をbase64に変換すればいいので、CFのToBase64()を使えばいけそうな気がするのですが。。。

問題は、btwoc(g)の部分で、gの部分に付録Bの値をセットするところまではOKで、btwocは何をすればいいの??

4.2. 整数表現 (Integer Representations)の部分を読むと、

任意精度の整数は big-endian signed two's complement binary で符号化されなければならない (MUST)。従って、"btwoc" は任意精度の整数を引数としてとり、最小の big-endian two's complement representation として返す関数である。Diffie-Helman 鍵交換で使われる整数は全て正である。これは、the two's complement representation 最左ビットは常にゼロでなければならない (MUST) ことを意味する。

via:4.2. 整数表現 (Integer Representations)

と書かれていて、さらにわかりません。

ただ、説明の下にあった例を見ると、どうやら、以下のプロセスを経て数字が生成されていそうな気がしました。

1:10進数を16進数に変換
2:2桁ずつ区切り、それぞれの頭に「\x」を付ける
3:先頭の数字を2進数に変換してみて、1だった場合、一番先頭に「\x00」を追加する

リファレンスの例を元に考えてみます。

10進数:0 16進数:0 2進数:0→\x00
10進数:127 16進数:7F 2進数:0110 1111→\x7F
10進数:128 16進数:80 2進数:1000 0000→\x00\x80

と確かに、推測した文字列になってします。

この要領で、付録Bの値をbtwocに従ったアルゴリズムに変換しました。
<cfset KeyValue = "付録Bの値">
<cfparam name="tempKeyValue" default = "">
<cfparam name="KeyValueRest" default = "#KeyValue#">
<cfloop index="i" from="1" to="#Len(keyValue)/2#">
<!--- 左から2文字分を抜き出し、文字列結合する --->
<cfset tempKeyValue = tempKeyValue&"\x"&Left(KeyValueRest,2)>
<!--- テンポラリー文字列の長さが2文字よりも小さくなるまで行う --->
<cfif Len(KeyValueRest) gte 2>
<!--- 左から3番目以降の文字列を抜き出す --->
<cfset KeyValueRest = Mid(KeyValueRest,3,Len(KeyValueRest) - 2) >
</cfif>
</cfloop>
<!--- 頭に「\00」をつけ、Base64に変換を行う --->
<cfset dh_modulus = ToBase64("\x00"&tempKeyValue)>

最後に「\00」をつけている理由は、付録Bの先頭の値が、「C」なので、それを2進数変換とすると、「1100」となるので、追加しました。

この勢いで、デフォルトの2を使って「openid.dh_gen」の値をセットします。

で、最後のopenid.dh_consumer_publicですが、リファレンスでは「base64(btwoc(g ^ xa mod p))」と書かれていて、gとpは、すでに決まっているのですが、「xa」はどうするだろうか???

ここで、バカ正直に、xaを任意に設定し、「g ^ xa mod p」をやろうとすると、おそらくメモリーがもたないだろうと思いました。

というのも、pの値が、付録Bに記載されている値だったので、modすると、確実にやばいと思ったので、ここは、g ^ xa mod pの値自体を任意に設定することにしました。

任意の数字(x)を設定した後、base64(btwoc(x)とし、これですべてのパラメータがそろい、あとは、httpリクエスト(post)するだけ

<cfset KeyValue = "付録Bの値">
<cfparam name="tempKeyValue" default = "">
<cfparam name="KeyValueRest" default = "#KeyValue#">
<cfloop index="i" from="1" to="#Len(keyValue)/2#">
 <!--- 左から2文字分を抜き出し、文字列結合する --->
 <cfset tempKeyValue = tempKeyValue&"\x"&Left(KeyValueRest,2)>
 <!--- テンポラリー文字列の長さが2文字よりも小さくなるまで行う --->
 <cfif Len(KeyValueRest) gte 2>
  <!--- 左から3番目以降の文字列を抜き出す --->
  <cfset KeyValueRest = Mid(KeyValueRest,3,Len(KeyValueRest) - 2) >
 </cfif>
</cfloop>
<!--- 頭に「\00」をつけ、Base64に変換を行う --->
<cfset dh_modulus = ToBase64("\x00"&tempKeyValue)>
<cfset dh_gen = ToBase64("\x02")>

<cfset tempKeyValue = 0>
<cfset KeyValueRest = KeyValue>
<cfloop index="i" from="1" to="#Len(keyValue)#">
 <!--- 右から一文字抜き出して10進数変換を行う --->
 <cfset tempKeyValue = tempKeyValue + InputBaseN(Right(#KeyValueRest#,1),16) * (16^(#i#-1))>
 <cfif i lt Len(keyValue)>
  <cfset KeyValueRest = Mid(KeyValueRest,1,Len(KeyValueRest)-1)>
 </cfif>
</cfloop>
<cfset dh_consumer_public = ToBase64("任意の数字")>

<!--- httpリクエスト --->
<cfhttp url="#ReqUrl#" method="post" redirect="yes">
 <cfhttpparam type="formField" name="openid.ns" value="http://specs.openid.net/auth/2.0" >
 <cfhttpparam type="formField" name="openid.mode" value="associate">
 <cfhttpparam type="formField" name="openid.assoc_type" value="HMAC-SHA1">
 <cfhttpparam type="formField" name="openid.session_type" value="DH-SHA1">
 <cfhttpparam type="formField" name="openid.dh_modulus" value="#dh_modulus#">
 <cfhttpparam type="formField" name="openid.dh_gen" value="#dh_gen#">
 <cfhttpparam type="formField" name="openid.dh_consumer_public" value="#dh_consumer_public#">
</cfhttp>

0 コメント:

コメントを投稿