⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crypter.java

📁 lumaQQ的源文件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            }
            if(pos == 8)
                encrypt8Bytes();
        }
        
        // 头部填充完了,这里开始填真正的明文了,也是满了8字节就加密,一直到明文读完
        int i = offset;
        while(len > 0) {
            if(pos < 8) {
                plain[pos++] = in[i++];
                len--;
            }
            if(pos == 8)
                encrypt8Bytes();
        }
        
        // 最后填上0,以保证是8字节的倍数
        padding = 1;
        while(padding <= 7) {
            if(pos < 8) {
                plain[pos++] = 0x0;
                padding++;
            }
            if(pos == 8)
                encrypt8Bytes();
        }
        
        return out;
    }

    /**
     * @param in
     *            需要加密的明文
     * @param inLen
     *            明文长度
     * @param k
     *            密钥
     * @return Message 密文
     */
    public byte[] encrypt(byte[] in, byte[] k) {
        return encrypt(in, 0, in.length, k);
    }

    /**
     * 加密一个8字节块
     * 
     * @param in
     * 		明文字节数组
     * @return
     * 		密文字节数组
     */
    private byte[] encipher(byte[] in) {
        // 迭代次数,16次
        int loop = 0x10;
        // 得到明文和密钥的各个部分,注意java没有无符号类型,所以为了表示一个无符号的整数
        // 我们用了long,这个long的前32位是全0的,我们通过这种方式模拟无符号整数,后面用到的long也都是一样的
        // 而且为了保证前32位为0,需要和0xFFFFFFFF做一下位与            
        long y = Util.getUnsignedInt(in, 0, 4);
        long z = Util.getUnsignedInt(in, 4, 4);
        long a = Util.getUnsignedInt(key, 0, 4);
        long b = Util.getUnsignedInt(key, 4, 4);
        long c = Util.getUnsignedInt(key, 8, 4);
        long d = Util.getUnsignedInt(key, 12, 4);
        // 这是算法的一些控制变量,为什么delta是0x9E3779B9呢?
        // 这个数是TEA算法的delta,实际是就是(sqr(5) - 1) * 2^31 (根号5,减1,再乘2的31次方)
        long sum = 0;
        long delta = 0x9E3779B9;
        delta &= 0xFFFFFFFFL;

        // 开始迭代了,乱七八糟的,我也看不懂,反正和DES之类的差不多,都是这样倒来倒去
        while (loop-- > 0) {
            sum += delta;
            sum &= 0xFFFFFFFFL;
            y += ((z << 4) + a) ^ (z + sum) ^ ((z >>> 5) + b);
            y &= 0xFFFFFFFFL;
            z += ((y << 4) + c) ^ (y + sum) ^ ((y >>> 5) + d);
            z &= 0xFFFFFFFFL;
        }

        // 最后,我们输出密文,因为我用的long,所以需要强制转换一下变成int
        baos.reset();
        writeInt((int)y);
        writeInt((int)z);
        return baos.toByteArray();
    }
    
    /**
     * 解密从offset开始的8字节密文
     * 
     * @param in
     * 		密文字节数组
     * @param offset
     * 		密文开始位置
     * @return
     * 		明文
     */
    private byte[] decipher(byte[] in, int offset) {
        // 迭代次数,16次
        int loop = 0x10;
        // 得到密文和密钥的各个部分,注意java没有无符号类型,所以为了表示一个无符号的整数
        // 我们用了long,这个long的前32位是全0的,我们通过这种方式模拟无符号整数,后面用到的long也都是一样的
        // 而且为了保证前32位为0,需要和0xFFFFFFFF做一下位与
        long y = Util.getUnsignedInt(in, offset, 4);
        long z = Util.getUnsignedInt(in, offset + 4, 4);
        long a = Util.getUnsignedInt(key, 0, 4);
        long b = Util.getUnsignedInt(key, 4, 4);
        long c = Util.getUnsignedInt(key, 8, 4);
        long d = Util.getUnsignedInt(key, 12, 4);
        // 算法的一些控制变量,sum在这里也有数了,这个sum和迭代次数有关系
        // 因为delta是这么多,所以sum如果是这么多的话,迭代的时候减减减,减16次,最后
        // 得到0。反正这就是为了得到和加密时相反顺序的控制变量,这样才能解密呀~~
        long sum = 0xE3779B90;
        sum &= 0xFFFFFFFFL;
        long delta = 0x9E3779B9;
        delta &= 0xFFFFFFFFL;

        // 迭代开始了, @_@
        while(loop-- > 0) {
            z -= ((y << 4) + c) ^ (y + sum) ^ ((y >>> 5) + d);
            z &= 0xFFFFFFFFL;
            y -= ((z << 4) + a) ^ (z + sum) ^ ((z >>> 5) + b);
            y &= 0xFFFFFFFFL;
            sum -= delta;
            sum &= 0xFFFFFFFFL;
        }

        baos.reset();
        writeInt((int)y);
        writeInt((int)z);
        return baos.toByteArray();
    }
    
    /**
     * 写入一个整型到输出流,高字节优先
     * 
     * @param t
     */
    private void writeInt(int t) {
        baos.write(t >>> 24);
        baos.write(t >>> 16);
        baos.write(t >>> 8);
        baos.write(t);
    }
    
    /**
     * 解密
     * 
     * @param in
     * 		密文
     * @return
     * 		明文
     */
    private byte[] decipher(byte[] in) {
        return decipher(in, 0);
    }
    
    /**
     * 加密8字节 
     */
    private void encrypt8Bytes() {
        // 这部分完成我上面所说的 plain ^ preCrypt,注意这里判断了是不是第一个8字节块,如果是的话,那个prePlain就当作preCrypt用
        for(pos = 0; pos < 8; pos++) {
            if(header) 
            	plain[pos] ^= prePlain[pos];
            else
            	plain[pos] ^= out[preCrypt + pos];
        }
        // 这个完成我上面说的 f(plain ^ preCrypt)
        byte[] crypted = encipher(plain);
        // 这个没什么,就是拷贝一下,java不像c,所以我只好这么干,c就不用这一步了
        System.arraycopy(crypted, 0, out, crypt, 8);
        
        // 这个完成了 f(plain ^ preCrypt) ^ prePlain,ok,下面拷贝一下就行了
        for(pos = 0; pos < 8; pos++)
            out[crypt + pos] ^= prePlain[pos];
        System.arraycopy(plain, 0, prePlain, 0, 8);
        
        // 完成了加密,现在是调整crypt,preCrypt等等东西的时候了
        preCrypt = crypt;
        crypt += 8;      
        pos = 0;
        header = false;            
    }

    /**
     * 解密8个字节
     * 
     * @param in
     * 		密文字节数组
     * @param offset
     * 		从何处开始解密
     * @param len
     * 		密文的长度
     * @return
     * 		true表示解密成功
     */
    private boolean decrypt8Bytes(byte[] in , int offset, int len) {
        // 这里第一步就是判断后面还有没有数据,没有就返回,如果有,就执行 crypt ^ prePlain
        for(pos = 0; pos < 8; pos++) {
            if(contextStart + pos >= len) 
                return true;
            prePlain[pos] ^= in[offset + crypt + pos];
        }
        
        // 好,这里执行到了 d(crypt ^ prePlain)
        prePlain = decipher(prePlain);
        if(prePlain == null)
        	return false;
        
        // 解密完成,最后一步好像没做? 
        // 这里最后一步放到decrypt里面去做了,因为解密的步骤有点不太一样
        // 调整这些变量的值先
        contextStart += 8;
        crypt += 8;
        pos = 0;
        return true;
    }
    
    /**
     * 这是个随机因子产生器,用来填充头部的,如果为了调试,可以用一个固定值
     * 随机因子可以使相同的明文每次加密出来的密文都不一样
     * 
     * @return
     * 		随机因子
     */
    private int rand() {
        return random.nextInt();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -