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.
 
 
 

245 lines
5.7 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 blake2s implements the BLAKE2s hash algorithm defined by RFC 7693
  5. // and the extendable output function (XOF) BLAKE2Xs.
  6. //
  7. // For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf
  8. // and for BLAKE2Xs see https://blake2.net/blake2x.pdf
  9. //
  10. // If you aren't sure which function you need, use BLAKE2s (Sum256 or New256).
  11. // If you need a secret-key MAC (message authentication code), use the New256
  12. // function with a non-nil key.
  13. //
  14. // BLAKE2X is a construction to compute hash values larger than 32 bytes. It
  15. // can produce hash values between 0 and 65535 bytes.
  16. package blake2s // import "golang.org/x/crypto/blake2s"
  17. import (
  18. "encoding/binary"
  19. "errors"
  20. "hash"
  21. )
  22. const (
  23. // The blocksize of BLAKE2s in bytes.
  24. BlockSize = 64
  25. // The hash size of BLAKE2s-256 in bytes.
  26. Size = 32
  27. // The hash size of BLAKE2s-128 in bytes.
  28. Size128 = 16
  29. )
  30. var errKeySize = errors.New("blake2s: invalid key size")
  31. var iv = [8]uint32{
  32. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  33. 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
  34. }
  35. // Sum256 returns the BLAKE2s-256 checksum of the data.
  36. func Sum256(data []byte) [Size]byte {
  37. var sum [Size]byte
  38. checkSum(&sum, Size, data)
  39. return sum
  40. }
  41. // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil
  42. // key turns the hash into a MAC. The key must between zero and 32 bytes long.
  43. // When the key is nil, the returned hash.Hash implements BinaryMarshaler
  44. // and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
  45. func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
  46. // New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
  47. // non-empty key. Note that a 128-bit digest is too small to be secure as a
  48. // cryptographic hash and should only be used as a MAC, thus the key argument
  49. // is not optional.
  50. func New128(key []byte) (hash.Hash, error) {
  51. if len(key) == 0 {
  52. return nil, errors.New("blake2s: a key is required for a 128-bit hash")
  53. }
  54. return newDigest(Size128, key)
  55. }
  56. func newDigest(hashSize int, key []byte) (*digest, error) {
  57. if len(key) > Size {
  58. return nil, errKeySize
  59. }
  60. d := &digest{
  61. size: hashSize,
  62. keyLen: len(key),
  63. }
  64. copy(d.key[:], key)
  65. d.Reset()
  66. return d, nil
  67. }
  68. func checkSum(sum *[Size]byte, hashSize int, data []byte) {
  69. var (
  70. h [8]uint32
  71. c [2]uint32
  72. )
  73. h = iv
  74. h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24)
  75. if length := len(data); length > BlockSize {
  76. n := length &^ (BlockSize - 1)
  77. if length == n {
  78. n -= BlockSize
  79. }
  80. hashBlocks(&h, &c, 0, data[:n])
  81. data = data[n:]
  82. }
  83. var block [BlockSize]byte
  84. offset := copy(block[:], data)
  85. remaining := uint32(BlockSize - offset)
  86. if c[0] < remaining {
  87. c[1]--
  88. }
  89. c[0] -= remaining
  90. hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
  91. for i, v := range h {
  92. binary.LittleEndian.PutUint32(sum[4*i:], v)
  93. }
  94. }
  95. type digest struct {
  96. h [8]uint32
  97. c [2]uint32
  98. size int
  99. block [BlockSize]byte
  100. offset int
  101. key [BlockSize]byte
  102. keyLen int
  103. }
  104. const (
  105. magic = "b2s"
  106. marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1
  107. )
  108. func (d *digest) MarshalBinary() ([]byte, error) {
  109. if d.keyLen != 0 {
  110. return nil, errors.New("crypto/blake2s: cannot marshal MACs")
  111. }
  112. b := make([]byte, 0, marshaledSize)
  113. b = append(b, magic...)
  114. for i := 0; i < 8; i++ {
  115. b = appendUint32(b, d.h[i])
  116. }
  117. b = appendUint32(b, d.c[0])
  118. b = appendUint32(b, d.c[1])
  119. // Maximum value for size is 32
  120. b = append(b, byte(d.size))
  121. b = append(b, d.block[:]...)
  122. b = append(b, byte(d.offset))
  123. return b, nil
  124. }
  125. func (d *digest) UnmarshalBinary(b []byte) error {
  126. if len(b) < len(magic) || string(b[:len(magic)]) != magic {
  127. return errors.New("crypto/blake2s: invalid hash state identifier")
  128. }
  129. if len(b) != marshaledSize {
  130. return errors.New("crypto/blake2s: invalid hash state size")
  131. }
  132. b = b[len(magic):]
  133. for i := 0; i < 8; i++ {
  134. b, d.h[i] = consumeUint32(b)
  135. }
  136. b, d.c[0] = consumeUint32(b)
  137. b, d.c[1] = consumeUint32(b)
  138. d.size = int(b[0])
  139. b = b[1:]
  140. copy(d.block[:], b[:BlockSize])
  141. b = b[BlockSize:]
  142. d.offset = int(b[0])
  143. return nil
  144. }
  145. func (d *digest) BlockSize() int { return BlockSize }
  146. func (d *digest) Size() int { return d.size }
  147. func (d *digest) Reset() {
  148. d.h = iv
  149. d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24)
  150. d.offset, d.c[0], d.c[1] = 0, 0, 0
  151. if d.keyLen > 0 {
  152. d.block = d.key
  153. d.offset = BlockSize
  154. }
  155. }
  156. func (d *digest) Write(p []byte) (n int, err error) {
  157. n = len(p)
  158. if d.offset > 0 {
  159. remaining := BlockSize - d.offset
  160. if n <= remaining {
  161. d.offset += copy(d.block[d.offset:], p)
  162. return
  163. }
  164. copy(d.block[d.offset:], p[:remaining])
  165. hashBlocks(&d.h, &d.c, 0, d.block[:])
  166. d.offset = 0
  167. p = p[remaining:]
  168. }
  169. if length := len(p); length > BlockSize {
  170. nn := length &^ (BlockSize - 1)
  171. if length == nn {
  172. nn -= BlockSize
  173. }
  174. hashBlocks(&d.h, &d.c, 0, p[:nn])
  175. p = p[nn:]
  176. }
  177. d.offset += copy(d.block[:], p)
  178. return
  179. }
  180. func (d *digest) Sum(sum []byte) []byte {
  181. var hash [Size]byte
  182. d.finalize(&hash)
  183. return append(sum, hash[:d.size]...)
  184. }
  185. func (d *digest) finalize(hash *[Size]byte) {
  186. var block [BlockSize]byte
  187. h := d.h
  188. c := d.c
  189. copy(block[:], d.block[:d.offset])
  190. remaining := uint32(BlockSize - d.offset)
  191. if c[0] < remaining {
  192. c[1]--
  193. }
  194. c[0] -= remaining
  195. hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
  196. for i, v := range h {
  197. binary.LittleEndian.PutUint32(hash[4*i:], v)
  198. }
  199. }
  200. func appendUint32(b []byte, x uint32) []byte {
  201. var a [4]byte
  202. binary.BigEndian.PutUint32(a[:], x)
  203. return append(b, a[:]...)
  204. }
  205. func consumeUint32(b []byte) ([]byte, uint32) {
  206. x := binary.BigEndian.Uint32(b)
  207. return b[4:], x
  208. }