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