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  }