web-dev-qa-db-fra.com

"Privatekey non valide" lors de l'utilisation de JSch

J'utilise le code suivant pour travailler avec Git dans une application Java. J'ai une clé valide (utilisez-la tout le temps), et ce code spécifique a déjà fonctionné pour moi avec le même référentiel de clés et git, mais maintenant je reçois l'exception suivante:

clé privée non valide: [B @ 59c40796.

A cette ligne:

jSch.addIdentity("<key_path>/private_key.pem");

Mon code complet:

    String remoteURL = "ssh://git@<git_repository>";
    TransportConfigCallback transportConfigCallback = new SshTransportConfigCallback();
    File gitFolder = new File(workingDirectory);
    if (gitFolder.exists()) FileUtils.delete(gitFolder, FileUtils.RECURSIVE);

    Git git = Git.cloneRepository()
            .setURI(remoteURL)
            .setTransportConfigCallback(transportConfigCallback)
            .setDirectory(new File(workingDirectory))
            .call();
}


private static class SshTransportConfigCallback implements TransportConfigCallback {
    private final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
        @Override
        protected void configure(OpenSshConfig.Host hc, Session session) {
            session.setConfig("StrictHostKeyChecking", "no");
        }

        @Override
        protected JSch createDefaultJSch(FS fs) throws JSchException {
            JSch jSch = super.createDefaultJSch(fs);
            jSch.addIdentity("<key_path>/private_key.pem");

            return jSch;
        }
    };

Après une recherche en ligne, j'ai modifié createDefaultJSch pour utiliser pemWriter:

@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
    JSch jSch = super.createDefaultJSch(fs);
    byte[] privateKeyPEM = null;

    try {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        List<String> lines = Files.readAllLines(Paths.get("<my_key>.pem"), StandardCharsets.US_ASCII);
        PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(String.join("", lines)));
        RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);

        PKCS8Generator pkcs8 = new PKCS8Generator(privKey);

        StringWriter writer = new StringWriter();
        PemWriter pemWriter = new PemWriter(writer);
        pemWriter.writeObject(pkcs8);

        privateKeyPEM = writer.toString().getBytes("US-ASCII");

    } catch (Exception e) {
        e.printStackTrace();
    }

    jSch.addIdentity("git", privateKeyPEM, null, null);

    return jSch;
}

Mais toujours avoir "invalidkey private" exception.

17
o_b7

Je suis également tombé sur cette question. en cours d'exécution Jgit sur mac, pour certains utilisateurs, nous avons constaté l'exception suivante:

org.Eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.Java:160)
    at org.Eclipse.jgit.transport.SshTransport.getSession(SshTransport.Java:137)
    at org.Eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.Java:274)
    at org.Eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.Java:169)
    at org.Eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.Java:136)
    at org.Eclipse.jgit.transport.FetchProcess.execute(FetchProcess.Java:122)
    at org.Eclipse.jgit.transport.Transport.fetch(Transport.Java:1236)
    at org.Eclipse.jgit.api.FetchCommand.call(FetchCommand.Java:234)
    ... 17 more
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@e4487af
    at com.jcraft.jsch.KeyPair.load(KeyPair.Java:664)
    at com.jcraft.jsch.KeyPair.load(KeyPair.Java:561)
    at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.Java:40)
    at com.jcraft.jsch.JSch.addIdentity(JSch.Java:407)
    at com.jcraft.jsch.JSch.addIdentity(JSch.Java:367)
    at org.Eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.Java:276)
    at org.Eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.Java:220)
    at org.Eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.Java:176)
    at org.Eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.Java:110)

La cause première a été découverte comme étant l’incompatibilité de clé privée ssh. L'exception ne s'est produite que pour les utilisateurs dont la clé est d'un type plus récent, ed25519, qui génère cet en-tête de clé:

-----BEGIN OPENSSH PRIVATE KEY-----

au lieu de genre RSA :

-----BEGIN RSA PRIVATE KEY-----

régénérer une clé RSA (ssh-keygen -t rsa), a fait disparaître l’exception.

Modifiez les commentaires suivants: Si vous utilisez OpenSSH 7.8 et versions ultérieures, vous devrez peut-être ajouter -m PEM à la commande de génération: ssh-keygen -t rsa -m PEM

21
Natan

Les versions récentes d'OpenSSH (7.8 et plus récent) génèrent des clés au format nouveau OpenSSH par défaut, qui commencent par:

-----BEGIN OPENSSH PRIVATE KEY-----

JSch ne supporte pas ce format de clé.


Vous pouvez utiliser ssh-keygen pour convertir la clé au format OpenSSH classique :

ssh-keygen -p -f file -m pem -P passphrase -N passphrase

(Si la clé n'est pas chiffrée avec une phrase secrète, utilisez "" au lieu de passphrase)


Si vous êtes sous Windows, vous pouvez utiliser PuTTYgen (à partir de package PuTTY ). Chargez la clé puis accédez à Conversions> Exporter la clé OpenSSH . Pour les clés RSA, il utilisera le format classique .


Si vous créez une nouvelle clé avec ssh-keygen, Ajoutez simplement -m PEM pour générer la nouvelle clé au format classique :

ssh-keygen -m PEM
13
Martin Prikryl
  1. Vous lisez un fichier nommé .pem Et de-base64 all et vous traitez le résultat comme étant non chiffré avec PKCS8, apparemment avec succès. Cela signifie que le fichier n'était PAS au format PEM. Le format PEM au minimum DOIT avoir les lignes dash-BEGIN et dash-END valides. Si elles ne sont pas supprimées, de-base64 échoue ou est erroné. (Certains Les formats PEM ont également des en-têtes de style 822 qui doivent être gérés.)

  2. Vous semblez utiliser BouncyCastle, mais dans mes versions, il n'y a pas de constructeur PKCS8Generator Qui ne prend que RSAPrivateKey. La chose la plus proche qui fonctionne est JcaPKCS8Generator (RSAPrivateKey implements PrivateKey, OutputEncryptor=null) (c'est-à-dire une classe différente mais liée et deux arguments pas un).

  3. PemWriter est mis en mémoire tampon et vous ne l'avez pas vidé avant de regarder le StringWriter sous-jacent. En conséquence, writer.toString().getBytes() est un tableau vide/de longueur nulle, que JSch considère à juste titre comme non valide.

Avec les numéros 2 et 3 corrigés et utilisant mon entrée, et appelant JSch directement au lieu de via JGit, cela fonctionne pour moi.

0