2019-08-13 01:34:14 -07:00
|
|
|
// +build !amd64 noasm
|
|
|
|
|
|
|
|
package sip13
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/bits"
|
2020-10-08 00:26:01 -07:00
|
|
|
"unsafe"
|
2019-08-13 01:34:14 -07:00
|
|
|
)
|
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
func Sum64(k0, k1 uint64, b []byte) uint64 {
|
|
|
|
return Sum64Str(k0, k1, unsafeB2S(b))
|
2019-08-13 01:34:14 -07:00
|
|
|
}
|
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
func readUint64(b string) uint64 {
|
|
|
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
|
|
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
|
|
|
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
2019-08-13 01:34:14 -07:00
|
|
|
}
|
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
func unsafeB2S(b []byte) string {
|
|
|
|
return *(*string)(unsafe.Pointer(&b))
|
2019-08-13 01:34:14 -07:00
|
|
|
}
|
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
func Sum64Str(k0, k1 uint64, p string) uint64 {
|
|
|
|
var v0, v1, v2, v3 uint64
|
2019-08-13 01:34:14 -07:00
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
v0 = k0 ^ 0x736f6d6570736575
|
|
|
|
v1 = k1 ^ 0x646f72616e646f6d
|
|
|
|
v2 = k0 ^ 0x6c7967656e657261
|
|
|
|
v3 = k1 ^ 0x7465646279746573
|
2019-08-13 01:34:14 -07:00
|
|
|
b := uint64(len(p)) << 56
|
|
|
|
|
|
|
|
for len(p) >= 8 {
|
2020-10-08 00:26:01 -07:00
|
|
|
m := readUint64(p)
|
|
|
|
v3 ^= m
|
|
|
|
v0 += v1
|
|
|
|
v2 += v3
|
|
|
|
v1 = bits.RotateLeft64(v1, 13)
|
|
|
|
v3 = bits.RotateLeft64(v3, 16)
|
|
|
|
v1 ^= v0
|
|
|
|
v3 ^= v2
|
|
|
|
v0 = bits.RotateLeft64(v0, 32)
|
|
|
|
v2 += v1
|
|
|
|
v0 += v3
|
|
|
|
v1 = bits.RotateLeft64(v1, 17)
|
|
|
|
v3 = bits.RotateLeft64(v3, 21)
|
|
|
|
v1 ^= v2
|
|
|
|
v3 ^= v0
|
|
|
|
v2 = bits.RotateLeft64(v2, 32)
|
|
|
|
v0 ^= m
|
2019-08-13 01:34:14 -07:00
|
|
|
p = p[8:]
|
|
|
|
}
|
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
for _, c := range []byte(p) {
|
|
|
|
b = bits.RotateLeft64(b|uint64(c), 56)
|
2019-08-13 01:34:14 -07:00
|
|
|
}
|
2020-10-08 00:26:01 -07:00
|
|
|
m := bits.RotateLeft64(b, len(p)*8)
|
2019-08-13 01:34:14 -07:00
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
// last block with finalization
|
|
|
|
v3 ^= m
|
|
|
|
f := uint64(0xff)
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
v0 += v1
|
|
|
|
v2 += v3
|
|
|
|
v1 = bits.RotateLeft64(v1, 13)
|
|
|
|
v3 = bits.RotateLeft64(v3, 16)
|
|
|
|
v1 ^= v0
|
|
|
|
v3 ^= v2
|
|
|
|
v0 = bits.RotateLeft64(v0, 32)
|
|
|
|
v2 += v1
|
|
|
|
v0 += v3
|
|
|
|
v1 = bits.RotateLeft64(v1, 17)
|
|
|
|
v3 = bits.RotateLeft64(v3, 21)
|
|
|
|
v1 ^= v2
|
|
|
|
v3 ^= v0
|
|
|
|
v2 = bits.RotateLeft64(v2, 32)
|
|
|
|
v2 ^= f
|
|
|
|
v0 ^= m
|
|
|
|
m, f = 0, 0 // clear last block and finalization mixins
|
|
|
|
}
|
2019-08-13 01:34:14 -07:00
|
|
|
|
2020-10-08 00:26:01 -07:00
|
|
|
return v0 ^ v1 ^ v2 ^ v3
|
2019-08-13 01:34:14 -07:00
|
|
|
}
|