Grid

Struct Grid 

Source
pub struct Grid<const W: usize, const H: usize>(/* private fields */);
Expand description

A 2D matrix of 64-bit signed integers used as the core data structure in WHY2 encryption.

The Grid represents either input data or a key, formatted into rows and columns of i64 cells. All transformations—round mixing, key scheduling, and nonlinear diffusion—operate directly on this structure.

Grids are flexible and can be transformed in-place. This abstraction allows WHY2 to generalize encryption over variable-sized blocks of dimension $W \times H$.

§Grid Size Consistency

WHY2 requires that the same grid dimensions ($W \times H$) be used consistently throughout encryption and decryption. Mixing grid sizes within a single session or across rounds is unsupported and may lead to incorrect results or undefined behavior.

Implementations§

Source§

impl<const W: usize, const H: usize> Grid<W, H>

Implementation of core Grid operations for fixed-size grids.

This block defines methods for Grid<W, H>, where W and H are compile-time constants representing the grid’s width and height. All transformations — such as ARX mixing, key application, and round-based encryption - operate on grids of this fixed shape.

§Type Parameters

  • W: Number of columns (width), must be a compile-time constant.
  • H: Number of rows (height), must be a compile-time constant.

§Notes

  • Grid dimensions must remain consistent across encryption and decryption.
Source

pub fn new() -> Result<Self, GridError>

Creates a new Grid initialized with zeroes.

This constructor sets up an empty Grid where all cells are set to 0.

§Returns
  • Ok(Grid) instance with all values set to zero and area is larger than 1.
  • Err(GridError) if the area is 1
§Notes
  • This method does not perform any encryption or transformation.
Source

pub fn from_key(vec: Zeroizing<Vec<i64>>) -> Result<Self, GridError>

Initializes a key Grid from a vector of signed 64-bit integers.

Each cell is built from two key parts using nonlinear mixing. addition, XOR, and rotation. This improves diffusion and avoids simple linear patterns in the key.

§Algorithm

For each cell index $i$, the key parts $A$ and $B$ are derived from the input vector $V$:

$$ A = (V_i + V_{i + \text{Area}}) \lll (i \bmod 64) $$

$$ B = (V_i \oplus V_{i + \text{Area}}) \ggg (i \bmod 64) $$

where $\lll$ and $\ggg$ denote left and right rotation respectively.

The final grid value is computed as: $$ Grid_{x,y} = A \oplus B \oplus i $$

§Parameters
  • vec: A vector of signed 64-bit integers representing the raw key.
§Returns
  • Ok(Grid) with mixed key values if dimensions are valid.
  • Err(GridError) if the grid area is too small.
Source

pub fn from_bytes(bytes: &[u8]) -> Result<Vec<Self>, GridError>

Initializes Grid from vector of unsigned 8-bit integers.

This function constructs Grid by chunking the input vector into i64 cells. It expects exactly $W \times H \times 8$ bytes and returns an error if the input length does not match.

§Parameters
  • bytes: A byte slice (&[8u]) containing the raw data.
§Returns
  • Ok(Vec<Grid>) if the byte length matches the expected grid size
  • Err(GridError) if the input length is not divisible by matrix size.
§Notes
  • No transformation is applied
  • Use this for raw Grid construction, not for secure key loading
Source

pub fn iter(&self) -> Iter<'_, [i64; W]>

Returns an iterator over rows in the Grid

Source

pub fn iter_mut(&mut self) -> IterMut<'_, [i64; W]>

Returns a mutable iterator over rows in the Grid

Source

pub fn width(&self) -> usize

Returns width (number of columns) in the Grid

Source

pub fn height(&self) -> usize

Returns height (number of rows) in the Grid

Source

pub fn xor_grids(&mut self, key_grid: &Grid<W, H>)

Computes the cell-wise XOR of two Grids.

This function takes two Grids of equal dimensions and modifies the Grid in-place: $$ G_{x,y} = G_{x,y} \oplus K_{x,y} $$ It is used in WHY2 for mixing round keys, applying masks, or combining intermediate states.

§Parameters
  • key_grid: Input Grid for XOR
Source

pub fn subcell(&mut self, round: usize)

Applies nonlinear ARX-style mixing to each cell in the grid.

This transformation introduces symmetric diffusion by modifying each i64 cell using a combination of addition, rotation, and XOR operations. The process is round-dependent and designed to obscure bit patterns across the Grid.

§Parameters
  • round: A round index used to tweak the transformation logic.
§Behavior

Each 64-bit cell is split into two 32-bit halves $v_0, v_1$. For SUBCELL_ROUNDS iterations, the Feistel-like network applies:

$$ v_0 \leftarrow v_0 + (((v_1 \ll 4) \oplus (v_1 \gg 5)) + v_1) \oplus \text{sum} $$

$$ v_1 \leftarrow v_1 + (((v_0 \ll 4) \oplus (v_0 \gg 5)) + v_0) \oplus \text{sum} $$

where $\text{sum}$ is incremented by a constant $\delta = $ SUBCELL_DELTA in each round:

$$ \text{sum} \leftarrow \text{sum} + \delta $$

§Notes
  • This method mutates the Grid in-place.
  • It is inspired by TEA/XTEA but adapted for WHY2’s Grid architecture.
  • The transformation is deterministic for a given round and Grid state.
Source

pub fn shift_rows(&mut self, key_grid: &Grid<W, H>)

Applies row-wise shifting to the Grid based on a key Grid.

This transformation rotates each row of the Grid by a variable amount derived from the corresponding row in key_grid. The shift amount $S_i$ for row $i$ is computed as:

$$ S_i = \left( \bigoplus_{j=0}^{W-1} K_{i,j} \right) \bmod W $$

§Behavior
  • Each row is rotated left by $S_i$.
§Notes
  • This method mutates the grid in-place.
Source

pub fn mix_columns(&mut self)

Applies column-wise mixing to the grid using linear XOR diffusion.

This transformation modifies each column by XORing it with its adjacent column, introducing horizontal diffusion across the grid.

§Behavior

For each column $c \in {0, \dots, W-1}$, compute: $$ G_{r, c} \leftarrow G_{r, c} \oplus G_{r, (c + 1) \bmod W} $$

§Notes
  • This method mutates the grid in-place.
Source

pub fn mix_matrix(&mut self, key_grid: &Grid<W, H>)

Applies a matrix-based affine transformation to mix rows.

This function treats the Grid as a matrix and multiplies it by a key-dependent transformation matrix, while adding a deterministic noise term. This converts the transformation from purely linear ($Ax$) to affine:

$$ G’ = (L \cdot U) \cdot G + \text{noise} $$

To ensure the operation is reversible (invertible) in modular arithmetic, the transformation is constructed as a product of a Lower triangular matrix ($L$) and an Upper triangular matrix ($U$).

§Behavior
  • Lower Pass ($L$): Each row adds a multiple of previous rows ($i > j$).
  • Upper Pass ($U$): Each row adds a multiple of following rows ($i < j$).
§Notes
  • This method mutates the Grid in-place.
  • All additions and multiplications are wrapping (modulo $2^{64}$).
Source

pub fn mix_diagonals(&mut self)

Applies diagonal-wise mixing to the grid using XOR diffusion.

This transformation modifies each diagonal line by XORing each element with the next element along that diagonal.

§Behavior
  • Processes all diagonals parallel to the main diagonal.
  • For each cell $(r, c)$, compute: $$ G_{r,c} \leftarrow G_{r,c} \oplus G_{r+1, c+1} $$
§Notes
  • This method mutates the grid in-place.
Source

pub fn increment(&mut self, amount: &mut u64)

Increments the Grid value by a specified amount, treating it as a large Little-Endian integer.

This method performs modular addition of a 64-bit value to the multi-precision integer represented by the grid:

$$ G \leftarrow (G + \text{amount}) \bmod 2^{64 \times W \times H} $$

§Parameters
  • amount: The unsigned 64-bit value to add to the grid.
    • Pass 1 for standard sequential counter increment.
    • Pass a block index $i$ (offset) when initializing parallel CTR counters.
§Behavior
  • The Grid is treated as a single large integer in Little-Endian format (the cell at [0][0] is the least significant limb).
  • The amount is added to the first cell, and any resulting carry is propagated sequentially through the remaining cells.
  • If the entire grid overflows (wraps around), the value resets modulo the grid size.
§Security
  • When the constant-time feature is enabled, this function always iterates through the entire grid to prevent timing leaks via carry propagation analysis.

Trait Implementations§

Source§

impl<const W: usize, const H: usize> BitXorAssign<&Grid<W, H>> for Grid<W, H>

Source§

fn bitxor_assign(&mut self, rhs: &Grid<W, H>)

Performs the ^= operation. Read more
Source§

impl<const W: usize, const H: usize> Clone for Grid<W, H>

Source§

fn clone(&self) -> Grid<W, H>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const W: usize, const H: usize> ConstantTimeEq for Grid<W, H>

Available on crate feature constant-time only.
Source§

fn ct_eq(&self, other: &Self) -> Choice

Determine if two items are equal. Read more
Source§

fn ct_ne(&self, other: &Self) -> Choice

Determine if two items are NOT equal. Read more
Source§

impl<const W: usize, const H: usize> Debug for Grid<W, H>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const W: usize, const H: usize> Display for Grid<W, H>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const W: usize, const H: usize> Index<usize> for Grid<W, H>

Source§

type Output = [i64; W]

The returned type after indexing.
Source§

fn index(&self, y: usize) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<const W: usize, const H: usize> IndexMut<usize> for Grid<W, H>

Source§

fn index_mut(&mut self, y: usize) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl<const W: usize, const H: usize> IntoIterator for Grid<W, H>

Source§

type Item = i64

The type of the elements being iterated over.
Source§

type IntoIter = Flatten<IntoIter<[i64; W], H>>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<const W: usize, const H: usize> LowerHex for Grid<W, H>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const W: usize, const H: usize> PartialEq for Grid<W, H>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<const W: usize, const H: usize> Zeroize for Grid<W, H>

Source§

fn zeroize(&mut self)

Zero out this object from memory using Rust intrinsics which ensure the zeroization operation is not “optimized away” by the compiler.

Auto Trait Implementations§

§

impl<const W: usize, const H: usize> Freeze for Grid<W, H>

§

impl<const W: usize, const H: usize> RefUnwindSafe for Grid<W, H>

§

impl<const W: usize, const H: usize> Send for Grid<W, H>

§

impl<const W: usize, const H: usize> Sync for Grid<W, H>

§

impl<const W: usize, const H: usize> Unpin for Grid<W, H>

§

impl<const W: usize, const H: usize> UnwindSafe for Grid<W, H>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V