You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

290 lines
7.2 KiB

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