hash.go 3.4 KB

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