// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256 // hash algorithms as defined in FIPS 180-4. // // All the hash.Hash implementations returned by this package also // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to // marshal and unmarshal the internal state of the hash.
package sha512 import ( ) func init() { crypto.RegisterHash(crypto.SHA384, New384) crypto.RegisterHash(crypto.SHA512, New) crypto.RegisterHash(crypto.SHA512_224, New512_224) crypto.RegisterHash(crypto.SHA512_256, New512_256) } const ( // Size is the size, in bytes, of a SHA-512 checksum. Size = 64 // Size224 is the size, in bytes, of a SHA-512/224 checksum. Size224 = 28 // Size256 is the size, in bytes, of a SHA-512/256 checksum. Size256 = 32 // Size384 is the size, in bytes, of a SHA-384 checksum. Size384 = 48 // BlockSize is the block size, in bytes, of the SHA-512/224, // SHA-512/256, SHA-384 and SHA-512 hash functions. BlockSize = 128 ) const ( chunk = 128 init0 = 0x6a09e667f3bcc908 init1 = 0xbb67ae8584caa73b init2 = 0x3c6ef372fe94f82b init3 = 0xa54ff53a5f1d36f1 init4 = 0x510e527fade682d1 init5 = 0x9b05688c2b3e6c1f init6 = 0x1f83d9abfb41bd6b init7 = 0x5be0cd19137e2179 init0_224 = 0x8c3d37c819544da2 init1_224 = 0x73e1996689dcd4d6 init2_224 = 0x1dfab7ae32ff9c82 init3_224 = 0x679dd514582f9fcf init4_224 = 0x0f6d2b697bd44da8 init5_224 = 0x77e36f7304c48942 init6_224 = 0x3f9d85a86a1d36c8 init7_224 = 0x1112e6ad91d692a1 init0_256 = 0x22312194fc2bf72c init1_256 = 0x9f555fa3c84c64c2 init2_256 = 0x2393b86b6f53b151 init3_256 = 0x963877195940eabd init4_256 = 0x96283ee2a88effe3 init5_256 = 0xbe5e1e2553863992 init6_256 = 0x2b0199fc2c85b8aa init7_256 = 0x0eb72ddc81c52ca2 init0_384 = 0xcbbb9d5dc1059ed8 init1_384 = 0x629a292a367cd507 init2_384 = 0x9159015a3070dd17 init3_384 = 0x152fecd8f70e5939 init4_384 = 0x67332667ffc00b31 init5_384 = 0x8eb44a8768581511 init6_384 = 0xdb0c2e0d64f98fa7 init7_384 = 0x47b5481dbefa4fa4 ) // digest represents the partial evaluation of a checksum. type digest struct { h [8]uint64 x [chunk]byte nx int len uint64 function crypto.Hash } func ( *digest) () { switch .function { case crypto.SHA384: .h[0] = init0_384 .h[1] = init1_384 .h[2] = init2_384 .h[3] = init3_384 .h[4] = init4_384 .h[5] = init5_384 .h[6] = init6_384 .h[7] = init7_384 case crypto.SHA512_224: .h[0] = init0_224 .h[1] = init1_224 .h[2] = init2_224 .h[3] = init3_224 .h[4] = init4_224 .h[5] = init5_224 .h[6] = init6_224 .h[7] = init7_224 case crypto.SHA512_256: .h[0] = init0_256 .h[1] = init1_256 .h[2] = init2_256 .h[3] = init3_256 .h[4] = init4_256 .h[5] = init5_256 .h[6] = init6_256 .h[7] = init7_256 default: .h[0] = init0 .h[1] = init1 .h[2] = init2 .h[3] = init3 .h[4] = init4 .h[5] = init5 .h[6] = init6 .h[7] = init7 } .nx = 0 .len = 0 } const ( magic384 = "sha\x04" magic512_224 = "sha\x05" magic512_256 = "sha\x06" magic512 = "sha\x07" marshaledSize = len(magic512) + 8*8 + chunk + 8 ) func ( *digest) () ([]byte, error) { := make([]byte, 0, marshaledSize) switch .function { case crypto.SHA384: = append(, magic384...) case crypto.SHA512_224: = append(, magic512_224...) case crypto.SHA512_256: = append(, magic512_256...) case crypto.SHA512: = append(, magic512...) default: return nil, errors.New("crypto/sha512: invalid hash function") } = byteorder.BeAppendUint64(, .h[0]) = byteorder.BeAppendUint64(, .h[1]) = byteorder.BeAppendUint64(, .h[2]) = byteorder.BeAppendUint64(, .h[3]) = byteorder.BeAppendUint64(, .h[4]) = byteorder.BeAppendUint64(, .h[5]) = byteorder.BeAppendUint64(, .h[6]) = byteorder.BeAppendUint64(, .h[7]) = append(, .x[:.nx]...) = [:len()+len(.x)-.nx] // already zero = byteorder.BeAppendUint64(, .len) return , nil } func ( *digest) ( []byte) error { if len() < len(magic512) { return errors.New("crypto/sha512: invalid hash state identifier") } switch { case .function == crypto.SHA384 && string([:len(magic384)]) == magic384: case .function == crypto.SHA512_224 && string([:len(magic512_224)]) == magic512_224: case .function == crypto.SHA512_256 && string([:len(magic512_256)]) == magic512_256: case .function == crypto.SHA512 && string([:len(magic512)]) == magic512: default: return errors.New("crypto/sha512: invalid hash state identifier") } if len() != marshaledSize { return errors.New("crypto/sha512: invalid hash state size") } = [len(magic512):] , .h[0] = consumeUint64() , .h[1] = consumeUint64() , .h[2] = consumeUint64() , .h[3] = consumeUint64() , .h[4] = consumeUint64() , .h[5] = consumeUint64() , .h[6] = consumeUint64() , .h[7] = consumeUint64() = [copy(.x[:], ):] , .len = consumeUint64() .nx = int(.len % chunk) return nil } func consumeUint64( []byte) ([]byte, uint64) { return [8:], byteorder.BeUint64() } // New returns a new hash.Hash computing the SHA-512 checksum. func () hash.Hash { if boring.Enabled { return boring.NewSHA512() } := &digest{function: crypto.SHA512} .Reset() return } // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum. func () hash.Hash { := &digest{function: crypto.SHA512_224} .Reset() return } // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum. func () hash.Hash { := &digest{function: crypto.SHA512_256} .Reset() return } // New384 returns a new hash.Hash computing the SHA-384 checksum. func () hash.Hash { if boring.Enabled { return boring.NewSHA384() } := &digest{function: crypto.SHA384} .Reset() return } func ( *digest) () int { switch .function { case crypto.SHA512_224: return Size224 case crypto.SHA512_256: return Size256 case crypto.SHA384: return Size384 default: return Size } } func ( *digest) () int { return BlockSize } func ( *digest) ( []byte) ( int, error) { if .function != crypto.SHA512_224 && .function != crypto.SHA512_256 { boring.Unreachable() } = len() .len += uint64() if .nx > 0 { := copy(.x[.nx:], ) .nx += if .nx == chunk { block(, .x[:]) .nx = 0 } = [:] } if len() >= chunk { := len() &^ (chunk - 1) block(, [:]) = [:] } if len() > 0 { .nx = copy(.x[:], ) } return } func ( *digest) ( []byte) []byte { if .function != crypto.SHA512_224 && .function != crypto.SHA512_256 { boring.Unreachable() } // Make a copy of d so that caller can keep writing and summing. := new(digest) * = * := .checkSum() switch .function { case crypto.SHA384: return append(, [:Size384]...) case crypto.SHA512_224: return append(, [:Size224]...) case crypto.SHA512_256: return append(, [:Size256]...) default: return append(, [:]...) } } func ( *digest) () [Size]byte { // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128. := .len var [128 + 16]byte // padding + length buffer [0] = 0x80 var uint64 if %128 < 112 { = 112 - %128 } else { = 128 + 112 - %128 } // Length in bits. <<= 3 := [:+16] // Upper 64 bits are always zero, because len variable has type uint64, // and tmp is already zeroed at that index, so we can skip updating it. // byteorder.BePutUint64(padlen[t+0:], 0) byteorder.BePutUint64([+8:], ) .Write() if .nx != 0 { panic("d.nx != 0") } var [Size]byte byteorder.BePutUint64([0:], .h[0]) byteorder.BePutUint64([8:], .h[1]) byteorder.BePutUint64([16:], .h[2]) byteorder.BePutUint64([24:], .h[3]) byteorder.BePutUint64([32:], .h[4]) byteorder.BePutUint64([40:], .h[5]) if .function != crypto.SHA384 { byteorder.BePutUint64([48:], .h[6]) byteorder.BePutUint64([56:], .h[7]) } return } // Sum512 returns the SHA512 checksum of the data. func ( []byte) [Size]byte { if boring.Enabled { return boring.SHA512() } := digest{function: crypto.SHA512} .Reset() .Write() return .checkSum() } // Sum384 returns the SHA384 checksum of the data. func ( []byte) [Size384]byte { if boring.Enabled { return boring.SHA384() } := digest{function: crypto.SHA384} .Reset() .Write() := .checkSum() := (*[Size384]byte)([:]) return * } // Sum512_224 returns the Sum512/224 checksum of the data. func ( []byte) [Size224]byte { := digest{function: crypto.SHA512_224} .Reset() .Write() := .checkSum() := (*[Size224]byte)([:]) return * } // Sum512_256 returns the Sum512/256 checksum of the data. func ( []byte) [Size256]byte { := digest{function: crypto.SHA512_256} .Reset() .Write() := .checkSum() := (*[Size256]byte)([:]) return * }