使用JGit和JSCH时无效的privateKey

o_b*_*_b7 25 java ssh jsch

我正在使用以下代码在Java应用程序中使用Git.我有一个有效的密钥(一直使用它),这个特定的代码以前使用相同的密钥和git存储库,但现在我得到以下异常:无效的私钥:[B @ 59c40796.

jSch.addIdentity("<key_path>/private_key.pem");
Run Code Online (Sandbox Code Playgroud)

在线搜索后,我将createDefaultJSch更改为使用pemWriter:

    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;
        }
    };
Run Code Online (Sandbox Code Playgroud)

但仍然得到无效的privateKey异常.

Nat*_*tan 30

我也偶然发现了这个问题.在mac上运行Jgit,对于一些用户,我们看到了以下异常:

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)
Run Code Online (Sandbox Code Playgroud)

发现根本原因是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

  • 如果你想通过`ssh-keygen`生成一组新的私有/公共RSA密钥并且有[OpenSSH 7.8及以上版本](https://www.openssh.com/releasenotes.html),你可能需要添加` - m PEM`到生成命令,否则某些框架如`JSch`可能会认为私钥是无效的,因为它从这里提到的预告片开始. (9认同)
  • 此外,如果通过“IdentityFile”指令将任何非 RSA 和/或非 PEM 文件添加到列表中,JSch 似乎会读取“~/ssh/config”并失败。 (4认同)

Mar*_*ryl 24

OpenSSH的最新版本(7.8及更高版本)默认情况下会以新的 OpenSSH格式生成密钥,其开头为:

-----BEGIN OPENSSH PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

JSch不支持此密钥格式。


您可以使用ssh-keygen将密钥转换为经典的 OpenSSH格式:

ssh-keygen -p -f file -m pem -P passphrase -N passphrase
Run Code Online (Sandbox Code Playgroud)

(如果密钥未使用密码加密,请使用""代替passphrase


如果您使用的是Windows,则可以使用PuTTYgen(来自PuTTY软件包)。加载密钥,然后转到“ 转换”>“导出OpenSSH密钥”。对于RSA密钥,它将使用经典格式。


如果您要使用创建新密钥ssh-keygen,只需添加-m PEM以生成经典格式的新密钥:

ssh-keygen -m PEM
Run Code Online (Sandbox Code Playgroud)

  • 额外的荣誉指出如何转换现有密钥而不是仅仅生成新密钥 (13认同)

Ste*_*ola 8

回复很晚了,但想留下如何面对这个问题的轨迹。

正如许多人在他们的答案中已经提到的那样,重点实际上是生成密钥和选项-m PEM解析的方式。

但是,如果像我一样,您无法重新生成密钥,因为公共部分已经安装在多个服务器中,您仍然可以将私钥转换为合适的格式。

为此,只需发出以下命令:

ssh-keygen -p -m pem -f id_rsa
Run Code Online (Sandbox Code Playgroud)

它将要求输入新的密码。如果需要,您可以使用参数-P(旧密码)和-N(新密码)立即提供它们。

  • 确实如此,但这就是我上面的答案已经说过的。 (3认同)

Mat*_*ann 8

除了将OPENSSH密钥格式转换为原始 JSch 支持的格式之外,您还可以切换到 JSch 的一个分支,您可以在https://github.com/mwiede/jsch找到它

您只需要将 JSch Maven 坐标替换为com.github.mwiede:jsch:0.1.61.

该分支确实支持OPENSSH密钥格式和更多算法,这在未来可能会变得很重要,因为 OpenSSH 服务器会将允许的算法集限制为最安全的算法。