Migrate from bincode to rkyv
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-29 16:20:01 +01:00
parent b0667312e5
commit c850288d85
4 changed files with 451 additions and 387 deletions

796
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,16 +12,16 @@ license = "GPL-2.0-or-later"
[dependencies] [dependencies]
log = "0.4.21" log = "0.4.21"
reqwest = { version = "0.12.14", features = ["json"] } reqwest = { version = "0.12.14", features = ["json"] }
base64 = "0.22.0" base64 = "0.22.0"
serde = { version = "1.0.198", features = ["derive"] } serde = { version = "1.0.198", features = ["derive"] }
serde_json = "1.0.115" serde_json = "1.0.115"
urlencoding = "2.1.3" urlencoding = "2.1.3"
# Dependencies for crypto wrapper # Dependencies for crypto wrapper
bincode = { version = "3.0.0", optional = true } rkyv = { version = "0.8.12", optional = true }
aes-gcm = { version = "0.10.3", optional = true } aes-gcm = { version = "0.10.3", optional = true }
rand = { version = "0.9.0", optional = true } rand = { version = "0.9.0", optional = true }
[features] [features]
crypto-wrapper = ["bincode", "aes-gcm", "rand"] crypto-wrapper = ["rkyv", "aes-gcm", "rand"]

View File

@@ -11,10 +11,9 @@ use std::fmt;
use crate::crypto_wrapper::CryptoWrapper; use crate::crypto_wrapper::CryptoWrapper;
use crate::time_utils::time; use crate::time_utils::time;
use bincode::{Decode, Encode};
use std::net::IpAddr; use std::net::IpAddr;
#[derive(Encode, Decode, Debug)] #[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
struct State { struct State {
ip: IpAddr, ip: IpAddr,
expire: u64, expire: u64,
@@ -49,7 +48,7 @@ pub struct BasicStateManager(CryptoWrapper);
impl BasicStateManager { impl BasicStateManager {
/// Initialize the state manager by creating a random encryption key. This function /// Initialize the state manager by creating a random encryption key. This function
/// should be called only one, ideally in the main function of the application /// should be called only once, ideally in the main function of the application
pub fn new() -> Self { pub fn new() -> Self {
Self(CryptoWrapper::new_random()) Self(CryptoWrapper::new_random())
} }

View File

@@ -2,15 +2,21 @@ use aes_gcm::aead::{Aead, OsRng};
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce}; use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use base64::Engine as _; use base64::Engine as _;
use bincode::{Decode, Encode};
use rand::Rng; use rand::Rng;
use rkyv::api::high::{HighSerializer, HighValidator};
use rkyv::bytecheck::CheckBytes;
use rkyv::de::Pool;
use rkyv::rancor::Strategy;
use rkyv::ser::allocator::ArenaHandle;
use rkyv::util::AlignedVec;
use rkyv::{Archive, Deserialize, Serialize};
use std::error::Error; use std::error::Error;
/// The lenght of the nonce used to initialize encryption /// The length of the nonce used to initialize encryption
const NONCE_LEN: usize = 12; const NONCE_LEN: usize = 12;
/// CryptoWrapper is a library that can be used to encrypt and decrypt some data marked /// CryptoWrapper is a library that can be used to encrypt and decrypt some data marked
/// that derives [Encode] and [Decode] traits using AES encryption /// that derives [SchemaWrite] and [SchemaRead] traits using AES encryption
pub struct CryptoWrapper { pub struct CryptoWrapper {
key: Key<Aes256Gcm>, key: Key<Aes256Gcm>,
} }
@@ -24,11 +30,14 @@ impl CryptoWrapper {
} }
/// Encrypt some data, returning the result as a base64-encoded string /// Encrypt some data, returning the result as a base64-encoded string
pub fn encrypt<T: Encode + Decode<()>>(&self, data: &T) -> Result<String, Box<dyn Error>> { pub fn encrypt(
&self,
data: &impl for<'a> Serialize<HighSerializer<AlignedVec, ArenaHandle<'a>, rkyv::rancor::Error>>,
) -> Result<String, Box<dyn Error>> {
let aes_key = Aes256Gcm::new(&self.key); let aes_key = Aes256Gcm::new(&self.key);
let nonce_bytes = rand::rng().random::<[u8; NONCE_LEN]>(); let nonce_bytes = rand::rng().random::<[u8; NONCE_LEN]>();
let serialized_data = bincode::encode_to_vec(data, bincode::config::standard())?; let serialized_data = rkyv::to_bytes(data)?;
let mut enc = aes_key let mut enc = aes_key
.encrypt(Nonce::from_slice(&nonce_bytes), serialized_data.as_slice()) .encrypt(Nonce::from_slice(&nonce_bytes), serialized_data.as_slice())
@@ -39,7 +48,12 @@ impl CryptoWrapper {
} }
/// Decrypt some data previously encrypted using the [`CryptoWrapper::encrypt`] method /// Decrypt some data previously encrypted using the [`CryptoWrapper::encrypt`] method
pub fn decrypt<T: Decode<()>>(&self, input: &str) -> Result<T, Box<dyn Error>> { pub fn decrypt<T>(&self, input: &str) -> Result<T, Box<dyn Error>>
where
T: Archive,
T::Archived: for<'a> CheckBytes<HighValidator<'a, rkyv::rancor::Error>>
+ Deserialize<T, Strategy<Pool, rkyv::rancor::Error>>,
{
let bytes = BASE64_STANDARD.decode(input)?; let bytes = BASE64_STANDARD.decode(input)?;
if bytes.len() < NONCE_LEN { if bytes.len() < NONCE_LEN {
@@ -63,16 +77,15 @@ impl CryptoWrapper {
} }
}; };
Ok(bincode::decode_from_slice(&dec, bincode::config::standard())?.0) Ok(rkyv::from_bytes(&dec)?)
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::crypto_wrapper::CryptoWrapper; use crate::crypto_wrapper::CryptoWrapper;
use bincode::{Decode, Encode};
#[derive(Encode, Decode, Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
struct Message(String); struct Message(String);
#[test] #[test]