Example #1
0
// Reseed uses the current generator state and the given seed value to
// update the generator state.  Care is taken to make sure that
// knowledge of the new state after a reseed does not allow to
// reconstruct previous output values of the generator.
//
// This is like the ReseedInt64() method, but the seed is given as a
// byte slice instead of as an int64.
func (gen *Generator) Reseed(seed []byte) {
	hash := sha256d.New()
	hash.Write(gen.key)
	hash.Write(seed)
	gen.setKey(hash.Sum(nil))
	gen.inc()
	trace.T("fortuna/generator", trace.PrioVerbose, "seed updated")
}
Example #2
0
// NewAccumulator allocates a new instance of the Fortuna random
// number generator.  The argument 'newCipher' allows to choose a
// block cipher like Serpent or Twofish instead of the default AES.
// NewAccumulator(aes.NewCipher, seedFileName) is the same as
// NewRNG(seedFileName).  See the documentation for NewRNG() for more
// information.
func NewAccumulator(newCipher NewCipher, seedFileName string) (*Accumulator, error) {
	acc := &Accumulator{
		gen: NewGenerator(newCipher),
	}
	for i := 0; i < len(acc.pool); i++ {
		acc.pool[i] = sha256d.New()
	}
	acc.stopSources = make(chan bool)

	if seedFileName != "" {
		seedFile, err := os.OpenFile(seedFileName,
			os.O_RDWR|os.O_CREATE|os.O_SYNC, os.FileMode(0600))
		if err != nil {
			return nil, err
		}
		acc.seedFile = seedFile

		err = flock(acc.seedFile)
		if err != nil {
			acc.seedFile.Close()
			return nil, err
		}

		// The initial seed of the generator depends on the current
		// time.  This (partially) protects us against old seed files
		// being restored from backups, etc.
		err = acc.updateSeedFile()
		if err != nil {
			acc.seedFile.Close()
			return nil, err
		}

		quit := make(chan bool)
		acc.stopAutoSave = quit
		go func() {
			ticker := time.Tick(seedFileUpdateInterval)
			for {
				select {
				case <-quit:
					return
				case <-ticker:
					acc.writeSeedFile()
				}
			}
		}()
	}

	return acc, nil
}