gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }