Java 使用 JSch 时出现“无效私钥”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/53134212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Invalid privatekey" when using JSch
提问by o_b7
I'm using the following code to work with Git in a Java application. I have a valid key (use it all the time), and this specific code has work for me before with the same key and git repository, but now I get the following exception:
我正在使用以下代码在 Java 应用程序中使用 Git。我有一个有效的密钥(一直使用它),并且这个特定的代码以前使用相同的密钥和 git 存储库对我有用,但现在我得到以下异常:
invalid privatekey: [B@59c40796.
无效的私钥:[B@59c40796。
At this line:
在这一行:
jSch.addIdentity("<key_path>/private_key.pem");
My full code:
我的完整代码:
String remoteURL = "ssh://git@<git_repository>";
TransportConfigCallback transportConfigCallback = new SshTransportConfigCallback();
File gitFolder = new File(workingDirectory);
if (gitFolder.exists()) FileUtils.delete(gitFolder, FileUtils.RECURSIVE);
Git git = Git.cloneRepository()
.setURI(remoteURL)
.setTransportConfigCallback(transportConfigCallback)
.setDirectory(new File(workingDirectory))
.call();
}
private static class SshTransportConfigCallback implements TransportConfigCallback {
private final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host hc, Session session) {
session.setConfig("StrictHostKeyChecking", "no");
}
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
jSch.addIdentity("<key_path>/private_key.pem");
return jSch;
}
};
After searching online, I've change createDefaultJSch to use pemWriter:
在线搜索后,我将 createDefaultJSch 更改为使用 pemWriter:
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch jSch = super.createDefaultJSch(fs);
byte[] privateKeyPEM = null;
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
List<String> lines = Files.readAllLines(Paths.get("<my_key>.pem"), StandardCharsets.US_ASCII);
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(String.join("", lines)));
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
PKCS8Generator pkcs8 = new PKCS8Generator(privKey);
StringWriter writer = new StringWriter();
PemWriter pemWriter = new PemWriter(writer);
pemWriter.writeObject(pkcs8);
privateKeyPEM = writer.toString().getBytes("US-ASCII");
} catch (Exception e) {
e.printStackTrace();
}
jSch.addIdentity("git", privateKeyPEM, null, null);
return jSch;
}
But still getting "invalid privatekey"exception.
但仍然收到“无效的私钥”异常。
采纳答案by Natan
I also stumbled upon this issue. running Jgiton mac, for some users we saw the following exception:
我也偶然发现了这个问题。在mac上运行Jgit,对于一些用户我们看到以下异常:
org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:160)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:137)
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:274)
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:169)
at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:136)
at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:122)
at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1236)
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:234)
... 17 more
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@e4487af
at com.jcraft.jsch.KeyPair.load(KeyPair.java:664)
at com.jcraft.jsch.KeyPair.load(KeyPair.java:561)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:407)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:367)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:276)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:220)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:176)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:110)
The root cause was discovered to be the ssh private key mismatch. The exception only happened for users with key of newer kind ed25519, which outputs this key header:
发现根本原因是 ssh 私钥不匹配。异常只发生在具有更新类型ed25519密钥的用户身上,它输出这个密钥头:
-----BEGIN OPENSSH PRIVATE KEY-----
-----BEGIN OPENSSH PRIVATE KEY-----
instead of kind RSA:
而不是那种RSA:
-----BEGIN RSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
regenerating an RSA key (ssh-keygen -t rsa
), made the exception go away.
重新生成 RSA 密钥 ( ssh-keygen -t rsa
),使异常消失。
Edit following comments:
If you have OpenSSH 7.8 and above you might need to add -m PEM to the generation command:
ssh-keygen -t rsa -m PEM
编辑以下注释:如果您有 OpenSSH 7.8 及更高版本,您可能需要将 -m PEM 添加到生成命令中:
ssh-keygen -t rsa -m PEM
回答by dave_thompson_085
You read a file named
.pem
and de-base64 allof it and treat the result as PKCS8-unencrypted, apparently successfully. This means the file was NOT PEM-format. PEM format at minimum MUST have the dash-BEGIN and dash-END lines to be valid, which if not removed cause de-base64 to either fail or be wrong. (SomePEM formats also have 822-style headers which must be handled.)You appear to be using BouncyCastle, but in my versions there is no
PKCS8Generator
constructor that takes onlyRSAPrivateKey
. The closest thing that works isJcaPKCS8Generator (RSAPrivateKey implements PrivateKey, OutputEncryptor=null)
(i.e. a different but related class, and two arguments not one).PemWriter
is buffered, and you didn't flush it before looking at the underlyingStringWriter
. As a resultwriter.toString().getBytes()
is an empty/zero-length array, whichJSch
rightly considers invalid.
你读一个文件名为
.pem
和的base64去所有的它,并把结果作为PKCS8未加密,显然是成功的。这意味着该文件不是 PEM 格式。PEM 格式至少必须有 dash-BEGIN 和 dash-END 行是有效的,如果不删除会导致 de-base64 失败或错误。(某些PEM 格式还具有必须处理的 822 样式的标头。)您似乎在使用 BouncyCastle,但在我的版本中,没有
PKCS8Generator
构造函数只需要RSAPrivateKey
. 最接近的工作是JcaPKCS8Generator (RSAPrivateKey implements PrivateKey, OutputEncryptor=null)
(即一个不同但相关的类,两个参数不是一个)。PemWriter
已缓冲,并且您在查看底层StringWriter
. 结果writer.toString().getBytes()
是一个空/零长度数组,JSch
正确地认为无效。
With #2 and #3 fixed and using my input, and calling JSch
directly instead of via JGit
, it works for me.
修复 #2 和 #3 并使用我的输入,并JSch
直接调用而不是 via JGit
,它对我有用。
回答by Martin Prikryl
Recent versions of OpenSSH (7.8 and newer) generate keys in newOpenSSH format by default, which start with:
最新版本的 OpenSSH(7.8 和更高版本)默认以新的OpenSSH 格式生成密钥,其开头为:
-----BEGIN OPENSSH PRIVATE KEY-----
JSch does not support this key format.
JSch 不支持这种密钥格式。
You can use ssh-keygen
to convert the key to the classicOpenSSH format:
您可以使用ssh-keygen
将密钥转换为经典的OpenSSH 格式:
ssh-keygen -p -f file -m pem -P passphrase -N passphrase
(if the key is not encrypted with a passphrase, use ""
instead of passphrase
)
(如果密钥未使用密码加密,请使用""
代替passphrase
)
For Windows users: Note that ssh-keygen.exe
is now built-in in Windows 10. And can be downloaded from Microsoft Win32-OpenSSH projectfor older versions of Windows.
对于 Windows 用户:请注意,ssh-keygen.exe
现在 Windows 10 中内置了它。对于旧版本的 Windows ,可以从 Microsoft Win32-OpenSSH 项目下载。
On Windows, you can also use PuTTYgen (from PuTTY package):
在 Windows 上,您还可以使用 PuTTYgen(来自PuTTY 包):
- Start PuTTYgen
- Load the key
- Go to Conversions > Export OpenSSH key.
For RSA keys, it will use the classicformat.
- 启动 PuTTYgen
- 加载密钥
- 转至转换 > 导出 OpenSSH 密钥。
对于 RSA 密钥,它将使用经典格式。
If you are creating a new key with ssh-keygen
, just add -m PEM
to generate the new key in the classicformat:
如果您使用 来创建新密钥ssh-keygen
,只需添加-m PEM
即可以经典格式生成新密钥:
ssh-keygen -m PEM
回答by Ananth Kumar
JSch does not support this key format. It supports only RSAPrivateKey. This command works for me. Try this solution
JSch 不支持这种密钥格式。它仅支持 RSAPrivateKey。这个命令对我有用。试试这个解决方案
ssh-keygen -m PEM -t rsa -b 2048
//edited to rsa with 2048 keysize
//编辑为2048密钥大小的rsa