关于rust:如何迭代调用Sha256 :: digest,将先前的结果传递给每个后续调用?

How can I iteratively call Sha256::digest, passing the previous result to each subsequent call?

我正在尝试实现迭代的SHA256。这有效:

1
2
3
4
5
6
use sha2::{Digest, Sha256}; // 0.8.2

fn main() {
    let preimage = [42; 80];
    let hash = Sha256::digest(&Sha256::digest(&preimage));
}

这不是:

1
2
3
4
5
6
7
8
9
use sha2::{Digest, Sha256}; // 0.8.2

fn main() {
    let preimage = [42; 80];
    let mut hash = preimage;
    for _ in 0..2 {
        hash = Sha256::digest(&hash);
    }
}

我收到一个错误:

1
2
3
4
5
6
7
8
error[E0308]: mismatched types
 --> src/main.rs:7:16
  |
7 |         hash = Sha256::digest(&hash);
  |                ^^^^^^^^^^^^^^^^^^^^^ expected array `[u8; 80]`, found struct `generic_array::GenericArray`
  |
  = note: expected array `[u8; 80]`
            found struct `generic_array::GenericArray<u8, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>`

我想要第二种样式,因此我可以轻松地重复两次以上。


正如编译器告诉您的,类型必须匹配才能为变量分配新值。您不能将i32存放在bool所在的位置。数组和GenericArray是不同的类型。

您的第一个尝试可能是将所有内容都设置为GenericArray

1
2
3
4
5
6
7
8
9
use sha2::{Digest, Sha256}; // 0.8.2
use generic_array_0_12_3::GenericArray; // 0.12.3

fn main() {
    let mut hash = GenericArray::clone_from_slice(&[42u8; 80]);
    for _ in 0..2 {
        hash = Sha256::digest(&hash);
    }
}

但是,这会引起panic,因为您的输入数组是80个元素,并且返回的GenericArray必须具有32个元素-这是SHA-256摘要的长度!

相反,您需要引入一些中间步骤和一些间接指示:

1
2
3
4
5
6
7
8
9
10
11
12
use sha2::{Digest, Sha256}; // 0.8.2

fn main() {
    let input = [42u8; 80];
    let mut intermediate;
    let mut hash = &input[..];
   
    for _ in 0..2 {
        intermediate = Sha256::digest(&hash);
        hash = &intermediate[..];
    }
}

input是具有80个元素的数组,intermediateGenericArray<u8, 32>hash&[u8]inputintermediate都可以视为切片,因此hash被视为两者之间的通用类型。

另请参见:

  • 是否允许多态变量?
  • 使用动态数量的.and()创建Diesel.rs查询


最简单的解决方案是将第一次迭代拖出循环:

1
2
3
4
5
let preimage = [42; 80];
let mut hash = Sha256::digest(&preimage);
for _ in 1..2 {
    hash = Sha256::digest(&hash);
}

(游乐场)

这从一开始就使hash成为GenericArray,因此循环工作正常。