web-dev-qa-db-fra.com

Java: InvalidAlgorithmParameterException La taille principale doit être multiple de 64

J'ai implémenté un programme Java qui connectera et exécutera une commande sur un serveur distant utilisant JSCH. Le problème est que chaque fois que j'essayais de me connecter au serveur, j'avais l'exception suivante:

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)

J'ai essayé la solution de l'ajout du fournisseur Bouncy Castle dans jre/lib et security.provider et cela fonctionne. Mais je dois le rendre dépendant du projet. J'ai donc essayé d'ajouter Bouncy Castle dans mon chemin de génération et d'ajouter manuellement le fournisseur Bouncy Castle dans mon programme. Mais après l'avoir exporté dans un bocal, je reçois toujours l'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();
    }
}
}

Voici mes utilitaires de serveur qui gère la connexion au serveur:

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

Lors du débogage, je découvre que l'erreur se produit lorsque le service d'imprimante tente de se connecter au serveur.

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

J'aimerais également savoir s'il existe un moyen de rendre Bouncy Castle léger, car j'ai besoin que mon bocal soit <2 Mo, car je dois le transférer sur un serveur et je ne dispose pas de l'autorisation nécessaire pour transférer un fichier. > 2MB.

Merci pour l'aide. Ceci est mon premier article dans stackoverflow, et j'aime beaucoup cette communauté. Merci.

4
Vaanz

J'ai essayé d'utiliser une clé 2048 bits que je génère sur un serveur, mais je reçois toujours ces erreurs. La solution que j'ai trouvée consiste à utiliser une bibliothèque SSH différente et celle qui fonctionne est Ganymed SSH-2, au lieu de JSch. Merci pour toutes les suggestions et commentaires.

Édité: De plus, cette bibliothèque est légère ~ 1Mo.

1
Vaanz

Je n'avais pas l'avantage de passer à Ganymed, alors j'ai installé les bibliothèques "Bouncy Castle" pour remplacer la sécurité sur la JVM. Pour une raison quelconque, la machine virtuelle Java Java 8 ne permet toujours pas que les clés de sécurité aient une longueur supérieure à 1024.

  1. Téléchargez les fichiers jar à partir de https://www.bouncycastle.org/latest_releases.html (recherchez les fichiers jar commençant par 'bcprov-jdk')

  2. Placez les fichiers jar sous $ Java_HOME/jre/lib/ext

  3. Editez le fichier Java.security situé dans $ Java_HOME/jre/lib/security
  4. Faites défiler la liste vers le bas et vous trouverez une liste numérotée de fournisseurs de sécurité (environ 9 ou 8). Placez un commentaire pour la ligne du deuxième fournisseur (avec un #)
  5. Remplacez la ligne commentée par ceci:

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

  6. Redémarrez ce que vous devez et essayez à nouveau.

Je ne comprends pas pourquoi nous devons pirater le JDK de cette façon. Cela n'inspire pas beaucoup de confiance à ceux que j'ai mentionnés au travail. Mais comme il existe peu de documentation (ou d’éducation) sur tout ce qui concerne la sécurité, nous le traitons comme une solution «temporaire».

4
Salvador Valencia

J'ai résolu un problème similaire sur Oracle Java 8 en basculant vers le fournisseur Bouncycastle pour SSL/TL:

  1. Bouncycastle a été ajouté à mon projet

    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.54</version>
    </dependency>
    
  2. Avant de faire quelque chose avec SSL, j'ajoute le fournisseur BouncyCastle en tant que 1er fournisseur à la liste:

    Security.insertProviderAt(new BouncyCastleProvider(),1);
    

Cela fonctionne avec la plupart des logiciels qui utilisent SSLSocketFactory de Sun. Cela peut donc également fonctionner avec JSch.

2
Michael Wyraz

Je recevais cette erreur

ERREUR: Message du serveur distant: Session.connect: Java.security.InvalidAlgorithmParameterException: la taille principale doit être multiple de 64 et ne peut être comprise que entre 512 et 1024

J'ai pu le résoudre en définissant la version du client comme dans cette ligne

session.setClientVersion("SSH-2.0-OpenSSH_2.5.3");

La valeur par défaut à l'origine de l'erreur est

session.setClientVersion("SSH-2.0-JSCH-0.1.54");
0
jamjabi

Moi aussi j'ai fait face au même problème et je l'ai résolu en dégradant le fichier jar de jsch-1.5.4 à jsch-1.5.0. Essayez de changer le fichier jsch jar et voyez quelle version convient à votre code. La cause première du problème est due à une méthode dans la mise à niveau du fichier jsch jar, qui attend un paramètre d'entrée supplémentaire et qui manque dans votre code.

0
Prathyush

Ma solution de contournement consistait à modifier cette clé de registre pour autoriser les clés DH 1024 bits dans Windows 10 (la taille minimale était de 2048 bits par 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
0
Beau Harder