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  }