zkgroup/crypto/
profile_key_commitment.rs

1//
2// Copyright 2020 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6#![allow(non_snake_case)]
7
8use std::sync::LazyLock;
9
10use curve25519_dalek_signal::ristretto::RistrettoPoint;
11use curve25519_dalek_signal::scalar::Scalar;
12use partial_default::PartialDefault;
13use serde::{Deserialize, Serialize};
14
15use crate::common::constants::*;
16use crate::common::sho::*;
17use crate::common::simple_types::*;
18use crate::crypto::profile_key_struct;
19
20static SYSTEM_PARAMS: LazyLock<SystemParams> =
21    LazyLock::new(|| crate::deserialize::<SystemParams>(&SystemParams::SYSTEM_HARDCODED).unwrap());
22
23#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
24pub struct SystemParams {
25    pub(crate) G_j1: RistrettoPoint,
26    pub(crate) G_j2: RistrettoPoint,
27    pub(crate) G_j3: RistrettoPoint,
28}
29
30#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub struct CommitmentWithSecretNonce {
32    pub(crate) J1: RistrettoPoint,
33    pub(crate) J2: RistrettoPoint,
34    pub(crate) J3: RistrettoPoint,
35    pub(crate) j3: Scalar,
36}
37
38#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
39pub struct Commitment {
40    pub(crate) J1: RistrettoPoint,
41    pub(crate) J2: RistrettoPoint,
42    pub(crate) J3: RistrettoPoint,
43}
44
45impl SystemParams {
46    pub fn generate() -> Self {
47        let mut sho = Sho::new(
48            b"Signal_ZKGroup_20200424_Constant_ProfileKeyCommitment_SystemParams_Generate",
49            b"",
50        );
51        let G_j1 = sho.get_point();
52        let G_j2 = sho.get_point();
53        let G_j3 = sho.get_point();
54        SystemParams { G_j1, G_j2, G_j3 }
55    }
56
57    pub fn get_hardcoded() -> SystemParams {
58        *SYSTEM_PARAMS
59    }
60
61    const SYSTEM_HARDCODED: [u8; 96] = [
62        0xa8, 0xca, 0xb, 0xbd, 0x11, 0x48, 0xc4, 0x66, 0x72, 0x58, 0x60, 0x64, 0xa, 0xc5, 0x3d,
63        0x27, 0x72, 0xb1, 0x4e, 0xea, 0xe0, 0x17, 0xa, 0x38, 0xc6, 0x2c, 0x7b, 0x3d, 0xd2, 0x9c,
64        0x3e, 0x4a, 0x14, 0xb9, 0x46, 0x2d, 0x94, 0x8f, 0x5, 0x94, 0x50, 0x79, 0x9f, 0x4c, 0xc2,
65        0xa0, 0x6e, 0x55, 0xde, 0xc8, 0x7, 0x73, 0x56, 0x70, 0xb9, 0x4a, 0x5c, 0xe8, 0xf, 0x59,
66        0xf1, 0x95, 0x8, 0x61, 0xb0, 0xc0, 0xf7, 0xb9, 0x1f, 0x6e, 0xf9, 0xc7, 0x55, 0x60, 0x93,
67        0xd8, 0x93, 0xa, 0x86, 0xbd, 0x36, 0x18, 0x8c, 0xec, 0x74, 0x5, 0x54, 0x65, 0x7d, 0x92,
68        0xdc, 0xd8, 0x6a, 0xad, 0x25, 0x1c,
69    ];
70}
71
72impl CommitmentWithSecretNonce {
73    pub fn new(
74        profile_key: profile_key_struct::ProfileKeyStruct,
75        uid_bytes: UidBytes,
76    ) -> CommitmentWithSecretNonce {
77        let commitment_system = SystemParams::get_hardcoded();
78
79        let profile_key_struct::ProfileKeyStruct { M3, M4, .. } = profile_key;
80        let j3 = Self::calc_j3(profile_key.bytes, uid_bytes);
81        let J1 = (j3 * commitment_system.G_j1) + M3;
82        let J2 = (j3 * commitment_system.G_j2) + M4;
83        let J3 = j3 * commitment_system.G_j3;
84        CommitmentWithSecretNonce { J1, J2, J3, j3 }
85    }
86
87    pub fn get_profile_key_commitment(&self) -> Commitment {
88        Commitment {
89            J1: self.J1,
90            J2: self.J2,
91            J3: self.J3,
92        }
93    }
94
95    pub fn calc_j3(profile_key_bytes: ProfileKeyBytes, uid_bytes: UidBytes) -> Scalar {
96        let mut combined_array = [0u8; PROFILE_KEY_LEN + UUID_LEN];
97        combined_array[..PROFILE_KEY_LEN].copy_from_slice(&profile_key_bytes);
98        combined_array[PROFILE_KEY_LEN..].copy_from_slice(&uid_bytes);
99        Sho::new(
100            b"Signal_ZKGroup_20200424_ProfileKeyAndUid_ProfileKeyCommitment_Calcj3",
101            &combined_array,
102        )
103        .get_scalar()
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_system() {
113        let params = SystemParams::generate();
114        println!("PARAMS = {:#x?}", bincode::serialize(&params));
115        assert!(SystemParams::generate() == SystemParams::get_hardcoded());
116    }
117
118    #[test]
119    fn test_commitment() {
120        let profile_key = profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16);
121        let c1 = CommitmentWithSecretNonce::new(profile_key, TEST_ARRAY_16);
122        let c2 = CommitmentWithSecretNonce::new(profile_key, TEST_ARRAY_16);
123        assert!(c1 == c2);
124    }
125}