fix password digests
This commit is contained in:
parent
7eb06b150e
commit
76e65def2c
|
@ -1,7 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
import os
|
||||
import re
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List
|
||||
|
@ -57,6 +59,21 @@ class Password(Field):
|
|||
salt_size = 4
|
||||
digest_size = 16
|
||||
|
||||
@classmethod
|
||||
def is_digest(cls, passwd: str):
|
||||
if not passwd:
|
||||
return False
|
||||
offset = 2 * cls.salt_size # each byte is 2 hex chars
|
||||
try:
|
||||
if passwd[offset] != ":":
|
||||
return False
|
||||
digest = passwd[offset + 1 :]
|
||||
if len(digest) != cls.digest_size * 2:
|
||||
return False
|
||||
return re.match(r"^[0-9a-f]+$", digest)
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_digest(cls, passwd: str, salt: bytes = None):
|
||||
if not salt:
|
||||
|
@ -68,10 +85,10 @@ class Password(Field):
|
|||
def compare(cls, passwd: value_type, stored: value_type):
|
||||
stored_salt, stored_digest = stored.split(":")
|
||||
input_digest, input_salt = cls.get_digest(passwd, bytes.fromhex(stored_salt))
|
||||
return input_digest == stored_digest
|
||||
return hmac.compare_digest(input_digest, stored_digest)
|
||||
|
||||
def before_insert(self, value: value_type, db: TinyDB, record: Record) -> None:
|
||||
if value:
|
||||
if value and not self.__class__.is_digest(value):
|
||||
digest, salt = self.__class__.get_digest(value)
|
||||
record[self.name] = f"{salt}:{digest}"
|
||||
|
||||
|
|
|
@ -123,6 +123,9 @@ def test_search(db):
|
|||
def test_password(db):
|
||||
user = db.save(examples.User(name="john", email="john@foo", password="fnord"))
|
||||
|
||||
# make sure we don't compute the digest on an existing digest
|
||||
user = db.save(user)
|
||||
|
||||
assert ":" in user.password
|
||||
assert user.password != "fnord"
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user