这两天程序做压力测试,发现了一个问题,在用jdk提供的des加密时,当访问量过大时,加解密时突然报错
java.lang.IllegalStateException: Cipher not initialized
at javax.crypto.Cipher.c(DashoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at com.changda.encrypt.DESEngine.encrypt(DESEngine.java:67)
at com.changda.encrypt.DESEngine.encrypt(DESEngine.java:106)
at com.changda.clientapi.BaseCall.creatKey(BaseCall.java:220)
at com.changda.util.SendXNMRequest.sendRequest(SendXNMRequest.java:50)
at com.changda.business.service.AccountServiceImpl.login(AccountServiceImpl.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy1.login(Unknown Source)
at com.changda.struts.action.LoginAction.execute(LoginAction.java:71)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at com.changda.util.ParseConfigfile.doFilter(ParseConfigfile.java:18)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at com.mas.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:122)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:595)
看错误是Cipher未初始化,可代码中肯定初始化了,怀疑是jdk本身没来得及初始化,原程序中的做法是,每次解加解密,都创建一个Cipher对象,现改为,有几个密钥就创建几个静态的Cipher对象,放在hashmap中,问题解决。
修改后的java des加密 程序如下:
import java.security.*;
import java.util.HashMap;
import javax.crypto.*;
public class DESEngine {
private static HashMap encryptCipherMap=new HashMap();
private static HashMap decryptCipherMap=new HashMap();
public static String byteArr2HexStr(byte[] arrB) throws Exception {
int iLen = arrB.length;
StringBuffer sb = new StringBuffer(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
while (intTmp < 0) {
intTmp = intTmp + 256;
}
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
}
public byte[] hexStr2ByteArr(String strIn) throws Exception {
byte[] arrB = strIn.getBytes();
int iLen = arrB.length;
byte[] arrOut = new byte[iLen / 2];
for (int i = 0; i < iLen; i = i + 2) {
String strTmp = new String(arrB, i, 2);
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
}
return arrOut;
}
private static DESEngine single = new DESEngine();
private DESEngine() {
}
public static DESEngine getInstance() {
return single;
}
private void init(String strKey)throws Exception{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(strKey.getBytes());
if(encryptCipherMap.get(strKey)==null){
Cipher encryptCipher = Cipher.getInstance("DES/ECB/NoPadding","SunJCE");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
encryptCipherMap.put(strKey, encryptCipher);
}
if(decryptCipherMap.get(key)==null){
Cipher decryptCipher = Cipher.getInstance("DES/ECB/NoPadding","SunJCE");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
decryptCipherMap.put(strKey, decryptCipher);
}
}
public byte[] encrypt(byte[] arrB,String key) throws Exception {
return ((Cipher)encryptCipherMap.get(key)).doFinal(arrB);
}
public byte[] decrypt(byte[] arrB,String key) throws Exception {
return ((Cipher)decryptCipherMap.get(key)).doFinal(arrB);
}
private Key getKey(byte[] arrBTmp) throws Exception {
byte[] arrB = new byte[8];
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
arrB[i] = arrBTmp[i];
}
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
return key;
}
public String encrypt(String key,String strIn) throws Exception {
this.init(key);
byte[] inb = strIn.getBytes();
int length = inb.length;
int mod = length % 8;
if (mod != 0) {
mod = 8 - mod;
}
byte[] newin = new byte[length + mod];
for (int u = 0; u < length; u++) {
newin[u] = inb[u];
}
//给存储明文的字节数组a的不足位补0
for (int u = length; u < newin.length; u++) {
newin[u] = 0;
}
return byteArr2HexStr(encrypt(newin,key));
}
public String decrypt(String key,String strIn) throws Exception {
this.init(key);
return new String(decrypt(hexStr2ByteArr(strIn),key));
}
}