The ISAAC cipher: Difference between revisions
Content added Content deleted
(Added Wren) |
(Add Rust implementation) |
||
Line 4,649: | Line 4,649: | ||
This is a little test file |
This is a little test file |
||
that shows my encryption</pre> |
that shows my encryption</pre> |
||
=={{header|Rust}}== |
|||
<lang rust> |
|||
//! includes the XOR version of the encryption scheme |
|||
use std::num::Wrapping as w; |
|||
const MSG: &str = "a Top Secret secret"; |
|||
const KEY: &str = "this is my secret key"; |
|||
fn main() { |
|||
let mut isaac = Isaac::new(); |
|||
isaac.seed(KEY, true); |
|||
let encr = isaac.vernam(MSG.as_bytes()); |
|||
println!("msg: {}", MSG); |
|||
println!("key: {}", KEY); |
|||
print!("XOR: "); |
|||
for a in &encr { |
|||
print!("{:02X}", *a); |
|||
} |
|||
let mut isaac = Isaac::new(); |
|||
isaac.seed(KEY, true); |
|||
let decr = isaac.vernam(&encr[..]); |
|||
print!("\nXOR dcr: "); |
|||
println!("{}", String::from_utf8(decr).unwrap()) |
|||
} |
|||
macro_rules! mix_v( |
|||
($a:expr) => ( |
|||
{ |
|||
$a[0] ^= $a[1] << 11; $a[3] += $a[0]; $a[1] += $a[2]; |
|||
$a[1] ^= $a[2] >> 2; $a[4] += $a[1]; $a[2] += $a[3]; |
|||
$a[2] ^= $a[3] << 8; $a[5] += $a[2]; $a[3] += $a[4]; |
|||
$a[3] ^= $a[4] >> 16; $a[6] += $a[3]; $a[4] += $a[5]; |
|||
$a[4] ^= $a[5] << 10; $a[7] += $a[4]; $a[5] += $a[6]; |
|||
$a[5] ^= $a[6] >> 4; $a[0] += $a[5]; $a[6] += $a[7]; |
|||
$a[6] ^= $a[7] << 8; $a[1] += $a[6]; $a[7] += $a[0]; |
|||
$a[7] ^= $a[0] >> 9; $a[2] += $a[7]; $a[0] += $a[1]; |
|||
} ); |
|||
); |
|||
struct Isaac { |
|||
mm: [w<u32>; 256], |
|||
aa: w<u32>, |
|||
bb: w<u32>, |
|||
cc: w<u32>, |
|||
rand_rsl: [w<u32>; 256], |
|||
rand_cnt: u32, |
|||
} |
|||
impl Isaac { |
|||
fn new() -> Isaac { |
|||
Isaac { |
|||
mm: [w(0u32); 256], |
|||
aa: w(0), |
|||
bb: w(0), |
|||
cc: w(0), |
|||
rand_rsl: [w(0u32); 256], |
|||
rand_cnt: 0, |
|||
} |
|||
} |
|||
fn isaac(&mut self) { |
|||
self.cc += w(1); |
|||
self.bb += self.cc; |
|||
for i in 0..256 { |
|||
let w(x) = self.mm[i]; |
|||
match i % 4 { |
|||
0 => self.aa ^= self.aa << 13, |
|||
1 => self.aa ^= self.aa >> 6, |
|||
2 => self.aa ^= self.aa << 2, |
|||
3 => self.aa ^= self.aa >> 16, |
|||
_ => unreachable!(), |
|||
} |
|||
self.aa += self.mm[((i + 128) % 256) as usize]; |
|||
let w(y) = self.mm[((x >> 2) % 256) as usize] + self.aa + self.bb; |
|||
self.bb = self.mm[((y >> 10) % 256) as usize] + w(x); |
|||
self.rand_rsl[i] = self.bb; |
|||
} |
|||
self.rand_cnt = 0; |
|||
} |
|||
fn rand_init(&mut self, flag: bool) { |
|||
let mut a_v = [w(0x9e37_79b9u32); 8]; |
|||
for _ in 0..4 { |
|||
// scramble it |
|||
mix_v!(a_v); |
|||
} |
|||
for i in (0..256).step_by(8) { |
|||
// fill in mm[] with messy stuff |
|||
if flag { |
|||
// use all the information in the seed |
|||
for (j, value) in a_v.iter_mut().enumerate().take(8) { |
|||
*value += self.rand_rsl[i + j]; |
|||
} |
|||
} |
|||
mix_v!(a_v); |
|||
for (j, value) in a_v.iter().enumerate().take(8) { |
|||
self.mm[i + j] = *value; |
|||
} |
|||
} |
|||
if flag { |
|||
// do a second pass to make all of the seed affect all of mm |
|||
for i in (0..256).step_by(8) { |
|||
for (j, value) in a_v.iter_mut().enumerate().take(8) { |
|||
*value += self.mm[i + j]; |
|||
} |
|||
mix_v!(a_v); |
|||
for (j, value) in a_v.iter().enumerate().take(8) { |
|||
self.mm[i + j] = *value; |
|||
} |
|||
} |
|||
} |
|||
self.isaac(); // fill in the first set of results |
|||
self.rand_cnt = 0; // prepare to use the first set of results |
|||
} |
|||
/// Get a random 32-bit value |
|||
fn i_random(&mut self) -> u32 { |
|||
let r = self.rand_rsl[self.rand_cnt as usize]; |
|||
self.rand_cnt += 1; |
|||
if self.rand_cnt > 255 { |
|||
self.isaac(); |
|||
self.rand_cnt = 0; |
|||
} |
|||
r.0 |
|||
} |
|||
/// Seed ISAAC with a string |
|||
fn seed(&mut self, seed: &str, flag: bool) { |
|||
for i in 0..256 { |
|||
self.mm[i] = w(0); |
|||
} |
|||
for i in 0..256 { |
|||
self.rand_rsl[i] = w(0); |
|||
} |
|||
for i in 0..seed.len() { |
|||
self.rand_rsl[i] = w(u32::from(seed.as_bytes()[i])); |
|||
} |
|||
// initialize ISAAC with seed |
|||
self.rand_init(flag); |
|||
} |
|||
/// Get a random character in printable ASCII range |
|||
fn i_rand_ascii(&mut self) -> u8 { |
|||
(self.i_random() % 95 + 32) as u8 |
|||
} |
|||
/// XOR message |
|||
fn vernam(&mut self, msg: &[u8]) -> Vec<u8> { |
|||
msg.iter() |
|||
.map(|&b| (self.i_rand_ascii() ^ b)) |
|||
.collect::<Vec<u8>>() |
|||
} |
|||
} |
|||
impl Default for Isaac { |
|||
fn default() -> Self { |
|||
Isaac::new() |
|||
} |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
msg: a Top Secret secret |
|||
key: this is my secret key |
|||
XOR: 1C0636190B1260233B35125F1E1D0E2F4C5422 |
|||
XOR dcr: a Top Secret secret |
|||
</pre> |
|||
=={{header|Sidef}}== |
=={{header|Sidef}}== |