V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
copyangle
V2EX  ›  Python

求个 转 python 的算法,原 java tea 加密算法

  •  
  •   copyangle · 2015-07-29 11:58:22 +08:00 · 2380 次点击
    这是一个创建于 3200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    java算法如下,可独立运行。怎奈小弟才疏学浅,有一段转换byte数组没看懂,哪位大侠能帮忙写个python版本,感激不尽~

    package com.bmcc.service.pub.util;
    
    
    /** 
    * Tea算法
    * KEY为16字节,应为包含4个int型数的int[],一个int为4个字节
    * 加密解密轮数应为8的倍数,推荐加密轮数为64轮
    **/
    public class Tea {
        private int[] KEY = new int[] { //加密解密所用的KEY
            1, 2, 3, 4 };
        private String separatoradd = "0"; //加密字符串分隔符"+"
    
        private String separatordel = "1"; //加密字符串分隔符"-"
        //加密
        private byte[] encrypt(
            byte[] content,
            int offset,
            int[] key,
            int times) { //times为加密轮数
            int[] tempInt = byteToInt(content, offset);
            int y = tempInt[0], z = tempInt[1], sum = 0, i;
            int delta = 0x9e3779b9; //这是算法标准给的值
            int a = key[0], b = key[1], c = key[2], d = key[3];
    
            for (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);
            }
            tempInt[0] = y;
            tempInt[1] = z;
            return intToByte(tempInt, 0);
        }
        //解密
        private byte[] decrypt(
            byte[] encryptContent,
            int offset,
            int[] key,
            int times) {
            int[] tempInt = byteToInt(encryptContent, offset);
            int y = tempInt[0], z = tempInt[1], sum = 0xC6EF3720, i;
            int delta = 0x9e3779b9; //这是算法标准给的值
            int a = key[0], b = key[1], c = key[2], d = key[3];
    
            for (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;
            }
            tempInt[0] = y;
            tempInt[1] = z;
    
            return intToByte(tempInt, 0);
        }
        //byte[]型数据转成int[]型数据
        private int[] byteToInt(byte[] content, int offset) {
    
            int[] result = new int[content.length >> 2];
            for (int i = 0, j = offset; j < content.length; i++, j += 4) {
                result[i] =
                    transform(content[j + 3]) | transform(content[j + 2])
                        << 8 | transform(content[j + 1])
                        << 16 | (int) content[j]
                        << 24;
            }
            return result;
    
        }
        //int[]型数据转成byte[]型数据
        private byte[] intToByte(int[] content, int offset) {
            byte[] result = new byte[content.length << 2];
            for (int i = 0, j = offset; j < result.length; i++, j += 4) {
                result[j + 3] = (byte) (content[i] & 0xff);
                result[j + 2] = (byte) ((content[i] >> 8) & 0xff);
                result[j + 1] = (byte) ((content[i] >> 16) & 0xff);
                result[j] = (byte) ((content[i] >> 24) & 0xff);
            }
            return result;
        }
        //若某字节被解释成负的则需将其转成无符号正数
        private int transform(byte temp) {
            int tempInt = (int) temp;
            if (tempInt < 0) {
                tempInt += 256;
            }
            return tempInt;
        }
        //  通过TEA算法加密信息
        public String encryptByTea(String info) {
            byte[] temp = info.getBytes();
            int n = 8 - temp.length % 8; //若temp的位数不足8的倍数,需要填充的位数
            byte[] encryptStr = new byte[temp.length + n];
            encryptStr[0] = (byte) n;
            System.arraycopy(temp, 0, encryptStr, n, temp.length);
            byte[] result = new byte[encryptStr.length];
            for (int offset = 0; offset < result.length; offset += 8) {
                byte[] tempEncrpt = encrypt(encryptStr, offset, KEY, 32);
                System.arraycopy(tempEncrpt, 0, result, offset, 8);
            }
            String tmp = encryptTwo(result);
            //      for (int i = 0; i < result.length; i++) {
            //          tmp = tmp + result[i] + this.separator;
            //      }
            return tmp;
        }
    
        private String encryptTwo(byte[] source) {
            String all = "";
            for (int i = 0; i < source.length; i++) {
                String tmp = this.separatoradd;
                int s = source[i];
                if (s < 0) {
                    s = ~s + 1;
                    tmp = this.separatordel;
                }
                String res = Integer.toHexString(s);
                if (res.length() == 1)
                    res = "0" + res;
                all = all + res + tmp;
            }
            return all;
        }
    
        public byte[] decryptTwo(String res) {
            int k = 0;
            byte[] result = new byte[res.length() / 3];
            for (int i = 0, j = 3; i < res.length(); i = i + 3, j = i + 3) {
                String tmp = res.substring(i, j);
                if (this.separatoradd.charAt(0) == tmp.charAt(2))
                    result[k++] = Byte.parseByte(tmp.substring(0, 2),16);
                else if (this.separatordel.charAt(0) == tmp.charAt(2))
                    result[k++] = Byte.parseByte("-" + tmp.substring(0, 2),16);
            }
            return result;
        }
        //    通过TEA算法解密信息
        public String decryptByTea(String info) {
            byte[] secretInfo = this.decryptTwo(info);
            byte[] decryptStr = null;
            byte[] tempDecrypt = new byte[secretInfo.length];
            for (int offset = 0; offset < secretInfo.length; offset += 8) {
                decryptStr = decrypt(secretInfo, offset, KEY, 32);
                System.arraycopy(decryptStr, 0, tempDecrypt, offset, 8);
            }
            int n = tempDecrypt[0];
            return new String(tempDecrypt, n, decryptStr.length - n);
    
        }
    
        public static void main(String[] args) {
            Tea tea = new Tea();
            String src ="abcd1234";
            String tmp = tea.encryptByTea(src);
            String result = tea.decryptByTea("2700304515a02c16411f06e14f17b14e16401c01c0591390");
            System.out.print("原数据:");
            System.out.println(src);
            System.out.print("加密后的数据:");
            System.out.println(tmp);
            System.out.print("解密后的数据:");
            System.out.println(result);
        }
    }
    
    6 条回复    2015-08-03 09:55:49 +08:00
    copyangle
        1
    copyangle  
    OP
       2015-07-29 13:49:06 +08:00
    主要是这一段不明白,求解

    // 通过TEA算法加密信息
    public String encryptByTea(String info) {
    byte[] temp = info.getBytes();
    int n = 8 - temp.length % 8; //若temp的位数不足8的倍数,需要填充的位数
    byte[] encryptStr = new byte[temp.length + n];
    encryptStr[0] = (byte) n;
    System.arraycopy(temp, 0, encryptStr, n, temp.length);
    byte[] result = new byte[encryptStr.length];
    for (int offset = 0; offset < result.length; offset += 8) {
    byte[] tempEncrpt = encrypt(encryptStr, offset, KEY, 32);
    System.arraycopy(tempEncrpt, 0, result, offset, 8);
    }
    String tmp = encryptTwo(result);
    // for (int i = 0; i < result.length; i++) {
    // tmp = tmp + result[i] + this.separator;
    // }
    return tmp;
    }
    zhantss
        2
    zhantss  
       2015-07-30 11:46:55 +08:00   ❤️ 1
    for循环前的转换?
    获取输入字符的byte数组
    获取填充位数n(<8)
    新的byte数组第一个位置 放填充数n(<8所以byte足够表示)
    然后从第n(填充位)开始放原有temp的内容(长度正好)

    for开始就是加密的过程了
    copyangle
        3
    copyangle  
    OP
       2015-07-30 17:22:15 +08:00
    @zhantss python里面怎么把string转换成byte数组?
    zhantss
        4
    zhantss  
       2015-07-31 10:38:56 +08:00
    @copyangle 有点复杂 建议你看一下资料

    python 是动态类型 一般情况下type(target) 可以看target的类型
    python2 中用encode之后type()还是得到str类型 (你可以试一下help(bytes)出来的还是str)

    python3 中这样写就好了

    s = 'test'
    bs = bytes(s, encoding='[你的字符串编码类型/文件标注编码类型]')
    或者bs = s.encode('[你的字符串编码类型/文件标注编码类型]')
    这时候type(bs)得到的是bytes类型

    python2 中用第二种写法就好了, 第一种一般需要判断一下,但是你看到的类型还是str,有点难理解就是了,用还是可以用,稍稍有些不同
    copyangle
        5
    copyangle  
    OP
       2015-07-31 17:44:34 +08:00
    @zhantss 多谢,看来还是我基础不牢靠
    zhantss
        6
    zhantss  
       2015-08-03 09:55:49 +08:00
    @copyangle 相互学习啦 python我一般经常拿来干一些日常的事情 还没写过大型的python项目呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   810 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 22:33 · PVG 06:33 · LAX 15:33 · JFK 18:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.