Crypto.Skein

skein-1.0.9.2: Skein, a family of cryptographic hash functions. Includes Skein-MAC as well.

Copyright | (c) 2011 Felipe A. Lessa
License | BSD3 (see LICENSE)
Maintainer | felipe.lessa@gmail.com
Stability | provisional
Portability | portable (needs FFI)
Safe Haskell | None
Language | Haskell98

Crypto.Skein

Contents

- Using this module
  - Skein as a cryptographic hash function
  - Skein as a message authentication code (MAC)
- About Skein
- Main cryptographic hash functions
  - Skein-512-512
  - Skein-1024-1024
  - Skein-256-256
- Skein-MAC
- Other variants of cryptographic hash functions
  - Skein-256-128
  - Skein-256-160
  - Skein-256-224
- Skein-512
  - Skein-512-128
  - Skein-512-160
  - Skein-512-224
  - Skein-512-256
  - Skein-512-384
- Skein-1024
  - Skein-1024-384
  - Skein-1024-512

Description

High-level interface for the Skein family of hash functions.

Synopsis

- data Skein_512_512
- data Skein_512_512_Ctx
- data Skein_1024_1024
- data Skein_1024_1024_Ctx
- data Skein_256_256
- data Skein_256_256_Ctx
- type Key = ByteString
- skeinMAC :: (SkeinMAC skeinCtx, Hash skeinCtx digest) => Key -> ByteString -> digest
- skeinMAC' :: (SkeinMAC skeinCtx, Hash skeinCtx digest) => Key -> ByteString -> digest
- class SkeinMAC skeinCtx where
  - skeinMACCtx :: Key -> skeinCtx
- data Skein_256_128
- data Skein_256_128_Ctx
- data Skein_256_160
- data Skein_256_160_Ctx
- data Skein_256_224
- data Skein_256_224_Ctx
- data Skein_512_128
- data Skein_512_128_Ctx
- data Skein_512_160
- data Skein_512_160_Ctx
- data Skein_512_224
- data Skein_512_224_Ctx
- data Skein_512_256
- data Skein_512_256_Ctx
- data Skein_512_384
- data Skein_512_384_Ctx
- data Skein_1024_384
- data Skein_1024_384_Ctx
- data Skein_1024_512
- data Skein_1024_512_Ctx

# Using this module

Currently this module provides both Skein as a cryptographic hash function and Skein as a MAC. This module currently does not provide some Skein functions, such as tree hashing, pseudo-random number generation, stream ciphing or key derivation.

Terminology note: we say "message" for your variable-sized data that is given to Skein.

## Skein as a cryptographic hash function

There are many variants of Skein as a cryptographic hash function. They are called `Skein_X_Y`, where `X` is internal state size in bits and `Y` is the output size in bits. The main ones are `Skein_512_512`, `Skein_1024_1024` and `Skein_256_256`. If you are unsure, then use `Skein_512_512`.

To use these data types, you have to use `Hash` and `Serialize`. Suppose you wanted to hash a lazy `ByteString` `bs`. Then you could use

      digest :: ByteString
      digest = let h = hash bs :: Skein_512_512
               in encode h

where `hash` is from Crypto.Classes (`crypto-api` package), `encode` is from `Serialize` (`cereal` package) and `digest` is a strict `ByteString` with the hash. Given that we've used `Skein_512_512` which has an output size of 512 bits, `digest` will have `512 / 8 = 64` bytes of length.

## Skein as a message authentication code (MAC)

If you need a message authentication code (MAC), you may use HMAC with Skein (e.g. HMAC-Skein-512-512). Using HMAC with Skein is supported and secure. However, Skein also supports another secure method, called Skein-MAC.

Skein-MAC is as secure as HMAC with Skein, however with a much lower overhead (especially for short messages). HMAC requires two hash invocations. Skein-MAC, on the other hand, requires just one hash invocation after the setup.

To use Skein-MAC, you need `skeinMAC` (or `skeinMAC'`) and `Serialize`. You also need a `Key` with at least as many bits as the state size you choose (`256`, `512` or `1024` bits).

Suppose you want to use Skein-MAC with `Skein_512_512`. To setup the MAC function with a `Key` `key` (that has at least `512 / 8 = 64` bytes), use

      let calcMAC :: ByteString -> Skein_512_512
          calcMAC = skeinMAC key

It is recommended to partially apply `skeinMAC` (or `skeinMAC'`) to avoid recomputing the key setup. We give an explicit type to `calcMAC` because we have to choose which Skein we want.

Now, if you want to calculate the Skein-MAC of a lazy `ByteString` message `msg`, use

      let msgMAC = encode (calcMAC msg)

where `encode` is from `Serialize` (`cereal` package) and `msgMAC` is a strict `ByteString` with the MAC.

Now, suppose you are given a `msg'` with MAC `msgMAC'` and want to check the integrity and authenticity of `msg'`. You may do so by calculating the MAC of `msg'` and checking against `msgMAC'`:

      let msgMAC'' = encode (calcMAC msg')
      in if msgMAC' == msgMAC''
         then Right "Message is okay"
         else Left "Message has been corrupted or tampered with"

# About Skein

From http://www.skein-hash.info/about at 09/2011:

Skein is a new family of cryptographic hash functions. Its design combines speed, security, simplicity, and a great deal of flexibility in a modular package that is easy to analyze.

Skein is fast. Skein-512 -- our primary proposal -- hashes data at 6.1 clock cycles per byte on a 64-bit CPU. This means that on a 3.1 GHz x64 Core 2 Duo CPU, Skein hashes data at 500 MBytes/second per core -- almost twice as fast as SHA-512 and three times faster than SHA-256. An optional hash-tree mode speeds up parallelizable implementations even more. Skein is fast for short messages, too; Skein-512 hashes short messages in about 1000 clock cycles.

Skein is secure. Our current best attack on Skein-512 is on 25 of 72 rounds, for a safety factor of 2.9. For comparison, at a similar stage in the standardization process, the AES encryption algorithm had an attack on 6 of 10 rounds, for a safety factor of only 1.7. Additionally, Skein has a number of provably secure properties, increasing confidence in the algorithm.

Skein is simple. Using only three primitive operations, the Skein compression function can be easily understood and remembered. The rest of the algorithm is a straightforward iteration of this function.

Skein is flexible. Skein is defined for three different internal state sizes -- 256 bits, 512 bits, and 1024 bits -- and any output size. This allows Skein to be a drop-in replacement for the entire SHA family of hash functions. A completely optional and extendable argument system makes Skein an efficient tool to use for a very large number of functions: a PRNG, a stream cipher, a key derivation function, authentication without the overhead of HMAC, and a personalization capability. All these features can be implemented with very low overhead. Together with the Threefish large-block cipher at Skein core, this design provides a full set of symmetric cryptographic primitives suitable for most modern applications.

Skein is efficient on a variety of platforms, both hardware and software. Skein-512 can be implemented in about 200 bytes of state. Small devices, such as 8-bit smart cards, can implement Skein-256 using about 100 bytes of memory. Larger devices can implement the larger versions of Skein to achieve faster speeds.

Skein was designed by a team of highly experienced cryptographic experts from academia and industry, with expertise in cryptography, security analysis, software, chip design, and implementation of real-world cryptographic systems. This breadth of knowledge allowed them to create a balanced design that works well in all environments.

# Main cryptographic hash functions

These are the main Skein hash functions. Unless you have any special reasons, you should use one of these.

`Skein_512_512`
  is the primary cryptographic hash function of this package. It can safely be used for all current hashing applications, and should remain secure for the foreseeable future.
`Skein_1024_1024`
  is the ultra-conservative variant. Even if some future attack managed to break `Skein_512_512`, it is quite likely that `Skein_1024_1024` would remain secure.
`Skein_256_256`
  is the low-memory variant. It can be implemented using 100 bytes of RAM, but this is not the case with this implementation. It is faster than `Skein_512_512` only for small message lengths, so it's preferable to use `Skein_512_512`. If you can't afford 512 bits of output, you may get the speed advantage of `Skein_512_512` by using `Skein_512_256`.

## Skein-512-512

data Skein_512_512

Skein-512-512 hash. You probably want to use `encode` to obtain a 512-bit (64-byte) `ByteString`. It's the main Skein hash function. May be used as a drop-in replacement for SHA-512 as well.

Instances

Eq Skein_512_512 |
Ord Skein_512_512 |
Serialize Skein_512_512 |
Hash Skein_512_512_Ctx Skein_512_512 |

data Skein_512_512_Ctx

Context of the Skein-512-512 hash function.

Instances

SkeinMAC Skein_512_512_Ctx |
Hash Skein_512_512_Ctx Skein_512_512 |

## Skein-1024-1024

data Skein_1024_1024

Skein-1024-1024 hash. You probably want to use `encode` to obtain a 1024-bit (128-byte) `ByteString`. This is the ultra-conservative variant. Even if some future attack managed to break Skein-512, it's quite likely that Skein-1024 would remain secure.

Instances

Eq Skein_1024_1024 |
Ord Skein_1024_1024 |
Serialize Skein_1024_1024 |
Hash Skein_1024_1024_Ctx Skein_1024_1024 |

data Skein_1024_1024_Ctx

Context of the Skein-1024-1024 hash function.

Instances

SkeinMAC Skein_1024_1024_Ctx |
Hash Skein_1024_1024_Ctx Skein_1024_1024 |

## Skein-256-256

data Skein_256_256

Skein-256-256 hash. You probably want to use `encode` to obtain a 256-bit (32-byte) `ByteString`. Usually it's better to use `Skein_512_256` (256 bits of output) or `Skein_512_512` (512 bits of output).

Instances

Eq Skein_256_256 |
Ord Skein_256_256 |
Serialize Skein_256_256 |
Hash Skein_256_256_Ctx Skein_256_256 |

data Skein_256_256_Ctx

Context of the Skein-256-256 hash function.

Instances

SkeinMAC Skein_256_256_Ctx |
Hash Skein_256_256_Ctx Skein_256_256 |

# Skein-MAC

The standard way to use a hash function for authentication is to use the HMAC construction. While you may securely use Skein with HMAC (e.g. HMAC-Skein-512-512), Skein also supports another mode for MAC. Skein-MAC is as secure as HMAC-Skein, however faster. Skein-MAC is as fast as Skein as a hash function, with zero overhead.

type Key = ByteString

Secret key used to calculate the Skein-MAC.

The `Key` may have any length. However, it's recommended to have at least the same number of bits of the state size. For example, when using `skeinMAC` with `Skein_512_256`, it is recommended to have a key with at least 64 bytes (512 bits), which is the state size of `Skein_512_256` (the first of the two numbers).

skeinMAC :: (SkeinMAC skeinCtx, Hash skeinCtx digest) => Key -> ByteString -> digest

Calculate the Skein-MAC of a lazy `ByteString` given a `Key`. You probably also want to apply `encode` to get a `ByteString` out of the `digest`.

This function may be partially applied for increased performance. Using a partially applied `skeinMAC` is as fast as using Skein as a cryptographic hash function. So, instead of

    let mac1 = skeinMAC key message1
        mac2 = skeinMAC key message2
        mac3 = skeinMAC key message3
        ...

write the following code:

    let calcMAC = skeinMAC key
        mac1 = calcMAC message1
        mac2 = calcMAC message2
        mac3 = calcMAC message3
        ...

This way the key will be processed only once (with `skeinMACCtx`).

skeinMAC' :: (SkeinMAC skeinCtx, Hash skeinCtx digest) => Key -> ByteString -> digest

Same as `skeinMAC`, however using a strict `ByteString`. Should be faster for small `ByteString` `s`.

class SkeinMAC skeinCtx where

Class of Skein contexts that may be used for Skein-MAC (all of them). Included here mostly for documentation purposes, since adding new instances is not safe (functions using `SkeinMAC` unsurprisingly assume that they are using Skein).

Methods

skeinMACCtx :: Key -> skeinCtx

Construct a context `skeinCtx` given a `Key`. This context may be used with the usual `Hash` interface to obtain a message authentication code (MAC).

For a simpler interface, see `skeinMAC` and `skeinMAC'`.

Instances

SkeinMAC Skein_1024_1024_Ctx |
SkeinMAC Skein_1024_512_Ctx |
SkeinMAC Skein_1024_384_Ctx |
SkeinMAC Skein_512_512_Ctx |
SkeinMAC Skein_512_384_Ctx |
SkeinMAC Skein_512_256_Ctx |
SkeinMAC Skein_512_224_Ctx |
SkeinMAC Skein_512_160_Ctx |
SkeinMAC Skein_512_128_Ctx |
SkeinMAC Skein_256_256_Ctx |
SkeinMAC Skein_256_224_Ctx |
SkeinMAC Skein_256_160_Ctx |
SkeinMAC Skein_256_128_Ctx |

# Other variants of cryptographic hash functions

These hash functions produce less output bits than their state size. For example, `Skein_512_160` produces 160 output bits while having 512 bits of state size. Their main use is to be a drop-in replacement to legacy hash functions. If you don't have any special reason for using them, use one of the main hash functions above (e.g. `Skein_512_512`).

You may replace:

MD5
  with `Skein_256_128` or `Skein_512_128`.
SHA-1
  with `Skein_256_160` or `Skein_512_160`.
SHA-224
  with `Skein_256_224` or `Skein_512_224`.
SHA-256
  with `Skein_256_256` or `Skein_512_256`.
SHA-384
  with `Skein_512_384` or `Skein_1024_384`.
SHA-512
  with `Skein_512_512` or `Skein_1024_512`.

## Skein-256-128

data Skein_256_128

Skein-256-128 hash. You probably want to use `encode` to obtain a 128-bit (16-byte) `ByteString`. May be used as a drop-in replacement for MD5.

Instances

Eq Skein_256_128 |
Ord Skein_256_128 |
Serialize Skein_256_128 |
Hash Skein_256_128_Ctx Skein_256_128 |

data Skein_256_128_Ctx

Context of the Skein-256-128 hash function.

Instances

SkeinMAC Skein_256_128_Ctx |
Hash Skein_256_128_Ctx Skein_256_128 |

## Skein-256-160

data Skein_256_160

Skein-256-160 hash. You probably want to use `encode` to obtain a 160-bit (20-byte) `ByteString`. May be used as a drop-in replacement for SHA-1.

Instances

Eq Skein_256_160 |
Ord Skein_256_160 |
Serialize Skein_256_160 |
Hash Skein_256_160_Ctx Skein_256_160 |

data Skein_256_160_Ctx

Context of the Skein-256-160 hash function.

Instances

SkeinMAC Skein_256_160_Ctx |
Hash Skein_256_160_Ctx Skein_256_160 |

## Skein-256-224

data Skein_256_224

Skein-256-224 hash. You probably want to use `encode` to obtain a 224-bit (28-byte) `ByteString`. May be used as a drop-in replacement for SHA-224.

Instances

Eq Skein_256_224 |
Ord Skein_256_224 |
Serialize Skein_256_224 |
Hash Skein_256_224_Ctx Skein_256_224 |

data Skein_256_224_Ctx

Context of the Skein-256-224 hash function.

Instances

SkeinMAC Skein_256_224_Ctx |
Hash Skein_256_224_Ctx Skein_256_224 |

# Skein-512

## Skein-512-128

data Skein_512_128

Skein-512-128 hash. You probably want to use `encode` to obtain a 128-bit (16-byte) `ByteString`. May be used as a drop-in replacement for MD5.

Instances

Eq Skein_512_128 |
Ord Skein_512_128 |
Serialize Skein_512_128 |
Hash Skein_512_128_Ctx Skein_512_128 |

data Skein_512_128_Ctx

Context of the Skein-512-128 hash function.

Instances

SkeinMAC Skein_512_128_Ctx |
Hash Skein_512_128_Ctx Skein_512_128 |

## Skein-512-160

data Skein_512_160

Skein-512-160 hash. You probably want to use `encode` to obtain a 160-bit (20-byte) `ByteString`. May be used as a drop-in replacement for SHA-1.

Instances

Eq Skein_512_160 |
Ord Skein_512_160 |
Serialize Skein_512_160 |
Hash Skein_512_160_Ctx Skein_512_160 |

data Skein_512_160_Ctx

Context of the Skein-512-160 hash function.

Instances

SkeinMAC Skein_512_160_Ctx |
Hash Skein_512_160_Ctx Skein_512_160 |

## Skein-512-224

data Skein_512_224

Skein-512-224 hash. You probably want to use `encode` to obtain a 224-bit (28-byte) `ByteString`. May be used as a drop-in replacement for SHA-224.

Instances

Eq Skein_512_224 |
Ord Skein_512_224 |
Serialize Skein_512_224 |
Hash Skein_512_224_Ctx Skein_512_224 |

data Skein_512_224_Ctx

Context of the Skein-512-224 hash function.

Instances

SkeinMAC Skein_512_224_Ctx |
Hash Skein_512_224_Ctx Skein_512_224 |

## Skein-512-256

data Skein_512_256

Skein-512-256 hash. You probably want to use `encode` to obtain a 256-bit (32-byte) `ByteString`.

Instances

Eq Skein_512_256 |
Ord Skein_512_256 |
Serialize Skein_512_256 |
Hash Skein_512_256_Ctx Skein_512_256 |

data Skein_512_256_Ctx

Context of the Skein-512-256 hash function.

Instances

SkeinMAC Skein_512_256_Ctx |
Hash Skein_512_256_Ctx Skein_512_256 |

## Skein-512-384

data Skein_512_384

Skein-512-384 hash. You probably want to use `encode` to obtain a 384-bit (48-byte) `ByteString`. May be used as a drop-in replacement for SHA-384.

Instances

Eq Skein_512_384 |
Ord Skein_512_384 |
Serialize Skein_512_384 |
Hash Skein_512_384_Ctx Skein_512_384 |

data Skein_512_384_Ctx

Context of the Skein-512-384 hash function.

Instances

SkeinMAC Skein_512_384_Ctx |
Hash Skein_512_384_Ctx Skein_512_384 |

# Skein-1024

## Skein-1024-384

data Skein_1024_384

Skein-1024-384 hash. You probably want to use `encode` to obtain a 384-bit (48-byte) `ByteString`. May be used as a drop-in replacement for SHA-384.

Instances

Eq Skein_1024_384 |
Ord Skein_1024_384 |
Serialize Skein_1024_384 |
Hash Skein_1024_384_Ctx Skein_1024_384 |

data Skein_1024_384_Ctx

Context of the Skein-1024-384 hash function.

Instances

SkeinMAC Skein_1024_384_Ctx |
Hash Skein_1024_384_Ctx Skein_1024_384 |

## Skein-1024-512

data Skein_1024_512

Skein-1024-512 hash. You probably want to use `encode` to obtain a 512-bit (64-byte) `ByteString`. May be used as a drop-in replacement for SHA-512.

Instances

Eq Skein_1024_512 |
Ord Skein_1024_512 |
Serialize Skein_1024_512 |
Hash Skein_1024_512_Ctx Skein_1024_512 |

data Skein_1024_512_Ctx

Context of the Skein-1024-512 hash function.

Instances

SkeinMAC Skein_1024_512_Ctx |
Hash Skein_1024_512_Ctx Skein_1024_512 |