package hashrng import ( "encoding/binary" "io" "runtime" "time" "xdx.jelly/xgcl/grand/drng/internal" "xdx.jelly/xgcl/sm" "xdx.jelly/xgcl/sm/sm3" ) var _ = sm3.BlockSize // import sm3 // 内部状态 type internalState struct { v []byte c []byte reseedCounter uint32 lastReseedTime time.Time } // zeromize 对内部状态置0 func (s *internalState) zeromize() { for i := 0; i < len(s.v); i++ { s.v[i] = 0 } for i := 0; i < len(s.c); i++ { s.c[i] = 0 } s.reseedCounter = 0 } type HashDrng struct { // mu sync.Mutex config internal.DrngConfig hash sm.Hash df func(input []byte, n int) []byte state internalState personalizationString []byte //个性化字符串,来自应用的比特串 } // Read implements internal.internal. // func (hd *HashDrng) Read(p []byte) (n int, err error) { // return len(p), hd.Generate(p, nil) // } // var SM3_df = newDF(sm.SM3) // newDF 返回一个使用hash作为杂凑的df函数 // 例:SM3_df = newDF(sm.SM3) func newDF(hash sm.Hash) func(input []byte, n int) []byte { h := hash.New() return func(input []byte, n int) []byte { out := make([]byte, 0, n+hash.Size()-1) len := (n + hash.Size() - 1) / hash.Size() counter := uint32(1) buf := make([]byte, 8) for i := 0; i < len; i++ { binary.BigEndian.PutUint32(buf, counter) binary.BigEndian.PutUint32(buf[4:], uint32(n<<3)) h.Write(buf) h.Write(input) out = h.Sum(out) h.Reset() counter += 1 } return out[:n] } } // func New(hash sm.Hash, config *internal.DrngConfig) (internal.Drng, error) { // raw, _ := NewHashDrng(hash, config) // pool := entropy.GetEntropyPool() // d, err := raw.Instantiate([]byte(internal.PERSONALIZATIONSTRING), internal.Nonce(), pool) // if err != nil { // return nil, err // } // return &drng.DrngUtil{ // Drng: d, // ReseedSource: pool, // }, nil // } func NewHashDrng(hash sm.Hash, config *internal.DrngConfig) (internal.RawDrng, error) { hd := &HashDrng{ hash: hash, df: newDF(hash), config: *config, } // HashDrng 析构时对内部状态置0 runtime.SetFinalizer(hd, func(hd *HashDrng) { hd.state.zeromize() }) return hd, nil } func (hd *HashDrng) OutLen() int { return hd.config.Outlen } func (hd *HashDrng) Config() *internal.DrngConfig { return &hd.config } // Instantiate 初始化HashDrng func (hd *HashDrng) Instantiate(personalizationString []byte, nonce []byte, entropySource io.Reader) (internal.Drng, error) { // hd.mu.Lock() // defer hd.mu.Unlock() cfg := hd.config hd.personalizationString = personalizationString seedMaterial := make([]byte, 2*cfg.MinEntropyInputLength, int(2*cfg.MinEntropyInputLength)+len(nonce)+len(personalizationString)) var m, n int var err error var errCount int for n < int(cfg.MinEntropyInputLength) { m, err = entropySource.Read(seedMaterial[n:]) n += m if err != nil { errCount++ } if errCount > 3 { return hd, err } } seedMaterial = append(seedMaterial, nonce...) seedMaterial = append(seedMaterial, personalizationString...) seed := hd.df(seedMaterial, cfg.Seedlen) //初始化内部状态变量 hd.state.v = append(hd.state.v[:0], seed...) hd.state.c = append(hd.state.c[:0], hd.df(append([]byte{0}, seed...), cfg.Seedlen)...) hd.state.reseedCounter = 1 hd.state.lastReseedTime = time.Now() // seed和seedMaterial置0 for i := 0; i < len(seed); i++ { seed[i] = 0 } for i := 0; i < len(seedMaterial); i++ { seedMaterial[i] = 0 } return hd, nil } // Reseed 更新HashDrng的内部状态 func (hd *HashDrng) Reseed(entropyInput, additionalInput []byte) { // hd.mu.Lock() // defer hd.mu.Unlock() seedMaterial := make([]byte, 1, 1+len(entropyInput)+len(hd.state.v)+len(additionalInput)) seedMaterial[0] = 1 seedMaterial = append(seedMaterial, entropyInput...) seedMaterial = append(seedMaterial, hd.state.v...) seedMaterial = append(seedMaterial, additionalInput...) seed := hd.df(seedMaterial, hd.config.Seedlen) copy(hd.state.v, seed) hd.state.c = append(hd.state.c[:0], hd.df(append([]byte{0}, seed...), hd.config.Seedlen)...) hd.state.reseedCounter = 1 hd.state.lastReseedTime = time.Now() // seed和seedMaterial置0 for i := 0; i < len(seed); i++ { seed[i] = 0 } for i := 0; i < len(seedMaterial); i++ { seedMaterial[i] = 0 } } // Generate 输出函数 func (hd *HashDrng) Generate(b []byte, additionalInput []byte) error { // hd.mu.Lock() // defer hd.mu.Unlock() if len(b) > hd.config.Outlen { return internal.ErrReturnedBitsTooLong } // 需要重播种 if hd.state.reseedCounter > uint32(hd.config.ReseedIntervalInCounter) || time.Since(hd.state.lastReseedTime) > hd.config.ReseedIntervalInTime { return internal.ErrNeedReseed } hash := hd.hash.New() if len(additionalInput) > 0 { hash.Write([]byte{2}) hash.Write(hd.state.v) hash.Write(additionalInput) W := hash.Sum(nil) internal.AddModBytes(hd.state.v, W) } hash.Reset() _, _ = hash.Write(hd.state.v) temp := hash.Sum(nil) copy(b, temp) hash.Reset() hash.Write([]byte{3}) hash.Write(hd.state.v) H := hash.Sum(nil) reseedCounterBytes := make([]byte, 4) binary.BigEndian.PutUint32(reseedCounterBytes, hd.state.reseedCounter) internal.AddModBytes(hd.state.v, H[:]) internal.AddModBytes(hd.state.v, hd.state.c) internal.AddModBytes(hd.state.v, reseedCounterBytes) hd.state.reseedCounter++ return nil }