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

@@ -19,9 +19,9 @@ serde_json = "1.0.115"
urlencoding = "2.1.3"
# 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 }
rand = { version = "0.9.0", optional = true }
[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::time_utils::time;
use bincode::{Decode, Encode};
use std::net::IpAddr;
#[derive(Encode, Decode, Debug)]
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
struct State {
ip: IpAddr,
expire: u64,
@@ -49,7 +48,7 @@ pub struct BasicStateManager(CryptoWrapper);
impl BasicStateManager {
/// 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 {
Self(CryptoWrapper::new_random())
}

View File

@@ -2,15 +2,21 @@ use aes_gcm::aead::{Aead, OsRng};
use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use base64::Engine as _;
use bincode::{Decode, Encode};
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;
/// The lenght of the nonce used to initialize encryption
/// The length of the nonce used to initialize encryption
const NONCE_LEN: usize = 12;
/// 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 {
key: Key<Aes256Gcm>,
}
@@ -24,11 +30,14 @@ impl CryptoWrapper {
}
/// 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 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
.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
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)?;
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)]
mod test {
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);
#[test]