Working on Traits

This commit is contained in:
K Shiva Kiran 2024-03-26 12:16:32 +05:30
parent 182832bc6e
commit 778a045be6
10 changed files with 290 additions and 366 deletions

View File

@ -1,5 +1,4 @@
use false_bottom::FBCrypt;
use false_bottom::{FB128, FalseBottom};
fn main() {
// Input messages
@ -8,7 +7,7 @@ fn main() {
let real_msg2 = "Please meet me at the Paradise hotel at 5:30 PM";
// Cipher initialization
let mut fb = FBCrypt::init(18, 12).unwrap();
let mut fb = FB128::init(18, 12).unwrap();
// Encryption
let real_key1 = fb.add(&real_msg1.as_bytes());

View File

@ -1,8 +1,8 @@
use false_bottom::{FBCrypt, FBKey};
use false_bottom::{FBObj, FBKey};
fn main() {
// Cipher Initialization
let mut fb = FBCrypt::init(18, 9).unwrap();
let mut fb = FBObj::init(18, 9).unwrap();
// Encryption
let msg1 = "This is a message";
@ -16,7 +16,7 @@ fn main() {
let key2_exp = key2.export();
// Import
let fb_new = FBCrypt::import(&cipher, &keybase).unwrap();
let fb_new = FBObj::import(&cipher, &keybase).unwrap();
let key1_imp = FBKey::import(&key1_exp).unwrap();
let key2_imp = FBKey::import(&key2_exp).unwrap();

View File

@ -1,130 +0,0 @@
use crypto_bigint::{U128, Limb, RandomMod, NonZero, Encoding};
use crate::{FBError, FBKey, pack::Packing};
use rand::{Rng, prelude::IteratorRandom};
mod fb128;
pub trait FB<T>: FBBlock<T>
where
T: RandomMod + SpecialMod + InvMod + Encoding + std::cmp::PartialOrd + Packing<T>
{
const MODULUS: NonZero<T>;
fn init(n: usize, k: usize) -> Result<FBStruct<T>, FBError>
where
T: RandomMod
{
if n < k || k < 2 {
return Err(FBError::InvalidParams);
}
let mut rng = rand::thread_rng();
let r = (0..k)
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
let c = (0..n)
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
Ok(FBStruct { c, r })
}
fn add(&mut self, msg: &[u8]) -> FBKey {
let indices = T::pack(msg).into_iter()
.map(|msg_uint| self.add_u128(&msg_uint))
.collect();
FBKey { indices }
}
fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> {
let decr = key.indices.iter()
.map(|index_row| self.decrypt_u128(&index_row))
.collect::<Result<Vec<_>, _>>()?;
let msg = T::unpack(&decr)?;
Ok(msg)
}
}
trait SpecialMod {
fn mul_mod_special(&self, rhs: &Self, c: Limb) -> Self;
fn add_mod_special(&self, rhs: &Self, c: Limb) -> Self;
fn sub_mod_special(&self, rhs: &Self, c: Limb) -> Self;
}
use crypto_bigint::CtChoice;
trait InvMod {
fn inv_mod(&self, modulus: &Self) -> (Self, CtChoice)
where Self: Sized;
}
impl SpecialMod for U128 {
fn mul_mod_special(&self, rhs: &Self, c: Limb) -> Self {self.mul_mod_special(rhs, c)}
fn add_mod_special(&self, rhs: &Self, c: Limb) -> Self {self.add_mod_special(rhs, c)}
fn sub_mod_special(&self, rhs: &Self, c: Limb) -> Self {self.sub_mod_special(rhs, c)}
}
impl InvMod for U128 {
fn inv_mod(&self, modulus: &Self) -> (Self, CtChoice) {
self.inv_mod(modulus)
}
}
trait FBBlock<T>
where
T: RandomMod + SpecialMod + InvMod
{
const P: T;
const P_POS: Limb;
fn cipher(&self) -> &Vec<T>;
fn cipher_mut(&mut self) -> &mut Vec<T>;
fn keybase(&self) -> &Vec<T>;
fn add_u128(&mut self, msg_uint: &T) -> Vec<(usize, usize)> {
let c = self.cipher();
let r = self.keybase();
let mut rng = rand::thread_rng();
let n = rng.gen_range(2..=r.len());
let mut c_i = (0..c.len()).choose_multiple(&mut rng, n - 1);
let r_i = (0..r.len()).choose_multiple(&mut rng, n);
let mut sum = T::ZERO;
for (&ci, &ri) in c_i.iter().zip(r_i.iter()) {
sum = sum.add_mod_special(
&c[ci].mul_mod_special(&r[ri], Self::P_POS),
Self::P_POS);
}
let ri_last = *r_i.last().expect("r_i will contain at least 2 elements");
let mod_inv = r[ri_last].inv_mod(&Self::P).0;
let c_new_el = msg_uint.sub_mod_special(&sum, Self::P_POS)
.mul_mod_special(&mod_inv, Self::P_POS);
let c = self.cipher_mut();
c.push(c_new_el);
c_i.push(c.len() - 1);
let indices = c_i.into_iter()
.zip(r_i.into_iter())
.collect();
indices
}
fn decrypt_u128(&self, indices: &[(usize, usize)]) -> Result<T, FBError> {
let (r, c) = (self.keybase(), self.cipher());
if indices.len() > r.len() {
return Err(FBError::InvalidKey);
}
let mut msg = T::ZERO;
for &(ci, ri) in indices {
let c_el = c.get(ci).ok_or(FBError::InvalidKey)?;
let r_el = r.get(ri).ok_or(FBError::InvalidKey)?;
msg = msg.add_mod_special(
&c_el.mul_mod_special(&r_el, Self::P_POS),
Self::P_POS);
}
Ok(msg)
}
}
pub struct FBStruct<T> {
pub(crate) c: Vec<T>,
pub(crate) r: Vec<T>,
}

View File

@ -1,53 +0,0 @@
use crypto_bigint::{U128, Limb, NonZero};
use crate::{
crypt::{FB, FBStruct, FBBlock},
pack::Packing,
};
impl FB<U128> for FBStruct<U128> {
const MODULUS: NonZero<U128> = NonZero::<U128>::const_new(Self::P).0;
}
impl FBBlock<U128> for FBStruct<U128> {
const P: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159 - 1));
const P_POS: Limb = Limb::from_u8(159);
fn cipher(&self) -> &Vec<U128> {
&self.c
}
fn cipher_mut(&mut self) -> &mut Vec<U128> {
&mut self.c
}
fn keybase(&self) -> &Vec<U128> {
&self.r
}
}
impl Packing<U128> for U128 {
const P_MINUS_ONE: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159));
const BYTES: usize = 16;
}
#[test]
fn encrypt_u128() {
let msg = U128::from_u32(100);
let mut fb = FBStruct::init(20, 12).unwrap();
let key = fb.add_u128(&msg);
let decrypted = fb.decrypt_u128(&key).unwrap();
assert_eq!(msg, decrypted);
}
#[test]
fn encrypt_bytes() {
let input1 = vec![255_u8; 150];
let input2 = vec![0_u8; 102];
let mut fb = FBStruct::init(21, 12).unwrap();
let key1 = fb.add(&input1);
let key2 = fb.add(&input2);
let decr1 = fb.decrypt(&key1).unwrap();
let decr2 = fb.decrypt(&key2).unwrap();
assert_eq!(input1, decr1);
assert_eq!(input2, decr2);
}

View File

@ -1,60 +1,14 @@
use base64::prelude::{BASE64_STANDARD, Engine};
use bincode::{Options, DefaultOptions};
use crypto_bigint::{U128, Encoding};
use crate::{FBCrypt, FBKey, errors::FBError};
use crypto_bigint::Encoding;
use crate::FBError;
impl FBCrypt {
pub fn export(&self) -> (String, String) {
let c_bytes: Vec<u8> = self.c.iter()
.flat_map(|bigint| bigint.to_le_bytes())
.collect();
let r_bytes: Vec<u8> = self.r.iter()
.flat_map(|bigint| bigint.to_le_bytes())
.collect();
(BASE64_STANDARD.encode(c_bytes), BASE64_STANDARD.encode(r_bytes))
}
pub fn import(cipher: &str, keybase: &str) -> Result<FBCrypt, FBError> {
let c_bytes = BASE64_STANDARD.decode(cipher)
.map_err(|_| FBError::DecodeError)?;
let c: Vec<U128> = c_bytes.chunks_exact(16)
.map(|chunk| U128::from_le_bytes(chunk.try_into().unwrap()))
.collect();
let r_bytes = BASE64_STANDARD.decode(keybase)
.map_err(|_| FBError::DecodeError)?;
let r: Vec<U128> = r_bytes.chunks_exact(16)
.map(|chunk| U128::from_le_bytes(chunk.try_into().unwrap()))
.collect();
if c.len() < r.len() || r.len() < 2 {
return Err(FBError::InvalidParams);
}
Ok(FBCrypt {c, r})
}
}
impl FBKey {
pub fn export(&self) -> String {
let binc = DefaultOptions::new();
let indice_bytes = binc.serialize(&self.indices)
.unwrap();
BASE64_STANDARD.encode(&indice_bytes)
}
pub fn import(key_str: &str) -> Result<FBKey, FBError> {
let binc = DefaultOptions::new();
let indice_bytes = BASE64_STANDARD.decode(key_str)
.map_err(|_| FBError::DecodeError)?;
let indices: Vec<_> = binc.deserialize(&indice_bytes)
.map_err(|_| FBError::DecodeError)?;
if indices.len() < 2 {
return Err(FBError::DecodeError);
}
Ok (FBKey {indices})
}
pub trait Encode<T>
where
T: Encoding
{
const BYTES: usize;
fn export(&self) -> (String, String);
fn import(cipher: &str, keybase: &str) -> Result<Self, FBError>
where
Self: Sized;
}

View File

@ -1,71 +1,96 @@
use crypto_bigint::{U128, Limb, RandomMod, NonZero};
use rand::{seq::IteratorRandom, Rng};
use crate::{errors::FBError, packing};
pub mod fb128;
pub struct FBCrypt {
pub(crate) c: Vec<U128>, // Ciphertext
pub(crate) r: Vec<U128>, // Keybase
use crypto_bigint::{Limb, RandomMod, NonZero, Encoding};
use base64::prelude::{BASE64_STANDARD, Engine};
use crate::{FBError, Packing, FBKey, Encode};
use rand::{Rng, prelude::IteratorRandom};
use std::cmp::PartialOrd;
pub struct FBObj<T> {
pub(crate) c: Vec<T>,
pub(crate) r: Vec<T>,
}
pub struct FBKey {
// 2D Vec containing (cipher_index, keybase_index) pairs
pub(crate) indices: Vec<Vec<(usize, usize)>>,
}
pub trait FalseBottom<T>: FBBlockOperations<T>
where
T: RandomMod + ModPrime<T> + Encoding + PartialOrd + Packing<T>
{
const MODULUS: NonZero<T>;
// Value and position of the Prime used (2^128 - 159)
const P: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159 - 1));
const P_POS: Limb = Limb::from_u8(159);
impl FBCrypt {
pub fn init(n: usize, k: usize) -> Result<FBCrypt, FBError> {
fn init(n: usize, k: usize) -> Result<FBObj<T>, FBError>
where
T: RandomMod
{
if n < k || k < 2 {
return Err(FBError::InvalidParams);
}
const MODULUS: NonZero<U128> = NonZero::<U128>::const_new(P).0;
let mut rng = rand::thread_rng();
let r = (0..k)
.map(|_| U128::random_mod(&mut rng, &MODULUS))
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
let c = (0..n)
.map(|_| U128::random_mod(&mut rng, &MODULUS))
.map(|_| T::random_mod(&mut rng, &Self::MODULUS))
.collect();
Ok(FBCrypt { c, r })
Ok(FBObj { c, r })
}
pub fn add(&mut self, msg: &[u8]) -> FBKey {
let indices = packing::pack(msg).into_iter()
fn add(&mut self, msg: &[u8]) -> FBKey {
let indices = T::pack(msg).into_iter()
.map(|msg_uint| self.add_u128(&msg_uint))
.collect();
FBKey { indices }
}
pub fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> {
fn decrypt(&self, key: &FBKey) -> Result<Vec<u8>, FBError> {
let decr = key.indices.iter()
.map(|index_row| self.decrypt_u128(&index_row))
.collect::<Result<Vec<_>, _>>()?;
let msg = packing::unpack(&decr)?;
let msg = T::unpack(&decr)?;
Ok(msg)
}
}
fn add_u128(&mut self, msg_uint: &U128) -> Vec<(usize, usize)> {
let (r, c) = (&self.r, &mut self.c);
pub trait ModPrime<T> {
const PRIME_POS: Limb;
const PRIME: T;
fn mul_mod_prime(&self, rhs: &Self) -> Self;
fn add_mod_prime(&self, rhs: &Self) -> Self;
fn sub_mod_prime(&self, rhs: &Self) -> Self;
fn inv_mod_prime(&self) -> Self;
}
pub trait FBBlockOperations<T>
where
T: RandomMod + ModPrime<T>
{
const P: T;
const P_POS: Limb;
fn cipher(&self) -> &Vec<T>;
fn cipher_mut(&mut self) -> &mut Vec<T>;
fn keybase(&self) -> &Vec<T>;
fn add_u128(&mut self, msg_uint: &T) -> Vec<(usize, usize)> {
let c = self.cipher();
let r = self.keybase();
let mut rng = rand::thread_rng();
let n = rng.gen_range(2..=r.len());
let mut c_i = (0..c.len()).choose_multiple(&mut rng, n - 1);
let r_i = (0..r.len()).choose_multiple(&mut rng, n);
let mut sum = U128::ZERO;
for (&ci, &ri) in c_i.iter().zip(r_i.iter()) {
sum = sum.add_mod_special(
&c[ci].mul_mod_special(&r[ri], P_POS),
P_POS);
let mut sum = T::ZERO;
for (&ci, &ri) in c_i.iter().zip( r_i.iter() ) {
sum = sum.add_mod_prime( &c[ci].mul_mod_prime(&r[ri]) );
}
let ri_last = *r_i.last().expect("r_i will contain at least 2 elements");
let mod_inv = r[ri_last].inv_mod(&P).0;
let c_new_el = msg_uint.sub_mod_special(&sum, P_POS)
.mul_mod_special(&mod_inv, P_POS);
let ri_last = *r_i.last()
.expect("r_i will contain at least 2 elements");
let mod_inv = r[ri_last].inv_mod_prime();
let c_new_el = msg_uint.sub_mod_prime(&sum)
.mul_mod_prime(&mod_inv);
let c = self.cipher_mut();
c.push(c_new_el);
c_i.push(c.len() - 1);
let indices = c_i.into_iter()
@ -75,41 +100,59 @@ impl FBCrypt {
indices
}
fn decrypt_u128(&self, indices: &[(usize, usize)]) -> Result<U128, FBError> {
if indices.len() > self.r.len() {
fn decrypt_u128(&self, indices: &[(usize, usize)]) -> Result<T, FBError> {
let (r, c) = (self.keybase(), self.cipher());
if indices.len() > r.len() {
return Err(FBError::InvalidKey);
}
let mut msg = U128::ZERO;
let mut msg = T::ZERO;
for &(ci, ri) in indices {
let c_el = self.c.get(ci).ok_or(FBError::InvalidKey)?;
let r_el = self.r.get(ri).ok_or(FBError::InvalidKey)?;
msg = msg.add_mod_special(
&c_el.mul_mod_special(&r_el, P_POS),
P_POS);
let c_el = c.get(ci).ok_or(FBError::InvalidKey)?;
let r_el = r.get(ri).ok_or(FBError::InvalidKey)?;
msg = msg.add_mod_prime(&c_el.mul_mod_prime(&r_el));
}
Ok(msg)
}
}
#[test]
fn encrypt_u128() {
let msg = U128::from_u32(100);
let mut fb = FBCrypt::init(20, 12).unwrap();
let key = fb.add_u128(&msg);
let decrypted = fb.decrypt_u128(&key).unwrap();
assert_eq!(msg, decrypted);
}
impl<T> Encode<T> for FBObj<T>
where
T: Encoding + crypto_bigint::Bounded,
<T as Encoding>::Repr: Iterator + for <'a> From<&'a [u8]>,
Vec<u8>: FromIterator<<<T as Encoding>::Repr as Iterator>::Item>
{
const BYTES: usize = T::BYTES;
#[test]
fn encrypt_bytes() {
let input1 = vec![255_u8; 150];
let input2 = vec![0_u8; 102];
let mut fb = FBCrypt::init(21, 12).unwrap();
let key1 = fb.add(&input1);
let key2 = fb.add(&input2);
let decr1 = fb.decrypt(&key1).unwrap();
let decr2 = fb.decrypt(&key2).unwrap();
assert_eq!(input1, decr1);
assert_eq!(input2, decr2);
fn export(&self) -> (String, String) {
let c_bytes: Vec<u8> = self.c.iter()
.flat_map(|bigint| bigint.to_le_bytes())
.collect();
let r_bytes: Vec<u8> = self.r.iter()
.flat_map(|bigint| bigint.to_le_bytes())
.collect();
(BASE64_STANDARD.encode(c_bytes), BASE64_STANDARD.encode(r_bytes))
}
fn import(cipher: &str, keybase: &str) -> Result<Self, FBError>
where
Self: Sized
{
let c_bytes = BASE64_STANDARD.decode(cipher)
.map_err(|_| FBError::DecodeError)?;
let c: Vec<T> = c_bytes.chunks_exact(Self::BYTES)
.map(|chunk| T::from_le_bytes(chunk.try_into().unwrap()))
.collect();
let r_bytes = BASE64_STANDARD.decode(keybase)
.map_err(|_| FBError::DecodeError)?;
let r: Vec<T> = r_bytes.chunks_exact(Self::BYTES)
.map(|chunk| T::from_le_bytes(chunk.try_into().unwrap()))
.collect();
if c.len() < r.len() || r.len() < 2 {
return Err(FBError::InvalidParams);
}
Ok(Self {c, r})
}
}

126
src/false_bottom/fb128.rs Normal file
View File

@ -0,0 +1,126 @@
use crypto_bigint::{U128, Limb, NonZero, Encoding};
use crate::{
false_bottom::{FalseBottom, ModPrime, FBBlockOperations, FBObj},
pack::Packing, FBError,
};
pub type FB128 = FBObj<U128>;
impl FalseBottom<U128> for FBObj<U128> {
const MODULUS: NonZero<U128> = NonZero::<U128>::const_new(Self::P).0;
}
impl FBBlockOperations<U128> for FBObj<U128> {
const P: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159 - 1));
const P_POS: Limb = Limb::from_u8(159);
fn cipher(&self) -> &Vec<U128> {
&self.c
}
fn cipher_mut(&mut self) -> &mut Vec<U128> {
&mut self.c
}
fn keybase(&self) -> &Vec<U128> {
&self.r
}
}
impl ModPrime<U128> for U128 {
const PRIME_POS: Limb = Limb::from_u32(159);
const PRIME: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159 - 1));
fn mul_mod_prime(&self, rhs: &Self) -> Self {
self.mul_mod_special(rhs, Self::PRIME_POS)
}
fn add_mod_prime(&self, rhs: &Self) -> Self {
self.add_mod_special(rhs, Self::PRIME_POS)
}
fn sub_mod_prime(&self, rhs: &Self) -> Self {
self.sub_mod_special(rhs, Self::PRIME_POS)
}
fn inv_mod_prime(&self) -> Self {
self.inv_mod(&Self::PRIME).0
}
}
impl Packing<U128> for U128 {
const P_MINUS_ONE: U128 = U128::MAX.wrapping_sub(&U128::from_u8(159));
fn pack(inp: &[u8]) -> Vec<U128> {
let mut out = Vec::with_capacity(inp.len()/16 + 2);
inp.chunks(16)
.for_each(|inp_chunk| {
let mut out_chunk = [0_u8; 16];
out_chunk[..inp_chunk.len()].copy_from_slice(inp_chunk);
let mut out_uint = U128::from_le_bytes(out_chunk);
if out_uint >= Self::P_MINUS_ONE {
out.push(Self::P_MINUS_ONE);
out_uint = out_uint.wrapping_sub(&U128::from_u16(3000));
}
out.push(out_uint);
});
let inp_chunk_last = inp.chunks_exact(16)
.remainder();
let mut pad_chunk: [u8; 16] = [16; 16];
if inp_chunk_last.len() > 0 {
pad_chunk[15] += 16 - inp_chunk_last.len() as u8;
}
out.push(U128::from_le_bytes(pad_chunk));
out.shrink_to_fit();
out
}
fn unpack(inp: &[U128]) -> Result<Vec<u8>, FBError> {
let pad_len = inp.last()
.ok_or(FBError::InvalidKey)?
.to_le_bytes()[15] as usize;
if pad_len > 31 {
return Err(FBError::InvalidKey);
}
let mut out = Vec::with_capacity(inp.len()*16);
let mut add_3k = false;
for i in inp {
if add_3k {
let orig = i.wrapping_add(&U128::from_u16(3000));
out.extend(orig.to_le_bytes().into_iter());
add_3k = false;
} else if *i == Self::P_MINUS_ONE {
add_3k = true;
} else {
out.extend(i.to_le_bytes().into_iter());
}
}
let trunc_len = out.len().checked_sub(pad_len)
.ok_or(FBError::InvalidKey)?;
out.truncate(trunc_len);
out.shrink_to_fit();
Ok(out)
}
}
#[test]
fn encrypt_u128() {
let msg = U128::from_u32(100);
let mut fb = FBObj::init(20, 12).unwrap();
let key = fb.add_u128(&msg);
let decrypted = fb.decrypt_u128(&key).unwrap();
assert_eq!(msg, decrypted);
}
#[test]
fn encrypt_bytes() {
let input1 = vec![255_u8; 150];
let input2 = vec![0_u8; 102];
let mut fb = FBObj::init(21, 12).unwrap();
let key1 = fb.add(&input1);
let key2 = fb.add(&input2);
let decr1 = fb.decrypt(&key1).unwrap();
let decr2 = fb.decrypt(&key2).unwrap();
assert_eq!(input1, decr1);
assert_eq!(input2, decr2);
}

31
src/key.rs Normal file
View File

@ -0,0 +1,31 @@
use crate::FBError;
use base64::prelude::{BASE64_STANDARD, Engine};
use bincode::{Options, DefaultOptions};
pub struct FBKey {
pub(crate) indices: Vec<Vec<(usize, usize)>>,
}
impl FBKey {
pub fn export(&self) -> String {
let binc = DefaultOptions::new();
let indice_bytes = binc.serialize(&self.indices)
.unwrap();
BASE64_STANDARD.encode(&indice_bytes)
}
pub fn import(key_str: &str) -> Result<FBKey, FBError> {
let binc = DefaultOptions::new();
let indice_bytes = BASE64_STANDARD.decode(key_str)
.map_err(|_| FBError::DecodeError)?;
let indices: Vec<_> = binc.deserialize(&indice_bytes)
.map_err(|_| FBError::DecodeError)?;
if indices.len() < 2 {
return Err(FBError::DecodeError);
}
Ok (FBKey {indices})
}
}

View File

@ -1,11 +1,15 @@
mod encoding;
mod errors;
mod false_bottom;
mod key;
mod packing;
mod pack;
mod crypt;
pub use crate::{
errors::FBError,
false_bottom::{FBCrypt, FBKey},
false_bottom::fb128::FB128,
key::FBKey,
encoding::Encode,
};
pub(crate) use crate::pack::Packing;

View File

@ -1,4 +1,5 @@
use crypto_bigint::{Encoding};
use std::cmp::PartialOrd;
use crate::FBError;
/* PACKING SCHEME
@ -11,61 +12,10 @@ use crate::FBError;
pub(crate) trait Packing<T>
where
T: Encoding + std::cmp::PartialOrd
T: Encoding + PartialOrd
{
const P_MINUS_ONE: T;
const BYTES: usize;
fn pack(inp: &[u8]) -> Vec<T> {
let mut out = Vec::with_capacity(inp.len()/Self::BYTES + 2);
inp.chunks(Self::BYTES)
.for_each(|inp_chunk| {
let mut out_chunk = [0_u8; Self::BYTES];
out_chunk[..inp_chunk.len()].copy_from_slice(inp_chunk);
let mut out_uint = T::from_le_bytes(out_chunk);
if out_uint >= Self::P_MINUS_ONE {
out.push(Self::P_MINUS_ONE);
out_uint = out_uint.wrapping_sub(&T::from_u16(3000));
}
out.push(out_uint);
});
let inp_chunk_last = inp.chunks_exact(Self::BYTES)
.remainder();
let mut pad_chunk = [Self::BYTES as u8; Self::BYTES];
if inp_chunk_last.len() > 0 {
pad_chunk[Self::BYTES as u8 - 1] += Self::BYTES as u8 - inp_chunk_last.len() as u8;
}
out.push(T::from_le_bytes(pad_chunk));
out.shrink_to_fit();
out
}
fn unpack(inp: &[T]) -> Result<Vec<u8>, FBError> {
let pad_len = inp.last()
.ok_or(FBError::InvalidKey)?
.to_le_bytes()[15] as usize;
if pad_len > 31 {
return Err(FBError::InvalidKey);
}
let mut out = Vec::with_capacity(inp.len()*16);
let mut add_3k = false;
for i in inp {
if add_3k {
let orig = i.wrapping_add(&T::from_u16(3000));
out.extend(orig.to_le_bytes().into_iter());
add_3k = false;
} else if *i == Self::P_MINUS_ONE {
add_3k = true;
} else {
out.extend(i.to_le_bytes().into_iter());
}
}
let trunc_len = out.len().checked_sub(pad_len)
.ok_or(FBError::InvalidKey)?;
out.truncate(trunc_len);
out.shrink_to_fit();
Ok(out)
}
fn pack(inp: &[u8]) -> Vec<T>;
fn unpack(inp: &[T]) -> Result<Vec<u8>, FBError>;
}