Mercurial > p > roundup > code
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(): |
