init: v1.0.0
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
MinEntropyInputLength = 256 >> 3 // 最小熵阈值256比特
|
||||
MaxEntropyInputLength = (1 << 35) >> 3 // 最大熵阈值2^35比特
|
||||
|
||||
)
|
||||
|
||||
// 可能返回的错误
|
||||
var (
|
||||
ErrNeedReseed = errors.New("[drng] - need reseed")
|
||||
ErrReturnedBitsTooLong = errors.New("[drng] - requested number of bits too long")
|
||||
ErrEntropyLength = errors.New("[drng] - entropy length too short or too long")
|
||||
)
|
||||
|
||||
// 安全级别
|
||||
type SecureLevel uint
|
||||
|
||||
const (
|
||||
SecureLevel1 SecureLevel = 1 + iota
|
||||
SecureLevel2
|
||||
)
|
||||
|
||||
type DrngConfig struct {
|
||||
Seedlen int
|
||||
Outlen int
|
||||
ReseedIntervalInTime time.Duration // 重播种时间阈值
|
||||
ReseedIntervalInCounter int // 重播种计数器阈值
|
||||
MinEntropy int64
|
||||
MinEntropyInputLength int64
|
||||
MaxEntropyInputLength int64
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNonceCounter(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 10000; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
for i := 0; i < 10000; i++ {
|
||||
nonceCounter.LoadAndAdd(1)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
assert.Equal(t, nonceCounter.n, uint64(10000)*10000)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// RawDrng 未初始化状态,初始化后返回Drng状态
|
||||
// Note: 状态模式
|
||||
type RawDrng interface {
|
||||
// Instantiate 初始化,personalization_string为可选,返回成功则内部状态初始化完成。
|
||||
Instantiate(personalizationString []byte, nonce []byte, entropySource io.Reader) (Drng, error)
|
||||
}
|
||||
|
||||
// Drng is the low level interface for DRNG.
|
||||
//
|
||||
// For most users, use DrngUtil instead.
|
||||
type Drng interface {
|
||||
// Reseed 重播种,entropyInput为输入熵
|
||||
// additionalInput为来自应用的比特串,可以为nil
|
||||
Reseed(entropyInput, additionalInput []byte)
|
||||
|
||||
// Generate 将输出缓冲区b用随机数填充,additionalInputt为来自应用的比特串,可为nil
|
||||
Generate(b []byte, additionalInput []byte) error
|
||||
|
||||
// 每次调用输出的最大字节数(32)
|
||||
OutLen() int
|
||||
|
||||
Config() *DrngConfig
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"xdx.jelly/xgcl/internal"
|
||||
)
|
||||
|
||||
// var nonceCounter atomic.Int64
|
||||
|
||||
// atomic.Int64 only available in go 1.19, so we make a new one.
|
||||
type atomicUint64 struct {
|
||||
spin internal.SpinLock
|
||||
n uint64
|
||||
}
|
||||
|
||||
var nonceCounter atomicUint64
|
||||
|
||||
func (a *atomicUint64) LoadAndAdd(n uint64) uint64 {
|
||||
a.spin.Lock()
|
||||
defer a.spin.Unlock()
|
||||
v := a.n
|
||||
a.n += n
|
||||
return v
|
||||
}
|
||||
|
||||
// nonce 由时间戳和单调递增的计数器组成
|
||||
func Nonce() []byte {
|
||||
out := make([]byte, 16)
|
||||
binary.BigEndian.PutUint64(out, uint64(time.Now().UnixNano()))
|
||||
binary.BigEndian.PutUint64(out[8:], nonceCounter.LoadAndAdd(1))
|
||||
return out
|
||||
}
|
||||
|
||||
// AddModBytes a = a+b as integer, a,b are bigendian and len(a) >= len(b).
|
||||
func AddModBytes(a, b []byte) {
|
||||
var x uint
|
||||
|
||||
x = 0
|
||||
i := len(a) - 1
|
||||
j := len(b) - 1
|
||||
for j >= 0 {
|
||||
x += uint(a[i]) + uint(b[j])
|
||||
a[i] = byte(x)
|
||||
x = x >> 8
|
||||
j--
|
||||
i--
|
||||
}
|
||||
if x == 0 {
|
||||
return
|
||||
}
|
||||
for i >= 0 {
|
||||
a[i] += 1
|
||||
if a[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func IncBytes(a []byte) {
|
||||
i := len(a) - 1
|
||||
for i >= 0 {
|
||||
a[i]++
|
||||
if a[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user