go-peer/pkg/crypto/random/random.go
2025-04-30 22:39:03 +07:00

73 lines
1.5 KiB
Go

package random
import (
"crypto/rand"
"strings"
"github.com/number571/go-peer/pkg/encoding"
)
const (
charListSize = (1 << 6) // 2^n is a important condition
charList = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-`
)
var (
_ IRandom = &sRandom{}
)
type sRandom struct {
}
func NewRandom() IRandom {
return &sRandom{}
}
// Generates a cryptographically strong pseudo-random bytes.
func (p *sRandom) GetBytes(n uint64) []byte {
slice := make([]byte, n)
if _, err := rand.Read(slice); err != nil {
panic(err) // 'return nil' is insecure
}
return slice
}
// Generates a cryptographically strong pseudo-random string.
/*
// 1:2
raw_byte = 2^8 (1 byte)
hex_byte = 2^4 + 2^4 (2 bytes)
// 3:4
raw_byte = 2^8 + 2^8 + 2^8 (3 bytes)
cur_byte = 2^6 + 2^6 + 2^6 + 2^6 (4 bytes)
// result
security[p=128] = random(16) raw_bytes
security[p=128] = random(32) hex_byte
security[p=128] = random(21.(3)) cur_byte
*/
func (p *sRandom) GetString(n uint64) string {
result := strings.Builder{}
result.Grow(int(n)) //nolint:gosec
randBytes := p.GetBytes(n)
for _, b := range randBytes {
result.WriteByte(charList[b%charListSize])
}
return result.String()
}
// Generate cryptographically strong pseudo-random uint64 number.
func (p *sRandom) GetUint64() uint64 {
res := [encoding.CSizeUint64]byte{}
copy(res[:], p.GetBytes(encoding.CSizeUint64))
return encoding.BytesToUint64(res)
}
// Generate cryptographically strong pseudo-random bool value.
func (p *sRandom) GetBool() bool {
return p.GetBytes(1)[0]%2 == 0
}