Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
367 views
in Technique[技术] by (71.8m points)

ssh - Java: InvalidAlgorithmParameterException Prime size must be multiple of 64

I implemented a Java program that will connect and execute a command in a remote server using JSCH. The problem is that whenever I tried to connect to the server, I got the following exception:

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)

I tried the solution of adding the Bouncy Castle provider in jre/lib and security.provider and it works. But I need to make it project dependent, so I tried to add Bouncy Castle in my build path and add manually the Bouncy Castle provider in my program. But after exporting it to jar, I am still receiving the exception.

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();
    }
}
}

Here is my Server utilities that handles server connection:

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;
    }
}
}

While debugging, I find out that the error occurs when the printer service tries to connect to the server.

    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.pr

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I didn't have the benefit of switching to Ganymed, so I installed the "Bouncy Castle" libraries to replace the security on the JVM. For some reason the Java 8 JVM still does not allow for security keys to be larger than 1024 in length.

  1. Download the jar files from https://www.bouncycastle.org/latest_releases.html (look for jar files that start with 'bcprov-jdk')

  2. Place the jar files under $JAVA_HOME/jre/lib/ext

  3. Edit the java.security file located in $JAVA_HOME/jre/lib/security
  4. Scroll down past the middle of the file and you will find a numbered list of security providers (around 9 or 8). Place a comment for the line of the seecond provider (with a #)
  5. Replace the commented line with this:

    security.provider.2=org.bouncycastle.jce.provider.BouncyCastleProvider

  6. Restart what you must, and try again.

I'm baffled as to why we need to hack the JDK this way. It doesn't inspire a lot of confidence to anybody I mentioned it at work. But since there is poor documentation (or education) on anything relating to security we are treating it as a 'temporary' fix.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...