Skip to main content

arcis_compiler/core/
mxe_input.rs

1use crate::{
2    core::{
3        actually_used_field::ActuallyUsedField,
4        bounds::{BoolBounds, Bounds, CurveBounds, FieldBounds},
5        circuits::boolean::byte::Byte,
6        expressions::expr::EvalValue,
7    },
8    traits::FromLeBytes,
9    utils::{
10        crypto::key::{
11            AES_128_KEY_COUNT,
12            AES_192_KEY_COUNT,
13            AES_256_KEY_COUNT,
14            ED25519_SECRET_KEY_COUNT,
15            ED25519_SIGNING_KEY_HASH_PREFIX_COUNT,
16            ED25519_VERIFYING_KEY_COUNT,
17            MXE_AES128_KEY,
18            MXE_AES192_KEY,
19            MXE_AES256_KEY,
20            MXE_ED25519_SECRET_KEY,
21            MXE_ED25519_SIGNING_KEY_HASH_PREFIX,
22            MXE_ED25519_SIGNING_KEY_S,
23            MXE_ED25519_VERIFYING_KEY,
24            MXE_ELGAMAL_PUBKEY,
25            MXE_ELGAMAL_SECRET_KEY,
26            MXE_RESCUE_BASE_FIELD_KEY,
27            MXE_RESCUE_SCALAR_FIELD_KEY,
28            MXE_X25519_PRIVATE_KEY,
29            RESCUE_KEY_COUNT,
30        },
31        curve_point::CurvePoint,
32        field::{BaseField, ScalarField},
33    },
34};
35use curve25519_dalek_arcium_fork::ristretto::CompressedRistretto;
36use ff::PrimeField;
37use serde::{Deserialize, Serialize};
38use std::marker::PhantomData;
39
40/// `pub trait` but meant to be closed.
41pub trait ArxInput {
42    type Output;
43    /// Whether this `MxeInput` is plaintext.
44    fn is_plaintext(&self) -> bool;
45    /// The mock value of this `MxeInput`.
46    fn mock_eval(&self) -> Self::Output;
47}
48
49/// An input given by the MXE, not by the user.
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
51pub enum MxeInput {
52    Bit(MxeBitInput),
53    ScalarOnly(MxeScalarInput),
54    Scalar(MxeFieldInput<ScalarField>),
55    Base(MxeFieldInput<BaseField>),
56    Curve(MxeCurveInput),
57}
58
59impl MxeInput {
60    /// The bounds of this `MxeInput`.
61    pub fn bounds(&self) -> Bounds {
62        match self {
63            MxeInput::Bit(_) => Bounds::Bit(BoolBounds::new(true, true)),
64            MxeInput::ScalarOnly(_) => Bounds::Scalar(FieldBounds::All),
65            MxeInput::Scalar(i) => Bounds::Scalar(i.bounds()),
66            MxeInput::Base(i) => Bounds::Base(i.bounds()),
67            MxeInput::Curve(_) => Bounds::Curve(CurveBounds::All),
68        }
69    }
70}
71
72impl ArxInput for MxeInput {
73    type Output = EvalValue;
74    fn is_plaintext(&self) -> bool {
75        match self {
76            MxeInput::Bit(i) => i.is_plaintext(),
77            MxeInput::ScalarOnly(i) => i.is_plaintext(),
78            MxeInput::Scalar(i) => i.is_plaintext(),
79            MxeInput::Base(i) => i.is_plaintext(),
80            MxeInput::Curve(i) => i.is_plaintext(),
81        }
82    }
83    fn mock_eval(&self) -> Self::Output {
84        match self {
85            MxeInput::Bit(i) => EvalValue::Bit(i.mock_eval()),
86            MxeInput::ScalarOnly(i) => EvalValue::Scalar(i.mock_eval()),
87            MxeInput::Scalar(i) => EvalValue::Scalar(i.mock_eval()),
88            MxeInput::Base(i) => EvalValue::Base(i.mock_eval()),
89            MxeInput::Curve(i) => EvalValue::Curve(i.mock_eval()),
90        }
91    }
92}
93
94/// A `bool` MXE input.
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
96pub enum MxeBitInput {
97    /// The MXE aes-128 key.
98    AES128Key(usize),
99    /// The MXE aes-192 key.
100    AES192Key(usize),
101    /// The MXE aes-256 key.
102    AES256Key(usize),
103    /// The MXE ed25519 secret key.
104    Ed25519SecretKey(usize),
105    /// The MXE ed25519 signing key hash-prefix.
106    Ed25519SigningKeyHashPrefix(usize),
107}
108
109impl ArxInput for MxeBitInput {
110    type Output = bool;
111
112    fn is_plaintext(&self) -> bool {
113        false
114    }
115
116    fn mock_eval(&self) -> Self::Output {
117        match *self {
118            MxeBitInput::AES128Key(i) => {
119                if i < AES_128_KEY_COUNT {
120                    Byte::from(MXE_AES128_KEY[i / 8]).get_bits()[i % 8]
121                } else {
122                    false
123                }
124            }
125            MxeBitInput::AES192Key(i) => {
126                if i < AES_192_KEY_COUNT {
127                    Byte::from(MXE_AES192_KEY[i / 8]).get_bits()[i % 8]
128                } else {
129                    false
130                }
131            }
132            MxeBitInput::AES256Key(i) => {
133                if i < AES_256_KEY_COUNT {
134                    Byte::from(MXE_AES256_KEY[i / 8]).get_bits()[i % 8]
135                } else {
136                    false
137                }
138            }
139            MxeBitInput::Ed25519SecretKey(i) => {
140                if i < ED25519_SECRET_KEY_COUNT {
141                    Byte::from(MXE_ED25519_SECRET_KEY[i / 8]).get_bits()[i % 8]
142                } else {
143                    false
144                }
145            }
146            MxeBitInput::Ed25519SigningKeyHashPrefix(i) => {
147                if i < ED25519_SIGNING_KEY_HASH_PREFIX_COUNT {
148                    Byte::from(MXE_ED25519_SIGNING_KEY_HASH_PREFIX[i / 8]).get_bits()[i % 8]
149                } else {
150                    false
151                }
152            }
153        }
154    }
155}
156
157/// A `ScalarField` MXE input.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
159pub enum MxeScalarInput {
160    /// The MXE x25519 private key.
161    X25519PrivateKey(),
162    /// The MXE ed25519 signing key s.
163    Ed25519SigningKeyS(),
164    /// The ElGamal secret key, used for c-spl.
165    ElGamalSecretKey(),
166}
167
168impl ArxInput for MxeScalarInput {
169    type Output = ScalarField;
170
171    fn is_plaintext(&self) -> bool {
172        false
173    }
174
175    fn mock_eval(&self) -> Self::Output {
176        match self {
177            MxeScalarInput::X25519PrivateKey() => {
178                ScalarField::from_le_bytes(MXE_X25519_PRIVATE_KEY)
179            }
180            MxeScalarInput::Ed25519SigningKeyS() => {
181                ScalarField::from_le_bytes(MXE_ED25519_SIGNING_KEY_S)
182            }
183            MxeScalarInput::ElGamalSecretKey() => {
184                ScalarField::from_le_bytes(MXE_ELGAMAL_SECRET_KEY)
185            }
186        }
187    }
188}
189
190/// An MXE input that could exist on any field.
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
192pub enum MxeFieldInput<F: ActuallyUsedField> {
193    /// The MXE ed25519 verifying key.
194    Ed25519VerifyingKey(usize),
195    /// Rescue Key.
196    RescueKey(usize),
197    /// Do not use.
198    Phantom(PhantomData<F>),
199}
200
201impl<F: ActuallyUsedField> MxeFieldInput<F> {
202    pub fn bounds(&self) -> FieldBounds<F> {
203        match self {
204            MxeFieldInput::Ed25519VerifyingKey(_) => FieldBounds::new(F::ZERO, F::from(255)),
205            MxeFieldInput::RescueKey(_) => FieldBounds::All,
206            MxeFieldInput::Phantom(_) => {
207                panic!("Phantom type cannot be created.")
208            }
209        }
210    }
211}
212
213impl<F: ActuallyUsedField> ArxInput for MxeFieldInput<F> {
214    type Output = F;
215    fn is_plaintext(&self) -> bool {
216        match self {
217            MxeFieldInput::Ed25519VerifyingKey(_) => true,
218            MxeFieldInput::RescueKey(_) => false,
219            MxeFieldInput::Phantom(_) => {
220                panic!("Phantom type is not supported")
221            }
222        }
223    }
224    fn mock_eval(&self) -> F {
225        match *self {
226            MxeFieldInput::Ed25519VerifyingKey(i) => {
227                if i < ED25519_VERIFYING_KEY_COUNT {
228                    F::from(MXE_ED25519_VERIFYING_KEY[i] as u64)
229                } else {
230                    F::ZERO
231                }
232            }
233            MxeFieldInput::RescueKey(i) => {
234                if i < RESCUE_KEY_COUNT {
235                    match F::MODULUS {
236                        BaseField::MODULUS => F::from_le_bytes(MXE_RESCUE_BASE_FIELD_KEY[i]),
237                        ScalarField::MODULUS => F::from_le_bytes(MXE_RESCUE_SCALAR_FIELD_KEY[i]),
238                        _ => F::ZERO,
239                    }
240                } else {
241                    F::ZERO
242                }
243            }
244            MxeFieldInput::Phantom(_) => {
245                panic!("Phantom type is not supported")
246            }
247        }
248    }
249}
250
251/// An MXE input that is a curve point.
252#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
253pub enum MxeCurveInput {
254    /// The ElGamal pubkey, used for c-spl.
255    ElGamalPubkey(),
256}
257
258impl ArxInput for MxeCurveInput {
259    type Output = CurvePoint;
260
261    fn is_plaintext(&self) -> bool {
262        true
263    }
264    fn mock_eval(&self) -> CurvePoint {
265        match self {
266            MxeCurveInput::ElGamalPubkey() => {
267                let point = CompressedRistretto::from_slice(&MXE_ELGAMAL_PUBKEY)
268                    .unwrap()
269                    .decompress()
270                    .unwrap();
271                CurvePoint::new(point)
272            }
273        }
274    }
275}