今回は、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 コメント:
コメントを投稿