You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java将SSH2私钥转换为RSA格式以适配JSch库?

解决JSch不支持SSH2格式私钥的自动转换问题

我之前也碰到过一模一样的问题!JSch确实只认OpenSSH格式的私钥,而Tectia生成的SSH2格式(带---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----头)根本没法直接用。手动用PuttyGen转换太麻烦,要在Java里自动搞定这个事,我们可以借助BouncyCastle库来解析SSH2密钥,再转成JSch能识别的OpenSSH RSA格式。

步骤1:添加依赖

首先得引入BouncyCastle的相关包,Maven项目可以直接加这段依赖:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

步骤2:编写转换代码

核心逻辑很清晰:读取SSH2密钥文件 → 用BouncyCastle解析(处理加密密码)→ 转成OpenSSH格式字符串 → 直接给JSch用或者存成文件。

下面是完整的可运行代码:

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.StringReader;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;

public class SSH2ToOpenSSHConverter {

    static {
        // 注册BouncyCastle安全提供者
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    /**
     * 将SSH2加密私钥转换为OpenSSH RSA格式私钥字符串
     * @param ssh2KeyPath SSH2私钥文件路径
     * @param passphrase 密钥密码(无密码传null)
     * @return OpenSSH格式的私钥字符串
     * @throws Exception 转换过程中的异常
     */
    public static String convertSSH2ToOpenSSH(String ssh2KeyPath, String passphrase) throws Exception {
        // 读取SSH2密钥文件内容
        StringBuilder ssh2KeyContent = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader(ssh2KeyPath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                ssh2KeyContent.append(line).append("\n");
            }
        }

        // 解析SSH2密钥
        PEMParser pemParser = new PEMParser(new StringReader(ssh2KeyContent.toString()));
        Object obj = pemParser.readObject();
        pemParser.close();

        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        KeyPair keyPair;

        if (obj instanceof PEMEncryptedKeyPair) {
            // 处理加密的密钥
            PEMEncryptedKeyPair encryptedKeyPair = (PEMEncryptedKeyPair) obj;
            PEMDecryptorProvider decryptorProvider = new JcePEMDecryptorProviderBuilder()
                    .build(passphrase.toCharArray());
            keyPair = converter.getKeyPair(encryptedKeyPair.decryptKeyPair(decryptorProvider));
        } else {
            // 处理未加密的密钥
            PEMKeyPair pemKeyPair = (PEMKeyPair) obj;
            keyPair = converter.getKeyPair(pemKeyPair);
        }

        // 将私钥转换为OpenSSH格式
        PrivateKey privateKey = keyPair.getPrivate();
        PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance(privateKey.getEncoded());
        byte[] openSSHKeyBytes = org.bouncycastle.openssl.jcajce.JcaPEMWriter.writeObject(privateKeyInfo);
        
        // 替换头尾部,适配JSch的RSA格式要求
        String openSSHKey = new String(openSSHKeyBytes)
                .replace("-----BEGIN PRIVATE KEY-----", "-----BEGIN RSA PRIVATE KEY-----")
                .replace("-----END PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----");

        return openSSHKey;
    }

    // 测试示例
    public static void main(String[] args) throws Exception {
        String ssh2KeyPath = "/path/to/your/tectia_ssh2_key";
        String passphrase = "your_key_password"; // 无密码则传null
        String openSSHKey = convertSSH2ToOpenSSH(ssh2KeyPath, passphrase);
        
        // 直接把转换后的密钥交给JSch使用
        com.jcraft.jsch.JSch jsch = new com.jcraft.jsch.JSch();
        jsch.addIdentity("converted_rsa_key", openSSHKey.getBytes(), null, passphrase != null ? passphrase.getBytes() : null);
        
        // 后续的SFTP连接逻辑...
    }
}

关键细节说明

  • BouncyCastle的作用:它是唯一能直接解析SSH2格式PEM密钥的Java库,不管密钥是加密还是明文的都能处理。
  • 格式适配:BouncyCastle默认生成的是PKCS#8格式私钥,我们需要把头尾替换成RSA专属的标识,JSch才能正确识别。
  • 密码处理:如果你的SSH2密钥是加密的,一定要传入正确的密码,否则解析会直接失败。

验证转换结果

转换完成后,可以把字符串存成文件,用ssh-keygen -y -f converted_key命令验证,如果能正常输出对应的公钥,就说明转换成功了。

内容的提问来源于stack exchange,提问作者Limmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:49:54