<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY%2Fgen_fingerprint_corpus.py</id>
	<title>The Principia Machina/TPC-PY/gen fingerprint corpus.py - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY%2Fgen_fingerprint_corpus.py"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;action=history"/>
	<updated>2026-10-21T12:08:29Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4829&amp;oldid=prev</id>
		<title>BFP Rauch: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4829&amp;oldid=prev"/>
		<updated>2026-09-30T02:11:02Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:11, 30 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4828:rev-4829 --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4828&amp;oldid=prev</id>
		<title>BFP Rauch: TPC-PY source gen_fingerprint_corpus.py (0.1.0), SHA-256 6c9f79908e1902e5; conformed TPS 0.4.0; PROPOSED, not declared (TPC-PY 0.2.0)</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4828&amp;oldid=prev"/>
		<updated>2026-09-30T02:10:58Z</updated>

		<summary type="html">&lt;p&gt;TPC-PY source gen_fingerprint_corpus.py (0.1.0), SHA-256 6c9f79908e1902e5; conformed TPS 0.4.0; PROPOSED, not declared (TPC-PY 0.2.0)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:10, 30 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l237&quot;&gt;Line 237:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 237:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        &amp;quot;test_key&amp;quot;: &amp;quot;K_TEST = 000102...1f (32 bytes), a TEST KEY, never a real secret (D127.1)&amp;quot;,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        &amp;quot;test_key&amp;quot;: &amp;quot;K_TEST = 000102...1f (32 bytes), a TEST KEY, never a real secret (D127.1)&amp;quot;,&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        &amp;quot;counts&amp;quot;: counts, &amp;quot;cases&amp;quot;: cases}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;        &amp;quot;counts&amp;quot;: counts, &amp;quot;cases&amp;quot;: cases}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;with open(os.path.join(here, &quot;fingerprint_corpus.json&quot;), &quot;w&quot;, encoding=&quot;utf-8&quot;) as f:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;with open(os.path.join(here, &quot;fingerprint_corpus.json&quot;), &quot;w&quot;, encoding=&quot;utf-8&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&quot;, newline=&quot;\n&lt;/ins&gt;&quot;) as f:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     json.dump(out, f, indent=1, ensure_ascii=False)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     json.dump(out, f, indent=1, ensure_ascii=False)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     f.write(&amp;quot;\n&amp;quot;)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     f.write(&amp;quot;\n&amp;quot;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;print(&amp;quot;fingerprint_corpus.json&amp;quot;, len(cases), &amp;quot;cases&amp;quot;, counts)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;print(&amp;quot;fingerprint_corpus.json&amp;quot;, len(cases), &amp;quot;cases&amp;quot;, counts)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4149:rev-4828:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4149&amp;oldid=prev</id>
		<title>BFP Rauch: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4149&amp;oldid=prev"/>
		<updated>2026-09-28T04:32:53Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 04:32, 28 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4148:rev-4149 --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4148&amp;oldid=prev</id>
		<title>BFP Rauch: TPC-PY source gen_fingerprint_corpus.py (0.1.0), SHA-256 625f7bfc9c1fb79d; conformed TPS 0.3.0; PROPOSED, not declared (CO-8)</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/gen_fingerprint_corpus.py&amp;diff=4148&amp;oldid=prev"/>
		<updated>2026-09-27T15:43:18Z</updated>

		<summary type="html">&lt;p&gt;TPC-PY source gen_fingerprint_corpus.py (0.1.0), SHA-256 625f7bfc9c1fb79d; conformed TPS 0.3.0; PROPOSED, not declared (CO-8)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;quot;&amp;quot;&amp;quot;gen_fingerprint_corpus 0.1.0: builds fingerprint_corpus.json for&lt;br /&gt;
tpc_fingerprint 0.1.0. Deterministic. TEST-KEY vectors only: the fixed&lt;br /&gt;
TEST KEY is the 32 bytes 00 01 ... 1f, the per-agent salts are fixed&lt;br /&gt;
patterns, no real secret exists here (D127.1: TPC-PY fixes the encoding&lt;br /&gt;
and computes no real fingerprint). Expectations are computed&lt;br /&gt;
INDEPENDENTLY here with hashlib and hmac over the D97 netstring written&lt;br /&gt;
out by hand (never through the module), then asserted equal to the&lt;br /&gt;
module&amp;#039;s render before pinning; RFC 5869&amp;#039;s own test cases 1-3 (Expand&lt;br /&gt;
step) pin the HKDF.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import hashlib&lt;br /&gt;
import hmac&lt;br /&gt;
import json&lt;br /&gt;
import os&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
here = os.path.dirname(os.path.abspath(__file__))&lt;br /&gt;
sys.path.insert(0, here)&lt;br /&gt;
from tpc_fingerprint import run_case  # noqa: E402&lt;br /&gt;
&lt;br /&gt;
cases = []&lt;br /&gt;
K = &amp;quot;000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f&amp;quot;&lt;br /&gt;
K2 = &amp;quot;ff&amp;quot; * 32&lt;br /&gt;
K3 = &amp;quot;0b&amp;quot; * 32&lt;br /&gt;
SALT = &amp;quot;00112233445566778899aabbccddeeff&amp;quot;&lt;br /&gt;
SALT2 = &amp;quot;0f&amp;quot; * 16&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def add(name, fn, args, hand=False, check=None):&lt;br /&gt;
    got = run_case(fn, args)&lt;br /&gt;
    if check is not None:&lt;br /&gt;
        assert got == check, (name, got, check)&lt;br /&gt;
    cases.append({&amp;quot;name&amp;quot;: name, &amp;quot;fn&amp;quot;: fn, &amp;quot;args&amp;quot;: args, &amp;quot;hand_checked&amp;quot;: hand,&lt;br /&gt;
                  &amp;quot;expected&amp;quot;: got})&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def ind_expand(prk_hex, info, length):&lt;br /&gt;
    key = bytes.fromhex(prk_hex)&lt;br /&gt;
    out = b&amp;quot;&amp;quot;&lt;br /&gt;
    t = b&amp;quot;&amp;quot;&lt;br /&gt;
    i = 1&lt;br /&gt;
    while len(out) &amp;lt; length:&lt;br /&gt;
        t = hmac.new(key, t + info + bytes([i]), hashlib.sha256).digest()&lt;br /&gt;
        out += t&lt;br /&gt;
        i += 1&lt;br /&gt;
    return out[:length]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def ind_ns(items):&lt;br /&gt;
    return b&amp;quot;&amp;quot;.join(str(len(b)).encode() + b&amp;quot;:&amp;quot; + b for b in items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def ind_fp(k, f):&lt;br /&gt;
    kfp = ind_expand(k, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32)&lt;br /&gt;
    pre = ind_ns([b&amp;quot;TPX-FINGERPRINT&amp;quot;, b&amp;quot;1&amp;quot;, str(f[&amp;quot;sponsor_user_id&amp;quot;]).encode(),&lt;br /&gt;
                  f[&amp;quot;sponsor_registration&amp;quot;].encode(), str(f[&amp;quot;agent_user_id&amp;quot;]).encode(),&lt;br /&gt;
                  f[&amp;quot;agent_registration&amp;quot;].encode(), bytes.fromhex(f[&amp;quot;salt&amp;quot;]),&lt;br /&gt;
                  str(f[&amp;quot;cert_serial&amp;quot;]).encode(), f[&amp;quot;cert_time&amp;quot;].encode()])&lt;br /&gt;
    fp = hmac.new(kfp, pre, hashlib.sha256).hexdigest()&lt;br /&gt;
    kid = hmac.new(bytes.fromhex(k), b&amp;quot;TPX-KEY-ID&amp;quot;, hashlib.sha256).hexdigest()[:16]&lt;br /&gt;
    return &amp;quot;%s|%s|%s|%s&amp;quot; % (fp, fp[:16], kid, pre.hex())&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# ---- hkdf (RFC 5869 test cases 1-3, the Expand step) -----------------------&lt;br /&gt;
add(&amp;quot;H01 RFC 5869 test case 1&amp;quot;, &amp;quot;hkdf&amp;quot;,&lt;br /&gt;
    {&amp;quot;prk&amp;quot;: &amp;quot;077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5&amp;quot;, &amp;quot;info&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
     &amp;quot;info_hex&amp;quot;: &amp;quot;f0f1f2f3f4f5f6f7f8f9&amp;quot;, &amp;quot;length&amp;quot;: 42}, True,&lt;br /&gt;
    &amp;quot;3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865&amp;quot;)&lt;br /&gt;
add(&amp;quot;H02 RFC 5869 test case 2 (82 bytes, three blocks)&amp;quot;, &amp;quot;hkdf&amp;quot;,&lt;br /&gt;
    {&amp;quot;prk&amp;quot;: &amp;quot;06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244&amp;quot;, &amp;quot;info&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
     &amp;quot;info_hex&amp;quot;: &amp;quot;b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff&amp;quot;,&lt;br /&gt;
     &amp;quot;length&amp;quot;: 82}, True,&lt;br /&gt;
    &amp;quot;b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87&amp;quot;)&lt;br /&gt;
add(&amp;quot;H03 RFC 5869 test case 3 (empty info)&amp;quot;, &amp;quot;hkdf&amp;quot;,&lt;br /&gt;
    {&amp;quot;prk&amp;quot;: &amp;quot;19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04&amp;quot;, &amp;quot;info&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
     &amp;quot;info_hex&amp;quot;: &amp;quot;&amp;quot;, &amp;quot;length&amp;quot;: 42}, True,&lt;br /&gt;
    &amp;quot;8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8&amp;quot;)&lt;br /&gt;
add(&amp;quot;H04 the purpose key under the test key&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;TPX-FINGERPRINT-1&amp;quot;,&lt;br /&gt;
                                                       &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;H05 length 1&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 1}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;x&amp;quot;, 1).hex())&lt;br /&gt;
add(&amp;quot;H06 length 32&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;x&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;H07 length 33 (two blocks)&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 33}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;x&amp;quot;, 33).hex())&lt;br /&gt;
add(&amp;quot;H08 length 8160 (the maximum)&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 8160}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;x&amp;quot;, 8160).hex())&lt;br /&gt;
add(&amp;quot;H09 a UTF-8 info&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;café&amp;quot;, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    ind_expand(K, &amp;quot;café&amp;quot;.encode(), 32).hex())&lt;br /&gt;
add(&amp;quot;H10 a 64-byte PRK&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K + K2, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    ind_expand(K + K2, b&amp;quot;x&amp;quot;, 32).hex())&lt;br /&gt;
for i in range(6):&lt;br /&gt;
    add(&amp;quot;H%02d sweep info %d&amp;quot; % (11 + i, i), &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K3, &amp;quot;info&amp;quot;: &amp;quot;info-%d&amp;quot; % i,&lt;br /&gt;
                                                     &amp;quot;length&amp;quot;: 16 + 7 * i}, False)&lt;br /&gt;
add(&amp;quot;H17 length 0 refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 0}, True, &amp;quot;ERROR:length&amp;quot;)&lt;br /&gt;
add(&amp;quot;H18 length 8161 refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 8161}, True,&lt;br /&gt;
    &amp;quot;ERROR:length&amp;quot;)&lt;br /&gt;
add(&amp;quot;H19 a 31-byte PRK refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K[:62], &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;H20 uppercase hex refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K.upper(), &amp;quot;info&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;H21 info not a string refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: 5, &amp;quot;length&amp;quot;: 32}, True,&lt;br /&gt;
    &amp;quot;ERROR:info&amp;quot;)&lt;br /&gt;
add(&amp;quot;H22 odd info_hex refused&amp;quot;, &amp;quot;hkdf&amp;quot;, {&amp;quot;prk&amp;quot;: K, &amp;quot;info&amp;quot;: &amp;quot;&amp;quot;, &amp;quot;info_hex&amp;quot;: &amp;quot;abc&amp;quot;, &amp;quot;length&amp;quot;: 32},&lt;br /&gt;
    True, &amp;quot;ERROR:info&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# ---- key_fp / agent_key / key_id / call_sign --------------------------------&lt;br /&gt;
add(&amp;quot;F01 K_FP under the test key&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K}, True,&lt;br /&gt;
    ind_expand(K, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;F02 K_FP under ff..ff&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K2}, True, ind_expand(K2, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;F03 K_FP under 0b..0b&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K3}, True, ind_expand(K3, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
for i in range(9):&lt;br /&gt;
    k = (&amp;quot;%02x&amp;quot; % (i * 17)) * 32&lt;br /&gt;
    add(&amp;quot;F%02d sweep key %02x&amp;quot; % (4 + i, i * 17), &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: k}, True,&lt;br /&gt;
        ind_expand(k, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;F13 a 33-byte key refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K + &amp;quot;00&amp;quot;}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F14 a 31-byte key refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K[:62]}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F15 non-hex refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;zz&amp;quot; * 32}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F16 key not a string refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: 5}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F17 key_fp differs from key_id&amp;#039;s input use&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;a1&amp;quot; * 32}, True,&lt;br /&gt;
    ind_expand(&amp;quot;a1&amp;quot; * 32, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
add(&amp;quot;F18 key with a trailing space refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: K[:63] + &amp;quot; &amp;quot;}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F19 empty key refused&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;&amp;quot;}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;F20 key 00..00&amp;quot;, &amp;quot;key_fp&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;00&amp;quot; * 32}, True,&lt;br /&gt;
    ind_expand(&amp;quot;00&amp;quot; * 32, b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, 32).hex())&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def ind_agent_key(k, uid, salt):&lt;br /&gt;
    info = ind_ns([b&amp;quot;TPX-FINGERPRINT-1&amp;quot;, str(uid).encode(), bytes.fromhex(salt)])&lt;br /&gt;
    return ind_expand(k, info, 32).hex()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
add(&amp;quot;A01 per-agent key (speculation 12.1&amp;#039;s form)&amp;quot;, &amp;quot;agent_key&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 7, &amp;quot;salt&amp;quot;: SALT}, True, ind_agent_key(K, 7, SALT))&lt;br /&gt;
add(&amp;quot;A02 another salt&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 7, &amp;quot;salt&amp;quot;: SALT2}, True,&lt;br /&gt;
    ind_agent_key(K, 7, SALT2))&lt;br /&gt;
add(&amp;quot;A03 another user&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 8, &amp;quot;salt&amp;quot;: SALT}, True,&lt;br /&gt;
    ind_agent_key(K, 8, SALT))&lt;br /&gt;
for i in range(12):&lt;br /&gt;
    add(&amp;quot;A%02d sweep&amp;quot; % (4 + i), &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K3, &amp;quot;agent_user_id&amp;quot;: 100 + i * 37,&lt;br /&gt;
                                                &amp;quot;salt&amp;quot;: (&amp;quot;%02x&amp;quot; % (i * 23 % 256)) * 16}, True,&lt;br /&gt;
        ind_agent_key(K3, 100 + i * 37, (&amp;quot;%02x&amp;quot; % (i * 23 % 256)) * 16))&lt;br /&gt;
add(&amp;quot;A16 user_id 0 refused&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 0, &amp;quot;salt&amp;quot;: SALT}, True,&lt;br /&gt;
    &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;A17 salt 15 bytes refused&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 7, &amp;quot;salt&amp;quot;: SALT[:30]},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;A18 salt 17 bytes refused&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: 7, &amp;quot;salt&amp;quot;: SALT + &amp;quot;00&amp;quot;},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;A19 key malformed refused&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;agent_user_id&amp;quot;: 7, &amp;quot;salt&amp;quot;: SALT}, True,&lt;br /&gt;
    &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;A20 user_id a string refused&amp;quot;, &amp;quot;agent_key&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;agent_user_id&amp;quot;: &amp;quot;7&amp;quot;, &amp;quot;salt&amp;quot;: SALT},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
add(&amp;quot;I01 key id under the test key&amp;quot;, &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: K}, True,&lt;br /&gt;
    hmac.new(bytes.fromhex(K), b&amp;quot;TPX-KEY-ID&amp;quot;, hashlib.sha256).hexdigest()[:16])&lt;br /&gt;
add(&amp;quot;I02 key id under ff..ff&amp;quot;, &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: K2}, True,&lt;br /&gt;
    hmac.new(bytes.fromhex(K2), b&amp;quot;TPX-KEY-ID&amp;quot;, hashlib.sha256).hexdigest()[:16])&lt;br /&gt;
for i in range(15):&lt;br /&gt;
    k = (&amp;quot;%02x&amp;quot; % ((i * 41 + 3) % 256)) * 32&lt;br /&gt;
    add(&amp;quot;I%02d sweep %02x&amp;quot; % (3 + i, (i * 41 + 3) % 256), &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: k}, True,&lt;br /&gt;
        hmac.new(bytes.fromhex(k), b&amp;quot;TPX-KEY-ID&amp;quot;, hashlib.sha256).hexdigest()[:16])&lt;br /&gt;
add(&amp;quot;I18 a 31-byte key refused&amp;quot;, &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: K[:62]}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;I19 uppercase refused&amp;quot;, &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: K.upper()}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;I20 key not a string refused&amp;quot;, &amp;quot;key_id&amp;quot;, {&amp;quot;k&amp;quot;: None}, True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
FP = &amp;quot;22f59d4401109a8b3660d16b8e483248c2e21648875022a1b66395aecdaf86c3&amp;quot;&lt;br /&gt;
add(&amp;quot;C01 the call sign is the first 16 hex&amp;quot;, &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: FP}, True, FP[:16])&lt;br /&gt;
add(&amp;quot;C02 all zeros&amp;quot;, &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: &amp;quot;0&amp;quot; * 64}, True, &amp;quot;0&amp;quot; * 16)&lt;br /&gt;
for i in range(15):&lt;br /&gt;
    fp = hashlib.sha256(b&amp;quot;cs%d&amp;quot; % i).hexdigest()&lt;br /&gt;
    add(&amp;quot;C%02d sweep&amp;quot; % (3 + i), &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: fp}, True, fp[:16])&lt;br /&gt;
add(&amp;quot;C18 63 hex refused&amp;quot;, &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: FP[:63]}, True, &amp;quot;ERROR:fingerprint&amp;quot;)&lt;br /&gt;
add(&amp;quot;C19 uppercase refused&amp;quot;, &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: FP.upper()}, True, &amp;quot;ERROR:fingerprint&amp;quot;)&lt;br /&gt;
add(&amp;quot;C20 not a string refused&amp;quot;, &amp;quot;call_sign&amp;quot;, {&amp;quot;fp&amp;quot;: 5}, True, &amp;quot;ERROR:fingerprint&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# ---- fingerprint -----------------------------------------------------------&lt;br /&gt;
def fields(**over):&lt;br /&gt;
    f = {&amp;quot;sponsor_user_id&amp;quot;: 1, &amp;quot;sponsor_registration&amp;quot;: &amp;quot;20250101000000&amp;quot;, &amp;quot;agent_user_id&amp;quot;: 7,&lt;br /&gt;
         &amp;quot;agent_registration&amp;quot;: &amp;quot;20260924062344&amp;quot;, &amp;quot;salt&amp;quot;: SALT, &amp;quot;cert_serial&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;cert_time&amp;quot;: &amp;quot;20261001120000&amp;quot;}&lt;br /&gt;
    f.update(over)&lt;br /&gt;
    return f&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
add(&amp;quot;P01 the reference pairing under the test key&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields()},&lt;br /&gt;
    True, ind_fp(K, fields()))&lt;br /&gt;
add(&amp;quot;P02 another key: another fingerprint&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K2, &amp;quot;fields&amp;quot;: fields()}, True,&lt;br /&gt;
    ind_fp(K2, fields()))&lt;br /&gt;
add(&amp;quot;P03 another salt: another fingerprint for the same pair&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(salt=SALT2)}, True, ind_fp(K, fields(salt=SALT2)))&lt;br /&gt;
add(&amp;quot;P04 the certificate&amp;#039;s serial enters&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(cert_serial=2)},&lt;br /&gt;
    True, ind_fp(K, fields(cert_serial=2)))&lt;br /&gt;
add(&amp;quot;P05 the certificate&amp;#039;s time enters&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(cert_time=&amp;quot;20261001120001&amp;quot;)}, True,&lt;br /&gt;
    ind_fp(K, fields(cert_time=&amp;quot;20261001120001&amp;quot;)))&lt;br /&gt;
add(&amp;quot;P06 the sponsor&amp;#039;s registration enters&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(sponsor_registration=&amp;quot;20250101000001&amp;quot;)}, True,&lt;br /&gt;
    ind_fp(K, fields(sponsor_registration=&amp;quot;20250101000001&amp;quot;)))&lt;br /&gt;
add(&amp;quot;P07 the agent&amp;#039;s registration enters&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_registration=&amp;quot;20260924062345&amp;quot;)}, True,&lt;br /&gt;
    ind_fp(K, fields(agent_registration=&amp;quot;20260924062345&amp;quot;)))&lt;br /&gt;
add(&amp;quot;P08 a large user_id&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_user_id=123456789)},&lt;br /&gt;
    True, ind_fp(K, fields(agent_user_id=123456789)))&lt;br /&gt;
add(&amp;quot;P09 the sponsor as its own agent&amp;#039;s pair (user_id 1, 1)&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_user_id=1)}, True, ind_fp(K, fields(agent_user_id=1)))&lt;br /&gt;
for i in range(7):&lt;br /&gt;
    f = fields(sponsor_user_id=10 + i, agent_user_id=20 + 3 * i, cert_serial=i + 1,&lt;br /&gt;
               salt=(&amp;quot;%02x&amp;quot; % (i * 31 % 256)) * 16)&lt;br /&gt;
    add(&amp;quot;P%02d sweep&amp;quot; % (10 + i), &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K3, &amp;quot;fields&amp;quot;: f}, True, ind_fp(K3, f))&lt;br /&gt;
add(&amp;quot;P17 registration 13 digits refused&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_registration=&amp;quot;2026092406234&amp;quot;)}, True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P18 registration with a letter refused&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_registration=&amp;quot;2026092406234x&amp;quot;)}, True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P19 cert_serial 0 refused&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(cert_serial=0)}, True,&lt;br /&gt;
    &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P20 salt malformed refused&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(salt=&amp;quot;zz&amp;quot; * 16)},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P21 a missing field refused&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: {k: v for k, v in fields().items() if k != &amp;quot;salt&amp;quot;}}, True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P22 an extra field refused&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: dict(fields(), model=&amp;quot;x&amp;quot;)},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P23 the key refused before the fields&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: &amp;quot;x&amp;quot;, &amp;quot;fields&amp;quot;: fields(cert_serial=0)},&lt;br /&gt;
    True, &amp;quot;ERROR:key&amp;quot;)&lt;br /&gt;
add(&amp;quot;P24 user_id a boolean refused&amp;quot;, &amp;quot;fingerprint&amp;quot;, {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(agent_user_id=True)},&lt;br /&gt;
    True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
add(&amp;quot;P25 cert_time an integer refused (TS_MW form only)&amp;quot;, &amp;quot;fingerprint&amp;quot;,&lt;br /&gt;
    {&amp;quot;k&amp;quot;: K, &amp;quot;fields&amp;quot;: fields(cert_time=1700000000)}, True, &amp;quot;ERROR:fields&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
names = [c[&amp;quot;name&amp;quot;] for c in cases]&lt;br /&gt;
assert len(names) == len(set(names)), &amp;quot;duplicate case names&amp;quot;&lt;br /&gt;
counts = {}&lt;br /&gt;
for c in cases:&lt;br /&gt;
    counts[c[&amp;quot;fn&amp;quot;]] = counts.get(c[&amp;quot;fn&amp;quot;], 0) + 1&lt;br /&gt;
for fn, m in sorted(counts.items()):&lt;br /&gt;
    assert m &amp;gt;= 20, (fn, m)&lt;br /&gt;
out = {&amp;quot;corpus&amp;quot;: &amp;quot;fingerprint_corpus&amp;quot;, &amp;quot;version&amp;quot;: &amp;quot;0.1.0&amp;quot;, &amp;quot;module&amp;quot;: &amp;quot;tpc_fingerprint 0.1.0&amp;quot;,&lt;br /&gt;
       &amp;quot;test_key&amp;quot;: &amp;quot;K_TEST = 000102...1f (32 bytes), a TEST KEY, never a real secret (D127.1)&amp;quot;,&lt;br /&gt;
       &amp;quot;counts&amp;quot;: counts, &amp;quot;cases&amp;quot;: cases}&lt;br /&gt;
with open(os.path.join(here, &amp;quot;fingerprint_corpus.json&amp;quot;), &amp;quot;w&amp;quot;, encoding=&amp;quot;utf-8&amp;quot;) as f:&lt;br /&gt;
    json.dump(out, f, indent=1, ensure_ascii=False)&lt;br /&gt;
    f.write(&amp;quot;\n&amp;quot;)&lt;br /&gt;
print(&amp;quot;fingerprint_corpus.json&amp;quot;, len(cases), &amp;quot;cases&amp;quot;, counts)&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
</feed>