Browse Source

Tests, benchmarks, input stream

master
Maya Herrscher 11 months ago
parent
commit
dc59f69e80
  1. 543
      Cargo.lock
  2. 8
      Cargo.toml
  3. 16
      benches/idea_timing_benchmark.rs
  4. 218
      src/lib.rs
  5. 226
      src/main.rs
  6. BIN
      test0

543
Cargo.lock

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.14"
@ -51,12 +60,58 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"bitflags",
"textwrap",
"unicode-width",
]
[[package]]
name = "clap"
version = "4.5.9"
@ -112,19 +167,145 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "criterion"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
dependencies = [
"atty",
"cast",
"clap 2.34.0",
"criterion-plot",
"csv",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "csv"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "env_logger"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"log",
"regex",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "half"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "idea"
version = "0.2.0"
version = "1.0.0"
dependencies = [
"clap",
"clap 4.5.9",
"clap-num",
"criterion",
"modinverse",
"quickcheck",
]
[[package]]
@ -133,6 +314,54 @@ version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "modinverse"
version = "0.1.1"
@ -160,6 +389,46 @@ dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
version = "11.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
[[package]]
name = "plotters"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
[[package]]
name = "plotters-svg"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
@ -169,6 +438,17 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quickcheck"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
dependencies = [
"env_logger",
"log",
"rand",
]
[[package]]
name = "quote"
version = "1.0.36"
@ -178,6 +458,129 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "strsim"
version = "0.11.1"
@ -195,18 +598,154 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "web-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"

8
Cargo.toml

@ -7,3 +7,11 @@ edition = "2021"
clap = { version = "4.0", features = ["derive"] }
clap-num = { version = "1.1" }
modinverse = { version = "0.1" }
[dev-dependencies]
criterion = "0.3"
quickcheck = "1.0.3"
[[bench]]
name = "idea_timing_benchmark"
harness = false

16
benches/idea_timing_benchmark.rs

@ -0,0 +1,16 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use idea::{decrypt, encrypt};
pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("encrypt ", |b| {
b.iter(|| {
encrypt(
black_box(0x9d31ccc9ce639084e2f1f70541285b8d),
black_box(0xba431a8cfda88c8f),
)
})
});
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

218
src/lib.rs

@ -0,0 +1,218 @@
use modinverse::modinverse;
struct Vr {
v1: u16,
v2: u16,
v3: u16,
v4: u16,
}
impl Vr {
fn split(v: u64) -> Self {
let v4 = (v & 0xFFFF) as u16;
let v3 = ((v >> 16) & 0xFFFF) as u16;
let v2 = ((v >> 32) & 0xFFFF) as u16;
let v1 = ((v >> 48) & 0xFFFF) as u16;
Self {
v1: v1,
v2: v2,
v3: v3,
v4: v4,
}
}
fn expand(&self) -> u64 {
(self.v1 as u64 * 2_u64.pow(48))
+ (self.v2 as u64 * 2_u64.pow(32))
+ (self.v3 as u64 * 2_u64.pow(16))
+ self.v4 as u64
}
}
struct Keys {
z1: u16,
z2: u16,
z3: u16,
z4: u16,
z5: u16,
z6: u16,
}
fn derive_keys(mut k: u128) -> Vec<Keys> {
let mut keys: Vec<Keys> = Vec::new();
let mut subkeys = Vec::new();
while subkeys.len() < 52 {
subkeys.push((k & 0xFFFF) as u16);
subkeys.push(((k >> 16) & 0xFFFF) as u16);
subkeys.push(((k >> 32) & 0xFFFF) as u16);
subkeys.push(((k >> 48) & 0xFFFF) as u16);
subkeys.push(((k >> 64) & 0xFFFF) as u16);
subkeys.push(((k >> 80) & 0xFFFF) as u16);
subkeys.push(((k >> 96) & 0xFFFF) as u16);
subkeys.push(((k >> 112) & 0xFFFF) as u16);
k = k.rotate_left(25);
}
let mut i = 0;
while keys.len() < 8 {
keys.push(Keys {
z1: subkeys[0 + i],
z2: subkeys[1 + i],
z3: subkeys[2 + i],
z4: subkeys[3 + i],
z5: subkeys[4 + i],
z6: subkeys[5 + i],
});
i = i + 1;
}
keys.push(Keys {
z1: subkeys[0 + i],
z2: subkeys[1 + i],
z3: subkeys[2 + i],
z4: subkeys[3 + i],
z5: 0,
z6: 0,
});
keys
}
fn add(a: u16, b: u16) -> u16 {
let (a, b, m) = (a as i32, b as i32, 0x10000 as i32);
((a + b) % m) as u16
}
// 0010 0110 % 10001 -> 0010 * (-0001) + 0110 -> 0110
fn slow_mul(a: u16, b: u16) -> u16 {
let (a, b, m) = (a as u32, b as u32, 0x10001 as u32);
let a = if a == 0 {0x10000} else {a};
let b = if b == 0 {0x10000} else {b};
((a * b) % m) as u16
}
fn mul(a: u16, b: u16) -> u16 {
let (a, b) = (a as u32, b as u32);
if a == 0 && b == 0 { return 1 }
let a = if a == 0 { 0x10000 } else { a };
let b = if b == 0 { 0x10000 } else { b };
let ab = a * b;
let ab_high = ab >> 16;
let ab_low = ab & 0xffff;
let m = if ab_high > ab_low { 0x10001 } else { 0 };
(ab_low + m - ab_high) as u16
}
fn idea_round(ks: &Keys, xs: Vr) -> Vr {
let u1 = mul(ks.z1, xs.v1);
let u2 = mul(ks.z2, xs.v2);
let u3 = add(ks.z3, xs.v3);
let u4 = add(ks.z4, xs.v4);
let u13 = u1 ^ u3;
let u24 = u2 ^ u4;
let u5 = mul(ks.z5, u13);
let c1 = mul(ks.z6, add(u24, u5));
let c2 = add(u5, c1);
Vr {
v1: c1 ^ u3,
v2: c2 ^ u4,
v3: c1 ^ u1,
v4: c2 ^ u2,
}
}
fn idea_finish(ks: &Keys, xs: Vr) -> Vr {
let u1 = mul(ks.z1, xs.v1);
let u2 = mul(ks.z2, xs.v2);
let u3 = add(ks.z3, xs.v3);
let u4 = add(ks.z4, xs.v4);
Vr {
v1: u1,
v2: u2,
v3: u3,
v4: u4,
}
}
fn invert_keys(ks: &Keys, z5: u16, z6: u16) -> Keys {
let mut z1 = ks.z1 as i32;
let mut z2 = ks.z2 as i32;
if ks.z1 == 0 {
z1 = 0x010000 as i32;
}
if ks.z2 == 0 {
z2 = 0x010000 as i32;
}
Keys {
z1: modinverse(z1 as i32, 0x0010001 as i32).expect("Modular inverse of z1 doesn't exist!")
as u16,
z2: modinverse(z2 as i32, 0x0010001 as i32).expect("Modular inverse of z2 doesn't exist!")
as u16,
z3: (0x10000 as u32 - ks.z3 as u32) as u16,
z4: (0x10000 as u32 - ks.z4 as u32) as u16,
z5: z5,
z6: z6,
}
}
pub fn encrypt(k: u128, m: u64) -> u64 {
let xr = Vr::split(m);
assert_eq!(m, xr.expand());
// Derive keys
let kr = derive_keys(k);
let mut bs = xr;
let mut i = 0;
while i < 8 {
// println!("Round {i}:");
bs = idea_round(&kr[i], bs);
// println!("intermediate result: {:?}\n", bs.expand());
i = i + 1;
}
let ys = idea_finish(&kr[8], bs);
ys.expand()
}
pub fn decrypt(k: u128, m: u64) -> u64 {
let xr = Vr::split(m);
assert_eq!(m, xr.expand());
// Derive and invert keys
let kr = derive_keys(k);
let mut dr: Vec<Keys> = Vec::new();
let mut i = 8;
while i > 0 {
let ds = invert_keys(&kr[i], kr[i - 1].z5, kr[i - 1].z6);
i = i - 1;
dr.push(ds);
}
let ds = invert_keys(&kr[0], 0, 0);
dr.push(ds);
let mut bs = xr;
while i < 8 {
// println!("Round {i}:");
bs = idea_round(&dr[i], bs);
// println!("intermediate result: {:?}\n", bs.expand());
i = i + 1;
}
let ys = idea_finish(&dr[8], bs);
ys.expand()
}
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(test)]
mod tests {
use super::{decrypt, encrypt};
quickcheck! {
fn decrypt_encrypt(ks: u128, mes: u64) -> bool {
mes == decrypt(ks, encrypt(ks, mes))
}
}
use super::{slow_mul, mul};
quickcheck! {
fn correct_mul(a: u16, b: u16) -> bool {
mul(a, b) == slow_mul(a, b)
}
}
}

226
src/main.rs

@ -1,8 +1,12 @@
// ca 5h
// ca 5h initial coding
use clap::Parser;
use clap::ArgAction;
use clap_num::maybe_hex;
use modinverse::modinverse;
use idea::{decrypt, encrypt};
use std::cmp::min;
use std::io::BufRead;
use std::io::Write;
#[derive(Parser)]
struct Cli {
@ -12,177 +16,57 @@ struct Cli {
// the key used for encryption/decryption
#[arg(short = 'k', long = "key", value_parser=maybe_hex::<u128>, default_value_t = 123456789012345678901234567890)]
key: u128,
#[clap(long = "decrypt", short = 'd', action=ArgAction::SetFalse)]
decrypt: bool,
}
struct Vr {
v1: u16,
v2: u16,
v3: u16,
v4: u16,
}
impl Vr {
fn split(v: u64) -> Self {
let v4 = (v & 0xFFFF) as u16;
let v3 = ((v >> 16) & 0xFFFF) as u16;
let v2 = ((v >> 32) & 0xFFFF) as u16;
let v1 = ((v >> 48) & 0xFFFF) as u16;
Self{ v1: v1, v2: v2, v3: v3, v4: v4 }
}
fn expand(&self) -> u64 {
(self.v1 as u64 * 2_u64.pow(48)) + (self.v2 as u64 * 2_u64.pow(32)) + (self.v3 as u64 * 2_u64.pow(16)) + self.v4 as u64
}
}
struct Keys {
z1: u16, z2: u16, z3: u16, z4: u16, z5: u16, z6: u16,
}
fn derive_keys(mut k: u128) -> Vec<Keys> {
let mut keys: Vec<Keys> = Vec::new();
let mut subkeys = Vec::new();
while subkeys.len() < 52 {
subkeys.push((k & 0xFFFF) as u16);
subkeys.push(((k >> 16) & 0xFFFF) as u16);
subkeys.push(((k >> 32) & 0xFFFF) as u16);
subkeys.push(((k >> 48) & 0xFFFF) as u16);
subkeys.push(((k >> 64) & 0xFFFF) as u16);
subkeys.push(((k >> 80) & 0xFFFF) as u16);
subkeys.push(((k >> 96) & 0xFFFF) as u16);
subkeys.push(((k >> 112) & 0xFFFF) as u16);
k = k.rotate_left(25);
}
let mut i = 0;
while keys.len() < 8 {
keys.push(
Keys{ z1: subkeys[0+i], z2: subkeys[1+i], z3: subkeys[2+i], z4: subkeys[3+i], z5: subkeys[4+i], z6: subkeys[5+i] }
);
i = i+1;
}
keys.push(
Keys{ z1: subkeys[0+i], z2: subkeys[1+i], z3: subkeys[2+i], z4: subkeys[3+i], z5: 0, z6: 0 }
);
keys
}
fn add(a: u16, b: u16) -> u16 {
let (a, b, m) = (a as i32, b as i32, 0x10000 as i32);
((a + b) % m) as u16
}
fn mul(a: u16, b: u16) -> u16 {
let (a, b, m) = (a as u32, b as u32, 0x10001 as u32);
if a == 0 {
let a = 0x10000;
((a * b) % m) as u16
}
else if b == 0 {
let b = 0x10000;
((a * b) % m) as u16
}
else{
((a * b) % m) as u16
}
}
fn idea_round(ks: &Keys, xs: Vr) -> Vr {
let u1 = mul(ks.z1, xs.v1);
let u2 = mul(ks.z2, xs.v2);
let u3 = add(ks.z3, xs.v3);
let u4 = add(ks.z4, xs.v4);
let u13 = u1 ^ u3;
let u24 = u2 ^ u4;
let u5 = mul(ks.z5, u13);
let c1 = mul(ks.z6, add(u24, u5));
let c2 = add(u5, c1);
Vr { v1: c1 ^ u3, v2: c2 ^ u4, v3: c1 ^ u1, v4: c2 ^ u2 }
}
fn idea_finish(ks: &Keys, xs: Vr) -> Vr {
let u1 = mul(ks.z1, xs.v1);
let u2 = mul(ks.z2, xs.v2);
let u3 = add(ks.z3, xs.v3);
let u4 = add(ks.z4, xs.v4);
Vr { v1: u1, v2: u2, v3: u3, v4: u4 }
}
fn invert_keys(ks: &Keys, z5: u16, z6: u16) -> Keys {
let mut z1 = ks.z1 as i32;
let mut z2 = ks.z2 as i32;
if ks.z1 == 0 {
z1 = 0x010000 as i32;
}
if ks.z2 == 0 {
z2 = 0x010000 as i32;
}
Keys {
z1: modinverse(z1 as i32, 0x0010001 as i32).expect("Modular inverse of z1 doesn't exist!") as u16,
z2: modinverse(z2 as i32, 0x0010001 as i32).expect("Modular inverse of z2 doesn't exist!") as u16,
z3: (0x10000 as u32 - ks.z3 as u32) as u16,
z4: (0x10000 as u32 - ks.z4 as u32) as u16,
z5: z5,
z6: z6 }
}
fn encrypt(k: u128, m: u64) -> u64 {
let xr = Vr::split(m);
assert_eq!(m, xr.expand());
// Derive keys
let kr = derive_keys(k);
let mut bs = xr;
let mut i = 0;
while i < 8 {
println!("Round {i}:");
bs = idea_round(&kr[i], bs);
println!("intermediate result: {:?}\n", bs.expand());
i = i+1;
}
let ys = idea_finish(&kr[8], bs);
ys.expand()
}
fn decrypt(k: u128, m: u64) -> u64 {
let xr = Vr::split(m);
assert_eq!(m, xr.expand());
// Derive and invert keys
let kr = derive_keys(k);
let mut dr: Vec<Keys> = Vec::new();
let mut i = 8;
while i > 0 {
let ds = invert_keys(&kr[i], kr[i-1].z5, kr[i-1].z6);
i = i-1;
dr.push(ds);
}
let ds = invert_keys(&kr[0], 0, 0);
dr.push(ds);
let mut bs = xr;
while i < 8 {
println!("Round {i}:");
bs = idea_round(&dr[i], bs);
println!("intermediate result: {:?}\n", bs.expand());
i = i+1;
}
let ys = idea_finish(&dr[8], bs);
ys.expand()
}
fn main() {
println!("Welcome to your IDEA encryption tool!\n");
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
let key: u128 = args.key;
let key2: u128 = args.key;
let message: u64 = args.message;
println!("message: {:?}, key: {:?}\n", message, key);
let cipher: u64 = encrypt(key, message);
println!("Ciphertext: {:?}\n", cipher);
let plain: u64 = decrypt(key2, cipher);
println!("Computed plaintext: {:?}", plain);
// let message: u64 = args.message;
// println!("message: {:?}, key: {:?}\n", message, key);
let zeros = [0,0,0,0,0,0,0,0];
let mut inp = std::io::stdin().lock();
let mut out = std::io::stdout();
let mut buf: Vec<u8> = vec![0u8; 4096];
let mut amt = 0;
loop {
while amt < 8 {
let buff = inp.fill_buf()?;
if buff.is_empty() {
break;
}
let to_copy = min(buf.len() - amt, buff.len());
buf[amt..(amt + to_copy)].copy_from_slice(&buff[0..to_copy]);
amt += to_copy;
inp.consume(to_copy);
}
if amt < 8 {
let pad = 8 - amt;
buf[amt..8].copy_from_slice(&zeros[0..pad]);
amt += pad;
}
let mut offset = 0;
while amt >= offset + 8 {
let array: [u8; 8] = buf[offset..offset + 8].try_into().unwrap();
let plain = u64::from_le_bytes(array);
let cipher: u64;
if args.decrypt {
cipher = decrypt(key, plain);
}
else {
cipher = encrypt(key, plain);
}
out.write_all(&cipher.to_le_bytes())?;
offset += 8;
}
buf.copy_within(offset..amt, 0);
amt = amt - offset;
if amt == 0 {
return Ok(());
}
}
}
//

BIN
test0

Binary file not shown.
Loading…
Cancel
Save