use crate::{
core::{
circuits::{
boolean::{boolean_value::BooleanValue, ed25519::Ed25519SecretKey, sha3::SHA3_256},
key_recovery::{utils::reed_solomon::KeyRecoveryReedSolomonInit, MXE_KEYS_ENC_COUNT},
},
global_value::{curve_array::CurveArray, field_array::FieldArray, value::FieldValue},
},
traits::{FromLeBits, GetBit, Reveal, ToLeBytes},
utils::{
crypto::{
key::{
AES128Key,
AES192Key,
AES256Key,
RescueKey,
X25519PrivateKey,
X25519PublicKey,
RESCUE_KEY_COUNT,
},
rescue_cipher::RescueCipher,
},
field::{BaseField, ScalarField},
zkp::elgamal::ElGamalSecretKey,
},
};
use ff::PrimeField;
#[allow(dead_code)]
pub fn key_recovery_init<const N: usize, const D: usize>(
base_mxe_x25519_private_key: X25519PrivateKey<FieldValue<ScalarField>>,
mxe_rescue_base_field_key: RescueKey<FieldValue<BaseField>>,
peer_x25519_pubkeys: X25519PublicKey<CurveArray<N>>,
nonce: FieldValue<BaseField>,
n: FieldValue<BaseField>,
g: [FieldValue<BaseField>; D],
) -> [FieldArray<N, BaseField>; RESCUE_KEY_COUNT] {
assert_eq!(D, N - (N - 1) / 3);
let rescue_base_field_key_shares = mxe_rescue_base_field_key.inner().map(|key| {
FieldArray::from(KeyRecoveryReedSolomonInit::encode::<
N,
D,
BooleanValue,
FieldValue<BaseField>,
>(key, g, (n - 1) / 3 + 1))
});
let base_mxe_x25519_private_key_vec = X25519PrivateKey::new(
FieldArray::<N, ScalarField>::from(base_mxe_x25519_private_key.inner()),
base_mxe_x25519_private_key.is_expected_non_zero,
);
let peer_ciphers = RescueCipher::new_with_client_from_keys(
base_mxe_x25519_private_key_vec,
peer_x25519_pubkeys,
);
let rescue_base_field_key_shares_enc = peer_ciphers
.encrypt(
rescue_base_field_key_shares.to_vec(),
FieldArray::from(nonce),
)
.try_into()
.unwrap_or_else(|v: Vec<FieldArray<N, BaseField>>| {
panic!(
"Expected a Vec of length {} (found {})",
RESCUE_KEY_COUNT,
v.len()
)
});
rescue_base_field_key_shares_enc
}
#[allow(dead_code, clippy::too_many_arguments)]
pub fn key_encryption_init(
mxe_rescue_base_field_key: RescueKey<FieldValue<BaseField>>,
nonce: FieldValue<BaseField>,
mxe_x25519_private_key: X25519PrivateKey<FieldValue<ScalarField>>,
mxe_rescue_scalar_field_key: RescueKey<FieldValue<ScalarField>>,
mxe_aes_128_key: AES128Key<BooleanValue>,
mxe_aes_192_key: AES192Key<BooleanValue>,
mxe_aes_256_key: AES256Key<BooleanValue>,
mxe_ed25519_secret_key: Ed25519SecretKey,
mxe_elgamal_secret_key: ElGamalSecretKey,
) -> [FieldValue<BaseField>; MXE_KEYS_ENC_COUNT] {
let mxe_cipher = RescueCipher::new(mxe_rescue_base_field_key);
let mxe_x25519_private_key = FieldValue::<BaseField>::from_le_bits(
(0..ScalarField::NUM_BITS as usize)
.map(|i| mxe_x25519_private_key.inner().get_bit(i, false))
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_rescue_scalar_field_key = mxe_rescue_scalar_field_key.inner().map(|key| {
FieldValue::<BaseField>::from_le_bits(
(0..ScalarField::NUM_BITS as usize)
.map(|i| key.get_bit(i, false))
.collect::<Vec<BooleanValue>>(),
false,
)
});
let mxe_aes_128_key_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_aes_128_key
.inner()
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_aes_192_key_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_aes_192_key
.inner()
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_aes_256_key_bits = mxe_aes_256_key
.inner()
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>();
let mxe_aes_256_key_lo_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_aes_256_key_bits
.iter()
.copied()
.take(128)
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_aes_256_key_hi_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_aes_256_key_bits
.iter()
.copied()
.skip(128)
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_ed25519_secret_key_bits = mxe_ed25519_secret_key
.inner()
.into_iter()
.flat_map(|byte| byte.to_vec())
.collect::<Vec<BooleanValue>>();
let mxe_ed25519_secret_key_lo_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_ed25519_secret_key_bits
.iter()
.copied()
.take(128)
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_ed25519_secret_key_hi_compressed = FieldValue::<BaseField>::from_le_bits(
mxe_ed25519_secret_key_bits
.iter()
.copied()
.skip(128)
.collect::<Vec<BooleanValue>>(),
false,
);
let mxe_elgamal_secret_key = FieldValue::<BaseField>::from_le_bits(
(0..ScalarField::NUM_BITS as usize)
.map(|i| mxe_elgamal_secret_key.get_scalar().get_bit(i, false))
.collect::<Vec<BooleanValue>>(),
false,
);
let mut mxe_keys = vec![mxe_x25519_private_key];
mxe_keys.extend(mxe_rescue_scalar_field_key);
mxe_keys.extend(vec![
mxe_aes_128_key_compressed,
mxe_aes_192_key_compressed,
mxe_aes_256_key_lo_compressed,
mxe_aes_256_key_hi_compressed,
mxe_ed25519_secret_key_lo_compressed,
mxe_ed25519_secret_key_hi_compressed,
mxe_elgamal_secret_key,
]);
let mxe_keys_enc = mxe_cipher
.encrypt(mxe_keys, nonce)
.try_into()
.unwrap_or_else(|v: Vec<FieldValue<BaseField>>| {
panic!(
"Expected a Vec of length {} (found {})",
MXE_KEYS_ENC_COUNT,
v.len()
)
});
mxe_keys_enc
}
#[allow(dead_code, clippy::too_many_arguments)]
pub fn hash_keys(
mxe_x25519_private_key: X25519PrivateKey<FieldValue<ScalarField>>,
mxe_rescue_base_field_key: RescueKey<FieldValue<BaseField>>,
mxe_rescue_scalar_field_key: RescueKey<FieldValue<ScalarField>>,
mxe_aes_128_key: AES128Key<BooleanValue>,
mxe_aes_192_key: AES192Key<BooleanValue>,
mxe_aes_256_key: AES256Key<BooleanValue>,
mxe_ed25519_secret_key: Ed25519SecretKey,
mxe_elgamal_secret_key: ElGamalSecretKey,
) -> [FieldValue<BaseField>; 32] {
let mut mxe_keys = mxe_x25519_private_key.inner().to_le_bytes().to_vec();
mxe_keys.extend(
mxe_rescue_base_field_key
.inner()
.into_iter()
.flat_map(|key| key.to_le_bytes().to_vec()),
);
mxe_keys.extend(
mxe_rescue_scalar_field_key
.inner()
.into_iter()
.flat_map(|key| key.to_le_bytes().to_vec()),
);
mxe_keys.extend(mxe_aes_128_key.inner());
mxe_keys.extend(mxe_aes_192_key.inner());
mxe_keys.extend(mxe_aes_256_key.inner());
mxe_keys.extend(mxe_ed25519_secret_key.inner());
mxe_keys.extend(mxe_elgamal_secret_key.get_scalar().to_le_bytes());
let hasher = SHA3_256::new();
let digest = hasher.digest(mxe_keys);
digest.map(|byte| FieldValue::<BaseField>::from(byte.reveal()))
}