From 60870290a20eecd4be6d3b16893c183e40cd13a2 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 2 Aug 2019 12:52:40 +0300 Subject: [PATCH] GOST34112012 hashes satisfy Binary(Un)Marshaler --- .../gogost/internal/gost34112012/hash.go | 44 +++++++++++++++++++ .../gogost/internal/gost34112012/hash_test.go | 23 +++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/cypherpunks.ru/gogost/internal/gost34112012/hash.go b/src/cypherpunks.ru/gogost/internal/gost34112012/hash.go index c4d98da..ea35468 100644 --- a/src/cypherpunks.ru/gogost/internal/gost34112012/hash.go +++ b/src/cypherpunks.ru/gogost/internal/gost34112012/hash.go @@ -19,11 +19,15 @@ package gost34112012 import ( + "bytes" "encoding/binary" + "errors" ) const ( BlockSize = 64 + + MarshaledName = "STREEBOG" ) var ( @@ -403,3 +407,43 @@ func l(data *[BlockSize]byte) *[BlockSize]byte { } return r } + +func (h *Hash) MarshalBinary() (data []byte, err error) { + data = make([]byte, len(MarshaledName)+1+8+3*BlockSize+len(h.buf)) + copy(data, []byte(MarshaledName)) + idx := len(MarshaledName) + data[idx] = byte(h.size) + idx += 1 + binary.BigEndian.PutUint64(data[idx:idx+8], h.n) + idx += 8 + copy(data[idx:], h.hsh[:]) + idx += BlockSize + copy(data[idx:], h.chk[:]) + idx += BlockSize + copy(data[idx:], h.tmp[:]) + idx += BlockSize + copy(data[idx:], h.buf) + return +} + +func (h *Hash) UnmarshalBinary(data []byte) error { + if len(data) < len(MarshaledName)+1+8+3*BlockSize { + return errors.New("too short data") + } + if !bytes.HasPrefix(data, []byte(MarshaledName)) { + return errors.New("no hash name prefix") + } + idx := len(MarshaledName) + h.size = int(data[idx]) + idx += 1 + h.n = binary.BigEndian.Uint64(data[idx : idx+8]) + idx += 8 + copy(h.hsh[:], data[idx:]) + idx += BlockSize + copy(h.chk[:], data[idx:]) + idx += BlockSize + copy(h.tmp[:], data[idx:]) + idx += BlockSize + h.buf = data[idx:] + return nil +} diff --git a/src/cypherpunks.ru/gogost/internal/gost34112012/hash_test.go b/src/cypherpunks.ru/gogost/internal/gost34112012/hash_test.go index 1e0df64..5309447 100644 --- a/src/cypherpunks.ru/gogost/internal/gost34112012/hash_test.go +++ b/src/cypherpunks.ru/gogost/internal/gost34112012/hash_test.go @@ -19,6 +19,7 @@ package gost34112012 import ( "bytes" "crypto/rand" + "encoding" "hash" "testing" "testing/quick" @@ -27,6 +28,8 @@ import ( func TestHashInterface(t *testing.T) { h := New(64) var _ hash.Hash = h + var _ encoding.BinaryMarshaler = h + var _ encoding.BinaryUnmarshaler = h } func TestVectors(t *testing.T) { @@ -188,12 +191,30 @@ func TestRandom(t *testing.T) { h.Reset() h.Write(data) d1 := h.Sum(nil) + h1Raw, err := h.MarshalBinary() + if err != nil { + return false + } h.Reset() for _, c := range data { h.Write([]byte{c}) } d2 := h.Sum(nil) - return bytes.Compare(d1, d2) == 0 + if bytes.Compare(d1, d2) != 0 { + return false + } + h2Raw, err := h.MarshalBinary() + if err != nil { + return false + } + if bytes.Compare(h1Raw, h2Raw) != 0 { + return false + } + hNew := New(64) + if err = hNew.UnmarshalBinary(h1Raw); err != nil { + return false + } + return bytes.Compare(hNew.Sum(nil), d1) == 0 } if err := quick.Check(f, nil); err != nil { t.Error(err) -- 2.44.0