Golang中如何从结构体生成SHA256哈希
Golang中如何从结构体生成SHA256哈希 我有一个结构体,它输出两个 math/big 数字,例如 {111169861534908786450528219480688090365166902692935576283050714991761558678040 88379901547641513630174298532615870317238075620523861278786581687498037788537}。
我需要获取这个结构体的 SHA256 哈希值。我在网上看到了几个例子,但没有找到任何在不导入外部库的情况下能产生可靠结果的方法。有人能帮我解决这个问题吗?谢谢
SHA256 是通过对一系列字节进行计算得出的。你需要决定如何编码你的数字,然后对该编码的结果计算哈希值。
更多关于Golang中如何从结构体生成SHA256哈希的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
严格来说,它是一个字节切片([]byte)。
此外,Sum() 方法并不是那样工作的。h 是一个写入器,你需要将数据写入其中,最后调用 h.Sum(nil)(是的,我也不喜欢这个接口)来获取 32 字节长的哈希值。
然后你可以将其进行 base16 编码,得到你熟悉的 64 字符字符串。
在Go中从结构体生成SHA256哈希,可以通过序列化结构体数据来实现。以下是几种可靠的方法:
方法1:使用encoding/binary(适用于固定大小数字)
package main
import (
"crypto/sha256"
"encoding/binary"
"fmt"
"math/big"
)
type MyStruct struct {
Num1 *big.Int
Num2 *big.Int
}
func hashStructBinary(s MyStruct) [32]byte {
// 获取big.Int的字节表示
num1Bytes := s.Num1.Bytes()
num2Bytes := s.Num2.Bytes()
// 创建缓冲区并写入数据
totalLen := 8 + len(num1Bytes) + 8 + len(num2Bytes) // 8字节存储长度
buf := make([]byte, totalLen)
offset := 0
binary.BigEndian.PutUint64(buf[offset:], uint64(len(num1Bytes)))
offset += 8
copy(buf[offset:], num1Bytes)
offset += len(num1Bytes)
binary.BigEndian.PutUint64(buf[offset:], uint64(len(num2Bytes)))
offset += 8
copy(buf[offset:], num2Bytes)
return sha256.Sum256(buf)
}
方法2:使用encoding/gob(通用方法)
import (
"bytes"
"crypto/sha256"
"encoding/gob"
"math/big"
)
func hashStructGob(s MyStruct) ([32]byte, error) {
var buf bytes.Buffer
encoder := gob.NewEncoder(&buf)
// 注册big.Int类型
gob.Register(&big.Int{})
if err := encoder.Encode(s); err != nil {
return [32]byte{}, err
}
return sha256.Sum256(buf.Bytes()), nil
}
方法3:自定义序列化(推荐用于big.Int)
func hashStructCustom(s MyStruct) [32]byte {
h := sha256.New()
// 写入第一个数字
num1Bytes := s.Num1.Bytes()
h.Write([]byte{byte(len(num1Bytes))})
h.Write(num1Bytes)
// 写入第二个数字
num2Bytes := s.Num2.Bytes()
h.Write([]byte{byte(len(num2Bytes))})
h.Write(num2Bytes)
var hash [32]byte
copy(hash[:], h.Sum(nil))
return hash
}
完整示例
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
)
func main() {
// 创建示例结构体
num1, _ := new(big.Int).SetString("111169861534908786450528219480688090365166902692935576283050714991761558678040", 10)
num2, _ := new(big.Int).SetString("88379901547641513630174298532615870317238075620523861278786581687498037788537", 10)
myStruct := MyStruct{
Num1: num1,
Num2: num2,
}
// 使用方法1
hash1 := hashStructBinary(myStruct)
fmt.Printf("Binary hash: %s\n", hex.EncodeToString(hash1[:]))
// 使用方法3
hash3 := hashStructCustom(myStruct)
fmt.Printf("Custom hash: %s\n", hex.EncodeToString(hash3[:]))
}
注意事项
- 序列化一致性:确保始终使用相同的序列化方法,否则哈希值会不同
- big.Int处理:big.Int可能包含符号,使用
Bytes()方法获取无符号字节表示 - 边界分隔:在序列化多个字段时,需要添加边界分隔符或长度前缀
这些方法都不需要外部库,完全使用Go标准库实现。方法3(自定义序列化)通常是最可靠的选择,因为它明确控制了序列化格式。


