为何Inno Setup的SHA256函数计算结果与其他实现不匹配?
问题原因
Inno Setup内置的两个SHA256字符串哈希函数,计算结果和通用实现不一致的核心原因是字符编码默认值不同,并没有额外插入长度字节:
GetSHA256OfUnicodeString会直接将内存中存储的UTF-16LE编码(Inno Setup Unicode版本默认字符串编码,每个字符占2字节,低位字节在前)的字符串内容传入哈希算法计算- 你使用的在线计算器、Java默认字符串哈希逻辑,都是将字符串转为UTF-8编码后再计算哈希值
你给出的示例中,字符串Test的两种编码字节内容差异如下:
- UTF-8编码:
0x54 0x65 0x73 0x74,对应哈希值532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25 - UTF-16LE编码:
0x54 0x00 0x65 0x00 0x73 0x00 0x74 0x00,对应哈希值fe520676b1a1d93dabab2319eea03674f3632eaeeb163d1e88244f5eb1de10eb,和Inno Setup官方示例结果完全匹配。
另外GetSHA256OfString函数在Unicode版本的Inno Setup中,会先把字符串转为系统默认ANSI编码再计算哈希,结果受当前系统代码页影响,更难和跨平台的Java代码对齐,不建议使用。
解决方案
你可以任选其中一种方案实现两端校验对齐:
方案1:Java侧适配Inno Setup的计算逻辑
Java计算哈希时指定使用UTF-16LE编码转码字符串,即可和GetSHA256OfUnicodeString的结果完全匹配,示例代码如下:
import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHA256Matcher { public static String getSHA256MatchInnoSetup(String input) throws NoSuchAlgorithmException { // 指定用UTF-16LE编码转字符串为字节数组 byte[] inputBytes = input.getBytes(StandardCharsets.UTF_16LE); MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); byte[] digest = sha256.digest(inputBytes); // 字节数组转小写十六进制字符串 StringBuilder hexStr = new StringBuilder(); for (byte b : digest) { hexStr.append(String.format("%02x", b)); } return hexStr.toString(); } public static void main(String[] args) throws NoSuchAlgorithmException { // 测试输入Test,输出结果和Inno Setup示例一致 System.out.println(getSHA256MatchInnoSetup("Test")); } }
方案2:Inno Setup侧输出通用UTF-8编码的哈希值
如果要让Inno Setup输出的哈希值和通用实现、默认Java逻辑对齐,你可以先将字符串转成UTF-8编码的字节数组,再计算SHA256。你可以通过Inno Setup的WideCharToMultiByte系统API实现Unicode字符串到UTF-8的转码,再传入哈希计算逻辑即可。
内容的提问来源于stack exchange,提问作者JoeBun
相关产品推荐
相关产品推荐

