在尝试通过KeyPairGenerator加载RSA私钥时,JSch获得"无效私钥:"

use*_*110 5 java ssh rsa jsch

我正在使用java.security.KeyPairGenerator来生成RSA密钥对,然后尝试通过Jsch(0.1.49)中提供的KeyPair类加载私钥.代码:

public static void main(String[] args) {
    String header = "-----BEGIN RSA PRIVATE KEY-----";
    String footer = "-----END RSA PRIVATE KEY-----";
    KeyPairGenerator keyPairGenerator;
    try {
        keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048, new SecureRandom());
        PrivateKey privateKey = keyPairGenerator.genKeyPair().getPrivate();
        String key = new String(Base64.encodeBase64(privateKey.getEncoded()));
        StringBuffer pem = new StringBuffer(header+"\n");
        int len=key.length();
        for( int idx=0 ; idx < len ; idx+= 64 )
            pem.append(key.substring(idx, (idx+64)<len?(idx+64):len)+"\n");
        pem.append(footer);
        String privateKeyStr = pem.toString();
        System.out.println(privateKeyStr);
        com.jcraft.jsch.KeyPair.load(null, privateKeyStr.getBytes(), null);
    } catch (JSchException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

System.out的输出:

-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCABIDFa/cp23OH
PZwpnBme3mvVun8ErtTpMtjCHBKbFyiVKI84e1sZt6BosIiXVbhJ3wsG+tmcJAVK
+rVRqSHUjPh9lHSI+4QQNvWIQC+v6zPyLKVRo47VK6dKTIZrsfA/A/+3hk/GrNx8
gbx9yENZ6WLg7GQ0mUwdV+kDwudll5sXjL7PHMIkVuxDOFv1cXXYmPuCtnFKvn/X
5XnD6fV8IOgLbwXTNzUxLdfnBn90PFYbRRUJVwIXzqSVJb3EXsEL6WAl2KdQ2BPS
UEv7jEw2Ja+fztUZUjqxWcrckq3rKUeHn3ykhTlq0+Iqg5sbgqz2zYt+6Zq4w42E
XrCqGlmVAgMBAAECggEAYLcGMiBnEpBgr4O0PxtXn9aZ0VacL4WGBMgNSli7FcBh
QI7r5NgM81jvLyhviSWRnP2M7zEExhnQhdzyr0b/7/ywnu9RO0wJcdaTmOQlItqm
3Acuvoa6mgHo2REHXMWJo5H510T5cDeYO9gn9z8c4wiXUyZEbhiCkIih2d2dw/mv
SBwfwOQN/3JXNBlW5c012usG6MLKvbOAYhqLfzq89ZqKJnrRW58Y6m+qb91fx5tt
DKrqVEXPBLcC0faXK+iMINGIbXqv8l1hd69f/SzSveI49yMgJBPCS5mtckcJqCm7
oxMafu3zGhaR7TYUM6CaqP3Sk2nLv6Sy9vNsFt4eAQKBgQD1TM/2nMV2HhVOl6Gm
hqCSGCxb6M+bv92tlkvuijpU0Bx5JjHTQ/dk8+0L0h/x+jPMo1+yrYyXNmE4kzyY
2s4jcDcBch5d8bSKksPv29sKYkMhEv0O31fcGVFhOyHvBm92EtA+l2vDVn0WSo7r
SAjsD3QSAdEr/pOqrUjInJfvMQKBgQCFmgjkVuMHgg5fjM+xQnPtLpJBRbe+gBdj
09jCj5D0mN5WpqvjO2cV40i2vYqaWz3/BgWcmlT4Crf2MtYxmR0rWsSQQsnk34EU
vej5kmkT8Pq4HRMskH2f/kNu55yHjY4TvMn13Gl9UWIb+g5oYdMbpb6B9jol9gm8
Op1wiopfpQKBgAbTvHYApv5CmBU34yffV1i5k4J7WEvday4JoNNixXzWzfQRPBHF
Mn18zHwnvPvfGtH3OhKfAeqzeME6V9VpQZN67Az+QBodQAkbTJjAZbhEQ9oHzUM8
tBVMHxe1rZwZccC3hVQ4oqctIQ4dxRyHRLhNNc3KfyfaTgHSENSEhzYBAoGAS4j8
MAVD1JHeiH03S9PzcQzcmdTN/wGyt7klm1LKNNBdHIadNhr2vHRFPzRIsd6WXaJM
9+51zctZmPPDEEWuLT3jVmC8fw8yjsSUfM4fZKvhRMkDdzW2IQgDnieK40TQKC6b
zMqyRa0GmCS3kqKEVeROonHRDHdfp7FIJEHf3BUCgYAjzIH744n31iTa/WhLXoIx
tR8rvTgdW6tn0YKGKy2RvgkABdDdjFc1oGBOSgNRopn1mL7cVtScMOenPTqKCEgO
yzVVOgE0ON1YmF/t3phOcJYIC9dy1CMHOjnG3deWxu2z3NAidF2TcAf8G/LtKOY2
t6uWCaHlDg2r/WDkbpxsgA==
-----END RSA PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

然后我看到KeyPair的异常说它是一个无效的私钥,我检查了JSch的源代码,异常是由于在解析数据时indexoutofbounds.堆栈跟踪:

com.jcraft.jsch.JSchException: invalid privatekey: [B@5f2e5f2e
    at com.jcraft.jsch.KeyPair.load(KeyPair.java:809)
    at com.ibm.maestro.common.utils.Test.main(Test.java:149)
Run Code Online (Sandbox Code Playgroud)

我猜我可以通过在生成密钥对时添加/更改一些参数来解决这个问题,任何线索?我们将非常感谢您的帮助!

Dun*_*nes 5

当您调用 时,Sun JCA 提供程序将返回 DER 编码的未加密 PKCS #8 结构,而不是 RSAPrivateKey 对象PrivateKey.getEncoded()

您可以使用 BouncyCastle 为您提供所需格式的密钥:

import java.io.StringWriter;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;

import org.bouncycastle.openssl.PEMWriter;

public class JSCH {

  public static void main(String[] args) throws Exception {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048, new SecureRandom());
    PrivateKey privateKey = keyPairGenerator.genKeyPair().getPrivate();

    StringWriter writer = new StringWriter();

    try (PEMWriter pemWriter = new PEMWriter(writer)) {
      pemWriter.writeObject(privateKey);
    }

    String privateKeyStr = writer.toString();
    System.out.println(privateKeyStr);
    com.jcraft.jsch.KeyPair
        .load(null, privateKeyStr.getBytes("US-ASCII"), null);
  }
}
Run Code Online (Sandbox Code Playgroud)

可能有一种更优雅的方法来获取字节字符串形式的编码密钥。将其写为字符串并调用感觉很难看getBytes(),但也许您可以研究一下。

输出示例:

import java.io.StringWriter;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;

import org.bouncycastle.openssl.PEMWriter;

public class JSCH {

  public static void main(String[] args) throws Exception {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048, new SecureRandom());
    PrivateKey privateKey = keyPairGenerator.genKeyPair().getPrivate();

    StringWriter writer = new StringWriter();

    try (PEMWriter pemWriter = new PEMWriter(writer)) {
      pemWriter.writeObject(privateKey);
    }

    String privateKeyStr = writer.toString();
    System.out.println(privateKeyStr);
    com.jcraft.jsch.KeyPair
        .load(null, privateKeyStr.getBytes("US-ASCII"), null);
  }
}
Run Code Online (Sandbox Code Playgroud)