golang 随机数

随机数主要分为以下三类:

  • 弱伪随机数
  • 强伪随机数
  • 真随机数

随机数的分类是根据随机数的性质进行的分类。随机数的性质分为以下三类:

  • 随机性一不存在统计学偏差,是完全杂乱的数列
  • 不可预测性一不能从过去的数列推测出”下一个出现的数
  • 不可重现性一除非将数列本身保存下来,否则不能重现相同的数列

密码技术中所使用的随机数,仅仅具备随机性是不够的,至少还需要具备不可预测性才行。

GoLang 中的伪随机数

在 GoLang 中,我们可以通过 math/rand 包里的方法来生成一个伪随机数:

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
"math/rand"
)

func main() {
fmt.Println(rand.Int()) // => 134020434
}

你会发现运行的结果一直是 134020434,怎样才能显示不同的结果,需要了解一下“随机种子”的概念。

随机种子

伪随机数,是使用一个确定性的算法计算出来的似乎是随机的数序,因此伪随机数实际上并不随机。

那么自然,在计算伪随机数时假如使用的开始值不变的话,那么算法计算出的伪随机数的数序自然也是不变的咯。

这个“开始值”,就被称为随机种子。

可以通过 rand.Seed 方法设置随机种子,如果不设置,则默认值显示为 1,为了保证每次伪随机数生成器工作时使用的是不同的种子,通常的做法是采用当前时间作为种子。

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

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

func main() {

rand.Seed(int64(time.Now().Unix()))
fmt.Println(rand.Intn(100))
}

真随机数

如果我们的应用对安全性要求比较高,需要使用真随机数的话,那么可以使用 crypto/rand 包中的方法。

1
2
3
4
5
6
7
8
9
10
11
12
package main

import (
"crypto/rand"
"fmt"
"math/big"
)

func main() {
result, _ := rand.Int(rand.Reader, big.NewInt(100))
fmt.Println(result)
}