我正在尝试在Golang中实现HOTP(rfc-4226),但我无法生成有效的HOTP。我可以在Java中生成它,但由于某种原因,在Golang中实现不同。以下是示例:
public static String constructOTP(final Long counter, final String key)
throws NoSuchAlgorithmException, DecoderException, InvalidKeyException {
final Mac mac = Mac.getInstance("HmacSHA512");
final byte[] binaryKey = Hex.decodeHex(key.toCharArray());
mac.init(new SecretKeySpec(binaryKey, "HmacSHA512"));
final byte[] b = ByteBuffer.allocate(8).putLong(counter).array();
byte[] computedOtp = mac.doFinal(b);
return new String(Hex.encodeHex(computedOtp));
}
而在Go语言中:
func getOTP(counter uint64, key string) string {
str, err := hex.DecodeString(key)
if err != nil {
panic(err)
}
h := hmac.New(sha512.New, str)
bs := make([]byte, 8)
binary.BigEndian.PutUint64(bs, counter)
h.Write(bs)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
我认为问题在于Java中的这行代码:
ByteBuffer.allocate(8).putLong(counter).array();
生成的字节数组与Go中的这行代码: binary.BigEndian.PutUint64(bs, counter)
不同。在Java中,生成的字节数组如下:
83 -116 -9 -98 115 -126 -3 -48
,而在Go中是: 83 140 247 158 115 130 253 207
。有没有人知道这两行代码的区别以及如何将Java代码转换成Go?
byte
值,只需将其转换为int8
。请参见编辑后的答案。 - iczabase64.StdEncoding.EncodeToString(h.Sum(nil))
改为hex.EncodeToString(h.Sum(nil))
似乎解决了这个问题。 - Zach Kauffman