HOTP 不会生成与 Google 验证器相同的代码
HOTP does not generate the same code as from the Google Authenticator
目前,我正在为 Android 的 Java 中的 HOTP 实施而苦苦挣扎。我正在尝试生成一个 OTP 代码以将它们与用户输入相匹配以登录应用程序。为此,我使用这个 script。
当我从移动因子 0 到 19 创建一些测试值时,我得到以下代码:
106764
867240
658913
270241
373368
105291
051234
812749
615640
648397
846312
825014
565042
820956
757355
372673
964093
451446
360409
这些代码都是从这个 Base32 编码的共享秘密生成的:AECQIBADA3PK3PXP
当我将代码与 Google Authenticator 应用程序生成的代码进行比较时,它们总是不同的。 Google Authenticator 应用程序中没有任何代码与上面的代码匹配。
我使用以下 URI 生成了 QR 码,所以我不知道我做错了什么:
otpauth://hotp/Hash%20based?secret=AECQIBADA3PK3PXP&issuer=Testserver&counter=0&algorithm=SHA1
有人可以帮助我吗?提前致谢。
我将此代码与您的密码一起使用,生成的 OTP 与 Google 身份验证器相同。
使用 0<=counter<=100 调用此方法。你会看到结果。
public static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8
= {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
public String generateHOTP(long count, String seedString) {
byte[] counter = new byte[8];
long movingFactor = count;
for (int i = counter.length - 1; i >= 0; i--) {
counter[i] = (byte) (movingFactor & 0xff);
movingFactor >>= 8;
}
//from org.apache.commons.codec.binary.Base32;
Base32 base32 = new Base32();
byte[] seed = base32.decode(seedString);
byte[] hash = HMAC(seed, counter);
int offset = hash[hash.length - 1] & 0xf;
int otpBinary = ((hash[offset] & 0x7f) << 24)
| ((hash[offset + 1] & 0xff) << 16)
| ((hash[offset + 2] & 0xff) << 8)
| (hash[offset + 3] & 0xff);
int otp = otpBinary % DIGITS_POWER[6];
String result = Integer.toString(otp);
while (result.length() < 6) {
result = "0" + result;
}
return result;
}
private byte[] HMAC(byte[] seed, byte[] counter) {
try {
Mac hmac = Mac.getInstance("HmacSHA1");
SecretKeySpec macKey = new SecretKeySpec(seed, "RAW");
hmac.init(macKey);
return hmac.doFinal(counter);
} catch (GeneralSecurityException ex) {
throw new UndeclaredThrowableException(ex);
}
}
目前,我正在为 Android 的 Java 中的 HOTP 实施而苦苦挣扎。我正在尝试生成一个 OTP 代码以将它们与用户输入相匹配以登录应用程序。为此,我使用这个 script。 当我从移动因子 0 到 19 创建一些测试值时,我得到以下代码:
106764
867240
658913
270241
373368
105291
051234
812749
615640
648397
846312
825014
565042
820956
757355
372673
964093
451446
360409
这些代码都是从这个 Base32 编码的共享秘密生成的:AECQIBADA3PK3PXP
当我将代码与 Google Authenticator 应用程序生成的代码进行比较时,它们总是不同的。 Google Authenticator 应用程序中没有任何代码与上面的代码匹配。
我使用以下 URI 生成了 QR 码,所以我不知道我做错了什么:
otpauth://hotp/Hash%20based?secret=AECQIBADA3PK3PXP&issuer=Testserver&counter=0&algorithm=SHA1
有人可以帮助我吗?提前致谢。
我将此代码与您的密码一起使用,生成的 OTP 与 Google 身份验证器相同。
使用 0<=counter<=100 调用此方法。你会看到结果。
public static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8
= {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
public String generateHOTP(long count, String seedString) {
byte[] counter = new byte[8];
long movingFactor = count;
for (int i = counter.length - 1; i >= 0; i--) {
counter[i] = (byte) (movingFactor & 0xff);
movingFactor >>= 8;
}
//from org.apache.commons.codec.binary.Base32;
Base32 base32 = new Base32();
byte[] seed = base32.decode(seedString);
byte[] hash = HMAC(seed, counter);
int offset = hash[hash.length - 1] & 0xf;
int otpBinary = ((hash[offset] & 0x7f) << 24)
| ((hash[offset + 1] & 0xff) << 16)
| ((hash[offset + 2] & 0xff) << 8)
| (hash[offset + 3] & 0xff);
int otp = otpBinary % DIGITS_POWER[6];
String result = Integer.toString(otp);
while (result.length() < 6) {
result = "0" + result;
}
return result;
}
private byte[] HMAC(byte[] seed, byte[] counter) {
try {
Mac hmac = Mac.getInstance("HmacSHA1");
SecretKeySpec macKey = new SecretKeySpec(seed, "RAW");
hmac.init(macKey);
return hmac.doFinal(counter);
} catch (GeneralSecurityException ex) {
throw new UndeclaredThrowableException(ex);
}
}