github.com/fumiama/gofastTEA@v0.0.10/tea_1.16.go (about) 1 //go:build (!go1.17 && amd64) || !amd64 2 // +build !go1.17,amd64 !amd64 3 4 package tea 5 6 import "encoding/binary" 7 8 // Encrypt tea 加密 9 // http://bbs.chinaunix.net/thread-583468-1-1.html 10 // 感谢xichen大佬对TEA的解释 11 //go:nosplit 12 func (t TEA) EncryptLittleEndian(src []byte, sumtable [0x10]uint32) (dst []byte) { 13 lens := len(src) 14 fill := 10 - (lens+1)&7 15 dst = make([]byte, fill+lens+7) 16 binary.LittleEndian.PutUint32(dst, randuint32()) 17 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 18 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 19 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 20 copy(dst[fill:], src) 21 22 var iv1, iv2, holder uint64 23 var v0, v1 uint32 24 for i := 0; i < len(dst); i += 8 { 25 holder = binary.LittleEndian.Uint64(dst[i:]) ^ iv1 26 v0, v1 = uint32(holder>>32), uint32(holder) 27 for i := 0; i < 0x10; i++ { 28 v0 += (v1 + sumtable[i]) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 29 v1 += (v0 + sumtable[i]) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 30 } 31 iv1 = (uint64(v0)<<32 | uint64(v1)) ^ iv2 32 iv2 = holder 33 binary.LittleEndian.PutUint64(dst[i:], iv1) 34 } 35 36 return dst 37 } 38 39 //go:nosplit 40 func (t TEA) EncryptLittleEndianTo(src []byte, sumtable [0x10]uint32, dst []byte) int { 41 lens := len(src) 42 fill := 10 - (lens+1)&7 43 binary.LittleEndian.PutUint32(dst, randuint32()) 44 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 45 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 46 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 47 copy(dst[fill:], src) 48 49 var iv1, iv2, holder uint64 50 var v0, v1 uint32 51 for i := 0; i < fill+lens+7; i += 8 { 52 holder = binary.LittleEndian.Uint64(dst[i:]) ^ iv1 53 v0, v1 = uint32(holder>>32), uint32(holder) 54 for i := 0; i < 0x10; i++ { 55 v0 += (v1 + sumtable[i]) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 56 v1 += (v0 + sumtable[i]) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 57 } 58 iv1 = (uint64(v0)<<32 | uint64(v1)) ^ iv2 59 iv2 = holder 60 binary.LittleEndian.PutUint64(dst[i:], iv1) 61 } 62 63 return fill + lens + 7 64 } 65 66 //go:nosplit 67 func (t TEA) Decrypt(data []byte) []byte { 68 if len(data) < 16 || len(data)&7 != 0 { 69 return nil 70 } 71 dst := make([]byte, len(data)) 72 73 var iv1, iv2, holder uint64 74 var v0, v1 uint32 75 for i := 0; i < len(dst); i += 8 { 76 iv1 = binary.BigEndian.Uint64(data[i:]) 77 iv2 ^= iv1 78 v0, v1 = uint32(iv2>>32), uint32(iv2) 79 v1 -= (v0 + 0xe3779b90) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 80 v0 -= (v1 + 0xe3779b90) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 81 v1 -= (v0 + 0x454021d7) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 82 v0 -= (v1 + 0x454021d7) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 83 v1 -= (v0 + 0xa708a81e) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 84 v0 -= (v1 + 0xa708a81e) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 85 v1 -= (v0 + 0x08d12e65) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 86 v0 -= (v1 + 0x08d12e65) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 87 v1 -= (v0 + 0x6a99b4ac) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 88 v0 -= (v1 + 0x6a99b4ac) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 89 v1 -= (v0 + 0xcc623af3) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 90 v0 -= (v1 + 0xcc623af3) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 91 v1 -= (v0 + 0x2e2ac13a) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 92 v0 -= (v1 + 0x2e2ac13a) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 93 v1 -= (v0 + 0x8ff34781) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 94 v0 -= (v1 + 0x8ff34781) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 95 v1 -= (v0 + 0xf1bbcdc8) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 96 v0 -= (v1 + 0xf1bbcdc8) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 97 v1 -= (v0 + 0x5384540f) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 98 v0 -= (v1 + 0x5384540f) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 99 v1 -= (v0 + 0xb54cda56) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 100 v0 -= (v1 + 0xb54cda56) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 101 v1 -= (v0 + 0x1715609d) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 102 v0 -= (v1 + 0x1715609d) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 103 v1 -= (v0 + 0x78dde6e4) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 104 v0 -= (v1 + 0x78dde6e4) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 105 v1 -= (v0 + 0xdaa66d2b) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 106 v0 -= (v1 + 0xdaa66d2b) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 107 v1 -= (v0 + 0x3c6ef372) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 108 v0 -= (v1 + 0x3c6ef372) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 109 v1 -= (v0 + 0x9e3779b9) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 110 v0 -= (v1 + 0x9e3779b9) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 111 iv2 = uint64(v0)<<32 | uint64(v1) 112 binary.BigEndian.PutUint64(dst[i:], iv2^holder) 113 holder = iv1 114 } 115 116 return dst[dst[0]&7+3 : len(data)-7] 117 } 118 119 //go:nosplit 120 func (t TEA) DecryptTo(data []byte, dst []byte) (from, to int) { 121 if len(data) < 16 || len(data)&7 != 0 { 122 return -1, -1 123 } 124 125 var iv1, iv2, holder uint64 126 var v0, v1 uint32 127 for i := 0; i < len(data); i += 8 { 128 iv1 = binary.BigEndian.Uint64(data[i:]) 129 iv2 ^= iv1 130 v0, v1 = uint32(iv2>>32), uint32(iv2) 131 v1 -= (v0 + 0xe3779b90) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 132 v0 -= (v1 + 0xe3779b90) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 133 v1 -= (v0 + 0x454021d7) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 134 v0 -= (v1 + 0x454021d7) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 135 v1 -= (v0 + 0xa708a81e) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 136 v0 -= (v1 + 0xa708a81e) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 137 v1 -= (v0 + 0x08d12e65) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 138 v0 -= (v1 + 0x08d12e65) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 139 v1 -= (v0 + 0x6a99b4ac) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 140 v0 -= (v1 + 0x6a99b4ac) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 141 v1 -= (v0 + 0xcc623af3) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 142 v0 -= (v1 + 0xcc623af3) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 143 v1 -= (v0 + 0x2e2ac13a) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 144 v0 -= (v1 + 0x2e2ac13a) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 145 v1 -= (v0 + 0x8ff34781) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 146 v0 -= (v1 + 0x8ff34781) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 147 v1 -= (v0 + 0xf1bbcdc8) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 148 v0 -= (v1 + 0xf1bbcdc8) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 149 v1 -= (v0 + 0x5384540f) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 150 v0 -= (v1 + 0x5384540f) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 151 v1 -= (v0 + 0xb54cda56) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 152 v0 -= (v1 + 0xb54cda56) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 153 v1 -= (v0 + 0x1715609d) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 154 v0 -= (v1 + 0x1715609d) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 155 v1 -= (v0 + 0x78dde6e4) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 156 v0 -= (v1 + 0x78dde6e4) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 157 v1 -= (v0 + 0xdaa66d2b) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 158 v0 -= (v1 + 0xdaa66d2b) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 159 v1 -= (v0 + 0x3c6ef372) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 160 v0 -= (v1 + 0x3c6ef372) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 161 v1 -= (v0 + 0x9e3779b9) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 162 v0 -= (v1 + 0x9e3779b9) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 163 iv2 = uint64(v0)<<32 | uint64(v1) 164 binary.BigEndian.PutUint64(dst[i:], iv2^holder) 165 holder = iv1 166 } 167 168 return int(dst[0]&7 + 3), len(data) - 7 169 } 170 171 //go:nosplit 172 func (t TEA) DecryptLittleEndian(data []byte, sumtable [0x10]uint32) []byte { 173 if len(data) < 16 || len(data)&7 != 0 { 174 return nil 175 } 176 dst := make([]byte, len(data)) 177 178 var iv1, iv2, holder uint64 179 var v0, v1 uint32 180 for i := 0; i < len(dst); i += 8 { 181 iv1 = binary.LittleEndian.Uint64(data[i:]) 182 iv2 ^= iv1 183 v0, v1 = uint32(iv2>>32), uint32(iv2) 184 for i := 0xf; i >= 0; i-- { 185 v1 -= (v0 + sumtable[i]) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 186 v0 -= (v1 + sumtable[i]) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 187 } 188 iv2 = uint64(v0)<<32 | uint64(v1) 189 binary.LittleEndian.PutUint64(dst[i:], iv2^holder) 190 holder = iv1 191 } 192 193 return dst[dst[0]&7+3 : len(data)-7] 194 } 195 196 //go:nosplit 197 func (t TEA) DecryptLittleEndianTo(data []byte, sumtable [0x10]uint32, dst []byte) (from, to int) { 198 if len(data) < 16 || len(data)&7 != 0 { 199 return -1, -1 200 } 201 202 var iv1, iv2, holder uint64 203 var v0, v1 uint32 204 for i := 0; i < len(data); i += 8 { 205 iv1 = binary.LittleEndian.Uint64(data[i:]) 206 iv2 ^= iv1 207 v0, v1 = uint32(iv2>>32), uint32(iv2) 208 for i := 0xf; i >= 0; i-- { 209 v1 -= (v0 + sumtable[i]) ^ ((v0 << 4) + t[2]) ^ ((v0 >> 5) + t[3]) 210 v0 -= (v1 + sumtable[i]) ^ ((v1 << 4) + t[0]) ^ ((v1 >> 5) + t[1]) 211 } 212 iv2 = uint64(v0)<<32 | uint64(v1) 213 binary.LittleEndian.PutUint64(dst[i:], iv2^holder) 214 holder = iv1 215 } 216 217 return int(dst[0]&7 + 3), len(data) - 7 218 }