user1686149
user1686149

Reputation: 55

How to make an GnuPG key compatible with Pycrypto

I'm trying to use a key generated via GPG with RSA encryption (this part is changeable, GnuPG and Pycrypto aren't) to encrypt a file, but I'm having trouble actually importing the key. I'm currently using code like this:

key = cryptoRSA.importKey(public_key)
cipher = PKCS1_OAEP.new(RSAkey)
file = open(filename)

However, this is throwing an error because my public_key is not a DER structure. Is there a way I can generate a public_key that WOULD work with Pycrypto? I'm really new to cryptography, so I'm not entirely sure on what to do about this problem at all.

Upvotes: 4

Views: 1842

Answers (2)

Craig McQueen
Craig McQueen

Reputation: 43426

I have done this using openpgp2pem from Monkeysphere.

First, get the key's ID by doing:

gpg --list-secret-keys

Note the 8-digit hexadecimal ID of the key. E.g. 0123ABCD

Public key

To get a public key:

gpg --export --no-armor 0123ABCD | openpgp2pem 0123ABCD

Secret key

To get a secret key using openpgp2pem, unfortunately the GPG key must have its passphrase removed. Do this by:

gpg --edit-key 0123ABCD

Then use the passwd command to remove its passphrase. (You could do this on a copy of the original GPG homedir, and use the gpg --homedir option to operate on the temporary copy.)

Then after that you can do:

gpg --export-secret-keys --no-armor 0123ABCD | openpgp2pem 0123ABCD

Convert PEM for use by Python

In practice, I've found that the secret key so generated can be directly used in PyCrypto using:

from Crypto.PublicKey import RSA

with open('secret-key.pem', 'rb') as f:
    key_secret = RSA.importKey(f.read())

However, the public key generated above could not be directly used with PyCrypto (it's missing something). I had to generate a PyCrypto-compatible PEM as follows:

from base64 import b64encode, b64decode
from Crypto.PublicKey import RSA

def publicpem2pycrypto(public_pem):
    public_64 = public_pem.replace(b"-----BEGIN RSA PUBLIC KEY-----", b"").replace(b"-----END RSA PUBLIC KEY-----", b"")
    pub_der = b64decode(public_64)
    key_pub = RSA.importKey(pub_der)
    key_public_export = key_pub.exportKey('PEM')
    print(key_public_export.decode('ascii'))
    with open('public-key.pem', 'wb') as f:
        f.write(key_public_export)
    print("Saved to public-key.pem")

Or, it could be generated from the secret key as follows. Also, the following allows a passphrase to be added back on to the secret key:

from base64 import b64encode, b64decode
from Crypto.PublicKey import RSA

def secretpem2pycrypto(out_secret_filename, out_public_filename, secret_pem, passphrase=None):
    secret_64 = secret_pem.replace(b"-----BEGIN RSA PRIVATE KEY-----", b"").replace(b"-----END RSA PRIVATE KEY-----", b"")
    secret_64 = secret_64.replace(b"\n", b"")
    #print(secret_64)
    secret_der = b64decode(secret_64)
    #print(b64encode(secret_der))
    key_secret = RSA.importKey(secret_der)
    key_secret_export = key_secret.exportKey('PEM', passphrase=passphrase)
    key_public_export = key_secret.publickey().exportKey('PEM')
    print(key_secret_export.decode('ascii'))
    with open(out_secret_filename, 'wb') as f:
        f.write(key_secret_export)
    print("Saved to " + out_secret_filename)
    if True:
        print()
        print(key_public_export.decode('ascii'))
        with open(out_public_filename, 'wb') as f:
            f.write(key_public_export)
        print("Saved to " + out_public_filename)

Once the secret key has a passphrase added, it can be used via:

from Crypto.PublicKey import RSA

with open('secret-key.pem', 'rb') as f:
    key_secret = RSA.importKey(f.read(), passphrase="xxxxxxxxxxxxxxxxxxxx")

Upvotes: 3

Daniele Ricci
Daniele Ricci

Reputation: 581

A GPG key is much more than a "normal" key; it adds a lot of other stuff. You should convert it first to a standard OpenSSL PEM key using the openpgp2pem tool in monkeysphere.

Upvotes: 2

Related Questions