Commits

Daniel Holth  committed a665bb5

use dlitz's pbkdf2

  • Participants
  • Parent commits 97f9d99

Comments (0)

Files changed (4)

File cryptacular/pbkdf2/__init__.py

 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
+from __future__ import absolute_import
+
 __all__ = ['PBKDF2PasswordManager']
 
 import os
     import M2Crypto.EVP
     _pbkdf2 = M2Crypto.EVP.pbkdf2
 except (ImportError, AttributeError): # pragma NO COVERAGE
-    from . import pbkdf2
-    _pbkdf2 = pbkdf2.pbkdf2
+    from pbkdf2 import PBKDF2
+    def _pbkdf2(password, salt, rounds, keylen):
+        return PBKDF2(password, salt, rounds).read(keylen)
 
 class PBKDF2PasswordManager(object):
 

File cryptacular/pbkdf2/pbkdf2.py

-# A simple implementation of pbkdf2 using stock python modules. See RFC2898
-# for details. Basically, it derives a key from a password and salt.
-
-# Copyright 2004 Matt Johnston <matt @ ucc asn au>
-# Copyright 2009 Daniel Holth <dholth@fastmail.fm>
-# This code may be freely used and modified for any purpose.
-
-# Revision history
-# v0.1  October 2004    - Initial release
-# v0.2  8 March 2007    - Make usable with hashlib in Python 2.5 and use
-# v0.3  ""                 the correct digest_size rather than always 20
-# v0.4  Oct 2009        - Rescue from chandler svn, test and optimize. 
-
-import sys
-import hmac
-from struct import pack
-try:
-    # only in python 2.5
-    import hashlib
-    sha = hashlib.sha1
-    md5 = hashlib.md5
-    sha256 = hashlib.sha256
-except ImportError: # pragma: NO COVERAGE
-    # fallback
-    import sha
-    import md5
-
-# this is what you want to call.
-def pbkdf2( password, salt, itercount, keylen, hashfn = sha ):
-    try:
-        # depending whether the hashfn is from hashlib or sha/md5
-        digest_size = hashfn().digest_size
-    except TypeError: # pragma: NO COVERAGE
-        digest_size = hashfn.digest_size
-    # l - number of output blocks to produce
-    l = keylen / digest_size
-    if keylen % digest_size != 0:
-        l += 1
-
-    h = hmac.new( password, None, hashfn )
-
-    T = ""
-    for i in range(1, l+1):
-        T += pbkdf2_F( h, salt, itercount, i )
-
-    return T[0: keylen]
-
-def xorstr( a, b ):
-    if len(a) != len(b):
-        raise ValueError("xorstr(): lengths differ")
-    return ''.join((chr(ord(x)^ord(y)) for x, y in zip(a, b)))
-
-def prf( h, data ):
-    hm = h.copy()
-    hm.update( data )
-    return hm.digest()
-
-# Helper as per the spec. h is a hmac which has been created seeded with the
-# password, it will be copy()ed and not modified.
-def pbkdf2_F( h, salt, itercount, blocknum ):
-    U = prf( h, salt + pack('>i',blocknum ) )
-    T = U
-
-    for i in range(2, itercount+1):
-        U = prf( h, U )
-        T = xorstr( T, U )
-
-    return T

File cryptacular/pbkdf2/test_pbkdf2.py

 from nose.tools import eq_, raises, assert_not_equal
 from cryptacular.pbkdf2 import PBKDF2PasswordManager
 from binascii import hexlify, unhexlify
-from pbkdf2 import *
+
+import cryptacular.pbkdf2
+pbkdf2 = cryptacular.pbkdf2._pbkdf2
 
 def test():
     # test vector from rfc3211
-    password = 'password'
     salt = unhexlify( '1234567878563412' )
     password = 'All n-entities must communicate with other n-entities via n-1 entiteeheehees'
     itercount = 500
     hexret = hexlify(ret).upper()
     eq_(hexret, expect)
 
-    eq_(xorstr('foo', 'foo'), '\x00\x00\x00')
-
 def test_passwordmanager():
     from base64 import urlsafe_b64decode
     manager = PBKDF2PasswordManager()
     eq_(hash, "$p5k2$1$ZxK4ZBJCfQg=$Kexp0NAVgxlDwoA-TS34o8o2Okg=")
     assert manager.check(hash, text)
 
-@raises(ValueError)
-def test_xorstr():
-    xorstr('foo', 'quux')
-
 if __name__ == "__main__":
     test() # pragma: NO COVERAGE
       namespace_packages = ['cryptacular'],
       include_package_data=True,
       zip_safe=False,
-      install_requires = ['setuptools'],
+      install_requires = ['pbkdf2', 'setuptools'],
       tests_require = tests_require,
       extras_require = dict(test=tests_require),
       test_suite = 'nose.collector',