因为项目使用ssh秘钥连接时候异常报错,所以有去查看源码。 报错信息: com.jcraft.jsch.JSchException: invalid privatekey: [B@53a7a60c
项目需用使用ssh连接的可以参考: Java SSH 秘钥连接mysql数据库.
这里使用的jsch版本是
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency>
ssh-keygen -t rsa -C “个人邮箱”
后文说明第一种秘钥以及新格式秘钥都是这种方式生成的秘钥。使用此行命令生成的秘钥开头是
BEGIN OPENSSH PRIVATE KEY
这种秘钥是jsch解析不了的,所以需要加上-m 参数指定密钥的格式,PEM(也就是RSA格式)是之前使用的旧格式。这是第二种秘钥。
ssh-keygen -m PEM -t rsa -C “个人邮箱”
这时候生成的秘钥开头是
BEGIN RSA PRIVATE KEY
注意:新格式秘钥xshell5不支持导入秘钥,xshell6支持
那为什么新格式的秘钥jsch解析不了呢?
jSch.addIdentity(p.getProperty("ssh.identity"));
报错是从这行代码中开始的。
从源码可知道,如果公钥的名称为null,则会取私钥名称.pub,如果公钥名称不是私钥名称.pub则会报异常,而报错也是报无效私钥的异常。
从这里可以看到type的初始值为ERROR,而在后面可以看到当type==ERROR时会报无效秘钥的异常。那在这中间就会修改type的值。
从这里可以看到,jsch是通过解析字符串来解析秘钥的。当文件不是begi开头时候也报错。后面也只有判断RSA、DSA并没有判断开头是OPENSSH的地方。所以使用新格式秘钥时会无效私钥的异常。
但本人试过修改新格式秘钥的开头,但还是报无效秘钥。这个问题留之后再看。
jsch也是支持使用.ppk文件经常秘钥校验,无论是使用新格式秘钥还是旧格式秘钥,只要生成.ppk文件后,使用.ppk文件就不会有上面的问题。
使用putty进行转换,我只找到最新版的官网下载地址,旧版在官网中没找到(太多英文了,而且翻译不了,我英语实在不行,请找到的小伙伴联系我),但在其他网站是可以下载到的。
PuTTY下载网址
推荐使用0.74版本的,但最新的0.75正式版已经出来了,但是0.75版本的转换的是.ppk文件jsch有点转换不了。
使用PuTTYGen.exe。点击File -> Load private key -> save private key就可以生成.ppk文件。(界面上0.75和0.74是没有区别的)
PuTTY-User-Key-File-2: ssh-rsa
这是0.74版本的开头
PuTTY-User-Key-File-3: ssh-rsa
这是0.75生成的
前面说了jsch是通过解析字符串来解析秘钥的。遗憾的是,jsch只识别0.74版本的开头
本人在修改了0.75生成的.ppk文件开头后还是有问题,也是会报无效私钥的异常。
然后发现这里会去用0x0d(回车’\r’)以及0x0a(换行’\n’)做字符串截取。0x0d做字符串结尾标识,0x0a则做了字符串连接表示。
这是0.74版本转换的.ppk文件,这里的的回车换行是两个标识。
而在0.75版本转换的.ppk文件,这里就只有一个换行的标识。
本人秉着坚持不懈的原则,将所有的0x0a(换行’\n’)的标识都改成了0x0d(回车’\r’)标识。最后重新启动项目是成功的。
正确使用jsch秘钥的方式
1、在创建秘钥时候使用 -m PEM参数生成旧格式的秘钥。
2、公钥名称要等于私钥名称.pub。
如果不想使用旧版本秘钥,就需要生成.ppk文件。
1、使用0.74版本之前的或者0.74版本的PuTTY去生成.ppk文件
2、使用0.75版本的PuTTY生成的.ppk文件需要手动修改注释头以及修改回车换行标识。