Live Demo

🔓
Identity Owner Full Control

Pick different values below then hit Update to encrypt & store on-chain

Transaction pending — waiting for confirmation...
Public Chain View Encrypted
🔒

No on-chain data loaded yet.

🔍
Service Provider Selective Disclosure
🔍

No disclosed data yet.

🏛
Exchange / Regulator Full Disclosure
🏛

No disclosed data yet.

How It Works

Five-step flow from identity creation to regulatory audit.

1

Encrypt

Identity owner encrypts each KYC field with their VerusID private key. Each field is independently encrypted.

2

Store

Encrypted data is written to the Verus blockchain as a contentmultimap on the owner's VerusID.

3

Verify

An attestation authority signs a hash of the plaintext fields, confirming the data is genuine.

4

Disclose

Owner selectively decrypts specific fields for a verifier — e.g. name and age only for a service provider.

5

Audit

Regulators receive full disclosure with attestation proof. Audit trail is immutable on-chain.

Schema

VDXF key mapping for encrypted KYC contentmultimap entries.

// contentmultimap structure on a VerusID
{
  // vrsc::identity.firstname
  "iLB8SG7ErJtTYcG1f4w9RLuMJPpAsjFkiL": [encrypted_blob],
  // vrsc::identity.dateofbirth
  "iSZsa7C4esogN3W6fBngUHR6GvSmt7We4j": [encrypted_blob],
  // vrsc::identity.homeaddress
  "i9A1fD5sVwFFXzEmCJWSRDqN94PXp9oNaS": [encrypted_blob],
  // vrsc::identity.idnumber.value
  "iQrnvbCNWMaG6PjTmeXzrcuAXKsMzmNJWA": [encrypted_blob],
  // vrsc::identity.email
  "iJ4pq4DCymfbu8SAuXyNhasLeSHFNKPr23": [encrypted_blob],
  // vrsc::identity.nationality
  "iEUYNTkw6kFhZWto7vyTpQqtdRL7eoKZY2": [encrypted_blob],
  // vrsc::identity.phonenumber
  "iAQY8o4HwupzcJAw9aBtFwgrvWZGQStkge": [encrypted_blob]
}

// Each encrypted_blob contains:
{
  "version":    1,
  "algorithm":  "AES-256-GCM",
  "ciphertext": "base64-encoded...",
  "iv":         "base64-encoded...",
  "tag":        "base64-encoded..."
}

// Selective disclosure request:
GET /dev/multimap/api/partial-disclosure?fields=name,email,dob,nationality

// Returns only the requested fields, decrypted:
{
  "name":      "Alice Johnson",
  "email":     "alice.johnson@example.com",
  "over16":    true,
  "disclosed": ["name", "email", "dob"]
}

Security

Layered protection for identity data at rest and in transit.

🔐

Per-Field Encryption

Each KYC field is independently encrypted with AES-256-GCM. Disclosing one field reveals nothing about the others.

🔑

VerusID Key Control

Encryption keys derive from the VerusID primary address. Only the identity owner (or designated recovery) can decrypt.

Attestation Signatures

A trusted authority signs a hash of the plaintext data. Verifiers confirm authenticity without re-validating documents.

🧾

Immutable Audit Trail

Every update is a blockchain transaction. Regulators can trace the full history of identity changes on-chain.

Cooldown Protection

Server-enforced 5-minute cooldown between updates prevents abuse and ensures each transaction confirms before the next.

🛡

Zero-Knowledge Proofs

Age verification ("Over 16") is derived without revealing the actual date of birth — selective disclosure at its core.

Attestation Requests

Request signed attestations from users via QR code. The user's wallet creates a cryptographically signed proof without revealing raw personal data.

userdatarequest

Website asks: "Prove you're over 18"

userdatapacket

Wallet responds with a signed attestation

🔒
Waiting for attestation response...
📋
1. Website requests
Generates a userdatarequest specifying what proof is needed
📱
2. User scans QR
Verus Mobile shows what data is requested and asks for consent
🔐
3. Wallet signs proof
Creates a userdatapacket — a signed attestation with only the requested data
4. Website verifies
Verifies the signature on-chain — no personal data stored, just the proof

Integration

// 1. Create an attestation request
const res = await fetch('/verus/generic-request', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    details: [{
      vdxfkey: 'vrsc::identity.attestation.request',
      data: { requested_fields: ['age_over_18'] }
    }]
  })
});
const { deep_link, qr_string } = await res.json();

// 2. Show QR code — user scans with Verus Mobile
QRCode.toCanvas(canvas, qr_string, { width: 220 });

// 3. Poll for response (or use callback URL)
// The wallet POSTs the signed userdatapacket to your callback
// Verify the signature against the signer's VerusID on-chain

The userdatapacket contains a cryptographic signature from the user's VerusID. Verify it with verifymessage or verifyHash — no trust in any third party, just math.