二段階認証のコードを生成するアプリを作成するために、TOTPの仕様を確認したところ、secretがBase32でエンコードされていることがわかりました。
Base64の場合は、VB.netでクラスが用意されているのですが、Base32の場合はありません。
ということで、VB.netでBase32をデコードするコードを書いてみることにしました。
まずは、Base32のエンコードの仕組みを確認します。
スポンサーリンク
エンコードする文字列を2進数に変換。
5ビットずつ区切り、最後が5ビットに満たない場合は右に0を追加して5ビットに合わせる。
5ビットを10進数に変換する。
すると、0から31までの数値になります。
この数字は、アルファベットのA~Z、数字の2~7に対応しています。
0:A、1:B、、、25:Z、26:2、、、31:7
正確な仕様では、一旦40バイトで区切って、足りない分「=」でパディングしますが、少し単純化しています。
ということで、この逆を行えばデコードできるはずです。
Private Function Base32Decode(sSecret As String) As Byte() Dim bDecoded() As Byte 'Base32の対応表をハッシュテーブルに格納 'htBase32("A") = "00000"というふうになるように書いてます。 Dim htBase32 As Hashtable = New Hashtable For i = 0 To 26 htBase32(Chr(i + 1 + 64).ToString) = Convert.ToString(i, 2).PadLeft(5, "0") Next For i = 2 To 7 htBase32(CStr(i)) = Convert.ToString(i + 24, 2).PadLeft(5, "0") Next '一文字ずつ5桁の2進数に変換して結合します。 Dim sDecode As String = "" For i = 0 To sSecret.Length - 1 sDecode &= htBase32(sSecret(i).ToString) Next '8ビットずつ区切って、10進数に変換します。 'sDecodeの長さが8の倍数じゃないときの処理をどうすればよいのか確認していません。 ReDim bDecoded(sDecode.Length / 8 - 1) For i = 0 To sDecode.Length / 8 - 1 bDecoded(i) = Convert.ToInt32(sDecode.Substring(8 * i, 8), 2) Next Return bDecoded End Function
2段階認証のsecretをデコードしたいだけだったので、細かい部分が省略されています。
VB.netで二段階認証のコードを生成するツールを作りました。
こちらの記事で、実際にこの関数を使っています。