简体   繁体   English

计算 SHA-256 哈希时的前导零

[英]Leading zeros when computing SHA-256 hash

I am trying to compare the SHA-256 hash values of the same file with Python and Java.我正在尝试将同一文件的 SHA-256 哈希值与 Python 和 Java 进行比较。 However, in some instances, the Python hash value has leading zeros, whereas the Java version does not.但是,在某些情况下,Python 哈希值具有前导零,而 Java 版本则没有。 For instance, hashing somefile.txt in both programs yields:例如,在两个程序中散列somefile.txt 会产生:

Python: 000c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890蟒蛇: 000c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890

Java : c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890 Java: c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890

Is it safe to simply remove leading 0's and compare or is there an implementation which does not produce the leading zeros?简单地删除前导 0 并进行比较是否安全,或者是否有不产生前导零的实现?

Python Code Python代码

def sha256sum(filename):
    h  = hashlib.sha256()
    b  = bytearray(128*1024)
    mv = memoryview(b)
    with open(filename, 'rb', buffering=0) as f:
        for n in iter(lambda : f.readinto(mv), 0):
            h.update(mv[:n])
    return h.hexdigest()

print(sha256sum('/somepath/somefile.txt'))

# 000c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890

Java Code Java代码

public static String calculateSHA256(File updateFile) {
    MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, "Exception while getting digest", e);
        return null;
    }

    InputStream is;
    try {
        is = new FileInputStream(updateFile);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "Exception while getting FileInputStream", e);
        return null;
    }

    byte[] buffer = new byte[8192];
    int read;
    try {
        while ((read = is.read(buffer)) > 0) {
            digest.update(buffer, 0, read);
        }
        byte[] shaSum = digest.digest();
        BigInteger bigInt = new BigInteger(1, shaSum);
        String output = bigInt.toString(16);
        return output;
    } catch (IOException e) {
        throw new RuntimeException("Unable to process file for SHA256", e);
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            Log.e(TAG, "Exception on closing SHA256 input stream", e);
        }
    }
}

Log.i("Output", calculateSHA256(somefile))

// I/Output: c3720cf1066fcde30876f498f060b0b3ad4e21abd473588f1f31f10fdd890

The BigInteger conversion is ignoring leading zeros in your SHA-256 hash. BigInteger转换会忽略 SHA-256 哈希中的前导零。 Instead you should encode byte[] directly.相反,您应该直接对byte[]进行编码。 As suggested in this answer you can use String.format() :如此答案中所建议的您可以使用String.format()

StringBuilder sb = new StringBuilder();
for (byte b : shaSum) {
    sb.append(String.format("%02X", b));
}
return sb.toString();

When encoded as hex string the SHA-256 value has 64 characters, as per wiki example :根据wiki 示例,当编码为十六进制字符串时,SHA-256 值有 64 个字符:

SHA256("") SHA256("")

0x e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0x e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM