Skip to content

Commit 4384f83

Browse files
authored
Add implementation of encoding.BinaryAppender for hash algorithms (#170)
* add:implementation of encoder interface to hash marshaler * fix:remove AppendText implementation for narrowing the given support * fix:move marshalling logic to appendbinary and construct passed buffers with size * fix the padding logic of hashes * fix:add tests for AppendBinary * fix: rebase with v2 * fix:add a binaryappender tests as a separate function * fix:skip unsupported tests
1 parent dc8da3a commit 4384f83

File tree

2 files changed

+176
-101
lines changed

2 files changed

+176
-101
lines changed

hash.go

Lines changed: 126 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -368,20 +368,8 @@ type md5Marshal struct {
368368
}
369369

370370
func (h *md5Marshal) MarshalBinary() ([]byte, error) {
371-
d := (*md5State)(h.hashState())
372-
if d == nil {
373-
return nil, errors.New("crypto/md5: can't retrieve hash state")
374-
}
375-
b := make([]byte, 0, md5MarshaledSize)
376-
b = append(b, md5Magic...)
377-
b = appendUint32(b, d.h[0])
378-
b = appendUint32(b, d.h[1])
379-
b = appendUint32(b, d.h[2])
380-
b = appendUint32(b, d.h[3])
381-
b = append(b, d.x[:d.nx]...)
382-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
383-
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
384-
return b, nil
371+
buf := make([]byte, 0, md5MarshaledSize)
372+
return h.AppendBinary(buf)
385373
}
386374

387375
func (h *md5Marshal) UnmarshalBinary(b []byte) error {
@@ -408,6 +396,23 @@ func (h *md5Marshal) UnmarshalBinary(b []byte) error {
408396
return nil
409397
}
410398

399+
func (h *md5Marshal) AppendBinary(buf []byte) ([]byte, error) {
400+
d := (*md5State)(h.hashState())
401+
if d == nil {
402+
return nil, errors.New("crypto/md5: can't retrieve hash state")
403+
}
404+
405+
buf = append(buf, md5Magic...)
406+
buf = appendUint32(buf, d.h[0])
407+
buf = appendUint32(buf, d.h[1])
408+
buf = appendUint32(buf, d.h[2])
409+
buf = appendUint32(buf, d.h[3])
410+
buf = append(buf, d.x[:d.nx]...)
411+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
412+
buf = appendUint64(buf, uint64(d.nl)>>3|uint64(d.nh)<<29)
413+
return buf, nil
414+
}
415+
411416
// NewSHA1 returns a new SHA1 hash.
412417
func NewSHA1() hash.Hash {
413418
h := sha1Hash{evpHash: newEvpHash(crypto.SHA1)}
@@ -457,21 +462,8 @@ type sha1Marshal struct {
457462
}
458463

459464
func (h *sha1Marshal) MarshalBinary() ([]byte, error) {
460-
d := (*sha1State)(h.hashState())
461-
if d == nil {
462-
return nil, errors.New("crypto/sha1: can't retrieve hash state")
463-
}
464-
b := make([]byte, 0, sha1MarshaledSize)
465-
b = append(b, sha1Magic...)
466-
b = appendUint32(b, d.h[0])
467-
b = appendUint32(b, d.h[1])
468-
b = appendUint32(b, d.h[2])
469-
b = appendUint32(b, d.h[3])
470-
b = appendUint32(b, d.h[4])
471-
b = append(b, d.x[:d.nx]...)
472-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
473-
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
474-
return b, nil
465+
buf := make([]byte, 0, sha1MarshaledSize)
466+
return h.AppendBinary(buf)
475467
}
476468

477469
func (h *sha1Marshal) UnmarshalBinary(b []byte) error {
@@ -499,6 +491,23 @@ func (h *sha1Marshal) UnmarshalBinary(b []byte) error {
499491
return nil
500492
}
501493

494+
func (h *sha1Marshal) AppendBinary(buf []byte) ([]byte, error) {
495+
d := (*sha1State)(h.hashState())
496+
if d == nil {
497+
return nil, errors.New("crypto/sha1: can't retrieve hash state")
498+
}
499+
buf = append(buf, sha1Magic...)
500+
buf = appendUint32(buf, d.h[0])
501+
buf = appendUint32(buf, d.h[1])
502+
buf = appendUint32(buf, d.h[2])
503+
buf = appendUint32(buf, d.h[3])
504+
buf = appendUint32(buf, d.h[4])
505+
buf = append(buf, d.x[:d.nx]...)
506+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
507+
buf = appendUint64(buf, uint64(d.nl)>>3|uint64(d.nh)<<29)
508+
return buf, nil
509+
}
510+
502511
// NewSHA224 returns a new SHA224 hash.
503512
func NewSHA224() hash.Hash {
504513
h := sha224Hash{evpHash: newEvpHash(crypto.SHA224)}
@@ -583,45 +592,13 @@ type sha256Marshal struct {
583592
}
584593

585594
func (h *sha224Marshal) MarshalBinary() ([]byte, error) {
586-
d := (*sha256State)(h.hashState())
587-
if d == nil {
588-
return nil, errors.New("crypto/sha256: can't retrieve hash state")
589-
}
590-
b := make([]byte, 0, marshaledSize256)
591-
b = append(b, magic224...)
592-
b = appendUint32(b, d.h[0])
593-
b = appendUint32(b, d.h[1])
594-
b = appendUint32(b, d.h[2])
595-
b = appendUint32(b, d.h[3])
596-
b = appendUint32(b, d.h[4])
597-
b = appendUint32(b, d.h[5])
598-
b = appendUint32(b, d.h[6])
599-
b = appendUint32(b, d.h[7])
600-
b = append(b, d.x[:d.nx]...)
601-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
602-
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
603-
return b, nil
595+
buf := make([]byte, 0, marshaledSize256)
596+
return h.AppendBinary(buf)
604597
}
605598

606599
func (h *sha256Marshal) MarshalBinary() ([]byte, error) {
607-
d := (*sha256State)(h.hashState())
608-
if d == nil {
609-
return nil, errors.New("crypto/sha256: can't retrieve hash state")
610-
}
611-
b := make([]byte, 0, marshaledSize256)
612-
b = append(b, magic256...)
613-
b = appendUint32(b, d.h[0])
614-
b = appendUint32(b, d.h[1])
615-
b = appendUint32(b, d.h[2])
616-
b = appendUint32(b, d.h[3])
617-
b = appendUint32(b, d.h[4])
618-
b = appendUint32(b, d.h[5])
619-
b = appendUint32(b, d.h[6])
620-
b = appendUint32(b, d.h[7])
621-
b = append(b, d.x[:d.nx]...)
622-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
623-
b = appendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
624-
return b, nil
600+
buf := make([]byte, 0, marshaledSize256)
601+
return h.AppendBinary(buf)
625602
}
626603

627604
func (h *sha224Marshal) UnmarshalBinary(b []byte) error {
@@ -680,6 +657,46 @@ func (h *sha256Marshal) UnmarshalBinary(b []byte) error {
680657
return nil
681658
}
682659

660+
func (h *sha224Marshal) AppendBinary(buf []byte) ([]byte, error) {
661+
d := (*sha256State)(h.hashState())
662+
if d == nil {
663+
return nil, errors.New("crypto/sha256: can't retrieve hash state")
664+
}
665+
buf = append(buf, magic224...)
666+
buf = appendUint32(buf, d.h[0])
667+
buf = appendUint32(buf, d.h[1])
668+
buf = appendUint32(buf, d.h[2])
669+
buf = appendUint32(buf, d.h[3])
670+
buf = appendUint32(buf, d.h[4])
671+
buf = appendUint32(buf, d.h[5])
672+
buf = appendUint32(buf, d.h[6])
673+
buf = appendUint32(buf, d.h[7])
674+
buf = append(buf, d.x[:d.nx]...)
675+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
676+
buf = appendUint64(buf, uint64(d.nl)>>3|uint64(d.nh)<<29)
677+
return buf, nil
678+
}
679+
680+
func (h *sha256Marshal) AppendBinary(buf []byte) ([]byte, error) {
681+
d := (*sha256State)(h.hashState())
682+
if d == nil {
683+
return nil, errors.New("crypto/sha256: can't retrieve hash state")
684+
}
685+
buf = append(buf, magic256...)
686+
buf = appendUint32(buf, d.h[0])
687+
buf = appendUint32(buf, d.h[1])
688+
buf = appendUint32(buf, d.h[2])
689+
buf = appendUint32(buf, d.h[3])
690+
buf = appendUint32(buf, d.h[4])
691+
buf = appendUint32(buf, d.h[5])
692+
buf = appendUint32(buf, d.h[6])
693+
buf = appendUint32(buf, d.h[7])
694+
buf = append(buf, d.x[:d.nx]...)
695+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
696+
buf = appendUint64(buf, uint64(d.nl)>>3|uint64(d.nh)<<29)
697+
return buf, nil
698+
}
699+
683700
// NewSHA384 returns a new SHA384 hash.
684701
func NewSHA384() hash.Hash {
685702
h := sha384Hash{evpHash: newEvpHash(crypto.SHA384)}
@@ -766,45 +783,13 @@ type sha512Marshal struct {
766783
}
767784

768785
func (h *sha384Marshal) MarshalBinary() ([]byte, error) {
769-
d := (*sha512State)(h.hashState())
770-
if d == nil {
771-
return nil, errors.New("crypto/sha512: can't retrieve hash state")
772-
}
773-
b := make([]byte, 0, marshaledSize512)
774-
b = append(b, magic384...)
775-
b = appendUint64(b, d.h[0])
776-
b = appendUint64(b, d.h[1])
777-
b = appendUint64(b, d.h[2])
778-
b = appendUint64(b, d.h[3])
779-
b = appendUint64(b, d.h[4])
780-
b = appendUint64(b, d.h[5])
781-
b = appendUint64(b, d.h[6])
782-
b = appendUint64(b, d.h[7])
783-
b = append(b, d.x[:d.nx]...)
784-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
785-
b = appendUint64(b, d.nl>>3|d.nh<<61)
786-
return b, nil
786+
buf := make([]byte, 0, marshaledSize512)
787+
return h.AppendBinary(buf)
787788
}
788789

789790
func (h *sha512Marshal) MarshalBinary() ([]byte, error) {
790-
d := (*sha512State)(h.hashState())
791-
if d == nil {
792-
return nil, errors.New("crypto/sha512: can't retrieve hash state")
793-
}
794-
b := make([]byte, 0, marshaledSize512)
795-
b = append(b, magic512...)
796-
b = appendUint64(b, d.h[0])
797-
b = appendUint64(b, d.h[1])
798-
b = appendUint64(b, d.h[2])
799-
b = appendUint64(b, d.h[3])
800-
b = appendUint64(b, d.h[4])
801-
b = appendUint64(b, d.h[5])
802-
b = appendUint64(b, d.h[6])
803-
b = appendUint64(b, d.h[7])
804-
b = append(b, d.x[:d.nx]...)
805-
b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
806-
b = appendUint64(b, d.nl>>3|d.nh<<61)
807-
return b, nil
791+
buf := make([]byte, 0, marshaledSize512)
792+
return h.AppendBinary(buf)
808793
}
809794

810795
func (h *sha384Marshal) UnmarshalBinary(b []byte) error {
@@ -869,6 +854,46 @@ func (h *sha512Marshal) UnmarshalBinary(b []byte) error {
869854
return nil
870855
}
871856

857+
func (h *sha384Marshal) AppendBinary(buf []byte) ([]byte, error) {
858+
d := (*sha512State)(h.hashState())
859+
if d == nil {
860+
return nil, errors.New("crypto/sha512: can't retrieve hash state")
861+
}
862+
buf = append(buf, magic384...)
863+
buf = appendUint64(buf, d.h[0])
864+
buf = appendUint64(buf, d.h[1])
865+
buf = appendUint64(buf, d.h[2])
866+
buf = appendUint64(buf, d.h[3])
867+
buf = appendUint64(buf, d.h[4])
868+
buf = appendUint64(buf, d.h[5])
869+
buf = appendUint64(buf, d.h[6])
870+
buf = appendUint64(buf, d.h[7])
871+
buf = append(buf, d.x[:d.nx]...)
872+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
873+
buf = appendUint64(buf, d.nl>>3|d.nh<<61)
874+
return buf, nil
875+
}
876+
877+
func (h *sha512Marshal) AppendBinary(buf []byte) ([]byte, error) {
878+
d := (*sha512State)(h.hashState())
879+
if d == nil {
880+
return nil, errors.New("crypto/sha512: can't retrieve hash state")
881+
}
882+
buf = append(buf, magic512...)
883+
buf = appendUint64(buf, d.h[0])
884+
buf = appendUint64(buf, d.h[1])
885+
buf = appendUint64(buf, d.h[2])
886+
buf = appendUint64(buf, d.h[3])
887+
buf = appendUint64(buf, d.h[4])
888+
buf = appendUint64(buf, d.h[5])
889+
buf = appendUint64(buf, d.h[6])
890+
buf = appendUint64(buf, d.h[7])
891+
buf = append(buf, d.x[:d.nx]...)
892+
buf = append(buf, make([]byte, len(d.x)-int(d.nx))...)
893+
buf = appendUint64(buf, d.nl>>3|d.nh<<61)
894+
return buf, nil
895+
}
896+
872897
// NewSHA3_224 returns a new SHA3-224 hash.
873898
func NewSHA3_224() hash.Hash {
874899
return &sha3_224Hash{

hash_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,56 @@ func TestHash_BinaryMarshaler(t *testing.T) {
117117
}
118118
}
119119

120+
func TestHash_BinaryAppender(t *testing.T) {
121+
for _, ch := range hashes {
122+
t.Run(ch.String(), func(t *testing.T) {
123+
t.Parallel()
124+
if !openssl.SupportsHash(ch) {
125+
t.Skip("skipping: not supported")
126+
}
127+
h := cryptoToHash(ch)()
128+
if h, ok := h.(interface {
129+
AppendBinary(b []byte) ([]byte, error)
130+
Sum(b []byte) []byte
131+
}); ok {
132+
// Create a slice with 10 elements
133+
prebuiltSlice := make([]byte, 10)
134+
// Fill the slice with some data
135+
for i := range prebuiltSlice {
136+
prebuiltSlice[i] = byte(i)
137+
}
138+
139+
// Clone the prebuilt slice for comparison
140+
prebuiltSliceClone := append([]byte(nil), prebuiltSlice...)
141+
142+
// Append binary data to the prebuilt slice
143+
state, err := h.AppendBinary(prebuiltSlice)
144+
if err != nil {
145+
t.Errorf("could not append binary: %v", err)
146+
}
147+
148+
// Ensure the first 10 elements are still the same
149+
if !bytes.Equal(state[:10], prebuiltSliceClone) {
150+
t.Errorf("prebuilt slice modified: got %v, want %v", state[:10], prebuiltSliceClone)
151+
}
152+
153+
// Use only the newly appended part of the slice
154+
appendedState := state[10:]
155+
156+
h2 := cryptoToHash(ch)()
157+
if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(appendedState); err != nil {
158+
t.Errorf("could not unmarshal: %v", err)
159+
}
160+
if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) {
161+
t.Errorf("0x%x != appended 0x%x", actual, actual2)
162+
}
163+
} else {
164+
t.Skip("skipping: not supported")
165+
}
166+
})
167+
}
168+
}
169+
120170
func TestHash_Clone(t *testing.T) {
121171
msg := []byte("testing")
122172
for _, ch := range hashes {

0 commit comments

Comments
 (0)