【Golang】golang仿C++的变种TEA加密与解密

什么是TEA加密

TEA算法是由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明,TEA是Tiny Encryption Algorithm的缩写,以加密解密速度快,实现简单著称。TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。为解决TEA算法密钥表攻击的问题,TEA算法先后经历了几次改进,从XTEA到BLOCK TEA,直至最新的XXTEA。XTEA也称做TEAN,它使用与TEA相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。Block TEA算法可以对32位的任意整数倍长度的变量块进行加解密的操作,该算法将XTEA轮循函数依次应用于块中的每个字,并且将它附加于被应用字的邻字。XXTEA使用跟Block TEA相似的结构,但在处理块中每个字时利用了相邻字,且用拥有两个输入量的MX函数代替了XTEA轮循函数。上面提到的相邻字其实就是数组中相邻的项。

TEA系列算法中均使用了一个DELTA常数,但DELTA的值对算法并无什么影响,只是为了避免不良的取值,推荐DELTA的值取为黄金分割数(5√-2)/2与232的乘积,取整后的十六进制值为0x9e3779B9,用于保证每一轮加密都不相同。

本案例仅实现台服DNF的加解密TEA版本,不完全适用于原本TEA加密,本案例仅用于学习,请不要用于商业。

台服DNF 地下城与勇士的C++版本对数据库加密

#include <cstring>
#include <cstdio>
char *key = "troqkddmtroqkcdm";
char *postfix = "e8b10c1f8bc3595be8b10c1f8bc3595b";
class Encrypt {
	public:
	void getKeyPre(char sixkey[9], char *ret) {
		ret[0] = 0;
		char res1[80];
		encrypt(sixkey, res1);		
		strcat(ret, res1);
		strcat(ret, postfix);
	}
	private:
	long long bytes_to_long(char *t) {
		unsigned char *r = (unsigned char *) t;
		long long a = (0xFFFFFFFF & (unsigned int) r[0]) << 24;
		long long b = (0xFFFFFFFF & (unsigned int) r[1]) << 16;
		long long c = (0xFFFFFFFF & (unsigned int) r[2]) << 8;
		long long d = r[3];
		return (a + b + c + d);
	}
	void long_to_bytes(long long v, char *ret) {
		int a = (int) ((0xFF000000 & v) >> 24);
		int b = (int) ((0xFF0000 & v) >> 16);
		int c = (int) ((0xFF00 & v) >> 8);
		int d = (int) (0xFF & v);
		sprintf(ret, "%02x%02x%02x%02x", a, b, c, d);
	}
	long long unpack(char *tmp, int start, int len) {
		unsigned char *arr = (unsigned char *) (tmp + start);
		long long d = arr[0];
		long long c = arr[1];
		long long b = arr[2];
		long long a = arr[3];
		a = a << 24;
		b = b << 16;
		c = c << 8;
		return (a + b + c + d);
	}
	void encrypt(char v[9], char *ret) {
		long long v0 = bytes_to_long(v);
		long long v1 = bytes_to_long(v + 4);
		long long sum = 0;
		for (int i = 0; i < 32; ++i) {
			long long tv1 = toUInt32(toUInt32(v1 << 4)) ^ toUInt32((v1 >> 5 & 0x07FFFFFF));
			long long tv2 = unpack(key, ((int) sum & 3) * 4, 4);
			v0 = toUInt32(v0 + (toUInt32(tv1 + v1) ^ toUInt32(tv2 + sum)));
			sum = toUInt32(sum + 0x9E3779B9);
			tv1 = toUInt32(toUInt32(toUInt32(v0 << 4)) ^ toUInt32((v0 >> 5 & 0x07FFFFFF)));
			tv2 = unpack(key, ((int) toUInt32((int) sum >> 11) & 3) * 4, 4);
			v1 = toUInt32(v1 + (toUInt32(tv1 + v0) ^ toUInt32(tv2 + sum)));
		}
		long_to_bytes(v0, ret);
		long_to_bytes(v1, ret + 8);		
	}
	long long toUInt32(long long v) {
		return (v & 0xFFFFFFFF);
	}
}
;
void getKey(char sixkey[9], char *ret) {
	Encrypt enc;
	enc.getKeyPre(sixkey, ret);
}
int main() {
	char password[] = "uu5!^%jg";
	char res[100];	
	getKey(password, res);
	printf("%s", res);
	return (0);
}

golang版本仿写加、解密

package main

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"log"
	"strconv"
)

func main() {
	var (
		yourText = []byte("uu5!^%jg")                 // 你的加密串(自行修改)
		key      = []byte("troqkddmtroqkcdm")         // 密钥 (勿动)
		postFix  = "e8b10c1f8bc3595be8b10c1f8bc3595b" // 补充信息(勿动)
	)

	tc, err := NewCipher(key)
	if err != nil {
		log.Fatalln(err)
	}
	dst, dst1 := make([]byte, 8), make([]byte, 8)
	tc.Encrypt(dst, yourText)
	result := hex.EncodeToString(dst) + postFix
	fmt.Println("加密后:", result)
	tc.Decrypt(dst1, dst)
	fmt.Println("解密后:", string(dst1))
}

type teaCipher struct {
	key []byte
}

type KeySizeError int

func (k KeySizeError) Error() string {
	return "tea: invalid key size " + strconv.Itoa(int(k))
}

func NewCipher(key []byte) (*teaCipher, error) {
	if len(key) != 16 {
		return nil, KeySizeError(len(key))
	}
	cipher := new(teaCipher)
	cipher.key = key
	return cipher, nil
}

func (c *teaCipher) BlockSize() int {
	return 8
}

func (c *teaCipher) Encrypt(dst, src []byte) {
	var (
		end                  = binary.BigEndian
		v0, v1               = end.Uint32(src), end.Uint32(src[4:])
		sum           uint32 = 0
		delta         uint32 = 0x9E3779B9 // 黄金分割位
		CorrectionBit uint32 = 0x7FFFFFF  // 修正位
	)
	for i := 0; i < 32; i++ {
		tv1 := (v1 << 4) ^ (v1 >> 5 & CorrectionBit)
		tv2 := unpack(c.key, (sum&3)*4)
		v0 += (tv1 + v1) ^ (tv2 + sum)
		sum += delta
		tv1 = (v0 << 4) ^ (v0 >> 5 & CorrectionBit)
		tv2 = unpack(c.key, ((sum>>11)&3)*4)
		v1 += (tv1 + v0) ^ (tv2 + sum)
	}
	end.PutUint32(dst, v0)
	end.PutUint32(dst[4:], v1)
}

func (c *teaCipher) Decrypt(dst, src []byte) {
	var (
		end                  = binary.BigEndian
		v0, v1               = end.Uint32(src[0:4]), end.Uint32(src[4:8])
		delta         uint32 = 0x9E3779B9 // 黄金分割位
		sum           uint32 = delta << 5
		CorrectionBit uint32 = 0x7FFFFFF // 修正位
	)
	for i := 0; i < 32; i++ {
		tv1 := (v0 << 4) ^ (v0 >> 5 & CorrectionBit)
		tv2 := unpack(c.key, ((sum>>11)&3)*4)
		v1 -= (tv1 + v0) ^ (tv2 + sum)
		sum -= delta
		tv1 = (v1 << 4) ^ (v1 >> 5 & CorrectionBit)
		tv2 = unpack(c.key, (sum&3)*4)
		v0 -= (tv1 + v1) ^ (tv2 + sum)
	}
	end.PutUint32(dst, v0)
	end.PutUint32(dst[4:], v1)
}

func unpack(tmp []byte, start uint32) uint32 {
	tmp = tmp[start:]
	a := tmp[3]
	b := tmp[2]
	c := tmp[1]
	d := tmp[0]
	return uint32(d) | uint32(c)<<8 | uint32(b)<<16 | uint32(a)<<24
}

用例运行效果如下:

在这里插入图片描述

github原文:https://github.com/anyanfei/DofTeaCrypt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值