Overview
MIR Assertions is a system for creating cryptographically-signed statements about media artifacts. Each assertion records who made a statement, not whether it's accurate.
Key Concepts
- Artifact Hash — SHA-256 hash of the media file. Files are never uploaded; only the hash is recorded.
- Issuer — An organization's identity that signs assertions. Tied to cryptographic keys.
- Public Key — Registered with MIR. Used by anyone to verify signatures.
- Private Key — Stays on your infrastructure. Never sent to MIR. Used to sign assertions.
- Assertion — A signed statement about a media artifact (e.g., "We published this image").
What stays local vs. what goes to MIR
| Your Infrastructure | MIR |
|---|---|
| Media files | SHA-256 hashes only |
| Private key | Public key |
| Signing happens here | Signature verification |
Media files are never uploaded. You compute the SHA-256 hash locally and submit only the hash. This protects IP and scales to any file size.
How verification works
When anyone looks up an artifact hash on MIR, they see all assertions made about it. Each assertion includes:
- The issuer's identity and verification status
- The assertion type (ISSUED_BY, NOT_ISSUED_BY, DISPUTE, etc.)
- A cryptographic signature that proves the issuer authorized the statement
- Whether conflicting assertions exist from other issuers
MIR verifies that signatures are valid and that the signing key belongs to the claimed issuer. MIR does not verify whether the assertion is truthful.
Computing Artifact Hash
The artifact hash is a SHA-256 hash of your media file's raw bytes. Compute it locally — files are never uploaded to MIR.
Command Line
macOS / Linux:
shasum -a 256 your-file.jpg # Output: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 your-file.jpg
Windows (PowerShell):
Get-FileHash -Algorithm SHA256 your-file.jpg | Select-Object -ExpandProperty Hash
Node.js
const crypto = require('crypto');
const fs = require('fs');
function hashFile(filepath) {
const buffer = fs.readFileSync(filepath);
return crypto.createHash('sha256').update(buffer).digest('hex');
}
const hash = hashFile('your-file.jpg');
console.log(hash); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Python
import hashlib
def hash_file(filepath):
with open(filepath, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
hash = hash_file('your-file.jpg')
print(hash) # e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Browser (JavaScript)
async function hashFile(file) {
const buffer = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
// Usage with file input
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
const hash = await hashFile(e.target.files[0]);
console.log(hash);
});
Why hash-only? Your media never leaves your systems. MIR stores only the 64-character hash, protecting IP and scaling to any file size.
Private Key Storage
Your private key never goes to MIR. MIR only stores your public key. You sign assertions locally, then submit the signature. If someone intercepts your API traffic, they cannot forge signatures without your private key.
Where you store your private key depends on your setup:
- Organizations with servers — Store on your server with restricted file permissions or a secrets manager (Vault, AWS Secrets Manager, etc.).
- Creators with a computer — Store on your local machine. Sign assertions from there.
- No server? — Use our Browser Signer to generate keys and sign directly in your browser. Keys are protected with biometrics or a passphrase.
Keep it secure — if compromised, revoke and rotate immediately via the Issuer Portal.
Never commit private keys to git. Add *.pem and .mir/ to your .gitignore.
Signing Model
Every assertion must include a cryptographic signature. This proves the issuer authorized the statement.
Supported Algorithms
| Algorithm | Key Type | Notes |
|---|---|---|
Ed25519 | EdDSA | Recommended. Fast, small keys, no configuration. |
ES256 | ECDSA P-256 | Widely supported. Used by the Browser Signer (WebCrypto). |
How it works
- Create a signed payload — JSON object with version, artifact hash, assertion type, issuer ID, and timestamp
- Sign with your private key — Produce a base64-encoded signature
- Submit both — MIR verifies the signature against your registered public key before recording
Signed Payload Structure
{
"version": 1,
"artifactHash": "e3b0c44298fc1c14...",
"type": "ISSUED_BY",
"issuerId": "your-issuer-id",
"timestamp": "2025-01-15T12:00:00.000Z"
}
| Field | Required | Description |
|---|---|---|
version | Required | Must be 1 |
artifactHash | Required | SHA-256 hash of the artifact |
type | Required | Assertion type (e.g., ISSUED_BY) |
issuerId | Required | Your issuer ID (found in the portal dashboard) |
timestamp | Required | ISO 8601 timestamp, must be within 5 minutes of server time |
Timestamps must be within 5 minutes of server time. This prevents replay attacks. Use ISO 8601 format.
Where do I find my Issuer ID? Log in to the Issuer Portal — your Issuer ID is shown at the top of the dashboard with a copy button.
No server? The Browser Signer handles key generation, signing, and submission entirely in your browser — no code needed.
Lookup Assertions
Look up all assertions for a given artifact hash. No authentication required.
Query Parameters
| Parameter | Required | Description |
|---|---|---|
hash |
Required | SHA-256 hash of the artifact (64-char hex) |
Example
curl "https://mirassertions.org/assertions?hash=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
Response
{
"artifactHash": "e3b0c44298fc1c14...",
"assertions": [
{
"id": "assertion_xyz789",
"type": "ISSUED_BY",
"issuer": {
"id": "issuer_abc123",
"name": "News Organization",
"status": "VERIFIED",
"verified": true
},
"scope": null,
"context": null,
"createdAt": "2025-01-15T12:00:00.000Z",
"revoked": false
}
],
"conflicts": false,
"guidance": "MIR records who made each assertion. MIR does not verify content accuracy."
}
When conflicting assertions exist (e.g., ISSUED_BY and NOT_ISSUED_BY from different issuers, or a DISPUTE), the conflicts field is true and guidance is updated accordingly.
Batch Lookup
Look up assertions for up to 100 artifact hashes in a single request. API key required.
Headers
| Header | Required | Description |
|---|---|---|
x-api-key |
Required | Your issuer API key |
Request Body
| Field | Type | Description |
|---|---|---|
hashes |
string[] |
Array of SHA-256 hashes (64-char hex). Max 100. |
Example
curl -X POST "https://mirassertions.org/assertions/lookup" \
-H "x-api-key: mir_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"hashes": [
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
]
}'
Response
{
"results": {
"e3b0c44298fc1c14...": {
"assertions": [ ... ],
"hasConflicts": false,
"guidance": "MIR records who made each assertion. MIR does not verify content accuracy."
},
"a1b2c3d4e5f6a1b2...": {
"assertions": [],
"hasConflicts": false,
"guidance": "No assertions found for this artifact. Absence of assertions is not evidence of anything."
}
},
"meta": {
"hashesRequested": 2,
"hashesQueried": 2
}
}
Each hash in the results has the same shape as the single lookup response. Hashes with no assertions return an empty array. Duplicate hashes are deduplicated before querying.
Rate limit: 30 requests per minute (separate from the general rate limit).
Assertion Types
| Type | Meaning | Example Use |
|---|---|---|
ISSUED_BY |
"We created/published this artifact" | News org claiming authorship of a photo |
NOT_ISSUED_BY |
"This artifact is NOT from us" | Denying a fake image attributed to you |
DISPUTE |
"We dispute an existing assertion on this artifact" | Challenging another issuer's claim |
ROLE_SCOPE |
"Our relationship to this artifact is..." | Photographer vs publisher distinction |
INTENT |
"The purpose of this artifact is..." | Satire, parody, training data, marketing |
METHOD |
"This artifact was created using..." | AI-generated, human, hybrid |
An issuer can have only one active assertion of each type per artifact hash. To change, revoke the existing assertion and create a new one, or use the supersede flow.
Recommended Metadata
When creating assertions, include metadata to make your assertion records human-readable and easier to manage. These fields are optional but strongly recommended.
| Field | Type | Recommendation |
|---|---|---|
displayName |
string (max 200) | A friendly label. Defaults to filename if submitted via Browser Signer. |
originalFilename |
string | The source filename. Auto-captured by the Browser Signer. |
artifactMimeType |
string | Strongly recommended. e.g. image/jpeg, video/mp4, application/pdf |
artifactByteSize |
integer | Strongly recommended. File size in bytes. |
note |
string (max 500) | Internal note for your team. Not shown publicly. |
tags |
string[] (max 10) | Labels for organizing. e.g. ["press-release", "Q4", "official"] |
context |
string (max 500) | Public-facing context about the assertion. |
The Browser Signer auto-captures originalFilename, artifactMimeType, artifactByteSize, and displayName from dropped files. For API integrations, include these fields in your POST body.
Metadata can be edited after creation via the Issuer Portal's "My Assertions" tab, or retroactively matched to files using the Match File helper.
Issuer Badges
Issuers are assigned badges based on their verification status:
| Status | Badge | Meaning |
|---|---|---|
VERIFIED |
Verified | Domain ownership confirmed, identity validated |
UNVERIFIED |
Unverified | Registered but not yet verified. Can still publish assertions. |
RESTRICTED |
Restricted | Under review, limited capabilities |
SUSPENDED |
Suspended | Temporarily blocked from publishing |
Verification is achieved by confirming domain ownership via DNS TXT record, or automatically after sustained assertion activity without disputes.
Error Codes
| Code | Meaning |
|---|---|
400 | Bad request — invalid input or missing required field |
401 | Unauthorized — missing or invalid API key / session |
402 | Payment required — active subscription needed to create assertions |
403 | Forbidden — issuer suspended or action not allowed |
404 | Not found — assertion or issuer doesn't exist |
429 | Rate limited — too many requests |
500 | Server error — retry or contact support |
Error Response Format
{
"error": "Description of what went wrong",
"hint": "Optional guidance on how to fix it"
}
What MIR Does Not Prevent
MIR Assertions is not a system for determining truth, originality, or authenticity of media. It is a system for attribution and accountability.
Edited or Derivative Media
Anyone can modify a video, image, or audio file and create a new artifact with a new hash. MIR treats this as a new artifact with its own assertion history.
False or Misleading Claims
Issuers may publish assertions that are incorrect or dishonest. MIR records who made the claim, not whether it is accurate.
Competing or Conflicting Assertions
Multiple issuers may assert different claims about the same artifact. MIR preserves all assertions without adjudicating between them.
Content Misuse or Impersonation Attempts
MIR does not block impersonation attempts at creation time. It makes impersonation visible, attributable, and accountable after the fact.
Important: Absence of an assertion should never be interpreted as proof of authenticity or illegitimacy. MIR verifies signatures and attribution — not truth, intent, or content.
Repudiation Playbook
When an organization encounters a fake, altered, or impersonated video, speed and clarity matter more than takedowns alone. MIR provides a structured, auditable repudiation path.
Step 1: Identify the Artifact
- Obtain the media file (video, audio, image)
- Compute its SHA-256 hash locally
- Confirm the exact artifact being circulated (re-encodes produce different hashes)
Step 2: Publish a NOT_ISSUED_BY Assertion
Create a signed assertion of type NOT_ISSUED_BY against the artifact hash. This establishes an official, cryptographically signed denial tied to your issuer identity.
Step 3: Add Context
Include concise, factual context:
- "Impersonates our CFO"
- "Fabricated video circulating on social media"
- "No official communication was made via this channel"
Step 4: Share the Lookup Link
Provide the MIR lookup URL to stakeholders — finance teams, journalists, platforms, law enforcement. Anyone can independently verify: who denied the artifact, when, and under what authority.
Why This Works
- Attackers can claim authorship — they cannot claim your authority
- Repudiation is fast, public, and attributable
- History is preserved; nothing is silently erased
- MIR never becomes the arbiter — organizations speak for themselves
Key principle: MIR prevents silent impersonation, not dishonest speech.
Badge Overlay Widget
Overlay a small clickable MIR badge directly on images and videos on your website. When a visitor clicks the badge, they see assertion details. The badge only appears if an assertion exists for the artifact.
Setup
<script src="https://mirassertions.org/js/mir-badge-overlay.js"></script>
Images
<!-- Explicit hash (recommended) --> <img src="photo.jpg" data-mir-badge="YOUR_HASH_HERE" /> <!-- Auto-hash (same-origin images only) --> <img src="photo.jpg" data-mir-badge />
Video
<video src="video.mp4" data-mir-badge="YOUR_HASH_HERE" controls></video>
Video requires an explicit hash — auto-hashing is not supported for video files (too large to hash in the browser).
Customization
| Attribute | Default | Description |
|---|---|---|
data-mir-position | bottom-right | bottom-right, bottom-left, top-right, top-left |
data-mir-size | 48 | Badge size in pixels |
data-mir-opacity | 0.9 | Overlay opacity (0–1) |
Full Example
<img src="https://example.com/photo.jpg"
data-mir-badge="a1b2c3d4e5f6..."
data-mir-position="top-left"
data-mir-size="36"
data-mir-opacity="0.8" />
Full API Reference
Endpoint details for creating, revoking, and superseding assertions, key management, team invites, and more.
Sign in to Issuer Portal →