tunafish

package
v0.0.0-...-8d9eed9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 15, 2021 License: ISC Imports: 8 Imported by: 0

README

fishtuna: Fortuna implementation using Twofish and Keccak

The core component of this package is the Fortuna type. A new Fortuna
PRNG should be set up with one of two functions:

* New to initialise a new PRNG with an empty state
* FromSeed to initialise a new PRNG from a seed file

If possible, FromSeed should be used to give the PRNG some internal
state. The Fortuna designers recommend that the seed file be written
every ten minutes and on shutdown; the `AutoUpdate` function will
start a goroutine in the background that will check for a shutdown
event and write out a seed file. It also updates the seed file every
ten minutes.

Random data can be read from the PRNG using the Read method; the
PRNG provides an io.Reader interface. Adding entropy is done via
sources; these should call AddRandomEvent, noting the conditions
explained in the function documentation.  Each source should have
an identifying byte; perhaps 0x01 to indicate OS RNG facilities,
0x02 to indicate a HWRNG, 0x03 to denote keypress events, etc.
Sources are also expected to distribute events over the entire set
of entropy pools used by the PRNG; this can be done by using the
`i` parameter of AddRandomEvent. The current number of pools is
provided in the PoolSize constant; the source can iterate over this
count. An event has a maximum size, set in the MaxEventSize constant.
A source may choose to accept larger events and distribute them
over multiple pools. The SourceWriter takes this approach.

The PRNG will not be able to provide random data until it has
acquired enough entropy. Based on recommendations in the book and
in real world use, the PRNG will need to collect roughly 1040 bytes
of entropy if it is operating correctly. This is because the maximum
event size, which is currently 32 bytes (a constraint imposed by
the Fortuna designers), is less than the current minimum pool size
(which applies to the first pool). Due to the design requirement
of distributing events over the entire set of pools, this means
that all of the pools (there are 32 pools in a Fortuna PRNG) should
be filled, with an additional 16 bytes in the first pool. That is,

   Initial collection, assuming maximum event size:
   32 bytes maximum event size * 32 pools = 1024 bytes

   This can be circumvented by not distributing over the pools, but
   this violates a design parameter of the PRNG and you should not
   expect it to maintain its integrity at that point.

   The first pool now has 32 bytes, and a minimum of 48 bytes in
   this pool is required for reading random data. Therefore, the
   first pool needs to collect another
   48 bytes - 32 bytes - 16 bytes

   This brings our total to 1040 bytes as an approximation to bring
   the PRNG online.

If events aren't distrbuted evenly, such as the case where event A
might only provide 4 bytes of entropy, while event B provides 8
bytes of entropy in a system that iterates over pools on each event
(i.e. A goes to pool 2, B goes to pool 3, etc...), the number of
bytes required might be less or slightly more. Note that a seeded
PRNG is ready immediately.

Documentation

Overview

package tunafish implements the Fortuna PRNG designed by Niels Ferguson, Bruce Schneier, and Yadayoshi Kohno. The PRNG is described in the book _Cryptography Engineering_, by the same authors (see pages 142-160). This implementation uses Twofish-256 and as the underlying PRF and Keccak-256 as the underlying PRG.

The Tunafish type provided by this package contains the actual PRNG; clients should use one of the provided sources (or write their own) in order to add entropy to the PRNG.

The book describes an alternative implementation in which a separate accumulator thread performs the hashing; this implementation takes the standard approach.

The documentation for AddRandomEvent contains notes for writing new sources of random events to feed the PRNG.

The book also recommends that the PRNG's seed file be updated regularly; at the very least, at shutdown with an update every ten minutes recommended.

Index

Constants

View Source
const MaxEventSize = 32

MaxEventSize is the limit to the amount of data that can be sent in an event.

View Source
const MaxRead int = 1048576
View Source
const PoolSize = 32

PoolSize contains the number of pools used by the PRNG.

View Source
const SeedFileLength = 64

SeedFileLength is the number of bytes that should be present in the seed file.

Variables

View Source
var (
	MinPoolSize int64 = 48
	ReseedDelay       = 100 * time.Millisecond
)

MinPoolSize stores the number of bytes that will trigger a reseed. The ReseedDelay prevents reseed events from occuring too quickly.

View Source
var (
	ErrNotSeeded      = errors.New("tunafish: PRNG not seeded yet")
	ErrInvalidEvent   = errors.New("tunafish: invalid random event")
	ErrInvalidSeed    = errors.New("tunafish: invalid seed")
	ErrNotInitialised = errors.New("fortuna: PRNG not initialised")
)
View Source
var ErrReadTooLarge = errors.New("tunafish: can't provide requested number of bytes")

Functions

This section is empty.

Types

type Generator

type Generator struct {
	// contains filtered or unexported fields
}

Generator represents the underlying PRG used by the Fortuna PRNG.

func NewGenerator

func NewGenerator() *Generator

New initialises a new Fortuna generator context. This is required to properly initialise a new generator instance.

func (*Generator) Read

func (g *Generator) Read(p []byte) (int, error)

Read presents the generator as an io.Reader, and is used to read random data from the generator.

func (*Generator) Reseed

func (g *Generator) Reseed(s string)

Reseed reseeds the generator with the given arbitrary input.

func (*Generator) Write

func (g *Generator) Write(bs []byte) (int, error)

Write performs the same operation as Reseed, but allows the generator to be used as an io.Writer.

type SourceChannel

type SourceChannel struct {
	In  chan []byte // In receives incoming random events.
	Out chan error  // Out sends outgoing errors.
	// contains filtered or unexported fields
}

SourceChannel provides an interface to a PRNG that reads random events from a channel and adds them to the PRNG for entropy. The source number s should be used by the application to identify this particular source.

func NewSourceChannel

func NewSourceChannel(rng *Tunafish, source byte) *SourceChannel

NewSourceChannel initialises a new channel source. This is required to properly initialise one. The source parameter should contain the source number. The rng must already be initialised, and the channel source must be started before it can be used.

func (*SourceChannel) Start

func (cs *SourceChannel) Start(buf int)

Start the channel source, setting up the channel sender and receiver.

func (*SourceChannel) Stop

func (cs *SourceChannel) Stop()

Stop halts the channel source, closing the channels.

type SourceWriter

type SourceWriter struct {
	// contains filtered or unexported fields
}

SourceWriter provides an io.Writer source for adding events to the PRNG.

func NewSourceWriter

func NewSourceWriter(rng *Tunafish, source byte) *SourceWriter

NewSourceWriter intialises a new io.Writer source. This is required to properly intialise the source. The PRNG provided must already be initialised; the source parameter is used to identify the source to the host system.

func (*SourceWriter) Write

func (sw *SourceWriter) Write(p []byte) (int, error)

Write adds the byte slice as entropy to the pools in the PRNG.

type Tunafish

type Tunafish struct {
	// contains filtered or unexported fields
}

func FromSeed

func FromSeed(filename string) (*Tunafish, error)

FromSeed creates a new PRNG instance from the seed file. This can be used to start an RNG on start up.

func New

func New() *Tunafish

New sets up a new Fortuna PRNG; it is required for ensuring that the PRNG is properly initialised.

func (*Tunafish) AddRandomEvent

func (rng *Tunafish) AddRandomEvent(s byte, i int, e []byte) error

AddRandomEvent should be called by sources to add random events to the PRNG; it takes a source identifier, a pool number, and a random event. Sources should cycle through pools, evenly distributing events over the entire set of pools; the Fortuna designers specify that this should be done "in a round-robin fashion." The choice of a source identifier is up to the host application.

func (*Tunafish) AutoUpdate

func (rng *Tunafish) AutoUpdate(filename string, shutdown chan interface{}, fsError chan error)

AutoUpdate runs in the background, updating the PRNG's seed file every ten minutes. The shutdown channel should be closed when the PRNG is to shut down; it will automatically shutdown the PRNG and prevent any state changes. The fsError channel should be used to report errors (typically file system errors). This should never be closed by any other other means.

func (*Tunafish) Initialised

func (rng *Tunafish) Initialised() bool

Initialised returns true if the rng is initialised.

func (*Tunafish) Read

func (rng *Tunafish) Read(p []byte) (int, error)

func (*Tunafish) ReadSeed

func (rng *Tunafish) ReadSeed(p []byte) error

ReadSeed reseeds the PRNG with a seed that is expected to have been read from a seed file.

func (*Tunafish) Seed

func (rng *Tunafish) Seed() ([]byte, error)

Seed dumps a byte slice containing a seed that may be used to restore the PRNG's state.

func (*Tunafish) UpdateSeed

func (rng *Tunafish) UpdateSeed(filename string) error

UpdateSeed reads a seed from a file and updates the seed file with new random data.

func (*Tunafish) WriteSeed

func (rng *Tunafish) WriteSeed(filename string) error

WriteSeed writes a seed to a file; this should be used for restoring the PRNG state later.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL