diff --git a/src/serde_impl.rs b/src/serde_impl.rs index 8fdad40..da634fe 100644 --- a/src/serde_impl.rs +++ b/src/serde_impl.rs @@ -24,6 +24,15 @@ pub(crate) mod serialize_secret_internal { pub trait SerializeSecret { fn serialize_secret(&self, serializer: S) -> Result; } + + impl SerializeSecret for &T { + fn serialize_secret( + &self, + serializer: S, + ) -> Result<::Ok, ::Error> { + (*self).serialize_secret(serializer) + } + } } /// `SerdeSecret` is a wrapper struct for serializing and deserializing secret keys. Due to security @@ -53,21 +62,91 @@ impl SerdeSecret { } impl<'de, T: Deserialize<'de>> Deserialize<'de> for SerdeSecret { - fn deserialize(deserializer: D) -> Result where - D: Deserializer<'de> + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, { Ok(SerdeSecret(Deserialize::deserialize(deserializer)?)) } } impl<'de, T: SerializeSecret> Serialize for SerdeSecret { - fn serialize(&self, serializer: S) -> Result where - S: Serializer + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, { self.0.serialize_secret(serializer) } } +#[cfg(not(feature = "use-insecure-test-only-mock-crypto"))] +impl<'de> Deserialize<'de> for crate::SecretKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + use pairing::bls12_381; + use pairing::PrimeField; + + use serde::de; + use std::fmt; + + struct ReprVisitor; + impl<'de> serde::de::Visitor<'de> for ReprVisitor { + type Value = [u64; 4]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "A tuple of four u64 integers.") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut repr = [0u64; 4]; + for (num, part) in repr.iter_mut().enumerate() { + *part = match seq.next_element()? { + Some(x) => x, + None => return Err(de::Error::invalid_length(num + 1, &"Expected 4 u64s")), + }; + } + Ok(repr) + } + } + + let repr = deserializer.deserialize_tuple(4, ReprVisitor)?; + let mut fr = match bls12_381::Fr::from_repr(bls12_381::FrRepr(repr)) { + Ok(x) => x, + Err(pairing::PrimeFieldDecodingError::NotInField(_)) => { + return Err(de::Error::invalid_value( + de::Unexpected::Other(&"Number outside of prime field."), + &"Valid prime field element.", + )) + } + }; + + Ok(crate::SecretKey::from_mut(&mut fr)) + } +} + +#[cfg(not(feature = "use-insecure-test-only-mock-crypto"))] +impl SerializeSecret for crate::SecretKey { + fn serialize_secret(&self, serializer: S) -> Result { + use pairing::PrimeField; + use serde::ser::SerializeTuple; + + let repr: &[u64] = &self.0.into_repr().0; + debug_assert_eq!(repr.len(), 4); + + let mut serialize_tuple = serializer.serialize_tuple(4)?; + for part in repr { + serialize_tuple.serialize_element(part)?; + } + + serialize_tuple.end() + } +} + /// A type with the same content as `BivarCommitment`, but that has not been validated yet. #[derive(Serialize, Deserialize)] struct WireBivarCommitment<'a> { @@ -305,4 +384,28 @@ mod tests { assert_eq!(comm, de_comm); } } + + #[test] + #[cfg(not(feature = "use-insecure-test-only-mock-crypto"))] + fn serde_secret_key() { + use crate::serde_impl::SerdeSecret; + use crate::SecretKey; + use rand::{thread_rng, Rng}; + + let mut rng = thread_rng(); + for _ in 0..2048 { + let sk: SecretKey = rng.gen(); + let ser_ref = bincode::serialize(&SerdeSecret(&sk)).expect("serialize secret key"); + + let de = bincode::deserialize(&ser_ref).expect("deserialize secret key"); + assert_eq!(sk, de); + + let de_serde_secret: SerdeSecret = + bincode::deserialize(&ser_ref).expect("deserialize secret key"); + assert_eq!(sk, de_serde_secret.into_inner()); + + let ser_val = bincode::serialize(&SerdeSecret(sk)).expect("serialize secret key"); + assert_eq!(ser_ref, ser_val); + } + } }