]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add property based test for nsec3hash utility
authorEvan Hunt <each@isc.org>
Wed, 30 Apr 2025 00:03:47 +0000 (17:03 -0700)
committerPetr Špaček <pspacek@isc.org>
Tue, 29 Jul 2025 08:00:36 +0000 (10:00 +0200)
Check the correctness of NSEC3 hash generation by generating random
combinations of name, salt, and iterations and comparing the outputs
of the nsec3hash tool against the dnspython nsec3_hash function
for the same inputs.

bin/tests/system/tools/tests_tools_nsec3hash.py

index 67709f271e8a097d26bdf5e0ff56dddee21eb123..f1384d6ceb5d6d6e0fa2a324e970286a0ed231ee 100644 (file)
@@ -15,6 +15,12 @@ import subprocess
 import pytest
 
 import isctest
+from isctest.hypothesis.strategies import dns_names
+
+from hypothesis import strategies, given, settings
+
+from dns.dnssectypes import NSEC3Hash
+import dns.dnssec
 
 NSEC3HASH = os.environ.get("NSEC3HASH")
 
@@ -120,3 +126,51 @@ def test_nsec3_missing_args(args):
 def test_nsec3_bad_option():
     with pytest.raises(subprocess.CalledProcessError):
         isctest.run.cmd([NSEC3HASH, "-?"])
+
+
+@given(
+    domain=dns_names(),
+    it=strategies.integers(min_value=0, max_value=65535),
+    salt_bytes=strategies.binary(min_size=0, max_size=255),
+)
+def test_nsec3hash_acceptable_values(domain, it, salt_bytes) -> None:
+    if not salt_bytes:
+        salt_text = "-"
+    else:
+        salt_text = salt_bytes.hex()
+    # calculate the hash using dnspython:
+    hash1 = dns.dnssec.nsec3_hash(
+        domain, salt=salt_bytes, iterations=it, algorithm=NSEC3Hash.SHA1
+    )
+
+    # calculate the hash using nsec3hash:
+    output = isctest.run.cmd(
+        [NSEC3HASH, salt_text, "1", str(it), str(domain)]
+    ).stdout.decode("ascii")
+    hash2 = output.partition(" ")[0]
+
+    assert hash1 == hash2
+
+
+@settings(max_examples=5)
+@given(
+    domain=dns_names(),
+    it=strategies.integers(min_value=0, max_value=65535),
+    salt_bytes=strategies.binary(min_size=256),
+)
+def test_nsec3hash_salt_too_long(domain, it, salt_bytes) -> None:
+    salt_text = salt_bytes.hex()
+    with pytest.raises(subprocess.CalledProcessError):
+        isctest.run.cmd([NSEC3HASH, salt_text, "1", str(it), str(domain)])
+
+
+@settings(max_examples=5)
+@given(
+    domain=dns_names(),
+    it=strategies.integers(min_value=65536),
+    salt_bytes=strategies.binary(min_size=0, max_size=255),
+)
+def test_nsec3hash_too_many_iterations(domain, it, salt_bytes) -> None:
+    salt_text = salt_bytes.hex()
+    with pytest.raises(subprocess.CalledProcessError):
+        isctest.run.cmd([NSEC3HASH, salt_text, "1", str(it), str(domain)])