arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/crypto-primitives/src/prf/blake2s/mod.rs
crypto-primitives/src/prf/blake2s/mod.rsRaw
 1use alloc::vec::Vec;
 2use blake2::{Blake2s as B2s, VarBlake2s};
 3use digest::Digest;
 4
 5use super::PRF;
 6use crate::CryptoError;
 7
 8#[cfg(feature = "r1cs")]
 9pub mod constraints;
10
11#[derive(Clone)]
12pub struct Blake2s;
13
14impl PRF for Blake2s {
15    type Input = [u8; 32];
16    type Output = [u8; 32];
17    type Seed = [u8; 32];
18
19    fn evaluate(seed: &Self::Seed, input: &Self::Input) -> Result<Self::Output, CryptoError> {
20        let eval_time = start_timer!(|| "Blake2s::Eval");
21        let mut h = B2s::new();
22        h.input(seed.as_ref());
23        h.input(input.as_ref());
24        let mut result = [0u8; 32];
25        result.copy_from_slice(&h.result());
26        end_timer!(eval_time);
27        Ok(result)
28    }
29}
30
31#[derive(Clone)]
32pub struct Blake2sWithParameterBlock {
33    pub digest_length: u8,
34    pub key_length: u8,
35    pub fan_out: u8,
36    pub depth: u8,
37    pub leaf_length: u32,
38    pub node_offset: u32,
39    pub xof_digest_length: u16,
40    pub node_depth: u8,
41    pub inner_length: u8,
42    pub salt: [u8; 8],
43    pub personalization: [u8; 8],
44}
45
46impl Blake2sWithParameterBlock {
47    pub fn parameters(&self) -> [u32; 8] {
48        let mut parameters = [0; 8];
49        parameters[0] = u32::from_le_bytes([
50            self.digest_length,
51            self.key_length,
52            self.fan_out,
53            self.depth,
54        ]);
55        parameters[1] = self.leaf_length;
56        parameters[2] = self.node_offset;
57        parameters[3] = u32::from_le_bytes([
58            self.xof_digest_length as u8,
59            (self.xof_digest_length >> 8) as u8,
60            self.node_depth,
61            self.inner_length,
62        ]);
63
64        let mut salt_bytes_1 = [0; 4];
65        let mut salt_bytes_2 = [0; 4];
66        let mut personalization_bytes_1 = [0; 4];
67        let mut personalization_bytes_2 = [0; 4];
68        for i in 0..4 {
69            salt_bytes_1[i] = self.salt[i];
70            salt_bytes_2[i] = self.salt[4 + i];
71            personalization_bytes_1[i] = self.personalization[i];
72            personalization_bytes_2[i] = self.personalization[4 + i];
73        }
74        parameters[4] = u32::from_le_bytes(salt_bytes_1);
75        parameters[5] = u32::from_le_bytes(salt_bytes_2);
76        parameters[6] = u32::from_le_bytes(personalization_bytes_1);
77        parameters[7] = u32::from_le_bytes(personalization_bytes_2);
78
79        parameters
80    }
81
82    pub fn evaluate(&self, input: &[u8]) -> Vec<u8> {
83        use digest::*;
84        let eval_time = start_timer!(|| "Blake2sWithParameterBlock::Eval");
85        let mut h = VarBlake2s::with_parameter_block(&self.parameters());
86        h.input(input.as_ref());
87        end_timer!(eval_time);
88        let mut buf = Vec::with_capacity(h.output_size());
89        h.variable_result(|res| buf.extend_from_slice(res));
90        buf
91    }
92}