How Verification Works¶
Verification confirms that a stamp is authentic and that a document has not been modified since it was stamped. PrimeStamp performs three independent checks, each of which can pass, fail, or be skipped.
Verification Checks¶
DocumentStamp + optional content
|
+------------+------------+
| | |
v v v
[SIGNATURE] [CONTENT] [TRUST]
Ed25519 Hash Anchor
check match score
| | |
v v v
bool/None bool/None int >= threshold?
| | |
+------------+------------+
|
v
is_valid (overall)
Check 1: Signature Verification¶
If the stamp has an author signature and public key, PrimeStamp verifies the Ed25519 signature:
- Regenerate the canonical bytes from the stamp (JSON with sorted keys, excluding the signature field).
- Verify the signature against those bytes using the stored public key.
| Outcome | Meaning |
|---|---|
True |
Signature is valid. The stamp was signed by the holder of the corresponding private key and has not been modified since signing. |
False |
Signature is invalid. Either the stamp was tampered with, or it was signed by a different key. |
None |
No signature present. The stamp was created anonymously. |
Signature scope
The signature covers the entire stamp structure -- document hash, storage config, anchor config, lineage, and all metadata. Any modification to any field invalidates the signature.
Check 2: Content Hash Verification¶
When you provide the original document content alongside the stamp, PrimeStamp recomputes the hash and compares it:
- Read the content (bytes, string, or file path).
- Hash it using the same algorithm recorded in the stamp.
- Compare the computed hash to the stamp's
plaintext_hash.value.
| Outcome | Meaning |
|---|---|
True |
Hash matches. The document content is identical to what was originally stamped. |
False |
Hash mismatch. The document has been modified, or this is a different document. |
None |
No content was provided for comparison. |
# With content verification
result = engine.verify_stamp(stamp, b"original document content")
print(result.content_hash_valid) # True or False
print(result.computed_hash) # The hash we just computed
print(result.expected_hash) # The hash stored in the stamp
# Without content (signature-only check)
result = engine.verify_stamp(stamp)
print(result.content_hash_valid) # None
For a quick boolean check without the full result object:
matches = engine.verify_content(stamp, b"original document content")
# Returns True if content hash matches, False otherwise
Check 3: Trust Score Verification¶
The trust check examines how many blockchain anchors have confirmed and whether the cumulative trust score meets the stamp's threshold. This check does not require the original content.
- Count confirmed anchors (status =
CONFIRMED). - Sum their trust weights.
- Compare to the stamp's
trust_threshold.
| Outcome | Meaning |
|---|---|
trust_met = True |
Enough anchors have confirmed. The timestamp is considered reliable. |
trust_met = False |
Anchors are still pending or some have failed. |
result = engine.verify_stamp(stamp)
print(result.trust_score) # e.g., 9
print(result.trust_threshold) # e.g., 5
print(result.trust_met) # True (9 >= 5)
print(result.confirmed_anchors) # e.g., 2
print(result.pending_anchors) # e.g., 1
See Trust Scoring for the full weight table and threshold explanation.
Overall Validity¶
The is_valid field combines the signature and content checks:
is_valid = (
(signature_valid is None or signature_valid) and
(content_hash_valid is None or content_hash_valid)
)
In plain terms:
- A stamp is valid if all present checks pass. Missing checks (no signature, no content provided) are ignored rather than treated as failures.
- A stamp is invalid if any present check fails.
Trust score is reported separately and does not affect is_valid, because anchor confirmation is asynchronous -- a freshly created stamp has no confirmed anchors yet but is still structurally valid.
The StampVerificationResult Object¶
The verify_stamp() method returns a StampVerificationResult with these fields:
| Field | Type | Description |
|---|---|---|
stamp_id |
str |
UUID of the stamp being verified |
is_valid |
bool |
Overall validity (signature + content) |
signature_valid |
bool or None |
Signature check result |
content_hash_valid |
bool or None |
Content hash check result |
computed_hash |
str or None |
Hash computed from provided content |
expected_hash |
str or None |
Hash stored in the stamp |
trust_score |
int |
Current cumulative trust score |
trust_threshold |
int |
Required trust threshold |
trust_met |
bool |
Whether trust threshold is met |
confirmed_anchors |
int |
Number of confirmed anchors |
pending_anchors |
int |
Number of pending anchors |
Convert to a dictionary for JSON serialization or logging:
Verification via CLI¶
# Verify signature and structure only
primestamp verify document.stamp.json
# Verify signature, structure, AND content hash
primestamp verify document.stamp.json -f document.pdf
The CLI displays a formatted table showing each check's status:
Verification Results
┌──────────────┬───────────┬─────────────────────────┐
│ Check │ Status │ Details │
├──────────────┼───────────┼─────────────────────────┤
│ Signature │ Valid │ Signed by a1b2c3d4... │
│ Content Hash │ Match │ Hash: 9f8e7d6c... │
│ Trust Score │ Met │ 9/5 (confirmed: 2) │
│ Overall │ VALID │ Stamp integrity verified│
└──────────────┴───────────┴─────────────────────────┘