github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/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[:]...) 80 b = appendUint64(b, d.len) 81 return b, nil 82 } 83 84 func (d *digest) UnmarshalBinary(b []byte) error { 85 if len(b) < len(magic224) || (d.is224 && string(b[:len(magic224)]) != magic224) || (!d.is224 && string(b[:len(magic256)]) != magic256) { 86 return errors.New("crypto/sha256: invalid hash state identifier") 87 } 88 if len(b) != marshaledSize { 89 return errors.New("crypto/sha256: invalid hash state size") 90 } 91 b = b[len(magic224):] 92 b, d.h[0] = consumeUint32(b) 93 b, d.h[1] = consumeUint32(b) 94 b, d.h[2] = consumeUint32(b) 95 b, d.h[3] = consumeUint32(b) 96 b, d.h[4] = consumeUint32(b) 97 b, d.h[5] = consumeUint32(b) 98 b, d.h[6] = consumeUint32(b) 99 b, d.h[7] = consumeUint32(b) 100 b = b[copy(d.x[:], b):] 101 b, d.len = consumeUint64(b) 102 d.nx = int(d.len) % chunk 103 return nil 104 } 105 106 func appendUint64(b []byte, x uint64) []byte { 107 a := [8]byte{ 108 byte(x >> 56), 109 byte(x >> 48), 110 byte(x >> 40), 111 byte(x >> 32), 112 byte(x >> 24), 113 byte(x >> 16), 114 byte(x >> 8), 115 byte(x), 116 } 117 return append(b, a[:]...) 118 } 119 120 func appendUint32(b []byte, x uint32) []byte { 121 a := [4]byte{ 122 byte(x >> 24), 123 byte(x >> 16), 124 byte(x >> 8), 125 byte(x), 126 } 127 return append(b, a[:]...) 128 } 129 130 func consumeUint64(b []byte) ([]byte, uint64) { 131 _ = b[7] 132 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 133 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 134 return b[8:], x 135 } 136 137 func consumeUint32(b []byte) ([]byte, uint32) { 138 _ = b[3] 139 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 140 return b[4:], x 141 } 142 143 func (d *digest) Reset() { 144 if !d.is224 { 145 d.h[0] = init0 146 d.h[1] = init1 147 d.h[2] = init2 148 d.h[3] = init3 149 d.h[4] = init4 150 d.h[5] = init5 151 d.h[6] = init6 152 d.h[7] = init7 153 } else { 154 d.h[0] = init0_224 155 d.h[1] = init1_224 156 d.h[2] = init2_224 157 d.h[3] = init3_224 158 d.h[4] = init4_224 159 d.h[5] = init5_224 160 d.h[6] = init6_224 161 d.h[7] = init7_224 162 } 163 d.nx = 0 164 d.len = 0 165 } 166 167 // New returns a new hash.Hash computing the SHA256 checksum. 168 func New() hash.Hash { 169 d := new(digest) 170 d.Reset() 171 return d 172 } 173 174 // New224 returns a new hash.Hash computing the SHA224 checksum. 175 func New224() hash.Hash { 176 d := new(digest) 177 d.is224 = true 178 d.Reset() 179 return d 180 } 181 182 func (d *digest) Size() int { 183 if !d.is224 { 184 return Size 185 } 186 return Size224 187 } 188 189 func (d *digest) BlockSize() int { return BlockSize } 190 191 func (d *digest) Write(p []byte) (nn int, err error) { 192 nn = len(p) 193 d.len += uint64(nn) 194 if d.nx > 0 { 195 n := copy(d.x[d.nx:], p) 196 d.nx += n 197 if d.nx == chunk { 198 block(d, d.x[:]) 199 d.nx = 0 200 } 201 p = p[n:] 202 } 203 if len(p) >= chunk { 204 n := len(p) &^ (chunk - 1) 205 block(d, p[:n]) 206 p = p[n:] 207 } 208 if len(p) > 0 { 209 d.nx = copy(d.x[:], p) 210 } 211 return 212 } 213 214 func (d0 *digest) Sum(in []byte) []byte { 215 // Make a copy of d0 so that caller can keep writing and summing. 216 d := *d0 217 hash := d.checkSum() 218 if d.is224 { 219 return append(in, hash[:Size224]...) 220 } 221 return append(in, hash[:]...) 222 } 223 224 func (d *digest) checkSum() [Size]byte { 225 len := d.len 226 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 227 var tmp [64]byte 228 tmp[0] = 0x80 229 if len%64 < 56 { 230 d.Write(tmp[0 : 56-len%64]) 231 } else { 232 d.Write(tmp[0 : 64+56-len%64]) 233 } 234 235 // Length in bits. 236 len <<= 3 237 for i := uint(0); i < 8; i++ { 238 tmp[i] = byte(len >> (56 - 8*i)) 239 } 240 d.Write(tmp[0:8]) 241 242 if d.nx != 0 { 243 panic("d.nx != 0") 244 } 245 246 h := d.h[:] 247 if d.is224 { 248 h = d.h[:7] 249 } 250 251 var digest [Size]byte 252 for i, s := range h { 253 digest[i*4] = byte(s >> 24) 254 digest[i*4+1] = byte(s >> 16) 255 digest[i*4+2] = byte(s >> 8) 256 digest[i*4+3] = byte(s) 257 } 258 259 return digest 260 } 261 262 // Sum256 returns the SHA256 checksum of the data. 263 func Sum256(data []byte) [Size]byte { 264 var d digest 265 d.Reset() 266 d.Write(data) 267 return d.checkSum() 268 } 269 270 // Sum224 returns the SHA224 checksum of the data. 271 func Sum224(data []byte) (sum224 [Size224]byte) { 272 var d digest 273 d.is224 = true 274 d.Reset() 275 d.Write(data) 276 sum := d.checkSum() 277 copy(sum224[:], sum[:Size224]) 278 return 279 }