github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/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 "errors" 15 "github.com/insolar/x-crypto" 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 putUint64(x []byte, s uint64) { 199 _ = x[7] 200 x[0] = byte(s >> 56) 201 x[1] = byte(s >> 48) 202 x[2] = byte(s >> 40) 203 x[3] = byte(s >> 32) 204 x[4] = byte(s >> 24) 205 x[5] = byte(s >> 16) 206 x[6] = byte(s >> 8) 207 x[7] = byte(s) 208 } 209 210 func appendUint64(b []byte, x uint64) []byte { 211 var a [8]byte 212 putUint64(a[:], x) 213 return append(b, a[:]...) 214 } 215 216 func consumeUint64(b []byte) ([]byte, uint64) { 217 _ = b[7] 218 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 219 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 220 return b[8:], x 221 } 222 223 // New returns a new hash.Hash computing the SHA-512 checksum. 224 func New() hash.Hash { 225 d := &digest{function: crypto.SHA512} 226 d.Reset() 227 return d 228 } 229 230 // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum. 231 func New512_224() hash.Hash { 232 d := &digest{function: crypto.SHA512_224} 233 d.Reset() 234 return d 235 } 236 237 // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum. 238 func New512_256() hash.Hash { 239 d := &digest{function: crypto.SHA512_256} 240 d.Reset() 241 return d 242 } 243 244 // New384 returns a new hash.Hash computing the SHA-384 checksum. 245 func New384() hash.Hash { 246 d := &digest{function: crypto.SHA384} 247 d.Reset() 248 return d 249 } 250 251 func (d *digest) Size() int { 252 switch d.function { 253 case crypto.SHA512_224: 254 return Size224 255 case crypto.SHA512_256: 256 return Size256 257 case crypto.SHA384: 258 return Size384 259 default: 260 return Size 261 } 262 } 263 264 func (d *digest) BlockSize() int { return BlockSize } 265 266 func (d *digest) Write(p []byte) (nn int, err error) { 267 nn = len(p) 268 d.len += uint64(nn) 269 if d.nx > 0 { 270 n := copy(d.x[d.nx:], p) 271 d.nx += n 272 if d.nx == chunk { 273 block(d, d.x[:]) 274 d.nx = 0 275 } 276 p = p[n:] 277 } 278 if len(p) >= chunk { 279 n := len(p) &^ (chunk - 1) 280 block(d, p[:n]) 281 p = p[n:] 282 } 283 if len(p) > 0 { 284 d.nx = copy(d.x[:], p) 285 } 286 return 287 } 288 289 func (d *digest) Sum(in []byte) []byte { 290 // Make a copy of d so that caller can keep writing and summing. 291 d0 := new(digest) 292 *d0 = *d 293 hash := d0.checkSum() 294 switch d0.function { 295 case crypto.SHA384: 296 return append(in, hash[:Size384]...) 297 case crypto.SHA512_224: 298 return append(in, hash[:Size224]...) 299 case crypto.SHA512_256: 300 return append(in, hash[:Size256]...) 301 default: 302 return append(in, hash[:]...) 303 } 304 } 305 306 func (d *digest) checkSum() [Size]byte { 307 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. 308 len := d.len 309 var tmp [128]byte 310 tmp[0] = 0x80 311 if len%128 < 112 { 312 d.Write(tmp[0 : 112-len%128]) 313 } else { 314 d.Write(tmp[0 : 128+112-len%128]) 315 } 316 317 // Length in bits. 318 len <<= 3 319 putUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64 320 putUint64(tmp[8:], len) 321 d.Write(tmp[0:16]) 322 323 if d.nx != 0 { 324 panic("d.nx != 0") 325 } 326 327 var digest [Size]byte 328 putUint64(digest[0:], d.h[0]) 329 putUint64(digest[8:], d.h[1]) 330 putUint64(digest[16:], d.h[2]) 331 putUint64(digest[24:], d.h[3]) 332 putUint64(digest[32:], d.h[4]) 333 putUint64(digest[40:], d.h[5]) 334 if d.function != crypto.SHA384 { 335 putUint64(digest[48:], d.h[6]) 336 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 d := digest{function: crypto.SHA512} 345 d.Reset() 346 d.Write(data) 347 return d.checkSum() 348 } 349 350 // Sum384 returns the SHA384 checksum of the data. 351 func Sum384(data []byte) (sum384 [Size384]byte) { 352 d := digest{function: crypto.SHA384} 353 d.Reset() 354 d.Write(data) 355 sum := d.checkSum() 356 copy(sum384[:], sum[:Size384]) 357 return 358 } 359 360 // Sum512_224 returns the Sum512/224 checksum of the data. 361 func Sum512_224(data []byte) (sum224 [Size224]byte) { 362 d := digest{function: crypto.SHA512_224} 363 d.Reset() 364 d.Write(data) 365 sum := d.checkSum() 366 copy(sum224[:], sum[:Size224]) 367 return 368 } 369 370 // Sum512_256 returns the Sum512/256 checksum of the data. 371 func Sum512_256(data []byte) (sum256 [Size256]byte) { 372 d := digest{function: crypto.SHA512_256} 373 d.Reset() 374 d.Write(data) 375 sum := d.checkSum() 376 copy(sum256[:], sum[:Size256]) 377 return 378 }