diff --git a/pyproject.toml b/pyproject.toml index 55114db..7791d4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ dependencies = [ "pycryptodome >=3.17.0", "pydantic >=2.5.0", "httpx >=0.24.1", + 'typing_extensions; python_version<"3.12"', ] [dev-dependencies] test = [ diff --git a/src/vaultwarden/models/bitwarden.py b/src/vaultwarden/models/bitwarden.py index 17de6c0..45a09bd 100644 --- a/src/vaultwarden/models/bitwarden.py +++ b/src/vaultwarden/models/bitwarden.py @@ -1,12 +1,12 @@ import dataclasses import datetime +import sys from typing import ( TYPE_CHECKING, Annotated, Any, Generic, Literal, - Self, TypeVar, Union, cast, @@ -37,6 +37,12 @@ if TYPE_CHECKING: import vaultwarden.clients.bitwarden +if sys.version_info < (3, 12): + from typing_extensions import Self +else: + from typing import Self + + # Pydantic models for Bitwarden data structures T = TypeVar("T", bound="BitwardenBaseModel") @@ -67,8 +73,8 @@ def api_client(self) -> BitwardenAPIClient: def decode_bytes( value: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo ) -> bytes: - context: dict = cast(dict, info.context) - keys: list[bytes] = cast(list[bytes], context.get("cctx")) + context: dict = cast("dict", info.context) + keys: list[bytes] = cast("list[bytes]", context.get("cctx")) for key in keys[::-1]: try: return decrypt(handler(value), key) @@ -227,8 +233,8 @@ def set_key( info: ValidationInfo, ) -> Self: if (key := data.get("key")) is not None: - context = cast(dict, info.context) - cctx = cast(list[bytes], context.get("cctx")) + context = cast("dict", info.context) + cctx = cast("list[bytes]", context.get("cctx")) cctx.append(decrypt(key, cctx[0])) diff --git a/src/vaultwarden/utils/crypto.py b/src/vaultwarden/utils/crypto.py index 9353546..7b47841 100644 --- a/src/vaultwarden/utils/crypto.py +++ b/src/vaultwarden/utils/crypto.py @@ -118,19 +118,19 @@ def is_encrypted(cipher_string): return True -def make_master_key(password_: str, salt_: str, kdf: "vaultwarden.models.bitwarden.Kdf"): +def make_master_key(password: str, salt: str, kdf: "vaultwarden.models.bitwarden.Kdf"): import vaultwarden.models.bitwarden - assert isinstance(salt_, str) - assert isinstance(password_, str) + assert isinstance(salt, str) + assert isinstance(password, str) - password = password_.encode("utf-8") - salt = salt_.lower().encode("utf-8") + password_: bytes = password.encode("utf-8") + salt_: bytes = salt.lower().encode("utf-8") match kdf.Kdf: case vaultwarden.models.bitwarden.KdfType.Pbkdf2: assert kdf.KdfIterations is not None - return pbkdf2_hmac("sha256", password, salt, kdf.KdfIterations) + return pbkdf2_hmac("sha256", password_, salt_, kdf.KdfIterations) case vaultwarden.models.bitwarden.KdfType.Argon2id: # c.f. # https://github.com/vaultwarden/vw_web_builds/blob/355bddc6c9d5c110e55fe74c5fcfa86ddd85572c/libs/common/src/platform/services/key-generation.service.ts#L55-L75 @@ -138,9 +138,9 @@ def make_master_key(password_: str, salt_: str, kdf: "vaultwarden.models.bitward assert kdf.KdfIterations is not None assert kdf.KdfMemory is not None assert kdf.KdfParallelism is not None - hsalt = hashlib.new("sha256", salt).digest() + hsalt = hashlib.new("sha256", salt_).digest() v = argon2.low_level.hash_secret_raw( - password, + password_, hsalt, time_cost=kdf.KdfIterations, memory_cost=kdf.KdfMemory * 1024, diff --git a/tests/fixtures/server/db.sqlite3 b/tests/fixtures/server/db.sqlite3 index 93b7dcd..bf27515 100644 --- a/tests/fixtures/server/db.sqlite3 +++ b/tests/fixtures/server/db.sqlite3 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:45f2e69202615d295d7687fa4752e189ad29cae7de8852101f93f0b679cbcab6 -size 262144 +oid sha256:c8c11a331ba097f1644b297885cd09b4ac5fc975ed5605176c880bc5cf08a813 +size 245760