如何在 Rust 中散列二进制文件

How to hash a binary file in Rust

在 Rust 中,使用 sha256 = "1.0.2"(或类似的),我如何散列二进制文件(即 tar.gz 存档)?

我正在尝试获取该二进制文件的 sha256。

这不起作用:

fn hash() {
    let file = "file.tar.gz";
    let computed_hash = sha256::digest_file(std::path::Path::new(file)).unwrap();
    computed_hash
}

输出是:

...
Error { kind: InvalidData, message: "stream did not contain valid UTF-8" }

编辑: 升级到 sha256 = "1.0.3" 应该可以解决这个问题

问题是 digest_file 正在内部将文件读取到 String,这要求它包含有效的 UTF-8,在这种情况下这显然不是您想要的。

相反,您可以以字节形式读取文件并将其传递到 sha256::digest_bytes:

let bytes = std::fs::read(path).unwrap();  // Vec<u8>
let hash = sha256::digest_bytes(&bytes);

所依赖的 sha2 crate 支持散列 Readable 对象,而无需将整个文件读入内存。请参阅 hashes readme.

中的示例
use sha2::{Sha256, Digest};
use std::{io, fs};

let mut hasher = Sha256::new();
let mut file = fs::File::open("file.tar.gz")?;

let bytes_written = io::copy(&mut file, &mut hasher)?;
let hash_bytes = hasher.finalize();

这是一个使用 sha2 crate 的实现,它不会将整个文件读入内存,也不依赖于 ring crate。就我而言,戒指不是纯锈,这会导致 cross-compilation 困难。

use data_encoding::HEXLOWER;
use sha2::{Digest, Sha256};
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};

/// calculates sha256 digest as lowercase hex string
fn sha256_digest(path: &PathBuf) -> Result<String> {
    let input = File::open(path)?;
    let mut reader = BufReader::new(input);

    let digest = {
        let mut hasher = Sha256::new();
        let mut buffer = [0; 1024];
        loop {
            let count = reader.read(&mut buffer)?;
            if count == 0 { break }
            hasher.update(&buffer[..count]);
        }
        hasher.finalize()
    };
    Ok(HEXLOWER.encode(digest.as_ref()))
}