1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00
MiraiGo/binary/tea.go
wdvxdr a69487056d
drop unsafe in TEA encryption
name         old time/op    new time/op    delta
TEAen/16-8      245ns ± 0%     237ns ± 0%  -3.29%  (p=0.008 n=5+5)
TEAen/256-8    1.73µs ± 0%    1.69µs ± 0%  -2.77%  (p=0.008 n=5+5)
TEAen/4K-8     24.9µs ± 0%    25.0µs ± 1%    ~     (p=0.690 n=5+5)
TEAen/32K-8     198µs ± 0%     199µs ± 1%  +0.73%  (p=0.008 n=5+5)
TEAde/16-8      215ns ± 1%     196ns ± 1%  -8.93%  (p=0.008 n=5+5)
TEAde/256-8    1.70µs ± 0%    1.56µs ± 0%  -8.08%  (p=0.008 n=5+5)
TEAde/4K-8     24.9µs ± 1%    23.5µs ± 0%  -5.50%  (p=0.008 n=5+5)
TEAde/32K-8     198µs ± 0%     187µs ± 1%  -5.34%  (p=0.008 n=5+5)

name         old speed      new speed      delta
TEAen/16-8   65.4MB/s ± 0%  67.6MB/s ± 1%  +3.39%  (p=0.008 n=5+5)
TEAen/256-8   148MB/s ± 0%   152MB/s ± 0%  +2.84%  (p=0.008 n=5+5)
TEAen/4K-8    164MB/s ± 0%   164MB/s ± 1%    ~     (p=0.587 n=5+5)
TEAen/32K-8   166MB/s ± 0%   165MB/s ± 1%  -0.72%  (p=0.008 n=5+5)
TEAde/16-8    149MB/s ± 1%   163MB/s ± 1%  +9.81%  (p=0.008 n=5+5)
TEAde/256-8   160MB/s ± 0%   174MB/s ± 0%  +8.80%  (p=0.008 n=5+5)
TEAde/4K-8    165MB/s ± 1%   175MB/s ± 0%  +5.81%  (p=0.008 n=5+5)
TEAde/32K-8   166MB/s ± 0%   175MB/s ± 1%  +5.70%  (p=0.008 n=5+5)
2021-11-16 20:54:40 +08:00

133 lines
4.0 KiB
Go

package binary
import (
"encoding/binary"
"math/rand"
)
type TEA [4]uint32
// Encrypt tea 加密
// http://bbs.chinaunix.net/thread-583468-1-1.html
// 感谢xichen大佬对TEA的解释
func (t TEA) Encrypt(src []byte) (dst []byte) {
lens := len(src)
fill := 10 - (lens+1)%8
dst = make([]byte, fill+lens+7)
_, _ = rand.Read(dst[0:fill])
dst[0] = byte(fill-3) | 0xF8 // 存储pad长度
copy(dst[fill:], src)
var iv1, iv2, holder uint64
for i := 0; i < len(dst); i += 8 {
block := binary.BigEndian.Uint64(dst[i:])
holder = block ^ iv1
iv1 = t.encode(holder)
iv1 = iv1 ^ iv2
iv2 = holder
binary.BigEndian.PutUint64(dst[i:], iv1)
}
return dst
}
func (t TEA) Decrypt(data []byte) []byte {
if len(data) < 16 || len(data)%8 != 0 {
return nil
}
dst := make([]byte, len(data))
var iv1, iv2, holder, tmp uint64
for i := 0; i < len(dst); i += 8 {
block := binary.BigEndian.Uint64(data[i:])
tmp = t.decode(block ^ iv2)
iv2 = tmp
holder = tmp ^ iv1
iv1 = block
binary.BigEndian.PutUint64(dst[i:], holder)
}
return dst[dst[0]&7+3 : len(data)-7]
}
var sumTable = [0x10]uint32{
0x9e3779b9,
0x3c6ef372,
0xdaa66d2b,
0x78dde6e4,
0x1715609d,
0xb54cda56,
0x5384540f,
0xf1bbcdc8,
0x8ff34781,
0x2e2ac13a,
0xcc623af3,
0x6a99b4ac,
0x08d12e65,
0xa708a81e,
0x454021d7,
0xe3779b90,
}
//go:nosplit
func (t *TEA) encode(n uint64) uint64 {
v0, v1 := uint32(n>>32), uint32(n)
for i := 0; i < 0x10; i++ {
v0 += ((v1 << 4) + t[0]) ^ (v1 + sumTable[i]) ^ ((v1 >> 5) + t[1])
v1 += ((v0 << 4) + t[2]) ^ (v0 + sumTable[i]) ^ ((v0 >> 5) + t[3])
}
return uint64(v0)<<32 | uint64(v1)
}
// 每次8字节
//go:nosplit
func (t *TEA) decode(n uint64) uint64 {
v0, v1 := uint32(n>>32), uint32(n)
t0, t1, t2, t3 := t[0], t[1], t[2], t[3]
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xe3779b90) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xe3779b90) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x454021d7) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x454021d7) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xa708a81e) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xa708a81e) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x8d12e65) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x8d12e65) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x6a99b4ac) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x6a99b4ac) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xcc623af3) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xcc623af3) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x2e2ac13a) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x2e2ac13a) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x8ff34781) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x8ff34781) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xf1bbcdc8) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xf1bbcdc8) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x5384540f) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x5384540f) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xb54cda56) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xb54cda56) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x1715609d) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x1715609d) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x78dde6e4) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x78dde6e4) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0xdaa66d2b) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0xdaa66d2b) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x3c6ef372) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x3c6ef372) ^ ((v1 >> 5) + t1)
v1 -= ((v0 << 4) + t2) ^ (v0 + 0x9e3779b9) ^ ((v0 >> 5) + t3)
v0 -= ((v1 << 4) + t0) ^ (v1 + 0x9e3779b9) ^ ((v1 >> 5) + t1)
return uint64(v0)<<32 | uint64(v1)
}
//go:nosplit
func NewTeaCipher(key []byte) (t TEA) {
if len(key) != 16 {
return TEA{}
}
t[3] = binary.BigEndian.Uint32(key[12:])
t[2] = binary.BigEndian.Uint32(key[8:])
t[1] = binary.BigEndian.Uint32(key[4:])
t[0] = binary.BigEndian.Uint32(key[0:])
return t
}