Prime-Space Fingerprinting¶
Prime-Space fingerprinting is the core fingerprinting algorithm in PrimeStamp. It produces a multi-layered document fingerprint that supports partial proofs, progressive disclosure, and structural similarity comparison -- all derived from prime number geometry.
Based on Prime Space Theory by Brian Molidor (ORCID: 0009-0001-4839-5238).
Key Concepts¶
- Prime-indexed decomposition: Documents are split into chunks, each assigned a prime number index.
- Prime-Merkle tree: A Merkle tree built from prime-indexed chunks, enabling existence proofs for individual sections.
- Shadow transforms: Multi-scale lossy projections of document content at prime scales (2, 3, 5, 7, 11, 13), allowing structural comparison at varying resolutions.
- Crossover prime: The constant 127 (
CROSSOVER_PRIME) from Prime Space Theory, used as the modulus in frequency signatures and shadow transforms. - Frequency signatures: Character, word, and n-gram frequency vectors mapped through prime-scaled buckets.
- Partial proofs: Cryptographic proofs of existence, structure, similarity, or authorship without revealing the full document.
Generating a Fingerprint¶
from primestamp.fingerprint.prime_space import generate_fingerprint
from primestamp.core.models import DecompositionMethod
# Basic usage
fp = generate_fingerprint(b"Document content here...")
# With specific decomposition
fp = generate_fingerprint(
b"Document content here...",
method=DecompositionMethod.HIERARCHICAL,
)
The FingerprintGenerator class provides full control:
from primestamp.fingerprint.prime_space import FingerprintGenerator, SHADOW_SCALES
from primestamp.core.models import DecompositionMethod, HashAlgorithm
from primestamp.core.crypto import CROSSOVER_PRIME
generator = FingerprintGenerator(
decomposition_method=DecompositionMethod.HIERARCHICAL,
hash_algorithm=HashAlgorithm.SHA3_256,
shadow_scales=SHADOW_SCALES, # [2, 3, 5, 7, 11, 13]
crossover_mod=CROSSOVER_PRIME, # 127
)
fp = generator.generate(b"Document content here...")
Fingerprint Fields¶
| Field | Description |
|---|---|
standard_hash |
Whole-document cryptographic hash |
decomposition_method |
How the document was chunked |
chunk_count |
Number of chunks |
prime_indices |
Prime number assigned to each chunk |
merkle_root |
Root hash of the Prime-Merkle tree |
tree_depth |
Depth of the Merkle tree |
sections |
Per-chunk hashes and shadow values |
crossover_mod |
Prime modulus (127) |
shadows |
Multi-scale shadow fingerprints (keyed by scale) |
frequency |
Character, word, and n-gram frequency signatures |
Document Decomposition¶
The DocumentDecomposer splits documents into prime-indexed chunks. Four strategies are available:
Hierarchical (default)¶
Splits on paragraph boundaries (double newlines). Falls back to single newlines, then to fixed-size chunks.
from primestamp.fingerprint.prime_space import DocumentDecomposer
from primestamp.core.models import DecompositionMethod
decomposer = DocumentDecomposer(method=DecompositionMethod.HIERARCHICAL)
chunks = decomposer.decompose(b"Paragraph one.\n\nParagraph two.\n\nParagraph three.")
# 3 chunks with prime indices [2, 3, 5]
Flat¶
Fixed-size byte chunks (default 1024 bytes each).
Content-Addressed¶
Flat decomposition, then primes are reassigned based on each chunk's content hash. The first 4 bytes of the hash select from the first 10,000 primes.
Semantic¶
NLP-based chunking. Currently falls back to hierarchical; designed as an extension point.
Shadow Transforms¶
Shadow transforms project document content to lower-resolution representations at prime scales. Lower scale values reveal more structural detail.
Default scales: 2, 3, 5, 7, 11, 13
# Access shadows from a fingerprint
for scale, shadow in fp.shadows.items():
print(f"Scale {scale}: length={shadow.length}, hash={shadow.hash}")
Each ShadowFingerprint contains:
| Field | Description |
|---|---|
scale |
Prime scale factor |
hash |
SHA3-256 hash of the shadow values |
length |
Number of values in the shadow |
values |
The actual shadow transform values |
Resolution decreases as scale increases: scale 2 gives ~50% resolution, scale 13 gives ~7%.
Comparing Fingerprints¶
from primestamp.fingerprint.prime_space import compare_fingerprints
similarities = compare_fingerprints(fp1, fp2)
# Returns: {2: 0.95, 3: 0.91, 5: 0.88, 7: 0.82, 11: 0.79, 13: 0.76}
Comparison is performed at each shared shadow scale using shadow_similarity from primestamp.core.crypto. Values range from 0.0 (completely different) to 1.0 (identical).
Partial Proofs¶
The ProofGenerator creates four types of partial proofs that reveal specific properties without disclosing the full document.
Existence Proof¶
Prove that a specific section exists in the document without revealing its content. Uses the section's Merkle path.
proof = generator.prove_existence(section_index=3)
# proof.section_prime -- the prime index of the section
# proof.section_hash -- the section's content hash
# proof.root_hash -- Merkle root for verification
Structure Proof¶
Reveal the document's structure at a chosen shadow resolution. Higher scales disclose less detail.
proof = generator.prove_structure(scale=7)
# proof.shadow_scale -- 7
# proof.shadow_values -- the shadow transform at scale 7
# proof.root_hash -- Merkle root
Similarity Proof¶
Prove that two documents are similar without revealing either document. Compares shadow transforms across all shared scales.
proof = generator.prove_similarity(other_fingerprint)
# proof.reference_root -- Merkle root of the other document
# proof.shadow_similarities -- {scale: similarity_score}
Authorship Proof¶
Compare a document's frequency signature against an author's style profile.
proof = generator.prove_authorship(author_profile)
# proof.author_profile_hash -- hash of the author's signature
# proof.frequency_similarity -- character frequency cosine similarity
# proof.ngram_similarity -- n-gram overlap score
Frequency Analysis¶
Frequency signatures capture stylometric properties of the document.
Character Frequency¶
A 26-value vector (one per letter a-z) with frequencies mapped to prime-scaled buckets modulo 127.
from primestamp.fingerprint.prime_space import compute_character_frequency
sig = compute_character_frequency("Hello world", mod=127)
# Returns list of 26 integers
Word Frequency¶
Top-N word frequencies mapped to (word_hash_bucket, frequency_bucket) pairs.
from primestamp.fingerprint.prime_space import compute_word_frequency
sig = compute_word_frequency("the quick brown fox", top_n=50, mod=127)
N-gram Frequency¶
Character n-gram frequencies hashed to buckets.
from primestamp.fingerprint.prime_space import compute_ngram_frequency
sig = compute_ngram_frequency("hello world", n=3, mod=127)
# Returns dict of {bucket: normalized_frequency}
Shannon Entropy¶
from primestamp.fingerprint.prime_space import compute_entropy
entropy = compute_entropy("Hello world")
Frequency Similarity¶
Cosine similarity between two character frequency signatures:
from primestamp.fingerprint.prime_space import frequency_similarity
sim = frequency_similarity(sig_a, sig_b) # 0.0 to 1.0
Prime-Merkle Tree¶
The PrimeMerkleTree wraps a standard Merkle tree where leaves are document chunks with prime indices.
from primestamp.fingerprint.prime_space import PrimeMerkleTree, DocumentDecomposer
decomposer = DocumentDecomposer()
chunks = decomposer.decompose(b"content...")
tree = PrimeMerkleTree.build(chunks)
print(tree.root_hex) # Merkle root as hex string
print(tree.depth) # Tree depth
# Get a Merkle proof for chunk 0
proof = tree.get_proof(0)
# Returns [(sibling_hash_hex, is_left), ...]
# Verify a proof
is_valid = tree.verify_proof(
leaf_hash=chunks[0].content_hash,
proof=proof,
)