Internals

Keccak

KangarooTwelve.keccak_p1600Function
keccak_p1600(state::NTuple{25, UInt64}, ::Val{nrounds}=Val{12}())

Apply the Keccak-p[nrounds, 1600] permutation to state. This is formally defined in the Keccak reference and formalised in FIPS 202.

Extended help

This is a variable-round permutation, with up to 24 rounds, where the last round performed matches the final Keccak-f permutation round.

Each round of permutation consists of five steps, termed θ, ρ, π, χ, and ι. These all operate on a 200-byte state, viewed in a number of different configurations.

             ┌─┬─┬─┬─┬─┐
            ┌─┬─┬─┬─┬─┐┤
           ┌─┬─┬─┬─┬─┐┤┤
          ┌─┬─┬─┬─┬─┐┤┤┤
         ┌─┬─┬─┬─┬─┐┤┤┤┤
        ┌─┬─┬─┬─┬─┐┤┤┤┤┘
       ┌─┬─┬─┬─┬─┐┤┤┤┤┘
      ┌─┬─┬─┬─┬─┐┤┤┤┤┘
      ├─┼─┼─┼─┼─┤┤┤┤┘
      ├─┼─┼─┼─┼─┤┤┤┘
      ├─┼─┼─┼─┼─┤┤┘        ┌─┐ bit
      ├─┼─┼─┼─┼─┤┘         └─┘         ┌─┐
      └─┴─┴─┴─┴─┘                     ┌─┐┘
         state                       ┌─┐┘
                                    ┌─┐┘
                   ┌─┐             ┌─┐┘
                   ├─┤ column     ┌─┐┘
     row           ├─┤           ┌─┐┘
 ┌─┬─┬─┬─┬─┐       ├─┤          ┌─┐┘  lane
 └─┴─┴─┴─┴─┘       ├─┤          └─┘
                   └─┘
  • θ step Compute the parity of five columns, and xor-diffuse their parity into nearby columns.
  • ρ step Bitwise-rotate each of the 25 lanes by a different triangular number.
  • π step Permute each lane in a fixed pattern.
  • χ step Intra-row bitwise combination. This provides the non-linearity.
  • ι step The first lane is (xor-)mixed with a LFSR sequence across rounds. This serves to disrupt the symmetry of the scheme.
source

Turboshake

KangarooTwelve.turboshakeFunction
turboshake(output::Type, message::AbstractVector{<:UInt8to64},
           delimsuffix::UInt8=0x80, ::Val{capacity} = Val{256}())

Produce an output (Unsigned or NTuple{n, <:Unsigned}) value, by performing TurboSHAKE on message with a certain capacity and delimsuffix.

See also: absorb, pad, and squeeze.

source

Sponge & Vine

KangarooTwelve.AbstractSpongeType
AbstractSponge

A sponge is a generalisation of hash functions and stream ciphers. It is in essance an iterated construction of a variable-input variable-output function based on a fixed length permutation and an internal state.

The way the sponge operates can be illustrated well with a diagram following the state.

 Message (padded)
  └───┬──────┬──────┬──────┐      ┊ ┌──────┬──────┬───▶ Output
      │      │      │      │      ┊ │      │      │
 ┌─┐  │  ╭─╮ │  ╭─╮ │  ╭─╮ │  ╭─╮ ┆ │  ╭─╮ │  ╭─╮ │
 │ │  ▼  │ │ ▼  │ │ ▼  │ │ ▼  │ │ ┆ │  │ │ │  │ │ │
r│0├──⨁─▶│ ├─⨁─▶│ ├─⨁─▶│ ├─⨁─▶│ ├─┼─┴─▶│ ├─┴─▶│ ├─┴─▶ ╍
 │ │     │f│    │f│    │f│    │f│ ┆    │f│    │f│
 ├─┤     │ │    │ │    │ │    │ │ ┆    │ │    │ │
c│0├────▶│ ├───▶│ ├───▶│ ├───▶│ ├─┼───▶│ ├───▶│ ├───▶ ╍
 └─┘     ╰─╯    ╰─╯    ╰─╯    ╰─╯ ┆    ╰─╯    ╰─╯
                        Absorbing ┆ Squeezing

First, the input is padded with a reversible padding rule and the state is initialised to zero.

  • In the absorbing phase, the input is processed in blocks of r bits, and xor'd with the first r bits of the state (leaving the remaining c bits unchanged), with absorptions interlieved with applications of the function f.
  • In the squeezing phase, the first r bits of the state are returned as the output. Shoult more output be wanted, f can simply be applied to the state again.

While this construction is defined for any fixed-length permutation f, however we specialise on keccak_p1600.

It is possible to either incrementally either one lane at a time, or one byte at a time. To handle these two cases we have the Sponge and ByteSponge subtypes.

source
KangarooTwelve.AbstractCoralVineType
AbstractCoralVine{rate}

A binary tree where at each node, only one child itself has children.

trunk ◆
     / \
    ◆   ◇ leaf
   / \
  ◆   ◇ leaf
  ┆

This esentially creates a "vine" like structure, with a single "trunk" that has terminal "leaves" sprouting off it.

The trunk and its leaves are sponges, and it is this "vine of sponges" conception that lends itself to the "Coral Vine" name (since coral sponges are the only sponge that grows I'm aware of).

Since the final result of the vine is obtained from folding all leaves into it sequentially, we can represent the intermediate state of the vine with just the "trunk" and the most recent leaf (having folded all completed leaves into the trunk).

                      ╭──────╮
                      │ Leaf │
╭─────────╮      □    ╰─┬────╯
│  Trunk  ├──┬───┴───┬──╯
╰─────────╯  □       □

However, at the very start data is absorbed into the trunk itself. After it is full, all subsequent data goes to the leaves, and the trunk only absorbs values squeezed from leaves.

The distinction between these two stages is made with the subtypes CoralVineSeedling and CoralVine.

source
KangarooTwelve.absorb_lengthFunction
absorb_length(accumulator::Union{<:ByteSponge, <:AbstractCoralVine}, val::UInt, ::Val{bufsize}=Val{8}())

Ingest a right-encoded form of val into accumulator, allowing the encoding to be up to bufsize bytes.

source
KangarooTwelve.finaliseFunction
finalise(vine::AbstractCoralVine) -> ByteSponge

Finalise vine by folding in the current leaf returning the padded trunk.

source

State operations

The absorb, pad, squeeze, and squeeze! are implemented for state tuples, sponges, and vines.

KangarooTwelve.absorbFunction
absorb(state::NTuple{25, UInt64}, block::NTuple{rate, UInt64})

Ingest a single block of input (with implied rate) into state.

The first rate elements of the state are xor'd block, and then the state is permuted with keccak_p1600.

source
absorb(state::NTuple{25, UInt64}, ::Val{capacity}, message::AbstractVector{<:Unsigned})

Ingest message into state, with the rate calculated based on capacity.

This breaks message into rate-sized blocks and then absorbs them (as per absorb(state, ::NTuple{rate, UInt64})) in turn.

source
absorb(sponge::ByteSponge, x::Union{<:Unsigned, NTuple{N, <:Unsigned}})

Ingest x into sponge.

source
absorb(sponge::AbstractSponge, block::AbstractVector{<:Unsigned})

Ingest each element of block into sponge.

source
absorb(vine::AbstractCoralVine, leaflet::AbstractVector{<:Unsigned})
absorb(vine::AbstractCoralVine, x::Unsigned)

Ingest leaflet/x into vine, this may go into the leaves or the trunk depending on the vine type, and may cause the current leaf to be folded into the trunk, and a new leaf grown.

source
KangarooTwelve.padFunction
pad(state::NTuple{25, UInt64}, ::Val{capacity}, lastbyte::UInt, delimsuffix::UInt8)

Perform "padding" of the lastbyte byte of state with delimsuffix.

This is the final modification to state in turboshake.

source
KangarooTwelve.squeezeFunction
squeeze(outtype::Type, state::NTuple{25, UInt64}, ::Val{capacity})

Squeeze an outtype out of state. outtype can be an Unsigned type or an unsigned NTuple.

source
squeeze(T::Type, sponge::AbstractSponge)

Squeeze a T out of sponge.

source
KangarooTwelve.squeeze!Function
squeeze!(output::Vector{UInt64}, state::NTuple{25, UInt64}, ::Val{capacity})

Squeeze state into output.

source
squeeze!(output::Vector{UInt64}, sponge::AbstractSponge)

Squeeze sponge into output.

source