JAVA-原创差异化加密---觉得还行您就看看,觉得不行也没关系

该加密方法主要为满足差异化要求,加密字符限定---字母数字下划线。

密文结果跟两个数据集挂钩,即a方生成的密文,a方解析无误,但b方解析结果存异。详见数据集上注释。

代码如下:


package util;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

/**
 * 加密(字符限定数字字母下划线[0-9a-zA-Z_])
 * @author pangjs ~ 2013-07-11 下午07:28:21
 */
public class Encryptor {
//	'~'只是占位,除'~'在首位占位外,数组内的字符顺序可任意调换,不能增加,共63个可用字符[0-9a-zA-Z_]
	private static final char[] universe = new char[]{
		'~','a','b','c','d','0','1','2','3','4','5','6','8','9','_','7','e','f','g','h','i','j',
		'k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F',
		'Z','Y','X','W','V','U','T','S','R','Q','P','O','N','M','L','K','J','I','H','G'};

	private static final Map<Character,Integer> universeMap = new HashMap<Character,Integer>(64, 1f);
	
//	用作输出,保证同数组内无重复即可,字符任意,顺序任意。	加几组减几组都没事,不用改代码
	private static final char[][] show = new char[][]{
            {'1','5','2','7','6','0','8','3','A','a'},
            {'2','e','f','a','K','w','3','D','n','6'},
            {'b','d','f','u','n','m','5','t','2','z'},
            {'w','t','Z','G','H','R','x','a','A','f'},
            {'@','#','$','%','&','+','w','V','B','2'}};

	//分隔符没有特殊要求,但是不能等同于密文显示字符 show[]中字符
	private static final char SEPERATE_KEY = '=';
//	private static final String START = "song";
//	private static final String END = ":-)";
	private static final String START = "";
	private static final String END = "";
	static{
		for(int i=0;i<universe.length;i++){
			universeMap.put(universe[i],i);
		}
	}
	private Encryptor(){}
	
	/**
	 * 加密方法
	 * @param source:需要加密的字符串 ,数字、字母或者下划线组成
	 * @return	密文
	 */
	public static String encrypt(final String source){
		if(source == null || source.trim().isEmpty() || !source.matches("^[a-zA-Z0-9_]+$")){
			throw new EncryptException("超出数字字母下划线范围了,我不行了...");
		}
		if(source.length()<11){
			return en1(en0(source,1));
		}
		String digit = "";
		char[] src = source.toCharArray();
		int length = src.length;
		for(int i = (length-1)/10; i>0; i--){
			String temp = en0(new String(src,length-i*10,10),1);
			char[] chr = new char[64];
			for(int j=0;j<7;j++){
				chr[j]='0';
			}
			System.arraycopy(temp.toCharArray(), 0, chr, 64-temp.length(), temp.length());
			digit += new String(chr,0,64);
		}
		digit = en0(new String(src, 0, length%10==0?10:length%10),0) + digit;
		return en1(digit);
		
	}
	
	private static String en1(String digit){
		digit = new BigInteger(digit, 2).toString(10);
		StringBuilder need = new StringBuilder(START+SEPERATE_KEY);
		int length = digit.length();
		for(int i = 0; i<length; i++){
			need.append(show[i%show.length][digit.charAt(i) - '0']);
		}
		need.append(SEPERATE_KEY+END);
		return need.toString();
	}
	
	private static String en0(final String source, final int mode){
		long result = 0L;
		int a = 0, temp, length = source.length();
		boolean isOver5 = false;
		for(int i = 0; i<length; i++){
			temp = universeMap.get(source.charAt(i));
			a = (temp<<(6*(isOver5?(i-5):i)))|a;
			if(i == 4){
				result = (long)a<<32;
				a = 0;
				isOver5 = true;
			}
		}
		result = isOver5 ? a|result : (long)a<<32*mode;
		int pos = 64;
		char[] buf = new char[pos];
		char[] bin = {'0', '1'};
		for( ;result!=0 ; result>>>=1){
			buf[--pos] = bin[(int)result&1];
		}
		return new String(buf, pos, 64-pos);
	}
	
//	public static void main(String[] args) throws Exception {
//		String s = "AadsabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_A";
//		System.out.println("原文: "+s);
//		String en = encrypt(s);
//		System.out.println("密文: "+en);
//		System.out.println("解密: "+decrypt(en));
//		System.out.println("解密=原文 ? "+decrypt(en).equals(s));
//	}
	
	/**
	 * 
	 * @param encoded
	 * @return
	 */
	public static String decrypt(String encoded){
		encoded=encoded.substring(encoded.indexOf(SEPERATE_KEY)+1, encoded.lastIndexOf(SEPERATE_KEY));
		StringBuilder need=new StringBuilder();
		int length = encoded.length();
		for(int i=0;i<length;i++){
			char temp=encoded.charAt(i);
			for(int j=0;j<10;j++){
				if(temp==show[i%show.length][j]){
					need.append(j);
					break;
				}
			}
		}
		encoded = new BigInteger(need.toString(),10).toString(2);
		length = encoded.length();
		if(length<65){
			return de0(new String(encoded));
		}
		String source = "";
		char[] src = encoded.toCharArray();
		for(int i = (length-1)/64; i>0; i--){
			source += de0(new String(src,length-i*64,64));
		}
		return source = de0(new String(src, 0, length%64)) + source;
	}
	
	private static String de0(final String encoded){
		long get=Long.parseLong(encoded,2);
		StringBuilder need=new StringBuilder();
		int curr;
		if((get<<32)==0){
			get=get>>32;
		}else{
			for(int i=0;i<5;i++){
				if((curr=(int)(get&0x3fL))==0){
					get=get>>(30-6*i);
					break;
				}else{
					need.append(universe[curr]);
				}
				get=get>>6;
			}
			get=get>>2;
		}
		for(int i=0;i<5;i++){
			if((curr=(int)(get&0x3fL))==0){
				break;
			}else{
				need.insert(i, universe[curr]);
			}
			get=get>>6;
		}
		return need.toString();
	}
	
	
}

class EncryptException extends RuntimeException{

	private static final long serialVersionUID = -9018864433826547470L;

	public EncryptException(String message) {
		super(message);
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值