use crate::serialization::WithContext;
use seal_fhe::{
GaloisKeys, PublicKey as SealPublicKey, RelinearizationKeys, SecretKey as SealSecretKey,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Deserialize, PartialEq, Serialize)]
pub struct PublicKey {
pub public_key: WithContext<SealPublicKey>,
pub galois_key: Option<WithContext<GaloisKeys>>,
pub relin_key: Option<WithContext<RelinearizationKeys>>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub struct PrivateKey(pub(crate) WithContext<SealSecretKey>);
#[cfg(test)]
mod tests {
use super::*;
use crate::*;
use seal_fhe::{CoefficientModulus, PlainModulus, SecurityLevel, ToBytes};
use sunscreen_fhe_program::SchemeType;
#[test]
fn can_roundtrip_seal_public_key() {
let runtime = Runtime::new_fhe(&Params {
lattice_dimension: 8192,
security_level: SecurityLevel::TC128,
plain_modulus: 1234,
scheme_type: SchemeType::Bfv,
coeff_modulus: CoefficientModulus::bfv_default(8192, SecurityLevel::TC128)
.unwrap()
.iter()
.map(|x| x.value())
.collect(),
})
.unwrap();
let (public_key, _) = runtime.generate_keys().unwrap();
let data = bincode::serialize(&public_key.public_key).unwrap();
let enc_key: WithContext<SealPublicKey> = bincode::deserialize(&data).unwrap();
let public_2 = PublicKey {
public_key: enc_key,
..public_key
};
assert_eq!(
public_key.public_key.data.as_bytes(),
public_2.public_key.data.as_bytes()
);
}
#[test]
fn can_roundtrip_seal_galois_keys() {
let runtime = Runtime::new_fhe(&Params {
lattice_dimension: 8192,
security_level: SecurityLevel::TC128,
plain_modulus: PlainModulus::batching(8192, 20).unwrap().value(),
scheme_type: SchemeType::Bfv,
coeff_modulus: CoefficientModulus::bfv_default(8192, SecurityLevel::TC128)
.unwrap()
.iter()
.map(|x| x.value())
.collect(),
})
.unwrap();
let (public_key, _) = runtime.generate_keys().unwrap();
let data = bincode::serialize(&public_key.galois_key.as_ref().unwrap()).unwrap();
let galois_key: WithContext<GaloisKeys> = bincode::deserialize(&data).unwrap();
let public_2 = PublicKey {
galois_key: Some(galois_key),
..public_key
};
assert_eq!(
public_key.galois_key.unwrap().data.as_bytes(),
public_2.galois_key.unwrap().data.as_bytes()
);
}
#[test]
fn can_roundtrip_seal_relin_keys() {
let runtime = Runtime::new_fhe(&Params {
lattice_dimension: 8192,
security_level: SecurityLevel::TC128,
plain_modulus: PlainModulus::batching(8192, 20).unwrap().value(),
scheme_type: SchemeType::Bfv,
coeff_modulus: CoefficientModulus::bfv_default(8192, SecurityLevel::TC128)
.unwrap()
.iter()
.map(|x| x.value())
.collect(),
})
.unwrap();
let (public_key, _) = runtime.generate_keys().unwrap();
let data = serde_json::to_string(&public_key.relin_key.as_ref().unwrap()).unwrap();
let relin_keys: WithContext<RelinearizationKeys> = serde_json::from_str(&data).unwrap();
let public_2 = PublicKey {
relin_key: Some(relin_keys),
..public_key
};
assert_eq!(
public_key.relin_key.unwrap().data.as_bytes(),
public_2.relin_key.unwrap().data.as_bytes()
);
}
#[test]
fn can_roundtrip_all_keys() {
let runtime = Runtime::new_fhe(&Params {
lattice_dimension: 8192,
security_level: SecurityLevel::TC128,
plain_modulus: PlainModulus::batching(8192, 20).unwrap().value(),
scheme_type: SchemeType::Bfv,
coeff_modulus: CoefficientModulus::bfv_default(8192, SecurityLevel::TC128)
.unwrap()
.iter()
.map(|x| x.value())
.collect(),
})
.unwrap();
let (public_key, private_key) = runtime.generate_keys().unwrap();
let data = serde_json::to_string(&public_key).unwrap();
let sk_data = serde_json::to_string(&private_key).unwrap();
let public_2: PublicKey = serde_json::from_str(&data).unwrap();
let private_2: PrivateKey = serde_json::from_str(&sk_data).unwrap();
assert_eq!(
public_key.relin_key.unwrap().data.as_bytes(),
public_2.relin_key.unwrap().data.as_bytes()
);
assert_eq!(
public_key.galois_key.unwrap().data.as_bytes(),
public_2.galois_key.unwrap().data.as_bytes()
);
assert_eq!(
public_key.public_key.data.as_bytes(),
public_2.public_key.data.as_bytes()
);
assert_eq!(private_key.0.as_bytes(), private_2.0.as_bytes());
}
}