zkgroup/crypto/
profile_key_credential_request.rs

1//
2// Copyright 2020-2022 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6#![allow(non_snake_case)]
7
8use curve25519_dalek_signal::constants::RISTRETTO_BASEPOINT_POINT;
9use curve25519_dalek_signal::ristretto::RistrettoPoint;
10use curve25519_dalek_signal::scalar::Scalar;
11use partial_default::PartialDefault;
12use serde::{Deserialize, Serialize};
13
14use crate::common::sho::*;
15use crate::crypto::credentials::{
16    BlindedExpiringProfileKeyCredential, ExpiringProfileKeyCredential,
17};
18use crate::crypto::profile_key_struct;
19
20#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
21pub struct KeyPair {
22    // private
23    pub(crate) y: Scalar,
24
25    // public
26    pub(crate) Y: RistrettoPoint,
27}
28
29#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
30pub struct PublicKey {
31    pub(crate) Y: RistrettoPoint,
32}
33
34#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
35pub struct CiphertextWithSecretNonce {
36    pub(crate) r1: Scalar,
37    pub(crate) r2: Scalar,
38    pub(crate) D1: RistrettoPoint,
39    pub(crate) D2: RistrettoPoint,
40    pub(crate) E1: RistrettoPoint,
41    pub(crate) E2: RistrettoPoint,
42}
43
44#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, PartialDefault)]
45pub struct Ciphertext {
46    pub(crate) D1: RistrettoPoint,
47    pub(crate) D2: RistrettoPoint,
48    pub(crate) E1: RistrettoPoint,
49    pub(crate) E2: RistrettoPoint,
50}
51
52impl KeyPair {
53    pub fn generate(sho: &mut Sho) -> Self {
54        let y = sho.get_scalar();
55        let Y = y * RISTRETTO_BASEPOINT_POINT;
56        KeyPair { y, Y }
57    }
58
59    pub fn get_public_key(&self) -> PublicKey {
60        PublicKey { Y: self.Y }
61    }
62
63    pub fn encrypt(
64        &self,
65        profile_key_struct: profile_key_struct::ProfileKeyStruct,
66        sho: &mut Sho,
67    ) -> CiphertextWithSecretNonce {
68        let r1 = sho.get_scalar();
69        let r2 = sho.get_scalar();
70        let D1 = r1 * RISTRETTO_BASEPOINT_POINT;
71        let E1 = r2 * RISTRETTO_BASEPOINT_POINT;
72
73        let D2 = r1 * (self.Y) + profile_key_struct.M3;
74        let E2 = r2 * (self.Y) + profile_key_struct.M4;
75
76        CiphertextWithSecretNonce {
77            r1,
78            r2,
79            D1,
80            D2,
81            E1,
82            E2,
83        }
84    }
85
86    pub fn decrypt_blinded_expiring_profile_key_credential(
87        &self,
88        blinded_expiring_profile_key_credential: BlindedExpiringProfileKeyCredential,
89    ) -> ExpiringProfileKeyCredential {
90        let V = blinded_expiring_profile_key_credential.S2
91            - self.y * blinded_expiring_profile_key_credential.S1;
92        ExpiringProfileKeyCredential {
93            t: blinded_expiring_profile_key_credential.t,
94            U: blinded_expiring_profile_key_credential.U,
95            V,
96        }
97    }
98}
99
100impl CiphertextWithSecretNonce {
101    pub fn get_ciphertext(&self) -> Ciphertext {
102        Ciphertext {
103            D1: self.D1,
104            D2: self.D2,
105            E1: self.E1,
106            E2: self.E2,
107        }
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use crate::common::constants::*;
115    use crate::crypto::profile_key_commitment;
116
117    #[test]
118    fn test_request_response() {
119        let mut sho = Sho::new(b"Test_Profile_Key_Credential_Request", b"");
120
121        // client
122        let blind_key_pair = KeyPair::generate(&mut sho);
123
124        // server and client
125        let profile_key_struct =
126            profile_key_struct::ProfileKeyStruct::new(TEST_ARRAY_32, TEST_ARRAY_16);
127        let _ = profile_key_commitment::CommitmentWithSecretNonce::new(
128            profile_key_struct,
129            TEST_ARRAY_16,
130        );
131
132        // client
133        let _ = blind_key_pair.encrypt(profile_key_struct, &mut sho);
134
135        // server
136        /*TODO request_ciphertext.verify(c).unwrap();
137
138        let credential_key_pair = credentials::KeyPair::generate(TEST_ARRAY_32_2);
139        let uid_bytes = TEST_ARRAY_16;
140        let redemption_time = 37;
141        let randomness = TEST_ARRAY_32_3;
142        let response =
143            query.create_response(credential_key_pair, uid_bytes, redemption_time, randomness);
144
145        response
146            .verify(
147                blind_key_pair,
148                credential_key_pair.get_public_key(),
149                query.E_D1,
150                query.E_D2,
151                uid_bytes,
152                redemption_time,
153            )
154            .unwrap();
155
156        let mac = response.get_mac(blind_key_pair);
157
158        let master_key = GroupMasterKey::new(TEST_ARRAY_32_4);
159        let uid_enc_key_pair = uid_encryption::KeyPair::derive_from(master_key);
160        let profile_enc_key_pair = KeyPair::generate(TEST_ARRAY_32_4);
161        let profile_ciphertext = profile_enc_key_pair
162            .get_public_key()
163            .encrypt(profile_key, TEST_ARRAY_32_4);
164
165        let ppp = profile_presentation_proof::PresentationProof::new(
166            mac,
167            uid_enc_key_pair,
168            credential_key_pair.get_public_key(),
169            uid_bytes,
170            profile_ciphertext.E_B1,
171            profile_ciphertext.E_B2,
172            profile_key,
173            profile_enc_key_pair.B,
174            profile_enc_key_pair.b,
175            redemption_time,
176            TEST_ARRAY_32_5,
177        );
178
179        let uid = uid_encryption::UidStruct::new(uid_bytes);
180        let uid_ciphertext = uid_enc_key_pair.encrypt(uid);
181
182        ppp.verify(
183            uid_ciphertext,
184            uid_enc_key_pair.get_public_key(),
185            credential_key_pair,
186            redemption_time,
187            profile_ciphertext.E_B1,
188            profile_ciphertext.E_B2,
189            profile_enc_key_pair.B,
190        ).unwrap();
191        */
192    }
193}