mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 20:56:18 +08:00
drbg: use hash creator, but it's still NOT goroutine safe
This commit is contained in:
parent
a4d7601bd9
commit
75fde484ba
@ -88,7 +88,7 @@ func NewGmCtrDrbgPrng(entropySource io.Reader, securityStrength int, securityLev
|
||||
}
|
||||
|
||||
// NewHashDrbgPrng create pseudo random number generator base on HASH DRBG
|
||||
func NewHashDrbgPrng(md hash.Hash, entropySource io.Reader, securityStrength int, gm bool, securityLevel SecurityLevel, personalization []byte) (*DrbgPrng, error) {
|
||||
func NewHashDrbgPrng(newHash func() hash.Hash, entropySource io.Reader, securityStrength int, gm bool, securityLevel SecurityLevel, personalization []byte) (*DrbgPrng, error) {
|
||||
prng := new(DrbgPrng)
|
||||
if entropySource != nil {
|
||||
prng.entropySource = entropySource
|
||||
@ -114,7 +114,7 @@ func NewHashDrbgPrng(md hash.Hash, entropySource io.Reader, securityStrength int
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prng.impl, err = NewHashDrbg(md, securityLevel, gm, entropyInput, nonce, personalization)
|
||||
prng.impl, err = NewHashDrbg(newHash, securityLevel, gm, entropyInput, nonce, personalization)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -123,13 +123,13 @@ func NewHashDrbgPrng(md hash.Hash, entropySource io.Reader, securityStrength int
|
||||
}
|
||||
|
||||
// NewNistHashDrbgPrng create pseudo random number generator base on hash DRBG which follows NIST standard
|
||||
func NewNistHashDrbgPrng(md hash.Hash, entropySource io.Reader, securityStrength int, securityLevel SecurityLevel, personalization []byte) (*DrbgPrng, error) {
|
||||
return NewHashDrbgPrng(md, entropySource, securityStrength, false, securityLevel, personalization)
|
||||
func NewNistHashDrbgPrng(newHash func() hash.Hash, entropySource io.Reader, securityStrength int, securityLevel SecurityLevel, personalization []byte) (*DrbgPrng, error) {
|
||||
return NewHashDrbgPrng(newHash, entropySource, securityStrength, false, securityLevel, personalization)
|
||||
}
|
||||
|
||||
// NewGmHashDrbgPrng create pseudo random number generator base on hash DRBG which follows GM/T 0105-2021 standard
|
||||
func NewGmHashDrbgPrng(entropySource io.Reader, securityStrength int, securityLevel SecurityLevel, personalization []byte) (*DrbgPrng, error) {
|
||||
return NewHashDrbgPrng(sm3.New(), entropySource, securityStrength, true, securityLevel, personalization)
|
||||
return NewHashDrbgPrng(sm3.New, entropySource, securityStrength, true, securityLevel, personalization)
|
||||
}
|
||||
|
||||
func (prng *DrbgPrng) getEntropy(entropyInput []byte) error {
|
||||
|
@ -56,7 +56,7 @@ func TestGmHashDrbgPrng(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNistHashDrbgPrng(t *testing.T) {
|
||||
prng, err := NewNistHashDrbgPrng(sha256.New(), nil, 32, SECURITY_LEVEL_TEST, nil)
|
||||
prng, err := NewNistHashDrbgPrng(sha256.New, nil, 32, SECURITY_LEVEL_TEST, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/emmansun/gmsm/sm4"
|
||||
)
|
||||
|
||||
// CtrDrbg CTR DRBG structure, its instance is NOT goroutine safe!!!
|
||||
type CtrDrbg struct {
|
||||
BaseDrbg
|
||||
cipherProvider func(key []byte) (cipher.Block, error)
|
||||
|
@ -12,27 +12,32 @@ import (
|
||||
const HASH_DRBG_SEED_SIZE = 55
|
||||
const HASH_DRBG_MAX_SEED_SIZE = 111
|
||||
|
||||
// HashDrbg hash DRBG structure, its instance is NOT goroutine safe!!!
|
||||
type HashDrbg struct {
|
||||
BaseDrbg
|
||||
md hash.Hash
|
||||
c []byte
|
||||
newHash func() hash.Hash
|
||||
c []byte
|
||||
hashSize int
|
||||
}
|
||||
|
||||
// NewHashDrbg create one hash DRBG instance
|
||||
func NewHashDrbg(md hash.Hash, securityLevel SecurityLevel, gm bool, entropy, nonce, personalization []byte) (*HashDrbg, error) {
|
||||
func NewHashDrbg(newHash func() hash.Hash, securityLevel SecurityLevel, gm bool, entropy, nonce, personalization []byte) (*HashDrbg, error) {
|
||||
hd := &HashDrbg{}
|
||||
|
||||
hd.gm = gm
|
||||
hd.md = md
|
||||
hd.newHash = newHash
|
||||
hd.setSecurityLevel(securityLevel)
|
||||
|
||||
md := newHash()
|
||||
hd.hashSize = md.Size()
|
||||
|
||||
// here for the min length, we just check <=0 now
|
||||
if len(entropy) == 0 || (hd.gm && len(entropy) < hd.md.Size()) || len(entropy) >= MAX_BYTES {
|
||||
if len(entropy) == 0 || (hd.gm && len(entropy) < hd.hashSize) || len(entropy) >= MAX_BYTES {
|
||||
return nil, errors.New("invalid entropy length")
|
||||
}
|
||||
|
||||
// here for the min length, we just check <=0 now
|
||||
if len(nonce) == 0 || (hd.gm && len(nonce) < hd.md.Size()/2) || len(nonce) >= MAX_BYTES>>1 {
|
||||
if len(nonce) == 0 || (hd.gm && len(nonce) < hd.hashSize/2) || len(nonce) >= MAX_BYTES>>1 {
|
||||
return nil, errors.New("invalid nonce length")
|
||||
}
|
||||
|
||||
@ -40,7 +45,7 @@ func NewHashDrbg(md hash.Hash, securityLevel SecurityLevel, gm bool, entropy, no
|
||||
return nil, errors.New("personalization is too long")
|
||||
}
|
||||
|
||||
if md.Size() <= sm3.Size {
|
||||
if hd.hashSize <= sm3.Size {
|
||||
hd.v = make([]byte, HASH_DRBG_SEED_SIZE)
|
||||
hd.c = make([]byte, HASH_DRBG_SEED_SIZE)
|
||||
hd.seedLength = HASH_DRBG_SEED_SIZE
|
||||
@ -74,19 +79,19 @@ func NewHashDrbg(md hash.Hash, securityLevel SecurityLevel, gm bool, entropy, no
|
||||
}
|
||||
|
||||
// NewNISTHashDrbg return hash DRBG implementation which follows NIST standard
|
||||
func NewNISTHashDrbg(md hash.Hash, securityLevel SecurityLevel, entropy, nonce, personalization []byte) (*HashDrbg, error) {
|
||||
return NewHashDrbg(md, securityLevel, false, entropy, nonce, personalization)
|
||||
func NewNISTHashDrbg(newHash func() hash.Hash, securityLevel SecurityLevel, entropy, nonce, personalization []byte) (*HashDrbg, error) {
|
||||
return NewHashDrbg(newHash, securityLevel, false, entropy, nonce, personalization)
|
||||
}
|
||||
|
||||
// NewGMHashDrbg return hash DRBG implementation which follows GM/T 0105-2021 standard
|
||||
func NewGMHashDrbg(securityLevel SecurityLevel, entropy, nonce, personalization []byte) (*HashDrbg, error) {
|
||||
return NewHashDrbg(sm3.New(), securityLevel, true, entropy, nonce, personalization)
|
||||
return NewHashDrbg(sm3.New, securityLevel, true, entropy, nonce, personalization)
|
||||
}
|
||||
|
||||
// Reseed hash DRBG reseed process. GM/T 0105-2021 has a little different with NIST.
|
||||
func (hd *HashDrbg) Reseed(entropy, additional []byte) error {
|
||||
// here for the min length, we just check <=0 now
|
||||
if len(entropy) == 0 || (hd.gm && len(entropy) < hd.md.Size()) || len(entropy) >= MAX_BYTES {
|
||||
if len(entropy) == 0 || (hd.gm && len(entropy) < hd.hashSize) || len(entropy) >= MAX_BYTES {
|
||||
return errors.New("invalid entropy length")
|
||||
}
|
||||
|
||||
@ -133,10 +138,10 @@ func (hd *HashDrbg) addC() {
|
||||
}
|
||||
|
||||
func (hd *HashDrbg) addH() {
|
||||
hd.md.Write([]byte{0x03})
|
||||
hd.md.Write(hd.v)
|
||||
hd.addW(hd.md.Sum(nil))
|
||||
hd.md.Reset()
|
||||
md := hd.newHash()
|
||||
md.Write([]byte{0x03})
|
||||
md.Write(hd.v)
|
||||
hd.addW(md.Sum(nil))
|
||||
}
|
||||
|
||||
func (hd *HashDrbg) addReseedCounter() {
|
||||
@ -147,7 +152,7 @@ func (hd *HashDrbg) addReseedCounter() {
|
||||
|
||||
func (hd *HashDrbg) MaxBytesPerRequest() int {
|
||||
if hd.gm {
|
||||
return hd.md.Size()
|
||||
return hd.hashSize
|
||||
}
|
||||
return MAX_BYTES_PER_GENERATE
|
||||
}
|
||||
@ -158,10 +163,10 @@ func (hd *HashDrbg) Generate(b, additional []byte) error {
|
||||
if hd.NeedReseed() {
|
||||
return ErrReseedRequired
|
||||
}
|
||||
if (hd.gm && len(b) > hd.md.Size()) || (!hd.gm && len(b) > MAX_BYTES_PER_GENERATE) {
|
||||
if (hd.gm && len(b) > hd.hashSize) || (!hd.gm && len(b) > MAX_BYTES_PER_GENERATE) {
|
||||
return errors.New("too many bytes requested")
|
||||
}
|
||||
md := hd.md
|
||||
md := hd.newHash()
|
||||
m := len(b)
|
||||
|
||||
// if len(additional_input) > 0, then
|
||||
@ -200,8 +205,8 @@ func (hd *HashDrbg) Generate(b, additional []byte) error {
|
||||
|
||||
// derive Hash_df
|
||||
func (hd *HashDrbg) derive(seedMaterial []byte, len int) []byte {
|
||||
md := hd.md
|
||||
limit := uint64(len+md.Size()-1) / uint64(md.Size())
|
||||
md := hd.newHash()
|
||||
limit := uint64(len+hd.hashSize-1) / uint64(hd.hashSize)
|
||||
var requireBytes [4]byte
|
||||
binary.BigEndian.PutUint32(requireBytes[:], uint32(len<<3))
|
||||
var ct byte = 1
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
|
||||
var tests = []struct {
|
||||
gm bool
|
||||
md hash.Hash
|
||||
newHash func() hash.Hash
|
||||
entropyInput string
|
||||
nonce string
|
||||
personalizationString string
|
||||
@ -32,7 +32,7 @@ var tests = []struct {
|
||||
}{
|
||||
{
|
||||
false,
|
||||
sha1.New(),
|
||||
sha1.New,
|
||||
"1610b828ccd27de08ceea032a20e9208",
|
||||
"492cf1709242f6b5",
|
||||
"",
|
||||
@ -50,7 +50,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
false,
|
||||
sha1.New(),
|
||||
sha1.New,
|
||||
"d9bab5cedca96f6178d64509a0dfdc5e",
|
||||
"dad8989414450e01",
|
||||
"",
|
||||
@ -68,7 +68,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
false,
|
||||
sha256.New(),
|
||||
sha256.New,
|
||||
"63363377e41e86468deb0ab4a8ed683f6a134e47e014c700454e81e95358a569",
|
||||
"808aa38f2a72a62359915a9f8a04ca68",
|
||||
"",
|
||||
@ -86,7 +86,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
false,
|
||||
sha256.New(),
|
||||
sha256.New,
|
||||
"9cfb7ad03be487a3b42be06e9ae44f283c2b1458cec801da2ae6532fcb56cc4c",
|
||||
"a20765538e8db31295747ec922c13a69",
|
||||
"",
|
||||
@ -104,7 +104,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
false,
|
||||
sha512.New(),
|
||||
sha512.New,
|
||||
"3144e17a10c856129764f58fd8e4231020546996c0bf6cff8e91c24ee09be333",
|
||||
"b16fcb1cf0c010f31feab733588b8e04",
|
||||
"",
|
||||
@ -122,7 +122,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
false,
|
||||
sha512.New(),
|
||||
sha512.New,
|
||||
"c73a7820f0f53e8bbfc3b7b71d994143cf6e98642e9ea6d8df5dccbc43db8720",
|
||||
"20cc9834b588adcb1bbde64f0d2a34cb",
|
||||
"",
|
||||
@ -140,7 +140,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
true,
|
||||
sm3.New(),
|
||||
sm3.New,
|
||||
"63363377e41e86468deb0ab4a8ed683f6a134e47e014c700454e81e95358a569",
|
||||
"808aa38f2a72a62359915a9f8a04ca68",
|
||||
"",
|
||||
@ -158,7 +158,7 @@ var tests = []struct {
|
||||
},
|
||||
{
|
||||
true,
|
||||
sm3.New(),
|
||||
sm3.New,
|
||||
"9cfb7ad03be487a3b42be06e9ae44f283c2b1458cec801da2ae6532fcb56cc4c",
|
||||
"a20765538e8db31295747ec922c13a69",
|
||||
"",
|
||||
@ -183,7 +183,7 @@ func TestHashDRBG(t *testing.T) {
|
||||
personalizationString, _ := hex.DecodeString(test.personalizationString)
|
||||
v0, _ := hex.DecodeString(test.v0)
|
||||
c0, _ := hex.DecodeString(test.c0)
|
||||
hd, err := NewHashDrbg(test.md, SECURITY_LEVEL_ONE, test.gm, entropyInput, nonce, personalizationString)
|
||||
hd, err := NewHashDrbg(test.newHash, SECURITY_LEVEL_ONE, test.gm, entropyInput, nonce, personalizationString)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -232,15 +232,15 @@ func TestHashDRBG(t *testing.T) {
|
||||
|
||||
func TestGmHashDRBG_Validation(t *testing.T) {
|
||||
entropyInput := make([]byte, 64)
|
||||
_, err := NewHashDrbg(sm3.New(), SECURITY_LEVEL_ONE, true, entropyInput[:16], entropyInput[16:24], nil)
|
||||
_, err := NewHashDrbg(sm3.New, SECURITY_LEVEL_ONE, true, entropyInput[:16], entropyInput[16:24], nil)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error here")
|
||||
}
|
||||
_, err = NewHashDrbg(sm3.New(), SECURITY_LEVEL_ONE, true, entropyInput[:32], entropyInput[32:40], nil)
|
||||
_, err = NewHashDrbg(sm3.New, SECURITY_LEVEL_ONE, true, entropyInput[:32], entropyInput[32:40], nil)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error here")
|
||||
}
|
||||
hd, err := NewHashDrbg(sm3.New(), SECURITY_LEVEL_ONE, true, entropyInput[:32], entropyInput[32:48], nil)
|
||||
hd, err := NewHashDrbg(sm3.New, SECURITY_LEVEL_ONE, true, entropyInput[:32], entropyInput[32:48], nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user