use crate::{
core::{
circuits::boolean::{
boolean_value::{Boolean, BooleanValue},
byte::Byte,
},
expressions::{expr::Expr, other_expr::OtherExpr},
global_value::value::FieldValue,
},
traits::{
FromLeBits,
FromLeBytes,
MxeRescueKey,
MxeX25519PrivateKey,
Random,
Reveal,
ToMontgomery,
},
utils::{
curve_point::{Curve, CurvePoint},
elliptic_curve::{is_valid_x25519_public_key, AffineEdwardsPoint, F25519},
field::{BaseField, ScalarField},
matrix::Matrix,
},
MxeBitInput,
MxeInput,
};
use std::ops::Mul;
pub const X25519_PRIVATE_KEY_COUNT: usize = 1;
pub const X25519_PUBLIC_KEY_COUNT: usize = 1;
pub const X25519_PUBLIC_KEY_BYTES_COUNT: usize = 32;
pub const RESCUE_KEY_COUNT: usize = 5;
pub const AES_128_KEY_COUNT: usize = 128;
pub const AES_192_KEY_COUNT: usize = 192;
pub const AES_256_KEY_COUNT: usize = 256;
pub const ED25519_SECRET_KEY_COUNT: usize = 256;
pub const ED25519_SIGNING_KEY_S_COUNT: usize = 1;
pub const ED25519_SIGNING_KEY_HASH_PREFIX_COUNT: usize = 256;
pub const ED25519_VERIFYING_KEY_COUNT: usize = 32;
pub const ELGAMAL_SECRET_KEY_COUNT: usize = 1;
pub const ELGAMAL_PUBKEY_COUNT: usize = 1;
pub const ELGAMAL_PUBKEY_BYTES_COUNT: usize = 32;
#[derive(Copy, Clone)]
pub struct RescueKey<T: Clone + Copy + Random>([T; RESCUE_KEY_COUNT]);
impl<T: Clone + Copy + Random> RescueKey<T> {
pub fn new_from_inner(a: [T; RESCUE_KEY_COUNT]) -> Self {
Self(a)
}
pub fn inner(&self) -> [T; RESCUE_KEY_COUNT] {
self.0
}
pub fn mxe_rescue_key() -> Self
where
T: MxeRescueKey,
{
Self(
(0..RESCUE_KEY_COUNT)
.map(|i| T::mxe_rescue_key(i))
.collect::<Vec<T>>()
.try_into()
.unwrap_or_else(|v: Vec<T>| {
panic!(
"Expected a Vec of length {} (found {})",
RESCUE_KEY_COUNT,
v.len()
)
}),
)
}
}
impl<T: Clone + Copy + Random> Random for RescueKey<T> {
fn random() -> Self {
Self(
(0..RESCUE_KEY_COUNT)
.map(|_| T::random())
.collect::<Vec<T>>()
.try_into()
.unwrap_or_else(|v: Vec<T>| {
panic!(
"Expected a Vec of length {} (found {})",
RESCUE_KEY_COUNT,
v.len()
)
}),
)
}
}
impl<T: Clone + Copy + Random> From<RescueKey<T>> for Matrix<T> {
fn from(key: RescueKey<T>) -> Self {
Matrix::from(key.0.to_vec())
}
}
macro_rules! impl_aes_key {
($t: ident, $byte_len:expr, $key_func_trait: ident, $key_func:ident, $mxe_key: ident) => {
pub trait $key_func_trait {
fn $key_func(i: usize) -> Self;
}
impl $key_func_trait for BooleanValue {
fn $key_func(i: usize) -> Self {
assert!(i < 8 * $byte_len);
Self::from_expr(Expr::Other(OtherExpr::MxeKey(MxeInput::Bit(
MxeBitInput::$t(i),
))))
}
}
impl $key_func_trait for bool {
fn $key_func(i: usize) -> Self {
debug_assert!(i < 8 * $byte_len);
($mxe_key[i / 8] >> (i % 8)) & 1u8 == 1u8
}
}
#[derive(Clone, Copy)]
pub struct $t<B: Boolean>([Byte<B>; $byte_len]);
impl<B: Boolean> $t<B> {
pub fn new_from_inner(a: [Byte<B>; $byte_len]) -> Self {
Self(a)
}
pub fn inner(&self) -> [Byte<B>; $byte_len] {
self.0
}
pub fn mxe_aes_key() -> Self
where
B: $key_func_trait,
{
Self(
(0..8 * $byte_len)
.map(|i| B::$key_func(i))
.collect::<Vec<B>>()
.chunks(8)
.map(|chunk| {
Byte::new(chunk.to_vec().try_into().unwrap_or_else(|v: Vec<B>| {
panic!("Expected a Vec of length 8 (found {})", v.len())
}))
})
.collect::<Vec<Byte<B>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<B>>| {
panic!("Expected a Vec of length {} (found {})", $byte_len, v.len())
}),
)
}
}
impl<B: Boolean> Random for $t<B> {
fn random() -> Self {
Self(
(0..$byte_len)
.map(|_| Byte::<B>::random())
.collect::<Vec<Byte<B>>>()
.try_into()
.unwrap_or_else(|v: Vec<Byte<B>>| {
panic!("Expected a Vec of length {} (found {})", $byte_len, v.len())
}),
)
}
}
impl $t<BooleanValue> {
pub fn compress(&self) -> [FieldValue<BaseField>; ($byte_len as usize).div_ceil(16)] {
self.0
.chunks(16)
.map(|bytes| {
FieldValue::<BaseField>::from_le_bits(
bytes
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
)
})
.collect::<Vec<FieldValue<BaseField>>>()
.try_into()
.unwrap_or_else(|v: Vec<FieldValue<BaseField>>| {
panic!(
"Expected a Vec of length {} (found {})",
($byte_len + 15) / 16,
v.len()
)
})
}
}
};
}
impl_aes_key!(AES128Key, 16, MxeAES128Key, mxe_aes_128_key, MXE_AES128_KEY);
impl_aes_key!(AES192Key, 24, MxeAES192Key, mxe_aes_192_key, MXE_AES192_KEY);
impl_aes_key!(AES256Key, 32, MxeAES256Key, mxe_aes_256_key, MXE_AES256_KEY);
#[derive(Copy, Clone)]
pub struct X25519PrivateKey<S: Clone + Copy> {
key: S,
pub is_expected_non_zero: bool,
}
impl<S: Clone + Copy> X25519PrivateKey<S> {
pub fn new(value: S, is_expected_non_zero: bool) -> Self {
Self {
key: value,
is_expected_non_zero,
}
}
pub fn inner(&self) -> S {
self.key
}
pub fn random<B: Boolean>() -> Self
where
S: FromLeBits<B>,
{
let mut bits = vec![B::from(false); 3];
for _ in 0..251 {
bits.push(B::random());
}
bits.push(B::from(true));
Self {
key: S::from_le_bits(bits, false),
is_expected_non_zero: true,
}
}
pub fn mxe_private_key() -> Self
where
S: MxeX25519PrivateKey,
{
Self {
key: S::mxe_x25519_private_key(),
is_expected_non_zero: true,
}
}
}
impl<S: Clone + Copy + From<ScalarField>> FromLeBytes for X25519PrivateKey<S> {
fn from_le_bytes(bytes: [u8; 32]) -> Self {
let mut key_bytes = bytes;
key_bytes[0] &= 0b1111_1000;
key_bytes[31] &= 0b0111_1111;
key_bytes[31] |= 0b0100_0000;
X25519PrivateKey::new(
S::from(ScalarField::from_le_bits(
key_bytes
.into_iter()
.flat_map(|byte| Byte::from(byte).to_vec())
.collect::<Vec<bool>>(),
false,
)),
true,
)
}
}
impl Default for X25519PrivateKey<ScalarField> {
fn default() -> Self {
Self::from_le_bytes([0u8; 32])
}
}
#[derive(Copy, Clone)]
pub struct X25519PublicKey<C: Curve> {
point: C,
pub is_expected_non_identity: bool,
}
impl<C: Curve> X25519PublicKey<C> {
pub fn new(value: C, is_expected_non_identity: bool) -> Self {
Self {
point: value,
is_expected_non_identity,
}
}
pub fn new_from_private_key<S: Clone + Copy + Mul<C, Output = C>>(
private_key: X25519PrivateKey<S>,
) -> Self {
Self {
point: private_key.inner() * C::generator(),
is_expected_non_identity: private_key.is_expected_non_zero,
}
}
pub fn inner(&self) -> C {
self.point
}
pub fn to_montgomery<Base: F25519>(self) -> (Base, Base)
where
C: ToMontgomery<Output = Base>,
{
self.point.to_montgomery(self.is_expected_non_identity)
}
}
impl X25519PublicKey<CurvePoint> {
pub fn to_le_bytes(&self) -> [u8; 32] {
self.to_montgomery().0.to_le_bytes().map(u8::from)
}
pub fn from_le_bytes(bytes: [u8; 32]) -> Option<Self> {
is_valid_x25519_public_key(bytes).map(|montgomery_point| {
let edwards_point = AffineEdwardsPoint::from_montgomery(montgomery_point);
Self {
point: CurvePoint::from(edwards_point),
is_expected_non_identity: true,
}
})
}
}
impl<C: Curve> Reveal for X25519PublicKey<C> {
fn reveal(self) -> Self {
Self {
point: self.point.reveal(),
is_expected_non_identity: self.is_expected_non_identity,
}
}
}
impl Default for X25519PublicKey<CurvePoint> {
fn default() -> Self {
Self::new_from_private_key(X25519PrivateKey::<ScalarField>::default())
}
}
pub(crate) const MXE_X25519_PRIVATE_KEY: [u8; 32] = [
207, 40, 181, 230, 45, 204, 46, 17, 8, 19, 251, 241, 43, 129, 216, 23, 86, 169, 218, 248, 95,
114, 111, 9, 188, 159, 223, 16, 124, 98, 41, 1,
];
pub(crate) const MXE_RESCUE_BASE_FIELD_KEY: [[u8; 32]; 5] = [
[
124, 219, 118, 100, 151, 174, 173, 201, 180, 159, 95, 202, 109, 154, 90, 104, 99, 221, 206,
79, 44, 221, 182, 198, 143, 180, 180, 121, 78, 223, 238, 12,
],
[
158, 10, 32, 122, 234, 85, 113, 2, 69, 115, 151, 149, 163, 189, 216, 108, 160, 21, 118,
154, 185, 199, 198, 251, 142, 193, 168, 98, 218, 59, 20, 9,
],
[
45, 115, 67, 23, 196, 46, 150, 202, 33, 22, 44, 144, 204, 34, 166, 30, 183, 63, 38, 213,
166, 150, 234, 191, 201, 13, 79, 86, 171, 100, 140, 15,
],
[
209, 1, 108, 251, 175, 105, 199, 246, 83, 186, 72, 0, 15, 236, 105, 110, 5, 109, 41, 216,
148, 98, 208, 128, 32, 47, 224, 93, 90, 176, 33, 2,
],
[
179, 142, 132, 221, 113, 147, 206, 83, 22, 121, 245, 155, 239, 204, 18, 158, 119, 190, 54,
17, 28, 17, 247, 191, 151, 147, 118, 151, 38, 169, 21, 4,
],
];
pub(crate) const MXE_RESCUE_SCALAR_FIELD_KEY: [[u8; 32]; 5] = [
[
72, 239, 104, 144, 184, 215, 25, 76, 171, 209, 107, 34, 146, 39, 35, 134, 103, 10, 38, 148,
251, 155, 69, 207, 216, 234, 104, 220, 253, 63, 217, 14,
],
[
11, 232, 48, 222, 61, 142, 29, 189, 73, 204, 120, 1, 111, 20, 233, 1, 101, 49, 169, 220,
66, 250, 21, 125, 132, 247, 11, 21, 128, 217, 231, 12,
],
[
33, 164, 174, 155, 214, 77, 209, 93, 24, 230, 196, 38, 29, 5, 89, 76, 52, 85, 219, 66, 90,
7, 190, 27, 181, 51, 206, 187, 99, 72, 251, 2,
],
[
7, 178, 214, 42, 8, 10, 134, 249, 244, 69, 192, 63, 96, 204, 229, 10, 126, 3, 33, 49, 174,
26, 149, 5, 254, 118, 230, 75, 149, 105, 145, 5,
],
[
22, 94, 36, 119, 174, 65, 70, 75, 230, 11, 102, 41, 31, 194, 55, 255, 24, 25, 113, 181,
206, 213, 243, 203, 115, 152, 90, 177, 232, 228, 145, 3,
],
];
pub(crate) const MXE_AES128_KEY: [u8; 16] = [
124, 219, 118, 100, 151, 174, 173, 201, 180, 159, 95, 202, 109, 154, 90, 104,
];
pub(crate) const MXE_AES192_KEY: [u8; 24] = [
159, 234, 203, 164, 191, 151, 2, 150, 165, 97, 217, 48, 4, 227, 91, 13, 244, 2, 222, 234, 226,
187, 253, 127,
];
pub(crate) const MXE_AES256_KEY: [u8; 32] = [
196, 120, 191, 34, 144, 89, 36, 185, 242, 159, 162, 158, 170, 37, 234, 191, 33, 141, 52, 147,
253, 3, 58, 49, 169, 146, 53, 185, 1, 55, 60, 87,
];
pub(crate) const MXE_ED25519_SECRET_KEY: [u8; 32] = [
13, 192, 52, 244, 242, 224, 239, 161, 194, 4, 155, 74, 60, 148, 207, 43, 188, 194, 251, 154,
142, 189, 227, 93, 25, 249, 65, 205, 121, 53, 203, 22,
];
pub(crate) const MXE_ED25519_SIGNING_KEY_S: [u8; 32] = [
60, 248, 182, 157, 91, 202, 9, 247, 187, 176, 179, 140, 115, 51, 98, 253, 44, 82, 56, 212, 19,
155, 154, 68, 254, 17, 132, 223, 74, 130, 165, 12,
];
pub(crate) const MXE_ED25519_SIGNING_KEY_HASH_PREFIX: [u8; 32] = [
217, 141, 36, 192, 41, 135, 248, 83, 212, 208, 84, 27, 188, 50, 69, 245, 68, 207, 121, 207, 6,
115, 30, 27, 94, 187, 91, 113, 18, 219, 27, 64,
];
pub(crate) const MXE_ED25519_VERIFYING_KEY: [u8; 32] = [
14, 32, 126, 133, 202, 216, 28, 182, 228, 95, 141, 94, 34, 155, 36, 238, 53, 102, 82, 241, 81,
180, 136, 239, 169, 22, 226, 133, 195, 171, 252, 7,
];
pub(crate) const MXE_ELGAMAL_SECRET_KEY: [u8; 32] = [
57, 71, 187, 92, 7, 239, 222, 40, 252, 52, 135, 191, 198, 199, 173, 77, 31, 119, 254, 244, 152,
71, 131, 255, 183, 183, 182, 191, 87, 99, 182, 3,
];
pub(crate) const MXE_ELGAMAL_PUBKEY: [u8; 32] = [
168, 163, 137, 87, 0, 80, 192, 23, 16, 133, 172, 238, 187, 164, 133, 148, 115, 126, 183, 16,
220, 95, 125, 82, 16, 175, 99, 114, 226, 131, 197, 111,
];