Java: InvalidAlgorithmParameterException 质数大小必须是 64 的倍数
Java: InvalidAlgorithmParameterException Prime size must be multiple of 64
我实现了一个 Java 程序,它将使用 JSCH 连接到远程服务器并在其中执行命令。问题是每当我尝试连接到服务器时,都会出现以下异常:
com.jcraft.jsch.JSchException: Session.connect: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 256 to 2048 (inclusive)
我尝试了在 jre/lib 和 security.provider 中添加 Bouncy Castle 提供程序的解决方案,它有效。但是我需要让它依赖于项目,所以我尝试在我的构建路径中添加 Bouncy Castle 并在我的程序中手动添加 Bouncy Castle 提供程序。但是导出到jar后还是报异常
package services;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.Security;
import java.util.Iterator;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class MainService {
public MainService() {
Security.addProvider(new BouncyCastleProvider()); //Adding BouncyCastlePRovider in security
// TODO Auto-generated constructor stub
String report = "";
StringBuilder sb = new StringBuilder();
System.out.println("Running the monitoring...");
System.out.println("Starting printer monitoring...");
PrinterService ps = new PrinterService(); //A service that connects to the server and executes the commands
System.out.println("Building report for printer");
sb.append(ps.buildReport());
System.out.println("Done building report for printer");
System.out.println("Finish printer Monitoring...");
report = sb.toString();
writeToFile(report,"fai");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MainService msrv = new MainService();
}
public void writeToFile(String contents,String report_name){
try {
System.out.println("Writing to file...");
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(report_name+".html",false)));
pw.println(contents);
pw.close();
System.out.println("Done writing...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
这是我处理服务器连接的服务器实用程序:
package utilities;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Properties;
import javax.swing.JOptionPane;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import entity.Server;
public class ServerUtil {
public ServerUtil() {
// TODO Auto-generated constructor stub
}
public static Session createSession(Server srv){
JSch js = new JSch();
try {
Session s = js.getSession(srv.getUser().getUsername(), srv.getAddress(), 22);
s.setPassword(srv.getUser().getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications", "password");
s.setConfig(config);
s.connect();
return s;
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static ArrayList<String> executeCommands(Session s, String commands){
ArrayList<String> result = new ArrayList<String>();
try {
System.out.println("Creating channel...");
ChannelExec channel = (ChannelExec) s.openChannel("exec");
System.out.println("Channel created.");
System.out.println("Setting commands...");
channel.setCommand(commands);
System.out.println("Commands set.");
System.out.println("Connecting to channel...");
channel.connect();
System.out.println("Channel connected.");
System.out.println("Retrieving output...");
BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
String line;
while((line = reader.readLine()) != null){
result.add(line);
}
System.out.println("Output retrieved.");
channel.disconnect();
System.out.println("Returning result...");
return result;
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return result;
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return result;
}
}
}
在调试时,我发现错误发生在打印机服务尝试连接到服务器时。
package services;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;
import com.jcraft.jsch.Session;
import entity.Server;
import utilities.DatabaseUtil;
import utilities.ServerUtil;
public class PrinterService {
private ArrayList<String> server_names;
private ArrayList<ArrayList<String>> result_server;
public PrinterService() {
// TODO Auto-generated constructor stub
executePrinterMonitoring();
}
//Connect to the printer server and process printer monitoring
public void executePrinterMonitoring(){
Iterator<Server> it_s = DatabaseUtil.getServers("PRINTER").iterator();
server_names = new ArrayList<String>();
result_server = new ArrayList<ArrayList<String>>();
while(it_s.hasNext()){
Server svr = it_s.next();
System.out.println("***********START PRINTER SERVER***********");
String commands = "lpstat -t | sed '/READY/d'; lpstat -W | sed '/READY/d'";
Session connect = ServerUtil.createSession(svr);
StringTokenizer tokenize = new StringTokenizer(commands, ";");
ArrayList<String> res;
ArrayList<ArrayList<String>> res2 = new ArrayList<ArrayList<String>>();
System.out.println("Executing commands...");
while(tokenize.hasMoreTokens()){
String comm = tokenize.nextToken().trim();
res = ServerUtil.executeCommands(connect, comm);
res2.add(res);
}
System.out.println("Done executing commands...");
System.out.println("Processing results...");
processPMonitoring(res2,svr.getName());
connect.disconnect();
System.out.println("***********END PRINTER SERVER***********");
}
}
//Get the current date, date - 1, and date - 2
public String getDate(Calendar cal){
String mon;
String dy;
String dy2;
String dy3;
String yr;
int month = cal.get(Calendar.MONTH)+1;
int day = cal.get(Calendar.DATE);
int year = cal.get(Calendar.YEAR);
if(month < 10)
mon = "0"+month;
else
mon = ""+month;
if(day < 10){
dy = "0"+day;
}
else{
dy = ""+day;
}
yr = (year+"").substring(2, 4);
String date = mon+ "/"+dy+"/"+yr;
return date;
}
//Split and process the result from the server.
public void processPMonitoring(ArrayList<ArrayList<String>> s,String servername){
Iterator<String> res1 = s.get(0).iterator();
Iterator<String> res2 = s.get(1).iterator();
ArrayList<String> as = new ArrayList<String>();
ArrayList<String> fres = new ArrayList<String>();
Calendar cal = Calendar.getInstance();
String date1 = getDate(cal);
cal.add(Calendar.DATE, -1);
String date2 = getDate(cal);
cal.add(Calendar.DATE, -1);
String date3 = getDate(cal);
int header = 1;
System.out.println("Checking server:"+servername);
System.out.println("Getting queued results...");
while(res1.hasNext()){
if(header <= 3){
//as.add(res1.next());
header++;
}
else{
String curr = res1.next();
if(curr.contains("@")){
if(curr.contains("STDIN")){
String f4 = "";
String f5 = "";
if(res1.hasNext())
f4 = res1.next();
if(res1.hasNext())
f5 = res1.next();
if(f4.contains(date1)){
as.add(curr);
}
else if(f4.contains(date2)){
as.add(curr);
}
else if(f4.contains(date3)){
as.add(curr);
}
}
}
else{
String f1 = curr;
String f2 = "";
String f3 = "";
if(res1.hasNext())
f2 = res1.next();
if(res1.hasNext())
f3 = res1.next();
if(f2.contains(date1)){
as.add(f1);
}
else if(f2.contains(date2)){
as.add(f1);
}
else if(f2.contains(date3)){
as.add(f1 + " - 3 DAYS OLD!");
}
}
}
}
System.out.println("Done queued results...");
Iterator<String> g = as.iterator();
boolean flag = true;
String cl = "";
String std = "";
header = 1;
System.out.println("Processing queued results...");
while(res2.hasNext() && g.hasNext()){
if(header <=2){
fres.add(res2.next());
header++;
}
else{
String curr = res2.next();
if(curr.contains("@")){
fres.add(curr);
continue;
}
if(flag){
cl = g.next();
if(cl.contains("@") && cl.contains("STDIN")){
continue;
}
int first_st = cl.indexOf("STDIN");
int last_ind = 0;
for(last_ind = first_st+1;;last_ind++){
//System.out.println("Value of CL:"+cl);
//System.out.println("Checking for spaces");
//System.out.println("STD CURRENT CHAR:"+cl.charAt(last_ind));
if(cl.charAt(last_ind) == ' '){
break;
}
}
std = cl.substring(first_st, last_ind);
flag = false;
if(fres.get(fres.size()-1).contains(std)){
flag = true;
continue;
}
}
if(curr.contains(std)){
fres.add(curr);
flag = true;
}
}
}
System.out.println("Done processing queued results...");
System.out.println("Post-process queued results...");
int size = fres.size();
boolean down = false;
for(int i=0;i<size;i++){
if(fres.get(i).contains("@") && fres.get(i).contains("DOWN")){
down = true;
fres.remove(i);
i--;
size--;
continue;
}
if(down){
if(fres.get(i).contains("@") && !fres.get(i).contains("DOWN")){
down = false;
continue;
}
fres.remove(i);
i--;
size--;
}
}
System.out.println("Done post-processing queued results...");
//Post-process
server_names.add(servername);
result_server.add(fres);
//fres.add(0,servername);
//writeToFile(fres,3);
}
public String buildReport(){
String report = "";
StringBuilder sb = new StringBuilder();
Timestamp ts = new Timestamp(new Date().getTime());
sb.append("<table style=\"border:1px solid black; text-align:center;\" rules=\"all\">");
sb.append("<h1 style=\"margin:0px 0px 0px 50px\">Printer Monitoring as of "+ts.toString()+"</h1>");
sb.append("<tr style=\"background-color: seagreen\">"
+ "<th style=\"padding: 6px\">SERVER</th>"
+ "<th style=\"padding: 6px\">QUEUE</th>"
+ "<th style=\"padding: 6px\">DEV</th>"
+ "<th style=\"padding: 6px\">STATUS</th>"
+ "<th style=\"padding: 6px\">JOB FILES</th>"
+ "<th style=\"padding: 6px\">USER</th>"
+ "<th style=\"padding: 6px\">PP</th>"
+ "<th style=\"padding: 6px\">%</th>"
+ "<th style=\"padding: 6px\">BLKS</th>"
+ "<th style=\"padding: 6px\">CP</th>"
+ "<th style=\"padding: 6px\">RNK</th>"
+ "</tr>");
int counter = 0;
Iterator<String> it_s = server_names.iterator();
while(it_s.hasNext()){
sb.append("<tr style=\"background-color: green\"><td style=\"padding: 6px\"><b>"+it_s.next().toUpperCase()+"</b></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
Iterator<String> it_res = result_server.get(counter).iterator();
if(result_server.get(counter).isEmpty()){
sb.append("<tr><td></td><td style=\"padding: 6px\"><h5>CLEAN</h5></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
}
else if(result_server.get(counter).size() == 2){
sb.append("<tr><td></td><td style=\"padding: 6px\"><h5>CLEAN</h5></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
}
else{
while(it_res.hasNext()){
String res = it_res.next();
if(!res.contains("Dev") && !res.contains("----")){
StringTokenizer tok = new StringTokenizer(res," ");
sb.append("<tr>");
if(tok.countTokens() == 11){
sb.append("<td style=\"padding: 6px\"></td>");
for(int x=0;x<10;x++){
if(x == 3){
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+" "+tok.nextToken()+"</td>");
}
else{
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
}
}
}
else{
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+" "+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
}
sb.append("</tr>");
}
}
}
counter++;
}
sb.append("</table>");
sb.append("</br></br>");
report = sb.toString();
return report;
}
}
我还想知道是否有办法让 Bouncy Castle 更轻,因为我需要我的 jar < 2MB 因为我需要将它传输到服务器,而我没有允许传输大于 2MB 的文件。
感谢您的帮助。这是我在 Whosebug 中的第一个 post,我真的很喜欢这个社区。谢谢。
我尝试使用我在服务器中生成的 2048 位密钥,但我仍然收到这些错误。我找到的解决方案是使用不同的 SSH 库,有效的是 Ganymed SSH-2,而不是 JSch。感谢您的所有建议和意见。
已编辑:此外,这个库也很轻~1MB。
我通过切换到 ssl/tls 的 bouncycastle 提供程序解决了 oracle java 8 上的类似问题:
已将 bouncycastle 添加到我的项目中
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
在执行任何 SSL 操作之前,我将 BouncyCastle 提供程序作为第一个提供程序添加到列表中:
Security.insertProviderAt(new BouncyCastleProvider(),1);
这适用于大多数使用 sun 的 SSLSocketFactory 的东西,因此它也可能适用于 JSch。
我没有切换到 Ganymed 的好处,所以我安装了 "Bouncy Castle" 库来替换 JVM 上的安全性。出于某种原因,Java 8 JVM 仍然不允许安全密钥的长度超过 1024。
从 https://www.bouncycastle.org/latest_releases.html 下载 jar 文件(查找以 'bcprov-jdk' 开头的 jar 文件)
将 jar 文件放在 $JAVA_HOME/jre/lib/ext
下
- 编辑位于 $JAVA_HOME/jre/lib/security
的 java.security 文件
- 向下滚动到文件的中间部分,您会发现安全提供商的编号列表(大约 9 或 8)。为第二个提供者的行添加注释(带#)
将注释行替换为:
security.provider.2=org.bouncycastle.jce.provider.BouncyCastleProvider
必须重新启动,然后重试。
我很困惑为什么我们需要这样破解 JDK。它并没有激发我在工作中提到它的任何人的信心。但是由于与安全相关的任何内容的文档(或教育)都很差,我们将其视为 'temporary' 修复。
我遇到了这个错误
ERROR: Message form the remote server : Session.connect: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
我可以通过设置客户端版本来解决这个问题
session.setClientVersion("SSH-2.0-OpenSSH_2.5.3");
导致错误的默认值是
session.setClientVersion("SSH-2.0-JSCH-0.1.54");
我也遇到了同样的问题,并通过将 jar 文件从 jsch-1.5.4 降级到 jsch-1.5.0 来解决它。尝试更改 jsch jar 文件并查看哪个版本适合您的代码。问题的根本原因是由于 jsch jar 文件升级中的某些方法,需要额外的输入参数,而您的代码中缺少它。
我的解决方法是更改此注册表项以允许 Windows10 中的 1024 位 DH 密钥(2048 was/is 每个 https://docs.microsoft.com/en-us/security-updates/securityadvisories/2016/3174644 的最小位大小)
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ServerMinKeyBitLength"=dword:00000400
在您拥有 Session 实例之后添加这行代码:
public static Session createSession(Server srv){
JSch js = new JSch();
try {
Session s = js.getSession(srv.getUser().getUsername(), srv.getAddress(), 22);
s.setPassword(srv.getUser().getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications", "password");
config.put("kex", "diffie-hellman-group1-sha1");
s.setConfig(config);
...
要添加的行是:config.put("kex","diffie-hellman-group1-sha1");
我在 JGit 使用 JSch 时遇到了同样的错误。我在这个线程中尝试了很多建议都无济于事。
但是最近,我注意到如果我使用的 jre 比以前使用的稍微新一点,错误就会消失。
郑重声明,我使用的是 "jsch-0.1.55.jar",我试过的两个 jre 是:
- JRE 1.7.0_80(遇到异常)
- JRE 1.8.0_191(解决了问题)
我不能确定是 JRE 升级解决了问题,还是我另外进行了此线程的建议调整。
都一样,只是想分享经验,以防对其他人有帮助。
我对这个问题的解决方案是在我的主要方法的第一行添加以下内容:
public static void main(String[] args) {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
...
}
如果您使用的是 Spring,您可以添加:
@Configuration
public class AppConfig {
@PostConstruct
public void init(){
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
}
我实现了一个 Java 程序,它将使用 JSCH 连接到远程服务器并在其中执行命令。问题是每当我尝试连接到服务器时,都会出现以下异常:
com.jcraft.jsch.JSchException: Session.connect: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 256 to 2048 (inclusive)
我尝试了在 jre/lib 和 security.provider 中添加 Bouncy Castle 提供程序的解决方案,它有效。但是我需要让它依赖于项目,所以我尝试在我的构建路径中添加 Bouncy Castle 并在我的程序中手动添加 Bouncy Castle 提供程序。但是导出到jar后还是报异常
package services;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.Security;
import java.util.Iterator;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class MainService {
public MainService() {
Security.addProvider(new BouncyCastleProvider()); //Adding BouncyCastlePRovider in security
// TODO Auto-generated constructor stub
String report = "";
StringBuilder sb = new StringBuilder();
System.out.println("Running the monitoring...");
System.out.println("Starting printer monitoring...");
PrinterService ps = new PrinterService(); //A service that connects to the server and executes the commands
System.out.println("Building report for printer");
sb.append(ps.buildReport());
System.out.println("Done building report for printer");
System.out.println("Finish printer Monitoring...");
report = sb.toString();
writeToFile(report,"fai");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MainService msrv = new MainService();
}
public void writeToFile(String contents,String report_name){
try {
System.out.println("Writing to file...");
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(report_name+".html",false)));
pw.println(contents);
pw.close();
System.out.println("Done writing...");
} catch (IOException e) {
e.printStackTrace();
}
}
}
这是我处理服务器连接的服务器实用程序:
package utilities;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Properties;
import javax.swing.JOptionPane;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import entity.Server;
public class ServerUtil {
public ServerUtil() {
// TODO Auto-generated constructor stub
}
public static Session createSession(Server srv){
JSch js = new JSch();
try {
Session s = js.getSession(srv.getUser().getUsername(), srv.getAddress(), 22);
s.setPassword(srv.getUser().getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications", "password");
s.setConfig(config);
s.connect();
return s;
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static ArrayList<String> executeCommands(Session s, String commands){
ArrayList<String> result = new ArrayList<String>();
try {
System.out.println("Creating channel...");
ChannelExec channel = (ChannelExec) s.openChannel("exec");
System.out.println("Channel created.");
System.out.println("Setting commands...");
channel.setCommand(commands);
System.out.println("Commands set.");
System.out.println("Connecting to channel...");
channel.connect();
System.out.println("Channel connected.");
System.out.println("Retrieving output...");
BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
String line;
while((line = reader.readLine()) != null){
result.add(line);
}
System.out.println("Output retrieved.");
channel.disconnect();
System.out.println("Returning result...");
return result;
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return result;
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return result;
}
}
}
在调试时,我发现错误发生在打印机服务尝试连接到服务器时。
package services;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;
import com.jcraft.jsch.Session;
import entity.Server;
import utilities.DatabaseUtil;
import utilities.ServerUtil;
public class PrinterService {
private ArrayList<String> server_names;
private ArrayList<ArrayList<String>> result_server;
public PrinterService() {
// TODO Auto-generated constructor stub
executePrinterMonitoring();
}
//Connect to the printer server and process printer monitoring
public void executePrinterMonitoring(){
Iterator<Server> it_s = DatabaseUtil.getServers("PRINTER").iterator();
server_names = new ArrayList<String>();
result_server = new ArrayList<ArrayList<String>>();
while(it_s.hasNext()){
Server svr = it_s.next();
System.out.println("***********START PRINTER SERVER***********");
String commands = "lpstat -t | sed '/READY/d'; lpstat -W | sed '/READY/d'";
Session connect = ServerUtil.createSession(svr);
StringTokenizer tokenize = new StringTokenizer(commands, ";");
ArrayList<String> res;
ArrayList<ArrayList<String>> res2 = new ArrayList<ArrayList<String>>();
System.out.println("Executing commands...");
while(tokenize.hasMoreTokens()){
String comm = tokenize.nextToken().trim();
res = ServerUtil.executeCommands(connect, comm);
res2.add(res);
}
System.out.println("Done executing commands...");
System.out.println("Processing results...");
processPMonitoring(res2,svr.getName());
connect.disconnect();
System.out.println("***********END PRINTER SERVER***********");
}
}
//Get the current date, date - 1, and date - 2
public String getDate(Calendar cal){
String mon;
String dy;
String dy2;
String dy3;
String yr;
int month = cal.get(Calendar.MONTH)+1;
int day = cal.get(Calendar.DATE);
int year = cal.get(Calendar.YEAR);
if(month < 10)
mon = "0"+month;
else
mon = ""+month;
if(day < 10){
dy = "0"+day;
}
else{
dy = ""+day;
}
yr = (year+"").substring(2, 4);
String date = mon+ "/"+dy+"/"+yr;
return date;
}
//Split and process the result from the server.
public void processPMonitoring(ArrayList<ArrayList<String>> s,String servername){
Iterator<String> res1 = s.get(0).iterator();
Iterator<String> res2 = s.get(1).iterator();
ArrayList<String> as = new ArrayList<String>();
ArrayList<String> fres = new ArrayList<String>();
Calendar cal = Calendar.getInstance();
String date1 = getDate(cal);
cal.add(Calendar.DATE, -1);
String date2 = getDate(cal);
cal.add(Calendar.DATE, -1);
String date3 = getDate(cal);
int header = 1;
System.out.println("Checking server:"+servername);
System.out.println("Getting queued results...");
while(res1.hasNext()){
if(header <= 3){
//as.add(res1.next());
header++;
}
else{
String curr = res1.next();
if(curr.contains("@")){
if(curr.contains("STDIN")){
String f4 = "";
String f5 = "";
if(res1.hasNext())
f4 = res1.next();
if(res1.hasNext())
f5 = res1.next();
if(f4.contains(date1)){
as.add(curr);
}
else if(f4.contains(date2)){
as.add(curr);
}
else if(f4.contains(date3)){
as.add(curr);
}
}
}
else{
String f1 = curr;
String f2 = "";
String f3 = "";
if(res1.hasNext())
f2 = res1.next();
if(res1.hasNext())
f3 = res1.next();
if(f2.contains(date1)){
as.add(f1);
}
else if(f2.contains(date2)){
as.add(f1);
}
else if(f2.contains(date3)){
as.add(f1 + " - 3 DAYS OLD!");
}
}
}
}
System.out.println("Done queued results...");
Iterator<String> g = as.iterator();
boolean flag = true;
String cl = "";
String std = "";
header = 1;
System.out.println("Processing queued results...");
while(res2.hasNext() && g.hasNext()){
if(header <=2){
fres.add(res2.next());
header++;
}
else{
String curr = res2.next();
if(curr.contains("@")){
fres.add(curr);
continue;
}
if(flag){
cl = g.next();
if(cl.contains("@") && cl.contains("STDIN")){
continue;
}
int first_st = cl.indexOf("STDIN");
int last_ind = 0;
for(last_ind = first_st+1;;last_ind++){
//System.out.println("Value of CL:"+cl);
//System.out.println("Checking for spaces");
//System.out.println("STD CURRENT CHAR:"+cl.charAt(last_ind));
if(cl.charAt(last_ind) == ' '){
break;
}
}
std = cl.substring(first_st, last_ind);
flag = false;
if(fres.get(fres.size()-1).contains(std)){
flag = true;
continue;
}
}
if(curr.contains(std)){
fres.add(curr);
flag = true;
}
}
}
System.out.println("Done processing queued results...");
System.out.println("Post-process queued results...");
int size = fres.size();
boolean down = false;
for(int i=0;i<size;i++){
if(fres.get(i).contains("@") && fres.get(i).contains("DOWN")){
down = true;
fres.remove(i);
i--;
size--;
continue;
}
if(down){
if(fres.get(i).contains("@") && !fres.get(i).contains("DOWN")){
down = false;
continue;
}
fres.remove(i);
i--;
size--;
}
}
System.out.println("Done post-processing queued results...");
//Post-process
server_names.add(servername);
result_server.add(fres);
//fres.add(0,servername);
//writeToFile(fres,3);
}
public String buildReport(){
String report = "";
StringBuilder sb = new StringBuilder();
Timestamp ts = new Timestamp(new Date().getTime());
sb.append("<table style=\"border:1px solid black; text-align:center;\" rules=\"all\">");
sb.append("<h1 style=\"margin:0px 0px 0px 50px\">Printer Monitoring as of "+ts.toString()+"</h1>");
sb.append("<tr style=\"background-color: seagreen\">"
+ "<th style=\"padding: 6px\">SERVER</th>"
+ "<th style=\"padding: 6px\">QUEUE</th>"
+ "<th style=\"padding: 6px\">DEV</th>"
+ "<th style=\"padding: 6px\">STATUS</th>"
+ "<th style=\"padding: 6px\">JOB FILES</th>"
+ "<th style=\"padding: 6px\">USER</th>"
+ "<th style=\"padding: 6px\">PP</th>"
+ "<th style=\"padding: 6px\">%</th>"
+ "<th style=\"padding: 6px\">BLKS</th>"
+ "<th style=\"padding: 6px\">CP</th>"
+ "<th style=\"padding: 6px\">RNK</th>"
+ "</tr>");
int counter = 0;
Iterator<String> it_s = server_names.iterator();
while(it_s.hasNext()){
sb.append("<tr style=\"background-color: green\"><td style=\"padding: 6px\"><b>"+it_s.next().toUpperCase()+"</b></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
Iterator<String> it_res = result_server.get(counter).iterator();
if(result_server.get(counter).isEmpty()){
sb.append("<tr><td></td><td style=\"padding: 6px\"><h5>CLEAN</h5></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
}
else if(result_server.get(counter).size() == 2){
sb.append("<tr><td></td><td style=\"padding: 6px\"><h5>CLEAN</h5></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>");
}
else{
while(it_res.hasNext()){
String res = it_res.next();
if(!res.contains("Dev") && !res.contains("----")){
StringTokenizer tok = new StringTokenizer(res," ");
sb.append("<tr>");
if(tok.countTokens() == 11){
sb.append("<td style=\"padding: 6px\"></td>");
for(int x=0;x<10;x++){
if(x == 3){
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+" "+tok.nextToken()+"</td>");
}
else{
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
}
}
}
else{
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+" "+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\"></td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
sb.append("<td style=\"padding: 6px\">"+tok.nextToken()+"</td>");
}
sb.append("</tr>");
}
}
}
counter++;
}
sb.append("</table>");
sb.append("</br></br>");
report = sb.toString();
return report;
}
}
我还想知道是否有办法让 Bouncy Castle 更轻,因为我需要我的 jar < 2MB 因为我需要将它传输到服务器,而我没有允许传输大于 2MB 的文件。
感谢您的帮助。这是我在 Whosebug 中的第一个 post,我真的很喜欢这个社区。谢谢。
我尝试使用我在服务器中生成的 2048 位密钥,但我仍然收到这些错误。我找到的解决方案是使用不同的 SSH 库,有效的是 Ganymed SSH-2,而不是 JSch。感谢您的所有建议和意见。
已编辑:此外,这个库也很轻~1MB。
我通过切换到 ssl/tls 的 bouncycastle 提供程序解决了 oracle java 8 上的类似问题:
已将 bouncycastle 添加到我的项目中
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.54</version> </dependency>
在执行任何 SSL 操作之前,我将 BouncyCastle 提供程序作为第一个提供程序添加到列表中:
Security.insertProviderAt(new BouncyCastleProvider(),1);
这适用于大多数使用 sun 的 SSLSocketFactory 的东西,因此它也可能适用于 JSch。
我没有切换到 Ganymed 的好处,所以我安装了 "Bouncy Castle" 库来替换 JVM 上的安全性。出于某种原因,Java 8 JVM 仍然不允许安全密钥的长度超过 1024。
从 https://www.bouncycastle.org/latest_releases.html 下载 jar 文件(查找以 'bcprov-jdk' 开头的 jar 文件)
将 jar 文件放在 $JAVA_HOME/jre/lib/ext
下
- 编辑位于 $JAVA_HOME/jre/lib/security 的 java.security 文件
- 向下滚动到文件的中间部分,您会发现安全提供商的编号列表(大约 9 或 8)。为第二个提供者的行添加注释(带#)
将注释行替换为:
security.provider.2=org.bouncycastle.jce.provider.BouncyCastleProvider
必须重新启动,然后重试。
我很困惑为什么我们需要这样破解 JDK。它并没有激发我在工作中提到它的任何人的信心。但是由于与安全相关的任何内容的文档(或教育)都很差,我们将其视为 'temporary' 修复。
我遇到了这个错误
ERROR: Message form the remote server : Session.connect: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
我可以通过设置客户端版本来解决这个问题
session.setClientVersion("SSH-2.0-OpenSSH_2.5.3");
导致错误的默认值是
session.setClientVersion("SSH-2.0-JSCH-0.1.54");
我也遇到了同样的问题,并通过将 jar 文件从 jsch-1.5.4 降级到 jsch-1.5.0 来解决它。尝试更改 jsch jar 文件并查看哪个版本适合您的代码。问题的根本原因是由于 jsch jar 文件升级中的某些方法,需要额外的输入参数,而您的代码中缺少它。
我的解决方法是更改此注册表项以允许 Windows10 中的 1024 位 DH 密钥(2048 was/is 每个 https://docs.microsoft.com/en-us/security-updates/securityadvisories/2016/3174644 的最小位大小)
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ServerMinKeyBitLength"=dword:00000400
在您拥有 Session 实例之后添加这行代码:
public static Session createSession(Server srv){
JSch js = new JSch();
try {
Session s = js.getSession(srv.getUser().getUsername(), srv.getAddress(), 22);
s.setPassword(srv.getUser().getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
config.put("PreferredAuthentications", "password");
config.put("kex", "diffie-hellman-group1-sha1");
s.setConfig(config);
...
要添加的行是:config.put("kex","diffie-hellman-group1-sha1");
我在 JGit 使用 JSch 时遇到了同样的错误。我在这个线程中尝试了很多建议都无济于事。
但是最近,我注意到如果我使用的 jre 比以前使用的稍微新一点,错误就会消失。
郑重声明,我使用的是 "jsch-0.1.55.jar",我试过的两个 jre 是:
- JRE 1.7.0_80(遇到异常)
- JRE 1.8.0_191(解决了问题)
我不能确定是 JRE 升级解决了问题,还是我另外进行了此线程的建议调整。
都一样,只是想分享经验,以防对其他人有帮助。
我对这个问题的解决方案是在我的主要方法的第一行添加以下内容:
public static void main(String[] args) {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
...
}
如果您使用的是 Spring,您可以添加:
@Configuration
public class AppConfig {
@PostConstruct
public void init(){
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
}