mirror of
https://github.com/kristoferssolo/cipher-workshop.git
synced 2025-12-31 13:52:29 +00:00
docs(des): document Feistel network and cipher operations
Add doc comments to LR struct and DES helper functions explaining the Feistel network structure: IP -> 16 rounds -> FP, with each round using expansion, S-box substitution, and P-box permutation.
This commit is contained in:
parent
9e013352a5
commit
54b3d8716d
@ -1,6 +1,10 @@
|
|||||||
use crate::block::{block32::Block32, block64::Block64};
|
use crate::block::{block32::Block32, block64::Block64};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
|
|
||||||
|
/// Left-Right pair representing DES state during Feistel rounds.
|
||||||
|
///
|
||||||
|
/// DES splits a 64-bit block into two 32-bit halves (L and R) for
|
||||||
|
/// processing through 16 Feistel rounds.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct LR {
|
pub struct LR {
|
||||||
pub(crate) left: Block32,
|
pub(crate) left: Block32,
|
||||||
@ -8,6 +12,7 @@ pub struct LR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LR {
|
impl LR {
|
||||||
|
/// Creates a new L-R pair from two 32-bit blocks.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(left: impl Into<Block32>, right: impl Into<Block32>) -> Self {
|
pub fn new(left: impl Into<Block32>, right: impl Into<Block32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -16,17 +21,20 @@ impl LR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Swaps the left and right halves in place.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn swap(&mut self) {
|
pub const fn swap(&mut self) {
|
||||||
swap(&mut self.left, &mut self.right);
|
swap(&mut self.left, &mut self.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the left 32-bit half.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn left(self) -> Block32 {
|
pub const fn left(self) -> Block32 {
|
||||||
self.left
|
self.left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the right 32-bit half.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn right(self) -> Block32 {
|
pub const fn right(self) -> Block32 {
|
||||||
|
|||||||
@ -68,12 +68,14 @@ impl BlockCipher for Des {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initial Permutation - rearranges input bits according to IP table.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn ip(block: Block64) -> Block64 {
|
fn ip(block: Block64) -> Block64 {
|
||||||
permutate(block.as_u64(), 64, 64, &IP).into()
|
permutate(block.as_u64(), 64, 64, &IP).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes 16 Feistel rounds with the given subkeys.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn feistel_rounds<'a, I>(block: Block64, subkeys: I) -> Block64
|
fn feistel_rounds<'a, I>(block: Block64, subkeys: I) -> Block64
|
||||||
where
|
where
|
||||||
@ -88,12 +90,14 @@ where
|
|||||||
lr.into()
|
lr.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Single Feistel round: L' = R, R' = L XOR f(R, K).
|
||||||
fn feistel(lr: &mut LR, subkey: Subkey) {
|
fn feistel(lr: &mut LR, subkey: Subkey) {
|
||||||
let tmp = lr.right;
|
let tmp = lr.right;
|
||||||
lr.right = lr.left ^ f_function(lr.right, subkey);
|
lr.right = lr.left ^ f_function(lr.right, subkey);
|
||||||
lr.left = tmp;
|
lr.left = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The f-function: expansion -> XOR with key -> S-box -> P-box.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn f_function(right: Block32, subkey: Subkey) -> Block32 {
|
fn f_function(right: Block32, subkey: Subkey) -> Block32 {
|
||||||
let expanded = expansion_permutation(right);
|
let expanded = expansion_permutation(right);
|
||||||
@ -102,12 +106,14 @@ fn f_function(right: Block32, subkey: Subkey) -> Block32 {
|
|||||||
p_box_permutation(sboxed)
|
p_box_permutation(sboxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands 32 bits to 48 bits using the E-box permutation.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn expansion_permutation(right: Block32) -> Block48 {
|
fn expansion_permutation(right: Block32) -> Block48 {
|
||||||
permutate(right.as_u64(), 32, 48, &E_BOX).into()
|
permutate(right.as_u64(), 32, 48, &E_BOX).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Substitutes 48 bits through 8 S-boxes, producing 32 bits.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn s_box_substitution(block: Block48) -> Block32 {
|
fn s_box_substitution(block: Block48) -> Block32 {
|
||||||
let six_bit_blocks = block.as_block6_array();
|
let six_bit_blocks = block.as_block6_array();
|
||||||
@ -127,12 +133,14 @@ fn s_box_substitution(block: Block48) -> Block32 {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Permutes 32 bits according to the P-box table.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn p_box_permutation(block: Block32) -> Block32 {
|
fn p_box_permutation(block: Block32) -> Block32 {
|
||||||
permutate(block.as_u64(), 32, 32, &P_BOX).into()
|
permutate(block.as_u64(), 32, 32, &P_BOX).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Final Permutation - inverse of IP, produces the ciphertext.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn fp(result: Block64) -> Block64 {
|
fn fp(result: Block64) -> Block64 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user