github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/binary/tea.go (about) 1 package binary 2 3 import ( 4 "encoding/binary" 5 _ "unsafe" // required by go:linkname 6 ) 7 8 type TEA [4]uint32 9 10 // Encrypt tea 加密 11 // http://bbs.chinaunix.net/thread-583468-1-1.html 12 // 感谢xichen大佬对TEA的解释 13 func (t TEA) Encrypt(src []byte) (dst []byte) { 14 lens := len(src) 15 fill := 10 - (lens+1)%8 16 dst = make([]byte, fill+lens+7) 17 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 18 copy(dst[fill:], src) 19 20 var iv1, iv2, holder uint64 21 for i := 0; i < len(dst); i += 8 { 22 block := binary.BigEndian.Uint64(dst[i:]) 23 holder = block ^ iv1 24 iv1 = t.encode(holder) 25 iv1 ^= iv2 26 iv2 = holder 27 binary.BigEndian.PutUint64(dst[i:], iv1) 28 } 29 30 return dst 31 } 32 33 func (t TEA) Decrypt(data []byte) []byte { 34 if len(data) < 16 || len(data)%8 != 0 { 35 return nil 36 } 37 dst := make([]byte, len(data)) 38 var iv1, iv2, holder uint64 39 for i := 0; i < len(dst); i += 8 { 40 iv1 = binary.BigEndian.Uint64(data[i:]) 41 iv2 ^= iv1 42 iv2 = t.decode(iv2) 43 binary.BigEndian.PutUint64(dst[i:], iv2^holder) 44 holder = iv1 45 } 46 return dst[dst[0]&7+3 : len(data)-7] 47 } 48 49 //go:nosplit 50 func (t *TEA) encode(n uint64) uint64 { 51 v0, v1 := uint32(n>>32), uint32(n) 52 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 53 54 v0 += (v1 + 0x9e3779b9) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 55 v1 += (v0 + 0x9e3779b9) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 56 v0 += (v1 + 0x3c6ef372) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 57 v1 += (v0 + 0x3c6ef372) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 58 v0 += (v1 + 0xdaa66d2b) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 59 v1 += (v0 + 0xdaa66d2b) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 60 v0 += (v1 + 0x78dde6e4) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 61 v1 += (v0 + 0x78dde6e4) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 62 v0 += (v1 + 0x1715609d) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 63 v1 += (v0 + 0x1715609d) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 64 v0 += (v1 + 0xb54cda56) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 65 v1 += (v0 + 0xb54cda56) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 66 v0 += (v1 + 0x5384540f) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 67 v1 += (v0 + 0x5384540f) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 68 v0 += (v1 + 0xf1bbcdc8) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 69 v1 += (v0 + 0xf1bbcdc8) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 70 v0 += (v1 + 0x8ff34781) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 71 v1 += (v0 + 0x8ff34781) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 72 v0 += (v1 + 0x2e2ac13a) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 73 v1 += (v0 + 0x2e2ac13a) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 74 v0 += (v1 + 0xcc623af3) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 75 v1 += (v0 + 0xcc623af3) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 76 v0 += (v1 + 0x6a99b4ac) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 77 v1 += (v0 + 0x6a99b4ac) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 78 v0 += (v1 + 0x08d12e65) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 79 v1 += (v0 + 0x08d12e65) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 80 v0 += (v1 + 0xa708a81e) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 81 v1 += (v0 + 0xa708a81e) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 82 v0 += (v1 + 0x454021d7) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 83 v1 += (v0 + 0x454021d7) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 84 v0 += (v1 + 0xe3779b90) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 85 v1 += (v0 + 0xe3779b90) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 86 87 return uint64(v0)<<32 | uint64(v1) 88 } 89 90 // 每次8字节 91 // 92 //go:nosplit 93 func (t *TEA) decode(n uint64) uint64 { 94 v0, v1 := uint32(n>>32), uint32(n) 95 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 96 97 v1 -= (v0 + 0xe3779b90) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 98 v0 -= (v1 + 0xe3779b90) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 99 v1 -= (v0 + 0x454021d7) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 100 v0 -= (v1 + 0x454021d7) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 101 v1 -= (v0 + 0xa708a81e) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 102 v0 -= (v1 + 0xa708a81e) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 103 v1 -= (v0 + 0x08d12e65) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 104 v0 -= (v1 + 0x08d12e65) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 105 v1 -= (v0 + 0x6a99b4ac) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 106 v0 -= (v1 + 0x6a99b4ac) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 107 v1 -= (v0 + 0xcc623af3) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 108 v0 -= (v1 + 0xcc623af3) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 109 v1 -= (v0 + 0x2e2ac13a) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 110 v0 -= (v1 + 0x2e2ac13a) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 111 v1 -= (v0 + 0x8ff34781) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 112 v0 -= (v1 + 0x8ff34781) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 113 v1 -= (v0 + 0xf1bbcdc8) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 114 v0 -= (v1 + 0xf1bbcdc8) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 115 v1 -= (v0 + 0x5384540f) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 116 v0 -= (v1 + 0x5384540f) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 117 v1 -= (v0 + 0xb54cda56) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 118 v0 -= (v1 + 0xb54cda56) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 119 v1 -= (v0 + 0x1715609d) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 120 v0 -= (v1 + 0x1715609d) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 121 v1 -= (v0 + 0x78dde6e4) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 122 v0 -= (v1 + 0x78dde6e4) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 123 v1 -= (v0 + 0xdaa66d2b) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 124 v0 -= (v1 + 0xdaa66d2b) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 125 v1 -= (v0 + 0x3c6ef372) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 126 v0 -= (v1 + 0x3c6ef372) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 127 v1 -= (v0 + 0x9e3779b9) ^ (v0<<4 + t2) ^ (v0>>5 + t3) 128 v0 -= (v1 + 0x9e3779b9) ^ (v1<<4 + t0) ^ (v1>>5 + t1) 129 130 return uint64(v0)<<32 | uint64(v1) 131 } 132 133 //go:nosplit 134 func NewTeaCipher(key []byte) (t TEA) { 135 if len(key) != 16 { 136 return TEA{} 137 } 138 t[3] = binary.BigEndian.Uint32(key[12:16]) 139 t[2] = binary.BigEndian.Uint32(key[8:12]) 140 t[1] = binary.BigEndian.Uint32(key[4:8]) 141 t[0] = binary.BigEndian.Uint32(key[:4]) 142 return t 143 }