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  	"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  }
   385  

View as plain text