如何生成符合 RFC6238 和 RFC4086 的 HMAC SHA512 密钥以获得 TOTP?

Arj*_*jun 4 java hmac totp

我必须向 URL http://example.com/test发出 HTTP POST 请求,其中包含 JSON 字符串作为正文部分、标头“Content-Type:application/json”和“Authorization: Basic userid:password”。用户 ID 为 abc@example.com,密码必须是 10 位基于时间的一次性密码,符合 RFC6238 TOTP,使用 HMAC-SHA-512 作为哈希函数。

令牌共享密钥应为“abc@example.comTEXT5”,不带双引号。

因此,为了实现上述目标,我修改了 RFC6238 RC6238 TOTP Algo的 Java 代码

为了获得 TOTP,我使用在线转换器工具 以及一些生成相同 128 个字符长度的十六进制代码的代码将共享密钥“abc@example.comTEXT5”转换为 HMAC-SHA512

发出请求总是会回复“TOTP 错误”。

我注意到我生成了错误的密钥,因此 TOTP 是错误的。那么,如何用RFC6238算法的Java代码生成符合HMAC-SHA512的正确密钥呢?

算法有默认密钥作为种子:

String seed64 = "3132333435363738393031323334353637383930" +
         "3132333435363738393031323334353637383930" +
         "3132333435363738393031323334353637383930" +
         "31323334";
Run Code Online (Sandbox Code Playgroud)

我怎样才能为我的共享秘密“abc@example.comTEXT5”获得这样的seed64?我修改后的代码是10 位 TOTP

我感谢大家的帮助!

小智 7

RFC 6238 附录 A中的示例 64 字节种子是附录 B12345678901234567890中提供的ASCII 秘密的十六进制编码版本,其中包含真值表。

ASCII 1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0
HEX   31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30
Run Code Online (Sandbox Code Playgroud)

如果您想使用相同的模式转换共享密钥,abc@example.comTEXT5并且使用附录 A 中提供的示例代码,则需要将其转换为字符串格式的十六进制。

这将产生以下十六进制字符串:

616263406578616D706C652E636F6D5445585435

为了构建用于 SHA-512 哈希的示例 64 字节种子,重复最初的 20 个字节以使总共 64 个字节达到 SHA-512 哈希的最佳密钥长度。

对示例字符串执行相同操作将产生以下种子:

String seed64 = "616263406578616D706C652E636F6D5445585435" +
         "616263406578616D706C652E636F6D5445585435" +
         "616263406578616D706C652E636F6D5445585435" +
         "61626340";
Run Code Online (Sandbox Code Playgroud)

如果您使用示例代码的其余部分来计算时间步并请求 10 位 TOTP 代码,我认为它适合您。

如果您在生产中使用类似的东西,您可能希望使用更随机生成的秘密。

例如,要为 SHA-512 生成 64 字节机密,您可以执行以下操作:

  public static String generateRawSecret(int length) {
    byte[] buf = new byte[length];
    new SecureRandom().nextBytes(buf);
    String rawSecret = Base64.getEncoder().encodeToString(buf);
    return rawSecret.substring(1, length + 1);
  }

  // Random 64 byte secret
  String secret = generateRawSecret(64);
Run Code Online (Sandbox Code Playgroud)

看起来您已经完成了大部分代码,但如果您正在寻找一些其他 Java 示例,以下链接是一个 GitHub 项目,其中包含一个带有大量测试的简单实用程序类。https://github.com/FusionAuth/fusionauth-2FA