Random ramblings about Mac, Python, TeX, programming, and more  |     |          |     |  

PyCrypto with Python 3 on OS X 10.8

November 14, 2012  |  os-x, crypto, programming, python

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]).

Last updated: November 14, 2012