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