Remove hypothesis tests for config dependence of derived passphrases in `vault`
Marco Ricci

Marco Ricci commited on 2025-08-14 22:47:35
Zeige 2 geänderte Dateien mit 3 Einfügungen und 83 Löschungen.


Sadly, there exist configurations and pairs of master passphrases (and
presumably, pairs of services names as well) that lead to the same
derived passphrase.  (These are typically short-length derived
passphrases with strongly restricted character sets.)  Once `hypothesis`
has found such a set of inputs, its example database will cause it to
keep rediscovering that example.

Ideally, we want to express that given enough entropy through the
configuration, the chance of deriving the same passphrases with two
different master passphrases or two different service names becomes very
small.  However, this is a statement about the function's state space,
and I do not know how to sensibly express this statement in a unit-test
or `hypothesis`-test-compatible way, short of perhaps enumerating the
whole state space (which is computationally infeasible).  So, we remove
these tests of config dependence; they are clearly non-functional and
misleading.
... ...
@@ -788,7 +788,7 @@ class TestPhraseBasic:
788 788
 
789 789
     @pytest.mark.xfail(
790 790
         True,
791
-        reason='not implemented yet',
791
+        reason="not implemented yet",
792 792
         raises=NotImplementedError,
793 793
         strict=True,
794 794
     )
... ...
@@ -800,7 +800,7 @@ class TestPhraseBasic:
800 800
 
801 801
     @pytest.mark.xfail(
802 802
         True,
803
-        reason='not implemented yet',
803
+        reason="not implemented yet",
804 804
         raises=NotImplementedError,
805 805
         strict=True,
806 806
     )
... ...
@@ -1544,7 +1544,7 @@ class TestExportConfigValid:
1544 1544
 
1545 1545
     @pytest.mark.xfail(
1546 1546
         True,
1547
-        reason='not implemented yet',
1547
+        reason="not implemented yet",
1548 1548
         raises=NotImplementedError,
1549 1549
         strict=True,
1550 1550
     )
... ...
@@ -262,46 +262,6 @@ class TestPhraseDependence:
262 262
             phrase=phrases[0], service=service
263 263
         ) != vault.Vault.create_hash(phrase=phrases[1], service=service)
264 264
 
265
-    @hypothesis.given(
266
-        phrases=strategies.lists(
267
-            strategies.text(
268
-                strategies.characters(min_codepoint=32, max_codepoint=126),
269
-                min_size=1,
270
-                max_size=32,
271
-            ),
272
-            min_size=2,
273
-            max_size=2,
274
-            unique=True,
275
-        ),
276
-        config=hypothesis_machinery.vault_full_service_config(),
277
-        service=strategies.text(
278
-            strategies.characters(min_codepoint=32, max_codepoint=126),
279
-            min_size=1,
280
-            max_size=32,
281
-        ),
282
-    )
283
-    def test_phrase_dependence_with_config(
284
-        self,
285
-        phrases: list[str],
286
-        config: dict[str, int],
287
-        service: bytes,
288
-    ) -> None:
289
-        """The derived passphrase is dependent on the master passphrase."""
290
-        try:
291
-            assert vault.Vault(phrase=phrases[0], **config).generate(
292
-                service
293
-            ) != vault.Vault(phrase=phrases[1], **config).generate(service)
294
-        except ValueError as exc:  # pragma: no cover
295
-            # The service configuration strategy attempts to only
296
-            # generate satisfiable configurations.  It is possible,
297
-            # though rare, that this fails, and that unsatisfiability is
298
-            # only recognized when actually deriving a passphrase.  In
299
-            # that case, reject the generated configuration.
300
-            hypothesis.assume("no allowed characters left" not in exc.args)
301
-            # Otherwise it's a genuine bug in the test case or the
302
-            # implementation, and should be raised.
303
-            raise
304
-
305 265
 
306 266
 class TestServiceNameDependence:
307 267
     """Test the dependence of the internal hash on the service name."""
... ...
@@ -329,46 +289,6 @@ class TestServiceNameDependence:
329 289
             phrase=phrase, service=services[0]
330 290
         ) != vault.Vault.create_hash(phrase=phrase, service=services[1])
331 291
 
332
-    @hypothesis.given(
333
-        phrase=strategies.text(
334
-            strategies.characters(min_codepoint=32, max_codepoint=126),
335
-            min_size=1,
336
-            max_size=32,
337
-        ),
338
-        config=hypothesis_machinery.vault_full_service_config(),
339
-        services=strategies.lists(
340
-            strategies.text(
341
-                strategies.characters(min_codepoint=32, max_codepoint=126),
342
-                min_size=1,
343
-                max_size=32,
344
-            ),
345
-            min_size=2,
346
-            max_size=2,
347
-            unique=True,
348
-        ),
349
-    )
350
-    def test_service_name_dependence_with_config(
351
-        self,
352
-        phrase: str,
353
-        config: dict[str, int],
354
-        services: list[bytes],
355
-    ) -> None:
356
-        """The derived passphrase is dependent on the service name."""
357
-        try:
358
-            assert vault.Vault(phrase=phrase, **config).generate(
359
-                services[0]
360
-            ) != vault.Vault(phrase=phrase, **config).generate(services[1])
361
-        except ValueError as exc:  # pragma: no cover
362
-            # The service configuration strategy attempts to only
363
-            # generate satisfiable configurations.  It is possible,
364
-            # though rare, that this fails, and that unsatisfiability is
365
-            # only recognized when actually deriving a passphrase.  In
366
-            # that case, reject the generated configuration.
367
-            hypothesis.assume("no allowed characters left" not in exc.args)
368
-            # Otherwise it's a genuine bug in the test case or the
369
-            # implementation, and should be raised.
370
-            raise
371
-
372 292
 
373 293
 class TestInterchangablePhrases:
374 294
     """Test the interchangability of certain master passphrases."""
375 295