以 String rust 形式返回哈希值

Pac*_*ari 6 hash cryptography rust

我想将哈希函数的输出打印到标准输出。我使用 groestl 哈希函数,但我认为它的工作原理与 sha 或其他函数相同。这样做会按预期打印哈希值:

fn create_hash<D: Digest>(msg: &str, mut hasher: D) -> GenericArray<u8, D::OutputSize> {
  hasher.update(msg);
  hasher.finalize()
}

fn main() {
  let hasher = Groestl256::default();
  let res = create_hash("asdfasdf", hasher);
  println!("{:x}", res);
}
Run Code Online (Sandbox Code Playgroud)

输出:db102d374ae45b130ae49e91dcc7b648b86ba1a0415a32dcce7806d46f316460

现在我想做一个匹配以使其他算法(Groestl512,...)也可用。

    let dig = match algorithm {
        HashTypes::groestl224 => {
            create_hash(message.as_ref().unwrap(), Groestl224::default())
        }
        HashTypes::groestl256 => {
            create_hash(message.as_ref().unwrap(), Groestl256::default())
        }
        HashTypes::groestl384 => {
            create_hash(message.as_ref().unwrap(), Groestl384::default())
        }
        HashTypes::groestl512 => {
            create_hash(message.as_ref().unwrap(), Groestl512::default())
        }
    };
    let res = HashGroestl::create_hash("asdfasdf", Groestl256::default());
    
    println!("Result: {:x}", res);
Run Code Online (Sandbox Code Playgroud)

由于返回数组的大小不同,这会导致匹配臂具有不兼容的类型。我试图通过返回一个字符串而不是 GenericArray 来绕过这个问题。

当我想返回一个字符串时,结果create_hash出现format!("{:x}", hasher.finalize())以下错误:

cannot add `<D as groestl::Digest>::OutputSize` to `<D as groestl::Digest>::OutputSize`
the trait `std::ops::Add` is not implemented for `<D as groestl::Digest>::OutputSize`
required because of the requirements on the impl of `std::fmt::LowerHex` for `aes::cipher::generic_array::GenericArray<u8, <D as groestl::Digest>::OutputSize>`
required by `std::fmt::LowerHex::fmt`
Run Code Online (Sandbox Code Playgroud)

我还尝试将数组转换为 Vec 或使用 .as_slice()。

那么我怎样才能返回一个像上面这样的字符串或使火柴臂兼容呢?

编辑:好的,刚刚在通用函数中找到了解决方案来计算哈希(digest::Digest 特征)并返回一个字符串以作为字符串返回。但让比赛臂兼容的另一部分仍然让我感兴趣,所以如果有人对此有答案,不客气!

use*_*342 5

当我想String从 create_hash 返回 a 并format!("{:x}", hasher.finalize())导致 [...] 错误时

问题是create_hash泛型结束了D,只需要实现即可DigestDigest虽然您提供的具体实现也满足接受它们LowerHex所需的特征format!("{:x}"),但 的签名并create_hash没有反映出这一点。

要修复它,您应该对摘要的输出使用额外的约束,如下所示:

fn create_hash<D>(msg: &str, mut hasher: D) -> String
where
    D: Digest,
    digest::Output<D>: std::fmt::LowerHex,
{
    hasher.update(msg);
    format!("{:x}", hasher.finalize())
}
Run Code Online (Sandbox Code Playgroud)

操场

为了使不同的匹配臂兼容,您必须引入间接和分配。上面的示例已经使用 实现了这一点String,因此您可以将匹配臂包含在内format!("{:x}", create_hash(...)),并且它们会自动兼容。但如果你不喜欢这样,你也可以create_hash返回Vec<u8>

fn create_hash<D: Digest>(msg: &str, mut hasher: D) -> Vec<u8> {
    hasher.update(msg);
    hasher.finalize().as_slice().to_vec()
}
Run Code Online (Sandbox Code Playgroud)

这将使火柴臂兼容,但{:x}不再起作用。您还可以create_hash()返回一个实现以下功能的装箱对象LowerHex

fn create_hash<D>(msg: &str, mut hasher: D) -> Box<dyn LowerHex>
where
    D: Digest,
    digest::Output<D>: LowerHex,
{
    hasher.update(msg);
    Box::new(hasher.finalize())
}
Run Code Online (Sandbox Code Playgroud)

然后匹配臂计算:

fn main() {
    let res = if true {
        create_hash("asdfasdf", Sha256::default())
    } else {
        create_hash("asdfasdf", Sha512::default())
    };
    println!("{:x}", res.as_ref());
}
Run Code Online (Sandbox Code Playgroud)

操场