From d8ea2b2c3227a91f8a2984754b7cafce1b79007e Mon Sep 17 00:00:00 2001 From: Michael Thorp <28820955+Sarcastic-Pharm@users.noreply.github.com> Date: Sat, 28 Feb 2026 09:53:05 +1000 Subject: [PATCH 1/2] Added fingerprint equality check. Removed collected_at from fingerprint encoding components for consistency between fingerprints. Corrected getting-started.md. --- docs/guides/getting-started.md | 18 +++++++++--------- .../device_fingerprinting.py | 12 +++++++++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docs/guides/getting-started.md b/docs/guides/getting-started.md index 34be762..118c0f7 100644 --- a/docs/guides/getting-started.md +++ b/docs/guides/getting-started.md @@ -132,7 +132,7 @@ from device_fingerprinting import DeviceFingerprintGenerator generator = DeviceFingerprintGenerator() # Generate a device fingerprint -fingerprint = generator.generate_device_fingerprint() +fingerprint = generator.generate() # The fingerprint is a unique identifier for this device print(f"Device fingerprint: {fingerprint}") @@ -149,9 +149,9 @@ A key property of device fingerprints is that they remain stable: ```python # Generate fingerprint multiple times -fp1 = generator.generate_device_fingerprint() -fp2 = generator.generate_device_fingerprint() -fp3 = generator.generate_device_fingerprint() +fp1 = generator.generate() +fp2 = generator.generate() +fp3 = generator.generate() # All should be identical assert fp1 == fp2 == fp3 @@ -182,7 +182,7 @@ else: ```python # Generate and store a fingerprint securely -fingerprint = generator.generate_device_fingerprint() +fingerprint = generator.generate() # Store with encryption generator.store_fingerprint("my_device", fingerprint) @@ -243,7 +243,7 @@ Register a device for later verification: ```python def register_device(user_id, device_name): generator = DeviceFingerprintGenerator() - fingerprint = generator.generate_device_fingerprint() + fingerprint = generator.generate() # Store with user context storage_key = f"user_{user_id}_device_{device_name}" @@ -262,7 +262,7 @@ Verify that a request comes from a known device: ```python def verify_device(user_id, device_name): generator = DeviceFingerprintGenerator() - current_fingerprint = generator.generate_device_fingerprint() + current_fingerprint = generator.generate() # Retrieve stored fingerprint storage_key = f"user_{user_id}_device_{device_name}" @@ -315,7 +315,7 @@ Create device-bound secrets that only work on the original device: ```python def create_bound_secret(secret_data): generator = ProductionFingerprintGenerator() - fingerprint = generator.generate_device_fingerprint() + fingerprint = generator.generate() # Bind secret to device bound_token = generator.create_device_binding({ @@ -327,7 +327,7 @@ def create_bound_secret(secret_data): def verify_bound_secret(bound_token): generator = ProductionFingerprintGenerator() - current_fingerprint = generator.generate_device_fingerprint() + current_fingerprint = generator.generate() # Verify on the same device is_valid = generator.verify_device_binding(bound_token, current_fingerprint) diff --git a/src/device_fingerprinting/device_fingerprinting.py b/src/device_fingerprinting/device_fingerprinting.py index 6578d71..ac943b1 100644 --- a/src/device_fingerprinting/device_fingerprinting.py +++ b/src/device_fingerprinting/device_fingerprinting.py @@ -2288,7 +2288,11 @@ def reset_device_id(storage_key: str = "device_id") -> None: @dataclass class FingerprintResult: """Represents the result of a fingerprint generation.""" - + # Equality method to compare fingerprints + def __eq__(self, other): + if not isinstance(other, FingerprintResult): + return False + return self.fingerprint == other.fingerprint fingerprint: str method: str components: Dict[str, Any] @@ -2321,8 +2325,10 @@ def generate(self, method: FingerprintMethod = FingerprintMethod.STABLE) -> Fing confidence = 0.9 else: raise ValueError(f"Unsupported fingerprint method: {method}") - - fingerprint_data = json.dumps(components, sort_keys=True).encode("utf-8") + # Remove timestamp from fingerprint components to ensure consistent fingerprints generated at different times + fingerprint_components = components.copy() + fingerprint_components.pop("collected_at", None) + fingerprint_data = json.dumps(fingerprint_components, sort_keys=True).encode("utf-8") return FingerprintResult( fingerprint=base64.b64encode(fingerprint_data).decode("utf-8"), From 6eca63e2c169a965a0e721bafe84a164b747263f Mon Sep 17 00:00:00 2001 From: Johnson Date: Sat, 28 Feb 2026 12:06:19 +0000 Subject: [PATCH 2/2] Apply Black formatting to fix CI failure --- src/device_fingerprinting/device_fingerprinting.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/device_fingerprinting/device_fingerprinting.py b/src/device_fingerprinting/device_fingerprinting.py index 47fdeb7..3a4b5ca 100644 --- a/src/device_fingerprinting/device_fingerprinting.py +++ b/src/device_fingerprinting/device_fingerprinting.py @@ -2290,11 +2290,13 @@ def reset_device_id(storage_key: str = "device_id") -> None: @dataclass class FingerprintResult: """Represents the result of a fingerprint generation.""" + # Equality method to compare fingerprints def __eq__(self, other): if not isinstance(other, FingerprintResult): return False return self.fingerprint == other.fingerprint + fingerprint: str method: str components: Dict[str, Any]