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 "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 := copy(d.x[d.nx:], p) 110 d.nx += n 111 if d.nx == chunk { 112 block(d, d.x[:]) 113 d.nx = 0 114 } 115 p = p[n:] 116 } 117 if len(p) >= chunk { 118 n := len(p) &^ (chunk - 1) 119 block(d, p[:n]) 120 p = p[n:] 121 } 122 if len(p) > 0 { 123 d.nx = copy(d.x[:], p) 124 } 125 return 126 } 127 128 func (d0 *digest) Sum(in []byte) []byte { 129 // Make a copy of d0 so that caller can keep writing and summing. 130 d := *d0 131 hash := d.checkSum() 132 if d.is224 { 133 return append(in, hash[:Size224]...) 134 } 135 return append(in, hash[:]...) 136 } 137 138 func (d *digest) checkSum() [Size]byte { 139 len := d.len 140 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 141 var tmp [64]byte 142 tmp[0] = 0x80 143 if len%64 < 56 { 144 d.Write(tmp[0 : 56-len%64]) 145 } else { 146 d.Write(tmp[0 : 64+56-len%64]) 147 } 148 149 // Length in bits. 150 len <<= 3 151 for i := uint(0); i < 8; i++ { 152 tmp[i] = byte(len >> (56 - 8*i)) 153 } 154 d.Write(tmp[0:8]) 155 156 if d.nx != 0 { 157 panic("d.nx != 0") 158 } 159 160 h := d.h[:] 161 if d.is224 { 162 h = d.h[:7] 163 } 164 165 var digest [Size]byte 166 for i, s := range h { 167 digest[i*4] = byte(s >> 24) 168 digest[i*4+1] = byte(s >> 16) 169 digest[i*4+2] = byte(s >> 8) 170 digest[i*4+3] = byte(s) 171 } 172 173 return digest 174 } 175 176 // Sum256 returns the SHA256 checksum of the data. 177 func Sum256(data []byte) [Size]byte { 178 var d digest 179 d.Reset() 180 d.Write(data) 181 return d.checkSum() 182 } 183 184 // Sum224 returns the SHA224 checksum of the data. 185 func Sum224(data []byte) (sum224 [Size224]byte) { 186 var d digest 187 d.is224 = true 188 d.Reset() 189 d.Write(data) 190 sum := d.checkSum() 191 copy(sum224[:], sum[:Size224]) 192 return 193 } 194