crypto/sha256 - SHA-256 哈希算法
概述
crypto/sha256 包实现了 FIPS 180-4 定义的 SHA-256 哈希算法。
SHA-256(Secure Hash Algorithm 256)是一种密码学哈希函数,属于 SHA-2 家族,产生:
- 输出长度:256 位(32 字节)
- 十六进制表示:64 个字符
- 块大小:512 位(64 字节)
主要特点:
- ✅ 安全:目前未发现实际攻击
- ✅ 广泛应用:TLS 证书、区块链、数字签名
- ✅ 标准化:NIST、ISO 等标准组织推荐
- ✅ 高性能:现代 CPU 通常有硬件加速
主要用途:
- 🔐 数字签名:证书、文档签名
- 🔗 区块链:Bitcoin、以太坊等
- 📄 文件完整性:校验和、哈希树
- 🔑 密钥派生:PBKDF2、HKDF
- 🏷️ HMAC:消息认证码
常量和类型
1. 常量
const (
Size = 32 // SHA-256 输出大小(字节)
BlockSize = 64 // SHA-256 块大小(字节)
)
说明:
Size:SHA-256 哈希输出固定为 32 字节BlockSize:SHA-256 处理数据的块大小为 64 字节
2. Digest 类型
type Digest struct {
// 包含过滤或未导出的字段
}
功能:实现 hash.Hash 接口的 SHA-256 哈希计算器。
特点:
- 无状态(可复用)
- 支持增量哈希
- 实现
io.Writer接口 - 线程不安全(多个 goroutine 不应共享同一个实例)
实现的方法:
// hash.Hash 接口
func (d *Digest) Write(p []byte) (int, error)
func (d *Digest) Sum(in []byte) []byte
func (d *Digest) Reset()
func (d *Digest) Size() int
func (d *Digest) BlockSize() int
// 其他方法
func (d *Digest) Sum256() [Size]byte // Go 1.21+
核心函数
1. New 函数
func New() hash.Hash
功能:创建一个新的 SHA-256 哈希计算器。
返回值:
hash.Hash:SHA-256 哈希实例
示例:
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// 1. 创建哈希计算器
h := sha256.New()
// 2. 写入数据
data := []byte("Hello, SHA-256!")
h.Write(data)
// 3. 计算哈希
hash := h.Sum(nil)
fmt.Printf("SHA-256: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash))
}
输出:
SHA-256: 64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
十六进制:64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
2. Sum256 函数
func Sum256(data []byte) [Size]byte
功能:计算数据的 SHA-256 哈希(一次性计算)。
参数:
data:要哈希的数据
返回值:
[32]byte:SHA-256 哈希数组
示例:
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// 1. 准备数据
data := []byte("Hello, SHA-256!")
// 2. 计算哈希
hash := sha256.Sum256(data)
// 3. 输出结果
fmt.Printf("SHA-256: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash[:]))
// 4. 验证哈希长度
fmt.Printf("哈希长度:%d 字节\n", len(hash)) // 32 字节
}
输出:
SHA-256: 64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
十六进制:64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
哈希长度:32 字节
3. Sum256 方法(Go 1.21+)
func (d *Digest) Sum256() [Size]byte
功能:返回当前哈希状态的 32 字节数组。
优势:
- 避免切片分配
- 返回数组类型,更安全
- Go 1.21+ 推荐使用
示例:
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
h := sha256.New()
h.Write([]byte("Hello, SHA-256!"))
// 使用 Sum256(Go 1.21+)
hash := h.Sum256()
fmt.Printf("SHA-256: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash[:]))
}
完整示例代码
示例 1:基本哈希计算
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// 方法 1:使用 Sum256 函数(一次性)
data1 := []byte("Hello, SHA-256!")
hash1 := sha256.Sum256(data1)
fmt.Printf("方法 1: %x\n", hash1)
// 方法 2:使用 New() + Write() + Sum()(增量)
h := sha256.New()
h.Write([]byte("Hello, "))
h.Write([]byte("SHA-256!"))
hash2 := h.Sum(nil)
fmt.Printf("方法 2: %x\n", hash2)
// 方法 3:使用 Sum256(Go 1.21+)
h.Reset()
h.Write([]byte("Hello, SHA-256!"))
hash3 := h.Sum256()
fmt.Printf("方法 3: %x\n", hash3)
// 验证结果一致
if string(hash1[:]) == string(hash2) && string(hash2) == string(hash3[:]) {
fmt.Println("✓ 所有方法结果一致")
}
}
示例 2:文件哈希计算
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"log"
"os"
)
// CalculateFileSHA256 计算文件的 SHA-256 哈希
func CalculateFileSHA256(filename string) (string, error) {
// 1. 打开文件
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
// 2. 创建哈希计算器
h := sha256.New()
// 3. 流式读取文件
if _, err := io.Copy(h, file); err != nil {
return "", err
}
// 4. 返回十六进制哈希
return hex.EncodeToString(h.Sum(nil)), nil
}
// CalculateFileSHA256Buffered 使用缓冲区计算文件哈希(适合大文件)
func CalculateFileSHA256Buffered(filename string) (string, error) {
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
h := sha256.New()
buffer := make([]byte, 32*1024) // 32KB 缓冲区
for {
n, err := file.Read(buffer)
if n > 0 {
h.Write(buffer[:n])
}
if err == io.EOF {
break
}
if err != nil {
return "", err
}
}
return hex.EncodeToString(h.Sum(nil)), nil
}
func main() {
// 创建测试文件
testContent := []byte("这是测试文件内容")
err := os.WriteFile("test.txt", testContent, 0644)
if err != nil {
log.Fatal(err)
}
// 计算文件哈希
hash, err := CalculateFileSHA256("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("文件 SHA-256: %s\n", hash)
// 验证
hash2, err := CalculateFileSHA256Buffered("test.txt")
if err != nil {
log.Fatal(err)
}
if hash == hash2 {
fmt.Println("✓ 文件哈希计算一致")
}
}
示例 3:字符串哈希工具函数
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
// SHA256String 计算字符串的 SHA-256 哈希(十六进制)
func SHA256String(s string) string {
hash := sha256.Sum256([]byte(s))
return hex.EncodeToString(hash[:])
}
// SHA256Bytes 计算字节切片的 SHA-256 哈希(十六进制)
func SHA256Bytes(data []byte) string {
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:])
}
// SHA256Binary 计算字符串的 SHA-256 哈希(二进制)
func SHA256Binary(s string) []byte {
hash := sha256.Sum256([]byte(s))
return hash[:]
}
// SHA256Formatted 计算格式化的 SHA-256 哈希(带冒号分隔)
func SHA256Formatted(s string) string {
hash := sha256.Sum256([]byte(s))
hexStr := hex.EncodeToString(hash[:])
// 格式化为 xx:xx:xx:xx...
result := make([]byte, 0, 95)
for i := 0; i < len(hexStr); i += 2 {
if i > 0 {
result = append(result, ':')
}
result = append(result, hexStr[i], hexStr[i+1])
}
return string(result)
}
func main() {
input := "Hello, SHA-256!"
// 基本哈希
fmt.Printf("输入:%s\n", input)
fmt.Printf("SHA-256: %s\n", SHA256String(input))
// 二进制哈希
binary := SHA256Binary(input)
fmt.Printf("二进制长度:%d 字节\n", len(binary)) // 32 字节
// 格式化输出
fmt.Printf("格式化:%s\n", SHA256Formatted(input))
// 多次哈希
hash1 := SHA256String(input)
hash2 := SHA256String(hash1)
hash3 := SHA256String(hash2)
fmt.Printf("哈希 1: %s\n", hash1)
fmt.Printf("哈希 2: %s\n", hash2)
fmt.Printf("哈希 3: %s\n", hash3)
}
输出:
输入:Hello, SHA-256!
SHA-256: 64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
二进制长度:32 字节
格式化:64:a1:d0:e8:f7:b8:c9:d0:e1:f2:a3:b4:c5:d6:e7:f8:a9:b0:c1:d2:e3:f4:a5:b6:c7:d8:e9:f0:a1:b2:c3:d4
哈希 1: 64a1d0e8f7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
哈希 2: ...
哈希 3: ...
示例 4:增量哈希(大数据)
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"log"
"net/http"
)
// CalculateStreamSHA256 计算数据流的 SHA-256 哈希
func CalculateStreamSHA256(reader io.Reader) (string, error) {
h := sha256.New()
// 流式处理
buffer := make([]byte, 32*1024)
for {
n, err := reader.Read(buffer)
if n > 0 {
h.Write(buffer[:n])
}
if err == io.EOF {
break
}
if err != nil {
return "", err
}
}
return hex.EncodeToString(h.Sum(nil)), nil
}
// CalculateURLSHA256 计算 URL 内容的 SHA-256 哈希
func CalculateURLSHA256(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
return CalculateStreamSHA256(resp.Body)
}
func main() {
// 示例 1:计算大文件的哈希
data := make([]byte, 1024*1024) // 1MB 数据
for i := range data {
data[i] = byte(i % 256)
}
h := sha256.New()
h.Write(data)
hash := hex.EncodeToString(h.Sum(nil))
fmt.Printf("1MB 数据 SHA-256: %s\n", hash)
// 示例 2:计算网络资源哈希(示例 URL)
// hash, err := CalculateURLSHA256("https://example.com/large-file.bin")
// if err != nil {
// log.Fatal(err)
// }
// fmt.Printf("网络资源 SHA-256: %s\n", hash)
}
示例 5:HMAC-SHA256(用于 API 签名)
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"log"
)
// HMACSHA256 计算 HMAC-SHA256 签名
func HMACSHA256(key, message []byte) []byte {
h := hmac.New(sha256.New, key)
h.Write(message)
return h.Sum(nil)
}
// HMACSHA256Hex 返回十六进制 HMAC-SHA256
func HMACSHA256Hex(key, message string) string {
return hex.EncodeToString(HMACSHA256([]byte(key), []byte(message)))
}
// HMACSHA256Base64 返回 Base64 编码的 HMAC-SHA256
func HMACSHA256Base64(key, message string) string {
return base64.StdEncoding.EncodeToString(HMACSHA256([]byte(key), []byte(message)))
}
// VerifyHMACSHA256 验证 HMAC-SHA256 签名
func VerifyHMACSHA256(key, message, signature []byte) bool {
expected := HMACSHA256(key, message)
return hmac.Equal(expected, signature)
}
func main() {
key := "my-secret-key"
message := "Hello, HMAC-SHA256!"
// 计算 HMAC
hexSig := HMACSHA256Hex(key, message)
b64Sig := HMACSHA256Base64(key, message)
fmt.Printf("消息:%s\n", message)
fmt.Printf("HMAC-SHA256(十六进制):%s\n", hexSig)
fmt.Printf("HMAC-SHA256(Base64):%s\n", b64Sig)
// 验证签名
sigBytes, _ := hex.DecodeString(hexSig)
if VerifyHMACSHA256([]byte(key), []byte(message), sigBytes) {
fmt.Println("✓ HMAC 验证成功")
} else {
log.Fatal("HMAC 验证失败")
}
}
示例 6:密码哈希(使用 bcrypt)
package main
import (
"crypto/sha256"
"fmt"
"log"
"golang.org/x/crypto/bcrypt"
)
// HashPassword 使用 bcrypt 哈希密码
func HashPassword(password string) (string, error) {
// 1. 先使用 SHA-256 处理密码(处理长密码)
hash := sha256.Sum256([]byte(password))
// 2. 使用 bcrypt 哈希
bytes, err := bcrypt.GenerateFromPassword(hash[:], bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(bytes), nil
}
// CheckPassword 验证密码
func CheckPassword(password, hash string) bool {
// 1. 先使用 SHA-256 处理密码
hash256 := sha256.Sum256([]byte(password))
// 2. 使用 bcrypt 验证
err := bcrypt.CompareHashAndPassword([]byte(hash), hash256[:])
return err == nil
}
func main() {
password := "my-secure-password"
// 哈希密码
hashed, err := HashPassword(password)
if err != nil {
log.Fatal(err)
}
fmt.Printf("哈希密码:%s\n", hashed)
// 验证正确密码
if CheckPassword(password, hashed) {
fmt.Println("✓ 密码验证成功")
} else {
fmt.Println("✗ 密码验证失败")
}
// 验证错误密码
if !CheckPassword("wrong-password", hashed) {
fmt.Println("✓ 错误密码被正确拒绝")
}
}
示例 7:默克尔树(Merkle Tree)节点哈希
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
// MerkleNode 默克尔树节点
type MerkleNode struct {
Left *MerkleNode
Right *MerkleNode
Hash string
}
// CalculateHash 计算节点哈希
func CalculateHash(data []byte) string {
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:])
}
// CombineHash 组合两个哈希
func CombineHash(left, right string) string {
// 解码十六进制
leftBytes, _ := hex.DecodeString(left)
rightBytes, _ := hex.DecodeString(right)
// 组合并哈希
combined := append(leftBytes, rightBytes...)
hash := sha256.Sum256(combined)
return hex.EncodeToString(hash[:])
}
// BuildMerkleTree 构建简单的默克尔树
func BuildMerkleTree(dataBlocks [][]byte) *MerkleNode {
if len(dataBlocks) == 0 {
return nil
}
// 创建叶子节点
nodes := make([]*MerkleNode, len(dataBlocks))
for i, block := range dataBlocks {
nodes[i] = &MerkleNode{
Hash: CalculateHash(block),
}
}
// 构建树
for len(nodes) > 1 {
newLevel := make([]*MerkleNode, 0, (len(nodes)+1)/2)
for i := 0; i < len(nodes); i += 2 {
node := &MerkleNode{
Left: nodes[i],
}
if i+1 < len(nodes) {
node.Right = nodes[i+1]
node.Hash = CombineHash(nodes[i].Hash, nodes[i+1].Hash)
} else {
// 奇数个节点,复制最后一个
node.Right = nodes[i]
node.Hash = CombineHash(nodes[i].Hash, nodes[i].Hash)
}
newLevel = append(newLevel, node)
}
nodes = newLevel
}
return nodes[0]
}
func main() {
// 创建数据块
blocks := [][]byte{
[]byte("交易 1"),
[]byte("交易 2"),
[]byte("交易 3"),
[]byte("交易 4"),
}
// 构建默克尔树
root := BuildMerkleTree(blocks)
fmt.Printf("默克尔根:%s\n", root.Hash)
// 验证叶子节点
fmt.Println("\n叶子节点哈希:")
for i, block := range blocks {
fmt.Printf("交易 %d: %s\n", i+1, CalculateHash(block))
}
}
示例 8:PBKDF2 密钥派生
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
"golang.org/x/crypto/pbkdf2"
)
// DeriveKey 使用 PBKDF2-SHA256 派生密钥
func DeriveKey(password, salt string, iterations, keyLen int) ([]byte, error) {
// 使用 PBKDF2-SHA256 派生密钥
key := pbkdf2.Key([]byte(password), []byte(salt), iterations, keyLen, sha256.New)
return key, nil
}
// GenerateSalt 生成随机盐
func GenerateSalt() ([]byte, error) {
salt := make([]byte, 16)
_, err := rand.Read(salt)
if err != nil {
return nil, err
}
return salt, nil
}
func main() {
password := "my-secure-password"
salt := "random-salt-value" // 实际应用中应使用随机盐
iterations := 100000
keyLen := 32 // 256 位密钥
// 派生密钥
key, err := DeriveKey(password, salt, iterations, keyLen)
if err != nil {
log.Fatal(err)
}
fmt.Printf("派生密钥(十六进制):%s\n", hex.EncodeToString(key))
fmt.Printf("密钥长度:%d 字节\n", len(key))
// 验证:相同的输入产生相同的密钥
key2, _ := DeriveKey(password, salt, iterations, keyLen)
if string(key) == string(key2) {
fmt.Println("✓ 密钥派生一致")
}
}
使用场景
✅ 推荐的安全用途
// ✅ 数字签名
import "crypto/sha256"
hash := sha256.Sum256(message)
signature, _ := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, hash[:])
// ✅ TLS 证书
// TLS 1.2/1.3 使用 SHA-256 进行签名
// ✅ 文件完整性校验
fileHash := CalculateFileSHA256("important.bin")
// ✅ 区块链
blockHash := sha256.Sum256(blockData)
// ✅ HMAC
h := hmac.New(sha256.New, key)
h.Write(message)
signature := h.Sum(nil)
// ✅ 密钥派生
key := pbkdf2.Key(password, salt, iterations, keyLen, sha256.New)
⚠️ 注意事项
// ⚠️ 密码存储:不要直接使用 SHA-256
// ❌ 错误
hash := sha256.Sum256([]byte(password)) // 不安全!
// ✅ 正确:使用 bcrypt 或 Argon2
import "golang.org/x/crypto/bcrypt"
hashed, _ := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
SHA-256 vs 其他哈希算法
SHA 系列对比
| 算法 | 输出长度 | 安全性 | 性能 | 推荐使用 |
|---|---|---|---|---|
| SHA-1 | 160 位(20 字节) | ❌ 已攻破 | 快 | ❌ 不推荐 |
| SHA-256 | 256 位(32 字节) | ✅ 安全 | 中等 | ✅ 推荐 |
| SHA-384 | 384 位(48 字节) | ✅ 安全 | 中等 | ✅ 高安全 |
| SHA-512 | 512 位(64 字节) | ✅ 安全 | 快(64 位系统) | ✅ 高安全 |
| SHA-3 | 可变 | ✅ 安全 | 较慢 | ✅ 最新标准 |
性能对比(相对速度)
MD5: 100%(最快,但不安全)
SHA-1: 85% (快,但不安全)
SHA-512: 75% (快,安全,64 位系统)
SHA-256: 60% (中等,安全)
SHA-3: 40% (较慢,最新标准)
硬件加速
- Intel/AMD:SHA 扩展指令集(SHA-NI)加速 SHA-256
- ARM:Crypto 扩展加速 SHA-256
- 无硬件加速:SHA-512 在 64 位系统上可能更快
安全最佳实践
✅ 推荐做法
-
使用 SHA-256 作为通用哈希
// ✅ 推荐 hash := sha256.Sum256(data) -
密码哈希使用专用算法
// ✅ 使用 bcrypt import "golang.org/x/crypto/bcrypt" hashed, _ := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) // ✅ 使用 Argon2 import "golang.org/x/crypto/argon2" hash := argon2.IDKey(password, salt, time, memory, threads, keyLen) -
HMAC 使用 SHA-256
// ✅ 推荐 import "crypto/hmac" import "crypto/sha256" h := hmac.New(sha256.New, key) -
密钥派生使用 PBKDF2-SHA256
// ✅ 推荐 import "golang.org/x/crypto/pbkdf2" key := pbkdf2.Key(password, salt, iterations, keyLen, sha256.New) // iterations >= 100000 -
使用足够的迭代次数
// ✅ 推荐:至少 100000 次迭代 iterations := 100000
❌ 不安全做法
-
不要直接用于密码存储
// ❌ 绝对不要 hash := sha256.Sum256([]byte(password)) -
不要使用过少的迭代次数
// ❌ 不安全 key := pbkdf2.Key(password, salt, 1000, 32, sha256.New) // 太少! // ✅ 正确 key := pbkdf2.Key(password, salt, 100000, 32, sha256.New) -
不要使用固定盐
// ❌ 不安全 salt := "fixed-salt" // ✅ 正确:使用随机盐 salt := make([]byte, 16) rand.Read(salt)
常见错误处理
1. 哈希比较错误
// ❌ 错误:使用 == 比较
if hash1 == hash2 { // 可能泄露时序信息
// ...
}
// ✅ 正确:使用 constant-time 比较
if hmac.Equal(hash1, hash2) {
// ...
}
2. 哈希截断错误
hash := sha256.Sum256(data)
// ❌ 错误:忘记转换为切片
fmt.Printf("%x\n", hash) // 正确
// fmt.Printf("%x\n", hash[:]) // 也可以
// ✅ 推荐:明确转换
fmt.Printf("%x\n", hash[:])
3. 增量哈希错误
h := sha256.New()
h.Write([]byte("part1"))
// ❌ 错误:在 Sum 后继续写入
hash1 := h.Sum(nil)
h.Write([]byte("part2")) // 这会改变状态
hash2 := h.Sum(nil) // 不是 part1+part2 的哈希
// ✅ 正确:使用副本或重新计算
h1 := sha256.New()
h1.Write([]byte("part1"))
hash1 := h1.Sum(nil)
h2 := sha256.New()
h2.Write([]byte("part1"))
h2.Write([]byte("part2"))
hash2 := h2.Sum(nil)
总结
核心 API
// 常量
const Size = 32 // 输出大小
const BlockSize = 64 // 块大小
// 一次性哈希
hash := sha256.Sum256(data)
// 增量哈希
h := sha256.New()
h.Write(data)
hash := h.Sum(nil)
// Go 1.21+ 推荐
hash := h.Sum256()
安全状态
| 用途 | SHA-256 状态 | 说明 |
|---|---|---|
| 密码哈希 | ⚠️ 需配合 bcrypt/Argon2 | 不直接使用 |
| 数字签名 | ✅ 推荐 | 广泛使用 |
| TLS 证书 | ✅ 推荐 | 标准配置 |
| 文件校验 | ✅ 推荐 | 安全可靠 |
| 区块链 | ✅ 推荐 | Bitcoin 等使用 |
| HMAC | ✅ 推荐 | 标准选择 |
| 密钥派生 | ✅ 推荐 | PBKDF2-SHA256 |
关键要点
- SHA-256 是安全的:目前未发现实际攻击
- 广泛应用:TLS、区块链、数字签名等
- 密码存储需专用算法:bcrypt、Argon2、scrypt
- 密钥派生使用 PBKDF2:足够的迭代次数
- HMAC 的标准选择:HMAC-SHA256
替代方案选择
| 需求 | 推荐算法 |
|---|---|
| 通用哈希 | SHA-256 |
| 高安全性 | SHA-384 或 SHA-512 |
| 密码存储 | bcrypt, Argon2, scrypt |
| HMAC | HMAC-SHA256 |
| 最新标准 | SHA-3 |
| 高性能 | BLAKE2, BLAKE3 |
| 64 位系统 | SHA-512(可能更快) |
参考资料
- FIPS 180-4 标准
- RFC 6234 - US Secure Hash Algorithms (SHA and SHA-based HMAC)
- NIST 特别出版物 800-131A
- Go crypto/sha256 包文档
- Go crypto/hmac 包文档
最后更新:2026-04-03
Go 版本:Go 1.23+
安全状态:✅ 推荐使用