Mercurial > p > roundup > code
comparison roundup/password.py @ 5378:35ea9b1efc14
Python 3 preparation: "raise" syntax.
Changing "raise Exception, value" to "raise Exception(value)".
Tool-assisted patch. Particular cases to check carefully are the one
place in frontends/ZRoundup/ZRoundup.py where a string exception
needed to be fixed, and the one in roundup/cgi/client.py involving
raising an exception with a traceback (requires three-argument form of
raise in Python 2, which as I understand it requires exec() to avoid a
Python 3 syntax error).
| author | Joseph Myers <jsm@polyomino.org.uk> |
|---|---|
| date | Tue, 24 Jul 2018 21:39:58 +0000 |
| parents | 91954be46a66 |
| children | a391a071d045 |
comparison
equal
deleted
inserted
replaced
| 5377:12fe83f90f0d | 5378:35ea9b1efc14 |
|---|---|
| 111 salt = salt.encode("utf-8") | 111 salt = salt.encode("utf-8") |
| 112 if keylen > 40: | 112 if keylen > 40: |
| 113 #NOTE: pbkdf2 allows up to (2**31-1)*20 bytes, | 113 #NOTE: pbkdf2 allows up to (2**31-1)*20 bytes, |
| 114 # but m2crypto has issues on some platforms above 40, | 114 # but m2crypto has issues on some platforms above 40, |
| 115 # and such sizes aren't needed for a password hash anyways... | 115 # and such sizes aren't needed for a password hash anyways... |
| 116 raise ValueError, "key length too large" | 116 raise ValueError("key length too large") |
| 117 if rounds < 1: | 117 if rounds < 1: |
| 118 raise ValueError, "rounds must be positive number" | 118 raise ValueError("rounds must be positive number") |
| 119 return _pbkdf2(password, salt, rounds, keylen) | 119 return _pbkdf2(password, salt, rounds, keylen) |
| 120 | 120 |
| 121 class PasswordValueError(ValueError): | 121 class PasswordValueError(ValueError): |
| 122 """ The password value is not valid """ | 122 """ The password value is not valid """ |
| 123 pass | 123 pass |
| 129 if isinstance(pbkdf2, unicode): | 129 if isinstance(pbkdf2, unicode): |
| 130 pbkdf2 = pbkdf2.encode("ascii") | 130 pbkdf2 = pbkdf2.encode("ascii") |
| 131 try: | 131 try: |
| 132 rounds, salt, digest = pbkdf2.split("$") | 132 rounds, salt, digest = pbkdf2.split("$") |
| 133 except ValueError: | 133 except ValueError: |
| 134 raise PasswordValueError, "invalid PBKDF2 hash (wrong number of separators)" | 134 raise PasswordValueError("invalid PBKDF2 hash (wrong number of separators)") |
| 135 if rounds.startswith("0"): | 135 if rounds.startswith("0"): |
| 136 raise PasswordValueError, "invalid PBKDF2 hash (zero-padded rounds)" | 136 raise PasswordValueError("invalid PBKDF2 hash (zero-padded rounds)") |
| 137 try: | 137 try: |
| 138 rounds = int(rounds) | 138 rounds = int(rounds) |
| 139 except ValueError: | 139 except ValueError: |
| 140 raise PasswordValueError, "invalid PBKDF2 hash (invalid rounds)" | 140 raise PasswordValueError("invalid PBKDF2 hash (invalid rounds)") |
| 141 raw_salt = h64decode(salt) | 141 raw_salt = h64decode(salt) |
| 142 return rounds, salt, raw_salt, digest | 142 return rounds, salt, raw_salt, digest |
| 143 | 143 |
| 144 def encodePassword(plaintext, scheme, other=None, config=None): | 144 def encodePassword(plaintext, scheme, other=None, config=None): |
| 145 """Encrypt the plaintext password. | 145 """Encrypt the plaintext password. |
| 155 if config: | 155 if config: |
| 156 rounds = config.PASSWORD_PBKDF2_DEFAULT_ROUNDS | 156 rounds = config.PASSWORD_PBKDF2_DEFAULT_ROUNDS |
| 157 else: | 157 else: |
| 158 rounds = 10000 | 158 rounds = 10000 |
| 159 if rounds < 1000: | 159 if rounds < 1000: |
| 160 raise PasswordValueError, "invalid PBKDF2 hash (rounds too low)" | 160 raise PasswordValueError("invalid PBKDF2 hash (rounds too low)") |
| 161 raw_digest = pbkdf2(plaintext, raw_salt, rounds, 20) | 161 raw_digest = pbkdf2(plaintext, raw_salt, rounds, 20) |
| 162 return "%d$%s$%s" % (rounds, salt, h64encode(raw_digest)) | 162 return "%d$%s$%s" % (rounds, salt, h64encode(raw_digest)) |
| 163 elif scheme == 'SSHA': | 163 elif scheme == 'SSHA': |
| 164 if other: | 164 if other: |
| 165 raw_other = b64decode(other) | 165 raw_other = b64decode(other) |
| 182 salt = random.choice(saltchars) + random.choice(saltchars) | 182 salt = random.choice(saltchars) + random.choice(saltchars) |
| 183 s = crypt.crypt(plaintext, salt) | 183 s = crypt.crypt(plaintext, salt) |
| 184 elif scheme == 'plaintext': | 184 elif scheme == 'plaintext': |
| 185 s = plaintext | 185 s = plaintext |
| 186 else: | 186 else: |
| 187 raise PasswordValueError, 'Unknown encryption scheme %r'%scheme | 187 raise PasswordValueError('Unknown encryption scheme %r'%scheme) |
| 188 return s | 188 return s |
| 189 | 189 |
| 190 def generatePassword(length=12): | 190 def generatePassword(length=12): |
| 191 chars = string.letters+string.digits | 191 chars = string.letters+string.digits |
| 192 password = [random.choice(chars) for x in range(length)] | 192 password = [random.choice(chars) for x in range(length)] |
| 231 return cmp(self.scheme, other.scheme) | 231 return cmp(self.scheme, other.scheme) |
| 232 return cmp(self.password, other.password) | 232 return cmp(self.password, other.password) |
| 233 | 233 |
| 234 # assume password is plaintext | 234 # assume password is plaintext |
| 235 if self.password is None: | 235 if self.password is None: |
| 236 raise ValueError, 'Password not set' | 236 raise ValueError('Password not set') |
| 237 return cmp(self.password, encodePassword(other, self.scheme, | 237 return cmp(self.password, encodePassword(other, self.scheme, |
| 238 self.password or None)) | 238 self.password or None)) |
| 239 | 239 |
| 240 class Password(JournalPassword): | 240 class Password(JournalPassword): |
| 241 """The class encapsulates a Password property type value in the database. | 241 """The class encapsulates a Password property type value in the database. |
| 299 self.plaintext = None | 299 self.plaintext = None |
| 300 else: | 300 else: |
| 301 # currently plaintext - encrypt | 301 # currently plaintext - encrypt |
| 302 self.setPassword(encrypted, scheme, config=config) | 302 self.setPassword(encrypted, scheme, config=config) |
| 303 if strict and self.scheme not in self.known_schemes: | 303 if strict and self.scheme not in self.known_schemes: |
| 304 raise PasswordValueError, "Unknown encryption scheme: %r" % (self.scheme,) | 304 raise PasswordValueError("Unknown encryption scheme: %r" % (self.scheme,)) |
| 305 | 305 |
| 306 def setPassword(self, plaintext, scheme=None, config=None): | 306 def setPassword(self, plaintext, scheme=None, config=None): |
| 307 """Sets encrypts plaintext.""" | 307 """Sets encrypts plaintext.""" |
| 308 if scheme is None: | 308 if scheme is None: |
| 309 scheme = self.default_scheme | 309 scheme = self.default_scheme |
| 312 self.plaintext = plaintext | 312 self.plaintext = plaintext |
| 313 | 313 |
| 314 def __str__(self): | 314 def __str__(self): |
| 315 """Stringify the encrypted password for database storage.""" | 315 """Stringify the encrypted password for database storage.""" |
| 316 if self.password is None: | 316 if self.password is None: |
| 317 raise ValueError, 'Password not set' | 317 raise ValueError('Password not set') |
| 318 return '{%s}%s'%(self.scheme, self.password) | 318 return '{%s}%s'%(self.scheme, self.password) |
| 319 | 319 |
| 320 def test(): | 320 def test(): |
| 321 # SHA | 321 # SHA |
| 322 p = Password('sekrit') | 322 p = Password('sekrit') |
