github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/crypto/sha512/sha512.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 sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 6 // hash algorithms as defined in FIPS 180-4. 7 // 8 // All the hash.Hash implementations returned by this package also 9 // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to 10 // marshal and unmarshal the internal state of the hash. 11 package sha512 12 13 import ( 14 "crypto" 15 "errors" 16 "hash" 17 ) 18 19 func init() { 20 crypto.RegisterHash(crypto.SHA384, New384) 21 crypto.RegisterHash(crypto.SHA512, New) 22 crypto.RegisterHash(crypto.SHA512_224, New512_224) 23 crypto.RegisterHash(crypto.SHA512_256, New512_256) 24 } 25 26 const ( 27 // Size is the size, in bytes, of a SHA-512 checksum. 28 Size = 64 29 30 // Size224 is the size, in bytes, of a SHA-512/224 checksum. 31 Size224 = 28 32 33 // Size256 is the size, in bytes, of a SHA-512/256 checksum. 34 Size256 = 32 35 36 // Size384 is the size, in bytes, of a SHA-384 checksum. 37 Size384 = 48 38 39 // BlockSize is the block size, in bytes, of the SHA-512/224, 40 // SHA-512/256, SHA-384 and SHA-512 hash functions. 41 BlockSize = 128 42 ) 43 44 const ( 45 chunk = 128 46 init0 = 0x6a09e667f3bcc908 47 init1 = 0xbb67ae8584caa73b 48 init2 = 0x3c6ef372fe94f82b 49 init3 = 0xa54ff53a5f1d36f1 50 init4 = 0x510e527fade682d1 51 init5 = 0x9b05688c2b3e6c1f 52 init6 = 0x1f83d9abfb41bd6b 53 init7 = 0x5be0cd19137e2179 54 init0_224 = 0x8c3d37c819544da2 55 init1_224 = 0x73e1996689dcd4d6 56 init2_224 = 0x1dfab7ae32ff9c82 57 init3_224 = 0x679dd514582f9fcf 58 init4_224 = 0x0f6d2b697bd44da8 59 init5_224 = 0x77e36f7304c48942 60 init6_224 = 0x3f9d85a86a1d36c8 61 init7_224 = 0x1112e6ad91d692a1 62 init0_256 = 0x22312194fc2bf72c 63 init1_256 = 0x9f555fa3c84c64c2 64 init2_256 = 0x2393b86b6f53b151 65 init3_256 = 0x963877195940eabd 66 init4_256 = 0x96283ee2a88effe3 67 init5_256 = 0xbe5e1e2553863992 68 init6_256 = 0x2b0199fc2c85b8aa 69 init7_256 = 0x0eb72ddc81c52ca2 70 init0_384 = 0xcbbb9d5dc1059ed8 71 init1_384 = 0x629a292a367cd507 72 init2_384 = 0x9159015a3070dd17 73 init3_384 = 0x152fecd8f70e5939 74 init4_384 = 0x67332667ffc00b31 75 init5_384 = 0x8eb44a8768581511 76 init6_384 = 0xdb0c2e0d64f98fa7 77 init7_384 = 0x47b5481dbefa4fa4 78 ) 79 80 // digest represents the partial evaluation of a checksum. 81 type digest struct { 82 h [8]uint64 83 x [chunk]byte 84 nx int 85 len uint64 86 function crypto.Hash 87 } 88 89 func (d *digest) Reset() { 90 switch d.function { 91 case crypto.SHA384: 92 d.h[0] = init0_384 93 d.h[1] = init1_384 94 d.h[2] = init2_384 95 d.h[3] = init3_384 96 d.h[4] = init4_384 97 d.h[5] = init5_384 98 d.h[6] = init6_384 99 d.h[7] = init7_384 100 case crypto.SHA512_224: 101 d.h[0] = init0_224 102 d.h[1] = init1_224 103 d.h[2] = init2_224 104 d.h[3] = init3_224 105 d.h[4] = init4_224 106 d.h[5] = init5_224 107 d.h[6] = init6_224 108 d.h[7] = init7_224 109 case crypto.SHA512_256: 110 d.h[0] = init0_256 111 d.h[1] = init1_256 112 d.h[2] = init2_256 113 d.h[3] = init3_256 114 d.h[4] = init4_256 115 d.h[5] = init5_256 116 d.h[6] = init6_256 117 d.h[7] = init7_256 118 default: 119 d.h[0] = init0 120 d.h[1] = init1 121 d.h[2] = init2 122 d.h[3] = init3 123 d.h[4] = init4 124 d.h[5] = init5 125 d.h[6] = init6 126 d.h[7] = init7 127 } 128 d.nx = 0 129 d.len = 0 130 } 131 132 const ( 133 magic384 = "sha\x04" 134 magic512_224 = "sha\x05" 135 magic512_256 = "sha\x06" 136 magic512 = "sha\x07" 137 marshaledSize = len(magic512) + 8*8 + chunk + 8 138 ) 139 140 func (d *digest) MarshalBinary() ([]byte, error) { 141 b := make([]byte, 0, marshaledSize) 142 switch d.function { 143 case crypto.SHA384: 144 b = append(b, magic384...) 145 case crypto.SHA512_224: 146 b = append(b, magic512_224...) 147 case crypto.SHA512_256: 148 b = append(b, magic512_256...) 149 case crypto.SHA512: 150 b = append(b, magic512...) 151 default: 152 return nil, errors.New("crypto/sha512: invalid hash function") 153 } 154 b = appendUint64(b, d.h[0]) 155 b = appendUint64(b, d.h[1]) 156 b = appendUint64(b, d.h[2]) 157 b = appendUint64(b, d.h[3]) 158 b = appendUint64(b, d.h[4]) 159 b = appendUint64(b, d.h[5]) 160 b = appendUint64(b, d.h[6]) 161 b = appendUint64(b, d.h[7]) 162 b = append(b, d.x[:d.nx]...) 163 b = b[:len(b)+len(d.x)-int(d.nx)] // already zero 164 b = appendUint64(b, d.len) 165 return b, nil 166 } 167 168 func (d *digest) UnmarshalBinary(b []byte) error { 169 if len(b) < len(magic512) { 170 return errors.New("crypto/sha512: invalid hash state identifier") 171 } 172 switch { 173 case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384: 174 case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224: 175 case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256: 176 case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512: 177 default: 178 return errors.New("crypto/sha512: invalid hash state identifier") 179 } 180 if len(b) != marshaledSize { 181 return errors.New("crypto/sha512: invalid hash state size") 182 } 183 b = b[len(magic512):] 184 b, d.h[0] = consumeUint64(b) 185 b, d.h[1] = consumeUint64(b) 186 b, d.h[2] = consumeUint64(b) 187 b, d.h[3] = consumeUint64(b) 188 b, d.h[4] = consumeUint64(b) 189 b, d.h[5] = consumeUint64(b) 190 b, d.h[6] = consumeUint64(b) 191 b, d.h[7] = consumeUint64(b) 192 b = b[copy(d.x[:], b):] 193 b, d.len = consumeUint64(b) 194 d.nx = int(d.len) % chunk 195 return nil 196 } 197 198 func appendUint64(b []byte, x uint64) []byte { 199 a := [8]byte{ 200 byte(x >> 56), 201 byte(x >> 48), 202 byte(x >> 40), 203 byte(x >> 32), 204 byte(x >> 24), 205 byte(x >> 16), 206 byte(x >> 8), 207 byte(x), 208 } 209 return append(b, a[:]...) 210 } 211 212 func consumeUint64(b []byte) ([]byte, uint64) { 213 _ = b[7] 214 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 215 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 216 return b[8:], x 217 } 218 219 // New returns a new hash.Hash computing the SHA-512 checksum. 220 func New() hash.Hash { 221 d := &digest{function: crypto.SHA512} 222 d.Reset() 223 return d 224 } 225 226 // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum. 227 func New512_224() hash.Hash { 228 d := &digest{function: crypto.SHA512_224} 229 d.Reset() 230 return d 231 } 232 233 // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum. 234 func New512_256() hash.Hash { 235 d := &digest{function: crypto.SHA512_256} 236 d.Reset() 237 return d 238 } 239 240 // New384 returns a new hash.Hash computing the SHA-384 checksum. 241 func New384() hash.Hash { 242 d := &digest{function: crypto.SHA384} 243 d.Reset() 244 return d 245 } 246 247 func (d *digest) Size() int { 248 switch d.function { 249 case crypto.SHA512_224: 250 return Size224 251 case crypto.SHA512_256: 252 return Size256 253 case crypto.SHA384: 254 return Size384 255 default: 256 return Size 257 } 258 } 259 260 func (d *digest) BlockSize() int { return BlockSize } 261 262 func (d *digest) Write(p []byte) (nn int, err error) { 263 nn = len(p) 264 d.len += uint64(nn) 265 if d.nx > 0 { 266 n := copy(d.x[d.nx:], p) 267 d.nx += n 268 if d.nx == chunk { 269 block(d, d.x[:]) 270 d.nx = 0 271 } 272 p = p[n:] 273 } 274 if len(p) >= chunk { 275 n := len(p) &^ (chunk - 1) 276 block(d, p[:n]) 277 p = p[n:] 278 } 279 if len(p) > 0 { 280 d.nx = copy(d.x[:], p) 281 } 282 return 283 } 284 285 func (d0 *digest) Sum(in []byte) []byte { 286 // Make a copy of d0 so that caller can keep writing and summing. 287 d := new(digest) 288 *d = *d0 289 hash := d.checkSum() 290 switch d.function { 291 case crypto.SHA384: 292 return append(in, hash[:Size384]...) 293 case crypto.SHA512_224: 294 return append(in, hash[:Size224]...) 295 case crypto.SHA512_256: 296 return append(in, hash[:Size256]...) 297 default: 298 return append(in, hash[:]...) 299 } 300 } 301 302 func (d *digest) checkSum() [Size]byte { 303 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. 304 len := d.len 305 var tmp [128]byte 306 tmp[0] = 0x80 307 if len%128 < 112 { 308 d.Write(tmp[0 : 112-len%128]) 309 } else { 310 d.Write(tmp[0 : 128+112-len%128]) 311 } 312 313 // Length in bits. 314 len <<= 3 315 for i := uint(0); i < 16; i++ { 316 tmp[i] = byte(len >> (120 - 8*i)) 317 } 318 d.Write(tmp[0:16]) 319 320 if d.nx != 0 { 321 panic("d.nx != 0") 322 } 323 324 h := d.h[:] 325 if d.function == crypto.SHA384 { 326 h = d.h[:6] 327 } 328 329 var digest [Size]byte 330 for i, s := range h { 331 digest[i*8] = byte(s >> 56) 332 digest[i*8+1] = byte(s >> 48) 333 digest[i*8+2] = byte(s >> 40) 334 digest[i*8+3] = byte(s >> 32) 335 digest[i*8+4] = byte(s >> 24) 336 digest[i*8+5] = byte(s >> 16) 337 digest[i*8+6] = byte(s >> 8) 338 digest[i*8+7] = byte(s) 339 } 340 341 return digest 342 } 343 344 // Sum512 returns the SHA512 checksum of the data. 345 func Sum512(data []byte) [Size]byte { 346 d := digest{function: crypto.SHA512} 347 d.Reset() 348 d.Write(data) 349 return d.checkSum() 350 } 351 352 // Sum384 returns the SHA384 checksum of the data. 353 func Sum384(data []byte) (sum384 [Size384]byte) { 354 d := digest{function: crypto.SHA384} 355 d.Reset() 356 d.Write(data) 357 sum := d.checkSum() 358 copy(sum384[:], sum[:Size384]) 359 return 360 } 361 362 // Sum512_224 returns the Sum512/224 checksum of the data. 363 func Sum512_224(data []byte) (sum224 [Size224]byte) { 364 d := digest{function: crypto.SHA512_224} 365 d.Reset() 366 d.Write(data) 367 sum := d.checkSum() 368 copy(sum224[:], sum[:Size224]) 369 return 370 } 371 372 // Sum512_256 returns the Sum512/256 checksum of the data. 373 func Sum512_256(data []byte) (sum256 [Size256]byte) { 374 d := digest{function: crypto.SHA512_256} 375 d.Reset() 376 d.Write(data) 377 sum := d.checkSum() 378 copy(sum256[:], sum[:Size256]) 379 return 380 }