use std::io::{Read, Write};
use leb128;
use zeroize::Zeroizing;
use crate::CryptoCoreError;
pub trait Serializable: Sized {
type Error: From<CryptoCoreError>;
fn length(&self) -> usize;
fn write(&self, ser: &mut Serializer) -> Result<usize, Self::Error>;
fn read(de: &mut Deserializer) -> Result<Self, Self::Error>;
fn serialize(&self) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
let mut ser = Serializer::with_capacity(self.length());
ser.write(self)?;
Ok(ser.finalize())
}
fn deserialize(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.is_empty() {
return Err(CryptoCoreError::DeserializationEmptyError.into());
}
let mut de = Deserializer::new(bytes);
match de.read::<Self>() {
Ok(result) if !de.finalize().is_empty() => {
Err(CryptoCoreError::DeserializationSizeError {
given: bytes.len(),
expected: result.length(),
})?
}
success_or_failure => success_or_failure,
}
}
}
pub struct Deserializer<'a> {
readable: &'a [u8],
}
impl<'a> Deserializer<'a> {
#[must_use]
pub const fn new(bytes: &'a [u8]) -> Deserializer<'a> {
Deserializer { readable: bytes }
}
pub fn read_leb128_u64(&mut self) -> Result<u64, CryptoCoreError> {
leb128::read::unsigned(&mut self.readable).map_err(CryptoCoreError::ReadLeb128Error)
}
pub fn read_array<const LENGTH: usize>(&mut self) -> Result<[u8; LENGTH], CryptoCoreError> {
let mut buf = [0; LENGTH];
self.readable.read_exact(&mut buf).map_err(|_| {
CryptoCoreError::DeserializationSizeError {
given: self.readable.len(),
expected: LENGTH,
}
})?;
Ok(buf)
}
pub fn read_vec(&mut self) -> Result<Vec<u8>, CryptoCoreError> {
let original_length = self.readable.len();
let len_u64 = self.read_leb128_u64()?;
if len_u64 == 0 {
return Ok(vec![]);
};
let len = usize::try_from(len_u64).map_err(|_| {
CryptoCoreError::GenericDeserializationError(format!(
"size of vector is too big for architecture: {len_u64} bytes",
))
})?;
let mut buf = vec![0_u8; len];
self.readable.read_exact(&mut buf).map_err(|_| {
CryptoCoreError::DeserializationSizeError {
expected: len + to_leb128_len(len),
given: original_length,
}
})?;
Ok(buf)
}
pub fn read_vec_as_ref(&mut self) -> Result<&'a [u8], CryptoCoreError> {
let len_u64 = self.read_leb128_u64()?;
let len = usize::try_from(len_u64).map_err(|_| {
CryptoCoreError::GenericDeserializationError(format!(
"size of vector is too big for architecture: {len_u64} bytes",
))
})?;
let (front, back) = self.readable.split_at(len);
self.readable = back;
Ok(front)
}
pub fn read<T: Serializable>(&mut self) -> Result<T, <T as Serializable>::Error> {
T::read(self)
}
#[must_use]
pub fn value(&self) -> &[u8] {
self.readable
}
#[must_use]
pub fn finalize(self) -> Vec<u8> {
self.readable.to_vec()
}
}
pub struct Serializer(Zeroizing<Vec<u8>>);
impl Serializer {
#[must_use]
pub fn new() -> Self {
Self(Zeroizing::new(vec![]))
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self(Zeroizing::new(Vec::with_capacity(capacity)))
}
pub fn write_leb128_u64(&mut self, n: u64) -> Result<usize, CryptoCoreError> {
leb128::write::unsigned(&mut *self.0, n)
.map_err(|error| CryptoCoreError::WriteLeb128Error { value: n, error })
}
pub fn write_array(&mut self, array: &[u8]) -> Result<usize, CryptoCoreError> {
self.0
.write(array)
.map_err(|error| CryptoCoreError::SerializationIoError {
bytes_len: array.len(),
error,
})
}
pub fn write_vec(&mut self, vector: &[u8]) -> Result<usize, CryptoCoreError> {
let mut len = self.write_leb128_u64(vector.len() as u64)?;
len += self.write_array(vector)?;
Ok(len)
}
pub fn write<T: Serializable>(
&mut self,
value: &T,
) -> Result<usize, <T as Serializable>::Error> {
value.write(self)
}
#[must_use]
pub fn finalize(self) -> Zeroizing<Vec<u8>> {
self.0
}
}
impl Default for Serializer {
fn default() -> Self {
Self::new()
}
}
#[must_use]
pub fn to_leb128_len(n: usize) -> usize {
let mut n = n >> 7;
let mut size = 1;
while n != 0 {
size += 1;
n >>= 7;
}
size
}
#[cfg(test)]
mod tests {
use super::{to_leb128_len, Deserializer, Serializable, Serializer};
use crate::{
reexport::rand_core::{RngCore, SeedableRng},
CryptoCoreError, CsRng,
};
#[derive(Debug)]
struct DummyLeb128Serializable {
bytes: Vec<u8>,
}
impl Serializable for DummyLeb128Serializable {
type Error = CryptoCoreError;
fn length(&self) -> usize {
to_leb128_len(self.bytes.len()) + self.bytes.len()
}
fn write(&self, ser: &mut crate::bytes_ser_de::Serializer) -> Result<usize, Self::Error> {
ser.write_vec(&self.bytes)
}
fn read(de: &mut crate::bytes_ser_de::Deserializer) -> Result<Self, Self::Error> {
Ok(Self {
bytes: de.read_vec()?,
})
}
}
#[test]
fn test_to_leb128_len() {
let mut rng = CsRng::from_entropy();
let mut ser = Serializer::new();
for i in 1..1000 {
let n = rng.next_u32();
let length = ser.write_leb128_u64(u64::from(n)).unwrap();
assert_eq!(
length,
to_leb128_len(n as usize),
"Wrong serialization length for {i}th integer: `{n}u64`"
);
}
}
#[test]
fn test_ser_de() -> Result<(), CryptoCoreError> {
let a1 = b"azerty".to_vec();
let a2 = b"".to_vec();
let a3 = "nbvcxwmlkjhgfdsqpoiuytreza)àç_è-('é&".as_bytes().to_vec();
let mut ser = Serializer::new();
assert_eq!(7, ser.write_vec(&a1)?);
assert_eq!(1, ser.write_vec(&a2)?);
assert_eq!(41, ser.write_vec(&a3)?);
assert_eq!(49, ser.0.len());
let mut de = Deserializer::new(&ser.0);
let a1_ = de.read_vec()?;
assert_eq!(a1, a1_);
let a2_ = de.read_vec()?;
assert_eq!(a2, a2_);
let a3_ = de.read_vec()?;
assert_eq!(a3, a3_);
Ok(())
}
#[cfg(feature = "curve25519")]
#[test]
fn test_r25519_serialization() -> Result<(), CryptoCoreError> {
use crate::asymmetric_crypto::R25519PrivateKey;
let key = R25519PrivateKey::new(&mut CsRng::from_entropy());
let serialized_key = key.serialize()?;
let key_ = R25519PrivateKey::deserialize(&serialized_key)?;
assert_eq!(key, key_);
assert_eq!(serialized_key, key_.serialize()?);
let dummy = DummyLeb128Serializable {
bytes: vec![1; 512],
};
let serialized_dummy = dummy.serialize()?;
let deserialized_dummy = DummyLeb128Serializable::deserialize(&serialized_dummy)?;
assert_eq!(deserialized_dummy.bytes, dummy.bytes);
{
let empty_error = R25519PrivateKey::deserialize(&[]);
dbg!(&empty_error);
assert!(matches!(
empty_error,
Err(CryptoCoreError::DeserializationEmptyError)
));
}
{
let too_small_error = R25519PrivateKey::deserialize(&[1, 2, 3]);
dbg!(&too_small_error);
assert!(matches!(
too_small_error,
Err(CryptoCoreError::DeserializationSizeError {
given: 3,
expected: 32
})
));
}
{
let too_big_error = R25519PrivateKey::deserialize(&[1; 34]);
dbg!(&too_big_error);
assert!(matches!(
too_big_error,
Err(CryptoCoreError::DeserializationSizeError {
given: 34,
expected: 32
})
));
}
Ok(())
}
#[test]
fn test_deserialization_errors() -> Result<(), CryptoCoreError> {
{
let empty_error = DummyLeb128Serializable::deserialize(&[]);
dbg!(&empty_error);
assert!(matches!(
empty_error,
Err(CryptoCoreError::DeserializationEmptyError)
));
}
let dummy = DummyLeb128Serializable {
bytes: vec![1; 512],
};
{
let mut bytes = dummy.serialize()?;
bytes.pop();
let too_small_error = DummyLeb128Serializable::deserialize(&bytes);
dbg!(&too_small_error);
assert!(matches!(
too_small_error,
Err(CryptoCoreError::DeserializationSizeError {
given: 513,
expected: 514
})
));
}
{
let mut bytes = dummy.serialize()?;
bytes.push(42);
let too_big_error = DummyLeb128Serializable::deserialize(&bytes);
dbg!(&too_big_error);
assert!(matches!(
too_big_error,
Err(CryptoCoreError::DeserializationSizeError {
given: 515,
expected: 514
})
));
}
Ok(())
}
}