java-QQ加密算法

	public QQDataTransformer(String key) {
		this(key, "qq");
	}
	public QQDataTransformer(String key, String name) {
		super(key, name);
		// TODO Auto-generated constructor stub
	}
	@Override
	public 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);
		}
	}
	@Override
	public String encode(String data) throws TransformerException {
		return StringTools.getUTF8String(encode(StringTools.getUTF8Bytes(data)));
	}
	@Override
	public 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);
		}
	}
	@Override
	public 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;
			else
				end = 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();
	    }
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java国产加密算法主要包括SM2密码算法和SM3密码杂凑算法。 SM2密码算法是一种国产的非对称加密算法,用于数字签名和加密通信。它基于椭圆曲线密码学,具有高度安全性和效率。通过Java可以使用国密文档提供的实现,使用SM2算法进行加密、签名和验签操作。要使用SM2算法,可以引入Bouncy Castle库的依赖,该库提供了对SM2算法的支持。例如,可以在项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.68</version> </dependency> ``` 然后,可以使用Java代码来调用Bouncy Castle库提供的SM2算法实现,进行加密、签名和验签等操作。 SM3密码杂凑算法是一种国产的密码学哈希函数,常用于数据完整性校验和身份认证等场景。与传统的哈希算法相比,SM3具有更高的安全性和抗碰撞能力。在Java中,可以使用相应的库或者工具类来调用SM3算法,对数据进行杂凑计算。然而,由于没有给出具体的引用内容,我无法提供更加详细的使用说明。 因此,如果你需要在Java中使用国产加密算法,可以参考国密文档提供的实现方式,同时引入Bouncy Castle库的依赖来支持SM2算法的使用。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [国产加密SM3算法java实现长度64位](https://download.csdn.net/download/qq_27917221/11649513)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Java实现国产加密算法SM4(ECB和CBC两种模式)](https://blog.csdn.net/trustProcess/article/details/127865787)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值