// 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") }
// 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 }