How to do PGP in Python (generate keys, encrypt/decrypt) How to do PGP in Python (generate keys, encrypt/decrypt) python python

How to do PGP in Python (generate keys, encrypt/decrypt)


You don't need PyCrypto or PyMe, fine though those packages may be - you will have all kinds of problems building under Windows. Instead, why not avoid the rabbit-holes and do what I did? Use gnupg 1.4.9. You don't need to do a full installation on end-user machines - just gpg.exe and iconv.dll from the distribution are sufficient, and you just need to have them somewhere in the path or accessed from your Python code using a full pathname. No changes to the registry are needed, and everything (executables and data files) can be confined to a single folder if you want.

There's a module GPG.py which was originally written by Andrew Kuchling, improved by Richard Jones and improved further by Steve Traugott. It's available here, but as-is it's not suitable for Windows because it uses os.fork(). Although originally part of PyCrypto, it is completely independent of the other parts of PyCrypto and needs only gpg.exe/iconv.dll in order to work.

I have a version (gnupg.py) derived from Traugott's GPG.py, which uses the subprocess module. It works fine under Windows, at least for my purposes - I use it to do the following:

  • Key management - generation, listing, export etc.
  • Import keys from an external source (e.g. public keys received from a partner company)
  • Encrypt and decrypt data
  • Sign and verify signatures

The module I've got is not ideal to show right now, because it includes some other stuff which shouldn't be there - which means I can't release it as-is at the moment. At some point, perhaps in the next couple of weeks, I hope to be able to tidy it up, add some more unit tests (I don't have any unit tests for sign/verify, for example) and release it (either under the original PyCrypto licence or a similar commercial-friendly license). If you can't wait, go with Traugott's module and modify it yourself - it wasn't too much work to make it work with the subprocess module.

This approach was a lot less painful than the others (e.g. SWIG-based solutions, or solutions which require building with MinGW/MSYS), which I considered and experimented with. I've used the same (gpg.exe/iconv.dll) approach with systems written in other languages, e.g. C#, with equally painless results.

P.S. It works with Python 2.4 as well as Python 2.5 and later. Not tested with other versions, though I don't foresee any problems.


After a LOT of digging, I found a package that worked for me. Although it is said to support the generation of keys, I didn't test it. However I did manage to decrypt a message that was encrypted using a GPG public key. The advantage of this package is that it does not require a GPG executable file on the machine, and is a Python based implementation of the OpenPGP (rather than a wrapper around the executable). I created the private and public keys using GPG4win and kleopatra for windowsSee my code below.

import pgpyemsg = pgpy.PGPMessage.from_file(<path to the file from the client that was encrypted using your public key>)key,_  = pgpy.PGPKey.from_file(<path to your private key>)with key.unlock(<your private key passpharase>):    print (key.decrypt(emsg).message)

Although the question is very old. I hope this helps future users.


PyCrypto supports PGP - albeit you should test it to make sure that it works to your specifications.

Although documentation is hard to come by, if you look through Util/test.py (the module test script), you can find a rudimentary example of their PGP support:

if verbose: print '  PGP mode:',obj1=ciph.new(password, ciph.MODE_PGP, IV)obj2=ciph.new(password, ciph.MODE_PGP, IV)start=time.time()ciphertext=obj1.encrypt(str)plaintext=obj2.decrypt(ciphertext)end=time.time()if (plaintext!=str):    die('Error in resulting plaintext from PGP mode')print_timing(256, end-start, verbose)del obj1, obj2

Futhermore, PublicKey/pubkey.py provides for the following relevant methods:

def encrypt(self, plaintext, K)def decrypt(self, ciphertext):def sign(self, M, K):def verify (self, M, signature):def can_sign (self):    """can_sign() : bool    Return a Boolean value recording whether this algorithm can    generate signatures.  (This does not imply that this    particular key object has the private information required to    to generate a signature.)    """    return 1