github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/crypto/sha256/sha256.go (about) 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 "crypto/internal/boring" 12 "encoding/binary" 13 "errors" 14 "hash" 15 ) 16 17 func init() { 18 crypto.RegisterHash(crypto.SHA224, New224) 19 crypto.RegisterHash(crypto.SHA256, New) 20 } 21 22 // The size of a SHA256 checksum in bytes. 23 const Size = 32 24 25 // The size of a SHA224 checksum in bytes. 26 const Size224 = 28 27 28 // The blocksize of SHA256 and SHA224 in bytes. 29 const BlockSize = 64 30 31 const ( 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. 52 type 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 60 const ( 61 magic224 = "sha\x02" 62 magic256 = "sha\x03" 63 marshaledSize = len(magic256) + 8*4 + chunk + 8 64 ) 65 66 func (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 = binary.BigEndian.AppendUint32(b, d.h[0]) 74 b = binary.BigEndian.AppendUint32(b, d.h[1]) 75 b = binary.BigEndian.AppendUint32(b, d.h[2]) 76 b = binary.BigEndian.AppendUint32(b, d.h[3]) 77 b = binary.BigEndian.AppendUint32(b, d.h[4]) 78 b = binary.BigEndian.AppendUint32(b, d.h[5]) 79 b = binary.BigEndian.AppendUint32(b, d.h[6]) 80 b = binary.BigEndian.AppendUint32(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 = binary.BigEndian.AppendUint64(b, d.len) 84 return b, nil 85 } 86 87 func (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 109 func consumeUint64(b []byte) ([]byte, uint64) { 110 _ = b[7] 111 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 112 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 113 return b[8:], x 114 } 115 116 func consumeUint32(b []byte) ([]byte, uint32) { 117 _ = b[3] 118 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 119 return b[4:], x 120 } 121 122 func (d *digest) Reset() { 123 if !d.is224 { 124 d.h[0] = init0 125 d.h[1] = init1 126 d.h[2] = init2 127 d.h[3] = init3 128 d.h[4] = init4 129 d.h[5] = init5 130 d.h[6] = init6 131 d.h[7] = init7 132 } else { 133 d.h[0] = init0_224 134 d.h[1] = init1_224 135 d.h[2] = init2_224 136 d.h[3] = init3_224 137 d.h[4] = init4_224 138 d.h[5] = init5_224 139 d.h[6] = init6_224 140 d.h[7] = init7_224 141 } 142 d.nx = 0 143 d.len = 0 144 } 145 146 // New returns a new hash.Hash computing the SHA256 checksum. The Hash 147 // also implements encoding.BinaryMarshaler and 148 // encoding.BinaryUnmarshaler to marshal and unmarshal the internal 149 // state of the hash. 150 func New() hash.Hash { 151 if boring.Enabled { 152 return boring.NewSHA256() 153 } 154 d := new(digest) 155 d.Reset() 156 return d 157 } 158 159 // New224 returns a new hash.Hash computing the SHA224 checksum. 160 func New224() hash.Hash { 161 if boring.Enabled { 162 return boring.NewSHA224() 163 } 164 d := new(digest) 165 d.is224 = true 166 d.Reset() 167 return d 168 } 169 170 func (d *digest) Size() int { 171 if !d.is224 { 172 return Size 173 } 174 return Size224 175 } 176 177 func (d *digest) BlockSize() int { return BlockSize } 178 179 func (d *digest) Write(p []byte) (nn int, err error) { 180 boring.Unreachable() 181 nn = len(p) 182 d.len += uint64(nn) 183 if d.nx > 0 { 184 n := copy(d.x[d.nx:], p) 185 d.nx += n 186 if d.nx == chunk { 187 block(d, d.x[:]) 188 d.nx = 0 189 } 190 p = p[n:] 191 } 192 if len(p) >= chunk { 193 n := len(p) &^ (chunk - 1) 194 block(d, p[:n]) 195 p = p[n:] 196 } 197 if len(p) > 0 { 198 d.nx = copy(d.x[:], p) 199 } 200 return 201 } 202 203 func (d *digest) Sum(in []byte) []byte { 204 boring.Unreachable() 205 // Make a copy of d so that caller can keep writing and summing. 206 d0 := *d 207 hash := d0.checkSum() 208 if d0.is224 { 209 return append(in, hash[:Size224]...) 210 } 211 return append(in, hash[:]...) 212 } 213 214 func (d *digest) checkSum() [Size]byte { 215 len := d.len 216 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 217 var tmp [64 + 8]byte // padding + length buffer 218 tmp[0] = 0x80 219 var t uint64 220 if len%64 < 56 { 221 t = 56 - len%64 222 } else { 223 t = 64 + 56 - len%64 224 } 225 226 // Length in bits. 227 len <<= 3 228 padlen := tmp[:t+8] 229 binary.BigEndian.PutUint64(padlen[t+0:], len) 230 d.Write(padlen) 231 232 if d.nx != 0 { 233 panic("d.nx != 0") 234 } 235 236 var digest [Size]byte 237 238 binary.BigEndian.PutUint32(digest[0:], d.h[0]) 239 binary.BigEndian.PutUint32(digest[4:], d.h[1]) 240 binary.BigEndian.PutUint32(digest[8:], d.h[2]) 241 binary.BigEndian.PutUint32(digest[12:], d.h[3]) 242 binary.BigEndian.PutUint32(digest[16:], d.h[4]) 243 binary.BigEndian.PutUint32(digest[20:], d.h[5]) 244 binary.BigEndian.PutUint32(digest[24:], d.h[6]) 245 if !d.is224 { 246 binary.BigEndian.PutUint32(digest[28:], d.h[7]) 247 } 248 249 return digest 250 } 251 252 // Sum256 returns the SHA256 checksum of the data. 253 func Sum256(data []byte) [Size]byte { 254 if boring.Enabled { 255 return boring.SHA256(data) 256 } 257 var d digest 258 d.Reset() 259 d.Write(data) 260 return d.checkSum() 261 } 262 263 // Sum224 returns the SHA224 checksum of the data. 264 func Sum224(data []byte) [Size224]byte { 265 if boring.Enabled { 266 return boring.SHA224(data) 267 } 268 var d digest 269 d.is224 = true 270 d.Reset() 271 d.Write(data) 272 sum := d.checkSum() 273 ap := (*[Size224]byte)(sum[:]) 274 return *ap 275 }