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