7

One of the tasks of a Java application I am building is to connect to a remote SFTP server. In order to do that I have the certificate of the remote machine and a local identity (id_rsa and id_rsa.pub in the .ssh folder). This is working fine.

I'd like to put the certificate and the identity in a password protected java keystore for easier and more secure configuration. I have this working for the certificate, but I am having problems storing the SSH identity in a JKS or PKCS12 keystore (either one would work).

To isolate the problem I have tried the following steps:

I use ssh-keygen -b 2048 to create the two identity files id_rsa_demo and id_rsa_demo.pub in te local directory. As I understand these are the private and public keys of the identity, so I try to combine those into an identity.p12 file:

openssl pkcs12 -export \
               -inkey "id_rsa_demo" \
               -in "id_rsa_demo.pub" \
               -out "identity.p12" \
               -password "pass:topsecret" \
               -name "demoalias"

This gives me the error unable to load certificates. I searched around and it seems that openssl expects a certificate with a complete chain for the -in parameter. Since my generated identity does not have that, I tried the -nocerts option, like so:

openssl pkcs12 -export \
               -inkey "id_rsa_demo" \
               -in "id_rsa_demo.pub" \
               -out "identity.p12" \
               -password "pass:topsecret" \
               -name "demoalias" \
               -nocerts

I get no errors, but the -nocerts option lives up to its promise and does not add my public key to the pkcs12 file:

openssl pkcs12 -info -in identity.p12 

Enter Import Password:
MAC Iteration 2048
MAC verified OK
PKCS7 Data
Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
Bag Attributes
    friendlyName: demoalias
Key Attributes: <No Attributes>
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIAOXpzckBb28CAggA
MBQGCCqGSIb3DQMHBAjPq9ibr445xQSCBMi5IlOk5F28kQPB5D97afiUb5d3It46
...
ejwYfHTj6bm+dEOUk68zNrWwKqwuJx5AZv3U8sm1cicVmh9W0HpL5tSmMMpDS1ey
Uos=
-----END ENCRYPTED PRIVATE KEY-----

Is there a way to store an SSH identity into a PKCS12 or JKS keystore?

Rolf
  • 7,098
  • 5
  • 38
  • 55
  • I found this related question, but I don't want to store it as a password string, that feels funny. https://stackoverflow.com/questions/6243446/how-to-store-a-simple-key-string-inside-java-keystore#6243755 – Rolf Jul 13 '15 at 15:20
  • I am not really sure here, but I think the java's keystores (either in PKCS12 or JKS format) are meant to be used for SSL communications. The SSL communication used something more complete than a public-key, called certificate, to authenticate entities. The certificate embed a Distinguish Name and other stuff to initialize a SSL communication between 2 entities. I think there is a confusion between SSL and SSH, and I am note sure it is possible that information stored in a keystore may be used for an SSH communication. – Francois Gergaud Jul 13 '15 at 15:29
  • Are you trying to use an existing private key, or is it okay to generate a new one? – Warren Dew Jul 13 '15 at 15:41

1 Answers1

11

Supposing you have a private key that looks like this:

id_rsa

-----BEGIN RSA PRIVATE KEY-----
MIICWgIBAAKBgQCh3czej+KeEraesxts3xP6kx+cO/Fu8ROc/k4hSl7fO9jFZ6Lm
OsGlzsRsi8VDg9n/fh6iFng/Umgnfd4J0IiLQihSRYnvyOsqqXbIJ8mBtydqO4s+
CjZLLDRSEMx3dw6GhFOcQ7xYYOeUMNY8QFidPn2LjURfMxG9XWOrCww8rwIBJQKB
gGA+sSpjZCajV9P7yx4jxrCqgX99lnlREpSy4lj7ybUqgOQUG6t84dg1wOaYS8dH
erOXGSIbMr3d+L2JHD0v4ntcKqzJm6Nf1FE27V0hvpzZl3fNax4NI/cIXM78zBx4
lBblr5QMYnTSd5eADIcDy7TZHuScRPkPViQ2x9QPayQ9AkEA67lfOXFEJ8iTYHdu
ykvj0Xqcs/peDX5nYXCEJ2XECxgxfKYVbQPazO5ACgp1VsgFMCsd4rDSwahOAgkE
rGfgCwJBAK/KFkSqMCLga8m19uqOftTQ+GhFc0O1lchWQ0A99+b9Rcs0yAe10GCN
SbgrEmMuXEQS1emT6ZHM7KIh2P7kiG0CQQDSPYxH/TzJiWDZf0cjIRdMIT+ncJkS
9DKw2flTkh2NWsRaap1858MleowkoYs/j81Gov76nbUNlhwPpy2uhiivAkByBor8
G11+aA6QrWHkQMD4vuZReSgr62gTPt+DndE74o4i8c3bfNowyllU3asP5rhjgdbc
svheksMBYhA2ohNNAkAiKQdv08UAG77piJi09OFIEcetTiq/wy9Zeb6fmEuMFzsT
2aR6x0d43OXqAgcKFgFuzqdXgxqhP/n9/eIqXdVA
-----END RSA PRIVATE KEY-----

Do two things:

1) Create a certificate to wrap the key and expose the public key as a certificate, so that keytool understands it.

openssl x509 -signkey id_rsa -req -in example.req

2) Create a self-signed certificate from your new request.

openssl x509 -signkey id_rsa -req -in example.req -out example.cer

Then, combine the certificate and private key, and import into keytool.

cat example.cer id_rsa > example.full
keytool -import -keystore example.jks -file example.full

This will get the keys in there. Utilizing the private and public keys and interacting with the SSH/SFTP library of your choice is left as an exercise.

Community
  • 1
  • 1
maxwellb
  • 13,366
  • 2
  • 25
  • 35
  • If I read this correctly, this creates a new certificate with a new public key, or does it in fact contain the original bytes of id_rsa.pub? – Rolf Jul 14 '15 at 07:19
  • A public key is always inferrable from the private key, at least in RSA. But yes, the bytes are in there, just packed with different formatting metadata. You would still use the format from id_rsa.pub to add to authorized_keys, for example. – maxwellb Jul 14 '15 at 12:42