1
0
mirror of https://github.com/golang/go synced 2024-11-25 09:07:58 -07:00

crypto/rand: use runtime.getRandomData on js/wasm

This mechanism ultimately calls the same JavaScript method, but being
consistent between runtime and crypto/rand lets us reuse test coverage
across them. Also, no allocations.

Cq-Include-Trybots: luci.golang.try:gotip-js-wasm
Change-Id: I035da1ed603fbcdad61945f2b57f3fb527a959fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/608396
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
This commit is contained in:
Filippo Valsorda 2024-08-25 14:00:18 +02:00
parent dd6b3821ca
commit ef14ba3e68
2 changed files with 14 additions and 34 deletions

View File

@ -4,41 +4,24 @@
package rand
import "syscall/js"
// The maximum buffer size for crypto.getRandomValues is 65536 bytes.
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions
const maxGetRandomRead = 64 << 10
// read implements a pseudorandom generator
// using JavaScript crypto.getRandomValues method.
//go:wasmimport gojs runtime.getRandomData
//go:noescape
func getRandomValues(r []byte)
// read calls the JavaScript Crypto.getRandomValues() method.
// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues.
var read = batched(getRandom, maxGetRandomRead)
var jsCrypto = js.Global().Get("crypto")
var uint8Array = js.Global().Get("Uint8Array")
func getRandom(b []byte) error {
a := uint8Array.New(len(b))
jsCrypto.Call("getRandomValues", a)
js.CopyBytesToGo(b, a)
func read(b []byte) error {
for len(b) > 0 {
size := len(b)
if size > maxGetRandomRead {
size = maxGetRandomRead
}
getRandomValues(b[:size])
b = b[size:]
}
return nil
}
// batched returns a function that calls f to populate a []byte by chunking it
// into subslices of, at most, readMax bytes.
func batched(f func([]byte) error, readMax int) func([]byte) error {
return func(out []byte) error {
for len(out) > 0 {
read := len(out)
if read > readMax {
read = readMax
}
if err := f(out[:read]); err != nil {
return err
}
out = out[read:]
}
return nil
}
}

View File

@ -160,9 +160,6 @@ func TestAllocations(t *testing.T) {
// Might be fixable with https://go.dev/issue/56378.
t.Skip("boringcrypto allocates")
}
if runtime.GOOS == "js" {
t.Skip("syscall/js allocates")
}
if race.Enabled {
t.Skip("urandomRead allocates under -race")
}