Source file src/crypto/sha512/sha512.go

     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  	"errors"
    17  	"hash"
    18  	"internal/byteorder"
    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 = byteorder.BeAppendUint64(b, d.h[0])
   157  	b = byteorder.BeAppendUint64(b, d.h[1])
   158  	b = byteorder.BeAppendUint64(b, d.h[2])
   159  	b = byteorder.BeAppendUint64(b, d.h[3])
   160  	b = byteorder.BeAppendUint64(b, d.h[4])
   161  	b = byteorder.BeAppendUint64(b, d.h[5])
   162  	b = byteorder.BeAppendUint64(b, d.h[6])
   163  	b = byteorder.BeAppendUint64(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 = byteorder.BeAppendUint64(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  	return b[8:], byteorder.BeUint64(b)
   202  }
   203  
   204  // New returns a new hash.Hash computing the SHA-512 checksum.
   205  func New() hash.Hash {
   206  	if boring.Enabled {
   207  		return boring.NewSHA512()
   208  	}
   209  	d := &digest{function: crypto.SHA512}
   210  	d.Reset()
   211  	return d
   212  }
   213  
   214  // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
   215  func New512_224() hash.Hash {
   216  	d := &digest{function: crypto.SHA512_224}
   217  	d.Reset()
   218  	return d
   219  }
   220  
   221  // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
   222  func New512_256() hash.Hash {
   223  	d := &digest{function: crypto.SHA512_256}
   224  	d.Reset()
   225  	return d
   226  }
   227  
   228  // New384 returns a new hash.Hash computing the SHA-384 checksum.
   229  func New384() hash.Hash {
   230  	if boring.Enabled {
   231  		return boring.NewSHA384()
   232  	}
   233  	d := &digest{function: crypto.SHA384}
   234  	d.Reset()
   235  	return d
   236  }
   237  
   238  func (d *digest) Size() int {
   239  	switch d.function {
   240  	case crypto.SHA512_224:
   241  		return Size224
   242  	case crypto.SHA512_256:
   243  		return Size256
   244  	case crypto.SHA384:
   245  		return Size384
   246  	default:
   247  		return Size
   248  	}
   249  }
   250  
   251  func (d *digest) BlockSize() int { return BlockSize }
   252  
   253  func (d *digest) Write(p []byte) (nn int, err error) {
   254  	if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
   255  		boring.Unreachable()
   256  	}
   257  	nn = len(p)
   258  	d.len += uint64(nn)
   259  	if d.nx > 0 {
   260  		n := copy(d.x[d.nx:], p)
   261  		d.nx += n
   262  		if d.nx == chunk {
   263  			block(d, d.x[:])
   264  			d.nx = 0
   265  		}
   266  		p = p[n:]
   267  	}
   268  	if len(p) >= chunk {
   269  		n := len(p) &^ (chunk - 1)
   270  		block(d, p[:n])
   271  		p = p[n:]
   272  	}
   273  	if len(p) > 0 {
   274  		d.nx = copy(d.x[:], p)
   275  	}
   276  	return
   277  }
   278  
   279  func (d *digest) Sum(in []byte) []byte {
   280  	if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
   281  		boring.Unreachable()
   282  	}
   283  	// Make a copy of d so that caller can keep writing and summing.
   284  	d0 := new(digest)
   285  	*d0 = *d
   286  	hash := d0.checkSum()
   287  	switch d0.function {
   288  	case crypto.SHA384:
   289  		return append(in, hash[:Size384]...)
   290  	case crypto.SHA512_224:
   291  		return append(in, hash[:Size224]...)
   292  	case crypto.SHA512_256:
   293  		return append(in, hash[:Size256]...)
   294  	default:
   295  		return append(in, hash[:]...)
   296  	}
   297  }
   298  
   299  func (d *digest) checkSum() [Size]byte {
   300  	// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
   301  	len := d.len
   302  	var tmp [128 + 16]byte // padding + length buffer
   303  	tmp[0] = 0x80
   304  	var t uint64
   305  	if len%128 < 112 {
   306  		t = 112 - len%128
   307  	} else {
   308  		t = 128 + 112 - len%128
   309  	}
   310  
   311  	// Length in bits.
   312  	len <<= 3
   313  	padlen := tmp[:t+16]
   314  	// Upper 64 bits are always zero, because len variable has type uint64,
   315  	// and tmp is already zeroed at that index, so we can skip updating it.
   316  	// byteorder.BePutUint64(padlen[t+0:], 0)
   317  	byteorder.BePutUint64(padlen[t+8:], len)
   318  	d.Write(padlen)
   319  
   320  	if d.nx != 0 {
   321  		panic("d.nx != 0")
   322  	}
   323  
   324  	var digest [Size]byte
   325  	byteorder.BePutUint64(digest[0:], d.h[0])
   326  	byteorder.BePutUint64(digest[8:], d.h[1])
   327  	byteorder.BePutUint64(digest[16:], d.h[2])
   328  	byteorder.BePutUint64(digest[24:], d.h[3])
   329  	byteorder.BePutUint64(digest[32:], d.h[4])
   330  	byteorder.BePutUint64(digest[40:], d.h[5])
   331  	if d.function != crypto.SHA384 {
   332  		byteorder.BePutUint64(digest[48:], d.h[6])
   333  		byteorder.BePutUint64(digest[56:], d.h[7])
   334  	}
   335  
   336  	return digest
   337  }
   338  
   339  // Sum512 returns the SHA512 checksum of the data.
   340  func Sum512(data []byte) [Size]byte {
   341  	if boring.Enabled {
   342  		return boring.SHA512(data)
   343  	}
   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) [Size384]byte {
   352  	if boring.Enabled {
   353  		return boring.SHA384(data)
   354  	}
   355  	d := digest{function: crypto.SHA384}
   356  	d.Reset()
   357  	d.Write(data)
   358  	sum := d.checkSum()
   359  	ap := (*[Size384]byte)(sum[:])
   360  	return *ap
   361  }
   362  
   363  // Sum512_224 returns the Sum512/224 checksum of the data.
   364  func Sum512_224(data []byte) [Size224]byte {
   365  	d := digest{function: crypto.SHA512_224}
   366  	d.Reset()
   367  	d.Write(data)
   368  	sum := d.checkSum()
   369  	ap := (*[Size224]byte)(sum[:])
   370  	return *ap
   371  }
   372  
   373  // Sum512_256 returns the Sum512/256 checksum of the data.
   374  func Sum512_256(data []byte) [Size256]byte {
   375  	d := digest{function: crypto.SHA512_256}
   376  	d.Reset()
   377  	d.Write(data)
   378  	sum := d.checkSum()
   379  	ap := (*[Size256]byte)(sum[:])
   380  	return *ap
   381  }
   382  

View as plain text