在尝试通过KeyPairGenerator加载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(); } } 

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

然后我看到KeyPair的exception说它是一个无效的私钥,我检查了JSch的源代码,exception是由于在解析数据时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) 

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

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

您可以使用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); } } 

可能有一种更优雅的方式将编码密钥作为字节字符串。 将它写成字符串并调用getBytes()会觉得很难看,但也许你可以调查一下。

输出示例:

 -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA3r29olF+Kul+aHsB28i9x8RiH6OEgIDoqcN4Ph0+bCYBi9lk E/TVtLXxNxXvvcsK5DyQLZAWj/W0QmvmItndkzcWFojIoS3XT7kFPeC49hPe6g/W ihM7eS5W3wTzAoljimyMjFUkw9ahShRrL+Dl6ZeqMW5bTwUXgcIFSKNw4iFQJFFO 5G8a1ObAV5iNA1ve5IFntKjCc5WIA4byilBCLcoXCeQNSPwyGVc1Okz22FTAQFzk 9eQthuF3AIAhHcDgf1yxx6RTTMMMSWzIva6xZvTHCKov3CwTLioH1Ri72UT9GAoq O4hS/CL4Q4m09X6KGicXR86CpQ8TiXD4A+HwkQIDAQABAoIBAQCLYmrvz1VHnzPm R8ti8NypzN+mctnw3Do8OcDeBcjRPntLO2+f+V9eJVjcItMSjqOzLZ7/lCI6VgRG aGTsPC+m9xrQYSpDin8pOVvpW94Cx26ARAb6Aoz+CRx9lQhI9xaeQc015/YIwx/N TrfAj1jwc2Miaa+j5EjQf0x1Jyn1pr41vgC5z2zD+FyNfVOu7Q4rmiEIi3B+QHWg 33YhtJrP2nWEmka6pn0NiYlS3IZRA6tL7DUC62iTfs7vs5M6OCsg9w7Vfq5YGwr3 cm9n+VencsupB4A6b13XZPWhyaImGO7+5TQy4xX9/mT99GoC6L73RX5O4Ehhg++m NpB8Bt5tAoGBAO+rR0dleFeH4aHtMeLlatjZhSIWcRzXqW/bkeaq4SrhF7h4GC9J Spih1fjWMznrfcsHxgJyYtZ3OBPMp7DhUZR9WbeqOwpD5Qd0Kr3LovKiX6HTeNKQ QyPvca0n3z6a72XGqbKonoXhUJ2OKv8pl7nVaBxO9r/YloTLZ5SOMpmHAoGBAO3r LU6zxBdUzaJ28tuNx2TCJJyLCDSrnZFgyTA+xexk1wpJXOJxmCVBTl5tajYwhjTc 9OMOVGr8qgcblcDOSCy4khZrgStHfjzZBQA8zesR/vNO+nzGxzfzIMSNey7OKtAB LoKMEe1O1FuxTCiQZveekzZlT3EKDgU809UDvksnAoGANGXF154fiUNz2Or6lRiD G5WyvZkacavUp1fhtgR15eIARZw77VqgrG31UcnCuU762YCBkddgNHMsF2gO4WTh aQ1eqADXl47wa4jCL2xt244USlTpfV98zkZzG+AztoQ5Ao9EWoLy5WI1Nbz3OYHm YgJ+GHJLD/ZSMgYmRxwvg9ECgYBVDs0l4/Lo/HJ/8NKmV6u/hAEezj3ixrAQd2+2 BdswxmRy0wOYGVBxkUV5UNi2AucYIx6Rxl+72BTZca06PwVip6HizhBh7q9dBaFa EmLz9X0Wc1fuIAq9H/jJDGPLuf1oW+PK3FTUaGhXV62ImweU42Zx/gpGuXeFu9dn wmzX5QKBgHgbQHqcf36bvwE/zr9jLCOPSkVZpFPYNt6/uUT/Vb4vDPME2/wk1SoU wV2I3Vj9bLsnkpsP6fOsX3QqGFwlnnpboF/IS9rObTkDZXsKfLJhT5x6xA6USnWC ZPY8jO4b1RXf3v1mHpkx21dKmY2YvNetzp6OaK8DzPwFM8KUh5GG -----END RSA PRIVATE KEY----- 

您可以使用PEMWriter将您的私钥转换为JSch将接受的PEM格式

以下示例转换从KeyStore(JKS)返回的密钥

 Key privateKey = KeyStore.getKey(privateKeyAlias, keyStorePassword);//get key from JKS StringWriter stringWriter = new StringWriter(); PEMWriter pemWriter = new PEMWriter(stringWriter); pemWriter.writeObject(privateKey); pemWriter.close(); byte[] privateKeyPEM = stringWriter.toString().getBytes();