2

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-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDNPvFmy81wj3L4ndJzMcYFa9YctDzz0KvXyb9vg+UQ5622kyE255fwL4eatihL8/TrH1OOLQtSVjThLwWObx4fQ6bk25rJA0jS7G7CAfAQwbTY9JpNrcH5HHtiAhbUjEF/MXU6IlPNCmBMQPFh1eSa21aIdYie+KVgXQnUP4qN6ks1iR8XX4YHpg2KKhEoJtaVYGHp15EmpRvDYzsheqrcfyg4N5taGgG9/GzdfpeBWqCyJhrjgso85ARecGTpqCHqFNy46tXtIMR6FL36UDc/EpWifmf7oY4HVLa0DJpLq2BHmjRlUtiFFox1Jzk+shFiDZYwnCmdKnpCnlxFQ1Hv06XLgvcUx/0mkleh14Nme/b61pmJDO05v9zKho+9Q+lNgrTK+kOeC7I9PgUePyzWJteys/0MqENJxvM4g65/r9vzpcSvdEziSJ8Y3xI3qlzOa3Av1Jv5qIntgjEeAnth+AANdUP/GcpYbnCNp1QsjaZoFKFe2DcUTYM3CGzh0SFm9CeRfBV1phQ2+5gi1bH5ZiAfTNpksZz+SYIPyEsbaqNRcBk53htWfINShNVP7a/b/H7tyZs+zvMoHN2bZzsIMIUWO8Df+owpCK7ZT/EadDZzkzG2LUUUjm6aVsz2rjLFcvQtYOs0U/+suWhXNQ2dAW4psGLHkNb3NDHSzjzk7wIDAQABAoICAFeJI83y1/DMzX0pWmtU7B69yji9yk02T0QeQG5gM18NYHJAt+bByXRf4Rbj37XdGzT4TFuT7IM2TyFHO7huvcsZwGFVI+Pdab7Dpc1KpEeRRf9N+01r8RG8ywaW24PVOc30mwmrQFBvv3hmLkzKu9AsAfD7J8SdSXMa2ylR3FcAeQkhLUh7rh8u/BFUNbMJNXXKAJiKHtb7jia7+KkjtyGJfe7UEIbSFrIfqZKh/h3mOCkixU8JJhXoLdDVYMSit6wtL6ISTiDvW7yxggDzG0zkMTt3bAPO+FM6Fx4dTeU99zcylmwsdDn2zvrcOrb5nR5Tqx2aTMlCJ5ioD7RerN+3YAhE1+cvrvZc5wa+aZruNMioTrxWzhc3iSoZHKKGE5VAnF/HkoR/lgCGVCcsWeNamdUjydD9H9Y/33S7Y0e+wLCNXOAmyE2jSMpHGEPwohlwyXrMvnKXoWX/LlNjhG8aWW8dWL6Lym3Z/eO3WBEe1Xccv9jd56h52rqvzW3MOpL320RcgqdLtgb7Ihz8twQdAyjaY81fJJtSnns/GBrbqAxO//EyWi8vBU82p4hl3tw8RAxGrx91LFPwv78ACvht8X8ogU4/c1B6rnI0n+Ofsvq9ZxQsATQAk1y83vPbTUNc+XJ8X/Jvxr/y1mp+8q9fIq2jHGUGJevBSW1+RBoZAoIBAQDzyhXuEiXtoBPMWew+ALUIJ5sW3JS+uShxq8KKo/a/V7OyrrBZTYmbjkxyxBlkKJUFA7xqwVXgnMkywA0EnrdE0TmmBwr7czZjT7Lp4PbhoZ73YJ/y31nuJJCGzkLeJKrtFaM2BdzPdqC86qeAIN9YHZnzyud+o6RkJlDje5hFv6cP5+JGu1OyhqNvFSyevKZLq5hGx6gkqSCVM65PhJELj4jwgI84E7pm9w7sZ5xN2X0W66dmElpN3OBj2VWlF6eiUNoIU3WyHwMn2+rrC8+YTGp9ByCR/+sHkM9mXQeT/3tjrBdXppRjy5EggcTW6T1KObnmOBgLDYLyxj4dFfXVAoIBAQDXhqUUFQarfK4jBgBcD3PzwyXtl9F6e4/IrdCwePjgRDuTNlcdUV/9HlfwNDEiVhd9ymcNwX/26W6VmEBAdec6czVVAY9fhZRz6Pp9DOH/7nJsln6Yz76ezOFeTJXm93dRLX/mkVM4qz4+JqPgll53IlYI9f6eqBZCfHJHj+LeCZDnDvKvF4M+LTpLR/fiF4/mVrBjrh6DuHwWPBnRCViKQyTkj8WCRRtRSWucZYplguCYN30iSH7Dv1MdnJGYie8dRDnDvV2G3dI666ugDVLZb48Rg+o3La3DzA7qEMQ6Lpy3abjyaaWOIz1Z/n3gQGWrqgeZpIZpnV04E5WS9X2zAoIBAH0iAmWjrRIuc1sV4PvmUwWvhpySdkr7MTY/amjNRm7qblNN9TixYuuUe8sAuuO9LNhZFZJaUGEtONyy1TvE198b4ZJF1S5B8e3Bz9zaWv5vffAOCauZV0i0Pfbj0lDB03ZD//VPxwo6IsE1VOqgdON+tjH7uR04k73QKP7KxtsuR2sTpAKYTpq5HxR6ct+7h0QZ/Nx/yN+gbBgJYfRw4B5l+20vH9Qx1CDbuS5A9GrFMr7cEJ2E2BNVR1wZByvpW2MmSvOxGx1la7I+4HLrKhBLUPGCAgbOrG3Ct6IcKDKgFU6Q255i45HhwElGMqn5KDt8K95udnDd65P/i4xUZE0CggEBALqThwixgwqlbqJHKbyIbBqTz5u1F9TubnSNc+Gxd9G9f81a92Mb9PrMb9gzdm2BFekBdOEFp996CQ9btBOZfcitv3eNWC6bFv6Yq2/h3SuPomK6jXGANkaGmnrl1ccSZ6pQty5ElES0ibeH/8oGolSD1vL+8aMrY8m+rbehqgYJRfWgjRpiQm1q/dH5xW9mcl42oZBJRYVGCbW95aN+cbWPlrp+c77oUFO4OX40sPBbsk5TivJIy+RtFmjGB4yDrAor6821euer07jKF9MAdb5hwvqotfN6ibi8SBT82sJ7Y5Or5D2Gk5lOjGgB1bpyRRGsqdOqB+oaHn7TBWMpPd0CggEAFPHds2f5CKjsNg9IkiA4yoCzfsjVhy9qiE/2BikA25JTc6nMfTfpWMzcDL3qnfhFGsFWz31Xf8MbZDMq0cCsMQhsgYPolU5N2AkWvAeqSbwMz9zIDiPeND/Ql4sOyicPd6LJrT3UTRWoY3+p4wo73rpOXM4Ju3u++sCeERTulghgGZoJBSIT+8H7pKa7cFchATvBKZQTUnOZEhqzQN4R2wZ3j5ujG8rGjfRHDRL8OPiNRRv/L/oHxGnhB4Rfbc4ba0zNx4zy6d+Em6H8wX72WHhz5eVs2xQR+EIBtxDVlmvdpGkvCtUhS1227yiiL+wqkfNz3UnTSjGy3eHNRGAsVg==
-----END RSA PRIVATE KEY-----
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
wheeler
  • 2,823
  • 3
  • 27
  • 43

1 Answers1

1

You need to write the private key in PEM format.

For that you need BouncyCastle library.

For an example see:
Java generate RSA key pair and convert to PEM

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992