-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
81eef39
commit 80373eb
Showing
5 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
use bincode::Options; | ||
use serde::de::DeserializeOwned; | ||
use serde::Serialize; | ||
|
||
const VERSION: &str = "0.3.0"; | ||
|
||
const VERSION_LENGTH_LIMIT: u64 = 100; | ||
|
||
const TYPE_LENGTH_LIMIT: u64 = 1000; | ||
|
||
pub fn safe_serialize<T: Serialize>( | ||
object: &T, | ||
mut writer: impl std::io::Write, | ||
serialized_size_limit: u64, | ||
) -> bincode::Result<()> { | ||
let options = bincode::DefaultOptions::new() | ||
.with_fixint_encoding() | ||
.with_limit(0); | ||
|
||
options | ||
.with_limit(VERSION_LENGTH_LIMIT) | ||
.serialize_into::<_, String>(&mut writer, &VERSION.to_owned())?; | ||
|
||
options | ||
.with_limit(TYPE_LENGTH_LIMIT) | ||
.serialize_into::<_, String>(&mut writer, &std::any::type_name::<T>().to_owned())?; | ||
|
||
options | ||
.with_limit(serialized_size_limit) | ||
.serialize_into(&mut writer, object)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn safe_deserialize<T: DeserializeOwned>( | ||
mut reader: impl std::io::Read, | ||
serialized_size_limit: u64, | ||
) -> Result<T, String> { | ||
let options = bincode::DefaultOptions::new() | ||
.with_fixint_encoding() | ||
.with_limit(0); | ||
|
||
let deserialized_version: String = options | ||
.with_limit(10000) | ||
.deserialize_from::<_, String>(&mut reader) | ||
.map_err(|err| err.to_string())?; | ||
|
||
if deserialized_version != VERSION { | ||
return Err(format!( | ||
"Expected version {}, got version {}", | ||
VERSION, deserialized_version | ||
)); | ||
} | ||
|
||
let deserialized_type: String = options | ||
.with_limit(TYPE_LENGTH_LIMIT) | ||
.deserialize_from::<_, String>(&mut reader) | ||
.map_err(|err| err.to_string())?; | ||
|
||
if deserialized_type != std::any::type_name::<T>() { | ||
return Err(format!( | ||
"Expected type {}, got type {}", | ||
std::any::type_name::<T>(), | ||
deserialized_type | ||
)); | ||
} | ||
|
||
options | ||
.with_limit(serialized_size_limit) | ||
.deserialize_from(&mut reader) | ||
.map_err(|err| err.to_string()) | ||
} | ||
|
||
pub trait ParameterSetConformant { | ||
type ParameterSet; | ||
|
||
fn conformant(&self, param: &Self::ParameterSet) -> bool; | ||
} | ||
|
||
pub fn safe_deserialize_conformant<T: DeserializeOwned + ParameterSetConformant>( | ||
reader: impl std::io::Read, | ||
serialized_size_limit: u64, | ||
parameter: &T::ParameterSet, | ||
) -> Result<T, String> { | ||
let deser: T = safe_deserialize(reader, serialized_size_limit)?; | ||
|
||
if !deser.conformant(parameter) { | ||
return Err("Deserialized object not conformant with given parameter set".to_owned()); | ||
} | ||
|
||
Ok(deser) | ||
} | ||
|
||
pub trait ParameterSetSerializationSized: Serialize + DeserializeOwned { | ||
type ParameterSet; | ||
|
||
fn serialized_size(param: &Self::ParameterSet) -> u64; | ||
} | ||
|
||
pub fn safe_deserialize_conformant_know_size<T, U>( | ||
reader: impl std::io::Read, | ||
parameter: &U, | ||
) -> Result<T, String> | ||
where | ||
T: ParameterSetSerializationSized<ParameterSet = U>, | ||
T: ParameterSetConformant<ParameterSet = U>, | ||
{ | ||
safe_deserialize_conformant(reader, T::serialized_size(parameter), parameter) | ||
} | ||
|
||
#[cfg(all(test, feature = "shortint"))] | ||
mod test { | ||
|
||
use crate::safe_serialization::{safe_deserialize_conformant, safe_serialize}; | ||
use crate::shortint::parameters::{ | ||
PARAM_MESSAGE_2_CARRY_2_KS_PBS, PARAM_MESSAGE_3_CARRY_3_KS_PBS, | ||
}; | ||
use crate::shortint::{gen_keys, Ciphertext, PBSParameters}; | ||
|
||
#[test] | ||
fn safe_ser_ct() { | ||
let (ck, _sk) = gen_keys(PARAM_MESSAGE_2_CARRY_2_KS_PBS); | ||
|
||
let msg = 2_u64; | ||
|
||
let ct = ck.encrypt(msg); | ||
|
||
let mut buffer = vec![]; | ||
|
||
safe_serialize(&ct, &mut buffer, 1 << 40).unwrap(); | ||
|
||
assert!(safe_deserialize_conformant::<Ciphertext>( | ||
buffer.as_slice(), | ||
1 << 40, | ||
&PBSParameters::PBS(PARAM_MESSAGE_3_CARRY_3_KS_PBS), | ||
) | ||
.is_err()); | ||
|
||
let ct2 = safe_deserialize_conformant( | ||
buffer.as_slice(), | ||
1 << 40, | ||
&PBSParameters::PBS(PARAM_MESSAGE_2_CARRY_2_KS_PBS), | ||
) | ||
.unwrap(); | ||
|
||
let dec = ck.decrypt(&ct2); | ||
assert_eq!(msg, dec); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters