Generating a random, fixed-length byte array in Go

huangapple go评论83阅读模式
英文:

Generating a random, fixed-length byte array in Go

问题

我有一个长度为4的字节数组。

token := make([]byte, 4)

我需要将每个字节设置为一个随机字节。在效率最高的情况下,我该如何做到这一点?据我所知,math/rand方法没有提供随机字节函数。

也许有一种内置的方法,或者我应该生成一个随机字符串然后将其转换为字节数组?

英文:

I have a byte array, with a fixed length of 4.

token := make([]byte, 4)

I need to set each byte to a random byte. How can I do so, in the most efficient matter? The math/rand methods do not provide a Random Byte function, as far as I am concerned.

Perhaps there is a built-in way, or should I go with generating a random string and converting it to a byte array?

答案1

得分: 66

> rand 包
>
> import "math/rand"
>
> func Read
>
> func Read(p []byte) (n int, err error)
>
> Read 从默认的 Source 生成 len(p) 个随机字节,并将它们写入 p。它总是返回 len(p) 和一个空的错误。
>
> func (*Rand) Read
>
> func (r *Rand) Read(p []byte) (n int, err error)
>
> Read 从 r 生成 len(p) 个随机字节,并将它们写入 p。它总是返回 len(p) 和一个空的错误。

例如,

package main

import (
	"math/rand";
	"fmt";
)

func main() {
	token := make([]byte, 4)
	rand.Read(token)
	fmt.Println(token)
}

输出:

[187 163 35 30]
英文:

> Package rand
>
> import "math/rand"
>
> func Read
>
> func Read(p []byte) (n int, err error)
>
> Read generates len(p) random bytes from the default Source and writes
> them into p. It always returns len(p) and a nil error.
>
> func (*Rand) Read
>
> func (r *Rand) Read(p []byte) (n int, err error)
>
> Read generates len(p) random bytes and writes them into p. It always
> returns len(p) and a nil error.

For example,

package main

import (
	"math/rand"
	"fmt"
)

func main() {
	token := make([]byte, 4)
	rand.Read(token)
	fmt.Println(token)
}

Output:

[187 163 35 30]

答案2

得分: 18

Go 1.6在math/rand包中添加了一个新的函数:

func Read(p []byte) (n int, err error)

该函数将传入的byte切片填充为随机数据。使用rand.Read()可以实现:

token := make([]byte, 4)
if _, err := rand.Read(token); err != nil {
    // 处理错误
}
fmt.Println(token)

rand.Read()有两个返回值:读取的字节数和(可选的)error。这是为了符合通用的io.Reader接口,但是rand.Read()的文档说明(尽管其签名如此)它实际上永远不会返回非nil的错误,所以我们可以省略对错误的检查,简化为:

token := make([]byte, 4)
rand.Read(token)
fmt.Println(token)

在使用math/rand包之前,不要忘记调用rand.Seed()进行正确的初始化,例如:

rand.Seed(time.Now().UnixNano())

注意:在Go 1.6之前,没有math/rand.Read()函数,但是有一个crypto/rand.Read()函数,但是crypto/rand包实现了一个加密安全的伪随机数生成器,所以它比math/rand要慢得多。

英文:

Go 1.6 added a new function to the math/rand package:

func Read(p []byte) (n int, err error)

which fills the passed byte slice with random data. Using this rand.Read():

token := make([]byte, 4)
if _, err := rand.Read(token); err != nil {
    // Handle err
}
fmt.Println(token)

rand.Read() has 2 return values: the number of "read" bytes and an (optional) error. This is to conform with the general io.Reader interface, but the documentation of rand.Read() states that (despite its signature) it will never actually return a non-nil error, so we may omit checking it, which simplifies it to this:

token := make([]byte, 4)
rand.Read(token)
fmt.Println(token)

Don't forget to call rand.Seed() to properly initialize it before you use the math/rand package, e.g.:

rand.Seed(time.Now().UnixNano())

Note: Prior to Go 1.6 there was no math/rand.Read() function, but there was (and still is) a crypto/rand.Read() function, but the crypto/rand package implements a cryptographically secure pseudorandom number generator, so it is much slower than math/rand.

答案3

得分: 16

使用math.Rand意味着您正在使用操作系统提供的系统CSPRNG。这意味着使用/dev/urandom和Windows的CryptGenRandom API。

幸运的是,Go的crypto/rand包将这些实现细节抽象化,以最小化出错的风险。

import (
    "crypto/rand"
    "encoding/base64"
)

// GenerateRandomBytes返回安全生成的随机字节。
// 如果系统的安全随机数生成器无法正常工作,它将返回错误,
// 在这种情况下,调用者不应继续执行。
func GenerateRandomBytes(n int) ([]byte, error) {
    b := make([]byte, n)
    _, err := rand.Read(b)
    // 注意,只有当我们读取了len(b)字节时,err == nil。
    if err != nil {
        return nil, err
    }

    return b, nil
}
英文:

Using math.Rand means that you are using the system CSPRNG that your operating system provides. This means using /dev/urandom/ and Windows’ CryptGenRandom API.
Go’s crypto/rand package, thankfully, abstracts these implementation details away to minimise the risk of getting it wrong.

import(
   "crypto/rand"
   "encoding/base64"
 )

// GenerateRandomBytes returns securely generated random bytes. 
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
     b := make([]byte, n)
    _, err := rand.Read(b)
    // Note that err == nil only if we read len(b) bytes.
    if err != nil {
	   return nil, err
   }

   return b, nil
}

huangapple
  • 本文由 发表于 2016年3月4日 03:24:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/35781197.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定