1

I want to do an asymmetrical file encryption:

openssl genrsa -des3 -out private.key 4096
openssl rsa -in private.key -pubout -out public.key
openssl rsautl -encrypt -pubin -inkey public.key -in a -out b

But I already have a key pair in my ~/.ssh directory, so how do I use this instead of generating new keys? Simply switching filenames gives an error:

$ openssl rsautl -encrypt -pubin -inkey ~/.ssh/id_rsa.pub -in a -out b
unable to load Public Key

public.key starts with BEGIN PUBLIC KEY while ~/.ssh/id_rsa.pub starts with ssh-rsa, so I figure it's some sort of format problem.

How can I generate a ~/.ssh key that openssl understands, or how can I instruct openssl to understand the keys I have in ~/.ssh?

e-sushi
  • 1,296
  • 2
  • 14
  • 41
forthrin
  • 1,741
  • 1
  • 13
  • 21

3 Answers3

2

That RSA key is for authentication, not for encryption! You should not use authentication key pairs for encryption (if you literally mean extracting the ssh key to store encrypted data, rather than to share the keypair with an X509 certificate); because the public and private operations or RSA commute. For example, if you use the same key for both:

  • encrypt = verify = public
  • decrypt = sign = private
  • public * private = private * public = 1

This sequence involving Alices signing and encryption key pair:

  • Bob to Alice: "here is a secret message": secretMsg := message * public
  • Eve to Alice: "please sign this for me": secretMsg
  • Alice to Eve: "okey dokey": toEve: signed := secretMsg * private
  • Eve:
    • signed
    • secretMsg * private
    • (message * public) * private
    • message * (public * private)
    • message * 1
    • message

Eve got the plaintext of a message that was sent encrypted to Alice. It is not exactly this simple because of formats; but it is well known that keypairs are either for signing/identity or for encryption, but should not be used for both uses.

Rob
  • 639
  • 3
  • 9
0

You can convert your existing ssh key to PKCS#8 with the following:

mv ~/.ssh/id_rsa{,.old}
umask 0077
openssl pkcs8 -topk8 -v2 des3 -in ~/.ssh/id_rsa.old -out ~/.ssh/id_rsa

After testing the converted key, you can then delete the original.

source

demure
  • 109
  • 5
  • Tried this (entering a blank password for the converted private key). When I tried to ssh (using the new private key), OS X displayed a GUI dialog asking for password (in parallel with the terminal asking for a password). Further suggestions? – forthrin May 29 '13 at 15:25
  • I haven't tried using it with a blank passphrase, but with a passphrase it works great on OS X (10.8.3) and CentOS. – demure May 29 '13 at 15:29
  • Tried it again and it worked. But your suggestion is for converting the private key, while the encryption requires the public key. How do I convert the public key? – forthrin May 29 '13 at 20:15
  • No, you should be encrypting with your private key (which only you have) and letting the recipient have access to your public key to decrypt the information. – Dave Mulligan Apr 16 '14 at 04:42
0

You can convert your SSH public key (id_rsa.pub) to a PEM public key file with the following Python script (cribbed from this blog post):

#!/usr/bin/python

# usage: sshpub2pem.py id_rsa.pub > id_rsa.pub.pem

import sys, base64, struct
from pyasn1.type import univ
from pyasn1.codec.der import encoder as der_encoder

keydata = base64.b64decode(
    open(sys.argv[1]).readlines()[0].split()[1])

parts = []
while keydata:
    dlen = struct.unpack('>I', keydata[:4])[0]
    data, keydata = keydata[4:dlen+4], keydata[4+dlen:]
    parts.append(data)

e_val = long(parts[1].encode('hex'), 16)
n_val = long(parts[2].encode('hex'), 16)

pkcs1_seq = univ.Sequence()
pkcs1_seq.setComponentByPosition(0, univ.Integer(n_val))
pkcs1_seq.setComponentByPosition(1, univ.Integer(e_val))
pkcs1_val = der_encoder.encode(pkcs1_seq)

head_seq = univ.Sequence()
head_seq.setComponentByPosition(0, univ.ObjectIdentifier('1.2.840.113549.1.1.1'))
head_seq.setComponentByPosition(1, univ.Null(''))

out_seq = univ.Sequence()
out_seq.setComponentByPosition(0, head_seq)
out_seq.setComponentByPosition(1, univ.BitString("'%s'H" % pkcs1_val.encode('hex')))

print '-----BEGIN PUBLIC KEY-----'
print base64.encodestring(der_encoder.encode(out_seq)).strip()
print '-----END PUBLIC KEY-----'

With id_rsa.pub.pem, you should be able to run

openssl rsautl -encrypt -pubin -inkey ~/.ssh/id_rsa.pub.pem -in sensitive-data -out encrypted-data

and decrypt with

openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in encrypted-data -out sensitive-data
kgutwin
  • 101
  • 2