// Reader is a global, shared instance of a cryptographically
// secure random number generator.
//
-// On Linux, FreeBSD, Dragonfly, NetBSD and Solaris, Reader uses getrandom(2) if
-// available, /dev/urandom otherwise.
-// On OpenBSD and macOS, Reader uses getentropy(2).
-// On other Unix-like systems, Reader reads from /dev/urandom.
-// On Windows systems, Reader uses the ProcessPrng API.
-// On JS/Wasm, Reader uses the Web Crypto API.
-// On WASIP1/Wasm, Reader uses random_get from wasi_snapshot_preview1.
+// - On Linux, FreeBSD, Dragonfly, and Solaris, Reader uses getrandom(2)
+// if available, and /dev/urandom otherwise.
+// - On macOS and iOS, Reader uses arc4random_buf(3).
+// - On OpenBSD and NetBSD, Reader uses getentropy(2).
+// - On other Unix-like systems, Reader reads from /dev/urandom.
+// - On Windows, Reader uses the ProcessPrng API.
+// - On js/wasm, Reader uses the Web Crypto API.
+// - On wasip1/wasm, Reader uses random_get from wasi_snapshot_preview1.
var Reader io.Reader
// Read is a helper function that calls Reader.Read using io.ReadFull.
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import "internal/syscall/unix"
+
+func init() {
+ // arc4random_buf is the recommended application CSPRNG, accepts buffers of
+ // any size, and never returns an error.
+ //
+ // "The subsystem is re-seeded from the kernel random number subsystem on a
+ // regular basis, and also upon fork(2)." - arc4random(3)
+ //
+ // Note that despite its legacy name, it uses a secure CSPRNG (not RC4) in
+ // all supported macOS versions.
+ altGetRandom = func(b []byte) error { unix.ARC4Random(b); return nil }
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (darwin && !ios) || openbsd || netbsd
+//go:build openbsd || netbsd
package rand
import "internal/syscall/unix"
func init() {
- // getentropy(2) returns a maximum of 256 bytes per call
+ // getentropy(2) returns a maximum of 256 bytes per call.
altGetRandom = batched(unix.GetEntropy, 256)
}
t.Fatalf("Read(nil) = %d, %v", n, err)
}
}
+
+func BenchmarkRead(b *testing.B) {
+ b.Run("32", func(b *testing.B) {
+ benchmarkRead(b, 32)
+ })
+ b.Run("4K", func(b *testing.B) {
+ benchmarkRead(b, 4<<10)
+ })
+}
+
+func benchmarkRead(b *testing.B, size int) {
+ b.SetBytes(int64(size))
+ buf := make([]byte, size)
+ for i := 0; i < b.N; i++ {
+ if _, err := Read(buf); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+import (
+ "internal/abi"
+ "unsafe"
+)
+
+//go:cgo_import_dynamic libc_arc4random_buf arc4random_buf "/usr/lib/libSystem.B.dylib"
+
+func libc_arc4random_buf_trampoline()
+
+// ARC4Random calls the macOS arc4random_buf(3) function.
+func ARC4Random(p []byte) {
+ // macOS 11 and 12 abort if length is 0.
+ if len(p) == 0 {
+ return
+ }
+ syscall_syscall(abi.FuncPCABI0(libc_arc4random_buf_trampoline),
+ uintptr(unsafe.Pointer(unsafe.SliceData(p))), uintptr(len(p)), 0)
+}
#include "textflag.h"
+TEXT ·libc_arc4random_buf_trampoline(SB),NOSPLIT,$0-0; JMP libc_arc4random_buf(SB)
TEXT ·libc_getaddrinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_getaddrinfo(SB)
TEXT ·libc_freeaddrinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_freeaddrinfo(SB)
TEXT ·libc_getnameinfo_trampoline(SB),NOSPLIT,$0-0; JMP libc_getnameinfo(SB)
+++ /dev/null
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build darwin && !ios
-
-package unix
-
-import (
- "internal/abi"
- "unsafe"
-)
-
-//go:cgo_import_dynamic libc_getentropy getentropy "/usr/lib/libSystem.B.dylib"
-
-func libc_getentropy_trampoline()
-
-// GetEntropy calls the macOS getentropy system call.
-func GetEntropy(p []byte) error {
- _, _, errno := syscall_syscall(abi.FuncPCABI0(libc_getentropy_trampoline),
- uintptr(unsafe.Pointer(&p[0])),
- uintptr(len(p)),
- 0)
- if errno != 0 {
- return errno
- }
- return nil
-}
+++ /dev/null
-// Copyright 2021 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build darwin && !ios
-
-#include "textflag.h"
-
-TEXT ·libc_getentropy_trampoline(SB),NOSPLIT,$0-0; JMP libc_getentropy(SB)