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:
parent
dd6b3821ca
commit
ef14ba3e68
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user