comparison roundup/password.py @ 4089:eddb82d0964c

Add compatibility package to allow us to deal with Python versions 2.3..2.6. Outstanding issues noted in roundup/anypy/TODO.txt
author Richard Jones <richard@users.sourceforge.net>
date Thu, 12 Mar 2009 02:52:56 +0000
parents 822a2719b81b
children 1613754d2646
comparison
equal deleted inserted replaced
4088:34434785f308 4089:eddb82d0964c
19 19
20 """Password handling (encoding, decoding). 20 """Password handling (encoding, decoding).
21 """ 21 """
22 __docformat__ = 'restructuredtext' 22 __docformat__ = 'restructuredtext'
23 23
24 import sha, md5, re, string, random 24 import re, string, random
25 from roundup.anypy.hashlib_ import md5, sha1
25 try: 26 try:
26 import crypt 27 import crypt
27 except: 28 except ImportError:
28 crypt = None 29 crypt = None
29 pass
30 30
31 class PasswordValueError(ValueError): 31 class PasswordValueError(ValueError):
32 ''' The password value is not valid ''' 32 """ The password value is not valid """
33 pass 33 pass
34 34
35 def encodePassword(plaintext, scheme, other=None): 35 def encodePassword(plaintext, scheme, other=None):
36 '''Encrypt the plaintext password. 36 """Encrypt the plaintext password.
37 ''' 37 """
38 if plaintext is None: 38 if plaintext is None:
39 plaintext = "" 39 plaintext = ""
40 if scheme == 'SHA': 40 if scheme == 'SHA':
41 s = sha.sha(plaintext).hexdigest() 41 s = sha1(plaintext).hexdigest()
42 elif scheme == 'MD5': 42 elif scheme == 'MD5':
43 s = md5.md5(plaintext).hexdigest() 43 s = md5(plaintext).hexdigest()
44 elif scheme == 'crypt' and crypt is not None: 44 elif scheme == 'crypt' and crypt is not None:
45 if other is not None: 45 if other is not None:
46 salt = other 46 salt = other
47 else: 47 else:
48 saltchars = './0123456789'+string.letters 48 saltchars = './0123456789'+string.letters
57 def generatePassword(length=8): 57 def generatePassword(length=8):
58 chars = string.letters+string.digits 58 chars = string.letters+string.digits
59 return ''.join([random.choice(chars) for x in range(length)]) 59 return ''.join([random.choice(chars) for x in range(length)])
60 60
61 class Password: 61 class Password:
62 '''The class encapsulates a Password property type value in the database. 62 """The class encapsulates a Password property type value in the database.
63 63
64 The encoding of the password is one if None, 'SHA', 'MD5' or 'plaintext'. 64 The encoding of the password is one if None, 'SHA', 'MD5' or 'plaintext'.
65 The encodePassword function is used to actually encode the password from 65 The encodePassword function is used to actually encode the password from
66 plaintext. The None encoding is used in legacy databases where no 66 plaintext. The None encoding is used in legacy databases where no
67 encoding scheme is identified. 67 encoding scheme is identified.
77 1 77 1
78 >>> 'sekrit' == p 78 >>> 'sekrit' == p
79 1 79 1
80 >>> 'not sekrit' != p 80 >>> 'not sekrit' != p
81 1 81 1
82 ''' 82 """
83 83
84 default_scheme = 'SHA' # new encryptions use this scheme 84 default_scheme = 'SHA' # new encryptions use this scheme
85 pwre = re.compile(r'{(\w+)}(.+)') 85 pwre = re.compile(r'{(\w+)}(.+)')
86 86
87 def __init__(self, plaintext=None, scheme=None, encrypted=None): 87 def __init__(self, plaintext=None, scheme=None, encrypted=None):
88 '''Call setPassword if plaintext is not None.''' 88 """Call setPassword if plaintext is not None."""
89 if scheme is None: 89 if scheme is None:
90 scheme = self.default_scheme 90 scheme = self.default_scheme
91 if plaintext is not None: 91 if plaintext is not None:
92 self.setPassword (plaintext, scheme) 92 self.setPassword (plaintext, scheme)
93 elif encrypted is not None: 93 elif encrypted is not None:
96 self.scheme = self.default_scheme 96 self.scheme = self.default_scheme
97 self.password = None 97 self.password = None
98 self.plaintext = None 98 self.plaintext = None
99 99
100 def unpack(self, encrypted, scheme=None): 100 def unpack(self, encrypted, scheme=None):
101 '''Set the password info from the scheme:<encryted info> string 101 """Set the password info from the scheme:<encryted info> string
102 (the inverse of __str__) 102 (the inverse of __str__)
103 ''' 103 """
104 m = self.pwre.match(encrypted) 104 m = self.pwre.match(encrypted)
105 if m: 105 if m:
106 self.scheme = m.group(1) 106 self.scheme = m.group(1)
107 self.password = m.group(2) 107 self.password = m.group(2)
108 self.plaintext = None 108 self.plaintext = None
109 else: 109 else:
110 # currently plaintext - encrypt 110 # currently plaintext - encrypt
111 self.setPassword(encrypted, scheme) 111 self.setPassword(encrypted, scheme)
112 112
113 def setPassword(self, plaintext, scheme=None): 113 def setPassword(self, plaintext, scheme=None):
114 '''Sets encrypts plaintext.''' 114 """Sets encrypts plaintext."""
115 if scheme is None: 115 if scheme is None:
116 scheme = self.default_scheme 116 scheme = self.default_scheme
117 self.scheme = scheme 117 self.scheme = scheme
118 self.password = encodePassword(plaintext, scheme) 118 self.password = encodePassword(plaintext, scheme)
119 self.plaintext = plaintext 119 self.plaintext = plaintext
120 120
121 def __cmp__(self, other): 121 def __cmp__(self, other):
122 '''Compare this password against another password.''' 122 """Compare this password against another password."""
123 # check to see if we're comparing instances 123 # check to see if we're comparing instances
124 if isinstance(other, Password): 124 if isinstance(other, Password):
125 if self.scheme != other.scheme: 125 if self.scheme != other.scheme:
126 return cmp(self.scheme, other.scheme) 126 return cmp(self.scheme, other.scheme)
127 return cmp(self.password, other.password) 127 return cmp(self.password, other.password)
131 raise ValueError, 'Password not set' 131 raise ValueError, 'Password not set'
132 return cmp(self.password, encodePassword(other, self.scheme, 132 return cmp(self.password, encodePassword(other, self.scheme,
133 self.password)) 133 self.password))
134 134
135 def __str__(self): 135 def __str__(self):
136 '''Stringify the encrypted password for database storage.''' 136 """Stringify the encrypted password for database storage."""
137 if self.password is None: 137 if self.password is None:
138 raise ValueError, 'Password not set' 138 raise ValueError, 'Password not set'
139 return '{%s}%s'%(self.scheme, self.password) 139 return '{%s}%s'%(self.scheme, self.password)
140 140
141 def test(): 141 def test():

Roundup Issue Tracker: http://roundup-tracker.org/