mirror of
https://github.com/kristoferssolo/cipher-workshop.git
synced 2025-12-20 11:04:38 +00:00
136 lines
3.8 KiB
Rust
136 lines
3.8 KiB
Rust
use crate::{
|
|
constants::{PC1, PC2, ROUND_ROTATIONS},
|
|
key::{Key, cd56::CD56, key56::Key56, subkey::Subkey},
|
|
utils::permutate,
|
|
};
|
|
use std::{
|
|
array,
|
|
fmt::Debug,
|
|
iter::Rev,
|
|
ops::Index,
|
|
slice::{Iter, IterMut},
|
|
};
|
|
|
|
/// Container for all 16 round subkeys; zeroized on drop.
|
|
#[derive(Default)]
|
|
pub struct Subkeys([Subkey; 16]);
|
|
|
|
impl Subkeys {
|
|
/// Generates 16 round subkeys from the given key.
|
|
#[must_use]
|
|
pub fn from_key(key: &Key) -> Self {
|
|
let mut cd56 = pc1(key).split(); // 56-bit: C0 + D0
|
|
|
|
let subkeys = array::from_fn(|idx| {
|
|
cd56.rotate_left(ROUND_ROTATIONS[idx]);
|
|
pc2(&cd56)
|
|
});
|
|
|
|
Self(subkeys)
|
|
}
|
|
|
|
/// Returns an iterator over the subkeys.
|
|
pub fn iter(&self) -> Iter<'_, Subkey> {
|
|
self.0.iter()
|
|
}
|
|
|
|
/// Returns a reverse iterator over the subkeys.
|
|
pub fn iter_rev(&self) -> Rev<Iter<'_, Subkey>> {
|
|
self.0.iter().rev()
|
|
}
|
|
|
|
/// Returns a mutable iterator over the subkeys.
|
|
pub fn iter_mut(&mut self) -> IterMut<'_, Subkey> {
|
|
self.0.iter_mut()
|
|
}
|
|
}
|
|
|
|
/// Initial permutation (PC-1): 64-bit -> 56-bit.
|
|
#[inline]
|
|
#[must_use]
|
|
fn pc1(key: &Key) -> Key56 {
|
|
permutate(key.as_u64(), 64, 56, &PC1).into()
|
|
}
|
|
|
|
/// Compression permutation (PC-2): 56-bit -> 48-bit.
|
|
#[inline]
|
|
#[must_use]
|
|
fn pc2(cd: &CD56) -> Subkey {
|
|
let key56 = Key56::from(cd);
|
|
permutate(key56.as_u64(), 56, 48, &PC2).into()
|
|
}
|
|
|
|
impl<'a> IntoIterator for &'a Subkeys {
|
|
type Item = &'a Subkey;
|
|
type IntoIter = Iter<'a, Subkey>;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
self.iter()
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoIterator for &'a mut Subkeys {
|
|
type Item = &'a mut Subkey;
|
|
type IntoIter = IterMut<'a, Subkey>;
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
self.iter_mut()
|
|
}
|
|
}
|
|
|
|
impl Index<usize> for Subkeys {
|
|
type Output = Subkey;
|
|
fn index(&self, index: usize) -> &Self::Output {
|
|
&self.0[index]
|
|
}
|
|
}
|
|
|
|
impl Debug for Subkeys {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_str("Subkeys[REDACTED]")
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use rstest::rstest;
|
|
|
|
const TEST_KEY: u64 = 0x1334_5779_9BBC_DFF1;
|
|
|
|
#[rstest]
|
|
#[case(TEST_KEY, 0x00F0_CCAA_F556_678F)]
|
|
fn pc1_permutaion_correct(#[case] key: u64, #[case] expected: u64) {
|
|
let result = pc1(&key.into()).as_u64();
|
|
assert_eq!(
|
|
result, expected,
|
|
"PC1 permutation failed. Expected {expected:08X}, got {result:08X}",
|
|
);
|
|
}
|
|
|
|
#[rstest]
|
|
#[case(0x00F0_CCAA_F556_678F, 0xCB3D_8B0E_17F5)] // K_0
|
|
#[case(0x00E1_9955_FAAC_CF1E, 0x1B02_EFFC_7072)] // K_1
|
|
#[case(0x00C3_32AB_F559_9E3D, 0x79AE_D9DB_C9E5)] // K_2
|
|
#[case(0x000C_CAAF_F566_78F5, 0x55FC_8A42_CF99)] // K_3
|
|
#[case(0x0033_2ABF_C599_E3D5, 0x72AD_D6DB_351D)] // K_4
|
|
#[case(0x00CC_AAFF_0667_8F55, 0x7CEC_07EB_53A8)] // K_5
|
|
#[case(0x0032_ABFC_399E_3D55, 0x63A5_3E50_7B2F)] // K_6
|
|
#[case(0x00CA_AFF0_C678_F556, 0xEC84_B7F6_18BC)] // K_7
|
|
#[case(0x002A_BFC3_39E3_D559, 0xF78A_3AC1_3BFB)] // K_8
|
|
#[case(0x0055_7F86_63C7_AAB3, 0xE0DB_EBED_E781)] // K_9
|
|
#[case(0x0055_FE19_9F1E_AACC, 0xB1F3_47BA_464F)] // K_10
|
|
#[case(0x0057_F866_5C7A_AB33, 0x215F_D3DE_D386)] // K_11
|
|
#[case(0x005F_E199_51EA_ACCF, 0x7571_F594_67E9)] // K_12
|
|
#[case(0x007F_8665_57AA_B33C, 0x97C5_D1FA_BA41)] // K_13
|
|
#[case(0x00FE_1995_5EAA_CCF1, 0x5F43_B7F2_E73A)] // K_14
|
|
#[case(0x00F8_6655_7AAB_33C7, 0xBF91_8D3D_3F0A)] // K_15
|
|
#[case(0x00F0_CCAA_F556_678F, 0xCB3D_8B0E_17F5)] // K_16
|
|
fn pc2_permutaion(#[case] before: u64, #[case] expected: u64) {
|
|
let key56 = Key56::from(before).split();
|
|
let result = pc2(&key56).as_u64();
|
|
assert_eq!(
|
|
result, expected,
|
|
"PC2 permutation failed. Expected {expected:016X}, got {result:016X}"
|
|
);
|
|
}
|
|
}
|