97 lines
2.2 KiB
Go
97 lines
2.2 KiB
Go
|
package tiger
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
var littleEndian bool
|
||
|
|
||
|
func init() {
|
||
|
x := uint32(0x04030201)
|
||
|
y := [4]byte{0x1, 0x2, 0x3, 0x4}
|
||
|
littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
|
||
|
}
|
||
|
|
||
|
func pass(a, b, c uint64, x []uint64, mul uint64) (uint64, uint64, uint64) {
|
||
|
a, b, c = round(a, b, c, x[0], mul)
|
||
|
b, c, a = round(b, c, a, x[1], mul)
|
||
|
c, a, b = round(c, a, b, x[2], mul)
|
||
|
a, b, c = round(a, b, c, x[3], mul)
|
||
|
b, c, a = round(b, c, a, x[4], mul)
|
||
|
c, a, b = round(c, a, b, x[5], mul)
|
||
|
a, b, c = round(a, b, c, x[6], mul)
|
||
|
b, c, a = round(b, c, a, x[7], mul)
|
||
|
return a, b, c
|
||
|
}
|
||
|
|
||
|
func round(a, b, c, x, mul uint64) (uint64, uint64, uint64) {
|
||
|
c ^= x
|
||
|
a -= t1[c&0xff] ^ t2[(c>>16)&0xff] ^ t3[(c>>32)&0xff] ^ t4[(c>>48)&0xff]
|
||
|
b += t4[(c>>8)&0xff] ^ t3[(c>>24)&0xff] ^ t2[(c>>40)&0xff] ^ t1[(c>>56)&0xff]
|
||
|
b *= mul
|
||
|
return a, b, c
|
||
|
}
|
||
|
|
||
|
func keySchedule(x []uint64) {
|
||
|
x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5
|
||
|
x[1] ^= x[0]
|
||
|
x[2] += x[1]
|
||
|
x[3] -= x[2] ^ ((^x[1]) << 19)
|
||
|
x[4] ^= x[3]
|
||
|
x[5] += x[4]
|
||
|
x[6] -= x[5] ^ ((^x[4]) >> 23)
|
||
|
x[7] ^= x[6]
|
||
|
x[0] += x[7]
|
||
|
x[1] -= x[0] ^ ((^x[7]) << 19)
|
||
|
x[2] ^= x[1]
|
||
|
x[3] += x[2]
|
||
|
x[4] -= x[3] ^ ((^x[2]) >> 23)
|
||
|
x[5] ^= x[4]
|
||
|
x[6] += x[5]
|
||
|
x[7] -= x[6] ^ 0x0123456789abcdef
|
||
|
}
|
||
|
|
||
|
func (d *digest) compress(data []byte) {
|
||
|
// save_abc
|
||
|
a := d.a
|
||
|
b := d.b
|
||
|
c := d.c
|
||
|
|
||
|
var x []uint64
|
||
|
if littleEndian {
|
||
|
x = []uint64{
|
||
|
binary.LittleEndian.Uint64(data[0:8]),
|
||
|
binary.LittleEndian.Uint64(data[8:16]),
|
||
|
binary.LittleEndian.Uint64(data[16:24]),
|
||
|
binary.LittleEndian.Uint64(data[24:32]),
|
||
|
binary.LittleEndian.Uint64(data[32:40]),
|
||
|
binary.LittleEndian.Uint64(data[40:48]),
|
||
|
binary.LittleEndian.Uint64(data[48:56]),
|
||
|
binary.LittleEndian.Uint64(data[56:64]),
|
||
|
}
|
||
|
} else {
|
||
|
x = []uint64{
|
||
|
binary.BigEndian.Uint64(data[0:8]),
|
||
|
binary.BigEndian.Uint64(data[8:16]),
|
||
|
binary.BigEndian.Uint64(data[16:24]),
|
||
|
binary.BigEndian.Uint64(data[24:32]),
|
||
|
binary.BigEndian.Uint64(data[32:40]),
|
||
|
binary.BigEndian.Uint64(data[40:48]),
|
||
|
binary.BigEndian.Uint64(data[48:56]),
|
||
|
binary.BigEndian.Uint64(data[56:64]),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
d.a, d.b, d.c = pass(d.a, d.b, d.c, x, 5)
|
||
|
keySchedule(x)
|
||
|
d.c, d.a, d.b = pass(d.c, d.a, d.b, x, 7)
|
||
|
keySchedule(x)
|
||
|
d.b, d.c, d.a = pass(d.b, d.c, d.a, x, 9)
|
||
|
|
||
|
// feedforward
|
||
|
d.a ^= a
|
||
|
d.b -= b
|
||
|
d.c += c
|
||
|
}
|