Hash 将哈希作为字符串返回

Hash 将哈希作为字符串返回,hash,rust,cryptography,Hash,Rust,Cryptography,我想将散列函数的输出打印到标准输出。我使用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 = Gr

我想将散列函数的输出打印到标准输出。我使用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);
}
这导致由于返回数组的大小不同,匹配臂具有不兼容的类型。我试图通过返回字符串而不是泛型数组来绕过这个问题

当我想用
格式从
create\u hash
返回字符串时!(“{: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`
无法将`::OutputSize`添加到`::OutputSize`中`
特性“std::ops::Add”未为“::OutputSize”实现`
由于对'aes::cipher::generic_array::GenericArray`的'std::fmt::LowerHex'impl的要求,因此需要此选项`
'std::fmt::LowerHex::fmt'所需`
我还尝试过将数组转换为Vec或.as_slice()

那么,我怎样才能返回如上所述的字符串,或者使匹配臂兼容呢

编辑:好的,刚刚在中找到了以字符串形式返回的解决方案。 但是另一个让火柴臂兼容的部分仍然让我感兴趣,所以如果有人对此有答案,欢迎

当我想用
格式从create\u hash返回
字符串时!(“{:x}”,hasher.finalize())
导致[…]错误

问题是
create\u hash
D
的泛型,它只需要实现
摘要
。在提供
摘要
的具体实现的同时,还满足了
格式所需的
LowerHex
特性!(“{:x}”)
要接受它们,
create\u 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())
}
这将使匹配臂兼容,但
{:x}
将不再工作。您还可以使
create_hash()
返回一个装箱对象,该对象实现
LowerHex
特性,这是
{:x}
用于格式化的:

fn create_hash<D>(msg: &str, mut hasher: D) -> Box<dyn LowerHex>
where
    D: Digest,
    digest::Output<D>: LowerHex,
    D::OutputSize: 'static,
{
    hasher.update(msg);
    Box::new(hasher.finalize())
}

问题在于,您匹配的每个变量都有不同的输出类型:

let dig=匹配算法{
HashTypes::groestl224=>{
创建_散列(message.as_ref().unwrap(),Groestl224::default())//键入#1
}
HashTypes::groestl256=>{
创建散列(message.as_ref().unwrap(),Groestl256::default())//键入#2
}
//等
};
因此,您的
dig
变量不能有任何精确的类型

您应该以某种方式将每个匹配的类型转换为完全相同的类型。最简单的方法是使用:

create_hash(message.as_ref().unwrap(),Groestl256::default())
.to_slice()
.to_拥有()
之后,您将拥有一个
Vec
,您可以拥有它并做您想做的事情。但它使用分配

也可以使用动态调度:

fn创建\u散列
fn create_hash<D: Digest>(msg: &str, mut hasher: D) -> Vec<u8> {
    hasher.update(msg);
    hasher.finalize().as_slice().to_vec()
}
fn create_hash<D>(msg: &str, mut hasher: D) -> Box<dyn LowerHex>
where
    D: Digest,
    digest::Output<D>: LowerHex,
    D::OutputSize: 'static,
{
    hasher.update(msg);
    Box::new(hasher.finalize())
}
fn main() {
    let res = if true {
        create_hash("asdfasdf", Sha256::default())
    } else {
        create_hash("asdfasdf", Sha512::default())
    };
    println!("{:x}", res.as_ref());
}