github.com/fumiama/gofastTEA@v0.0.10/tea_1.17.go (about) 1 //go:build go1.17 && amd64 2 // +build go1.17,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 func (t TEA) Encrypt(src []byte) (dst []byte) { 12 lens := len(src) 13 fill := 10 - (lens+1)%8 14 dst = make([]byte, fill+lens+7) 15 binary.LittleEndian.PutUint32(dst, randuint32()) 16 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 17 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 18 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 19 copy(dst[fill:], src) 20 21 var iv1, iv2, holder uint64 22 for i := 0; i < len(dst); i += 8 { 23 block := binary.BigEndian.Uint64(dst[i:]) 24 holder = block ^ iv1 25 iv1 = t.encode(holder) 26 iv1 = iv1 ^ iv2 27 iv2 = holder 28 binary.BigEndian.PutUint64(dst[i:], iv1) 29 } 30 31 return dst 32 } 33 34 func (t TEA) EncryptTo(src []byte, dst []byte) int { 35 lens := len(src) 36 fill := 10 - (lens+1)%8 37 binary.LittleEndian.PutUint32(dst, randuint32()) 38 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 39 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 40 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 41 copy(dst[fill:], src) 42 43 var iv1, iv2, holder uint64 44 for i := 0; i < fill+lens+7; i += 8 { 45 block := binary.BigEndian.Uint64(dst[i:]) 46 holder = block ^ iv1 47 iv1 = t.encode(holder) 48 iv1 = iv1 ^ iv2 49 iv2 = holder 50 binary.BigEndian.PutUint64(dst[i:], iv1) 51 } 52 53 return fill + lens + 7 54 } 55 56 func (t TEA) EncryptLittleEndian(src []byte, sumtable [0x10]uint32) (dst []byte) { 57 lens := len(src) 58 fill := 10 - (lens+1)%8 59 dst = make([]byte, fill+lens+7) 60 binary.LittleEndian.PutUint32(dst, randuint32()) 61 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 62 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 63 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 64 copy(dst[fill:], src) 65 66 var iv1, iv2, holder uint64 67 for i := 0; i < len(dst); i += 8 { 68 block := binary.LittleEndian.Uint64(dst[i:]) 69 holder = block ^ iv1 70 iv1 = t.encodeTable(holder, sumtable) 71 iv1 = iv1 ^ iv2 72 iv2 = holder 73 binary.LittleEndian.PutUint64(dst[i:], iv1) 74 } 75 76 return dst 77 } 78 79 func (t TEA) EncryptLittleEndianTo(src []byte, sumtable [0x10]uint32, dst []byte) int { 80 lens := len(src) 81 fill := 10 - (lens+1)%8 82 binary.LittleEndian.PutUint32(dst, randuint32()) 83 binary.LittleEndian.PutUint32(dst[4:], randuint32()) 84 binary.LittleEndian.PutUint32(dst[8:], randuint32()) 85 dst[0] = byte(fill-3) | 0xF8 // 存储pad长度 86 copy(dst[fill:], src) 87 88 var iv1, iv2, holder uint64 89 for i := 0; i < fill+lens+7; i += 8 { 90 block := binary.LittleEndian.Uint64(dst[i:]) 91 holder = block ^ iv1 92 iv1 = t.encodeTable(holder, sumtable) 93 iv1 = iv1 ^ iv2 94 iv2 = holder 95 binary.LittleEndian.PutUint64(dst[i:], iv1) 96 } 97 98 return fill + lens + 7 99 } 100 101 func (t TEA) Decrypt(data []byte) []byte { 102 if len(data) < 16 || len(data)%8 != 0 { 103 return nil 104 } 105 dst := make([]byte, len(data)) 106 var iv1, iv2, holder uint64 107 for i := 0; i < len(dst); i += 8 { 108 iv1 = binary.BigEndian.Uint64(data[i:]) 109 iv2 ^= iv1 110 iv2 = t.decode(iv2) 111 binary.BigEndian.PutUint64(dst[i:], iv2^holder) 112 holder = iv1 113 } 114 return dst[dst[0]&7+3 : len(data)-7] 115 } 116 117 func (t TEA) DecryptTo(data []byte, dst []byte) (from, to int) { 118 if len(data) < 16 || len(data)%8 != 0 { 119 return -1, -1 120 } 121 var iv1, iv2, holder uint64 122 for i := 0; i < len(data); i += 8 { 123 iv1 = binary.BigEndian.Uint64(data[i:]) 124 iv2 ^= iv1 125 iv2 = t.decode(iv2) 126 binary.BigEndian.PutUint64(dst[i:], iv2^holder) 127 holder = iv1 128 } 129 return int(dst[0]&7 + 3), len(data) - 7 130 } 131 132 func (t TEA) DecryptLittleEndian(data []byte, sumtable [0x10]uint32) []byte { 133 if len(data) < 16 || len(data)%8 != 0 { 134 return nil 135 } 136 dst := make([]byte, len(data)) 137 var iv1, iv2, holder uint64 138 for i := 0; i < len(dst); i += 8 { 139 iv1 = binary.LittleEndian.Uint64(data[i:]) 140 iv2 ^= iv1 141 iv2 = t.decodeTable(iv2, sumtable) 142 binary.LittleEndian.PutUint64(dst[i:], iv2^holder) 143 holder = iv1 144 } 145 return dst[dst[0]&7+3 : len(data)-7] 146 } 147 148 func (t TEA) DecryptLittleEndianTo(data []byte, sumtable [0x10]uint32, dst []byte) (from, to int) { 149 if len(data) < 16 || len(data)%8 != 0 { 150 return -1, -1 151 } 152 var iv1, iv2, holder uint64 153 for i := 0; i < len(data); i += 8 { 154 iv1 = binary.LittleEndian.Uint64(data[i:]) 155 iv2 ^= iv1 156 iv2 = t.decodeTable(iv2, sumtable) 157 binary.LittleEndian.PutUint64(dst[i:], iv2^holder) 158 holder = iv1 159 } 160 return int(dst[0]&7 + 3), len(data) - 7 161 } 162 163 //go:nosplit 164 func (t *TEA) encode(n uint64) uint64 { 165 v0, v1 := uint32(n>>32), uint32(n) 166 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 167 168 v0 += (v1 + 0x9e3779b9) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 169 v1 += (v0 + 0x9e3779b9) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 170 v0 += (v1 + 0x3c6ef372) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 171 v1 += (v0 + 0x3c6ef372) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 172 v0 += (v1 + 0xdaa66d2b) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 173 v1 += (v0 + 0xdaa66d2b) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 174 v0 += (v1 + 0x78dde6e4) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 175 v1 += (v0 + 0x78dde6e4) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 176 v0 += (v1 + 0x1715609d) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 177 v1 += (v0 + 0x1715609d) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 178 v0 += (v1 + 0xb54cda56) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 179 v1 += (v0 + 0xb54cda56) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 180 v0 += (v1 + 0x5384540f) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 181 v1 += (v0 + 0x5384540f) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 182 v0 += (v1 + 0xf1bbcdc8) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 183 v1 += (v0 + 0xf1bbcdc8) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 184 v0 += (v1 + 0x8ff34781) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 185 v1 += (v0 + 0x8ff34781) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 186 v0 += (v1 + 0x2e2ac13a) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 187 v1 += (v0 + 0x2e2ac13a) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 188 v0 += (v1 + 0xcc623af3) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 189 v1 += (v0 + 0xcc623af3) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 190 v0 += (v1 + 0x6a99b4ac) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 191 v1 += (v0 + 0x6a99b4ac) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 192 v0 += (v1 + 0x08d12e65) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 193 v1 += (v0 + 0x08d12e65) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 194 v0 += (v1 + 0xa708a81e) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 195 v1 += (v0 + 0xa708a81e) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 196 v0 += (v1 + 0x454021d7) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 197 v1 += (v0 + 0x454021d7) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 198 v0 += (v1 + 0xe3779b90) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 199 v1 += (v0 + 0xe3779b90) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 200 201 return uint64(v0)<<32 | uint64(v1) 202 } 203 204 //go:nosplit 205 func (t *TEA) encodeTable(n uint64, s [0x10]uint32) uint64 { 206 v0, v1 := uint32(n>>32), uint32(n) 207 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 208 209 for i := 0; i < 0x10; i++ { 210 v0 += (v1 + s[i]) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 211 v1 += (v0 + s[i]) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 212 } 213 214 return uint64(v0)<<32 | uint64(v1) 215 } 216 217 // 每次8字节 218 //go:nosplit 219 func (t *TEA) decode(n uint64) uint64 { 220 v0, v1 := uint32(n>>32), uint32(n) 221 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 222 223 v1 -= (v0 + 0xe3779b90) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 224 v0 -= (v1 + 0xe3779b90) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 225 v1 -= (v0 + 0x454021d7) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 226 v0 -= (v1 + 0x454021d7) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 227 v1 -= (v0 + 0xa708a81e) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 228 v0 -= (v1 + 0xa708a81e) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 229 v1 -= (v0 + 0x08d12e65) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 230 v0 -= (v1 + 0x08d12e65) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 231 v1 -= (v0 + 0x6a99b4ac) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 232 v0 -= (v1 + 0x6a99b4ac) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 233 v1 -= (v0 + 0xcc623af3) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 234 v0 -= (v1 + 0xcc623af3) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 235 v1 -= (v0 + 0x2e2ac13a) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 236 v0 -= (v1 + 0x2e2ac13a) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 237 v1 -= (v0 + 0x8ff34781) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 238 v0 -= (v1 + 0x8ff34781) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 239 v1 -= (v0 + 0xf1bbcdc8) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 240 v0 -= (v1 + 0xf1bbcdc8) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 241 v1 -= (v0 + 0x5384540f) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 242 v0 -= (v1 + 0x5384540f) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 243 v1 -= (v0 + 0xb54cda56) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 244 v0 -= (v1 + 0xb54cda56) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 245 v1 -= (v0 + 0x1715609d) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 246 v0 -= (v1 + 0x1715609d) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 247 v1 -= (v0 + 0x78dde6e4) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 248 v0 -= (v1 + 0x78dde6e4) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 249 v1 -= (v0 + 0xdaa66d2b) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 250 v0 -= (v1 + 0xdaa66d2b) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 251 v1 -= (v0 + 0x3c6ef372) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 252 v0 -= (v1 + 0x3c6ef372) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 253 v1 -= (v0 + 0x9e3779b9) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 254 v0 -= (v1 + 0x9e3779b9) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 255 256 return uint64(v0)<<32 | uint64(v1) 257 } 258 259 // 每次8字节 260 //go:nosplit 261 func (t *TEA) decodeTable(n uint64, s [0x10]uint32) uint64 { 262 v0, v1 := uint32(n>>32), uint32(n) 263 t0, t1, t2, t3 := t[0], t[1], t[2], t[3] 264 265 for i := 0xf; i >= 0; i-- { 266 v1 -= (v0 + s[i]) ^ ((v0 << 4) + t2) ^ ((v0 >> 5) + t3) 267 v0 -= (v1 + s[i]) ^ ((v1 << 4) + t0) ^ ((v1 >> 5) + t1) 268 } 269 270 return uint64(v0)<<32 | uint64(v1) 271 }