mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Add more state objects.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
use crate::crypto::feistel_shuffle;
|
||||
|
||||
#[cfg(feature = "counter_shuffle_none")]
|
||||
pub type Counter = NoShuffle;
|
||||
#[cfg(feature = "counter_shuffle_feistel")]
|
||||
pub type Counter = FeistelShuffle;
|
||||
#[cfg(feature = "counter_shuffle_feistel_lcg")]
|
||||
pub type Counter = FeistelLCGShuffle;
|
||||
|
||||
const NONCE16_1: u16 = const_random::const_random!(u16);
|
||||
const NONCE16_2: u16 = const_random::const_random!(u16);
|
||||
const NONCE32: u32 = const_random::const_random!(u32);
|
||||
|
||||
pub struct NoShuffle(u16);
|
||||
|
||||
/// Linear shuffle, no randomization, just a random starting point and step size
|
||||
impl NoShuffle {
|
||||
pub fn new() -> Self {
|
||||
Self(NONCE16_1)
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> u16 {
|
||||
self.0 = self.0.wrapping_add(1);
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Shuffle all 16 bit numbers, an actual shuffle
|
||||
/// But this still stores local values in a linear format
|
||||
pub struct FeistelShuffle(u16, u32);
|
||||
|
||||
impl FeistelShuffle {
|
||||
pub fn new() -> Self {
|
||||
Self(NONCE16_1, NONCE32)
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> u16 {
|
||||
self.0 = self.0.wrapping_add(NONCE16_2);
|
||||
feistel_shuffle(self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Linear recursive shuffle,
|
||||
/// feeds back into itself and doesn't store the actual state.
|
||||
/// Harder to decompile
|
||||
pub struct FeistelLCGShuffle {
|
||||
state: u16,
|
||||
a: u16, // Multiplier (must be 1 mod 4)
|
||||
c: u16, // Increment (must be odd)
|
||||
}
|
||||
|
||||
impl FeistelLCGShuffle {
|
||||
pub fn new() -> Self {
|
||||
let seed = NONCE32;
|
||||
let a = (((seed & 0x3FFF) as u16) << 2) | 1;
|
||||
let c = ((seed >> 16) as u16) | 1;
|
||||
Self { state: 0, a, c }
|
||||
}
|
||||
|
||||
pub fn next(&mut self) -> u16 {
|
||||
// 1. Advance state using LCG (Guarantees single cycle of 65536)
|
||||
self.state = self.state.wrapping_mul(self.a).wrapping_add(self.c);
|
||||
|
||||
// 2. Apply Feistel shuffle to the state (Adds randomness)
|
||||
feistel_shuffle(self.state, self.a as u32)
|
||||
}
|
||||
}
|
||||
+21
-4
@@ -1,10 +1,27 @@
|
||||
use alloc::string::String;
|
||||
|
||||
mod hash;
|
||||
mod ordering;
|
||||
// TODO: Make this seed dependent on env var;
|
||||
pub const GLOBAL_SEED: u32 = 0xDEAFBEEF;
|
||||
// pub const GLOBAL_NONCE: u32 = {
|
||||
// let time = match u128::from_str_radix(env!("BUILD_TIME"), 10) {
|
||||
// Ok(i) => i,
|
||||
// Err(_) => panic!("Failed to parse BUILD_TIME"),
|
||||
// };
|
||||
|
||||
pub use hash::sha256;
|
||||
pub use ordering::feistel_shuffle;
|
||||
// GLOBAL_SEED ^ (time as u32)
|
||||
// };
|
||||
|
||||
mod feistel;
|
||||
#[allow(dead_code)]
|
||||
mod feistel_state;
|
||||
mod sha256;
|
||||
|
||||
pub use feistel::feistel_shuffle;
|
||||
pub use feistel_state::{Counter, FeistelLCGShuffle, FeistelShuffle, NoShuffle};
|
||||
pub use sha256::sha256;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! hash_256 {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
use crate::crypto::{FeistelLCGShuffle, FeistelShuffle, NoShuffle};
|
||||
|
||||
#[test]
|
||||
fn test_linear_shuffle() {
|
||||
let mut seen = [false; 65536];
|
||||
let mut counter = NoShuffle::new();
|
||||
for _ in 0..65535 {
|
||||
let val = counter.next();
|
||||
|
||||
assert!(!seen[val as usize], "Collision detected");
|
||||
|
||||
seen[val as usize] = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_feistel_shuffle() {
|
||||
let mut seen = [false; 65536];
|
||||
let mut counter = FeistelShuffle::new();
|
||||
for _ in 0..65535 {
|
||||
let val = counter.next();
|
||||
|
||||
assert!(!seen[val as usize], "Collision detected");
|
||||
|
||||
seen[val as usize] = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fristel_lcg_shuffle() {
|
||||
let mut seen = [false; 65536];
|
||||
let mut counter = FeistelLCGShuffle::new();
|
||||
for _ in 0..65535 {
|
||||
let val = counter.next();
|
||||
|
||||
assert!(!seen[val as usize], "Collision detected");
|
||||
|
||||
seen[val as usize] = true;
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,11 @@ impl Endpoint {
|
||||
/// reuse an id before the previous route has closed. If every `u16` id is active
|
||||
/// the function panics; that is a hard local resource exhaustion condition, not a
|
||||
/// recoverable packet error.
|
||||
///
|
||||
/// TODO: Reevaluate this method of allocation checking. It can be quite slow
|
||||
pub fn allocate_hook_id(&mut self) -> HookID {
|
||||
for _ in 0..=HookID::MAX {
|
||||
let candidate = self.last_hook;
|
||||
self.last_hook = self.last_hook.wrapping_add(1);
|
||||
let candidate = self.last_hook.next();
|
||||
|
||||
if !self.hooks.contains_key(&candidate) {
|
||||
return candidate;
|
||||
|
||||
@@ -5,15 +5,17 @@ pub use hooks::HookID;
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
use crate::protocol::{ConnectionSet, HookMap, Leaf, Packet, Path, RouteMap};
|
||||
use crate::{
|
||||
crypto::Counter,
|
||||
protocol::{ConnectionSet, HookMap, Leaf, Packet, Path, RouteMap},
|
||||
};
|
||||
|
||||
pub struct Endpoint {
|
||||
// This endpoint's identifier
|
||||
pub id: u32,
|
||||
|
||||
// A counter that creates unique hook IDs.
|
||||
// TODO: Randomize the hooks for more obfuscation
|
||||
pub(crate) last_hook: u16,
|
||||
pub(crate) last_hook: Counter,
|
||||
|
||||
// Absolute path for this node. Must be set by some leaf
|
||||
pub path: Path,
|
||||
@@ -36,7 +38,7 @@ impl Endpoint {
|
||||
Self {
|
||||
id,
|
||||
// Init the hook at 0, which will increment
|
||||
last_hook: 0,
|
||||
last_hook: Counter::new(),
|
||||
|
||||
// Set the current path as an empty vec
|
||||
path: Vec::new(),
|
||||
|
||||
Reference in New Issue
Block a user