关于TOTP生成算法的小问题。
我正在构建一个TOTP生成算法。为了做到这一点,我使用HMAC SHA1。
结果是正确的,我多次使用HMAC SHA1生成的TOTP向服务器验证自己,我确认TOTP是正确的,非常高兴。
现在,知道HMAC SHA1不太安全,我想从HMAC SHA1迁移到HMAC SHA256。
我以为我只是简单地改变了HMAC算法。不幸的是,服务器不接受使用HMAC SHA256生成的所有TOTP。
只是想强调一下,这个问题是关于如何让它与HMAC SHA256一起工作。
这个问题不是关于:
-
HMAC SHA1有多安全
-
如果从HMAC SHA1迁移到HMAC256是一个不错的选择
-
如何更改服务器以接受HMAC256生成的TOTP。
这个技术问题实际上是关于使用HAMC SHA256生成TOTP的技术算法。
我用来生成HMAC SHA1 TOTP的代码是:
String getTOTP() {
try {
long value = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / TimeUnit.SECONDS.toMillis(30);
final byte[] key = new Base32().decode("the_password".toUpperCase(Locale.US));
final var data = new byte[8];
for (int i = 8; i-- > 0; value >>>= 8) {
data[i] = (byte) value;
}
final var signKey = new SecretKeySpec(key, "HmacSHA1"); // would like to change here to "HmacSHA256"
final var mac = Mac.getInstance("HmacSHA1"); // would like to change here to "HmacSHA256"
mac.init(signKey);
final String hashString = new String(new Hex().encode(mac.doFinal(data)));
final var offset = Integer.parseInt(hashString.substring(hashString.length() - 1), 16);
final var truncatedHash = hashString.substring(offset * 2, offset * 2 + 8);
final var finalHash = String.valueOf(Integer.parseUnsignedInt(truncatedHash, 16) & 0x7FFFFFFF);
final var finalHashCut = finalHash.substring(finalHash.length() - 6);
System.out.println("THE TOTP generated with HmacSHA1 is " + finalHashCut);
System.out.println("THE TOTP generated with HmacSHA256 will not work though :'( ");
return finalHashCut;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
LOGGER.warn("", e);
return "";
}
}
问题:为了让TOTP使用HMAC SHA256并且仍然有效,我应该调整算法的哪些元素?
非常感谢。