mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 03:07:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			100 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//
 | 
						|
// Copyright Coinbase, Inc. All Rights Reserved.
 | 
						|
//
 | 
						|
// SPDX-License-Identifier: Apache-2.0
 | 
						|
//
 | 
						|
 | 
						|
package common
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/hmac"
 | 
						|
	"hash"
 | 
						|
)
 | 
						|
 | 
						|
// HmacDrbg is an HMAC deterministic random bit generator
 | 
						|
// that can use any hash function. Handles reseeding
 | 
						|
// automatically
 | 
						|
type HmacDrbg struct {
 | 
						|
	k, v   []byte
 | 
						|
	count  int
 | 
						|
	hasher func() hash.Hash
 | 
						|
}
 | 
						|
 | 
						|
func NewHmacDrbg(entropy, nonce, pers []byte, hasher func() hash.Hash) *HmacDrbg {
 | 
						|
	drbg := new(HmacDrbg)
 | 
						|
	h := hasher()
 | 
						|
	drbg.k = make([]byte, h.Size())
 | 
						|
	drbg.v = make([]byte, h.Size())
 | 
						|
	drbg.count = 0
 | 
						|
	drbg.hasher = hasher
 | 
						|
 | 
						|
	for i := range drbg.v {
 | 
						|
		drbg.v[i] = 1
 | 
						|
	}
 | 
						|
 | 
						|
	drbg.update([][]byte{entropy, nonce, pers})
 | 
						|
	drbg.count += 1
 | 
						|
	return drbg
 | 
						|
}
 | 
						|
 | 
						|
func (drbg *HmacDrbg) Read(dst []byte) (n int, err error) {
 | 
						|
	toRead := len(dst)
 | 
						|
	if toRead == 0 {
 | 
						|
		return 0, nil
 | 
						|
	}
 | 
						|
	i := 0
 | 
						|
	for i < toRead {
 | 
						|
		vmac := drbg.getHmac()
 | 
						|
		_, _ = vmac.Write(drbg.v)
 | 
						|
		drbg.v = vmac.Sum(nil)
 | 
						|
 | 
						|
		for j, b := range drbg.v {
 | 
						|
			dst[i+j] = b
 | 
						|
		}
 | 
						|
		i += len(drbg.v)
 | 
						|
	}
 | 
						|
	drbg.update(nil)
 | 
						|
	drbg.count++
 | 
						|
	return i, nil
 | 
						|
}
 | 
						|
 | 
						|
func (drbg *HmacDrbg) Reseed(entropy []byte) {
 | 
						|
	drbg.update([][]byte{entropy})
 | 
						|
}
 | 
						|
 | 
						|
func (drbg *HmacDrbg) getHmac() hash.Hash {
 | 
						|
	return hmac.New(drbg.hasher, drbg.k)
 | 
						|
}
 | 
						|
 | 
						|
func (drbg *HmacDrbg) update(seeds [][]byte) {
 | 
						|
	kmac := drbg.getHmac()
 | 
						|
	_, _ = kmac.Write(drbg.v)
 | 
						|
	_, _ = kmac.Write([]byte{0})
 | 
						|
	if len(seeds) > 0 {
 | 
						|
		for _, seed := range seeds {
 | 
						|
			_, _ = kmac.Write(seed)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	drbg.k = kmac.Sum(nil)
 | 
						|
 | 
						|
	vmac := drbg.getHmac()
 | 
						|
	_, _ = vmac.Write(drbg.v)
 | 
						|
	drbg.v = vmac.Sum(nil)
 | 
						|
 | 
						|
	if len(seeds) == 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	kmac = drbg.getHmac()
 | 
						|
	_, _ = kmac.Write(drbg.v)
 | 
						|
	_, _ = kmac.Write([]byte{1})
 | 
						|
	for _, seed := range seeds {
 | 
						|
		_, _ = kmac.Write(seed)
 | 
						|
	}
 | 
						|
	drbg.k = kmac.Sum(nil)
 | 
						|
 | 
						|
	vmac = drbg.getHmac()
 | 
						|
	_, _ = vmac.Write(drbg.v)
 | 
						|
	drbg.v = vmac.Sum(nil)
 | 
						|
}
 |