Skip to content

PKCS#8 support #437

@j4ns8i

Description

@j4ns8i

I'm debugging an application that uses sshj for connecting to other machines when given an ssh key pair. I uploaded a PKCS#8 encoded private key to this application, with which I verified I could manually authenticate to the other machines it manages through ssh (ssh -i ~/.ssh/mykey.pem node). However, the sshj library failed to authenticate with this key with the following stacktrace:

net.schmizz.sshj.userauth.UserAuthException: Exhausted available authentication methods
    at net.schmizz.sshj.SSHClient.auth(SSHClient.java:232)
    at net.schmizz.sshj.SSHClient.auth(SSHClient.java:208)
    at com.cloudera.server.cmf.node.NodeConfigurator.connect(NodeConfigurator.java:368)
    at com.cloudera.server.cmf.node.NodeConfigurator.configure(NodeConfigurator.java:965)
    at com.cloudera.server.cmf.node.NodeConfigurator.run(NodeConfigurator.java:1043)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: net.schmizz.sshj.userauth.UserAuthException: Problem getting public key from PKCS8KeyFile{resource=[PrivateKeyStringResource]}
    at net.schmizz.sshj.userauth.method.KeyedAuthMethod.putPubKey(KeyedAuthMethod.java:46)
    at net.schmizz.sshj.userauth.method.AuthPublickey.buildReq(AuthPublickey.java:62)
    at net.schmizz.sshj.userauth.method.AuthPublickey.buildReq(AuthPublickey.java:81)
    at net.schmizz.sshj.userauth.method.AbstractAuthMethod.request(AbstractAuthMethod.java:63)
    at net.schmizz.sshj.userauth.UserAuthImpl.authenticate(UserAuthImpl.java:68)
    at net.schmizz.sshj.SSHClient.auth(SSHClient.java:226)
    ... 9 more
Caused by: java.io.IOException: Could not read key pair from: [PrivateKeyStringResource]
    at net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile.readKeyPair(PKCS8KeyFile.java:165)
    at net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile.getPublic(PKCS8KeyFile.java:78)
    at net.schmizz.sshj.userauth.method.KeyedAuthMethod.putPubKey(KeyedAuthMethod.java:44)
    ... 14 more

Right before that stacktrace is a debug message (which I believe should be a warning instead):

Expected PEMEncryptedKeyPair or PEMKeyPair, got: org.bouncycastle.asn1.pkcs.PrivateKeyInfo@d11392bd

This happens because my PKCS#8 private key contains the standard header of -----BEGIN PRIVATE KEY-----, which bouncycastle's openssl library parses into a PrivateKeyInfo object. As it is currently, sshj will only properly construct a PKCS8KeyFile from a PEMEncryptedKeyPair or PEMKeyPair (as explained in the debug/warning message), which will only be returned from files with the -----BEGIN RSA PRIVATE KEY----- header and correspond to PKCS#1 encoded files. Thus, it appears like the PKCS8KeyFile will actually only work with PKCS#1 keys.

I believe it should still be possible to construct the PKCS#8 object from the PrivateKeyInfo object that the openssl library returns. The object should contain the modulus and public exponent needed to reconstruct the public key for the key pair.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions