blake3.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. // Package blake3 implements the BLAKE3 cryptographic hash function.
  2. package blake3 // import "lukechampine.com/blake3"
  3. import (
  4. "encoding/binary"
  5. "errors"
  6. "hash"
  7. "io"
  8. "math"
  9. "math/bits"
  10. )
  11. const (
  12. flagChunkStart = 1 << iota
  13. flagChunkEnd
  14. flagParent
  15. flagRoot
  16. flagKeyedHash
  17. flagDeriveKeyContext
  18. flagDeriveKeyMaterial
  19. blockSize = 64
  20. chunkSize = 1024
  21. maxSIMD = 16 // AVX-512 vectors can store 16 words
  22. )
  23. var iv = [8]uint32{
  24. 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
  25. 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
  26. }
  27. // A node represents a chunk or parent in the BLAKE3 Merkle tree.
  28. type node struct {
  29. cv [8]uint32 // chaining value from previous node
  30. block [16]uint32
  31. counter uint64
  32. blockLen uint32
  33. flags uint32
  34. }
  35. // parentNode returns a node that incorporates the chaining values of two child
  36. // nodes.
  37. func parentNode(left, right [8]uint32, key [8]uint32, flags uint32) node {
  38. n := node{
  39. cv: key,
  40. counter: 0, // counter is reset for parents
  41. blockLen: blockSize, // block is full
  42. flags: flags | flagParent,
  43. }
  44. copy(n.block[:8], left[:])
  45. copy(n.block[8:], right[:])
  46. return n
  47. }
  48. // Hasher implements hash.Hash.
  49. type Hasher struct {
  50. key [8]uint32
  51. flags uint32
  52. size int // output size, for Sum
  53. // log(n) set of Merkle subtree roots, at most one per height.
  54. stack [50][8]uint32 // 2^50 * maxSIMD * chunkSize = 2^64
  55. counter uint64 // number of buffers hashed; also serves as a bit vector indicating which stack elems are occupied
  56. buf [maxSIMD * chunkSize]byte
  57. buflen int
  58. }
  59. func (h *Hasher) hasSubtreeAtHeight(i int) bool {
  60. return h.counter&(1<<i) != 0
  61. }
  62. func (h *Hasher) pushSubtree(cv [8]uint32) {
  63. // seek to first open stack slot, merging subtrees as we go
  64. i := 0
  65. for h.hasSubtreeAtHeight(i) {
  66. cv = chainingValue(parentNode(h.stack[i], cv, h.key, h.flags))
  67. i++
  68. }
  69. h.stack[i] = cv
  70. h.counter++
  71. }
  72. // rootNode computes the root of the Merkle tree. It does not modify the
  73. // stack.
  74. func (h *Hasher) rootNode() node {
  75. n := compressBuffer(&h.buf, h.buflen, &h.key, h.counter*maxSIMD, h.flags)
  76. for i := bits.TrailingZeros64(h.counter); i < bits.Len64(h.counter); i++ {
  77. if h.hasSubtreeAtHeight(i) {
  78. n = parentNode(h.stack[i], chainingValue(n), h.key, h.flags)
  79. }
  80. }
  81. n.flags |= flagRoot
  82. return n
  83. }
  84. // Write implements hash.Hash.
  85. func (h *Hasher) Write(p []byte) (int, error) {
  86. lenp := len(p)
  87. for len(p) > 0 {
  88. if h.buflen == len(h.buf) {
  89. n := compressBuffer(&h.buf, h.buflen, &h.key, h.counter*maxSIMD, h.flags)
  90. h.pushSubtree(chainingValue(n))
  91. h.buflen = 0
  92. }
  93. n := copy(h.buf[h.buflen:], p)
  94. h.buflen += n
  95. p = p[n:]
  96. }
  97. return lenp, nil
  98. }
  99. // Sum implements hash.Hash.
  100. func (h *Hasher) Sum(b []byte) (sum []byte) {
  101. // We need to append h.Size() bytes to b. Reuse b's capacity if possible;
  102. // otherwise, allocate a new slice.
  103. if total := len(b) + h.Size(); cap(b) >= total {
  104. sum = b[:total]
  105. } else {
  106. sum = make([]byte, total)
  107. copy(sum, b)
  108. }
  109. // Read into the appended portion of sum. Use a low-latency-low-throughput
  110. // path for small digests (requiring a single compression), and a
  111. // high-latency-high-throughput path for large digests.
  112. if dst := sum[len(b):]; len(dst) <= 64 {
  113. var out [64]byte
  114. wordsToBytes(compressNode(h.rootNode()), &out)
  115. copy(dst, out[:])
  116. } else {
  117. h.XOF().Read(dst)
  118. }
  119. return
  120. }
  121. // Reset implements hash.Hash.
  122. func (h *Hasher) Reset() {
  123. h.counter = 0
  124. h.buflen = 0
  125. }
  126. // BlockSize implements hash.Hash.
  127. func (h *Hasher) BlockSize() int { return 64 }
  128. // Size implements hash.Hash.
  129. func (h *Hasher) Size() int { return h.size }
  130. // XOF returns an OutputReader initialized with the current hash state.
  131. func (h *Hasher) XOF() *OutputReader {
  132. return &OutputReader{
  133. n: h.rootNode(),
  134. }
  135. }
  136. func newHasher(key [8]uint32, flags uint32, size int) *Hasher {
  137. return &Hasher{
  138. key: key,
  139. flags: flags,
  140. size: size,
  141. }
  142. }
  143. // New returns a Hasher for the specified size and key. If key is nil, the hash
  144. // is unkeyed. Otherwise, len(key) must be 32.
  145. func New(size int, key []byte) *Hasher {
  146. if key == nil {
  147. return newHasher(iv, 0, size)
  148. }
  149. var keyWords [8]uint32
  150. for i := range keyWords {
  151. keyWords[i] = binary.LittleEndian.Uint32(key[i*4:])
  152. }
  153. return newHasher(keyWords, flagKeyedHash, size)
  154. }
  155. // Sum256 and Sum512 always use the same hasher state, so we can save some time
  156. // when hashing small inputs by constructing the hasher ahead of time.
  157. var defaultHasher = New(0, nil)
  158. // Sum256 returns the unkeyed BLAKE3 hash of b, truncated to 256 bits.
  159. func Sum256(b []byte) (out [32]byte) {
  160. out512 := Sum512(b)
  161. copy(out[:], out512[:])
  162. return
  163. }
  164. // Sum512 returns the unkeyed BLAKE3 hash of b, truncated to 512 bits.
  165. func Sum512(b []byte) (out [64]byte) {
  166. var n node
  167. if len(b) <= blockSize {
  168. hashBlock(&out, b)
  169. return
  170. } else if len(b) <= chunkSize {
  171. n = compressChunk(b, &iv, 0, 0)
  172. n.flags |= flagRoot
  173. } else {
  174. h := *defaultHasher
  175. h.Write(b)
  176. n = h.rootNode()
  177. }
  178. wordsToBytes(compressNode(n), &out)
  179. return
  180. }
  181. // DeriveKey derives a subkey from ctx and srcKey. ctx should be hardcoded,
  182. // globally unique, and application-specific. A good format for ctx strings is:
  183. //
  184. // [application] [commit timestamp] [purpose]
  185. //
  186. // e.g.:
  187. //
  188. // example.com 2019-12-25 16:18:03 session tokens v1
  189. //
  190. // The purpose of these requirements is to ensure that an attacker cannot trick
  191. // two different applications into using the same context string.
  192. func DeriveKey(subKey []byte, ctx string, srcKey []byte) {
  193. // construct the derivation Hasher
  194. const derivationIVLen = 32
  195. h := newHasher(iv, flagDeriveKeyContext, 32)
  196. h.Write([]byte(ctx))
  197. derivationIV := h.Sum(make([]byte, 0, derivationIVLen))
  198. var ivWords [8]uint32
  199. for i := range ivWords {
  200. ivWords[i] = binary.LittleEndian.Uint32(derivationIV[i*4:])
  201. }
  202. h = newHasher(ivWords, flagDeriveKeyMaterial, 0)
  203. // derive the subKey
  204. h.Write(srcKey)
  205. h.XOF().Read(subKey)
  206. }
  207. // An OutputReader produces an seekable stream of 2^64 - 1 pseudorandom output
  208. // bytes.
  209. type OutputReader struct {
  210. n node
  211. buf [maxSIMD * blockSize]byte
  212. off uint64
  213. }
  214. // Read implements io.Reader. Callers may assume that Read returns len(p), nil
  215. // unless the read would extend beyond the end of the stream.
  216. func (or *OutputReader) Read(p []byte) (int, error) {
  217. if or.off == math.MaxUint64 {
  218. return 0, io.EOF
  219. } else if rem := math.MaxUint64 - or.off; uint64(len(p)) > rem {
  220. p = p[:rem]
  221. }
  222. lenp := len(p)
  223. for len(p) > 0 {
  224. if or.off%(maxSIMD*blockSize) == 0 {
  225. or.n.counter = or.off / blockSize
  226. compressBlocks(&or.buf, or.n)
  227. }
  228. n := copy(p, or.buf[or.off%(maxSIMD*blockSize):])
  229. p = p[n:]
  230. or.off += uint64(n)
  231. }
  232. return lenp, nil
  233. }
  234. // Seek implements io.Seeker.
  235. func (or *OutputReader) Seek(offset int64, whence int) (int64, error) {
  236. off := or.off
  237. switch whence {
  238. case io.SeekStart:
  239. if offset < 0 {
  240. return 0, errors.New("seek position cannot be negative")
  241. }
  242. off = uint64(offset)
  243. case io.SeekCurrent:
  244. if offset < 0 {
  245. if uint64(-offset) > off {
  246. return 0, errors.New("seek position cannot be negative")
  247. }
  248. off -= uint64(-offset)
  249. } else {
  250. off += uint64(offset)
  251. }
  252. case io.SeekEnd:
  253. off = uint64(offset) - 1
  254. default:
  255. panic("invalid whence")
  256. }
  257. or.off = off
  258. or.n.counter = uint64(off) / blockSize
  259. if or.off%(maxSIMD*blockSize) != 0 {
  260. compressBlocks(&or.buf, or.n)
  261. }
  262. // NOTE: or.off >= 2^63 will result in a negative return value.
  263. // Nothing we can do about this.
  264. return int64(or.off), nil
  265. }
  266. // ensure that Hasher implements hash.Hash
  267. var _ hash.Hash = (*Hasher)(nil)