def check_password(self, password, userid=None, login=None): if userid is None and login is None: raise ValueError("Must provide userid or login") if userid is not None: user = self.get(userid=userid) else: login = self._convert(login) userid = self.logins.get(login) user = self.get(login=login) if user['password'].startswith('SHA1:'): # old style password, need to upgrade but will check it first enc_password = get_sha_password(password) if strings_same(enc_password, user['password']): # upgrade this password... salt = get_random_string() user.update({'password': pbkdf2(password, salt), 'salt': salt}) self.data[userid] = user # trigger persistence return True else: return False else: # should be 'pbkdf2' encrypted now return strings_same(pbkdf2(password, user['salt']), user['password'])
def check_password(self, password, userid=None, login=None): if userid is None and login is None: raise ValueError("Must provide userid or login") if userid is not None: user = self.get(userid=userid) else: login = self._convert(login) userid = self.logins.get(login) user = self.get(login=login) if user['password'].startswith('SHA1:'): # old style password, need to upgrade but will check it first enc_password = get_sha_password(password) if strings_same(enc_password, user['password']): # upgrade this password... salt = get_random_string() user.update({ 'password': pbkdf2(password, salt), 'salt': salt }) self.data[userid] = user # trigger persistence return True else: return False else: # should be 'pbkdf2' encrypted now return strings_same( pbkdf2(password, user['salt']), user['password'])
def add(self, userid, login, cleartext_password, groups=None): self._upgrade() salt = get_random_string() encrypted_password = pbkdf2(cleartext_password, salt) if groups is None: groups = [] newgroups = set() for group in groups: group = self._convert(group) newgroups.add(group) userid = self._convert(userid) login = self._convert(login) info = { 'login': login, 'id': userid, 'salt': salt, 'password': encrypted_password, 'groups': newgroups } if userid in self.data: raise ValueError('User ID "%s" already exists' % userid) if login in self.logins: raise ValueError('Login "%s" already exists' % login) self.logins[login] = userid self.data[userid] = info for group in newgroups: userids = self.groups.get(group, set()) self.groups[group] = userids # trigger persistence userids.add(userid)
def decrypt_old(): key = pbkdf2(password, salt_and_iv, 1, 32) # only 1 iteration decrypted = aes256_ofb_decrypt(key, salt_and_iv, data) # OFB mode # The 16-byte last block, reversed, with all but the first byte of ISO 7816-4 padding removed: last_block = tuple(itertools.dropwhile(lambda x: x=="\0", decrypted[:15:-1])) padding = 17 - len(last_block) # ISO 7816-4 padding length return decrypted[:-padding] if 1 <= padding <= 16 and decrypted[-padding] == "\x80" and re.match('{\s*"guid"', decrypted) else None
def add(self, userid, login, cleartext_password, groups=None): self._upgrade() salt = get_random_string() encrypted_password = pbkdf2(cleartext_password, salt) if groups is None: groups = [] newgroups = set() for group in groups: group = self._convert(group) newgroups.add(group) userid = self._convert(userid) login = self._convert(login) info = { 'login': login, 'id': userid, 'salt': salt, 'password': encrypted_password, 'groups': newgroups} if userid in self.data: raise ValueError('User ID "%s" already exists' % userid) if login in self.logins: raise ValueError('Login "%s" already exists' % login) self.logins[login] = userid self.data[userid] = info for group in newgroups: userids = self.groups.get(group, set()) self.groups[group] = userids # trigger persistence userids.add(userid)
def change_password(self, userid, password): self._upgrade() userid = self._convert(userid) info = self.data[userid] if 'salt' not in info: info['salt'] = get_random_string() self.data[userid] = info # trigger persistence info['password'] = pbkdf2(password, info['salt'])
def decrypt_current(iter_count): key = pbkdf2(password, salt_and_iv, iter_count, 32) decrypted = aes256_cbc_decrypt(key, salt_and_iv, data) # CBC mode padding = ord(decrypted[-1:]) # ISO 10126 padding length # A bit fragile because it assumes the guid is in the first encrypted block, # although this has always been the case as of 6/2014 (since 12/2011) # As of May 2020, guid no longer appears in the first block, but tx_notes appears there instead return decrypted[:-padding] if 1 <= padding <= 16 and re.search(b"guid|tx_notes", decrypted) else None
def decrypt_current(iter_count): key = pbkdf2(password, salt_and_iv, iter_count, 32) decrypted = aes256_cbc_decrypt(key, salt_and_iv, data) # CBC mode padding = ord(decrypted[-1:]) # ISO 10126 padding length return decrypted[:-padding] if 1 <= padding <= 16 and re.match('{\s*"guid"', decrypted) else None