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