Golang – 打包和哈希二进制数据

huangapple go评论77阅读模式
英文:

Golang - Packing and hashing binary data

问题

我正在尝试学习Golang,并且有Python的背景。我目前正在努力理解如何将变量打包成二进制格式(带有校验和)。在Python中,我会使用类似以下的代码:

import struct
import hashlib

a = 100
b = "foo\x00\x00"  # 填充到固定长度
packet = struct.pack('<B5s', a, b)
digest = hashlib.sha256(packet).digest()
packet += digest

为了在Go中实现相同的功能,我尝试了以下代码:

package main

import (
    "crypto/sha256"
    "fmt"
    "encoding/binary"
    "bytes"
)

type packet struct {
    a uint8
    b string
}

func main() {
    var p = packet{}
    p.a = 1
    p.b = "foo\x00\x00"
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.LittleEndian, &p)
    h := sha256.New()
    h.Write(buf.Bytes())
    fmt.Printf("% x\n", p)
}

然而,不幸的是,无论我如何尝试,似乎都陷入了变量类型冲突的噩梦(缓冲区、字节数组和字符串)。我希望能得到一些指导,看看我是否采取了正确的方法。

英文:

I'm attempting to learn Golang and have a background in Python. I'm currently trying to get my head around how to pack variables into a binary format (with a checksum). In Python I'd use something like:

import struct
import hashlib

a = 100
b = &quot;foo\x00\x00&quot;  # Padded to fixed length
packet = struct.pack(&#39;&lt;B5s&#39;, a, b)
digest = hashlib.sha256(packet).digest()
packet += digest

To do the same thing in Go, I'm trying code like this:

package main

import (
    &quot;crypto/sha256&quot;
    &quot;fmt&quot;
    &quot;encoding/binary&quot;
    &quot;bytes&quot;
)

type packet struct {
    a uint8
    b string
}

func main() {
    var p = packet{}
    p.a = 1
    p.b = &quot;foo\x00\x00&quot;
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.LittleEndian, &amp;p)
    h := sha256.New()
    h.Write(buf.String())
    fmt.Printf(&quot;% x\n&quot;, p)
}

Unfortunately, however I attack it I seem to get into a nightmare of clashing variable types (buffers, byte arrays and strings). I'd appreciate some guidance as to whether I'm taking even remotely the right approach.

答案1

得分: 5

更新为可工作的代码。

package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"fmt"
)

type packet struct {
	a uint8
	b []byte
}

func main() {
	var p = packet{}
	p.a = 1
	p.b = []byte("foo\x00\x00")
	buf := bytes.Buffer{}
	err := binary.Write(&buf, binary.BigEndian, p.a)
	if err != nil {
		fmt.Println(err)
	}
	_, err = buf.Write(p.b)
	if err != nil {
		fmt.Println(err)
	}
	h := sha256.New()
	h.Write(buf.Bytes())
	hash := h.Sum([]byte{})
	fmt.Printf("% x\n", hash)
}

你是对的,使用encoding/binary在结构体中写入可能具有动态长度的项(切片和字符串)确实有些麻烦。你可能会对查看"encoding/gob"包感兴趣,它可以自动编码字符串(尽管它与你这里的填充字符串不兼容)。

英文:

Updated to something that works.

package main

import (
   &quot;bytes&quot;
   &quot;crypto/sha256&quot;
   &quot;encoding/binary&quot;
   &quot;fmt&quot;
)

type packet struct {
   a uint8
   b []byte
}

func main() {
   var p = packet{}
   p.a = 1
   p.b = []byte(&quot;foo\x00\x00&quot;)
   buf := bytes.Buffer{}
   err := binary.Write(&amp;buf, binary.BigEndian, p.a)
   if err != nil {
	   fmt.Println(err)
   }
   _, err = buf.Write(p.b)
   if err != nil {
	   fmt.Println(err)
   }
   h := sha256.New()
   h.Write(buf.Bytes())
   hash := h.Sum([]byte{})
   fmt.Printf(&quot;% x\n&quot;, hash)
}

http://play.golang.org/p/t8ltu_WCpe

You're right that it's a bit painful to write structs with possibly dynamic length items in them (slices and strings) using encoding/binary. You might be interested in checking out the "encoding/gob" package that encodes strings automatically (although it isn't compatible with the padded string you've got here).

huangapple
  • 本文由 发表于 2014年1月4日 23:07:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/20922598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定