crypto/rand: switch to arc4random_buf

This doesn't have the potential blocking issue of the getentropy call
(which calls WASI random_get when using wasi-libc) and should therefore
be a lot faster.

For context, this is what the random_get documentation says:

> Write high-quality random data into a buffer. This function blocks
> when the implementation is unable to immediately provide sufficient
> high-quality random data. This function may execute slowly, so when
> large mounts of random data are required, it's advisable to use this
> function to seed a pseudo-random number generator, rather than to
> provide the random data directly.
Этот коммит содержится в:
Ayke van Laethem 2021-08-06 21:00:51 +02:00 коммит произвёл Ron Evans
родитель 4f7b23c2b7
коммит d05103668f
2 изменённых файлов: 30 добавлений и 38 удалений

30
src/crypto/rand/rand_arc4random.go Обычный файл
Просмотреть файл

@ -0,0 +1,30 @@
// +build darwin freebsd tinygo.wasm
// This implementation of crypto/rand uses the arc4random_buf function
// (available on both MacOS and WASI) to generate random numbers.
//
// Note: arc4random_buf (unlike what the name suggets) does not use the insecure
// RC4 cipher. Instead, it uses a high-quality cipher, varying by the libc
// implementation.
package rand
import "unsafe"
func init() {
Reader = &reader{}
}
type reader struct {
}
func (r *reader) Read(b []byte) (n int, err error) {
if len(b) != 0 {
libc_arc4random_buf(unsafe.Pointer(&b[0]), uint(len(b)))
}
return len(b), nil
}
// void arc4random_buf(void *buf, size_t buflen);
//export arc4random_buf
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)

Просмотреть файл

@ -1,38 +0,0 @@
// +build darwin freebsd tinygo.wasm
// This implementation of crypto/rand uses the getentropy system call (available
// on both MacOS and WASI) to generate random numbers.
package rand
import (
"errors"
"unsafe"
)
var errReadFailed = errors.New("rand: could not read random bytes")
func init() {
Reader = &reader{}
}
type reader struct {
}
func (r *reader) Read(b []byte) (n int, err error) {
if len(b) != 0 {
if len(b) > 256 {
b = b[:256]
}
result := libc_getentropy(unsafe.Pointer(&b[0]), len(b))
if result < 0 {
// Maybe we should return a syscall.Errno here?
return 0, errReadFailed
}
}
return len(b), nil
}
// int getentropy(void *buf, size_t buflen);
//export getentropy
func libc_getentropy(buf unsafe.Pointer, buflen int) int