openzeppelin_crypto/pedersen/
mod.rs

1//! This module contains Pedersen Hash Function implementation.
2///
3/// Based on the [Starknet] implementation of the Pedersen Hash Function.
4///
5/// [Starknet]: <https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/crypto/signature/fast_pedersen_hash.py>
6pub mod instance;
7pub mod params;
8
9use crate::{
10    curve::{AffineRepr, CurveConfig},
11    field::prime::PrimeField,
12    pedersen::params::PedersenParams,
13};
14
15/// Pedersen hash.
16#[derive(Clone, Debug)]
17pub struct Pedersen<F: PedersenParams<P>, P: CurveConfig>
18where
19    <P as CurveConfig>::BaseField: PrimeField,
20    F::AffineRepr: AffineRepr<
21        Config = P,
22        BaseField = P::BaseField,
23        ScalarField = P::ScalarField,
24    >,
25{
26    params: core::marker::PhantomData<F>,
27    curve: core::marker::PhantomData<P>,
28}
29
30impl<F: PedersenParams<P>, P: CurveConfig> Default for Pedersen<F, P>
31where
32    <P as CurveConfig>::BaseField: PrimeField,
33    F::AffineRepr: AffineRepr<
34        Config = P,
35        BaseField = P::BaseField,
36        ScalarField = P::ScalarField,
37    >,
38{
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl<F: PedersenParams<P>, P: CurveConfig> Pedersen<F, P>
45where
46    <P as CurveConfig>::BaseField: PrimeField,
47    F::AffineRepr: AffineRepr<
48        Config = P,
49        BaseField = P::BaseField,
50        ScalarField = P::ScalarField,
51    >,
52{
53    #[must_use]
54    #[inline]
55    /// Creates a new Pedersen hash instance.
56    pub fn new() -> Self {
57        Self {
58            params: core::marker::PhantomData,
59            curve: core::marker::PhantomData,
60        }
61    }
62
63    fn process_single_element(
64        element: P::BaseField,
65        p1: F::AffineRepr,
66        p2: F::AffineRepr,
67    ) -> <F::AffineRepr as AffineRepr>::Group {
68        let element = element.into_bigint();
69
70        let high_nibble = element >> F::LOW_PART_BITS;
71        let low_part = element & F::LOW_PART_MASK;
72
73        p1.mul_bigint(low_part) + p2.mul_bigint(high_nibble)
74    }
75
76    /// Computes the Starkware version of the Pedersen hash of x and y.
77    ///
78    /// The hash is defined by:
79    /// [`PedersenParams::P_0`] + `x_low` * [`PedersenParams::P_1`] +
80    /// `x_high` * [`PedersenParams::P_2`] + `y_low` * [`PedersenParams::P_3`] +
81    /// `y_high` * [`PedersenParams::P_4`]
82    ///
83    /// where `x_low` is the 248 low bits of `x`, `x_high` is the 4 high bits of
84    /// `x` and similarly for `y`. [`PedersenParams::P_0`],
85    /// [`PedersenParams::P_1`], [`PedersenParams::P_2`],
86    /// [`PedersenParams::P_3`], [`PedersenParams::P_4`] are constant points
87    /// generated from the digits of pi.
88    ///
89    /// # Arguments
90    ///
91    /// * `&self` - Pedersen hasher instance.
92    /// * `x` - The x coordinate of the point to hash.
93    /// * `y` - The y coordinate of the point to hash.
94    #[must_use]
95    pub fn hash<T>(&self, x: T, y: T) -> Option<P::BaseField>
96    where
97        T: Into<P::BaseField>,
98    {
99        let hash: <F::AffineRepr as AffineRepr>::Group = F::P_0.into_group()
100            + Self::process_single_element(x.into(), F::P_1, F::P_2)
101            + Self::process_single_element(y.into(), F::P_3, F::P_4);
102
103        let hash: F::AffineRepr = hash.into();
104        hash.x()
105    }
106}