]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/sha1/sha1.go
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
[gostls13.git] / src / crypto / sha1 / sha1.go
index 535937e902847fbf517780e71787557ad4542105..3badf558852b2d27fd241e202eb1ce2721a97cfa 100644 (file)
@@ -10,6 +10,7 @@ package sha1
 
 import (
        "crypto"
+       "errors"
        "hash"
 )
 
@@ -40,6 +41,68 @@ type digest struct {
        len uint64
 }
 
+const (
+       magic         = "sha\x01"
+       marshaledSize = len(magic) + 5*4 + chunk + 8
+)
+
+func (d *digest) MarshalBinary() ([]byte, error) {
+       b := make([]byte, 0, marshaledSize)
+       b = append(b, magic...)
+       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 = append(b, d.x[:]...)
+       b = appendUint64(b, d.len)
+       return b, nil
+}
+
+func (d *digest) UnmarshalBinary(b []byte) error {
+       if len(b) < len(magic) || string(b[:len(magic)]) != magic {
+               return errors.New("crypto/sha1: invalid hash state identifier")
+       }
+       if len(b) != marshaledSize {
+               return errors.New("crypto/sha1: invalid hash state size")
+       }
+       b = b[len(magic):]
+       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 = b[copy(d.x[:], b):]
+       b, d.len = consumeUint64(b)
+       d.nx = int(d.len) % chunk
+       return nil
+}
+
+func appendUint64(b []byte, x uint64) []byte {
+       var a [8]byte
+       putUint64(a[:], x)
+       return append(b, a[:]...)
+}
+
+func appendUint32(b []byte, x uint32) []byte {
+       var a [4]byte
+       putUint32(a[:], x)
+       return append(b, a[:]...)
+}
+
+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
+}
+
 func (d *digest) Reset() {
        d.h[0] = init0
        d.h[1] = init1
@@ -50,7 +113,9 @@ func (d *digest) Reset() {
        d.len = 0
 }
 
-// New returns a new hash.Hash computing the SHA1 checksum.
+// New returns a new hash.Hash computing the SHA1 checksum. The Hash also
+// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
+// marshal and unmarshal the internal state of the hash.
 func New() hash.Hash {
        if boringEnabled {
                return boringNewSHA1()
@@ -109,9 +174,7 @@ func (d *digest) checkSum() [Size]byte {
 
        // Length in bits.
        len <<= 3
-       for i := uint(0); i < 8; i++ {
-               tmp[i] = byte(len >> (56 - 8*i))
-       }
+       putUint64(tmp[:], len)
        d.Write(tmp[0:8])
 
        if d.nx != 0 {
@@ -119,12 +182,12 @@ func (d *digest) checkSum() [Size]byte {
        }
 
        var digest [Size]byte
-       for i, s := range d.h {
-               digest[i*4] = byte(s >> 24)
-               digest[i*4+1] = byte(s >> 16)
-               digest[i*4+2] = byte(s >> 8)
-               digest[i*4+3] = byte(s)
-       }
+
+       putUint32(digest[0:], d.h[0])
+       putUint32(digest[4:], d.h[1])
+       putUint32(digest[8:], d.h[2])
+       putUint32(digest[12:], d.h[3])
+       putUint32(digest[16:], d.h[4])
 
        return digest
 }
@@ -211,3 +274,23 @@ func Sum(data []byte) [Size]byte {
        d.Write(data)
        return d.checkSum()
 }
+
+func putUint64(x []byte, s uint64) {
+       _ = x[7]
+       x[0] = byte(s >> 56)
+       x[1] = byte(s >> 48)
+       x[2] = byte(s >> 40)
+       x[3] = byte(s >> 32)
+       x[4] = byte(s >> 24)
+       x[5] = byte(s >> 16)
+       x[6] = byte(s >> 8)
+       x[7] = byte(s)
+}
+
+func putUint32(x []byte, s uint32) {
+       _ = x[3]
+       x[0] = byte(s >> 24)
+       x[1] = byte(s >> 16)
+       x[2] = byte(s >> 8)
+       x[3] = byte(s)
+}