Skip to content

Commit

Permalink
Add MarshalBinary/UnmarshalBinary support (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
klauspost committed Feb 22, 2023
1 parent d9c3aea commit 6096f89
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
go-version: [1.16.x, 1.15.x, 1.14.x]
go-version: [1.20.x, 1.19.x, 1.18.x]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Set up Go ${{ matrix.go-version }}
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module github.com/minio/sha256-simd

go 1.13
go 1.17

require github.com/klauspost/cpuid/v2 v2.2.3

require golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e // indirect
80 changes: 80 additions & 0 deletions sha256.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package sha256
import (
"crypto/sha256"
"encoding/binary"
"errors"
"hash"
)

Expand Down Expand Up @@ -386,3 +387,82 @@ var _K = []uint32{
0xbef9a3f7,
0xc67178f2,
}

const (
magic256 = "sha\x03"
marshaledSize = len(magic256) + 8*4 + chunk + 8
)

func (d *digest) MarshalBinary() ([]byte, error) {
b := make([]byte, 0, marshaledSize)
b = append(b, magic256...)
b = appendUint32(b, d.h[0])
b = appendUint32(b, d.h[1])
b = appendUint32(b, d.h[2])
b = appendUint32(b, d.h[3])
b = appendUint32(b, d.h[4])
b = appendUint32(b, d.h[5])
b = appendUint32(b, d.h[6])
b = appendUint32(b, d.h[7])
b = append(b, d.x[:d.nx]...)
b = b[:len(b)+len(d.x)-d.nx] // already zero
b = appendUint64(b, d.len)
return b, nil
}

func (d *digest) UnmarshalBinary(b []byte) error {
if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 {
return errors.New("crypto/sha256: invalid hash state identifier")
}
if len(b) != marshaledSize {
return errors.New("crypto/sha256: invalid hash state size")
}
b = b[len(magic256):]
b, d.h[0] = consumeUint32(b)
b, d.h[1] = consumeUint32(b)
b, d.h[2] = consumeUint32(b)
b, d.h[3] = consumeUint32(b)
b, d.h[4] = consumeUint32(b)
b, d.h[5] = consumeUint32(b)
b, d.h[6] = consumeUint32(b)
b, d.h[7] = consumeUint32(b)
b = b[copy(d.x[:], b):]
b, d.len = consumeUint64(b)
d.nx = int(d.len % chunk)
return nil
}

func appendUint32(b []byte, v uint32) []byte {
return append(b,
byte(v>>24),
byte(v>>16),
byte(v>>8),
byte(v),
)
}

func appendUint64(b []byte, v uint64) []byte {
return append(b,
byte(v>>56),
byte(v>>48),
byte(v>>40),
byte(v>>32),
byte(v>>24),
byte(v>>16),
byte(v>>8),
byte(v),
)
}

func consumeUint64(b []byte) ([]byte, uint64) {
_ = b[7]
x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
return b[8:], x
}

func consumeUint32(b []byte) ([]byte, uint32) {
_ = b[3]
x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
return b[4:], x
}

0 comments on commit 6096f89

Please sign in to comment.