blake2s.go 3.7 KB

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