Skip to content

Instantly share code, notes, and snippets.

@Isopod
Last active March 22, 2023 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Isopod/a411298879a144f378979241902f530a to your computer and use it in GitHub Desktop.
Save Isopod/a411298879a144f378979241902f530a to your computer and use it in GitHub Desktop.
Obfuscating IP addresses
[package]
name = "scramble"
version = "0.1.0"
edition = "2021"
[dependencies]
sha2 = "0.10"
[[bin]]
name = "scramble"
path = "scramble.rs"
use sha2::{Sha256, Digest};
const HASH_SIZE: usize = 8;
// Compute SHA-2 hash truncated to HASH_SIZE bytes
fn hash(data: &[u8]) -> [u8; HASH_SIZE] {
let mut hasher = Sha256::new();
hasher.update(data);
let digest = hasher.finalize();
let mut result = [0; HASH_SIZE];
result.copy_from_slice(&digest[0..HASH_SIZE]);
return result;
}
fn factorial(n: u64) -> u64 {
(1..=n).fold(1, |x,y| x * y)
}
fn scramble(
key: &[u8], ip: &[u8; 4], range: usize, unscramble: bool
) -> ([u8; 4], usize) {
assert!(range % 4 == 0);
// Split ip into 8 nibbles and set all nibbles that are not part of the subnet mask to 0
let mut a: Vec<u8> =
ip.iter().map(
|x| [x >> 4, x & 0x0F]
)
.flatten()
.enumerate()
.map(
|(i,x)| if 4*i >= range { 0 } else { x }
).collect();
assert_eq!(a.len(), 8);
//println!("a = {:?}", &a);
for _i in 0..range/4 {
// When encoding, we iterate backward (n/4-1 down to 0)
// When decoding, we iterate forward (0 to n/4-1)
let i = if unscramble { _i } else { range/4 - 1 - _i };
// Concatenate key and the first i elements of a
let secret: Vec<u8> = key.iter().chain(&a[0..i]).cloned().collect();
// Then hash the result
let h = hash(&secret);
let mut k: u64 = 0;
for b in h {
k = (256*k + (b as u64)) % factorial(16);
}
//println!("i={}, k={:?}", i, k);
// Create a permutation
let mut p: [u8; 16] = [0; 16];
for j in 0..16 {
let m = k % (j + 1);
k = k / (j + 1);
p[j as usize] = j as u8;
p[j as usize] = p[m as usize];
p[m as usize] = j as u8;
//println!(" j={}, p={:?}", j, &p);
}
if unscramble {
let mut m: u8 = 0;
for j in 0..16 {
if p[j] == a[i] {
m = j as u8;
}
}
a[i] = m;
} else {
a[i] = p[a[i] as usize];
}
//println!(" a={:?}", &a);
assert!(a[i] < 16);
}
// Fuse nibbles back into bytes and return the result
let grouped: Vec<u8> =
(0..a.len()/2).map(
|i| a[2*i] << 4 | a[2*i+1]
).collect();
let mut result = ([0; 4], range);
result.0.copy_from_slice(&grouped);
return result;
}
fn range_as_str(x: &([u8;4], usize)) -> String {
format!("{}.{}.{}.{}/{}", x.0[0], x.0[1], x.0[2], x.0[3], x.1).to_string()
}
fn main() {
let key = "secret".as_bytes();
let addrs = [
[0, 0, 0, 0],
//[1, 1, 1, 1],
[11, 22, 33, 44],
];
let mut scrambled_ranges = vec![];
println!("Scrambling");
for addr in addrs {
for r in (4..=32).filter(|x| x % 4 == 0) {
let plain = (addr, r);
let scrambled = scramble(key, &plain.0, plain.1, false);
println!(
"{:16} -> {:16}",
range_as_str(&plain), range_as_str(&scrambled),
);
scrambled_ranges.push(scrambled);
}
}
println!();
println!("Unscrambling");
for scrambled in scrambled_ranges {
let unscrambled = scramble(key, &scrambled.0, scrambled.1, true);
println!(
"{:16} <- {:16}",
range_as_str(&unscrambled), range_as_str(&scrambled),
);
}
}
Scrambling
0.0.0.0/4 -> 240.0.0.0/4
0.0.0.0/8 -> 249.0.0.0/8
0.0.0.0/12 -> 249.0.0.0/12
0.0.0.0/16 -> 249.3.0.0/16
0.0.0.0/20 -> 249.3.80.0/20
0.0.0.0/24 -> 249.3.86.0/24
0.0.0.0/28 -> 249.3.86.48/28
0.0.0.0/32 -> 249.3.86.59/32
11.22.33.44/4 -> 240.0.0.0/4
11.22.33.44/8 -> 244.0.0.0/8
11.22.33.44/12 -> 244.176.0.0/12
11.22.33.44/16 -> 244.178.0.0/16
11.22.33.44/20 -> 244.178.240.0/20
11.22.33.44/24 -> 244.178.248.0/24
11.22.33.44/28 -> 244.178.248.208/28
11.22.33.44/32 -> 244.178.248.209/32
Unscrambling
0.0.0.0/4 <- 240.0.0.0/4
0.0.0.0/8 <- 249.0.0.0/8
0.0.0.0/12 <- 249.0.0.0/12
0.0.0.0/16 <- 249.3.0.0/16
0.0.0.0/20 <- 249.3.80.0/20
0.0.0.0/24 <- 249.3.86.0/24
0.0.0.0/28 <- 249.3.86.48/28
0.0.0.0/32 <- 249.3.86.59/32
0.0.0.0/4 <- 240.0.0.0/4
11.0.0.0/8 <- 244.0.0.0/8
11.16.0.0/12 <- 244.176.0.0/12
11.22.0.0/16 <- 244.178.0.0/16
11.22.32.0/20 <- 244.178.240.0/20
11.22.33.0/24 <- 244.178.248.0/24
11.22.33.32/28 <- 244.178.248.208/28
11.22.33.44/32 <- 244.178.248.209/32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment