blake2b.go 7.3 KB

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