sipHash.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Written in 2012 by Dmitry Chestnykh.
  2. //
  3. // To the extent possible under law, the author have dedicated all copyright
  4. // and related and neighboring rights to this software to the public domain
  5. // worldwide. This software is distributed without any warranty.
  6. // http://creativecommons.org/publicdomain/zero/1.0/
  7. //
  8. // Package siphash implements SipHash-2-4, a fast short-input PRF
  9. // created by Jean-Philippe Aumasson and Daniel J. Bernstein.
  10. package bbloom
  11. // Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit
  12. // parts of 128-bit key: k0 and k1.
  13. func (bl Bloom) sipHash(p []byte) (l, h uint64) {
  14. // Initialization.
  15. v0 := uint64(8317987320269560794) // k0 ^ 0x736f6d6570736575
  16. v1 := uint64(7237128889637516672) // k1 ^ 0x646f72616e646f6d
  17. v2 := uint64(7816392314733513934) // k0 ^ 0x6c7967656e657261
  18. v3 := uint64(8387220255325274014) // k1 ^ 0x7465646279746573
  19. t := uint64(len(p)) << 56
  20. // Compression.
  21. for len(p) >= 8 {
  22. m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
  23. uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
  24. v3 ^= m
  25. // Round 1.
  26. v0 += v1
  27. v1 = v1<<13 | v1>>51
  28. v1 ^= v0
  29. v0 = v0<<32 | v0>>32
  30. v2 += v3
  31. v3 = v3<<16 | v3>>48
  32. v3 ^= v2
  33. v0 += v3
  34. v3 = v3<<21 | v3>>43
  35. v3 ^= v0
  36. v2 += v1
  37. v1 = v1<<17 | v1>>47
  38. v1 ^= v2
  39. v2 = v2<<32 | v2>>32
  40. // Round 2.
  41. v0 += v1
  42. v1 = v1<<13 | v1>>51
  43. v1 ^= v0
  44. v0 = v0<<32 | v0>>32
  45. v2 += v3
  46. v3 = v3<<16 | v3>>48
  47. v3 ^= v2
  48. v0 += v3
  49. v3 = v3<<21 | v3>>43
  50. v3 ^= v0
  51. v2 += v1
  52. v1 = v1<<17 | v1>>47
  53. v1 ^= v2
  54. v2 = v2<<32 | v2>>32
  55. v0 ^= m
  56. p = p[8:]
  57. }
  58. // Compress last block.
  59. switch len(p) {
  60. case 7:
  61. t |= uint64(p[6]) << 48
  62. fallthrough
  63. case 6:
  64. t |= uint64(p[5]) << 40
  65. fallthrough
  66. case 5:
  67. t |= uint64(p[4]) << 32
  68. fallthrough
  69. case 4:
  70. t |= uint64(p[3]) << 24
  71. fallthrough
  72. case 3:
  73. t |= uint64(p[2]) << 16
  74. fallthrough
  75. case 2:
  76. t |= uint64(p[1]) << 8
  77. fallthrough
  78. case 1:
  79. t |= uint64(p[0])
  80. }
  81. v3 ^= t
  82. // Round 1.
  83. v0 += v1
  84. v1 = v1<<13 | v1>>51
  85. v1 ^= v0
  86. v0 = v0<<32 | v0>>32
  87. v2 += v3
  88. v3 = v3<<16 | v3>>48
  89. v3 ^= v2
  90. v0 += v3
  91. v3 = v3<<21 | v3>>43
  92. v3 ^= v0
  93. v2 += v1
  94. v1 = v1<<17 | v1>>47
  95. v1 ^= v2
  96. v2 = v2<<32 | v2>>32
  97. // Round 2.
  98. v0 += v1
  99. v1 = v1<<13 | v1>>51
  100. v1 ^= v0
  101. v0 = v0<<32 | v0>>32
  102. v2 += v3
  103. v3 = v3<<16 | v3>>48
  104. v3 ^= v2
  105. v0 += v3
  106. v3 = v3<<21 | v3>>43
  107. v3 ^= v0
  108. v2 += v1
  109. v1 = v1<<17 | v1>>47
  110. v1 ^= v2
  111. v2 = v2<<32 | v2>>32
  112. v0 ^= t
  113. // Finalization.
  114. v2 ^= 0xff
  115. // Round 1.
  116. v0 += v1
  117. v1 = v1<<13 | v1>>51
  118. v1 ^= v0
  119. v0 = v0<<32 | v0>>32
  120. v2 += v3
  121. v3 = v3<<16 | v3>>48
  122. v3 ^= v2
  123. v0 += v3
  124. v3 = v3<<21 | v3>>43
  125. v3 ^= v0
  126. v2 += v1
  127. v1 = v1<<17 | v1>>47
  128. v1 ^= v2
  129. v2 = v2<<32 | v2>>32
  130. // Round 2.
  131. v0 += v1
  132. v1 = v1<<13 | v1>>51
  133. v1 ^= v0
  134. v0 = v0<<32 | v0>>32
  135. v2 += v3
  136. v3 = v3<<16 | v3>>48
  137. v3 ^= v2
  138. v0 += v3
  139. v3 = v3<<21 | v3>>43
  140. v3 ^= v0
  141. v2 += v1
  142. v1 = v1<<17 | v1>>47
  143. v1 ^= v2
  144. v2 = v2<<32 | v2>>32
  145. // Round 3.
  146. v0 += v1
  147. v1 = v1<<13 | v1>>51
  148. v1 ^= v0
  149. v0 = v0<<32 | v0>>32
  150. v2 += v3
  151. v3 = v3<<16 | v3>>48
  152. v3 ^= v2
  153. v0 += v3
  154. v3 = v3<<21 | v3>>43
  155. v3 ^= v0
  156. v2 += v1
  157. v1 = v1<<17 | v1>>47
  158. v1 ^= v2
  159. v2 = v2<<32 | v2>>32
  160. // Round 4.
  161. v0 += v1
  162. v1 = v1<<13 | v1>>51
  163. v1 ^= v0
  164. v0 = v0<<32 | v0>>32
  165. v2 += v3
  166. v3 = v3<<16 | v3>>48
  167. v3 ^= v2
  168. v0 += v3
  169. v3 = v3<<21 | v3>>43
  170. v3 ^= v0
  171. v2 += v1
  172. v1 = v1<<17 | v1>>47
  173. v1 ^= v2
  174. v2 = v2<<32 | v2>>32
  175. // return v0 ^ v1 ^ v2 ^ v3
  176. hash := v0 ^ v1 ^ v2 ^ v3
  177. h = hash >> bl.shift
  178. l = hash << bl.shift >> bl.shift
  179. return l, h
  180. }