Skip to content

Instantly share code, notes, and snippets.

@lordofscripts
Created July 23, 2024 14:48
Show Gist options
  • Save lordofscripts/2b8fdfbb37e6c93484b6c8e5ab736618 to your computer and use it in GitHub Desktop.
Save lordofscripts/2b8fdfbb37e6c93484b6c8e5ab736618 to your computer and use it in GitHub Desktop.
Using Go-Restruct for Binary serialization fails
// You can edit this code!
// Click here and start typing.
// Go-Restruct/restruct (v1.2) appears to serialize well but deserialization doesn't retrieve what I put there.
package main
import (
"encoding/binary"
"encoding/hex"
"fmt"
"log"
"github.com/creker/hashstructure"
"github.com/go-restruct/restruct"
)
type Share struct {
Field1 string
Field2 uint64
Field3 float64
}
type Container struct {
Len byte
Hash string
Data *Share
}
func (b *Container) Serialize() []byte {
hash, err := b.calculateHash()
if err != nil {
log.Fatal("Serialize Hash", err)
}
b.Len = byte(len(hash))
b.Hash = hex.EncodeToString(hash)
data, err := restruct.Pack(binary.BigEndian, b)
if err != nil {
log.Fatal(err)
}
return data
}
func (b *Container) Deserialize(data []byte) error {
// (A) Before it was just b but it was failing. I then tried this newC alternative to confirm that something is wrong
newC := Container{0, "", nil} // (A)
if err := restruct.Unpack(data, binary.BigEndian, &newC); err != nil { // (A)
log.Fatal(err)
}
fmt.Println("Recovered", newC.String())
b.Len = newC.Len // (A)
b.Hash = newC.Hash // (A)
b.Data = newC.Data // (A)
hash, err := b.calculateHash()
if err != nil {
log.Fatal("Deserialize Hash", err)
}
rhash := hex.EncodeToString(hash)
if rhash != b.Hash {
err := fmt.Errorf("Corrupted! %s != %s", b.Hash, rhash)
log.Fatal(err)
return err
}
return nil
}
func (b *Container) calculateHash() ([]byte, error) {
var hash []byte
var err error
hash, err = hashstructure.Hash(b.Data, hashstructure.FormatV2, nil)
if err != nil {
return nil, err
}
return hash, nil
}
func (b *Container) String() string {
return fmt.Sprintf("Container\n\tL: %d\n\tH: %s\n\t%s\n", b.Len, b.Hash, b.Data)
}
func (s Share) String() string {
return fmt.Sprintf("F1: %s F2: %d F3: %f", s.Field1, s.Field2, s.Field3)
}
func NewContainer(share *Share) *Container {
return &Container{0, "", share}
}
func main() {
fmt.Println("Hello, 世界")
share1 := Share{"Share #1", 854697, 4689.45}
share2 := Share{"Share #2", 9423858221, 1875348.287}
fmt.Println("Share #1", share1) // da554b7f921e5ef01b2e7efd9291f3ee4b3151f79f9180337e1181e60a007b2b
fmt.Println("Share #2", share2) // 6868640b6bf4a09ff337c489236ad0ad3d85217504e1259c955370430918f0f6
c1 := NewContainer(&share1)
c2 := NewContainer(&share2)
fmt.Println("Container #1", c1)
fmt.Println("Container #2", c2)
fmt.Println("Serialize")
d1 := c1.Serialize()
d2 := c2.Serialize()
fmt.Println("Container #1", c1)
fmt.Println("Container #2", c2)
fmt.Println("Binary #1", len(d1), "\n", hex.EncodeToString(d1))
fmt.Println("Binary #2", len(d2), "\n", hex.EncodeToString(d2))
fmt.Println("Deserialize")
c1P := &Container{}
c1P.Deserialize(d1)
fmt.Println("Container #1'", c1P)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment