字节与其16进制字符表示转换的bug

1、原始的字节一旦用16进制字符表示,还原回字节的时候不能直接hexStr.getBytes()

String tHex = SmUtil.sm3(...); // 返回的是 64 个十六进制字符,如 "3a5f…”

BigInteger t = new BigInteger(tHex.getBytes()); // 这是 64 个 ASCII 码字节,不是 32 个哈希字节

hex字符串,就是对字节数据用16进制字符这个规则进行编码,然后转化为字符串。64个16进制字符算起来也是32字节。

tHex这里是32字节 hash byte的16进制字符串表示。 

那么tHex.getBytes()是还原为字节数组。但问题出在这里,是每个字符去还原为1个字节,变成了64字节。

byte[] tBytes = HexUtil.decodeHex(tHex);  这里是真正的还原,就是每2个字符作为一个字节,是32字节。

 

2、new BigInteger(byte[] src) 把字节数组当作有符号大端整数解析。如果 src[0] 的最高位是 1,BigInteger 会把它理解为负数,toByteArray() 还原时会在前面补一个 0x00 字节,导致长度多1个字节。

即,首先new BigInteger(1, src) 保证按照正数来处理,最高位又是1  t = new BigInteger(1, src) ,那么t.toByteArray()会在最前加0x00,来明确说这个是正数,避免最高位是1表示负数的歧义,  如果最高位是0那就不用补位了;如果是t = new BigInteger(src)且src最高位是1,那么t.toByteArray()不会在前面补充,最高位是0当然也不用补位。

posted on 2026-05-12 21:30  幽州散人  阅读(0)  评论(0)    收藏  举报

导航