I am generating a keypair using Java's KeyPairGenerator
for use with JGit. However, JSch (the underlying SSH implementation for JGit) keeps giving me "invalid privatekey" errors when trying to use the generated private key.
Here is the stack trace:
Caught: org.eclipse.jgit.api.errors.TransportException: ssh://git@bitbucket.hostname/~wlaw/bitbucket_upgrade_test_repo.git: invalid privatekey: [B@4650a407
org.eclipse.jgit.api.errors.TransportException: ssh://git@bitbucket.hostname/~wlaw/bitbucket_upgrade_test_repo.git: invalid privatekey: [B@4650a407
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:254)
at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:306)
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:200)
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:1)
at java_util_concurrent_Callable$call.call(Unknown Source)
at Test.run(Test.groovy:95)
Caused by: org.eclipse.jgit.errors.TransportException: ssh://git@bitbucket.hostname/~wlaw/bitbucket_upgrade_test_repo.git: invalid privatekey: [B@4650a407
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:183)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:140)
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:280)
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:170)
at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:137)
at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:123)
at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1271)
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:243)
... 5 more
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@4650a407
at com.jcraft.jsch.KeyPair.load(KeyPair.java:948)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:46)
at com.jcraft.jsch.JSch.addIdentity(JSch.java:442)
at Test$1.createDefaultJSch(Test.groovy:82)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:335)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:293)
at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:200)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:130)
... 12 more
Here is my code:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA")
keyGen.initialize(4096)
KeyPair pair = keyGen.generateKeyPair()
def pub = pair.public as RSAPublicKey
def priv = pair.private as RSAPrivateCrtKey
Base64.Encoder encoder = Base64.getEncoder();
def publicKeyText = "ssh-rsa " + encoder.encodeToString(keyBlob(pub.publicExponent, pub.modulus))
def id = bitbucket.post {
request.uri.path = "/rest/ssh/1.0/keys"
request.uri.query = [user: bitbucketUsername]
request.body = new JsonBuilder([text: publicKeyText]).toPrettyString()
response.success { FromServer fs, Object responseBody ->
responseBody.id
}
response.failure { FromServer fs, Object responseBody ->
println fs.statusCode
println fs.message
println fs.headers
println responseBody
null
}
}
def privateKeyText = "-----BEGIN RSA PRIVATE KEY-----\n" +
encoder.encodeToString(priv.getEncoded()) +
"\n-----END RSA PRIVATE KEY-----\n"
new File("priv").text = privateKeyText
new File("pub").text = publicKeyText
SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
@Override
protected void configure(OpenSshConfig.Host hc, com.jcraft.jsch.Session session) {}
@Override
protected JSch createDefaultJSch(FS fs) throws JSchException {
JSch defaultJSch = super.createDefaultJSch(fs)
defaultJSch.addIdentity("test", privateKeyText.bytes, publicKeyText.bytes, null)
}
};
CloneCommand cloneCommand = Git.cloneRepository()
cloneCommand.setURI("ssh://git@$bitbucketHostPort/$project/${repo}.git")
cloneCommand.setTransportConfigCallback(new TransportConfigCallback() {
@Override
void configure(Transport transport) {
SshTransport sshTransport = (SshTransport) transport
sshTransport.setSshSessionFactory(sshSessionFactory)
}
})
cloneCommand.call()
I did some debugging in the JSch source code, and found that the library is getting an ArrayIndexOutOfBoundsException on line 228 in com.jcraft.jsch.KeyPairRSA.java.
Is it something I am doing wrong with formatting the keys for JSch? Or could this be a bug in Java's implementation of a KeyPair or perhaps JSch's implementation of parsing them?
Here is an example keypair that is generated by my code:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDNPvFmy81wj3L4ndJzMcYFa9YctDzz0KvXyb9vg+UQ5622kyE255fwL4eatihL8/TrH1OOLQtSVjThLwWObx4fQ6bk25rJA0jS7G7CAfAQwbTY9JpNrcH5HHtiAhbUjEF/MXU6IlPNCmBMQPFh1eSa21aIdYie+KVgXQnUP4qN6ks1iR8XX4YHpg2KKhEoJtaVYGHp15EmpRvDYzsheqrcfyg4N5taGgG9/GzdfpeBWqCyJhrjgso85ARecGTpqCHqFNy46tXtIMR6FL36UDc/EpWifmf7oY4HVLa0DJpLq2BHmjRlUtiFFox1Jzk+shFiDZYwnCmdKnpCnlxFQ1Hv06XLgvcUx/0mkleh14Nme/b61pmJDO05v9zKho+9Q+lNgrTK+kOeC7I9PgUePyzWJteys/0MqENJxvM4g65/r9vzpcSvdEziSJ8Y3xI3qlzOa3Av1Jv5qIntgjEeAnth+AANdUP/GcpYbnCNp1QsjaZoFKFe2DcUTYM3CGzh0SFm9CeRfBV1phQ2+5gi1bH5ZiAfTNpksZz+SYIPyEsbaqNRcBk53htWfINShNVP7a/b/H7tyZs+zvMoHN2bZzsIMIUWO8Df+owpCK7ZT/EadDZzkzG2LUUUjm6aVsz2rjLFcvQtYOs0U/+suWhXNQ2dAW4psGLHkNb3NDHSzjzk7w==
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----