Wednesday, October 2, 2013

Python-gnupg on a Raspberry Pi

Installing Python-gnupg ( on a Raspberry Pi shouldn't be much different than installing it on any other *nix system.  I'm documenting it here just for my own personal notes.

Install gnupg
This goes pretty much like you'd expect:

sudo apt-get install gnupg

Install Python-gnupg
First we need pip (and setup_tools, ...):
sudo apt-get install python-dev
wget -O - | sudo python
curl -O
sudo python

Now we can get gnupg:
sudo pip install python-gnupg

The following script creates a key using gnupg and installs that key in ~/.gnupg:
import gnupg

gpg = gnupg.GPG()

# generate a key
# first we need the input data
# really we shouldn't use key lengths shorter than 2048
input_data = gpg.gen_key_input(key_type="RSA", 
                               name_comment="Test key",
key = gpg.gen_key(input_data)
print key.fingerprint

Not Fast Enough
The script above works (and doesn't do much), but takes a long time to run.

pi@3-14159 ~/gnupgTesting $ time python 

real 6m4.396s
user 0m6.270s
sys 0m0.140s

This can be sped up by install rng-tools, however rng-tools requires a hardware random number source.

The Raspberry Pi has a hardware component for random number generation, but the software for it was just recently released.  (

You may need to completely update your Pi (see the instructions in the link above), but I was able to get away with just this (and adding bcm2708-rng to /etc/modules):
sudo modprobe bcm2708-rng
sudo apt-get install rng-tools

Now performance is much better.

pi@3-14159 ~/gnupgTesting $ time python 

real 0m5.524s
user 0m4.070s
sys 0m1.060s

Encrypting Data
In this example, '' is the intended recipient (we've previously imported Bob's key) and "hello world" is the data we're going to encrypt.

>>> import gnupg
>>> gpg = gnupg.GPG()
>>> encrypted_data = gpg.encrypt("hello world", "")
>>> print encrypted_data
Version: GnuPG v1.4.12 (GNU/Linux)


Decrypting Data
Here we decrypt the data sent to Bob (we must have Bob's private key installed for this to work).  Note the use of str() around 'encrypted_data'. That's because .encrypt doesn't return a string, but rather something that can be turned in to a string.

>>> decrypted_data = gpg.decrypt(str(encrypted_data))
>>> print decrypted_data
hello world

Pesky Details
In this example I had the private keys for both parties installed on my system. That's not realistic, but it's enough to become familiar with the software before starting to much around across systems.  Key distribution is often hard.  Regular gpg can be used to do the key management if you don't need to do it in python. It's probably easier that way.