Python and public/private key encryption

Edit (7/20/08): If you are looking to get PyCrypto running under Windows with Python 2.5 I wrote a short guide located here . There are already installers for Python 2.3 and 2.4 on the PyCrypto Homepage

Edit (7/10/08): After noticing that this got some hits on google I rearranged the content so that the first part explains how I got public/private key encryption in python and the second part explains why I wanted encryption in the first place.

I was looking for an easy way to do public/private key encryption in python and I found it!

Enter ezPyCrypto! This package was actually able to generate and export a public key as a string AND import it back in. I should also mention that ezPyCrypto is merely a wrapper for PyCrypto. I have to say ezPyCrypto was quite uh… easy. Here is an example of how you would make a 1024 bit RSA key and export it to a string. It also demonstrates how to import that key and use it to encrypt a message:

from ezPyCrypto import key

myKey = key(1024) #defaults to RSA, 1024 is bits to encrypt with

#Just calling exportKey will export only the public key
publicKey = myKey.exportKey()

#print publicKey  

#Then to load it back in to a new key
myNewKey = key(0)
myNewKey.importKey(publicKey)

#Testing time!
testEnc = myNewKey.encString("cheesecake tastes yummy")

#You should see 'cheesecake tastes yummy'
print myKey.decString(testEnc)

Look at how easy that is! I am quite pleased that I will be able to continue my work, and have some good encryption. The one thing I will say is that ezPyCrypto does not seem like it has seen much development in a while, but oh well. As long as it works when it needs to I will not complain 🙂 Also I only tested this with python-2.5 so your mileage may vary. On to the back story…

So today, among other things, I was looking for some good python libraries to do public/private key encryption. I am trying to write a few scripts that help with the administration of the computers I work on for my college’s internet radio station. I started out writing them all in perl, but now I have most of them written in python. Currently I have written a small backend which starts up the basic services that the radio station requires. At present that consists of: shoutcast server, darkice, a script to monitor the listener counts, and lighttpd. This backend is capable of accepting clients over the network and displaying the basic running status of all these services (IE: running or not). Now, I would like to add the ability to remotely control the services. Hence I would have to have some way of authenticating users who want to log in.

Lets take a step back here. Some of you might be wondering why I don’t just administer everything with ssh. Indeed, this is how I did it for a year, and for someone like me (I loves me a good terminal) this was not a problem. However, I have to face the reality that someone will probably take over the station (at some point or another) who is not at one with bash. This is why I decided to start this project to help ease them into administering the servers, which rarely die anyway. Python and the Tkinter libs were great for this because they would be fully cross platform. Although I hate to admit it, I think the next admin will probably be a Windows user. I think being able to run the server from their dorm will go a long way in helping them accept the job.

Back to the main problem. To authenticate I don’t plan to have anything too breathtaking. The backend will be run as a normal user and I plan to use PAM to authenticate against the user that is running the backend. So I need to be able to send the password over the network! There are plenty of guides to public/private key encryption and a quick google search will provide an explanation better than I will ever be able to give as to how they work. I was able to find a few options. The first is the PyCrypto package. This package seemed quite sufficient but the lack of reasonable documentation for it made me have second thoughts. This isn’t something I want to mess up because we are sending sensitive data across the network. I had a look at the source code but got tired of trying to make sense of it.

Next I found a package called yawPyCrypto (yet another wrapper for python crypto). That seemed quite promising. I was able to work out a simple example where it would generate a 1024bit RSA key pair, and I could encrypt and decrypt a string with it. Only one problem… I could not successfully export and import the string from yawPyCrypto. This meant the server would not be able to the send the client its public key… LAME. Again, I poked around the source code, but I didn’t see anything obvious, and I was not about to reinvent the wheel here.

Then I discovered ezPyCrypto, which as you read from above, solved all my problems 🙂 I should also mention that on my Ubuntu machine I had to play around with the source code in ezPyCrypto to get it to import properly (remove references to variables it couldn’t find). Yeah… sounds stupid, but I was confident that what I was playing with was not related to public/private key encryption which is all I wanted.

I already fear that no matter how much I automate things there will be a problem. That is the way it goes however. I am hoping that I can polish off these scripts soon so I will not have to worry about radio station stuff until the beginning of the school year. I will most likely have more to say about these scripts and maybe a summery of everything I have done with them. That’s all for now though 😀

Advertisements

One Response to Python and public/private key encryption

  1. alef says:

    despite pycrypto has bad documentation, it’s pretty simple to work with pub/priv keys.
    an attribute ‘keydata’ gives you a list with names of other attributes, that can be used to construct new objects with the same key.

    >>> from Crypto.PublicKey import RSA
    >>> from Crypto.Util.randpool import RandomPool
    >>> pool = RandomPool()
    >>> pool.stir()
    >>> rsa = RSA.generate(128, pool.get_bytes)
    >>> rsa.keydata
    [‘n’, ‘e’, ‘d’, ‘p’, ‘q’, ‘u’]
    >>> rsa.n
    279399773274424719986414971211576830621L
    >>> rsa.e
    65537L
    >>> rsa.d
    49065596390059876130093992250788704781L

    once you keep all those values in a list or tuple, you can rsa.construct(list_or_tuple_with_numbers) and get a brand new object with both private or only public keys.
    that’s probably what ezcrypto is doing, however, i’ve never seen nor used it. 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: