javascript - JavaScript 中的 TEA 加密

标签 javascript encryption

我正在尝试将 Objective C TEA 加密转换为 Javascript,但在其中一个内部循环内,数字与 Objective C 版本不匹配

这是 Objective C 版本

#define TIMES 32
@implementation NSData (NSData_extend)

// Encrypt NSData with pwdKey
-(NSData*)addTEA:(const unsigned int *)pwdkey
{
    unsigned char * ch = (unsigned char*)[self bytes];
    int n = 8-self.length%8;
    char byte[self.length+n];
    char cc = n;
    for (int i=0; i<n; i++) {
        if (i==0) {
            byte[i] = cc;
        }
        else{
            byte[i] = 0;
        }
    }
    for (int i=0; i<self.length; i++) {
        byte[n+i] = ch[i];
    }

    int delta = 0x9e3779b9;
    int a     = pwdkey[0];
    int b     = pwdkey[1];
    int c     = pwdkey[2];
    int d     = pwdkey[3];

    unsigned char newbyte[self.length+n];
    for (int offset=0; offset<self.length+n; offset += 8) {
        int y = [self ByteTounint:byte[offset+3]] | [self ByteTounint:byte[offset+2]]<<8 | [self ByteTounint:byte[offset+1]]<<16 | [self ByteTounint:byte[offset+0]]<<24;
        int z = [self ByteTounint:byte[offset+7]] | [self ByteTounint:byte[offset+6]]<<8 | [self ByteTounint:byte[offset+5]]<<16 | [self ByteTounint:byte[offset+4]]<<24;

        int sum = 0;
        for (int i=0; i<TIMES; i++) {
            sum += delta;
            y += ((z<<4) + a) ^ (z + sum) ^ ((z>>5) + b);
            z += ((y<<4) + c) ^ (y + sum) ^ ((y>>5) + d);
        }
        newbyte[offset+7] = z & 0x000000ff;
        newbyte[offset+6] = (z & 0x0000ff00) >> 8;
        newbyte[offset+5] = (z & 0x00ff0000) >> 16;
        newbyte[offset+4] = (z & 0xff000000) >> 24;
        newbyte[offset+3] = y & 0x000000ff;
        newbyte[offset+2] = (y & 0x0000ff00) >> 8;
        newbyte[offset+1] = (y & 0x00ff0000) >> 16;
        newbyte[offset+0] = (y & 0xff000000) >> 24;
    }

    NSData * resultData = [NSData dataWithBytes:newbyte length:self.length+n];
    return resultData;
}

// Decrypt NSData with pwdKey
-(NSData*)subtractTEA:(const unsigned int *)pwdkey
{
    unsigned char * byte = (unsigned char*)[self bytes];
    int delta = 0x9e3779b9;
    int a     = pwdkey[0];
    int b     = pwdkey[1];
    int c     = pwdkey[2];
    int d     = pwdkey[3];
    unsigned char newbyte[self.length];
    for (int offset=0; offset<self.length; offset += 8) {
        int y = [self ByteTounint:byte[offset+3]] | [self ByteTounint:byte[offset+2]]<<8 | [self ByteTounint:byte[offset+1]]<<16 | [self ByteTounint:byte[offset+0]]<<24;
        int z = [self ByteTounint:byte[offset+7]] | [self ByteTounint:byte[offset+6]]<<8 | [self ByteTounint:byte[offset+5]]<<16 | [self ByteTounint:byte[offset+4]]<<24;
        int sum = 0;
        if (TIMES == 32) {
            sum = 0xC6EF3720;
        }
        else if (TIMES == 16){
            sum = 0xE3779B90;
        }
        else{
            sum = delta * TIMES;
        }

        for (int i=0; i<TIMES; i++) {
            z   -= ((y<<4) + c) ^ (y + sum) ^ ((y>>5) + d);
            y   -= ((z<<4) + a) ^ (z + sum) ^ ((z>>5) + b);
            sum -= delta;
        }
        newbyte[offset+7] = z & 0x000000ff;
        newbyte[offset+6] = (z & 0x0000ff00) >> 8;
        newbyte[offset+5] = (z & 0x00ff0000) >> 16;
        newbyte[offset+4] = (z & 0xff000000) >> 24;
        newbyte[offset+3] = y & 0x000000ff;
        newbyte[offset+2] = (y & 0x0000ff00) >> 8;
        newbyte[offset+1] = (y & 0x00ff0000) >> 16;
        newbyte[offset+0] = (y & 0xff000000) >> 24;
    }
    int n = newbyte[0];
    unsigned char ch[self.length-n];
    for (int i=0; i<self.length-n; i++) {
        ch[i] = newbyte[i+n];
    }
    NSData * resultData = [NSData dataWithBytes:ch length:self.length-n];
    return resultData;
}

- (int)ByteTounint:(int)byte
{
    if (byte<0) {
        return (byte+256);
    }
    return byte;
}

我的 JavaScript 版本

TEA.prototype.encrypt = function(src,pwdkey) {
    var TIMES = 32;
    var n = 8 - (src.length % 8);
    var byte = Buffer.alloc(src.length + n);
    var cc = n;

    for (var i = 0; i < n; i++) {
        if (i == 0) {
            byte[i] = cc;
        }
        else {
            byte[i] = 0;
        }
    }

    for (var j = 0; j < src.length; j++) {
        byte.write( src[j],(n+j));

    }
    var delta = 0x9e3779b9;
    var a = pwdkey.readInt32LE(0);
    var b = pwdkey.readInt32LE(1);
    var c = pwdkey.readInt32LE(2);
    var d = pwdkey.readInt32LE(3);

    var newbyte = Buffer.alloc(src.length + n);

    for (var offset = 0; offset < src.length + n; offset += 8) {
        var y = ByteTounint(byte[offset + 3]) | ByteTounint(byte[offset + 2] << 8) | ByteTounint(byte[offset + 1] << 16) | ByteTounint(byte[offset + 0]) << 24;
        var z = ByteTounint(byte[offset + 7]) | ByteTounint(byte[offset + 6]) << 8 | ByteTounint(byte[offset + 5]) << 16 | ByteTounint(byte[offset + 4]) << 24;

        var sum = 0;
        for(var i=0;i<TIMES;i++)
        {
            sum += delta;
            sum >>>= 0;
            y += (((z<<4)+a) ^ (z+sum) ^ ((z>>>5)+b)) >>> 0;
            z += (((y<<4)+c) ^ (y+sum) ^ ((y>>>5)+d)) >>> 0;

        }
        newbyte.writeInt8((z & 0x000000ff),(offset + 7));
        newbyte.writeInt8(((z & 0x0000ff00) >> 8),(offset + 6));
        newbyte.writeInt8(((z & 0x00ff0000) >> 16),(offset + 5));
        newbyte.writeInt8(((z & 0xff000000) >> 24),(offset + 4));

        newbyte.writeInt8((y & 0x000000ff),(offset + 3));
        newbyte.writeInt8(((y & 0x0000ff00) >> 8),(offset + 2));
        newbyte.writeInt8(((y & 0x00ff0000) >> 16),(offset + 1));
        newbyte.writeInt8(((y & 0xff000000) >> 24),(offset + 0));
    }

    return newbyte

};

function ByteTounint(byte) {
    if (byte<0) {
        return (byte+256);
    }
    return byte;
}

JavaScript 版本的用法

var pwdkey = new Buffer("4523F10F214365873248738902EFCDAB","hex");
var dene = tea.encrypt("params={\"method\":\"waybill.querywaybill\",\"requstParams\":{\"memNo\":\"\",\"waybillNo\":\"606447740110\"}}",pwdkey);

目标版本的用法和示例结果

NSString *keyString = @"4523F10F214365873248738902EFCDAB";
NSData *keyData = [NSData dataWithHexString:keyString];
const unsigned char *src = (const unsigned char *)[key bytes];
NSString *str = @"params={\"method\":\"waybill.querywaybill\",\"requstParams\":{\"memNo\":\"\",\"waybillNo\":\"606447740110\"}}";
NSData *data = [NSData dataWithBytes:str.UTF8String length:str.length];
NSData * result2 = [data addTEA:src];
NSLog(@"%@",result2);
// prints 167da396 9b183f2e d12ac3f5 5083a581.....

我的版本开始在for(var i=0;i<TIMES;i++)内给出错误的值环形。然后它在newbyte.writeInt8期间崩溃部分。

最佳答案

终于,我成功了。这是一个工作版本,可以正确加密和解​​密任何大小的文本。

function ByteTounint(byte) {

    if (byte<0) {
        return (byte+256);
    }
    return byte;
}


TEA.prototype.decrypt = function(src,pwdkey) {
    var TIMES = 32;
    var delta = 0x9e3779b9;

    var a = pwdkey.readUInt32LE(0);
    var b = pwdkey.readUInt32LE(4);
    var c = pwdkey.readUInt32LE(8);
    var d = pwdkey.readUInt32LE(12);

    var newbyte = Buffer.alloc(src.length);

    for (var offset=0; offset<src.length; offset += 8) {
        var y = ByteTounint(src[offset + 3]) | ByteTounint(src[offset + 2]) << 8 | ByteTounint(src[offset + 1]) << 16 | ByteTounint(src[offset + 0]) << 24;
        var z = ByteTounint(src[offset + 7]) | ByteTounint(src[offset + 6]) << 8 | ByteTounint(src[offset + 5]) << 16 | ByteTounint(src[offset + 4]) << 24;


        var sum = 0;
        if (TIMES == 32) {
            sum = 0xC6EF3720;
        }
        else if (TIMES == 16) {
            sum = 0xE3779B90;
        }
        else {
            sum = delta * TIMES;
        }

        for (var i = 0; i < TIMES; i++) {
            z = (z - (( ( (y<<4) + c) & 0xFFFFFFFF) ^ (  (y + sum) & 0xFFFFFFFF ) ^ ( ((y >> 5) + d ) & 0xFFFFFFFF))) & 0xFFFFFFFF
            y = (y - (( ( (z<<4) + a) & 0xFFFFFFFF) ^ (  (z + sum) & 0xFFFFFFFF ) ^ ( ((z >> 5) + b ) & 0xFFFFFFFF))) & 0xFFFFFFFF
            sum = (sum - delta) & 0xFFFFFFFF;
        }

        newbyte.writeInt32BE((y & 0xFFFFFFFF),offset);
        newbyte.writeInt32BE((z & 0xFFFFFFFF),(offset+4));
    }

    var n = newbyte[0];
    var ch = Buffer.alloc(src.length - n);

    for (var i=0; i<src.length-n; i++) {
        ch[i] = newbyte[i+n];
    }

    return ch;
};

TEA.prototype.encrypt = function(src,pwdkey) {
    var TIMES = 32;
    var n = 8 - (src.length % 8);
    var byte = Buffer.alloc(src.length + n);
    var cc = n;

    for (var i = 0; i < n; i++) {
        if (i == 0) {
            byte[i] = cc;
        }
        else {
            byte[i] = 0;
        }
    }


    for (var j = 0; j < src.length; j++) {
        byte.write( src[j],(n+j));

    }
    var delta = 0x9e3779b9; 
    var a = pwdkey.readUInt32LE(0);
    var b = pwdkey.readUInt32LE(4);
    var c = pwdkey.readUInt32LE(8);
    var d = pwdkey.readUInt32LE(12);

    var newbyte = Buffer.alloc(src.length + n);

    for (var offset = 0; offset < src.length + n; offset += 8) {

        var y = ByteTounint(byte[offset + 3]) | ByteTounint(byte[offset + 2]) << 8 | ByteTounint(byte[offset + 1]) << 16 | ByteTounint(byte[offset + 0]) << 24;
        var z = ByteTounint(byte[offset + 7]) | ByteTounint(byte[offset + 6]) << 8 | ByteTounint(byte[offset + 5]) << 16 | ByteTounint(byte[offset + 4]) << 24;

        var sum = 0;

        for(var i=0;i<TIMES;i++)
        {
            sum = (sum + delta) & 0xFFFFFFFF;
            y = (y + (( ( (z<<4) + a) & 0xFFFFFFFF) ^ (  (z + sum) & 0xFFFFFFFF ) ^ ( ((z >> 5) + b ) & 0xFFFFFFFF))) & 0xFFFFFFFF;
            z = (z + (( ( (y<<4) + c) & 0xFFFFFFFF) ^ (  (y + sum) & 0xFFFFFFFF ) ^ ( ((y >> 5) + d ) & 0xFFFFFFFF))) & 0xFFFFFFFF
        }

        newbyte.writeInt32BE((y & 0xFFFFFFFF),offset);
        newbyte.writeInt32BE((z & 0xFFFFFFFF),(offset+4));
    }

    return newbyte

};

```

关于javascript - JavaScript 中的 TEA 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39676514/

相关文章:

javascript - 将 git show 输出转换为条目对象和对应的路径树对象

javascript - Onclick 更改脚本标签内的功能

c++ - _free_base "Error reading register value"

objective-c - Objective C 加密 CFB 模式

javascript - 如何在sequelize.js、node中以关联模式插入数据

javascript - 无法选择表格单元格内的链接

javascript - 未在无序列表中显示 json 解析的数据

java - 基于 Minecraft 世界的加密。是否可以?

c# - 使用在 .NET 中不起作用但在 SOAP UI 中起作用的证书解密加密 key

java - 在 Java 中加密和解密密码