Golang中如何从结构体生成SHA256哈希

Golang中如何从结构体生成SHA256哈希 我有一个结构体,它输出两个 math/big 数字,例如 {111169861534908786450528219480688090365166902692935576283050714991761558678040 88379901547641513630174298532615870317238075620523861278786581687498037788537}。

我需要获取这个结构体的 SHA256 哈希值。我在网上看到了几个例子,但没有找到任何在不导入外部库的情况下能产生可靠结果的方法。有人能帮我解决这个问题吗?谢谢

4 回复

SHA256 是通过对一系列字节进行计算得出的。你需要决定如何编码你的数字,然后对该编码的结果计算哈希值。

更多关于Golang中如何从结构体生成SHA256哈希的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


严格来说,它是一个字节切片([]byte)。

此外,Sum() 方法并不是那样工作的。h 是一个写入器,你需要将数据写入其中,最后调用 h.Sum(nil)(是的,我也不喜欢这个接口)来获取 32 字节长的哈希值。

然后你可以将其进行 base16 编码,得到你熟悉的 64 字符字符串。

好的,我尝试了以下方法:

h := sha256.New()
s := fmt.Sprintf("%v", struct)
sum := h.Sum([]byte(s))
fmt.Println(sum)

但结果看起来像这样:

[123 51 49 54 54 49 57 54 54 52 49 48 49 49 55 54 52 57 57 53 56 50 54 56 48 51 53 52 51 57 50 52 52 48 49 54 50 54 48 55 54 51 51 49 56 57 55 49 50 48 55 57 57 57 48 54 50 57 55 52 55 53 51 54 48 52 54 53 55 52 51 
55 55 56 48 53 52 52 32 51 54 52 50 50 49 56 56 55 54 54 55 57 57 51 52 55 55 57 49 54 54 51 53 57 56 56 56 56 56 50 56 52 56 48 52 50 51 53 55 57 52 56 53 49 55 48 54 57 57 52 53 51 49 51 56 56 55 49 53 57 56 50 49 52 54 50 48 50 52 54 51 56 52 54 54 49 125 227 176 196 66 152 252 28 20 154 251 244 200 153 111 185 36 39 174 65 228 100 155 147 76 164 149 153 27 120 82 184 85]

这是一个无符号整数的数组…

在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[:]))
}

注意事项

  1. 序列化一致性:确保始终使用相同的序列化方法,否则哈希值会不同
  2. big.Int处理:big.Int可能包含符号,使用Bytes()方法获取无符号字节表示
  3. 边界分隔:在序列化多个字段时,需要添加边界分隔符或长度前缀

这些方法都不需要外部库,完全使用Go标准库实现。方法3(自定义序列化)通常是最可靠的选择,因为它明确控制了序列化格式。

回到顶部