feistelnet 0.1.0-alpha.2

Symetric block split Feistel Network
Documentation
use super::{KeySchedule, RoundFunction};

pub struct MagmaKeySchedule;

impl KeySchedule<u32, [u32; 8]> for MagmaKeySchedule {
   type State = usize; // Pouze počítadlo rund 0..31

   fn new_state(&self, _master_key: &[u32; 8]) -> Self::State {
      0
   }

   fn next_key(&self, master_key: &[u32; 8], state: &mut Self::State) -> u32 {
      let round = *state;
      let key = if round < 24 {
         // Prvních 24 rund: klíče jdou popořadě k0..k7, k0..k7, k0..k7
         master_key[round % 8]
      } else {
         // Posledních 8 rund: klíče jdou obráceně k7..k0
         master_key[7 - (round % 8)]
      };

      *state += 1;
      key
   }
}

/**
Magma is GOST R34.12-2015 cipher.

Its based on Soviet GOST 28147-89 with following changes:

1. Little-Endian changed to Big-Endian.
1. S-BOXES are fixed.
1. Official name is *Magma*.
*/
pub struct MagmaRF;

impl MagmaRF {
   /**
     GOST 28147-89 Parameter Set

     The parameter set has the following object identifier:
     id-tc26-gost-28147-param-Z

     Rows are K1(x), K2(x), ..., K8(x)
   */
   const SBOX: [[u8; 16]; 8] = [
      [12, 4, 6, 2, 10, 5, 11, 9, 14, 8, 13, 7, 0, 3, 15, 1],
      [6, 8, 2, 3, 9, 10, 5, 12, 1, 14, 4, 7, 11, 13, 0, 15],
      [11, 3, 5, 8, 2, 15, 10, 13, 14, 1, 7, 4, 12, 9, 6, 0],
      [12, 8, 2, 1, 13, 4, 15, 6, 7, 0, 10, 5, 3, 14, 9, 11],
      [7, 15, 5, 10, 8, 1, 6, 13, 0, 9, 3, 14, 11, 4, 2, 12],
      [5, 13, 15, 6, 9, 2, 12, 10, 11, 7, 8, 1, 4, 3, 14, 0],
      [8, 14, 2, 5, 6, 9, 1, 12, 15, 4, 11, 0, 13, 10, 3, 7],
      [1, 7, 14, 13, 0, 5, 8, 3, 4, 15, 10, 6, 9, 12, 11, 2],
   ];

   fn t(value: u32) -> u32 {
      let mut result = 0u32;
      for i in 0..8 {
         let shift = (7 - i) * 4;
         let nibble = ((value >> shift) & 0xF) as usize;

         // Highest nibble (i=0) transform using K8 (index 7)
         let sbox_index = 7 - i;

         let substituted = Self::SBOX[sbox_index][nibble] as u32;
         result |= substituted << shift;
      }
      result
   }
}

impl RoundFunction<u32> for MagmaRF {
   fn f(&self, right: &u32, round_key: &u32) -> u32 {
      // 1. Sčítání s klíčem modulo 2^32
      let value = right.wrapping_add(*round_key);

      // 3. Bitová rotace o 11 pozic doleva
      MagmaRF::t(value).rotate_left(11)
   }
}

include!("magma_sbox.rs");

#[cfg(test)]
#[path = "magma_test.rs"]
mod magma_test;