Tuesday, November 27, 2012

Python 3 and PyObjC

My main programming platform is OS X 10.8 and Python 3 (currently Python 3.3). In earlier blog posts I have discussed installing and using PyCrypto in this environment. My next attempt was to find a GUI solutions for this platform. I usually prefer native approaches when programming, and for OS X the Cocoa framework is the native approach. To get access to this from Python we need a bridge, and the bridge is called PyObjC. At the home page PyObjC seems like a dead project. But Ronald Oussoren is still doing some development, including Python 3 support. It is not straight forward to compile and install PyObjC for Python 3, but Giacomo Lacava provides the necessary steps. To summarize I have done the installation using the following steps:

  1. Fetch the latest code from Ronald Oussoren:
    hg clone https://bitbucket.org/ronaldoussoren/pyobjc
    cd pyobjc
  2. Compile and install PyObjC core:
    (cd pyobjc-core && python3 setup.py install)
  3. Compile and install the Cocoa, CoreData and Quartz frameworks:
    for i in Cocoa Quartz CoreData; do
      (cd pyobjc-framework-$i && python3 setup.py install)
  4. Compile and install the rest of PyObjC (except the XgridFoundation framework):
    for i in pyobjc-framework-[^X]*; do
      (cd $i && python3 setup.py install)

So far everything seems to work OK. You need Mercurial (hg) to perform the first step.

Wednesday, November 14, 2012

AES and RSA PyCrypto examples with Python 3

Earlier today I wrote about installing PyCrypto for Python 3 on OS X 10.8. I will use the opportunity to provide a few examples using PyCrypto to do AES and RSA encryption and decryption. I have created 3 programs. The first one, pycrypto-mkkey.py [src], generates an RSA key and saves it in two different files. One including the private key and one with only the public key (using the .pub extension). The stored private key is password protected with the given password. The program is used like this:

python3 pycrypto-mkkey.py rsa-key "passwd"

The second program, pycrypto-encrypt.py [src], use the public RSA key to encrypt a file. Actually, the file is encrypted using AES, and the AES key is then encrypted with RSA. First the program generates a new fresh AES key and saves it to disk encrypted with the RSA key. Then it uses this AES key to encrypt the file (from stdin) and write the encrypted data to stdout. The program is used like this:

python3 pycrypto-encrypt.py rsa-key.pub aes-key < plain > cipher

The third program, pycrypto-decrypt.py [src], use the private RSA key to decrypt the file. Actually, the file is decrypted using AES, and the AES key is decrypted using RSA. First the program decrypts the AES key with the private RSA key. Then it uses this AES key to decrypt the file (from stdin) and write the decrypted data to stdout. The program is used like this:

python3 pycrypto-decrypt.py rsa-key aes-key "passwd" < cipher

Se also the README file distributed together with the programs.

PyCrypto with Python 3 on OS X 10.8

On an updated Mac (in my case 10.8.2) with an updated version of Xcode  (in my case 4.5.2) compiling and installing PyCrypto for Python 3 (in my case 3.3) is not just simply running the setup.py script. The latest release of PyCrypto is 2.6 and it supports Python 3 (it has supported Python 3 since version 2.4). But my earlier attempts using Python 3.2 on OS X 10.8 failed since it couldn't locate the SDKs and the SDK for OS X 10.6 was not installed (see issue14498 and related posts to solve these issues). In Python 3.3 this is not an issue any more, but using the correct version of the compiler is. To get the build process to use the correct compiler I tried with the following build command (llvm-gcc-4.2 is the compiler we want to use on current OS X):

> CC=llvm-gcc-4.2 python3.3 setup.py build

In the beginning of the build process it seemed to use llvm-gcc-4.2, but finally it failed with this message:

unable to execute gcc-4.2: No such file or directory

The obvious solution is the create a symlink from llvm-gcc-4.2 to gcc-4.2:

> sudo ln -s /usr/bin/llvm-gcc-4.2 /usr/bin/gcc-4.2
> python3.3 setup.py build

Success! Then install it:

> python3.3 setup.py install

And we are done. A small example using PyCrypto to encrypt a text with AES:

> python3.3
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 01:25:11)
GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from hashlib import sha256
>>> from Crypto import Random
>>> from Crypto.Cipher import AES
>>> from Crypto.Util import Counter
>>> pwd = "My secret password"
>>> key = sha256(pwd.encode()).digest()
>>> irv = Random.new().read(AES.block_size)
>>> icv = int.from_bytes(irv, "little")
>>> ctr = Counter.new(AES.block_size*8, initial_value=icv)
>>> cip = AES.new(key, AES.MODE_CTR, counter=ctr)
>>> msg = cip.encrypt('Attack at dawn'.encode())

To decrypt the message msg you need the password pwd or the key (the secret) and the initial counter value icv (can be public). The Python code to do this is left as an programming exercise for the reader (or you kan peek at pycryptex.py [src]).