Home | History | Annotate | Download | only in sha512
      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 }
    381