JavaCompiler API使用JSch连接SSH遇加密初始化异常求助
JavaCompiler API中使用JSch连接SSH报SecurityException的解决思路
问题概述
普通Java程序通过JSch连接Unix SSH可正常运行,但使用JavaCompiler API动态编译并执行代码时,抛出java.lang.SecurityException: Can not initialize cryptographic mechanism,怀疑与JVM加密长度限制相关。
完整错误栈示例
java.lang.SecurityException: Can not initialize cryptographic mechanism at javax.crypto.JceSecurity.<clinit>(JceSecurity.java:129) at javax.crypto.KeyGenerator.getInstance(KeyGenerator.java:169) at com.jcraft.jsch.jce.AES256CTR.init(AES256CTR.java:49) at com.jcraft.jsch.Session.checkCipher(Session.java:2401) at com.jcraft.jsch.Session.checkCiphers(Session.java:2378) at com.jcraft.jsch.Session.send_kexinit(Session.java:626) at com.jcraft.jsch.Session.connect(Session.java:307) at your.package.YourSSHClass.connect(YourSSHClass.java:XX) ...
已尝试的操作
- 运行时调用
Security.setProperty("crypto.policy", "unlimited") - 修改JRE下的
java.security文件,添加crypto.policy=unlimited配置 - 在JRE的
lib/security目录替换/添加local_policy.jar和US_export_policy.jar
解决方案建议
1. 给JavaCompiler的子进程传递加密策略参数
JavaCompiler API编译或执行代码时会启动独立子进程,运行时动态设置的Security.setProperty不会传递给子进程,需要显式添加JVM参数:
// 编译阶段传递参数 List<String> compileOptions = new ArrayList<>(); // 传递加密策略参数给编译子进程 compileOptions.add("-J-Dcrypto.policy=unlimited"); // 添加JSch依赖到类路径 compileOptions.add("-classpath"); compileOptions.add("path/to/jsch.jar"); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // 执行编译 compiler.getTask(null, null, null, compileOptions, null, compilationUnits).call();
如果是通过ProcessBuilder执行编译后的class文件,同样需要添加参数:
ProcessBuilder pb = new ProcessBuilder("java", "-Dcrypto.policy=unlimited", "-cp", "path/to/jsch.jar:output-dir", "YourMainClass"); pb.start();
2. 确认JavaCompiler使用的JRE环境
JavaCompiler可能默认使用系统JRE而非你修改过策略的JRE,通过以下代码查看当前JavaCompiler关联的JRE路径:
System.out.println("JavaCompiler JRE path: " + System.getProperty("java.home"));
检查该路径下的lib/security目录,确保政策jar包和java.security配置已正确修改。
3. 提前在主进程启动时设置加密策略
运行主程序时直接添加JVM参数-Dcrypto.policy=unlimited,而非在代码中动态设置,因为Security.setProperty在JVM初始化后可能无法生效:
java -Dcrypto.policy=unlimited -cp your-main-jar.jar YourMainClass
4. 验证加密策略是否生效
在SSH连接代码前添加验证逻辑,确认加密策略已正确应用:
// 打印当前加密策略配置 System.out.println("Current crypto policy: " + Security.getProperty("crypto.policy")); // 检查AES最大密钥长度(unlimited策略下应为256) KeyGenerator aesGenerator = KeyGenerator.getInstance("AES"); System.out.println("Max AES key length: " + aesGenerator.getMaxKeyLength());
若输出的最大长度为128,说明加密策略未生效,需重新检查JVM参数或政策文件。
内容的提问来源于stack exchange,提问作者Sudhanshoo Sarage
相关产品推荐
相关产品推荐

