Updated pbkdf2.py to the newest upstream version
[cnetworkmanager.git] / pbkdf2.py
blob2b7dd078c8a4327b4a60673e0050f8ab8a3622f4
1 #!/usr/bin/env python
3 # A simple implementation of pbkdf2 using stock python modules. See RFC2898
4 # for details. Basically, it derives a key from a password and salt.
6 # (c) 2004 Matt Johnston <matt @ ucc asn au>
7 # This code may be freely used, distributed, relicensed, and modified for any
8 # purpose.
10 # Revision history
11 # v0.1 October 2004 - Initial release
12 # v0.2 8 March 2007 - Make usable with hashlib in Python 2.5 and use
13 # v0.3 "" the correct digest_size rather than always 20
14 # v0.4 13 March 2009 - Mention distribution and relicensing in the copyright
16 import sys
17 import hmac
18 from binascii import hexlify, unhexlify
19 from struct import pack
20 try:
21 # only in python 2.5
22 import hashlib
23 sha = hashlib.sha1
24 md5 = hashlib.md5
25 sha256 = hashlib.sha256
26 except ImportError:
27 # fallback
28 import sha
29 import md5
31 # this is what you want to call.
32 def pbkdf2( password, salt, itercount, keylen, hashfn = sha ):
33 try:
34 # depending whether the hashfn is from hashlib or sha/md5
35 digest_size = hashfn().digest_size
36 except TypeError:
37 digest_size = hashfn.digest_size
38 # l - number of output blocks to produce
39 l = keylen / digest_size
40 if keylen % digest_size != 0:
41 l += 1
43 h = hmac.new( password, None, hashfn )
45 T = ""
46 for i in range(1, l+1):
47 T += pbkdf2_F( h, salt, itercount, i )
49 return T[0: keylen]
51 def xorstr( a, b ):
52 if len(a) != len(b):
53 raise "xorstr(): lengths differ"
55 ret = ''
56 for i in range(len(a)):
57 ret += chr(ord(a[i]) ^ ord(b[i]))
59 return ret
61 def prf( h, data ):
62 hm = h.copy()
63 hm.update( data )
64 return hm.digest()
66 # Helper as per the spec. h is a hmac which has been created seeded with the
67 # password, it will be copy()ed and not modified.
68 def pbkdf2_F( h, salt, itercount, blocknum ):
69 U = prf( h, salt + pack('>i',blocknum ) )
70 T = U
72 for i in range(2, itercount+1):
73 U = prf( h, U )
74 T = xorstr( T, U )
76 return T
79 def test():
80 # test vector from rfc3211
81 password = 'password'
82 salt = unhexlify( '1234567878563412' )
83 password = 'All n-entities must communicate with other n-entities via n-1 entiteeheehees'
84 itercount = 500
85 keylen = 16
86 ret = pbkdf2( password, salt, itercount, keylen )
87 hexret = ' '.join(map(lambda c: '%02x' % ord(c), ret)).upper()
88 print "key: %s" % hexret
89 print "expected: 6A 89 70 BF 68 C9 2C AE A8 4A 8D F2 85 10 85 86"
91 # from botan
92 password = unhexlify('6561696D72627A70636F706275736171746B6D77')
93 expect = 'C9A0B2622F13916036E29E7462E206E8BA5B50CE9212752EB8EA2A4AA7B40A4CC1BF'
94 salt = unhexlify('45248F9D0CEBCB86A18243E76C972A1F3B36772A')
95 keylen = 34
96 itercount = 100
97 ret = pbkdf2( password, salt, itercount, keylen )
98 hexret = hexlify(ret).upper()
99 print "key: %s" % hexret
100 print "expected: %s" % expect
104 if __name__ == '__main__':
105 test()