sha256.go (8862B)
1 /* 2 * Minio Cloud Storage, (C) 2016 Minio, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package sha256 18 19 import ( 20 "crypto/sha256" 21 "encoding/binary" 22 "errors" 23 "hash" 24 ) 25 26 // Size - The size of a SHA256 checksum in bytes. 27 const Size = 32 28 29 // BlockSize - The blocksize of SHA256 in bytes. 30 const BlockSize = 64 31 32 const ( 33 chunk = BlockSize 34 init0 = 0x6A09E667 35 init1 = 0xBB67AE85 36 init2 = 0x3C6EF372 37 init3 = 0xA54FF53A 38 init4 = 0x510E527F 39 init5 = 0x9B05688C 40 init6 = 0x1F83D9AB 41 init7 = 0x5BE0CD19 42 ) 43 44 // digest represents the partial evaluation of a checksum. 45 type digest struct { 46 h [8]uint32 47 x [chunk]byte 48 nx int 49 len uint64 50 } 51 52 // Reset digest back to default 53 func (d *digest) Reset() { 54 d.h[0] = init0 55 d.h[1] = init1 56 d.h[2] = init2 57 d.h[3] = init3 58 d.h[4] = init4 59 d.h[5] = init5 60 d.h[6] = init6 61 d.h[7] = init7 62 d.nx = 0 63 d.len = 0 64 } 65 66 type blockfuncType int 67 68 const ( 69 blockfuncStdlib blockfuncType = iota 70 blockfuncIntelSha 71 blockfuncArmSha2 72 blockfuncForceGeneric = -1 73 ) 74 75 var blockfunc blockfuncType 76 77 func init() { 78 switch { 79 case hasIntelSha: 80 blockfunc = blockfuncIntelSha 81 case hasArmSha2(): 82 blockfunc = blockfuncArmSha2 83 } 84 } 85 86 // New returns a new hash.Hash computing the SHA256 checksum. 87 func New() hash.Hash { 88 if blockfunc == blockfuncStdlib { 89 // Fallback to the standard golang implementation 90 // if no features were found. 91 return sha256.New() 92 } 93 94 d := new(digest) 95 d.Reset() 96 return d 97 } 98 99 // Sum256 - single caller sha256 helper 100 func Sum256(data []byte) (result [Size]byte) { 101 var d digest 102 d.Reset() 103 d.Write(data) 104 result = d.checkSum() 105 return 106 } 107 108 // Return size of checksum 109 func (d *digest) Size() int { return Size } 110 111 // Return blocksize of checksum 112 func (d *digest) BlockSize() int { return BlockSize } 113 114 // Write to digest 115 func (d *digest) Write(p []byte) (nn int, err error) { 116 nn = len(p) 117 d.len += uint64(nn) 118 if d.nx > 0 { 119 n := copy(d.x[d.nx:], p) 120 d.nx += n 121 if d.nx == chunk { 122 block(d, d.x[:]) 123 d.nx = 0 124 } 125 p = p[n:] 126 } 127 if len(p) >= chunk { 128 n := len(p) &^ (chunk - 1) 129 block(d, p[:n]) 130 p = p[n:] 131 } 132 if len(p) > 0 { 133 d.nx = copy(d.x[:], p) 134 } 135 return 136 } 137 138 // Return sha256 sum in bytes 139 func (d *digest) Sum(in []byte) []byte { 140 // Make a copy of d0 so that caller can keep writing and summing. 141 d0 := *d 142 hash := d0.checkSum() 143 return append(in, hash[:]...) 144 } 145 146 // Intermediate checksum function 147 func (d *digest) checkSum() (digest [Size]byte) { 148 n := d.nx 149 150 var k [64]byte 151 copy(k[:], d.x[:n]) 152 153 k[n] = 0x80 154 155 if n >= 56 { 156 block(d, k[:]) 157 158 // clear block buffer - go compiles this to optimal 1x xorps + 4x movups 159 // unfortunately expressing this more succinctly results in much worse code 160 k[0] = 0 161 k[1] = 0 162 k[2] = 0 163 k[3] = 0 164 k[4] = 0 165 k[5] = 0 166 k[6] = 0 167 k[7] = 0 168 k[8] = 0 169 k[9] = 0 170 k[10] = 0 171 k[11] = 0 172 k[12] = 0 173 k[13] = 0 174 k[14] = 0 175 k[15] = 0 176 k[16] = 0 177 k[17] = 0 178 k[18] = 0 179 k[19] = 0 180 k[20] = 0 181 k[21] = 0 182 k[22] = 0 183 k[23] = 0 184 k[24] = 0 185 k[25] = 0 186 k[26] = 0 187 k[27] = 0 188 k[28] = 0 189 k[29] = 0 190 k[30] = 0 191 k[31] = 0 192 k[32] = 0 193 k[33] = 0 194 k[34] = 0 195 k[35] = 0 196 k[36] = 0 197 k[37] = 0 198 k[38] = 0 199 k[39] = 0 200 k[40] = 0 201 k[41] = 0 202 k[42] = 0 203 k[43] = 0 204 k[44] = 0 205 k[45] = 0 206 k[46] = 0 207 k[47] = 0 208 k[48] = 0 209 k[49] = 0 210 k[50] = 0 211 k[51] = 0 212 k[52] = 0 213 k[53] = 0 214 k[54] = 0 215 k[55] = 0 216 k[56] = 0 217 k[57] = 0 218 k[58] = 0 219 k[59] = 0 220 k[60] = 0 221 k[61] = 0 222 k[62] = 0 223 k[63] = 0 224 } 225 binary.BigEndian.PutUint64(k[56:64], uint64(d.len)<<3) 226 block(d, k[:]) 227 228 { 229 const i = 0 230 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 231 } 232 { 233 const i = 1 234 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 235 } 236 { 237 const i = 2 238 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 239 } 240 { 241 const i = 3 242 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 243 } 244 { 245 const i = 4 246 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 247 } 248 { 249 const i = 5 250 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 251 } 252 { 253 const i = 6 254 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 255 } 256 { 257 const i = 7 258 binary.BigEndian.PutUint32(digest[i*4:i*4+4], d.h[i]) 259 } 260 261 return 262 } 263 264 func block(dig *digest, p []byte) { 265 if blockfunc == blockfuncIntelSha { 266 blockIntelShaGo(dig, p) 267 } else if blockfunc == blockfuncArmSha2 { 268 blockArmSha2Go(dig, p) 269 } else { 270 blockGeneric(dig, p) 271 } 272 } 273 274 func blockGeneric(dig *digest, p []byte) { 275 var w [64]uint32 276 h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] 277 for len(p) >= chunk { 278 // Can interlace the computation of w with the 279 // rounds below if needed for speed. 280 for i := 0; i < 16; i++ { 281 j := i * 4 282 w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) 283 } 284 for i := 16; i < 64; i++ { 285 v1 := w[i-2] 286 t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10) 287 v2 := w[i-15] 288 t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3) 289 w[i] = t1 + w[i-7] + t2 + w[i-16] 290 } 291 292 a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7 293 294 for i := 0; i < 64; i++ { 295 t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i] 296 297 t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c)) 298 299 h = g 300 g = f 301 f = e 302 e = d + t1 303 d = c 304 c = b 305 b = a 306 a = t1 + t2 307 } 308 309 h0 += a 310 h1 += b 311 h2 += c 312 h3 += d 313 h4 += e 314 h5 += f 315 h6 += g 316 h7 += h 317 318 p = p[chunk:] 319 } 320 321 dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 322 } 323 324 var _K = []uint32{ 325 0x428a2f98, 326 0x71374491, 327 0xb5c0fbcf, 328 0xe9b5dba5, 329 0x3956c25b, 330 0x59f111f1, 331 0x923f82a4, 332 0xab1c5ed5, 333 0xd807aa98, 334 0x12835b01, 335 0x243185be, 336 0x550c7dc3, 337 0x72be5d74, 338 0x80deb1fe, 339 0x9bdc06a7, 340 0xc19bf174, 341 0xe49b69c1, 342 0xefbe4786, 343 0x0fc19dc6, 344 0x240ca1cc, 345 0x2de92c6f, 346 0x4a7484aa, 347 0x5cb0a9dc, 348 0x76f988da, 349 0x983e5152, 350 0xa831c66d, 351 0xb00327c8, 352 0xbf597fc7, 353 0xc6e00bf3, 354 0xd5a79147, 355 0x06ca6351, 356 0x14292967, 357 0x27b70a85, 358 0x2e1b2138, 359 0x4d2c6dfc, 360 0x53380d13, 361 0x650a7354, 362 0x766a0abb, 363 0x81c2c92e, 364 0x92722c85, 365 0xa2bfe8a1, 366 0xa81a664b, 367 0xc24b8b70, 368 0xc76c51a3, 369 0xd192e819, 370 0xd6990624, 371 0xf40e3585, 372 0x106aa070, 373 0x19a4c116, 374 0x1e376c08, 375 0x2748774c, 376 0x34b0bcb5, 377 0x391c0cb3, 378 0x4ed8aa4a, 379 0x5b9cca4f, 380 0x682e6ff3, 381 0x748f82ee, 382 0x78a5636f, 383 0x84c87814, 384 0x8cc70208, 385 0x90befffa, 386 0xa4506ceb, 387 0xbef9a3f7, 388 0xc67178f2, 389 } 390 391 const ( 392 magic256 = "sha\x03" 393 marshaledSize = len(magic256) + 8*4 + chunk + 8 394 ) 395 396 func (d *digest) MarshalBinary() ([]byte, error) { 397 b := make([]byte, 0, marshaledSize) 398 b = append(b, magic256...) 399 b = appendUint32(b, d.h[0]) 400 b = appendUint32(b, d.h[1]) 401 b = appendUint32(b, d.h[2]) 402 b = appendUint32(b, d.h[3]) 403 b = appendUint32(b, d.h[4]) 404 b = appendUint32(b, d.h[5]) 405 b = appendUint32(b, d.h[6]) 406 b = appendUint32(b, d.h[7]) 407 b = append(b, d.x[:d.nx]...) 408 b = b[:len(b)+len(d.x)-d.nx] // already zero 409 b = appendUint64(b, d.len) 410 return b, nil 411 } 412 413 func (d *digest) UnmarshalBinary(b []byte) error { 414 if len(b) < len(magic256) || string(b[:len(magic256)]) != magic256 { 415 return errors.New("crypto/sha256: invalid hash state identifier") 416 } 417 if len(b) != marshaledSize { 418 return errors.New("crypto/sha256: invalid hash state size") 419 } 420 b = b[len(magic256):] 421 b, d.h[0] = consumeUint32(b) 422 b, d.h[1] = consumeUint32(b) 423 b, d.h[2] = consumeUint32(b) 424 b, d.h[3] = consumeUint32(b) 425 b, d.h[4] = consumeUint32(b) 426 b, d.h[5] = consumeUint32(b) 427 b, d.h[6] = consumeUint32(b) 428 b, d.h[7] = consumeUint32(b) 429 b = b[copy(d.x[:], b):] 430 b, d.len = consumeUint64(b) 431 d.nx = int(d.len % chunk) 432 return nil 433 } 434 435 func appendUint32(b []byte, v uint32) []byte { 436 return append(b, 437 byte(v>>24), 438 byte(v>>16), 439 byte(v>>8), 440 byte(v), 441 ) 442 } 443 444 func appendUint64(b []byte, v uint64) []byte { 445 return append(b, 446 byte(v>>56), 447 byte(v>>48), 448 byte(v>>40), 449 byte(v>>32), 450 byte(v>>24), 451 byte(v>>16), 452 byte(v>>8), 453 byte(v), 454 ) 455 } 456 457 func consumeUint64(b []byte) ([]byte, uint64) { 458 _ = b[7] 459 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 460 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 461 return b[8:], x 462 } 463 464 func consumeUint32(b []byte) ([]byte, uint32) { 465 _ = b[3] 466 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 467 return b[4:], x 468 }