mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
[utils]: added subpacakges and updated Write/Read API
This commit is contained in:
58
utils/sampling/prng.go
Normal file
58
utils/sampling/prng.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package sampling
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
// PRNG is an interface for secure (keyed) deterministic generation of random bytes
|
||||
type PRNG interface {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
// KeyedPRNG is a structure storing the parameters used to securely and deterministically generate shared
|
||||
// sequences of random bytes among different parties using the hash function blake2b. Backward sequence
|
||||
// security (given the digest i, compute the digest i-1) is ensured by default, however forward sequence
|
||||
// security (given the digest i, compute the digest i+1) is only ensured if the KeyedPRNG is keyed.
|
||||
type KeyedPRNG struct {
|
||||
key []byte
|
||||
xof blake2b.XOF
|
||||
}
|
||||
|
||||
// NewKeyedPRNG creates a new instance of KeyedPRNG.
|
||||
// Accepts an optional key, else set key=nil which is treated as key=[]byte{}
|
||||
// WARNING: A PRNG INITIALISED WITH key=nil IS INSECURE!
|
||||
func NewKeyedPRNG(key []byte) (*KeyedPRNG, error) {
|
||||
var err error
|
||||
prng := new(KeyedPRNG)
|
||||
prng.xof, err = blake2b.NewXOF(blake2b.OutputLengthUnknown, key)
|
||||
return prng, err
|
||||
}
|
||||
|
||||
// NewPRNG creates KeyedPRNG keyed from rand.Read for instances were no key should be provided by the user
|
||||
func NewPRNG() (*KeyedPRNG, error) {
|
||||
var err error
|
||||
prng := new(KeyedPRNG)
|
||||
key := make([]byte, 64)
|
||||
if _, err := rand.Read(key); err != nil {
|
||||
panic("crypto rand error")
|
||||
}
|
||||
prng.key = key
|
||||
prng.xof, err = blake2b.NewXOF(blake2b.OutputLengthUnknown, key)
|
||||
return prng, err
|
||||
}
|
||||
|
||||
// Read reads bytes from the KeyedPRNG on sum.
|
||||
func (prng *KeyedPRNG) Read(sum []byte) (n int, err error) {
|
||||
if n, err = prng.xof.Read(sum); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Reset resets the PRNG to its initial state.
|
||||
func (prng *KeyedPRNG) Reset() {
|
||||
prng.xof.Reset()
|
||||
}
|
||||
35
utils/sampling/prng_test.go
Normal file
35
utils/sampling/prng_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package sampling_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/sampling"
|
||||
)
|
||||
|
||||
func Test_PRNG(t *testing.T) {
|
||||
|
||||
t.Run("PRNG", func(t *testing.T) {
|
||||
|
||||
key := []byte{0x49, 0x0a, 0x42, 0x3d, 0x97, 0x9d, 0xc1, 0x07, 0xa1, 0xd7, 0xe9, 0x7b, 0x3b, 0xce, 0xa1, 0xdb,
|
||||
0x42, 0xf3, 0xa6, 0xd5, 0x75, 0xd2, 0x0c, 0x92, 0xb7, 0x35, 0xce, 0x0c, 0xee, 0x09, 0x7c, 0x98}
|
||||
|
||||
Ha, _ := sampling.NewKeyedPRNG(key)
|
||||
Hb, _ := sampling.NewKeyedPRNG(key)
|
||||
|
||||
sum0 := make([]byte, 512)
|
||||
sum1 := make([]byte, 512)
|
||||
|
||||
for i := 0; i < 128; i++ {
|
||||
Hb.Read(sum1)
|
||||
}
|
||||
|
||||
Hb.Reset()
|
||||
|
||||
Ha.Read(sum0)
|
||||
Hb.Read(sum1)
|
||||
|
||||
require.Equal(t, sum0, sum1)
|
||||
})
|
||||
|
||||
}
|
||||
40
utils/sampling/sampling.go
Normal file
40
utils/sampling/sampling.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package sampling
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// RandUint64 return a random value between 0 and 0xFFFFFFFFFFFFFFFF.
|
||||
func RandUint64() uint64 {
|
||||
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return binary.LittleEndian.Uint64(b)
|
||||
}
|
||||
|
||||
// RandFloat64 returns a random float between min and max.
|
||||
func RandFloat64(min, max float64) float64 {
|
||||
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f := float64(binary.LittleEndian.Uint64(b)) / 1.8446744073709552e+19
|
||||
return min + f*(max-min)
|
||||
}
|
||||
|
||||
// RandComplex128 returns a random complex with the real and imaginary part between min and max.
|
||||
func RandComplex128(min, max float64) complex128 {
|
||||
return complex(RandFloat64(min, max), RandFloat64(min, max))
|
||||
}
|
||||
|
||||
// RandInt generates a random Int in [0, max-1].
|
||||
func RandInt(max *big.Int) (n *big.Int) {
|
||||
var err error
|
||||
if n, err = rand.Int(rand.Reader, max); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user