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  }