github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/blake2s/blake2s.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 blake2s implements the BLAKE2s hash algorithm as
     6  // defined in RFC 7693.
     7  package blake2s // import "golang.org/x/crypto/blake2s"
     8  
     9  import (
    10  	"encoding/binary"
    11  	"errors"
    12  	"hash"
    13  )
    14  
    15  const (
    16  	// The blocksize of BLAKE2s in bytes.
    17  	BlockSize = 64
    18  	// The hash size of BLAKE2s-256 in bytes.
    19  	Size = 32
    20  )
    21  
    22  var errKeySize = errors.New("blake2s: invalid key size")
    23  
    24  var iv = [8]uint32{
    25  	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
    26  	0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
    27  }
    28  
    29  // Sum256 returns the BLAKE2s-256 checksum of the data.
    30  func Sum256(data []byte) [Size]byte {
    31  	var sum [Size]byte
    32  	checkSum(&sum, Size, data)
    33  	return sum
    34  }
    35  
    36  // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil
    37  // key turns the hash into a MAC. The key must between zero and 32 bytes long.
    38  func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
    39  
    40  func newDigest(hashSize int, key []byte) (*digest, error) {
    41  	if len(key) > Size {
    42  		return nil, errKeySize
    43  	}
    44  	d := &digest{
    45  		size:   hashSize,
    46  		keyLen: len(key),
    47  	}
    48  	copy(d.key[:], key)
    49  	d.Reset()
    50  	return d, nil
    51  }
    52  
    53  func checkSum(sum *[Size]byte, hashSize int, data []byte) {
    54  	var (
    55  		h [8]uint32
    56  		c [2]uint32
    57  	)
    58  
    59  	h = iv
    60  	h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24)
    61  
    62  	if length := len(data); length > BlockSize {
    63  		n := length &^ (BlockSize - 1)
    64  		if length == n {
    65  			n -= BlockSize
    66  		}
    67  		hashBlocks(&h, &c, 0, data[:n])
    68  		data = data[n:]
    69  	}
    70  
    71  	var block [BlockSize]byte
    72  	offset := copy(block[:], data)
    73  	remaining := uint32(BlockSize - offset)
    74  
    75  	if c[0] < remaining {
    76  		c[1]--
    77  	}
    78  	c[0] -= remaining
    79  
    80  	hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
    81  
    82  	for i, v := range h {
    83  		binary.LittleEndian.PutUint32(sum[4*i:], v)
    84  	}
    85  }
    86  
    87  type digest struct {
    88  	h      [8]uint32
    89  	c      [2]uint32
    90  	size   int
    91  	block  [BlockSize]byte
    92  	offset int
    93  
    94  	key    [BlockSize]byte
    95  	keyLen int
    96  }
    97  
    98  func (d *digest) BlockSize() int { return BlockSize }
    99  
   100  func (d *digest) Size() int { return d.size }
   101  
   102  func (d *digest) Reset() {
   103  	d.h = iv
   104  	d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24)
   105  	d.offset, d.c[0], d.c[1] = 0, 0, 0
   106  	if d.keyLen > 0 {
   107  		d.block = d.key
   108  		d.offset = BlockSize
   109  	}
   110  }
   111  
   112  func (d *digest) Write(p []byte) (n int, err error) {
   113  	n = len(p)
   114  
   115  	if d.offset > 0 {
   116  		remaining := BlockSize - d.offset
   117  		if n <= remaining {
   118  			d.offset += copy(d.block[d.offset:], p)
   119  			return
   120  		}
   121  		copy(d.block[d.offset:], p[:remaining])
   122  		hashBlocks(&d.h, &d.c, 0, d.block[:])
   123  		d.offset = 0
   124  		p = p[remaining:]
   125  	}
   126  
   127  	if length := len(p); length > BlockSize {
   128  		nn := length &^ (BlockSize - 1)
   129  		if length == nn {
   130  			nn -= BlockSize
   131  		}
   132  		hashBlocks(&d.h, &d.c, 0, p[:nn])
   133  		p = p[nn:]
   134  	}
   135  
   136  	d.offset += copy(d.block[:], p)
   137  	return
   138  }
   139  
   140  func (d *digest) Sum(b []byte) []byte {
   141  	var block [BlockSize]byte
   142  	h := d.h
   143  	c := d.c
   144  
   145  	copy(block[:], d.block[:d.offset])
   146  	remaining := uint32(BlockSize - d.offset)
   147  	if c[0] < remaining {
   148  		c[1]--
   149  	}
   150  	c[0] -= remaining
   151  
   152  	hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
   153  
   154  	var sum [Size]byte
   155  	for i, v := range h {
   156  		binary.LittleEndian.PutUint32(sum[4*i:], v)
   157  	}
   158  
   159  	return append(b, sum[:d.size]...)
   160  }