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

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

You dont 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 dont 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.

Theres a module GPG.py which was originally written by Andrew Kuchling, improved by Richard Jones and improved further by Steve Traugott. Its available here, but as-is its 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 Traugotts 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 Ive got is not ideal to show right now, because it includes some other stuff which shouldnt be there – which means I cant 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 dont 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 cant wait, go with Traugotts module and modify it yourself – it wasnt 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. Ive 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 dont 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 didnt 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 windows
See my code below.

import pgpy
emsg = 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.

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

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

Leave a Reply

Your email address will not be published.