-
-
Save Isopod/a411298879a144f378979241902f530a to your computer and use it in GitHub Desktop.
Obfuscating IP addresses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "scramble" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
sha2 = "0.10" | |
[[bin]] | |
name = "scramble" | |
path = "scramble.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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