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

Copyright(C) 2014 Ricky Elrod
LicenseBSD2 (see LICENSE file)
MaintainerRicky Elrod <ricky@elrod.me>
Stabilityexperimental
Portabilitylens
Safe HaskellNone
LanguageHaskell2010

Crypto.Cipher.Spritz

Contents

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.

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

data SpritzState

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 :: Int

Register: Always incremented by w `'mod'` n whenever changed.

_j :: Int

Register

_k :: Int

Register

_z :: Int

Register: Last value produced by output

_w :: Int

Register: Modified when whip is called. Always relatively prime to n.

_a :: Int

Register: Number of nibbles absorbed since start of last shuffle of s.

_s :: Vector Int

Length n. Permutation of Z_n.

_n :: Int

All values in Spritz are modulo n.

i :: Lens' SpritzState Int

j :: Lens' SpritzState Int

k :: Lens' SpritzState Int

z :: Lens' SpritzState Int

w :: Lens' SpritzState Int

a :: Lens' SpritzState Int

s :: Lens' SpritzState (Vector Int)

n :: Lens' SpritzState Int

Spritz basic functions

initializeState

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 ()

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 ()

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 ()

TODO: Write documentation. See §3.2 AbsorbNibble.

absorbStop :: State SpritzState ()

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 ()

whips, crushes, whips, crushes, and finally whips 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.

whip

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 ()

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

update :: State SpritzState ()

Helper functions

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

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

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

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

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

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

Swap two elements given indices of S.

Making use of everything

Encyrption

encrypt

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.

decrypt

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.

keySetup

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

hash

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)

mac

Arguments

:: Vector Int

The key.

-> Vector Int

The message.

-> Int

r

-> SpritzState 
-> Vector Int 

Message authentication code. See §2.4.