blake2b.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 be 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 be 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 be 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 be 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. // F is a compression function for BLAKE2b. It takes as an argument the state
  86. // vector `h`, message block vector `m`, offset counter `t`, final block indicator
  87. // flag `f`, and number of rounds `rounds`. The state vector provided as the first
  88. // parameter is modified by the function.
  89. func F(h *[8]uint64, m [16]uint64, c [2]uint64, final bool, rounds uint32) {
  90. var flag uint64
  91. if final {
  92. flag = 0xFFFFFFFFFFFFFFFF
  93. }
  94. f(h, &m, c[0], c[1], flag, uint64(rounds))
  95. }
  96. func newDigest(hashSize int, key []byte) (*digest, error) {
  97. if hashSize < 1 || hashSize > Size {
  98. return nil, errHashSize
  99. }
  100. if len(key) > Size {
  101. return nil, errKeySize
  102. }
  103. d := &digest{
  104. size: hashSize,
  105. keyLen: len(key),
  106. }
  107. copy(d.key[:], key)
  108. d.Reset()
  109. return d, nil
  110. }
  111. func checkSum(sum *[Size]byte, hashSize int, data []byte) {
  112. h := iv
  113. h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
  114. var c [2]uint64
  115. if length := len(data); length > BlockSize {
  116. n := length &^ (BlockSize - 1)
  117. if length == n {
  118. n -= BlockSize
  119. }
  120. hashBlocks(&h, &c, 0, data[:n])
  121. data = data[n:]
  122. }
  123. var block [BlockSize]byte
  124. offset := copy(block[:], data)
  125. remaining := uint64(BlockSize - offset)
  126. if c[0] < remaining {
  127. c[1]--
  128. }
  129. c[0] -= remaining
  130. hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
  131. for i, v := range h[:(hashSize+7)/8] {
  132. binary.LittleEndian.PutUint64(sum[8*i:], v)
  133. }
  134. }
  135. func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
  136. var m [16]uint64
  137. c0, c1 := c[0], c[1]
  138. for i := 0; i < len(blocks); {
  139. c0 += BlockSize
  140. if c0 < BlockSize {
  141. c1++
  142. }
  143. for j := range m {
  144. m[j] = binary.LittleEndian.Uint64(blocks[i:])
  145. i += 8
  146. }
  147. f(h, &m, c0, c1, flag, 12)
  148. }
  149. c[0], c[1] = c0, c1
  150. }
  151. type digest struct {
  152. h [8]uint64
  153. c [2]uint64
  154. size int
  155. block [BlockSize]byte
  156. offset int
  157. key [BlockSize]byte
  158. keyLen int
  159. }
  160. const (
  161. magic = "b2b"
  162. marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1
  163. )
  164. func (d *digest) MarshalBinary() ([]byte, error) {
  165. if d.keyLen != 0 {
  166. return nil, errors.New("crypto/blake2b: cannot marshal MACs")
  167. }
  168. b := make([]byte, 0, marshaledSize)
  169. b = append(b, magic...)
  170. for i := 0; i < 8; i++ {
  171. b = appendUint64(b, d.h[i])
  172. }
  173. b = appendUint64(b, d.c[0])
  174. b = appendUint64(b, d.c[1])
  175. // Maximum value for size is 64
  176. b = append(b, byte(d.size))
  177. b = append(b, d.block[:]...)
  178. b = append(b, byte(d.offset))
  179. return b, nil
  180. }
  181. func (d *digest) UnmarshalBinary(b []byte) error {
  182. if len(b) < len(magic) || string(b[:len(magic)]) != magic {
  183. return errors.New("crypto/blake2b: invalid hash state identifier")
  184. }
  185. if len(b) != marshaledSize {
  186. return errors.New("crypto/blake2b: invalid hash state size")
  187. }
  188. b = b[len(magic):]
  189. for i := 0; i < 8; i++ {
  190. b, d.h[i] = consumeUint64(b)
  191. }
  192. b, d.c[0] = consumeUint64(b)
  193. b, d.c[1] = consumeUint64(b)
  194. d.size = int(b[0])
  195. b = b[1:]
  196. copy(d.block[:], b[:BlockSize])
  197. b = b[BlockSize:]
  198. d.offset = int(b[0])
  199. return nil
  200. }
  201. func (d *digest) BlockSize() int { return BlockSize }
  202. func (d *digest) Size() int { return d.size }
  203. func (d *digest) Reset() {
  204. d.h = iv
  205. d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
  206. d.offset, d.c[0], d.c[1] = 0, 0, 0
  207. if d.keyLen > 0 {
  208. d.block = d.key
  209. d.offset = BlockSize
  210. }
  211. }
  212. func (d *digest) Write(p []byte) (n int, err error) {
  213. n = len(p)
  214. if d.offset > 0 {
  215. remaining := BlockSize - d.offset
  216. if n <= remaining {
  217. d.offset += copy(d.block[d.offset:], p)
  218. return
  219. }
  220. copy(d.block[d.offset:], p[:remaining])
  221. hashBlocks(&d.h, &d.c, 0, d.block[:])
  222. d.offset = 0
  223. p = p[remaining:]
  224. }
  225. if length := len(p); length > BlockSize {
  226. nn := length &^ (BlockSize - 1)
  227. if length == nn {
  228. nn -= BlockSize
  229. }
  230. hashBlocks(&d.h, &d.c, 0, p[:nn])
  231. p = p[nn:]
  232. }
  233. if len(p) > 0 {
  234. d.offset += copy(d.block[:], p)
  235. }
  236. return
  237. }
  238. func (d *digest) Sum(sum []byte) []byte {
  239. var hash [Size]byte
  240. d.finalize(&hash)
  241. return append(sum, hash[:d.size]...)
  242. }
  243. func (d *digest) finalize(hash *[Size]byte) {
  244. var block [BlockSize]byte
  245. copy(block[:], d.block[:d.offset])
  246. remaining := uint64(BlockSize - d.offset)
  247. c := d.c
  248. if c[0] < remaining {
  249. c[1]--
  250. }
  251. c[0] -= remaining
  252. h := d.h
  253. hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
  254. for i, v := range h {
  255. binary.LittleEndian.PutUint64(hash[8*i:], v)
  256. }
  257. }
  258. func appendUint64(b []byte, x uint64) []byte {
  259. var a [8]byte
  260. binary.BigEndian.PutUint64(a[:], x)
  261. return append(b, a[:]...)
  262. }
  263. func appendUint32(b []byte, x uint32) []byte {
  264. var a [4]byte
  265. binary.BigEndian.PutUint32(a[:], x)
  266. return append(b, a[:]...)
  267. }
  268. func consumeUint64(b []byte) ([]byte, uint64) {
  269. x := binary.BigEndian.Uint64(b)
  270. return b[8:], x
  271. }
  272. func consumeUint32(b []byte) ([]byte, uint32) {
  273. x := binary.BigEndian.Uint32(b)
  274. return b[4:], x
  275. }