Packaging fix: claim ownership of pkgdatadir.
[cnetworkmanager.git] / pbkdf2.py
blobfd22e73bf91d0e2adf87d8a47b0088f0f7cffe06
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 and modified for any purpose.
9 # Revision history
10 # v0.1 October 2004 - Initial release
11 # v0.2 8 March 2007 - Make usable with hashlib in Python 2.5 and use
12 # v0.3 "" the correct digest_size rather than always 20
14 import sys
15 import hmac
16 from binascii import hexlify, unhexlify
17 from struct import pack
18 try:
19 # only in python 2.5
20 import hashlib
21 sha = hashlib.sha1
22 md5 = hashlib.md5
23 sha256 = hashlib.sha256
24 except ImportError:
25 # fallback
26 import sha
27 import md5
29 # this is what you want to call.
30 def pbkdf2( password, salt, itercount, keylen, hashfn = sha ):
31 try:
32 # depending whether the hashfn is from hashlib or sha/md5
33 digest_size = hashfn().digest_size
34 except TypeError:
35 digest_size = hashfn.digest_size
36 # l - number of output blocks to produce
37 l = keylen / digest_size
38 if keylen % digest_size != 0:
39 l += 1
41 h = hmac.new( password, None, hashfn )
43 T = ""
44 for i in range(1, l+1):
45 T += pbkdf2_F( h, salt, itercount, i )
47 return T[0: keylen]
49 def xorstr( a, b ):
50 if len(a) != len(b):
51 raise "xorstr(): lengths differ"
53 ret = ''
54 for i in range(len(a)):
55 ret += chr(ord(a[i]) ^ ord(b[i]))
57 return ret
59 def prf( h, data ):
60 hm = h.copy()
61 hm.update( data )
62 return hm.digest()
64 # Helper as per the spec. h is a hmac which has been created seeded with the
65 # password, it will be copy()ed and not modified.
66 def pbkdf2_F( h, salt, itercount, blocknum ):
67 U = prf( h, salt + pack('>i',blocknum ) )
68 T = U
70 for i in range(2, itercount+1):
71 U = prf( h, U )
72 T = xorstr( T, U )
74 return T
77 def test():
78 # test vector from rfc3211
79 password = 'password'
80 salt = unhexlify( '1234567878563412' )
81 password = 'All n-entities must communicate with other n-entities via n-1 entiteeheehees'
82 itercount = 500
83 keylen = 16
84 ret = pbkdf2( password, salt, itercount, keylen )
85 hexret = ' '.join(map(lambda c: '%02x' % ord(c), ret)).upper()
86 print "key: %s" % hexret
87 print "expected: 6A 89 70 BF 68 C9 2C AE A8 4A 8D F2 85 10 85 86"
89 # from botan
90 password = unhexlify('6561696D72627A70636F706275736171746B6D77')
91 expect = 'C9A0B2622F13916036E29E7462E206E8BA5B50CE9212752EB8EA2A4AA7B40A4CC1BF'
92 salt = unhexlify('45248F9D0CEBCB86A18243E76C972A1F3B36772A')
93 keylen = 34
94 itercount = 100
95 ret = pbkdf2( password, salt, itercount, keylen )
96 hexret = hexlify(ret).upper()
97 print "key: %s" % hexret
98 print "expected: %s" % expect
102 if __name__ == '__main__':
103 test()