src/pkg/crypto/sha256/sha256.go - The Go Programming Language

Golang

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-2.
     7	package sha256
     8	
     9	import (
    10		"crypto"
    11		"hash"
    12	)
    13	
    14	func init() {
    15		crypto.RegisterHash(crypto.SHA224, New224)
    16		crypto.RegisterHash(crypto.SHA256, New)
    17	}
    18	
    19	// The size of a SHA256 checksum in bytes.
    20	const Size = 32
    21	
    22	// The size of a SHA224 checksum in bytes.
    23	const Size224 = 28
    24	
    25	// The blocksize of SHA256 and SHA224 in bytes.
    26	const BlockSize = 64
    27	
    28	const (
    29		_Chunk     = 64
    30		_Init0     = 0x6A09E667
    31		_Init1     = 0xBB67AE85
    32		_Init2     = 0x3C6EF372
    33		_Init3     = 0xA54FF53A
    34		_Init4     = 0x510E527F
    35		_Init5     = 0x9B05688C
    36		_Init6     = 0x1F83D9AB
    37		_Init7     = 0x5BE0CD19
    38		_Init0_224 = 0xC1059ED8
    39		_Init1_224 = 0x367CD507
    40		_Init2_224 = 0x3070DD17
    41		_Init3_224 = 0xF70E5939
    42		_Init4_224 = 0xFFC00B31
    43		_Init5_224 = 0x68581511
    44		_Init6_224 = 0x64F98FA7
    45		_Init7_224 = 0xBEFA4FA4
    46	)
    47	
    48	// digest represents the partial evaluation of a checksum.
    49	type digest struct {
    50		h     [8]uint32
    51		x     [_Chunk]byte
    52		nx    int
    53		len   uint64
    54		is224 bool // mark if this digest is SHA-224
    55	}
    56	
    57	func (d *digest) Reset() {
    58		if !d.is224 {
    59			d.h[0] = _Init0
    60			d.h[1] = _Init1
    61			d.h[2] = _Init2
    62			d.h[3] = _Init3
    63			d.h[4] = _Init4
    64			d.h[5] = _Init5
    65			d.h[6] = _Init6
    66			d.h[7] = _Init7
    67		} else {
    68			d.h[0] = _Init0_224
    69			d.h[1] = _Init1_224
    70			d.h[2] = _Init2_224
    71			d.h[3] = _Init3_224
    72			d.h[4] = _Init4_224
    73			d.h[5] = _Init5_224
    74			d.h[6] = _Init6_224
    75			d.h[7] = _Init7_224
    76		}
    77		d.nx = 0
    78		d.len = 0
    79	}
    80	
    81	// New returns a new hash.Hash computing the SHA256 checksum.
    82	func New() hash.Hash {
    83		d := new(digest)
    84		d.Reset()
    85		return d
    86	}
    87	
    88	// New224 returns a new hash.Hash computing the SHA224 checksum.
    89	func New224() hash.Hash {
    90		d := new(digest)
    91		d.is224 = true
    92		d.Reset()
    93		return d
    94	}
    95	
    96	func (d *digest) Size() int {
    97		if !d.is224 {
    98			return Size
    99		}
   100		return Size224
   101	}
   102	
   103	func (d *digest) BlockSize() int { return BlockSize }
   104	
   105	func (d *digest) Write(p []byte) (nn int, err error) {
   106		nn = len(p)
   107		d.len += uint64(nn)
   108		if d.nx > 0 {
   109			n := len(p)
   110			if n > _Chunk-d.nx {
   111				n = _Chunk - d.nx
   112			}
   113			for i := 0; i < n; i++ {
   114				d.x[d.nx+i] = p[i]
   115			}
   116			d.nx += n
   117			if d.nx == _Chunk {
   118				_Block(d, d.x[0:])
   119				d.nx = 0
   120			}
   121			p = p[n:]
   122		}
   123		n := _Block(d, p)
   124		p = p[n:]
   125		if len(p) > 0 {
   126			d.nx = copy(d.x[:], p)
   127		}
   128		return
   129	}
   130	
   131	func (d0 *digest) Sum(in []byte) []byte {
   132		// Make a copy of d0 so that caller can keep writing and summing.
   133		d := *d0
   134	
   135		// Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
   136		len := d.len
   137		var tmp [64]byte
   138		tmp[0] = 0x80
   139		if len%64 < 56 {
   140			d.Write(tmp[0 : 56-len%64])
   141		} else {
   142			d.Write(tmp[0 : 64+56-len%64])
   143		}
   144	
   145		// Length in bits.
   146		len <<= 3
   147		for i := uint(0); i < 8; i++ {
   148			tmp[i] = byte(len >> (56 - 8*i))
   149		}
   150		d.Write(tmp[0:8])
   151	
   152		if d.nx != 0 {
   153			panic("d.nx != 0")
   154		}
   155	
   156		h := d.h[:]
   157		size := Size
   158		if d.is224 {
   159			h = d.h[:7]
   160			size = Size224
   161		}
   162	
   163		var digest [Size]byte
   164		for i, s := range h {
   165			digest[i*4] = byte(s >> 24)
   166			digest[i*4+1] = byte(s >> 16)
   167			digest[i*4+2] = byte(s >> 8)
   168			digest[i*4+3] = byte(s)
   169		}
   170	
   171		return append(in, digest[:size]...)
   172	}