0

从以下问题我们可以看出:

带密钥的 Java HmacSHA256

用于 HOTP 的 Java 与 Golang (rfc-4226)

, 在 TOTP / HOTP / HmacSHA256 用例中使用密钥时,Java 并不能很好地发挥作用。我的分析是以下造成的麻烦:

  • String.getBytes(当然)将为字符值 > 127 的字符提供负字节值;
  • javax.crypto.Mac并且javax.crypto.spec.SecretKeySpec在外部和内部都byte[]用于接受和转换密钥。

我们已经获得了一些飞天 C-200 单按钮 OTP 设备,它们带有一个由大于 127 的字节值组成的十六进制字符串密码。

我们已经成功地为这些代币创建了一个使用 Ruby 的 PoC,它可以完美运行。由于我们想将这些集成到Keycloak中,我们需要找到一个 Java 解决方案。

由于我们看到的每个 TOTP / HOTP / HmacSHA256 实现都使用了javax.crypto库和byte[],因此我们担心我们必须重写所有使用的类,但要使用int才能支持这种情况。

问:还有其他方法吗?我们如何在 Java 中的 HmacSHA256 计算中使用秘密,其中字节的值 > 127 而不必重写所有内容?


更新

我看错了方向。我的问题是密钥表示为一个字符串(Java 中的 UTF-16),其中包含 Unicode 字符,这些字符传递getBytes()SecretKeySpec.

强制StandardCharsets.ISO_8859_1进行此转换可以解决问题。

4

3 回答 3

2

有符号与无符号是一个主要与人类相关的演示问题。计算机不知道也不关心是否0xFF意味着-1255对你。所以不,你不需要使用整数,使用byte[]就可以了。

这并不意味着您不能破坏事物,因为某些操作基于默认的签名变量类型工作。例如:

byte b = (byte)255;    // b is -1 or 255, depending on how you interpret it
int i = b;      // i is -1 or 2³² instead of 255
int u = b & 0xFF; // u is 255

booleanJava 只对原语进行了签名(而char不是承受),这似乎让很多人感到震惊。然而,Java 完全有能力执行加密操作,所以所有这些“不可能”的问题都只是用户错误。在编写安全敏感代码时,这不是您想要的。

于 2018-08-20T15:22:14.313 回答
0

不要害怕 Java :) 我已经测试了来自不同供应商的几十个令牌,Java 一切都很好,你只需要选择正确的转换器。

从 String 获取字节作为 getBytes() 而不是使用正确的转换器是常见的问题。您从供应商处获得的文件以十六进制格式表示密钥,因此只需 google 'java hex string to byte array' 并选择适合您的解决方案。

Hex、Base32、Base64 只是一种表示形式,您可以轻松地从一个转换为另一个。

于 2018-08-21T12:17:55.177 回答
0

我遇到了完全相同的问题(几年后):我们得到了飞天设备,并且不得不设置他们的服务器端代码。
没有可用的实现与它们一起工作(无论是 php 还是 java)。

解决方案:飞天设备带有十六进制种子。首先,您必须将种子解码为原始二进制文件(例如在 PHP 中使用hex2bin())。该数据是 TOTP/HOTP 函数的正确输入。
java的hex2bin()版本有点棘手,在OP的问题中清楚地写了它的解决方案。

(长话短说:您必须使用 StandardCharsets.ISO_8859_1 解释 hex2bin 的结果,否则某些字符将被解释为 2 字节 utf-16 字符,这会导致最后的密码不同)

String hex = "1234567890ABCDEF"; // original seed from Feitian

Sring secretKey = new String(hex2bin(hex), StandardCharsets.ISO_8859_1);
Key key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.ISO_8859_1), "RAW");
// or without String representation:
Key key = new SecretKeySpec(hex2bin(hex), "RAW");
于 2020-09-24T06:55:06.357 回答