...

Source file src/crypto/sha256/sha256.go

Documentation: crypto/sha256

		 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