背景:在java代码中使用jasypt-1.9.3.jar中的StandardPBEStringEncryptor类的decrypt()方法对数据进行解密时报如下错误,但是win10环境下正常,linux环境下有问题
原代码如下:
private String decodeByJasypt(String algorithm, String pwd, String decryptStr) {
StandardPBEStringEncryptor stringEncryptor = new StandardPBEStringEncryptor();
/*选用的加密算法:配置文件中配置如下的算法*/
stringEncryptor.setAlgorithm(algorithm);
/*加密得盐值:配置文件中配置的solt*/
stringEncryptor.setPassword(pwd);
/*要解密的文本*/
String decrypt = decryptStr;
if (decryptStr.startsWith("ENC(")) {
decrypt = decrypt.replace("ENC(", "");
decrypt = decrypt.substring(0, decrypt.length() - 1);
}
decrypt = stringEncryptor.decrypt(decrypt);
logger.info("解密后的值为:{}",decrypt);
return decrypt;
}
报错信息如下:
2022-09-27 17:55:40.351 ERROR [] [] [] org.springframework.web.context.ContextLoader - Context initialization failed
org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWithMD5AndDES SecretKeyFactory not available
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:773)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:566)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:718)
at com.hand.hdmp.cux.utils.EncryptPropertyCfg.decodeByJasypt(EncryptPropertyCfg.java:120)
at com.hand.hdmp.cux.utils.EncryptPropertyCfg.convertProperty(EncryptPropertyCfg.java:65)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.convertProperties(PropertyResourceConfigurer.java:106)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:83)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:183)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4678)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5139)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1727)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:456)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:405)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
at java.security.AccessController.doPrivileged(Native Method)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.NoSuchAlgorithmException: PBEWithMD5AndDES SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:122)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:160)
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:761)
... 60 common frames omitted
解决过程
- 网上查阅资料,均说是因为jdk版本导致jdk路径下缺少了 sunjce_provider.jar包,详细可参考 网友解决方案
- 让项目同事在出问题环境执行如下代码,有如下输出,项目上采用的算法也被打印出来了
public class MyTest {
public static void main(String[] args) {
Set<String> ciphers = Security.getAlgorithms("Cipher");
for (String cipher : ciphers) {
//用于验证是否有相关算法
System.out.println(cipher);
}
}
}
备注: 后面还有很多没截全
- 贼心不死再次确认,发现jdk(路径:%Java_Home%/jre/lib/ext)下确实有sunjce_provider.jar、sunec.jar
- 人已经绝望,无奈…
最终解决方案
是的你没有看错,是因为空格,运维人员在property配置文件中配置解密算法时加入了空格,最终把空格删除就好了,浪费了我一天的时间,最终发现是这个原因引起的
总结
写代码时一定要考虑全面,你永远不知道别人会怎么用,在property配置文件中,空格本来就具有一定的意义,但是运维人员不熟悉这个,所以就导致了这个问题,后面最终对该配置项的代码的字符串进行了截取