blake2b.go 4.3 KB

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