crypto/sha512 - SHA-512 哈希算法
概述
crypto/sha512 包实现了 FIPS 180-4 定义的 SHA-512 哈希算法。
SHA-512(Secure Hash Algorithm 512)是一种密码学哈希函数,属于 SHA-2 家族,产生:
- 输出长度:512 位(64 字节)
- 十六进制表示:128 个字符
- 块大小:1024 位(128 字节)
主要特点:
- ✅ 高安全性:512 位输出,提供最高安全级别
- ✅ 64 位优化:在 64 位系统上性能优异
- ✅ 标准化:NIST、ISO 等标准组织推荐
- ✅ 广泛应用:高安全性需求的场景
主要用途:
- 🔐 高安全数字签名:政府、金融系统
- 📄 长期完整性保护:档案、法律文档
- 🔑 密钥派生:PBKDF2-SHA512
- 🏷️ HMAC:高安全消息认证码
- 💾 数据库密码存储:配合 salt 和迭代
常量和类型
1. 常量
const (
Size = 64 // SHA-512 输出大小(字节)
BlockSize = 128 // SHA-512 块大小(字节)
)
说明:
Size:SHA-512 哈希输出固定为 64 字节BlockSize:SHA-512 处理数据的块大小为 128 字节
2. Digest 类型
type Digest struct {
// 包含过滤或未导出的字段
}
功能:实现 hash.Hash 接口的 SHA-512 哈希计算器。
特点:
- 无状态(可复用)
- 支持增量哈希
- 实现
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) Sum512() [Size]byte // Go 1.21+
核心函数
1. New 函数
func New() hash.Hash
功能:创建一个新的 SHA-512 哈希计算器。
返回值:
hash.Hash:SHA-512 哈希实例
示例:
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
// 1. 创建哈希计算器
h := sha512.New()
// 2. 写入数据
data := []byte("Hello, SHA-512!")
h.Write(data)
// 3. 计算哈希
hash := h.Sum(nil)
fmt.Printf("SHA-512: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash))
}
输出:
SHA-512: a1b2c3d4e5f6...
十六进制:a1b2c3d4e5f6...
2. Sum512 函数
func Sum512(data []byte) [Size]byte
功能:计算数据的 SHA-512 哈希(一次性计算)。
参数:
data:要哈希的数据
返回值:
[64]byte:SHA-512 哈希数组
示例:
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
// 1. 准备数据
data := []byte("Hello, SHA-512!")
// 2. 计算哈希
hash := sha512.Sum512(data)
// 3. 输出结果
fmt.Printf("SHA-512: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash[:]))
// 4. 验证哈希长度
fmt.Printf("哈希长度:%d 字节\n", len(hash)) // 64 字节
}
3. Sum512 方法(Go 1.21+)
func (d *Digest) Sum512() [Size]byte
功能:返回当前哈希状态的 64 字节数组。
优势:
- 避免切片分配
- 返回数组类型,更安全
- Go 1.21+ 推荐使用
示例:
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
h := sha512.New()
h.Write([]byte("Hello, SHA-512!"))
// 使用 Sum512(Go 1.21+)
hash := h.Sum512()
fmt.Printf("SHA-512: %x\n", hash)
fmt.Printf("十六进制:%s\n", hex.EncodeToString(hash[:]))
}
SHA-512/224 和 SHA-512/256
SHA-512 还定义了两种截断变体:
SHA-512/224
func New512_224() hash.Hash
特点:
- 输出:224 位(28 字节)
- 使用 SHA-512 内部实现
- 比 SHA-224 更快(在 64 位系统上)
SHA-512/256
func New512_256() hash.Hash
特点:
- 输出:256 位(32 字节)
- 使用 SHA-512 内部实现
- 比 SHA-256 更快(在 64 位系统上)
示例:
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
data := []byte("Hello, SHA-512/256!")
// SHA-512/256
h := sha512.New512_256()
h.Write(data)
hash256 := h.Sum(nil)
fmt.Printf("SHA-512/256: %x\n", hash256)
fmt.Printf("长度:%d 字节\n", len(hash256)) // 32 字节
// SHA-512/224
h224 := sha512.New512_224()
h224.Write(data)
hash224 := h224.Sum(nil)
fmt.Printf("SHA-512/224: %x\n", hash224)
fmt.Printf("长度:%d 字节\n", len(hash224)) // 28 字节
}
完整示例代码
示例 1:基本哈希计算
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
func main() {
// 方法 1:使用 Sum512 函数(一次性)
data1 := []byte("Hello, SHA-512!")
hash1 := sha512.Sum512(data1)
fmt.Printf("方法 1: %x\n", hash1)
// 方法 2:使用 New() + Write() + Sum()(增量)
h := sha512.New()
h.Write([]byte("Hello, "))
h.Write([]byte("SHA-512!"))
hash2 := h.Sum(nil)
fmt.Printf("方法 2: %x\n", hash2)
// 方法 3:使用 Sum512(Go 1.21+)
h.Reset()
h.Write([]byte("Hello, SHA-512!"))
hash3 := h.Sum512()
fmt.Printf("方法 3: %x\n", hash3)
// 验证结果一致
if string(hash1[:]) == string(hash2) && string(hash2) == string(hash3[:]) {
fmt.Println("✓ 所有方法结果一致")
}
}
示例 2:文件哈希计算
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
"io"
"log"
"os"
)
// CalculateFileSHA512 计算文件的 SHA-512 哈希
func CalculateFileSHA512(filename string) (string, error) {
// 1. 打开文件
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
// 2. 创建哈希计算器
h := sha512.New()
// 3. 流式读取文件
if _, err := io.Copy(h, file); err != nil {
return "", err
}
// 4. 返回十六进制哈希
return hex.EncodeToString(h.Sum(nil)), nil
}
// CalculateFileSHA512Buffered 使用缓冲区计算文件哈希
func CalculateFileSHA512Buffered(filename string) (string, error) {
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
h := sha512.New()
buffer := make([]byte, 64*1024) // 64KB 缓冲区(更大以匹配块大小)
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 := CalculateFileSHA512("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("文件 SHA-512: %s\n", hash)
fmt.Printf("哈希长度:%d 字符\n", len(hash)) // 128 字符
// 验证
hash2, err := CalculateFileSHA512Buffered("test.txt")
if err != nil {
log.Fatal(err)
}
if hash == hash2 {
fmt.Println("✓ 文件哈希计算一致")
}
}
示例 3:字符串哈希工具函数
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
// SHA512String 计算字符串的 SHA-512 哈希(十六进制)
func SHA512String(s string) string {
hash := sha512.Sum512([]byte(s))
return hex.EncodeToString(hash[:])
}
// SHA512Bytes 计算字节切片的 SHA-512 哈希(十六进制)
func SHA512Bytes(data []byte) string {
hash := sha512.Sum512(data)
return hex.EncodeToString(hash[:])
}
// SHA512Binary 计算字符串的 SHA-512 哈希(二进制)
func SHA512Binary(s string) []byte {
hash := sha512.Sum512([]byte(s))
return hash[:]
}
// SHA512Formatted 计算格式化的 SHA-512 哈希(带冒号分隔)
func SHA512Formatted(s string) string {
hash := sha512.Sum512([]byte(s))
hexStr := hex.EncodeToString(hash[:])
// 格式化为 xx:xx:xx:xx...
result := make([]byte, 0, 191)
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-512!"
// 基本哈希
fmt.Printf("输入:%s\n", input)
fmt.Printf("SHA-512: %s\n", SHA512String(input))
fmt.Printf("长度:%d 字符\n", len(SHA512String(input))) // 128 字符
// 二进制哈希
binary := SHA512Binary(input)
fmt.Printf("二进制长度:%d 字节\n", len(binary)) // 64 字节
// 格式化输出
fmt.Printf("格式化:%s\n", SHA512Formatted(input))
// 多次哈希
hash1 := SHA512String(input)
hash2 := SHA512String(hash1)
hash3 := SHA512String(hash2)
fmt.Printf("哈希 1: %s\n", hash1)
fmt.Printf("哈希 2: %s\n", hash2)
fmt.Printf("哈希 3: %s\n", hash3)
}
示例 4:HMAC-SHA512(高安全 API 签名)
package main
import (
"crypto/hmac"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"fmt"
"log"
)
// HMACSHA512 计算 HMAC-SHA512 签名
func HMACSHA512(key, message []byte) []byte {
h := hmac.New(sha512.New, key)
h.Write(message)
return h.Sum(nil)
}
// HMACSHA512Hex 返回十六进制 HMAC-SHA512
func HMACSHA512Hex(key, message string) string {
return hex.EncodeToString(HMACSHA512([]byte(key), []byte(message)))
}
// HMACSHA512Base64 返回 Base64 编码的 HMAC-SHA512
func HMACSHA512Base64(key, message string) string {
return base64.StdEncoding.EncodeToString(HMACSHA512([]byte(key), []byte(message)))
}
// VerifyHMACSHA512 验证 HMAC-SHA512 签名
func VerifyHMACSHA512(key, message, signature []byte) bool {
expected := HMACSHA512(key, message)
return hmac.Equal(expected, signature)
}
func main() {
key := "my-secret-key-for-high-security"
message := "Hello, HMAC-SHA512!"
// 计算 HMAC
hexSig := HMACSHA512Hex(key, message)
b64Sig := HMACSHA512Base64(key, message)
fmt.Printf("消息:%s\n", message)
fmt.Printf("HMAC-SHA512(十六进制):%s\n", hexSig)
fmt.Printf("HMAC-SHA512(Base64):%s\n", b64Sig)
fmt.Printf("签名长度:%d 字节\n", len(hex.DecodeString(hexSig))) // 64 字节
// 验证签名
sigBytes, _ := hex.DecodeString(hexSig)
if VerifyHMACSHA512([]byte(key), []byte(message), sigBytes) {
fmt.Println("✓ HMAC 验证成功")
} else {
log.Fatal("HMAC 验证失败")
}
}
示例 5:密码哈希(使用 bcrypt + SHA512)
package main
import (
"crypto/sha512"
"fmt"
"log"
"golang.org/x/crypto/bcrypt"
)
// HashPassword 使用 bcrypt + SHA-512 哈希密码
func HashPassword(password string) (string, error) {
// 1. 先使用 SHA-512 处理密码(处理长密码,提供固定长度输入)
hash := sha512.Sum512([]byte(password))
// 2. 使用 bcrypt 哈希(成本因子 12)
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-512 处理密码
hash512 := sha512.Sum512([]byte(password))
// 2. 使用 bcrypt 验证
err := bcrypt.CompareHashAndPassword([]byte(hash), hash512[:])
return err == nil
}
func main() {
password := "my-very-secure-password"
// 哈希密码
hashed, err := HashPassword(password)
if err != nil {
log.Fatal(err)
}
fmt.Printf("哈希密码:%s\n", hashed)
// 验证正确密码
if CheckPassword(password, hashed) {
fmt.Println("✓ 密码验证成功")
}
// 验证错误密码
if !CheckPassword("wrong-password", hashed) {
fmt.Println("✓ 错误密码被正确拒绝")
}
}
示例 6:PBKDF2-SHA512 密钥派生
package main
import (
"crypto/rand"
"crypto/sha512"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
"log"
"golang.org/x/crypto/pbkdf2"
)
// GenerateSalt 生成随机盐
func GenerateSalt(length int) ([]byte, error) {
salt := make([]byte, length)
_, err := io.ReadFull(rand.Reader, salt)
if err != nil {
return nil, err
}
return salt, nil
}
// DeriveKey 使用 PBKDF2-SHA512 派生密钥
func DeriveKey(password, salt []byte, iterations, keyLen int) []byte {
return pbkdf2.Key(password, salt, iterations, keyLen, sha512.New)
}
// HashPasswordPBKDF2 使用 PBKDF2-SHA512 哈希密码
func HashPasswordPBKDF2(password string) (string, error) {
// 1. 生成随机盐
salt, err := GenerateSalt(16)
if err != nil {
return "", err
}
// 2. 派生密钥(使用 100000 次迭代)
iterations := 100000
keyLen := 32 // 256 位密钥
key := DeriveKey([]byte(password), salt, iterations, keyLen)
// 3. 返回 salt:key 的 Base64 编码
result := append(salt, key...)
return base64.StdEncoding.EncodeToString(result), nil
}
// VerifyPasswordPBKDF2 验证 PBKDF2 密码
func VerifyPasswordPBKDF2(password, storedHash string) bool {
// 1. 解码存储的哈希
data, err := base64.StdEncoding.DecodeString(storedHash)
if err != nil {
return false
}
// 2. 提取 salt 和 key
salt := data[:16]
storedKey := data[16:]
// 3. 重新派生密钥
iterations := 100000
keyLen := 32
key := DeriveKey([]byte(password), salt, iterations, keyLen)
// 4. 比较密钥
return hmac.Equal(key, storedKey)
}
func main() {
password := "my-secure-password"
// 哈希密码
hashed, err := HashPasswordPBKDF2(password)
if err != nil {
log.Fatal(err)
}
fmt.Printf("PBKDF2 哈希:%s\n", hashed)
// 验证正确密码
if VerifyPasswordPBKDF2(password, hashed) {
fmt.Println("✓ 密码验证成功")
}
// 验证错误密码
if !VerifyPasswordPBKDF2("wrong-password", hashed) {
fmt.Println("✓ 错误密码被正确拒绝")
}
}
示例 7:大文件完整性校验
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
"io"
"log"
"os"
"path/filepath"
)
// FileHash 文件哈希信息
type FileHash struct {
Path string
Hash string
Size int64
}
// CalculateFileHash 计算文件 SHA-512 哈希
func CalculateFileHash(path string) (*FileHash, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
stat, err := file.Stat()
if err != nil {
return nil, err
}
h := sha512.New()
if _, err := io.Copy(h, file); err != nil {
return nil, err
}
return &FileHash{
Path: path,
Hash: hex.EncodeToString(h.Sum(nil)),
Size: stat.Size(),
}, nil
}
// CalculateDirectoryHashes 计算目录下所有文件的哈希
func CalculateDirectoryHashes(dir string) ([]*FileHash, error) {
var hashes []*FileHash
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
hash, err := CalculateFileHash(path)
if err != nil {
log.Printf("警告:无法计算 %s 的哈希:%v", path, err)
return nil
}
hashes = append(hashes, hash)
fmt.Printf("✓ %s: %s... (%d 字节)\n",
path, hash.Hash[:16], hash.Size)
}
return nil
})
return hashes, err
}
// SaveHashes 保存哈希到文件
func SaveHashes(hashes []*FileHash, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
for _, h := range hashes {
_, err := fmt.Fprintf(file, "%s %s\n", h.Hash, h.Path)
if err != nil {
return err
}
}
return nil
}
func main() {
// 创建测试文件
os.MkdirAll("testdir", 0755)
os.WriteFile("testdir/file1.txt", []byte("内容 1"), 0644)
os.WriteFile("testdir/file2.txt", []byte("内容 2"), 0644)
// 计算目录哈希
hashes, err := CalculateDirectoryHashes("testdir")
if err != nil {
log.Fatal(err)
}
fmt.Printf("\n共计算 %d 个文件的哈希\n", len(hashes))
// 保存哈希
err = SaveHashes(hashes, "checksums.sha512")
if err != nil {
log.Fatal(err)
}
fmt.Println("✓ 哈希已保存到 checksums.sha512")
}
示例 8:数据完整性验证链
package main
import (
"crypto/sha512"
"encoding/hex"
"fmt"
)
// Block 数据块
type Block struct {
Index int
Data string
PrevHash string
Hash string
}
// CalculateHash 计算块哈希
func CalculateHash(index int, data, prevHash string) string {
input := fmt.Sprintf("%d%s%s", index, data, prevHash)
hash := sha512.Sum512([]byte(input))
return hex.EncodeToString(hash[:])
}
// CreateGenesisBlock 创建创世块
func CreateGenesisBlock() *Block {
block := &Block{
Index: 0,
Data: "Genesis Block",
PrevHash: "0",
}
block.Hash = CalculateHash(block.Index, block.Data, block.PrevHash)
return block
}
// CreateNewBlock 创建新块
func CreateNewBlock(prevBlock *Block, data string) *Block {
block := &Block{
Index: prevBlock.Index + 1,
Data: data,
PrevHash: prevBlock.Hash,
}
block.Hash = CalculateHash(block.Index, block.Data, block.PrevHash)
return block
}
// VerifyChain 验证链完整性
func VerifyChain(blocks []*Block) bool {
for i := 1; i < len(blocks); i++ {
block := blocks[i]
prevBlock := blocks[i-1]
// 验证前驱哈希
if block.PrevHash != prevBlock.Hash {
fmt.Printf("✗ 块 %d 的前驱哈希不匹配\n", block.Index)
return false
}
// 验证当前哈希
expectedHash := CalculateHash(block.Index, block.Data, block.PrevHash)
if block.Hash != expectedHash {
fmt.Printf("✗ 块 %d 的哈希不匹配\n", block.Index)
return false
}
}
return true
}
func main() {
// 创建区块链
blocks := make([]*Block, 0)
// 创世块
genesis := CreateGenesisBlock()
blocks = append(blocks, genesis)
fmt.Printf("创世块:%s...\n", genesis.Hash[:16])
// 添加数据块
blocks = append(blocks, CreateNewBlock(genesis, "交易 1"))
blocks = append(blocks, CreateNewBlock(blocks[1], "交易 2"))
blocks = append(blocks, CreateNewBlock(blocks[2], "交易 3"))
fmt.Printf("\n区块链长度:%d\n", len(blocks))
// 验证链
if VerifyChain(blocks) {
fmt.Println("✓ 区块链完整性验证通过")
} else {
fmt.Println("✗ 区块链完整性验证失败")
}
}
使用场景
✅ 推荐的安全用途
// ✅ 高安全数字签名
import "crypto/sha512"
hash := sha512.Sum512(message)
signature, _ := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA512, hash[:])
// ✅ 长期完整性保护
fileHash := CalculateFileSHA512("important-document.pdf")
// ✅ HMAC(高安全)
h := hmac.New(sha512.New, key)
h.Write(message)
signature := h.Sum(nil)
// ✅ 密钥派生
key := pbkdf2.Key(password, salt, iterations, keyLen, sha512.New)
// ✅ 密码存储(配合 bcrypt)
hash := sha512.Sum512([]byte(password))
bcryptHash, _ := bcrypt.GenerateFromPassword(hash[:], cost)
⚠️ 注意事项
// ⚠️ 密码存储:不要直接使用 SHA-512
// ❌ 错误
hash := sha512.Sum512([]byte(password)) // 不安全!
// ✅ 正确:使用 bcrypt 或 Argon2
import "golang.org/x/crypto/bcrypt"
hashed, _ := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
SHA-512 vs 其他哈希算法
SHA 系列对比
| 算法 | 输出长度 | 安全性 | 性能(64 位) | 性能(32 位) | 推荐使用 |
|---|---|---|---|---|---|
| SHA-1 | 160 位(20 字节) | ❌ 已攻破 | 快 | 快 | ❌ 不推荐 |
| SHA-256 | 256 位(32 字节) | ✅ 安全 | 中等 | 中等 | ✅ 通用 |
| SHA-384 | 384 位(48 字节) | ✅ 安全 | 中等 | 中等 | ✅ 高安全 |
| SHA-512 | 512 位(64 字节) | ✅ 安全 | 快 | 慢 | ✅ 高安全(64 位) |
| SHA-3 | 可变 | ✅ 安全 | 较慢 | 较慢 | ✅ 最新标准 |
性能对比(相对速度)
64 位系统:
SHA-512: 100%(最快,安全)
SHA-256: 70%
SHA-3: 50%
32 位系统:
SHA-256: 100%
SHA-512: 50%(64 位运算在 32 位系统上较慢)
SHA-3: 40%
安全级别对比
| 算法 | 抗碰撞性 | 原像抗性 | 第二原像抗性 |
|---|---|---|---|
| SHA-256 | 128 位 | 256 位 | 256 位 |
| SHA-384 | 192 位 | 384 位 | 384 位 |
| SHA-512 | 256 位 | 512 位 | 512 位 |
安全最佳实践
✅ 推荐做法
-
在 64 位系统上使用 SHA-512
// ✅ 64 位系统推荐 hash := sha512.Sum512(data) -
密码哈希使用专用算法
// ✅ 使用 bcrypt + SHA-512 hash := sha512.Sum512([]byte(password)) hashed, _ := bcrypt.GenerateFromPassword(hash[:], bcrypt.DefaultCost) // ✅ 使用 PBKDF2-SHA512 key := pbkdf2.Key(password, salt, 100000, 32, sha512.New) -
HMAC 使用 SHA-512(高安全需求)
// ✅ 推荐(高安全) h := hmac.New(sha512.New, key) -
使用足够的迭代次数
// ✅ 推荐:至少 100000 次迭代 iterations := 100000 key := pbkdf2.Key(password, salt, iterations, keyLen, sha512.New) -
使用随机盐
// ✅ 正确:使用随机盐 salt := make([]byte, 16) rand.Read(salt)
❌ 不安全做法
-
不要直接用于密码存储
// ❌ 绝对不要 hash := sha512.Sum512([]byte(password)) -
不要在 32 位系统上过度使用
// ⚠️ 32 位系统上 SHA-512 较慢 // 考虑使用 SHA-256 -
不要使用过少的迭代次数
// ❌ 不安全 key := pbkdf2.Key(password, salt, 1000, 32, sha512.New) // 太少! // ✅ 正确 key := pbkdf2.Key(password, salt, 100000, 32, sha512.New)
常见错误处理
1. 哈希比较错误
// ❌ 错误:使用 == 比较
if hash1 == hash2 { // 可能泄露时序信息
// ...
}
// ✅ 正确:使用 constant-time 比较
if hmac.Equal(hash1, hash2) {
// ...
}
2. 哈希截断错误
hash := sha512.Sum512(data)
// ✅ 推荐:明确转换
fmt.Printf("%x\n", hash[:])
3. 增量哈希错误
h := sha512.New()
h.Write([]byte("part1"))
// ❌ 错误:在 Sum 后继续写入
hash1 := h.Sum(nil)
h.Write([]byte("part2")) // 这会改变状态
hash2 := h.Sum(nil) // 不是 part1+part2 的哈希
// ✅ 正确:使用副本或重新计算
h1 := sha512.New()
h1.Write([]byte("part1"))
hash1 := h1.Sum(nil)
h2 := sha512.New()
h2.Write([]byte("part1"))
h2.Write([]byte("part2"))
hash2 := h2.Sum(nil)
总结
核心 API
// 常量
const Size = 64 // 输出大小
const BlockSize = 128 // 块大小
// 一次性哈希
hash := sha512.Sum512(data)
// 增量哈希
h := sha512.New()
h.Write(data)
hash := h.Sum(nil)
// Go 1.21+ 推荐
hash := h.Sum512()
// 变体
h224 := sha512.New512_224() // SHA-512/224
h256 := sha512.New512_256() // SHA-512/256
安全状态
| 用途 | SHA-512 状态 | 说明 |
|---|---|---|
| 密码哈希 | ⚠️ 需配合 bcrypt/Argon2 | 不直接使用 |
| 数字签名 | ✅ 推荐(高安全) | 政府、金融系统 |
| TLS 证书 | ✅ 可用 | SHA-384 更常见 |
| 文件校验 | ✅ 推荐 | 长期完整性 |
| HMAC | ✅ 推荐(高安全) | 512 位输出 |
| 密钥派生 | ✅ 推荐 | PBKDF2-SHA512 |
| 区块链 | ✅ 可用 | 高安全需求 |
关键要点
- SHA-512 提供最高安全级别:512 位输出,256 位抗碰撞性
- 64 位系统性能优异:比 SHA-256 更快
- 32 位系统性能较差:考虑使用 SHA-256
- 密码存储需专用算法:bcrypt、Argon2、PBKDF2
- 适合长期完整性保护:档案、法律文档
替代方案选择
| 需求 | 推荐算法 |
|---|---|
| 通用哈希(64 位) | SHA-512 |
| 通用哈希(32 位) | SHA-256 |
| 高安全性 | SHA-512 或 SHA-384 |
| 密码存储 | bcrypt, Argon2, scrypt |
| HMAC | HMAC-SHA512 |
| 最新标准 | SHA-3 |
| 平衡性能和安全 | SHA-256 |
参考资料
- FIPS 180-4 标准
- RFC 6234 - US Secure Hash Algorithms (SHA and SHA-based HMAC)
- NIST 特别出版物 800-131A
- Go crypto/sha512 包文档
- Go crypto/hmac 包文档
最后更新:2026-04-03
Go 版本:Go 1.23+
安全状态:✅ 推荐使用(64 位系统)