2013年5月22日水曜日

YubiKey Client COM API その2

今回は、HMAC-SHA1 Challenge-Response を叩こうと思うのですが、何か題材が必要です。そこで、こちらの内容を VBA で COM を使って実装してみます。



C#でYubikeyのChallenge Response認証を行なうプログラム
http://spp5.blogspot.jp/2013/03/cyubikeychallenge-response.html

上記サイトは C# で COM を使って実装をしているため、ほとんど似た内容になってしまいそうですが、折角なので VBA でどこまでできるかやってみましょう。YubiKey の Slot2 を HMAC-SHA1 Challenge-Response に設定してテストしたいと思いますが、どうせなので、以前に使った COM の Personalization Library で設定してみます。

なお、今回使う秘密鍵は上記サイトと同様に "10 1f cb 53 c6 8d d4 1d d7 db 45 02 4c fb fc 65 6f 75 33 fc" としておきます。

前回と同じように参照設定に YubiKey 関連を加えておき以下のコードを使ってみましょう。

Sub setupSampleHmacSha1ChallengeResponse()
  Const SECRET_KEY = "101fcb53c68dd41dd7db45024cfbfc656f7533fc"

  Dim yk As New YubiKeyConfig
  
  If (0 = yk.ykIsInserted) Then Exit Sub
  
  yk.ykFlagProperty(ykFLAG_SECOND_CONFIG) = True
  yk.ykFlagProperty(ykFLAG_APPEND_CR) = False
  yk.ykFlagProperty(ykFLAG_CHAL_HMAC) = True
  yk.ykFlagProperty(ykFLAG_HMAC_LT64) = True
  yk.ykFlagProperty(ykFLAG_CHAL_BTN_TRIG) = False
  yk.ykKey = SECRET_KEY
  
  Debug.Print yk.ykProgram
End Sub

これを実行することで Slot2 に意図した HMAC-SHA1 Challenge-Response が設定できると思います。注意点として、ドキュメントには ykFLAG_CHAL_KEY_TRIG と定義がありますが、COM では ykFLAG_CHAL_BTN_TRIG と定義されていますので注意してください。



次に認証用のコードを書いてみます。HMAC-SHA1 のハッシュ生成を行う必要がありますが、一から組むなんて大変過ぎるので、使えるものを再利用して解決することにします。

.NET Framework がインストールがされている環境であれば mscorlib.dll の一部機能は VBA からも使えるので、これを参照設定に入れておきます。なお、VBA から mscorlib.dll の機能を叩く場合、コード補完が効くのはクラス名のみでタイプライブラリはほぼ機能しません。まともに組むなら .NET 等の環境を使うべきでしょう。

では、具体的なコードに移ります。

Function createRandomBytes(ByVal size As Integer) As Byte()
  Dim i As Integer
  ReDim result(size - 1) As Byte

  For i = 0 To UBound(result)
    result(i) = CByte(255 * Rnd)
  Next i

  createRandomBytes = result
End Function

Function hexStringToBytes(ByVal s As String) As Byte()
  Dim i As Integer
  ReDim result(Len(s) / 2 - 1) As Byte
  
  For i = 0 To UBound(result)
    result(i) = CByte("&H" & Mid(s, i * 2 + 1, 2))
  Next i
  
  hexStringToBytes = result
End Function

Function computeHmacSha1(secretBytes() As Byte, challengeBytes() As Byte) As Byte()
  Dim result() As Byte
  Dim hmac As New HMACSHA1
  hmac.key = secretBytes
  result = hmac.ComputeHash_2(challengeBytes)
  computeHmacSha1 = result
End Function

Sub debugOut(bytes() As Byte)
  Dim i As Integer
  Dim s As String
  For i = 0 To UBound(bytes)
    s = s & Hex(bytes(i)) & " "
  Next
  Debug.Print s
End Sub

Sub testSampleHmacSha1ChallengeResponse()
  Const SECRET_KEY = "101fcb53c68dd41dd7db45024cfbfc656f7533fc"
  Const TEST_SLOT = 2
  
  Dim y As New YubiClient
  Dim challenge() As Byte
  Dim secret() As Byte
  Dim result As Integer
  Dim response() As Byte
  Dim verify() As Byte
  
  If (ycRETCODE_OK <> y.isInserted) Then Exit Sub

  challenge = createRandomBytes(63)
  Call debugOut(challenge)
  
  secret = hexStringToBytes(SECRET_KEY)
  verify = computeHmacSha1(secret, challenge)
  Call debugOut(verify)
  
  y.dataEncoding = ycENCODING_BYTE_ARRAY
  y.dataBuffer = challenge
  result = y.HMACSHA1(TEST_SLOT, ycCALL_BLOCKING)
  If (ycRETCODE_OK <> result) Then
    Debug.Print "HMAC_SHA1 Error: " & result
    Exit Sub
  End If
  response = y.dataBuffer
  Call debugOut(response)
End Sub

こんな感じで組んでみました。
実行すると以下の順で出力されます。
Challenge : 63byte バイト配列
コード側で演算した HMAC-SHA1 バイト配列
YubiKey側で演算した HMAC-SHA1 バイト配列
なので、2行目と3行目が一致していれば、双方の演算結果が同じということで、認証成功になります。コードについては、難しいことは全て部品に任せているので、ドキュメントを見ながら触っていけば、解説する程の内容ではないと思います。



このレベルのコードを書く場合、コード補完が効かない部品を使っているのもありますし、VBA では物足りないというか・・・個人的にはコレジャナイ感が漂いますね。動いているだけ十分ではありますが。



今回、Challenge-Response 認証を見てみましたが、こういった認証について、演算結果が同じであっただけで、システムが意図している YubiKey の利用者自身を特定できているわけではありません。大概の本人認証はそういうものです。厳密に同じ秘密鍵を持っているかどうかを比較したわけでもないため、極めて高い可能性で意図した YubiKey が使われているのだろう。ということです。たまたま一致する可能性も無いとは言えないわけですが、ハッシュが突合するのは天文学的な確率になってくるため、普段使う限りのレベルでは滅多に起こらない。ということのようですね。基本的にセキュリティでは絶対大丈夫なんて考えるべきでは無いと思います。


現状において、今回使った Challenge-Response が単純なパスワードを使うだけよりも遥かに強固であるのは確かです。システム側からの Challenge に対して、秘密鍵を使った演算結果は常に一意に定まるわけですが、十分な複雑さを持つランダムな Challenge を渡し続ける限り、同じ Challenge を使う可能性は非常に低く出来ますし、そもそも認証用デバイスが必須という点で優位性があります。


とりあえず、クライアント上で直接 YubiKey へのアクセスを行った上で、HMAC-SHA1 Challenge-Respones の検証までできたわけですが、次回は、実際のシステムへの組み込みなんてのを少し考えて見ることにします。

0 件のコメント:

コメントを投稿