Go 语言标准库 —— crypto/rand 包(加密安全随机数生成器)
🔹 概述
crypto/rand 包实现了加密安全的随机数生成器(CSPRNG - Cryptographically Secure Pseudorandom Number Generator)。
主要功能:
- 生成加密安全的随机数
- 生成随机大整数
- 生成素数(用于 RSA 等)
- 生成随机令牌/密码
- 实现
io.Reader接口
重要说明:
- ✅ 加密安全 - 适用于密码学应用
- 🔒 不可预测 - 无法通过已生成的值预测下一个值
- 🌐 跨平台 - 使用操作系统提供的安全随机源
- 📦 全局共享 -
rand.Reader是全局的、可并发使用 - ⚡ FIPS 140-3 - 支持 FIPS 模式(使用 DRBG)
与 math/rand 的区别:
crypto/rand- 加密安全,用于密钥、令牌等math/rand- 非加密安全,用于游戏、模拟等
操作系统随机源:
- Linux/FreeBSD/Solaris -
getrandom(2)或/dev/urandom - macOS/iOS/OpenBSD -
arc4random_buf(3) - Windows -
ProcessPrngAPI - NetBSD -
kern.arandomsysctl - WebAssembly - Web Crypto API
- wasip1 -
random_get
🔹 全局变量
Reader - 全局随机数生成器
var Reader io.Reader
-
说明:
- 全局、共享的加密安全随机数生成器
- 可安全并发使用
- 在 FIPS 140-3 模式下,输出通过 SP 800-90A Rev.1 DRBG
-
特点:
- ✅ 线程安全
- ✅ 永不返回错误(在非传统 Linux 系统上)
- ✅ 总是填满缓冲区
-
示例:
package main import ( "crypto/rand" "encoding/hex" "fmt" ) func main() { // 使用全局 Reader 生成随机字节 bytes := make([]byte, 32) _, err := rand.Read(bytes) if err != nil { fmt.Println("错误:", err) return } fmt.Printf("随机字节:%s\n", hex.EncodeToString(bytes)) fmt.Printf("长度:%d 字节\n", len(bytes)) }
🔹 核心函数
Read - 填充随机字节
rand.Read(b []byte) (n int, err error)
-
说明:
- 用加密安全的随机字节填充切片 b
- 永不返回错误(在非传统 Linux 系统上)
- 总是完全填满 b
- 如果底层随机源失败,会直接终止程序
-
参数:
b []byte- 要填充的字节切片
-
返回值:
n int- 读取的字节数(总是等于 len(b))err error- 错误(通常为 nil)
-
示例(生成随机密钥):
package main import ( "crypto/rand" "encoding/hex" "fmt" ) // GenerateRandomKey 生成随机密钥 func GenerateRandomKey(size int) ([]byte, error) { key := make([]byte, size) _, err := rand.Read(key) if err != nil { return nil, err } return key, nil } func main() { // 生成 256 位密钥 key, err := GenerateRandomKey(32) // 32 字节 = 256 位 if err != nil { fmt.Println("错误:", err) return } fmt.Printf("256 位密钥:%s\n", hex.EncodeToString(key)) // 生成 128 位 IV iv := make([]byte, 16) // 16 字节 = 128 位 rand.Read(iv) fmt.Printf("128 位 IV: %s\n", hex.EncodeToString(iv)) } -
注意事项:
- ✅ 总是检查错误(虽然通常不会发生)
- ✅ 保证完全填满缓冲区
- ⚠️ 在极端情况下(系统熵源耗尽)会终止程序
Int - 生成随机大整数
rand.Int(rand io.Reader, max *big.Int) (n *big.Int, err error)
-
说明:
- 生成 [0, max) 范围内的均匀分布随机大整数
- 包含 0,不包含 max
-
参数:
rand io.Reader- 随机数源(通常使用rand.Reader)max *big.Int- 最大值(不包含)
-
返回值:
n *big.Int- 随机大整数err error- 错误信息
-
示例(生成随机数):
package main import ( "crypto/rand" "fmt" "math/big" ) func main() { // 生成 [0, 100) 的随机数 max := big.NewInt(100) n, err := rand.Int(rand.Reader, max) if err != nil { fmt.Println("错误:", err) return } fmt.Printf("随机数 [0, 100): %s\n", n.String()) // 生成 [0, 2^256) 的随机数 max256 := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil) n256, _ := rand.Int(rand.Reader, max256) fmt.Printf("256 位随机数:%s\n", n256.Text(16)) // 生成 [0, 10^100) 的随机数 max100 := new(big.Int).Exp(big.NewInt(10), big.NewInt(100), nil) n100, _ := rand.Int(rand.Reader, max100) fmt.Printf("100 位十进制随机数:%s\n", n100.String()) } -
注意事项:
- ⚠️
max <= 0时会 panic - ✅ 均匀分布
- ✅ 适用于密码学应用
- ⚠️
Prime - 生成随机素数
rand.Prime(r io.Reader, bits int) (*big.Int, error)
-
说明:
- 生成指定位数的随机素数
- 素数概率极高
- Go 1.26+ 总是使用安全随机源
-
参数:
r io.Reader- 随机数源(Go 1.26+ 可忽略)bits int- 素数的位数
-
返回值:
*big.Int- 随机素数error- 错误信息
-
示例(生成 RSA 素数):
package main import ( "crypto/rand" "fmt" ) func main() { // 生成 512 位素数(用于 RSA-1024) p, err := rand.Prime(rand.Reader, 512) if err != nil { fmt.Println("错误:", err) return } fmt.Printf("512 位素数:%s\n", p.Text(16)) fmt.Printf("位数:%d\n", p.BitLen()) // 生成 1024 位素数(用于 RSA-2048) q, _ := rand.Prime(rand.Reader, 1024) fmt.Printf("\n1024 位素数:%s\n", q.Text(16)) fmt.Printf("位数:%d\n", q.BitLen()) // 生成 2048 位素数(用于 RSA-4096) r, _ := rand.Prime(rand.Reader, 2048) fmt.Printf("\n2048 位素数(前 64 位):%s...\n", r.Text(16)[:64]) fmt.Printf("位数:%d\n", r.BitLen()) } -
注意事项:
- ⚠️
bits < 2时返回错误 - ✅ 素数测试使用 Miller-Rabin 等方法
- ✅ 适用于 RSA 密钥生成
- ⚠️
Text - 生成随机文本
rand.Text() string
-
说明:
- 生成加密安全的随机字符串
- 使用 RFC 4648 base32 字母表
- 包含至少 128 位随机性
- 适用于密码、令牌、密钥等
-
返回值:
string- 随机字符串(base32 编码)
-
示例(生成随机令牌):
package main import ( "crypto/rand" "fmt" ) func main() { // 生成随机令牌 token := rand.Text() fmt.Printf("随机令牌:%s\n", token) fmt.Printf("长度:%d 字符\n", len(token)) // 生成多个令牌 fmt.Println("\n生成多个令牌:") for i := 0; i < 5; i++ { fmt.Printf("令牌 %d: %s\n", i+1, rand.Text()) } } -
注意事项:
- ✅ 适用于会话令牌、API 密钥等
- ✅ 防碰撞(128 位随机性)
- ✅ 防暴力破解
- 📝 使用 base32 编码(A-Z, 2-7)
🔹 完整示例
1. 生成各种随机数据
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math/big"
)
func main() {
fmt.Println("=== 加密安全随机数生成 ===\n")
// 1. 生成随机字节
bytes := make([]byte, 32)
rand.Read(bytes)
fmt.Printf("32 字节随机数:%s\n", hex.EncodeToString(bytes))
// 2. 生成随机整数 [0, 1000)
max := big.NewInt(1000)
n, _ := rand.Int(rand.Reader, max)
fmt.Printf("\n随机整数 [0, 1000): %s\n", n.String())
// 3. 生成随机素数
prime, _ := rand.Prime(rand.Reader, 256)
fmt.Printf("\n256 位素数:%s\n", prime.Text(16))
// 4. 生成随机令牌
token := rand.Text()
fmt.Printf("\n随机令牌:%s\n", token)
// 5. 生成 UUID v4
uuid := make([]byte, 16)
rand.Read(uuid)
// 设置 UUID v4 版本
uuid[6] = (uuid[6] & 0x0f) | 0x40
// 设置 UUID 变体
uuid[8] = (uuid[8] & 0x3f) | 0x80
fmt.Printf("\nUUID v4: %x-%x-%x-%x-%x\n",
uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
}
2. 安全密码生成器
package main
import (
"crypto/rand"
"fmt"
"math/big"
"strings"
)
const (
lowercase = "abcdefghijklmnopqrstuvwxyz"
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits = "0123456789"
specials = "!@#$%^&*()_+-=[]{}|;:,.<>?"
allChars = lowercase + uppercase + digits + specials
)
// GenerateSecurePassword 生成安全密码
func GenerateSecurePassword(length int) (string, error) {
if length < 4 {
return "", fmt.Errorf("密码长度至少为 4")
}
password := make([]byte, length)
// 确保包含至少一个大写、一个小写、一个数字、一个特殊字符
password[0] = lowercase[randomInt(len(lowercase))]
password[1] = uppercase[randomInt(len(uppercase))]
password[2] = digits[randomInt(len(digits))]
password[3] = specials[randomInt(len(specials))]
// 剩余字符随机
for i := 4; i < length; i++ {
password[i] = allChars[randomInt(len(allChars))]
}
// 打乱顺序
shuffle(password)
return string(password), nil
}
func randomInt(max int) int {
n, _ := rand.Int(rand.Reader, big.NewInt(int64(max)))
return int(n.Int64())
}
func shuffle(bytes []byte) {
for i := len(bytes) - 1; i > 0; i-- {
j, _ := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
bytes[i], bytes[j] = bytes[j], bytes[i]
}
}
func main() {
fmt.Println("=== 安全密码生成器 ===\n")
lengths := []int{8, 12, 16, 20, 32}
for _, length := range lengths {
password, _ := GenerateSecurePassword(length)
fmt.Printf("%d 位密码:%s\n", length, password)
}
}
3. 随机令牌生成器(用于 API 认证)
package main
import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"time"
)
// TokenGenerator 令牌生成器
type TokenGenerator struct {
prefix string
}
// NewTokenGenerator 创建令牌生成器
func NewTokenGenerator(prefix string) *TokenGenerator {
return &TokenGenerator{prefix: prefix}
}
// GenerateToken 生成随机令牌
func (tg *TokenGenerator) GenerateToken() string {
// 生成 32 字节随机数据
randomBytes := make([]byte, 32)
rand.Read(randomBytes)
// 添加时间戳
timestamp := time.Now().UnixNano()
// 组合:prefix + timestamp + random
token := fmt.Sprintf("%s_%d_%s",
tg.prefix,
timestamp,
base64.URLEncoding.EncodeToString(randomBytes))
return token
}
// GenerateAPIKey 生成 API 密钥
func GenerateAPIKey() (string, error) {
key := make([]byte, 32) // 256 位
_, err := rand.Read(key)
if err != nil {
return "", err
}
return hex.EncodeToString(key), nil
}
// GenerateSessionID 生成会话 ID
func GenerateSessionID() string {
id := make([]byte, 16) // 128 位
rand.Read(id)
return hex.EncodeToString(id)
}
func main() {
fmt.Println("=== 随机令牌生成器 ===\n")
// API 令牌生成器
apiGen := NewTokenGenerator("api")
fmt.Println("API 令牌:")
for i := 0; i < 3; i++ {
fmt.Printf(" %s\n", apiGen.GenerateToken())
}
// 访问令牌生成器
accessGen := NewTokenGenerator("access")
fmt.Println("\n访问令牌:")
for i := 0; i < 3; i++ {
fmt.Printf(" %s\n", accessGen.GenerateToken())
}
// API 密钥
fmt.Println("\nAPI 密钥:")
for i := 0; i < 3; i++ {
key, _ := GenerateAPIKey()
fmt.Printf(" %s\n", key)
}
// 会话 ID
fmt.Println("\n会话 ID:")
for i := 0; i < 3; i++ {
fmt.Printf(" %s\n", GenerateSessionID())
}
}
4. 随机盐值生成(用于密码哈希)
package main
import (
"crypto/rand"
"encoding/base64"
"fmt"
)
// SaltConfig 盐值配置
type SaltConfig struct {
Size int // 盐值大小(字节)
Format string // 输出格式:"hex" 或 "base64"
}
// GenerateSalt 生成随机盐值
func GenerateSalt(config SaltConfig) (string, error) {
salt := make([]byte, config.Size)
_, err := rand.Read(salt)
if err != nil {
return "", err
}
switch config.Format {
case "base64":
return base64.StdEncoding.EncodeToString(salt), nil
case "hex":
fallthrough
default:
return fmt.Sprintf("%x", salt), nil
}
}
// HashPassword 模拟密码哈希(实际应使用 bcrypt/argon2)
func HashPassword(password, salt string) string {
// 实际应用中应使用 bcrypt 或 argon2
return fmt.Sprintf("%s$%s", salt, password)
}
func main() {
fmt.Println("=== 随机盐值生成器 ===\n")
// 配置
configs := []SaltConfig{
{Size: 8, Format: "hex"}, // 64 位盐
{Size: 16, Format: "hex"}, // 128 位盐
{Size: 16, Format: "base64"}, // 128 位盐 (base64)
{Size: 32, Format: "hex"}, // 256 位盐
}
passwords := []string{"password123", "secure_pass", "admin2024"}
for i, config := range configs {
fmt.Printf("%d. %d 位盐值 (%s):\n", i+1, config.Size*8, config.Format)
for _, pwd := range passwords {
salt, _ := GenerateSalt(config)
hashed := HashPassword(pwd, salt)
fmt.Printf(" 密码:%s\n", pwd)
fmt.Printf(" 盐值:%s\n", salt)
fmt.Printf(" 哈希:%s\n\n", hashed)
}
fmt.Println()
}
// 最佳实践建议
fmt.Println("=== 最佳实践 ===")
fmt.Println("✅ 每个密码使用唯一盐值")
fmt.Println("✅ 盐值至少 128 位(16 字节)")
fmt.Println("✅ 盐值与哈希一起存储")
fmt.Println("✅ 使用 bcrypt/argon2 进行密码哈希")
fmt.Println("❌ 不要重复使用盐值")
fmt.Println("❌ 不要使用固定盐值")
}
5. 随机 ID 生成器(用于数据库记录)
package main
import (
"crypto/rand"
"encoding/base32"
"fmt"
"strings"
"time"
)
// IDGenerator 随机 ID 生成器
type IDGenerator struct {
prefix string
idLength int
}
// NewIDGenerator 创建 ID 生成器
func NewIDGenerator(prefix string, length int) *IDGenerator {
return &IDGenerator{
prefix: strings.ToUpper(prefix),
idLength: length,
}
}
// Generate 生成随机 ID
func (g *IDGenerator) Generate() string {
// 生成随机字节
bytes := make([]byte, g.idLength)
rand.Read(bytes)
// Base32 编码
encoded := base32.StdEncoding.EncodeToString(bytes)
// 移除填充字符
encoded = strings.TrimRight(encoded, "=")
// 添加前缀和时间戳
timestamp := time.Now().UnixNano() % 1000000 // 微秒级时间戳
return fmt.Sprintf("%s-%d-%s", g.prefix, timestamp, encoded[:16])
}
// GenerateBatch 批量生成 ID
func (g *IDGenerator) GenerateBatch(count int) []string {
ids := make([]string, count)
for i := 0; i < count; i++ {
ids[i] = g.Generate()
}
return ids
}
func main() {
fmt.Println("=== 随机 ID 生成器 ===\n")
// 订单 ID 生成器
orderGen := NewIDGenerator("ORD", 16)
fmt.Println("订单 ID:")
for i := 0; i < 5; i++ {
fmt.Printf(" %s\n", orderGen.Generate())
}
// 用户 ID 生成器
userGen := NewIDGenerator("USR", 12)
fmt.Println("\n用户 ID:")
for i := 0; i < 5; i++ {
fmt.Printf(" %s\n", userGen.Generate())
}
// 产品 ID 生成器
productGen := NewIDGenerator("PRD", 14)
fmt.Println("\n产品 ID:")
for i := 0; i < 5; i++ {
fmt.Printf(" %s\n", productGen.Generate())
}
// 批量生成
fmt.Println("\n批量生成订单 ID:")
batchIDs := orderGen.GenerateBatch(10)
for _, id := range batchIDs {
fmt.Printf(" %s\n", id)
}
}
6. 与非加密随机数对比
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math/rand"
"time"
)
func main() {
fmt.Println("=== crypto/rand vs math/rand 对比 ===\n")
// 1. 可预测性对比
fmt.Println("1. 可预测性对比:")
fmt.Println(" math/rand(可预测):")
rand.Seed(12345) // 固定种子
for i := 0; i < 3; i++ {
fmt.Printf(" %d ", rand.Intn(100))
}
fmt.Println()
rand.Seed(12345) // 相同种子
for i := 0; i < 3; i++ {
fmt.Printf(" %d ", rand.Intn(100))
}
fmt.Println("\n ^ 相同种子产生相同序列")
fmt.Println("\n crypto/rand(不可预测):")
for i := 0; i < 2; i++ {
bytes := make([]byte, 8)
crypto.rand.Read(bytes)
fmt.Printf(" %s\n", hex.EncodeToString(bytes))
}
fmt.Println(" ^ 每次都不同,无法预测")
// 2. 性能对比
fmt.Println("\n2. 性能对比:")
// math/rand
start := time.Now()
for i := 0; i < 10000; i++ {
rand.Int63()
}
mathDuration := time.Since(start)
// crypto/rand
start = time.Now()
bytes := make([]byte, 8*10000)
crypto.rand.Read(bytes)
cryptoDuration := time.Since(start)
fmt.Printf(" math/rand: %.2f ms (10000 次)\n", float64(mathDuration.Microseconds())/1000)
fmt.Printf(" crypto/rand: %.2f ms (10000 次)\n", float64(cryptoDuration.Microseconds())/1000)
fmt.Printf(" 性能比:%.1fx\n", float64(cryptoDuration)/float64(mathDuration))
// 3. 使用场景
fmt.Println("\n3. 使用场景:")
fmt.Println(" ✅ crypto/rand:")
fmt.Println(" - 密码学密钥生成")
fmt.Println(" - 会话令牌")
fmt.Println(" - API 密钥")
fmt.Println(" - 密码盐值")
fmt.Println(" - 随机素数(RSA)")
fmt.Println("\n ✅ math/rand:")
fmt.Println(" - 游戏逻辑")
fmt.Println(" - 模拟测试")
fmt.Println(" - 随机采样")
fmt.Println(" - 负载均衡(非安全)")
}
🔹 注意事项和最佳实践
1. 与 math/rand 的区别
-
✅ crypto/rand - 加密安全
- 不可预测
- 使用操作系统熵源
- 适用于密码学应用
- 性能较慢
-
❌ math/rand - 非加密安全
- 可预测(知道种子可重现)
- 使用伪随机算法
- 适用于游戏、模拟
- 性能较快
// ✅ 正确 - 生成密钥
key := make([]byte, 32)
crypto.rand.Read(key)
// ❌ 错误 - 生成密钥
key := make([]byte, 32)
rand.Read(key) // 不安全!
2. 错误处理
- ✅
rand.Read()通常不返回错误 - ⚠️ 在极端情况下会终止程序
- ✅ 仍应检查错误(最佳实践)
// 正确 - 检查错误
bytes := make([]byte, 32)
_, err := crypto.rand.Read(bytes)
if err != nil {
return nil, err
}
// Go 1.26+ 可以简化
bytes := make([]byte, 32)
crypto.rand.Read(bytes) // 错误会 panic
3. 熵源质量
- ✅ 现代操作系统提供高质量熵源
- ⚠️ 虚拟机/容器可能熵源不足
- ✅ 使用硬件 RNG(如果可用)
// 检查熵源质量(Linux)
func checkEntropy() {
data, _ := os.ReadFile("/proc/sys/kernel/random/entropy_avail")
entropy, _ := strconv.Atoi(strings.TrimSpace(string(data)))
fmt.Printf("可用熵:%d 位\n", entropy)
if entropy < 1000 {
fmt.Println("警告:熵源可能不足")
}
}
4. 并发安全
- ✅
rand.Reader是线程安全的 - ✅ 可以在多个 goroutine 中同时使用
// 安全 - 并发使用
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
bytes := make([]byte, 16)
crypto.rand.Read(bytes) // 安全
}()
}
wg.Wait()
5. FIPS 140-3 合规性
- ✅ FIPS 模式下使用 DRBG(SP 800-90A Rev.1)
- ✅ 输出符合 FIPS 140-3 要求
- ⚠️ 需要启用 FIPS 模式
// FIPS 模式下自动使用 DRBG
// 无需特殊配置
bytes := make([]byte, 32)
crypto.rand.Read(bytes) // FIPS 合规
6. 常见用途
- ✅ 密钥生成 - AES、HMAC 密钥
- ✅ 令牌生成 - 会话令牌、API 令牌
- ✅ 盐值生成 - 密码哈希盐值
- ✅ 素数生成 - RSA 密钥
- ✅ Nonce/IV 生成 - 加密初始化向量
- ❌ 游戏逻辑 - 使用 math/rand
- ❌ 模拟测试 - 使用 math/rand
🔥 总结
核心函数
| 函数 | 说明 | 返回值 | 使用场景 |
|---|---|---|---|
| Read() | 填充随机字节 | (n, error) | 通用随机数生成 |
| Int() | 生成随机大整数 | (*big.Int, error) | 随机数、概率 |
| Prime() | 生成随机素数 | (*big.Int, error) | RSA 密钥生成 |
| Text() | 生成随机文本 | string | 令牌、密码 |
全局变量
| 变量 | 类型 | 说明 |
|---|---|---|
| Reader | io.Reader | 全局加密安全随机源 |
操作系统随机源
| 操作系统 | 随机源 |
|---|---|
| Linux/FreeBSD/Solaris | getrandom(2) 或 /dev/urandom |
| macOS/iOS/OpenBSD | arc4random_buf(3) |
| Windows | ProcessPrng API |
| NetBSD | kern.arandom sysctl |
| WebAssembly | Web Crypto API |
| wasip1 | random_get |
主要特点
- 加密安全 👉 不可预测,适用于密码学
- 全局共享 👉
rand.Reader可并发使用 - 跨平台 👉 使用操作系统安全随机源
- FIPS 合规 👉 支持 FIPS 140-3 模式
- 永不失败 👉 在非传统 Linux 系统上
使用场景
- ✅ 密码学生成 👉 密钥、IV、Nonce
- ✅ 令牌生成 👉 会话令牌、API 密钥
- ✅ 盐值生成 👉 密码哈希盐值
- ✅ 素数生成 👉 RSA 密钥生成
- ✅ 随机 ID 👉 数据库记录 ID
- ❌ 游戏逻辑 👉 使用 math/rand
- ❌ 模拟测试 👉 使用 math/rand
最佳实践
- ✅ 始终使用 crypto/rand 进行密码学操作
- ✅ 检查错误(虽然通常不会发生)
- ✅ 使用足够长的密钥/令牌(至少 128 位)
- ✅ 每个密码使用唯一盐值
- ✅ 令牌包含足够随机性(至少 128 位)
- ⚠️ 注意虚拟机熵源质量
- ❌ 不要使用 math/rand 进行安全操作
安全建议
- 🔒 密钥至少 256 位(32 字节)
- 🔒 令牌至少 128 位随机性
- 🔒 盐值至少 128 位(16 字节)
- 🔒 使用硬件 RNG(如果可用)
- 🔒 监控熵源质量
- 🔒 定期轮换密钥和令牌
🔹 常用工具函数封装
package random
import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"math/big"
)
// Bytes 生成指定长度的随机字节
func Bytes(length int) ([]byte, error) {
bytes := make([]byte, length)
_, err := rand.Read(bytes)
return bytes, err
}
// Hex 生成指定长度的随机十六进制字符串
func Hex(length int) (string, error) {
bytes, err := Bytes(length)
if err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
// Base64 生成指定长度的随机 Base64 字符串
func Base64(length int) (string, error) {
bytes, err := Bytes(length)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(bytes), nil
}
// Int 生成 [0, max) 范围内的随机整数
func Int(max int) (int, error) {
n, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
if err != nil {
return 0, err
}
return int(n.Int64()), nil
}
// Token 生成随机令牌(至少 128 位随机性)
func Token() string {
return rand.Text()
}
// Key 生成加密密钥(256 位)
func Key() ([]byte, error) {
return Bytes(32)
}
// Salt 生成盐值(128 位)
func Salt() (string, error) {
return Hex(16)
}
crypto/rand 包提供了加密安全的随机数生成,适用于所有密码学应用!