AZDG算法java实现
这个算法不知道什么时候出来的,discuz中用它来记录用户信息,存到客户端浏览器的cookie中,每次请求时,服务端解开它,得到用户信息,下面这段代码是java的实现,从网上搜到一些原始代码,改造了一下。
性能还可以,双核2G主频,8线程,可以稳定在13万tips以上,比从数据库、cache取数据要高效非常多。
明文、密码越长加密越慢,相同明文、密码,每次加密结果不同,解密结果相同。
不知道他的安全性怎样,discuz应该不会犯这种错误吧。如果可靠,用来解决“多服务器集群session共享问题”是个好办法,discuz就是用这种方法。
package com.huawei.core.common.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
public class AzDGCrypt {
/**
* 加密函数
* @param txt string 等待加密的原字串
* @param key string 私有密匙(用于解密和加密)
* @return string 经过私有密匙加密后的结果
*/
public final static String encrypt(String txt, String key){
//使用随机数发生器产生 0~32000 的值并 MD5()
String encryptKey = Utils.md5(int2Bytes((int)(Math.random() * 32000)));
int ctr = 0;
StringBuilder ciphertext = new StringBuilder();
int len = txt.length();
int ekLen = encryptKey.length();
for(int i = 0; i < len; i++) {
ctr = ctr == ekLen ? 0 : ctr; //如果ctr = encryptKey 的长度,则ctr清零
char a1 = encryptKey.charAt(ctr);
char t1 = txt.charAt(i);
char t2 = encryptKey.charAt(ctr++);
char a2 = (char)(t1 ^ t2);
ciphertext.append(a1).append(a2);
}
return Base64.encode((passport_key(ciphertext.toString(), key)).getBytes());
}
/**
* 解密函数
* @param string 加密后的字串
* @param string 私有密匙(用于解密和加密)
* @return string 字串经过私有密匙解密后的结果
* @throws Base64DecodingException
*/
public final static String decrypt(String ciphertext, String key) throws Base64DecodingException {
String txt = passport_key(new String(Base64.decode(ciphertext)), key);
int len = txt.length();
StringBuilder plaintext = new StringBuilder();
for (int i = 0; i < len; i++) {
//txt的第i位,与 txt的第i+1位取异或
plaintext.append((char)(txt.charAt(i) ^ txt.charAt(++i)));
}
return plaintext.toString();
}
/**
* Passport 密匙处理函数
* @param string 待加密或待解密的字串
* @param string 私有密匙(用于解密和加密)
* @return string 处理后的密匙
*/
private final static String passport_key(String txt, String key){
String encryptKey = Utils.md5(key);
int ctr = 0;
int len = txt.length();
int ekLen = encryptKey.length();
StringBuilder plaintext = new StringBuilder();
for(int i = 0; i < len; i++) {
ctr = ctr == ekLen ? 0 : ctr;
plaintext.append((char)(txt.charAt(i) ^ encryptKey.charAt(ctr++)));
}
return plaintext.toString();
}
private final static byte[] int2Bytes(int x) {
byte[] v = new byte[4];
for(int i = 0; i < 4; i++) { //小端序,因为不需要还原
v[i] = (byte)x;
x >>= 8;
}
return v;
}
public static void main(String[] args) throws Exception {
int threadNum = 8;
final int N = 1000000;
final CountDownLatch counter = new CountDownLatch(threadNum);
ExecutorService exectors = Executors.newFixedThreadPool(threadNum);
final String txt = "dddaa000000000000000aeee";
final String key = "ddd000000000000000000000";
long t1 = System.currentTimeMillis();
for(int j = 0; j < threadNum; j++) {
exectors.execute(new Runnable(){
public void run() {
String s;
System.out.println("start");
try {
for(int i = 0; i < N; i++) {
s = AzDGCrypt.encrypt(txt, key);
//System.out.println("txt:" + txt + " key:" + key + " txt after crypt:" + s);
s = AzDGCrypt.decrypt(s, key);
//System.out.println("txt:" + txt + " key:" + key + " txt after decrypt:" + s);
}
} catch(Exception e) {
e.printStackTrace();
}
counter.countDown();
System.out.println("end");
}
});
}
counter.await();
long t2 = System.currentTimeMillis();
System.out.println("speed=" + (1000 * (threadNum * N / (t2 - t1))));
System.exit(0);
}
}