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 }