将哈希作为字符串返回 rust
Returning a hash as String 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);
}
输出: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);
由于 returning 数组的大小不同,这会导致匹配臂具有不兼容的类型。我试图通过 returning 字符串而不是 GenericArray 来绕过这个问题。
当我想 return 来自 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`
我还尝试将数组转换为 Vec 或 .as_slice()。
那么我怎样才能 return 像上面那样的字符串或使匹配武器兼容?
编辑:好的,刚刚在 到 return 中找到了字符串形式的解决方案。
但是让火柴武器兼容的另一部分仍然让我感兴趣,所以如果有人对此有答案,欢迎您!
When i want to return a String
from create_hash with format!("{:x}", hasher.finalize())
results in [...] error
问题是 create_hash
在 D
上是通用的,只需要实现 Digest
。虽然您提供的 Digest
的具体实现也满足 format!("{:x}")
接受它们所需的 LowerHex
特征,但 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())
}
为了让不同的match arm兼容,你必须引入间接寻址,从而引入分配。上面的例子已经用 String
做到了,所以你可以让你的匹配臂包含 format!("{:x}", create_hash(...))
并且它们会自动兼容。但如果你不喜欢那样,你也可以 create_hash
return Vec<u8>
代替:
fn create_hash<D: Digest>(msg: &str, mut hasher: D) -> Vec<u8> {
hasher.update(msg);
hasher.finalize().as_slice().to_vec()
}
这将使火柴武器兼容,但 {:x}
将不再有效。您还可以使 create_hash()
return 成为实现 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())
}
然后火柴臂锻炼:
fn main() {
let res = if true {
create_hash("asdfasdf", Sha256::default())
} else {
create_hash("asdfasdf", Sha512::default())
};
println!("{:x}", res.as_ref());
}
问题是你匹配的每个变体都有不同的输出类型:
let dig = match algorithm {
HashTypes::groestl224 => {
create_hash(message.as_ref().unwrap(), Groestl224::default()) // type #1
}
HashTypes::groestl256 => {
create_hash(message.as_ref().unwrap(), Groestl256::default()) // type #2
}
// etc
};
所以你的 dig
变量不能有任何确切的类型。
您应该以某种方式将每个匹配的类型转换为完全相同的类型。最简单的方法是使用:
create_hash(message.as_ref().unwrap(), Groestl256::default())
.to_slice()
.to_owned()
之后你将拥有一个 Vec<u8>
,你可以拥有它并做你想做的事。但是它使用分配。
或者你可以使用动态调度:
fn create_hash<D: Digest + 'static>(msg: &str, mut hasher: D) -> Box<dyn std::ops::Deref<Target = [u8]>> {
hasher.update(msg);
let digest = hasher.finalize();
Box::new(digest)
}
最好、最复杂和最 Rust 的方法是定义一些 enum
它将根据给定的摘要选择它的变体。
我想将散列函数的输出打印到标准输出。我使用 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);
}
输出: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);
由于 returning 数组的大小不同,这会导致匹配臂具有不兼容的类型。我试图通过 returning 字符串而不是 GenericArray 来绕过这个问题。
当我想 return 来自 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`
我还尝试将数组转换为 Vec 或 .as_slice()。
那么我怎样才能 return 像上面那样的字符串或使匹配武器兼容?
编辑:好的,刚刚在
When i want to return a
String
from create_hash withformat!("{:x}", hasher.finalize())
results in [...] error
问题是 create_hash
在 D
上是通用的,只需要实现 Digest
。虽然您提供的 Digest
的具体实现也满足 format!("{:x}")
接受它们所需的 LowerHex
特征,但 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())
}
为了让不同的match arm兼容,你必须引入间接寻址,从而引入分配。上面的例子已经用 String
做到了,所以你可以让你的匹配臂包含 format!("{:x}", create_hash(...))
并且它们会自动兼容。但如果你不喜欢那样,你也可以 create_hash
return Vec<u8>
代替:
fn create_hash<D: Digest>(msg: &str, mut hasher: D) -> Vec<u8> {
hasher.update(msg);
hasher.finalize().as_slice().to_vec()
}
这将使火柴武器兼容,但 {:x}
将不再有效。您还可以使 create_hash()
return 成为实现 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())
}
然后火柴臂锻炼:
fn main() {
let res = if true {
create_hash("asdfasdf", Sha256::default())
} else {
create_hash("asdfasdf", Sha512::default())
};
println!("{:x}", res.as_ref());
}
问题是你匹配的每个变体都有不同的输出类型:
let dig = match algorithm {
HashTypes::groestl224 => {
create_hash(message.as_ref().unwrap(), Groestl224::default()) // type #1
}
HashTypes::groestl256 => {
create_hash(message.as_ref().unwrap(), Groestl256::default()) // type #2
}
// etc
};
所以你的 dig
变量不能有任何确切的类型。
您应该以某种方式将每个匹配的类型转换为完全相同的类型。最简单的方法是使用:
create_hash(message.as_ref().unwrap(), Groestl256::default())
.to_slice()
.to_owned()
之后你将拥有一个 Vec<u8>
,你可以拥有它并做你想做的事。但是它使用分配。
或者你可以使用动态调度:
fn create_hash<D: Digest + 'static>(msg: &str, mut hasher: D) -> Box<dyn std::ops::Deref<Target = [u8]>> {
hasher.update(msg);
let digest = hasher.finalize();
Box::new(digest)
}
最好、最复杂和最 Rust 的方法是定义一些 enum
它将根据给定的摘要选择它的变体。