在 Go 中生成随机的安全密码
Go 随机数 密码

> 
> Go 的随机数生成器是生成难以猜测的密码的好方法。
> 
> 
> 


![](/data/attachment/album/202205/21/152534k13a1wly39fuywu2.jpg)


你可以使用 [Go 编程语言](https://golang.org/) 提供的随机数生成器来生成由 ASCII 字符组成的难以猜测的密码。尽管本文中提供的代码很容易阅读，但是你仍需要了解 Go 的基础知识，才能更好地理解它。如果你是对 Go 还不熟悉，请阅读 [Go 语言之旅](https://tour.golang.org/welcome/1) 来了解更多信息，然后返回此处。


在介绍实用程序和它的代码之前，让我们先来看看这个 ASCII 表的子集，它可以在 `man ascii` 命令的输出中找到：



```
30 40 50 60 70 80 90 100 110 120
 ---------------------------------
0:    (  2  <  F  P  Z  d   n   x
1:    )  3  =  G  Q  [  e   o   y
2:    *  4  >  H  R  \  f   p   z
3: !  +  5  ?  I  S  ]  g   q   {
4: "  ,  6  @  J  T  ^  h   r   |
5: #  -  7  A  K  U  _  i   s   }
6: $  .  8  B  L  V  `  j   t   ~
7: %  /  9  C  M  W  a  k   u  DEL
8: &  0  :  D  N  X  b  l   v
9: '  1  ;  E  O  Y  c  m   w

```

在所有 ASCII 字符中，可打印字符的十进制值范围为 33 到 126，其他的 ASCII 值都不适合用于密码。因此，本文介绍的实用程序将生成该范围内的 ASCII 字符。


### 生成随机整数


第一个实用程序名为 `random.go`，它生成指定数量的随机整数，这些整数位于给定范围内。`random.go` 最重要的部分是这个函数：



```
func random(min, max int) int {
    return rand.Intn(max-min) + min
}

```

此函数使用了 `rand.Intn()` 函数来生成一个属于给定范围的随机整数。请注意，`rand.Intn()` 返回一个属于 `[0,n)` 的非负随机整数。如果它的参数是一个负数，这个函数将会抛出异常，异常消息是：`panic: invalid argument to Intn`。你可以在 [math/rand 文档](https://golang.org/pkg/math/rand/) 中找到 `math/rand` 包的使用说明。


`random.go` 实用程序接受三个命令行参数：生成的整数的最小值、最大值和个数。


编译和执行 `random.go` 会产生这样的输出：



```
$ go build random.go
$ ./random
Usage: ./random MIX MAX TOTAL
$ ./random 1 3 10
2 2 1 2 2 1 1 2 2 1

```

如果你希望在 Go 中生成更安全的随机数，请使用 Go 库中的 `crypto/rand` 包。


### 生成随机密码


第二个实用程序 `randomPass.go` 用于生成随机密码。`randomPass.go` 使用 `random()` 函数来生成随机整数，它们随后被以下 Go 代码转换为 ASCII 字符：



```
for {
    myRand := random(MIN, MAX)
    newChar := string(startChar[0] + byte(myRand))
    fmt.Print(newChar)
    if i == LENGTH {
        break
    }
    i++
}

```

`MIN` 的值为 `0`，`MAX` 的值为 `94`，而 `startChar` 的值为 `!`，它是 ASCII 表中第一个可打印的字符（十进制 ASCII 码为 `33`）。因此，所有生成的 ASCII 字符都位于 `!` 和 `~` 之间，后者的十进制 ASCII 码为 `126`。


因此，生成的每个随机数都大于 `MIN`，小于 `MAX`，并转换为 ASCII 字符。该过程继续进行，直到生成的密码达到指定的长度。


`randomPass.go` 实用程序接受单个（可选）命令行参数，以定义生成密码的长度，默认值为 8，这是一个非常常见的密码长度。执行 `randomPass.go` 会得到类似下面的输出：



```
$ go run randomPass.go 1
Z
$ go run randomPass.go 10
#Cw^a#IwkT
$ go run randomPass.go
Using default values!
[PP8@'Ci

```

最后一个细节：不要忘记调用 `rand.Seed()`，并提供一个<ruby> 种子 <rt>  seed </rt></ruby>值，以初始化随机数生成器。如果你始终使用相同的种子值，随机数生成器将生成相同的随机整数序列。


![随机数生成代码](/data/attachment/album/202205/21/152556qxmmdcopd13313pc.png)


你可以在 [GitHub](https://github.com/mactsouk/opensource.com) 找到 `random.go` 和 `randomPass.go` 的源码。你也可以直接在 [play.golang.org](https://play.golang.org/) 上执行它们。


我希望这篇文章对你有所帮助。如有任何问题，请在下方发表评论或在 [Twitter](https://twitter.com/mactsouk) 上与我联系。




---


via: <https://opensource.com/article/18/5/creating-random-secure-passwords-go>


作者：[Mihalis Tsoukalos](https://opensource.com/users/mtsouk) 选题：[lkxed](https://github.com/lkxed) 译者：[lkxed](https://github.com/lkxed) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
You can use the random number generator provided by the [Go programming language](https://golang.org/) to generate difficult-to-guess passwords comprised of ASCII characters. Although the code presented in this article is easy to read, it's best if you already know the basics of Go to understand it. If you're new to the programming language, take the [Tour of Go](https://tour.golang.org/welcome/1) to learn more, then come back here.

Before we get into the utilities and the code, take a look at this subset of the ASCII table as found in the output of the `man ascii`

command:

```
30 40 50 60 70 80 90 100 110 120
---------------------------------
0: ( 2 < F P Z d n x
1: ) 3 = G Q [ e o y
2: * 4 > H R \ f p z
3: ! + 5 ? I S ] g q {
4: " , 6 @ J T ^ h r |
5: # - 7 A K U _ i s }
6: $ . 8 B L V ` j t ~
7: % / 9 C M W a k u DEL
8: & 0 : D N X b l v
9: ' 1 ; E O Y c m w
```


The printable ASCII characters' decimal values range from 33 through 126; no other ASCII values are suitable for inclusion in passwords. Therefore, the utilities presented in this article will produce ASCII characters in that range.

## Creating random integers

The first utility is named `random.go`

, and it generates a specified number of random integers that reside in a given range. The most important part of `random.go`

is this function:

```
func random(min, max int) int {
return rand.Intn(max-min) + min
}
```


This function generates random integers that belong to a given range using the `rand.Intn()`

Go function. Note that `rand.Intn()`

returns a non-negative random number that belongs to `[0,n)`

; the function will panic if its argument is a negative number. The panic message will be `panic: invalid argument to Intn`

. You can find the documentation of the `math/rand`

package at [math/rand documentation](https://golang.org/pkg/math/rand/).

The `random.go`

utility accepts three command-line parameters: the minimum value of the generated integers, the maximum value, and the number of integers that will be generated.

Compiling and executing `random.go`

will create this kind of output:

```
$ go build random.go
$ ./random
Usage: ./random MIX MAX TOTAL
$ ./random 1 3 10
2 2 1 2 2 1 1 2 2 1
```


If you wish to generate more secure random numbers in Go, use the `crypto/rand`

package of the Go library.

## Creating random passwords

The second utility, `randomPass.go`

, generates the random passwords. `randomPass.go`

uses the `random()`

function to generate random numbers that will convert to ASCII characters using the following Go code:

```
for {
myRand := random(MIN, MAX)
newChar := string(startChar[0] + byte(myRand))
fmt.Print(newChar)
if i == LENGTH {
break
}
i++
}
```


The value of MIN is **0** and the value of MAX is **94**, whereas the value of `startChar`

is **!**, which is the first printable character in the ASCII table (with the decimal ASCII code of **33**). Therefore, all ASCII characters that will be generated are located after **!** and before the **~** character, which has a decimal ASCII code of **126**.


So, each random number that is generated is bigger than MIN, smaller than MAX, and converted into an ASCII character. The process keeps going until the generated password has the desired length.

The `randomPass.go`

utility accepts a single (optional) command-line parameter that defines the length of the generated password. Its default value is eight, which is a pretty common password length. Executing `randomPass.go`

will generate the following kind of output:

```
$ go run randomPass.go 1
Z
$ go run randomPass.go 10
#Cw^a#IwkT
$ go run randomPass.go
Using default values!
[PP8@'Ci
```


One last detail: Don't forget to call `rand.Seed()`

with a seed value in order to initialize the random number generator. If you use the same seed value all the time, the random number generator will create the same sequence of random integers.

You can find both `random.go`

and `randomPass.go`

at [GitHub](https://github.com/mactsouk/opensource.com). You can also execute it at [play.golang.org](https://play.golang.org/).

I hope this has been helpful. If you have any questions, please leave a comment below or reach out to me on [Twitter](https://twitter.com/mactsouk).

## 6 Comments