7

RFC 4226に基づいてC#でOTPソリューションを実装しようとしています:https ://www.rfc-editor.org/rfc/rfc4226

サンプル実装を見つけました。次のようになります。

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

namespace OTP
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
            byte[] secretKey = encoding.GetBytes("12345678901234567890");
            byte[] counter = encoding.GetBytes("1");
            Console.WriteLine(CalculateHotp(secretKey, counter));
            Console.ReadKey();
        }

        public static int CalculateHotp(byte[] key, byte[] counter)
        {
            var hmacsha1 = new HMACSHA1(key);
            byte[] hmac_result = hmacsha1.ComputeHash(counter);
            int offset = hmac_result[19] & 0x0f;
            int bin_code = (hmac_result[offset] & 0x7f) << 24
                           | (hmac_result[offset + 1] & 0xff) << 16
                           | (hmac_result[offset + 2] & 0xff) << 8
                           | (hmac_result[offset + 3] & 0xff);
            int hotp = bin_code % 1000000;
            return hotp;
        }
    }
}

問題は、次のような呼び出しです。

byte[] hmac_result = hmacsha1.ComputeHash(counter);

期待される結果が返されないため、返されたOTPは正しくありません。RFC4226付録D(https://www.rfc-editor.org/rfc/rfc4226#appendix-D)を読むと、使用するテスト値がいくつかあり、結果はそれらと一致しません。

From the RFC 4226, Appendix D:
The following test data uses the ASCII string
 "12345678901234567890" for the secret:

  Secret = 0x3132333435363738393031323334353637383930

  Table 1 details for each count, the intermediate HMAC value.

Count    Hexadecimal HMAC-SHA-1(secret, count)
0        cc93cf18508d94934c64b65d8ba7667fb7cde4b0
1        75a48a19d4cbe100644e8ac1397eea747a2d33ab
2        0bacb7fa082fef30782211938bc1c5e70416ff44
3        66c28227d03a2d5529262ff016a1e6ef76557ece
4        a904c900a64b35909874b33e61c5938a8e15ed1c
<snip>

Table 2 details for each count the truncated values (both in
hexadecimal and decimal) and then the HOTP value.

                  Truncated
Count    Hexadecimal    Decimal        HOTP
0        4c93cf18       1284755224     755224
1        41397eea       1094287082     287082
2         82fef30        137359152     359152
3        66ef7655       1726969429     969429
4        61c5938a       1640338314     338314
<snip>

上記の例では、キーとして「12345678901234567890」を使用し、カウンターとして「1」を使用しているため、ComputeHash()の結果は75a48a19d4cbe100644e8ac1397eea747a2d33ab、OTPは287082になると予想されます。

しかし、私はOTPを取得します:906627

ここで何が間違っているのか本当にわかりません。HMACSHA1クラスを使用してC#でカウンターベースのOTPを正常に実装した人はいますか?

4

1 に答える 1

12

カウンターの使い方が間違っています。カウンターはASCII文字列ではなく、ビッグエンディアンの数値(ロング)である必要があります。

使用する

var counter = new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 };

代わりにこのテストでは、コードは正しいOTPを返します。

于 2012-05-04T13:04:28.597 に答える