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