sha3.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright 2014 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 sha3
  5. import (
  6. "crypto/subtle"
  7. "encoding/binary"
  8. "errors"
  9. "unsafe"
  10. "golang.org/x/sys/cpu"
  11. )
  12. // spongeDirection indicates the direction bytes are flowing through the sponge.
  13. type spongeDirection int
  14. const (
  15. // spongeAbsorbing indicates that the sponge is absorbing input.
  16. spongeAbsorbing spongeDirection = iota
  17. // spongeSqueezing indicates that the sponge is being squeezed.
  18. spongeSqueezing
  19. )
  20. type state struct {
  21. a [1600 / 8]byte // main state of the hash
  22. // a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
  23. // into before running the permutation. If squeezing, it's the remaining
  24. // output to produce before running the permutation.
  25. n, rate int
  26. // dsbyte contains the "domain separation" bits and the first bit of
  27. // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
  28. // SHA-3 and SHAKE functions by appending bitstrings to the message.
  29. // Using a little-endian bit-ordering convention, these are "01" for SHA-3
  30. // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
  31. // padding rule from section 5.1 is applied to pad the message to a multiple
  32. // of the rate, which involves adding a "1" bit, zero or more "0" bits, and
  33. // a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
  34. // giving 00000110b (0x06) and 00011111b (0x1f).
  35. // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
  36. // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
  37. // Extendable-Output Functions (May 2014)"
  38. dsbyte byte
  39. outputLen int // the default output size in bytes
  40. state spongeDirection // whether the sponge is absorbing or squeezing
  41. }
  42. // BlockSize returns the rate of sponge underlying this hash function.
  43. func (d *state) BlockSize() int { return d.rate }
  44. // Size returns the output size of the hash function in bytes.
  45. func (d *state) Size() int { return d.outputLen }
  46. // Reset clears the internal state by zeroing the sponge state and
  47. // the buffer indexes, and setting Sponge.state to absorbing.
  48. func (d *state) Reset() {
  49. // Zero the permutation's state.
  50. for i := range d.a {
  51. d.a[i] = 0
  52. }
  53. d.state = spongeAbsorbing
  54. d.n = 0
  55. }
  56. func (d *state) clone() *state {
  57. ret := *d
  58. return &ret
  59. }
  60. // permute applies the KeccakF-1600 permutation.
  61. func (d *state) permute() {
  62. var a *[25]uint64
  63. if cpu.IsBigEndian {
  64. a = new([25]uint64)
  65. for i := range a {
  66. a[i] = binary.LittleEndian.Uint64(d.a[i*8:])
  67. }
  68. } else {
  69. a = (*[25]uint64)(unsafe.Pointer(&d.a))
  70. }
  71. keccakF1600(a)
  72. d.n = 0
  73. if cpu.IsBigEndian {
  74. for i := range a {
  75. binary.LittleEndian.PutUint64(d.a[i*8:], a[i])
  76. }
  77. }
  78. }
  79. // pads appends the domain separation bits in dsbyte, applies
  80. // the multi-bitrate 10..1 padding rule, and permutes the state.
  81. func (d *state) padAndPermute() {
  82. // Pad with this instance's domain-separator bits. We know that there's
  83. // at least one byte of space in the sponge because, if it were full,
  84. // permute would have been called to empty it. dsbyte also contains the
  85. // first one bit for the padding. See the comment in the state struct.
  86. d.a[d.n] ^= d.dsbyte
  87. // This adds the final one bit for the padding. Because of the way that
  88. // bits are numbered from the LSB upwards, the final bit is the MSB of
  89. // the last byte.
  90. d.a[d.rate-1] ^= 0x80
  91. // Apply the permutation
  92. d.permute()
  93. d.state = spongeSqueezing
  94. }
  95. // Write absorbs more data into the hash's state. It panics if any
  96. // output has already been read.
  97. func (d *state) Write(p []byte) (n int, err error) {
  98. if d.state != spongeAbsorbing {
  99. panic("sha3: Write after Read")
  100. }
  101. n = len(p)
  102. for len(p) > 0 {
  103. x := subtle.XORBytes(d.a[d.n:d.rate], d.a[d.n:d.rate], p)
  104. d.n += x
  105. p = p[x:]
  106. // If the sponge is full, apply the permutation.
  107. if d.n == d.rate {
  108. d.permute()
  109. }
  110. }
  111. return
  112. }
  113. // Read squeezes an arbitrary number of bytes from the sponge.
  114. func (d *state) Read(out []byte) (n int, err error) {
  115. // If we're still absorbing, pad and apply the permutation.
  116. if d.state == spongeAbsorbing {
  117. d.padAndPermute()
  118. }
  119. n = len(out)
  120. // Now, do the squeezing.
  121. for len(out) > 0 {
  122. // Apply the permutation if we've squeezed the sponge dry.
  123. if d.n == d.rate {
  124. d.permute()
  125. }
  126. x := copy(out, d.a[d.n:d.rate])
  127. d.n += x
  128. out = out[x:]
  129. }
  130. return
  131. }
  132. // Sum applies padding to the hash state and then squeezes out the desired
  133. // number of output bytes. It panics if any output has already been read.
  134. func (d *state) Sum(in []byte) []byte {
  135. if d.state != spongeAbsorbing {
  136. panic("sha3: Sum after Read")
  137. }
  138. // Make a copy of the original hash so that caller can keep writing
  139. // and summing.
  140. dup := d.clone()
  141. hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
  142. dup.Read(hash)
  143. return append(in, hash...)
  144. }
  145. const (
  146. magicSHA3 = "sha\x08"
  147. magicShake = "sha\x09"
  148. magicCShake = "sha\x0a"
  149. magicKeccak = "sha\x0b"
  150. // magic || rate || main state || n || sponge direction
  151. marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
  152. )
  153. func (d *state) MarshalBinary() ([]byte, error) {
  154. return d.AppendBinary(make([]byte, 0, marshaledSize))
  155. }
  156. func (d *state) AppendBinary(b []byte) ([]byte, error) {
  157. switch d.dsbyte {
  158. case dsbyteSHA3:
  159. b = append(b, magicSHA3...)
  160. case dsbyteShake:
  161. b = append(b, magicShake...)
  162. case dsbyteCShake:
  163. b = append(b, magicCShake...)
  164. case dsbyteKeccak:
  165. b = append(b, magicKeccak...)
  166. default:
  167. panic("unknown dsbyte")
  168. }
  169. // rate is at most 168, and n is at most rate.
  170. b = append(b, byte(d.rate))
  171. b = append(b, d.a[:]...)
  172. b = append(b, byte(d.n), byte(d.state))
  173. return b, nil
  174. }
  175. func (d *state) UnmarshalBinary(b []byte) error {
  176. if len(b) != marshaledSize {
  177. return errors.New("sha3: invalid hash state")
  178. }
  179. magic := string(b[:len(magicSHA3)])
  180. b = b[len(magicSHA3):]
  181. switch {
  182. case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
  183. case magic == magicShake && d.dsbyte == dsbyteShake:
  184. case magic == magicCShake && d.dsbyte == dsbyteCShake:
  185. case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
  186. default:
  187. return errors.New("sha3: invalid hash state identifier")
  188. }
  189. rate := int(b[0])
  190. b = b[1:]
  191. if rate != d.rate {
  192. return errors.New("sha3: invalid hash state function")
  193. }
  194. copy(d.a[:], b)
  195. b = b[len(d.a):]
  196. n, state := int(b[0]), spongeDirection(b[1])
  197. if n > d.rate {
  198. return errors.New("sha3: invalid hash state")
  199. }
  200. d.n = n
  201. if state != spongeAbsorbing && state != spongeSqueezing {
  202. return errors.New("sha3: invalid hash state")
  203. }
  204. d.state = state
  205. return nil
  206. }