spritz-0.1.0.0: An implementation of the Spritz RC4-like stream cipher in Haskell

Crypto.Cipher.Spritz

Description

The original paper for the Spritz cipher can be found here:

https://people.csail.mit.edu/rivest/pubs/RS14.pdf

This package provides a Haskell implementation of the pseudocode in the paper listed above. It intends to be a direct implementation of the cipher, so we rely heavily on use of the State monad. We also make heavy use of the lens library's combinators, internally, to ease our use of State.

Please report any and all bugs to https://github.com/relrod/spritz.

Lastly, I must give a shout-out to spritzjs for the bitmasking parts and for existing so that I had something to test against when I was done.

Synopsis

# State/Lenses

Register values and `s`. As a difference to the paper, we also include `n` in the state, for easy access to it within the various functions.

See §3.1 State.

Constructors

 SpritzState Fields_i :: IntRegister: Always incremented by `w `'mod'` n` whenever changed._j :: IntRegister_k :: IntRegister_z :: IntRegister: Last value produced by `output`_w :: IntRegister: Modified when `whip` is called. Always relatively prime to `n`._a :: IntRegister: Number of nibbles absorbed since start of last `shuffle` of `s`._s :: Vector IntLength `n`. Permutation of Z_n._n :: IntAll values in Spritz are modulo `n`.

Instances

 Eq SpritzState Ord SpritzState Show SpritzState

s :: Lens' SpritzState (Vector Int) Source

# Spritz basic functions

Arguments

 :: Int The `n` value to use throughout. -> SpritzState The initial state.

Returns the standard initial state. See §3.2 InitializeState.

absorb :: Vector Int -> State SpritzState () Source

Takes a variable-lenght input and updates the state based on it. Spritz absorbs input in blocks of `floor (n / 2)` nibbles each (low-order nibble of each byte first). After each block is absorbed, we call `shuffle`.

Satisfies the following law:

``absorb` x1 >> `absorb` x2 = 'absorb (x1 ++ x2)'`

See §3.2 Absorb.

absorbByte :: Int -> State SpritzState () Source

Splits the given input byte into two nibbles and updates state based on each nibble, low-order nibble first. See §3.2 AbsorbByte.

absorbNibble :: Int -> State SpritzState () Source

Tests whether Spritz is full of absorbed data (i.e. `a = floor (n / 2)`. If it is, calls `shuffle` to mix in the absorbed data and reset `a` to 0. Then updates the state based on the value of the supplied nibble. See §3.2 AbsorbNibble.

absorbStop :: State SpritzState () Source

Equivalent to absorbing a special "stop" symbol outside of the oridnary input alphabet. The intent is to provide a clean way to separate different inputs being absorbed. See §2.1.

shuffle :: State SpritzState () Source

`whip`s, `crush`es, `whip`s, `crush`es, and finally `whip`s again. According to the paper, each `whip` randomizes the state. Calling `crush` between each `whip` causes the effects of `crush` to be not easily determined by manipulating the input. See §3.2 Shuffle.

Arguments

 :: Int `r`. The number of times to call `update`. -> State SpritzState ()

Calls `update` `r` times. Also updates `w` to the next largest value that is relatively prime to `n`.

crush :: State SpritzState () Source

Provides a non-invertable transformation from states to states. Intentionally loses information about the current state by mapping 2^(n2) states to 1 state, since each of @`n`2@ pairs of compared values in `s` are sorted into increasing order. See §3.2 "crush".

squeeze :: Int -> State SpritzState (Vector Int) Source

Main output function for Spritz. The `Int` parameter states how many bytes to produce. Calls `shuffle` if `a > 0`, which shuffles any unabsorbed input and puts Spritz into "squeeze mode" (`a > 0`). See §3.2 "squeeze".

drip :: State SpritzState Int Source

Basic pseudorandom output routine. Calls `shuffle` when `a > 0`, updates state using `update`, and produces one output byte using `output`. See §3.2 "drip".

update :: State SpritzState () Source

Advances the system to the next state by adding `w` to `i`, giving `j` and `k` their next values, and swapping `s'_'i` with `s'_'j`. `w` being relatively prime to `n` means that the value of `i` cycles modulo `n` as repeated updates are performed. See §3.2 "update".

output :: State SpritzState Int Source

Computes a single byte (`n`-value) to output, saves it in register `z` and returns it.

# Helper functions

low :: (Bits a, Num a, Show a) => a -> a Source

See §3.1 Nibbles.

high :: (Bits a, Num a, Show a) => a -> a Source

See §3.1 Nibbles.

plusmod :: Integral a => a -> a -> a -> a Source

A utility function that adds the first parameter to the second then returns that modulo the third parameter (`n`). This is used throughout Spritz in place of a more traditional `xor` approach so that `n` can be any value and is not limited to being a power of 2.

submod :: Integral a => a -> a -> a -> a Source

See `plusmod`. This is very similar except it subtracts the first two arguments instead of adding them.

swap :: Int -> Int -> State SpritzState () Source

Swap two elements given indices of S.

# Making use of everything

## Encyrption

Arguments

 :: Vector Int The key. -> Vector Int The decrypted message. -> SpritzState Starting state. -> Vector Int

Adds-modulo-N (`plusmod`) each byte of the message with the corresponding byte of the output of `squeeze` yielding an ecrypted ciphertext. See §2.2.

Arguments

 :: Vector Int The key. -> Vector Int The encrypted message. -> SpritzState Starting state. -> Vector Int

Decrypts a message encrypted with `encrypt`. Identical to `encrypt` except uses `submod` instead. See §2.2.

Arguments

 :: Int Our N value. 256 in the paper. -> Vector Int The key. -> State SpritzState ()

Used in the paper at the top of `encrypt`* and `decrypt`, but not used by default in this library. Still, we provide it in case it's needed.

`keySetup n' k' = put (initializeState n') >> absorb k'`

## Hashing

Arguments

 :: Vector Int The message. -> Int r (number of bytes). -> SpritzState Initial state. -> Vector Int

Produces an `r`-byte hash of the input message.

`hash` absorbs the input message, calls `absorbStop` to signal the end of the input message, then absorbs the desired hash length (`r`).

The given `r` is absorbed for functional separation.

See §2.3.

## Message Authentication Code (MAC)

Arguments

 :: Vector Int The key. -> Vector Int The message. -> Int r -> SpritzState -> Vector Int

Message authentication code. See §2.4.