java-QQ加密算法

来源:互联网 发布:c 冒泡排序算法 编辑:程序博客网 时间:2024/05/18 03:13
public QQDataTransformer(String key) {this(key, "qq");}public QQDataTransformer(String key, String name) {super(key, name);// TODO Auto-generated constructor stub}@Overridepublic byte[] encode(byte[] data) throws TransformerException {MessageDigest md5;try {md5 = MessageDigest.getInstance("MD5");byte[] keyBytes = md5.digest(StringTools.getUTF8Bytes(this.key));swapBytes(keyBytes);reverseBits(keyBytes);byte[] enc = new QQCrypter().encrypt(data, keyBytes);enc = Base64.encode(enc);return enc;} catch (NoSuchAlgorithmException e) {throw new TransformerException(e);} catch (CodecException e) {throw new TransformerException(e);}}@Overridepublic String encode(String data) throws TransformerException {return StringTools.getUTF8String(encode(StringTools.getUTF8Bytes(data)));}@Overridepublic byte[] decode(byte[] data) throws TransformerException {MessageDigest md5;try {md5 = MessageDigest.getInstance("MD5");byte[] keyBytes = md5.digest(StringTools.getUTF8Bytes(key));swapBytes(keyBytes);reverseBits(keyBytes);byte[] dec = Base64.decode(data);byte[] rtn = new QQCrypter().decrypt(dec, keyBytes);return rtn;} catch (NoSuchAlgorithmException e) {throw new TransformerException(e);} catch (CodecException e) {throw new TransformerException(e);}}@Overridepublic String decode(String data) throws TransformerException {return StringTools.getUTF8String(decode(StringTools.getUTF8Bytes(data)));}private static void swapBytes(byte[] b) {for (int i = 0; i < b.length; i += 2) {byte tmp = b[i];b[i] = b[i + 1];b[i + 1] = tmp;}}private static void reverseBits(byte[] b) {for (int i = 0; i < b.length; i++)b[i] ^= 0xFF;}static class QQCrypter {    private byte[] plain;    private byte[] prePlain;    private byte[] out;    private int crypt, preCrypt;    private int pos;    private int padding;    private byte[] key;    private boolean header = true;    private int contextStart;    private static Random random = new Random();private ByteArrayOutputStream baos;public QQCrypter() {baos = new ByteArrayOutputStream(8);}private static long getUnsignedInt(byte[] in, int offset, int len) {long ret = 0;int end = 0;if (len > 8)end = offset + 8;elseend = offset + len;for (int i = offset; i < end; i++) {ret <<= 8;ret |= in[i] & 0xff;}return (ret & 0xffffffffl) | (ret >>> 32);}    public byte[] decrypt(byte[] in, int offset, int len, byte[] k) {    if(k == null)    return null;            crypt = preCrypt = 0;        this.key = k;                byte[] m = new byte[offset + 8];                if((len % 8 != 0) || (len < 16)) return null;        prePlain = decipher(in, offset);        pos = prePlain[0] & 0x7;        int count = len - pos - 10;        if(count < 0) return null;                for(int i = offset; i < m.length; i++)            m[i] = 0;        out = new byte[count];        preCrypt = 0;        crypt = 8;        contextStart = 8;        pos++;                padding = 1;        while(padding <= 2) {            if(pos < 8) {                pos++;                padding++;            }            if(pos == 8) {                m = in;                if(!decrypt8Bytes(in, offset, len)) return null;            }        }                int i = 0;        while(count != 0) {            if(pos < 8) {                out[i] = (byte)(m[offset + preCrypt + pos] ^ prePlain[pos]);                i++;                count--;                pos++;            }            if(pos == 8) {                m = in;                preCrypt = crypt - 8;                if(!decrypt8Bytes(in, offset, len))                     return null;            }        }        for(padding = 1; padding < 8; padding++) {            if(pos < 8) {                if((m[offset + preCrypt + pos] ^ prePlain[pos]) != 0)                    return null;                pos++;            }            if(pos == 8) {                m = in;                preCrypt = crypt;                if(!decrypt8Bytes(in, offset, len))                     return null;            }        }        return out;    }    public byte[] decrypt(byte[] in, byte[] k) {           return decrypt(in, 0, in.length, k);    }    public byte[] encrypt(byte[] in, int offset, int len, byte[] k) {    if(k == null)    return in;            plain = new byte[8];        prePlain = new byte[8];        pos = 1;                   padding = 0;         crypt = preCrypt = 0;        this.key = k;        header = true;                pos = (len + 0x0A) % 8;        if(pos != 0)            pos = 8 - pos;        out = new byte[len + pos + 10];        plain[0] = (byte)((rand() & 0xF8) | pos);                for(int i = 1; i <= pos; i++)            plain[i] = (byte)(rand() & 0xFF);        pos++;        for(int i = 0; i < 8; i++)            prePlain[i] = 0x0;                padding = 1;        while(padding <= 2) {            if(pos < 8) {                plain[pos++] = (byte)(rand() & 0xFF);                padding++;            }            if(pos == 8)                encrypt8Bytes();        }                int i = offset;        while(len > 0) {            if(pos < 8) {                plain[pos++] = in[i++];                len--;            }            if(pos == 8)                encrypt8Bytes();        }                padding = 1;        while(padding <= 7) {            if(pos < 8) {                plain[pos++] = 0x0;                padding++;            }            if(pos == 8)                encrypt8Bytes();        }                return out;    }    public byte[] encrypt(byte[] in, byte[] k) {        return encrypt(in, 0, in.length, k);    }    private byte[] encipher(byte[] in) {        int loop = 0x10;        long y = getUnsignedInt(in, 0, 4);        long z = getUnsignedInt(in, 4, 4);        long a = getUnsignedInt(key, 0, 4);        long b = getUnsignedInt(key, 4, 4);        long c = getUnsignedInt(key, 8, 4);        long d = getUnsignedInt(key, 12, 4);                long sum = 0;        long delta = 0x9E3779B9;        delta &= 0xFFFFFFFFL;        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;        }        baos.reset();        writeInt((int)y);        writeInt((int)z);        return baos.toByteArray();    }        private byte[] decipher(byte[] in, int offset) {        int loop = 0x10;        long y = getUnsignedInt(in, offset, 4);        long z = getUnsignedInt(in, offset + 4, 4);        long a = getUnsignedInt(key, 0, 4);        long b = getUnsignedInt(key, 4, 4);        long c = getUnsignedInt(key, 8, 4);        long d = getUnsignedInt(key, 12, 4);        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();    }        private void writeInt(int t) {        baos.write(t >>> 24);        baos.write(t >>> 16);        baos.write(t >>> 8);        baos.write(t);    }    private byte[] decipher(byte[] in) {        return decipher(in, 0);    }    private void encrypt8Bytes() {    for(pos = 0; pos < 8; pos++) {            if(header)             plain[pos] ^= prePlain[pos];            else            plain[pos] ^= out[preCrypt + pos];        }        byte[] crypted = encipher(plain);        System.arraycopy(crypted, 0, out, crypt, 8);                for(pos = 0; pos < 8; pos++)            out[crypt + pos] ^= prePlain[pos];        System.arraycopy(plain, 0, prePlain, 0, 8);                preCrypt = crypt;        crypt += 8;              pos = 0;        header = false;                }        private boolean decrypt8Bytes(byte[] in , int offset, int len) {        for(pos = 0; pos < 8; pos++) {            if(contextStart + pos >= len)                 return true;            prePlain[pos] ^= in[offset + crypt + pos];        }                prePlain = decipher(prePlain);        if(prePlain == null)        return false;        contextStart += 8;        crypt += 8;        pos = 0;        return true;    }        private int rand() {        return random.nextInt();    }}

原创粉丝点击