...

Source file src/pkg/crypto/sha256/sha256.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
     6	// in FIPS 180-4.
     7	package sha256
     8	
     9	import (
    10		"crypto"
    11		"encoding/binary"
    12		"errors"
    13		"hash"
    14	)
    15	
    16	func init() {
    17		crypto.RegisterHash(crypto.SHA224, New224)
    18		crypto.RegisterHash(crypto.SHA256, New)
    19	}
    20	
    21	// The size of a SHA256 checksum in bytes.
    22	const Size = 32
    23	
    24	// The size of a SHA224 checksum in bytes.
    25	const Size224 = 28
    26	
    27	// The blocksize of SHA256 and SHA224 in bytes.
    28	const BlockSize = 64
    29	
    30	const (
    31		chunk     = 64
    32		init0     = 0x6A09E667
    33		init1     = 0xBB67AE85
    34		init2     = 0x3C6EF372
    35		init3     = 0xA54FF53A
    36		init4     = 0x510E527F
    37		init5     = 0x9B05688C
    38		init6     = 0x1F83D9AB
    39		init7     = 0x5BE0CD19
    40		init0_224 = 0xC1059ED8
    41		init1_224 = 0x367CD507
    42		init2_224 = 0x3070DD17
    43		init3_224 = 0xF70E5939
    44		init4_224 = 0xFFC00B31
    45		init5_224 = 0x68581511
    46		init6_224 = 0x64F98FA7
    47		init7_224 = 0xBEFA4FA4
    48	)
    49	
    50	// digest represents the partial evaluation of a checksum.
    51	type digest struct {
    52		h     [8]uint32
    53		x     [chunk]byte
    54		nx    int
    55		len   uint64
    56		is224 bool // mark if this digest is SHA-224
    57	}
    58	
    59	const (
    60		magic224      = "sha\x02"
    61		magic256      = "sha\x03"
    62		marshaledSize = len(magic256) + 8*4 + chunk + 8
    63	)
    64	
    65	func (d *digest) MarshalBinary() ([]byte, error) {
    66		b := make([]byte, 0, marshaledSize)
    67		if d.is224 {
    68			b = append(b, magic224...)
    69		} else {
    70			b = append(b, magic256...)
    71		}
    72		b = appendUint32(b, d.h[0])
    73		b = appendUint32(b, d.h[1])
    74		b = appendUint32(b, d.h[2])
    75		b = appendUint32(b, d.h[3])
    76		b = appendUint32(b, d.h[4])
    77		b = appendUint32(b, d.h[5])
    78		b = appendUint32(b, d.h[6])
    79		b = appendUint32(b, d.h[7])
    80		b = append(b, d.x[:d.nx]...)
    81		b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
    82		b = appendUint64(b, d.len)
    83		return b, nil
    84	}
    85	
    86	func (d *digest) UnmarshalBinary(b []byte) error {
    87		if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) {
    88			return errors.New("crypto/sha256: invalid hash state identifier")
    89		}
    90		if len(b) != marshaledSize {
    91			return errors.New("crypto/sha256: invalid hash state size")
    92		}
    93		b = b[len(magic224):]
    94		b, d.h[0] = consumeUint32(b)
    95		b, d.h[1] = consumeUint32(b)
    96		b, d.h[2] = consumeUint32(b)
    97		b, d.h[3] = consumeUint32(b)
    98		b, d.h[4] = consumeUint32(b)
    99		b, d.h[5] = consumeUint32(b)
   100		b, d.h[6] = consumeUint32(b)
   101		b, d.h[7] = consumeUint32(b)
   102		b = b[copy(d.x[:], b):]
   103		b, d.len = consumeUint64(b)
   104		d.nx = int(d.len % chunk)
   105		return nil
   106	}
   107	
   108	func appendUint64(b []byte, x uint64) []byte {
   109		var a [8]byte
   110		binary.BigEndian.PutUint64(a[:], x)
   111		return append(b, a[:]...)
   112	}
   113	
   114	func appendUint32(b []byte, x uint32) []byte {
   115		var a [4]byte
   116		binary.BigEndian.PutUint32(a[:], x)
   117		return append(b, a[:]...)
   118	}
   119	
   120	func consumeUint64(b []byte) ([]byte, uint64) {
   121		_ = b[7]
   122		x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
   123			uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
   124		return b[8:], x
   125	}
   126	
   127	func consumeUint32(b []byte) ([]byte, uint32) {
   128		_ = b[3]
   129		x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
   130		return b[4:], x
   131	}
   132	
   133	func (d *digest) Reset() {
   134		if !d.is224 {
   135			d.h[0] = init0
   136			d.h[1] = init1
   137			d.h[2] = init2
   138			d.h[3] = init3
   139			d.h[4] = init4
   140			d.h[5] = init5
   141			d.h[6] = init6
   142			d.h[7] = init7
   143		} else {
   144			d.h[0] = init0_224
   145			d.h[1] = init1_224
   146			d.h[2] = init2_224
   147			d.h[3] = init3_224
   148			d.h[4] = init4_224
   149			d.h[5] = init5_224
   150			d.h[6] = init6_224
   151			d.h[7] = init7_224
   152		}
   153		d.nx = 0
   154		d.len = 0
   155	}
   156	
   157	// New returns a new hash.Hash computing the SHA256 checksum. The Hash
   158	// also implements encoding.BinaryMarshaler and
   159	// encoding.BinaryUnmarshaler to marshal and unmarshal the internal
   160	// state of the hash.
   161	func New() hash.Hash {
   162		d := new(digest)
   163		d.Reset()
   164		return d
   165	}
   166	
   167	// New224 returns a new hash.Hash computing the SHA224 checksum.
   168	func New224() hash.Hash {
   169		d := new(digest)
   170		d.is224 = true
   171		d.Reset()
   172		return d
   173	}
   174	
   175	func (d *digest) Size() int {
   176		if !d.is224 {
   177			return Size
   178		}
   179		return Size224
   180	}
   181	
   182	func (d *digest) BlockSize() int { return BlockSize }
   183	
   184	func (d *digest) Write(p []byte) (nn int, err error) {
   185		nn = len(p)
   186		d.len += uint64(nn)
   187		if d.nx > 0 {
   188			n := copy(d.x[d.nx:], p)
   189			d.nx += n
   190			if d.nx == chunk {
   191				block(d, d.x[:])
   192				d.nx = 0
   193			}
   194			p = p[n:]
   195		}
   196		if len(p) >= chunk {
   197			n := len(p) &^ (chunk - 1)
   198			block(d, p[:n])
   199			p = p[n:]
   200		}
   201		if len(p) > 0 {
   202			d.nx = copy(d.x[:], p)
   203		}
   204		return
   205	}
   206	
   207	func (d *digest) Sum(in []byte) []byte {
   208		// Make a copy of d so that caller can keep writing and summing.
   209		d0 := *d
   210		hash := d0.checkSum()
   211		if d0.is224 {
   212			return append(in, hash[:Size224]...)
   213		}
   214		return append(in, hash[:]...)
   215	}
   216	
   217	func (d *digest) checkSum() [Size]byte {
   218		len := d.len
   219		// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
   220		var tmp [64]byte
   221		tmp[0] = 0x80
   222		if len%64 < 56 {
   223			d.Write(tmp[0 : 56-len%64])
   224		} else {
   225			d.Write(tmp[0 : 64+56-len%64])
   226		}
   227	
   228		// Length in bits.
   229		len <<= 3
   230		binary.BigEndian.PutUint64(tmp[:], len)
   231		d.Write(tmp[0:8])
   232	
   233		if d.nx != 0 {
   234			panic("d.nx != 0")
   235		}
   236	
   237		var digest [Size]byte
   238	
   239		binary.BigEndian.PutUint32(digest[0:], d.h[0])
   240		binary.BigEndian.PutUint32(digest[4:], d.h[1])
   241		binary.BigEndian.PutUint32(digest[8:], d.h[2])
   242		binary.BigEndian.PutUint32(digest[12:], d.h[3])
   243		binary.BigEndian.PutUint32(digest[16:], d.h[4])
   244		binary.BigEndian.PutUint32(digest[20:], d.h[5])
   245		binary.BigEndian.PutUint32(digest[24:], d.h[6])
   246		if !d.is224 {
   247			binary.BigEndian.PutUint32(digest[28:], d.h[7])
   248		}
   249	
   250		return digest
   251	}
   252	
   253	// Sum256 returns the SHA256 checksum of the data.
   254	func Sum256(data []byte) [Size]byte {
   255		var d digest
   256		d.Reset()
   257		d.Write(data)
   258		return d.checkSum()
   259	}
   260	
   261	// Sum224 returns the SHA224 checksum of the data.
   262	func Sum224(data []byte) (sum224 [Size224]byte) {
   263		var d digest
   264		d.is224 = true
   265		d.Reset()
   266		d.Write(data)
   267		sum := d.checkSum()
   268		copy(sum224[:], sum[:Size224])
   269		return
   270	}
   271	

View as plain text