欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java 整合Ucenter (authcode)函数的算法 博客分类: java 算法JavaJ#SecurityC++ 

程序员文章站 2024-02-20 21:16:16
...
自己用java整合ucenter,发现网上的都不能用。看看下php的authcode,照着写了下,发现怎么写都会有个bug,请高手搞一下。
---接口
package com.hq.encryptor;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.hq.encryptor.iface.PasswordEnDe;

/**
 * Ucenter论坛可逆加密算法
 * bug:解密后的字符串可能多一个或者2个字符。谁解决了请发我信箱supttkl@163.com
 * @author GAO
 * 
 */
public class UcenterPasswordEncryptor implements PasswordEnDe {
	// 密钥字符串
	private String ENCRYPTOR_KEY = "1234567890";
	private BASE64Decoder decoder = new BASE64Decoder();
	private BASE64Encoder encoder = new BASE64Encoder();

	public UcenterPasswordEncryptor() {

	}

	/**
	 * @param key 密钥
	 */
	public UcenterPasswordEncryptor(String key) {
		this.ENCRYPTOR_KEY = key;
	}

	// 加密
	public String encrypt(String password) {
		try {
			password=URLEncoder.encode(password, "UTF-8");//支持中文
			String key = ENCRYPTOR_KEY;
			int ckey_length = 4;
			key = getMd5String(key);
			String keya = getMd5String(key.substring(0, 16));
			String keyb = getMd5String(key.substring(16, 32));
			String min = String.valueOf(System.currentTimeMillis());
			min = "0.00000000 " + min.substring(0, min.length() - 3);
			String keyc = ckey_length > 0 ? getMd5String(String.valueOf(min))
					: "";
			keyc = keyc.substring(keyc.length() - 4, keyc.length());
			String cryptkey = keya + getMd5String(keya + keyc);
			int key_length = cryptkey.length();
			byte[] temp = null;
			String str_temp = "0000000000"
					+ getMd5String(password + keyb).substring(0, 16) + password;
			temp = str_temp.getBytes("UTF-8");
			int[] box = new int[256];
			for (int i = 0; i < box.length; i++) {
				box[i] = i;
			}

			char[] rndkey = new char[256];
			for (int i = 0; i <= 255; i++) {
				rndkey[i] = cryptkey.charAt(i % key_length);
			}

			for (int j = 0, i = 0; i < 256; i++) {
				j = (j + box[i] + (int) rndkey[i]) % 256;
				int tmp = box[i];
				box[i] = box[j];
				box[j] = tmp;
			}
			for (int a = 0, j = 0, i = 0; i < temp.length; i++) {
				a = (a + 1) % 256;
				j = (j + box[a]) % 256;
				int tmp = box[a];
				box[a] = box[j];
				box[j] = tmp;
				int gao = (int) temp[i];
				byte c = (byte) (gao ^ (box[(box[a] + box[j]) % 256]));
				temp[i] = c;
			}
			ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
			ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(
					temp);
			encoder.encode(((InputStream) (bytearrayinputstream)),
					((OutputStream) (bytearrayoutputstream)));
			String s = bytearrayoutputstream.toString();
			return keyc + s.replace("=", "");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private String getMd5String(String password)
			throws NoSuchAlgorithmException {
		MessageDigest md = MessageDigest.getInstance("MD5");
		byte[] input = md.digest(password.getBytes());
		String hex = byteToHexString(input);
		return hex;
	}

	private String byteToHexString(byte[] res) {
		StringBuffer sb = new StringBuffer(res.length << 1);
		for (int i = 0; i < res.length; i++) {
			String digit = Integer.toHexString(0xFF & res[i]);
			if (digit.length() == 1) {
				digit = '0' + digit;
			}
			sb.append(digit);
		}
		return sb.toString();
	}
	//
	public boolean matches(String passwordToCheck, String storedPassword) {
		  if(storedPassword == null) {
	            throw new NullPointerException("storedPassword can not be null");
	        }
	        if(passwordToCheck == null) {
	            throw new NullPointerException("passwordToCheck can not be null");
	        }
	        
	        return encrypt(passwordToCheck).equals(storedPassword);
	}

	// 解密
	public String decrypt(String password) {
		try {
			
			int ckey_length = 4;
			String key = getMd5String(ENCRYPTOR_KEY);
			String keya = getMd5String(key.substring(0, 16));
			String min = String.valueOf(System.currentTimeMillis());
			min = "0.00000000 " + min.substring(0, min.length() - 3);
			
			String keyc = ckey_length > 0 ? password.substring(0, ckey_length)
					: "";
			String cryptkey = keya + getMd5String(keya + keyc);
			int key_length = cryptkey.length();
			byte[] temp = null;
			if(true){//这步为出bug的地方
				String t1 = password.substring(ckey_length, password.length());
		        ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(t1.getBytes("UTF-8"));
		        ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
		        decoder.decodeBuffer(((InputStream) (bytearrayinputstream)), ((OutputStream) (bytearrayoutputstream)));
		        temp=bytearrayoutputstream.toByteArray();
			}
	        
			int[] box=new int[256];
			for (int i = 0; i <box.length; i++) {
				box[i] = i;
			}
			
			char[] rndkey = new char[256];
			for (int i = 0; i <= 255; i++) {
				rndkey[i] = cryptkey.charAt(i % key_length);
			}

			for (int j = 0, i = 0; i < 256; i++) {
				j = (j + box[i] + (int) rndkey[i]) % 256;
				int tmp = box[i];
				box[i] = box[j];
				box[j] = tmp;
			}
			StringBuffer sb = new StringBuffer();
			for(int a =0, j=0, i = 0; i < temp.length; i++) {
				a = (a + 1) % 256;
				j = (j + box[a]) % 256;
				int tmp = box[a];
				box[a] = box[j];
				box[j] = tmp;
				int gao=(int)temp[i]<0? (int)temp[i]+256:(int)temp[i];
				char c =(char)(gao ^ (box[(box[a] + box[j]) % 256]));
				sb.append(c);
			}  
			String lastStr= sb.substring(26, sb.length());
			return URLDecoder.decode(lastStr, "UTF-8");
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

}