gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

blake2s.go (5919B)


      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 defined by RFC 7693
      6 // and the extendable output function (XOF) BLAKE2Xs.
      7 //
      8 // BLAKE2s is optimized for 8- to 32-bit platforms and produces digests of any
      9 // size between 1 and 32 bytes.
     10 // For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf
     11 // and for BLAKE2Xs see https://blake2.net/blake2x.pdf
     12 //
     13 // If you aren't sure which function you need, use BLAKE2s (Sum256 or New256).
     14 // If you need a secret-key MAC (message authentication code), use the New256
     15 // function with a non-nil key.
     16 //
     17 // BLAKE2X is a construction to compute hash values larger than 32 bytes. It
     18 // can produce hash values between 0 and 65535 bytes.
     19 package blake2s // import "golang.org/x/crypto/blake2s"
     20 
     21 import (
     22 	"encoding/binary"
     23 	"errors"
     24 	"hash"
     25 )
     26 
     27 const (
     28 	// The blocksize of BLAKE2s in bytes.
     29 	BlockSize = 64
     30 
     31 	// The hash size of BLAKE2s-256 in bytes.
     32 	Size = 32
     33 
     34 	// The hash size of BLAKE2s-128 in bytes.
     35 	Size128 = 16
     36 )
     37 
     38 var errKeySize = errors.New("blake2s: invalid key size")
     39 
     40 var iv = [8]uint32{
     41 	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
     42 	0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
     43 }
     44 
     45 // Sum256 returns the BLAKE2s-256 checksum of the data.
     46 func Sum256(data []byte) [Size]byte {
     47 	var sum [Size]byte
     48 	checkSum(&sum, Size, data)
     49 	return sum
     50 }
     51 
     52 // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil
     53 // key turns the hash into a MAC. The key must between zero and 32 bytes long.
     54 // When the key is nil, the returned hash.Hash implements BinaryMarshaler
     55 // and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
     56 func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
     57 
     58 // New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
     59 // non-empty key. Note that a 128-bit digest is too small to be secure as a
     60 // cryptographic hash and should only be used as a MAC, thus the key argument
     61 // is not optional.
     62 func New128(key []byte) (hash.Hash, error) {
     63 	if len(key) == 0 {
     64 		return nil, errors.New("blake2s: a key is required for a 128-bit hash")
     65 	}
     66 	return newDigest(Size128, key)
     67 }
     68 
     69 func newDigest(hashSize int, key []byte) (*digest, error) {
     70 	if len(key) > Size {
     71 		return nil, errKeySize
     72 	}
     73 	d := &digest{
     74 		size:   hashSize,
     75 		keyLen: len(key),
     76 	}
     77 	copy(d.key[:], key)
     78 	d.Reset()
     79 	return d, nil
     80 }
     81 
     82 func checkSum(sum *[Size]byte, hashSize int, data []byte) {
     83 	var (
     84 		h [8]uint32
     85 		c [2]uint32
     86 	)
     87 
     88 	h = iv
     89 	h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24)
     90 
     91 	if length := len(data); length > BlockSize {
     92 		n := length &^ (BlockSize - 1)
     93 		if length == n {
     94 			n -= BlockSize
     95 		}
     96 		hashBlocks(&h, &c, 0, data[:n])
     97 		data = data[n:]
     98 	}
     99 
    100 	var block [BlockSize]byte
    101 	offset := copy(block[:], data)
    102 	remaining := uint32(BlockSize - offset)
    103 
    104 	if c[0] < remaining {
    105 		c[1]--
    106 	}
    107 	c[0] -= remaining
    108 
    109 	hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
    110 
    111 	for i, v := range h {
    112 		binary.LittleEndian.PutUint32(sum[4*i:], v)
    113 	}
    114 }
    115 
    116 type digest struct {
    117 	h      [8]uint32
    118 	c      [2]uint32
    119 	size   int
    120 	block  [BlockSize]byte
    121 	offset int
    122 
    123 	key    [BlockSize]byte
    124 	keyLen int
    125 }
    126 
    127 const (
    128 	magic         = "b2s"
    129 	marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1
    130 )
    131 
    132 func (d *digest) MarshalBinary() ([]byte, error) {
    133 	if d.keyLen != 0 {
    134 		return nil, errors.New("crypto/blake2s: cannot marshal MACs")
    135 	}
    136 	b := make([]byte, 0, marshaledSize)
    137 	b = append(b, magic...)
    138 	for i := 0; i < 8; i++ {
    139 		b = appendUint32(b, d.h[i])
    140 	}
    141 	b = appendUint32(b, d.c[0])
    142 	b = appendUint32(b, d.c[1])
    143 	// Maximum value for size is 32
    144 	b = append(b, byte(d.size))
    145 	b = append(b, d.block[:]...)
    146 	b = append(b, byte(d.offset))
    147 	return b, nil
    148 }
    149 
    150 func (d *digest) UnmarshalBinary(b []byte) error {
    151 	if len(b) < len(magic) || string(b[:len(magic)]) != magic {
    152 		return errors.New("crypto/blake2s: invalid hash state identifier")
    153 	}
    154 	if len(b) != marshaledSize {
    155 		return errors.New("crypto/blake2s: invalid hash state size")
    156 	}
    157 	b = b[len(magic):]
    158 	for i := 0; i < 8; i++ {
    159 		b, d.h[i] = consumeUint32(b)
    160 	}
    161 	b, d.c[0] = consumeUint32(b)
    162 	b, d.c[1] = consumeUint32(b)
    163 	d.size = int(b[0])
    164 	b = b[1:]
    165 	copy(d.block[:], b[:BlockSize])
    166 	b = b[BlockSize:]
    167 	d.offset = int(b[0])
    168 	return nil
    169 }
    170 
    171 func (d *digest) BlockSize() int { return BlockSize }
    172 
    173 func (d *digest) Size() int { return d.size }
    174 
    175 func (d *digest) Reset() {
    176 	d.h = iv
    177 	d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24)
    178 	d.offset, d.c[0], d.c[1] = 0, 0, 0
    179 	if d.keyLen > 0 {
    180 		d.block = d.key
    181 		d.offset = BlockSize
    182 	}
    183 }
    184 
    185 func (d *digest) Write(p []byte) (n int, err error) {
    186 	n = len(p)
    187 
    188 	if d.offset > 0 {
    189 		remaining := BlockSize - d.offset
    190 		if n <= remaining {
    191 			d.offset += copy(d.block[d.offset:], p)
    192 			return
    193 		}
    194 		copy(d.block[d.offset:], p[:remaining])
    195 		hashBlocks(&d.h, &d.c, 0, d.block[:])
    196 		d.offset = 0
    197 		p = p[remaining:]
    198 	}
    199 
    200 	if length := len(p); length > BlockSize {
    201 		nn := length &^ (BlockSize - 1)
    202 		if length == nn {
    203 			nn -= BlockSize
    204 		}
    205 		hashBlocks(&d.h, &d.c, 0, p[:nn])
    206 		p = p[nn:]
    207 	}
    208 
    209 	d.offset += copy(d.block[:], p)
    210 	return
    211 }
    212 
    213 func (d *digest) Sum(sum []byte) []byte {
    214 	var hash [Size]byte
    215 	d.finalize(&hash)
    216 	return append(sum, hash[:d.size]...)
    217 }
    218 
    219 func (d *digest) finalize(hash *[Size]byte) {
    220 	var block [BlockSize]byte
    221 	h := d.h
    222 	c := d.c
    223 
    224 	copy(block[:], d.block[:d.offset])
    225 	remaining := uint32(BlockSize - d.offset)
    226 	if c[0] < remaining {
    227 		c[1]--
    228 	}
    229 	c[0] -= remaining
    230 
    231 	hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
    232 	for i, v := range h {
    233 		binary.LittleEndian.PutUint32(hash[4*i:], v)
    234 	}
    235 }
    236 
    237 func appendUint32(b []byte, x uint32) []byte {
    238 	var a [4]byte
    239 	binary.BigEndian.PutUint32(a[:], x)
    240 	return append(b, a[:]...)
    241 }
    242 
    243 func consumeUint32(b []byte) ([]byte, uint32) {
    244 	x := binary.BigEndian.Uint32(b)
    245 	return b[4:], x
    246 }