I'm generating Ed25519 key pairs in my Kotlin app using the BouncyCastle library and have two requirements that are easy to implement in isolation, but seemingly difficult to do in tandem:
- Provide the key pair as a JCE
KeyPair
instance for use with a third-party SSH library - Provide the public key in OpenSSH .pub format for the user to copy and paste into a git repository provider such as GitHub (i.e.
ssh-ed25519 <encoded key> <comment>
)
I have two options for generating the keys using BouncyCastle, each makes only one of these requirements easy.
Generate directly using BouncyCastle generator
val generator = Ed25519KeyPairGenerator()
generator.init(Ed25519KeyGenerationParameters(SecureRandom()))
val pair = generator.generateKeyPair()
This gives me a key containing Ed25519PublicKeyParameters
, which makes it super easy to get the OpenSSH .pub format using OpenSSHPublicKeyUtil
provided by BouncyCastle:
"ssh-ed25519 " + toBase64(OpenSSHPublicKeyUtil.encodePublicKey(publicKey))
...but there is no obvious way to get to a JCE KeyPair
from here. The BouncyCastle JCE implementation seems to use BCEdDSAPublicKey
and BCEdDSAPrivateKey
as wrapper classes for exactly this purpose, but their constructors are package-private.
Generate using BouncyCastle as a JCE security provider
Security.addProvider(BouncyCastleProvider())
val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance(EdDSAParameterSpec.Ed25519, BouncyCastleProvider.PROVIDER_NAME)
keyPairGenerator.initialize(EdDSAParameterSpec(EdDSAParameterSpec.Ed25519), SecureRandom())
val pair = keyPairGenerator.generateKeyPair()
This gives me the JCE KeyPair
I'm looking for, but no obvious way to convert it to OpenSSH .pub format. The answers in this RSA-specific question all only support DSA/RSA, or suggest libraries that also don't seem to be able to handle the Ed25519 keys. I have tried:
- Apache SSHD
- SSHJ
- Jsch
What I think I need
Any one of:
- A way to convert from BouncyCastle's
AsymmetricCipherKeyPair
to a JCEKeyPair
- A way to get a
Ed25519PublicKeyParameters
instance from aBCEdDSAPublicKey
wrapper so I can use BouncyCastle's OpenSSH utility method - Another way to output a BouncyCastle generated Ed25519 public key from a
KeyPair
in OpenSSH format - Another way/library to generate an Ed25519 keypair that will support my two requirements