github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/blake2b/blake2b.go (about)

     1  // Copyright 2016 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 blake2b implements the BLAKE2b hash algorithm as
     6  // defined in RFC 7693.
     7  package blake2b // import "golang.org/x/crypto/blake2b"
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"hash"
    13  )
    14  
    15  const (
    16  	// The blocksize of BLAKE2b in bytes.
    17  	BlockSize = 128
    18  	// The hash size of BLAKE2b-512 in bytes.
    19  	Size = 64
    20  	// The hash size of BLAKE2b-384 in bytes.
    21  	Size384 = 48
    22  	// The hash size of BLAKE2b-256 in bytes.
    23  	Size256 = 32
    24  )
    25  
    26  var (
    27  	useAVX2 bool
    28  	useAVX  bool
    29  	useSSE4 bool
    30  )
    31  
    32  var errKeySize = errors.New("blake2b: invalid key size")
    33  
    34  var iv = [8]uint64{
    35  	0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
    36  	0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
    37  }
    38  
    39  // Sum512 returns the BLAKE2b-512 checksum of the data.
    40  func Sum512(data []byte) [Size]byte {
    41  	var sum [Size]byte
    42  	checkSum(&sum, Size, data)
    43  	return sum
    44  }
    45  
    46  // Sum384 returns the BLAKE2b-384 checksum of the data.
    47  func Sum384(data []byte) [Size384]byte {
    48  	var sum [Size]byte
    49  	var sum384 [Size384]byte
    50  	checkSum(&sum, Size384, data)
    51  	copy(sum384[:], sum[:Size384])
    52  	return sum384
    53  }
    54  
    55  // Sum256 returns the BLAKE2b-256 checksum of the data.
    56  func Sum256(data []byte) [Size256]byte {
    57  	var sum [Size]byte
    58  	var sum256 [Size256]byte
    59  	checkSum(&sum, Size256, data)
    60  	copy(sum256[:], sum[:Size256])
    61  	return sum256
    62  }
    63  
    64  // New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
    65  // key turns the hash into a MAC. The key must between zero and 64 bytes long.
    66  func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
    67  
    68  // New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
    69  // key turns the hash into a MAC. The key must between zero and 64 bytes long.
    70  func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
    71  
    72  // New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
    73  // key turns the hash into a MAC. The key must between zero and 64 bytes long.
    74  func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
    75  
    76  func newDigest(hashSize int, key []byte) (*digest, error) {
    77  	if len(key) > Size {
    78  		return nil, errKeySize
    79  	}
    80  	d := &digest{
    81  		size:   hashSize,
    82  		keyLen: len(key),
    83  	}
    84  	copy(d.key[:], key)
    85  	d.Reset()
    86  	return d, nil
    87  }
    88  
    89  func checkSum(sum *[Size]byte, hashSize int, data []byte) {
    90  	h := iv
    91  	h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
    92  	var c [2]uint64
    93  
    94  	if length := len(data); length > BlockSize {
    95  		n := length &^ (BlockSize - 1)
    96  		if length == n {
    97  			n -= BlockSize
    98  		}
    99  		hashBlocks(&h, &c, 0, data[:n])
   100  		data = data[n:]
   101  	}
   102  
   103  	var block [BlockSize]byte
   104  	offset := copy(block[:], data)
   105  	remaining := uint64(BlockSize - offset)
   106  	if c[0] < remaining {
   107  		c[1]--
   108  	}
   109  	c[0] -= remaining
   110  
   111  	hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
   112  
   113  	for i, v := range h[:(hashSize+7)/8] {
   114  		binary.LittleEndian.PutUint64(sum[8*i:], v)
   115  	}
   116  }
   117  
   118  type digest struct {
   119  	h      [8]uint64
   120  	c      [2]uint64
   121  	size   int
   122  	block  [BlockSize]byte
   123  	offset int
   124  
   125  	key    [BlockSize]byte
   126  	keyLen int
   127  }
   128  
   129  func (d *digest) BlockSize() int { return BlockSize }
   130  
   131  func (d *digest) Size() int { return d.size }
   132  
   133  func (d *digest) Reset() {
   134  	d.h = iv
   135  	d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
   136  	d.offset, d.c[0], d.c[1] = 0, 0, 0
   137  	if d.keyLen > 0 {
   138  		d.block = d.key
   139  		d.offset = BlockSize
   140  	}
   141  }
   142  
   143  func (d *digest) Write(p []byte) (n int, err error) {
   144  	n = len(p)
   145  
   146  	if d.offset > 0 {
   147  		remaining := BlockSize - d.offset
   148  		if n <= remaining {
   149  			d.offset += copy(d.block[d.offset:], p)
   150  			return
   151  		}
   152  		copy(d.block[d.offset:], p[:remaining])
   153  		hashBlocks(&d.h, &d.c, 0, d.block[:])
   154  		d.offset = 0
   155  		p = p[remaining:]
   156  	}
   157  
   158  	if length := len(p); length > BlockSize {
   159  		nn := length &^ (BlockSize - 1)
   160  		if length == nn {
   161  			nn -= BlockSize
   162  		}
   163  		hashBlocks(&d.h, &d.c, 0, p[:nn])
   164  		p = p[nn:]
   165  	}
   166  
   167  	if len(p) > 0 {
   168  		d.offset += copy(d.block[:], p)
   169  	}
   170  
   171  	return
   172  }
   173  
   174  func (d *digest) Sum(b []byte) []byte {
   175  	var block [BlockSize]byte
   176  	copy(block[:], d.block[:d.offset])
   177  	remaining := uint64(BlockSize - d.offset)
   178  
   179  	c := d.c
   180  	if c[0] < remaining {
   181  		c[1]--
   182  	}
   183  	c[0] -= remaining
   184  
   185  	h := d.h
   186  	hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
   187  
   188  	var sum [Size]byte
   189  	for i, v := range h[:(d.size+7)/8] {
   190  		binary.LittleEndian.PutUint64(sum[8*i:], v)
   191  	}
   192  
   193  	return append(b, sum[:d.size]...)
   194  }