hash.go 3.5 KB

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