4

Well, today I was checking the hashlib module in python, but then I found something that I still can't figure out.

Inside this python module, there is an import that I can't follow. I goes like this:

def __get_builtin_constructor(name):
    if name in ('SHA1', 'sha1'):
        import _sha
        return _sha.new

I tried to import the _sha module from a python shell, but is seems that it cannot be reached that way.My first guess is that it's a C module, but I'm not sure.

So tell me guys, do you know where is that module? How do they import it?

FernandoEscher
  • 2,700
  • 2
  • 25
  • 27

2 Answers2

9

Actually, the _sha module is provided by shamodule.c and _md5 is provided by md5module.c and md5.c and both will be built only when your Python is not compiled with OpenSSL by default.

You can find the details in setup.py in your Python Source tarball.

    if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
        # The _sha module implements the SHA1 hash algorithm.
        exts.append( Extension('_sha', ['shamodule.c']) )
        # The _md5 module implements the RSA Data Security, Inc. MD5
        # Message-Digest Algorithm, described in RFC 1321.  The
        # necessary files md5.c and md5.h are included here.
        exts.append( Extension('_md5',
                        sources = ['md5module.c', 'md5.c'],
                        depends = ['md5.h']) )

Most often, your Python is built with Openssl library and in that case, those functions are provided by the OpenSSL libraries itself.

Now, if you want them separately, then you can build your Python without OpenSSL or better yet, you can build with pydebug option and have them.

From your Python Source tarball:

./configure --with-pydebug
make

And there you go:

>>> import _sha
[38571 refs]
>>> _sha.__file__
'/home/senthil/python/release27-maint/build/lib.linux-i686-2.7-pydebug/_sha.so'
[38573 refs]
Senthil Kumaran
  • 47,625
  • 13
  • 83
  • 117
5

Seems that you're python installation has sha compiled inside _haslib instead of _sha (both C modules). From hashlib.py in python 2.6:

import _haslib:
    .....
except ImportError:
    # We don't have the _hashlib OpenSSL module?
    # use the built in legacy interfaces via a wrapper function
    new = __py_new

    # lookup the C function to use directly for the named constructors
    md5 = __get_builtin_constructor('md5')
    sha1 = __get_builtin_constructor('sha1')
    sha224 = __get_builtin_constructor('sha224')
    sha256 = __get_builtin_constructor('sha256')
    sha384 = __get_builtin_constructor('sha384')
    sha512 = __get_builtin_constructor('sha512')
albertov
  • 2,242
  • 19
  • 15
  • So, is there a way I can do an import of that module form outside hashlib? – FernandoEscher Jan 04 '11 at 02:59
  • yep, import `_hashlib` (note the underscore). `_sha` seems to be a legacy interface which isn't installed if `_hashlib` is. Out of curiosity, why do you want to import it for? – albertov Jan 04 '11 at 03:08
  • I was curious XD. But now I get how it works! Thanks for the help! :P – FernandoEscher Jan 04 '11 at 03:17
  • albertov, Fernando: _hashlib and _sha are exclusive. I pointed out to the mechanism which is actually taking place in setup.py. Although, _hashlib will be built only when you don't have proper openssl. I am afraid, if this not a totally correct answer. – Senthil Kumaran Jan 04 '11 at 03:22
  • Actually, Senthil's answer is more complete. I misread the "How do they import it?" part of Fernando's post as "How do I import it" so my answer wanted to point out that "you can't, since you're installation provides it via the _hashlib module". Your answer is much more informative, hence my upvote. Thanks :) – albertov Jan 04 '11 at 03:31
  • Any python name prefix by an underscore is considered to be private and can be changed between any versions with little or no notice. You should not rely upon these names at all. – Nathan Ernst Jan 04 '11 at 03:33
  • Thanks for your responses! You pretty much covered everything. – FernandoEscher Jan 04 '11 at 03:33