java - 使用 JSch 时为 "Invalid privatekey"

标签 java ssh jsch

我正在使用以下代码在 Java 应用程序中使用 Git。 我有一个有效的 key (一直使用它),这个特定的代码之前使用相同的 key 和 git 存储库对我有用,但现在我得到以下异常:

invalid privatekey: [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;
}

但仍然“无效私钥”异常。

最佳答案

最新版本的 OpenSSH(7.8 和更新版本)默认以 OpenSSH 格式生成 key ,其开头为:

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

JSch 不支持这种 key 格式。


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

ssh-keygen -p -f <privateKeyFile> -m pem -P passphrase -N passphrase

这种“虐待”-p (更改密码)命令。它将覆盖 -f 标识的私钥文件带有经典 OpenSSH 格式 (pem) 的新私钥的选项。您可以将当前密码保留为新密码。如果 key 未使用密码加密,请使用 ""而不是 passphrase .之后,您可以使用 ssh-keygen -y -e -f <privateKeyFile> >temp.pub比较公钥并验证现有公钥是否适用于新格式的私钥。

对于 Windows 用户:请注意 ssh-keygen.exe现在内置于 Windows 10/11 中。并且可以是downloaded from Microsoft Win32-OpenSSH project适用于旧版本的 Windows。


在 Windows 上,您还可以使用 PuTTYgen(来自 PuTTY package):

  • 启动 PuTTYgen
  • 加载 key
  • 转到转换 > 导出 OpenSSH key
    对于 RSA key ,它将使用经典格式。

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

ssh-keygen -m PEM

实际上,原始的 JSch 似乎不再被积极维护。特别是,如果您要开始新项目,它可能不是最好的开始库。如今,JSch 存在许多兼容性问题。对于一些重要的,请参阅:

相反,您可以考虑使用这个 JSch 分支:
https://github.com/mwiede/jsch

除其他外,它确实支持新的 OpenSSH key 格式。

关于java - 使用 JSch 时为 "Invalid privatekey",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53134212/

相关文章:

java - JSch/Java - 检测断开连接的服务器的正确方法

java - 我怎样才能使 JSch 中的 session 持续更长时间?

sftp - Jsch 错误 - 发送 channel 请求失败

java - 如果建议没有方法,Intellij 可以显示警告吗?

java - java中将json字符串反序列化为string对象

javascript - 如何在javascript数组中添加Java对象?

postgresql - 无法连接到 VM (Ubuntu) 中的 postgreSQL : Access to database denied

java - 使用另一个类中的 jbutton 调用带有绘制和线程的 main 方法

shell - 我可以自动进行ssh连接吗? ssh user@server.company.com

python - 如何使用 Python 的 Paramiko 模块 ssh 进入需要两个密码身份验证的服务器?