本文不涉及任何高深技术难点,仅记录解决问题的过程,供自己在下次遇到的时候参考。
最近在对接工行的对账平台,需要使用sftp配合rsa私钥下载对账单,翻看了以前的代码以及网上搜索了一下,发现代码实现的话用jsch比较方便。
然后开始代码实现,然后发现网上大部分是通过密码或者私钥文件登录,但是这边不想存储文件,所以废了点时间找了直接通过私钥字符串来实现:
jsch.addIdentity("id_rsa", key.getBytes(), null, null);
本地密钥对是通过工行提供的工具来生成的,私钥类似于这种:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP3OMU9GXXXXXXXX...XXXXXX4W0F7bIvUZeuurhxv8MfER3B/H8hErSia81+HY=
是没有头部和尾部的
然后第一遍尝试果然出错了:
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@44e81672
于是开始仔细查看,然后发现应该是缺少头部和尾部,于是把私钥的头部为尾部加上,变成如下格式:
-----BEGIN RSA PRIVATE KEY-----
XXX...XXX=
-----END RSA PRIVATE KEY-----
再试一次,还是同样的错误,我一度怀疑是不是工行的工具有问题
后来在网上搜索rsa的密钥格式时,发现原来有pkcs1和pkcs8的区别,但是此时我粗心的没看他们具体区别是什么(毕竟大段的英文很费脑),只是简单的看到有区别,于是我去网上找了个简单的函数,可以把私钥在pkcs1和pkcs8之间转化,由于我也不确定我自己的是1还是8,因此两个都执行了,最后确定我的是8,然后转成1之后拼上头尾,果然可以了,正常事情到这里应该结束了,毕竟已经解决了
但是我又思考了下,jsch这么多人用,没道理不支持pkcs8,最终在官网发现这么一行:
• supporting private keys in OpenSSL(traditional SSLeay) and PKCS#8 format.
也就是说他们应该是支持的,那为什么我的不行呢
于是只能去看了下1和8的示例,参考文档:
cryptography - PKCS#1 and PKCS#8 format for RSA private key - Stack Overflow
然后发现原来1的头部和尾部是 “BEGIN RSA PRIVATE KEY” 和 “END RSA PRIVATE KEY”,而8的是“BEGIN PRIVATE KEY”和“END PRIVATE KEY”,果然是我的问题,我直接把1和8的转换函数都删了,然后在私钥拼了不带“RSA”的头尾:
-----BEGIN PRIVATE KEY-----
XXX...XXX=
-----END PRIVATE KEY-----
果然可以了
本来就只要拼一个正确的头尾的事情,走了很多弯路 😮💨