将随机性不足的值用作加密算法的密钥¶
ID: go/insecure-randomness
Kind: path-problem
Security severity: 7.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-338
Query suites:
- go-code-scanning.qls
- go-security-extended.qls
- go-security-and-quality.qls
使用加密强度较弱的伪随机数生成器来生成安全敏感值(例如密码)会使攻击者更容易预测该值。
伪随机数生成器生成的数字序列仅近似于随机数的属性。该序列并非真正的随机序列,因为它完全由一组相对较小的初始值(种子)决定。如果随机数生成器的加密强度较弱,则可以通过外部观察轻松预测该序列。
建议¶
如果输出将用于安全敏感的上下文中,请使用加密安全的伪随机数生成器。根据经验,如果预测某个值将允许攻击者执行他们原本无法执行的操作,则该值应被视为“安全敏感的”。例如,如果攻击者可以预测为新用户生成的随机密码,则他们将能够以该新用户的身份登录。
对于 Go,crypto/rand
提供了加密安全的伪随机数生成器。math/rand
的加密安全性较低,应避免在安全上下文中使用。对于非安全敏感的上下文,math/rand
可能是更好的选择,因为它具有更方便的接口,并且可能更快。
示例¶
以下示例使用 math/rand
包而不是 crypto/rand
来生成密码
package main
import (
"math/rand"
)
var charset = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
func generatePassword() string {
s := make([]rune, 20)
for i := range s {
s[i] = charset[rand.Intn(len(charset))]
}
return string(s)
}
而应使用 crypto/rand
package main
import (
"crypto/rand"
"math/big"
)
func generatePasswordGood() string {
s := make([]rune, 20)
for i := range s {
idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
if err != nil {
// handle err
}
s[i] = charset[idx.Int64()]
}
return string(s)
}