«Недействительный приватный ключ» при использовании JSch - PullRequest
0 голосов
/ 03 ноября 2018

Я использую следующий код для работы с Git в приложении Java. У меня есть действительный ключ (используйте его постоянно), и этот конкретный код раньше работал для меня с тем же ключом и git-репозиторием, но теперь я получаю следующее исключение:

неверный приватный ключ: [B@59c40796.

В этой строке:

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

Мой полный код:

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

После поиска в Интернете я изменил createDefaultJSch на использование 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;
}

Но все равно получаю «недействительный приватный ключ» исключение.

Ответы [ 3 ]

0 голосов
/ 14 декабря 2018

Я тоже наткнулся на эту проблему. работает Jgit на mac , для некоторых пользователей мы видели следующее исключение:

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)

Основной причиной было обнаружено несоответствие закрытого ключа ssh. Исключение произошло только для пользователей с ключом более нового типа ed25519 , который выводит этот заголовок ключа:

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

вместо вида RSA :

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

регенерация ключа RSA (ssh-keygen -t rsa), исключение исключено.

Редактировать следующие комментарии: Если у вас OpenSSH 7.8 и выше, вам может понадобиться добавить -m PEM к команде генерации: ssh-keygen -t rsa -m PEM

0 голосов
/ 18 апреля 2019

Последние версии OpenSSH (7.8 и новее) генерируют ключи в новом формате OpenSSH по умолчанию, который начинается с:

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

JSch не поддерживает этот формат ключей.


Вы можете использовать ssh-keygen для преобразования ключа в классический формат OpenSSH:

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

(если ключ не зашифрован парольной фразой, используйте "" вместо passphrase)


Если вы работаете в Windows, вы можете использовать PuTTYgen (из пакет PuTTY ). Загрузите ключ и перейдите к Преобразования> Экспортировать ключ OpenSSH . Для ключей RSA будет использоваться формат classic .


Если вы создаете новый ключ с ssh-keygen, просто добавьте -m PEM, чтобы сгенерировать новый ключ в формате classic :

ssh-keygen -m PEM
0 голосов
/ 06 ноября 2018
  1. Вы прочитали файл с именем .pem и de-base64 all и обработали результат как незашифрованный PKCS8, по-видимому, успешно. Это означает, что файл НЕ был PEM-форматом. Формат PEM как минимум ДОЛЖЕН иметь действительные строки dash-BEGIN и dash-END, которые, если не удалены, приводят к тому, что de-base64 либо не работает, либо ошибается. ( Некоторые форматы PEM также имеют заголовки в стиле 822, которые должны обрабатываться.)

  2. Вы, похоже, используете BouncyCastle, но в моих версиях нет конструктора PKCS8Generator, который бы занимал только RSAPrivateKey. Самое близкое, что работает, это JcaPKCS8Generator (RSAPrivateKey implements PrivateKey, OutputEncryptor=null) (то есть другой, но связанный класс и два аргумента, а не один).

  3. PemWriter буферизован, и вы не сбросили его, прежде чем посмотреть на базовый StringWriter. В результате writer.toString().getBytes() является пустым массивом нулевой длины, который JSch справедливо считает недействительным.

С исправленными # 2 и # 3 и использованием моего ввода и вызовом JSch напрямую, а не через JGit, это работает для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...