false_bottom/
encode.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2use crate::{FbError, FbObj};
3use crypto_bigint::{ArrayEncoding, generic_array::GenericArray, Uint};
4use std::sync::RwLock;
5
6#[cfg(feature = "base64")]
7#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
8use base64::{prelude::BASE64_STANDARD, Engine};
9
10/// Provides methods to encode and decode data to and from several formats.
11pub trait Encode {
12	/// Returns the byte representation of the ciphertext and keybase.
13	fn to_bytes(&self) -> (Vec<u8>, Vec<u8>);
14
15	/// Constructs the `FbObj` from the provided byte representations of
16	/// ciphertext and keybase.
17	/// # Errors
18	/// - [InvalidParams](FbError::InvalidParams) - Are the parameters in the wrong order?	
19	fn from_bytes(cipher: &[u8], keybase: &[u8]) -> Result<Self, FbError>
20	where
21		Self: Sized;
22
23	/// Returns the base64 encoded representation of the ciphertext and keybase.  
24	/// Requires `base64` feature to be enabled.
25    #[cfg(feature = "base64")]
26	#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
27	fn to_base64(&self) -> (String, String);
28
29	/// Constructs the `FbObj` from the provided base64 encoded forms of
30	/// ciphertext and keybase.  
31	/// Requires `base64` feature to be enabled.
32	/// # Errors
33	/// - [DecodeError](FbError::DecodeError)
34	/// - [InvalidParams](FbError::InvalidParams) - Are the parameters in the wrong order?
35    #[cfg(feature = "base64")]
36	#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]	
37	fn from_base64(cipher: &str, keybase: &str) -> Result<Self, FbError>
38	where
39		Self: Sized;
40}
41
42impl<const LIMBS: usize> Encode for FbObj<Uint<LIMBS>>
43where
44	Uint<LIMBS>: ArrayEncoding,
45{
46	fn to_bytes(&self) -> (Vec<u8>, Vec<u8>) {
47		let c = self.c.read().unwrap()
48			.iter()
49			.flat_map(|bigint| bigint.to_le_byte_array())
50			.collect();
51		let r = self.r.iter()
52			.flat_map(|bigint| bigint.to_le_byte_array())
53			.collect();
54
55		(c, r)
56	}
57
58	fn from_bytes(cipher: &[u8], keybase: &[u8]) -> Result<Self, FbError> {
59		let to_uint = |chunk| Uint::<LIMBS>::from_le_byte_array(GenericArray::clone_from_slice(chunk));
60		let c_vec: Vec<_> = cipher.chunks_exact(Uint::<LIMBS>::BYTES)
61			.map(to_uint)
62			.collect();
63		let r: Vec<_> = keybase.chunks_exact(Uint::<LIMBS>::BYTES)
64			.map(to_uint)
65			.collect();
66		if r.len() > c_vec.len() || r.len() < 2 {
67			return Err(FbError::InvalidParams);
68		}
69		let c = RwLock::new(c_vec);
70
71		Ok(FbObj {c, r})
72	}
73
74    #[cfg(feature = "base64")]
75	#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]	
76	fn to_base64(&self) -> (String, String) {
77		let (c, r) = self.to_bytes();
78
79		(BASE64_STANDARD.encode(c), BASE64_STANDARD.encode(r))
80	}
81
82    #[cfg(feature = "base64")]
83	#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]	
84	fn from_base64(cipher: &str, keybase: &str) -> Result<Self, FbError> {
85		let c_bytes = BASE64_STANDARD.decode(cipher)
86			.map_err(|_| FbError::DecodeError)?;
87		let r_bytes = BASE64_STANDARD.decode(keybase)
88			.map_err(|_| FbError::DecodeError)?;
89
90		Self::from_bytes(&c_bytes, &r_bytes)
91	}
92}