zkgroup/common/
sho.rs

1//
2// Copyright 2020 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use curve25519_dalek_signal::ristretto::RistrettoPoint;
7use curve25519_dalek_signal::scalar::Scalar;
8use poksho::ShoApi;
9use poksho::shoapi::ShoApiExt as _;
10
11#[derive(Clone)]
12pub struct Sho {
13    internal_sho: poksho::ShoHmacSha256,
14}
15
16impl Sho {
17    /// Creates a Sho and immediately absorbs `data` and ratchets.
18    ///
19    /// This is exactly equivalent to calling [`Sho::new_seed`] followed by
20    /// [`Sho::absorb_and_ratchet`]. Meant for when you're not doing any other absorbing.
21    pub fn new(label: &[u8], data: &[u8]) -> Self {
22        let mut sho = Self::new_seed(label);
23        sho.absorb_and_ratchet(data);
24        sho
25    }
26
27    pub fn new_seed(label: &[u8]) -> Self {
28        let sho = poksho::ShoHmacSha256::new(label);
29        Sho { internal_sho: sho }
30    }
31
32    pub fn absorb_and_ratchet(&mut self, data: &[u8]) {
33        self.internal_sho.absorb_and_ratchet(data)
34    }
35
36    pub fn squeeze(&mut self, outlen: usize) -> Vec<u8> {
37        self.internal_sho.squeeze_and_ratchet(outlen)
38    }
39
40    pub fn squeeze_as_array<const N: usize>(&mut self) -> [u8; N] {
41        self.internal_sho.squeeze_and_ratchet_as_array()
42    }
43
44    pub fn get_point(&mut self) -> RistrettoPoint {
45        RistrettoPoint::from_uniform_bytes(&self.internal_sho.squeeze_and_ratchet_as_array())
46    }
47
48    pub fn get_point_single_elligator(&mut self) -> RistrettoPoint {
49        RistrettoPoint::from_uniform_bytes_single_elligator(
50            &self.internal_sho.squeeze_and_ratchet_as_array(),
51        )
52    }
53
54    pub fn get_scalar(&mut self) -> Scalar {
55        Scalar::from_bytes_mod_order_wide(&self.internal_sho.squeeze_and_ratchet_as_array())
56    }
57}
58
59impl AsMut<poksho::ShoHmacSha256> for Sho {
60    fn as_mut(&mut self) -> &mut poksho::ShoHmacSha256 {
61        &mut self.internal_sho
62    }
63}