|
1 | 1 | """ |
2 | 2 | Defines the core interface for the Generalized XMSS signature scheme. |
3 | 3 |
|
4 | | -This file specifies the high-level functions (`key_gen`, `sign`, `verify`) |
| 4 | +Specification for the high-level functions (`key_gen`, `sign`, `verify`) |
5 | 5 | that constitute the public API of the signature scheme. For the purpose of this |
6 | 6 | specification, these are defined as placeholders with detailed documentation. |
7 | 7 | """ |
8 | 8 |
|
9 | | -from typing import List, Tuple |
| 9 | +from __future__ import annotations |
| 10 | + |
| 11 | +from typing import Tuple |
10 | 12 |
|
11 | | -from ..koalabear import Fp |
12 | | -from .constants import BASE, CHUNK_SIZE, DIMENSION, LIFETIME, MESSAGE_LENGTH |
13 | 13 | from .structures import PublicKey, SecretKey, Signature |
14 | | -from .utils import chain, encode, hash_tree_verify, tweakable_hash |
15 | 14 |
|
16 | 15 |
|
17 | 16 | def key_gen() -> Tuple[PublicKey, SecretKey]: |
@@ -55,34 +54,46 @@ def sign(sk: SecretKey, epoch: int, message: bytes) -> Signature: |
55 | 54 |
|
56 | 55 |
|
57 | 56 | def verify(pk: PublicKey, epoch: int, message: bytes, sig: Signature) -> bool: |
| 57 | + r""" |
| 58 | + Verifies a digital signature against a public key, message, and epoch. |
| 59 | +
|
| 60 | + This function is a placeholder. The complete verification logic is detailed |
| 61 | + below and will be implemented in a future update. |
| 62 | +
|
| 63 | + ### Verification Algorithm |
| 64 | +
|
| 65 | + 1. **Re-encode Message**: The verifier uses the randomness `rho` from the |
| 66 | + signature to re-compute the codeword $x = (x_1, \dots, x_v)$ from the |
| 67 | + message `m`. This includes calculating the checksum or checking the target sum. |
| 68 | +
|
| 69 | + 2. **Reconstruct One-Time Public Key**: For each intermediate hash `y_i` |
| 70 | + in the signature, the verifier completes the corresponding hash chain. |
| 71 | + Since `y_i` was computed with $x_i$ steps, the verifier applies the |
| 72 | + hash function an additional $w - 1 - x_i$ times to arrive at the |
| 73 | + one-time public key component `otpk_{ep,i}`. |
| 74 | +
|
| 75 | + 3. **Compute Merkle Leaf**: The verifier hashes the reconstructed one-time |
| 76 | + public key components to compute the expected Merkle leaf for `epoch`. |
| 77 | +
|
| 78 | + 4. **Verify Merkle Path**: The verifier uses the `path` from the signature |
| 79 | + to compute a candidate Merkle root starting from the computed leaf. |
| 80 | + Verification succeeds if and only if this candidate root matches the |
| 81 | + `root` in the `PublicKey`. |
| 82 | +
|
| 83 | + Args: |
| 84 | + pk: The public key to verify against. |
| 85 | + epoch: The epoch the signature corresponds to. |
| 86 | + message: The message that was supposedly signed. |
| 87 | + sig: The signature object to be verified. |
| 88 | +
|
| 89 | + Returns: |
| 90 | + `True` if the signature is valid, `False` otherwise. |
| 91 | +
|
| 92 | + For the formal specification of this process, please refer to: |
| 93 | + - "Hash-Based Multi-Signatures for Post-Quantum Ethereum" [DKKW25a] |
| 94 | + - "Technical Note: LeanSig for Post-Quantum Ethereum" [DKKW25b] |
| 95 | + - The canonical Rust implementation: https://github.com/b-wagn/hash-sig |
58 | 96 | """ |
59 | | - Verifies a digital signature against: |
60 | | - - a public key, |
61 | | - - a message, |
62 | | - - epoch. |
63 | | - """ |
64 | | - assert len(message) == MESSAGE_LENGTH, "Invalid message length" |
65 | | - assert 0 <= epoch < LIFETIME, "Epoch out of valid range" |
66 | | - |
67 | | - # Re-encode the message to get the expected codeword. |
68 | | - codeword = encode(pk.parameter, message, sig.rho, epoch) |
69 | | - if codeword is None: |
70 | | - return False |
71 | | - |
72 | | - # Reconstruct the one-time public key from the signature's hashes. |
73 | | - chain_ends: List[List[Fp]] = [] |
74 | | - for i in range(DIMENSION): |
75 | | - steps_to_end = (BASE**CHUNK_SIZE - 1) - codeword[i] |
76 | | - end_of_chain = chain( |
77 | | - pk.parameter, epoch, i, codeword[i], steps_to_end, sig.hashes[i] |
78 | | - ) |
79 | | - chain_ends.append(end_of_chain) |
80 | | - |
81 | | - # Compute the Merkle leaf by hashing the reconstructed one-time public key. |
82 | | - # Note: A proper tweak would be used here. For simplicity, we omit it. |
83 | | - computed_leaf = tweakable_hash(pk.parameter, [], chain_ends) |
84 | | - |
85 | | - # Verify the Merkle path against the public key's root. |
86 | | - return hash_tree_verify( |
87 | | - pk.parameter, pk.root, epoch, computed_leaf, sig.path |
| 97 | + raise NotImplementedError( |
| 98 | + "verify will be implemented in a future update to the specification." |
88 | 99 | ) |
0 commit comments