SSIMPL defines a self-sovereign identity framework backed by government-issued trust anchors and a peer-validated ledger.
The SSIMPL protocol defines a Self-Sovereign Identity & Mondial Pseudonymous Ledger framework that allows individuals to maintain control over their digital identity while enabling verifiable credential issuance and revocation. It bridges physical trust anchors (e.g., ePassports) with digital identity systems, ensuring cryptographic verification without reliance on centralized authorities.
SSIMPL addresses two key problems:
The protocol balances decentralization, peer authority, and optional server-assisted synchronization for efficiency and availability. Everything is made to be deterministic by default, so no authorities whatsoever are required except the one that signed the Trust Anchor (TA).
SSIMPL identities are rooted in cryptographically verifiable credentials derived from Trust Anchors, such as government-issued ePassports. A valid wallet:
This ensures only owners of verifiable physical credentials can create valid DIDs.
Identity is hard to verify by nature. Using a state-issued TA is not a perfect solution, but it's the best deterministic proof of (human) identity available at the moment.
These different levels allow people to authenticate themselves on several levels, depending on the context. Say a person would like to order a product from a website. Using SSIMPL, the webshop could request a certain scope of credentials (like a shipping address). The owner of the identity could then approve or disapprove this request. This flow is very similar to Open ID Connect, except that there is no need for a 3rd party.
The wallet is a Self-Sovereign means of identification that can be installed and bootstrapped entirely independent of any authority. It solely relies on cryptographic proof. This cryptographic proof is contained within the so-called VCR. The Verifiable Credential Root is a VC, as defined in [[VC]], necessary to link the signer of this VC to the related public key & DID.
The VCR can also be used as the root of a chain of VCs. This way it can, either explicitly or implicitly, verify association to other credentials further up in the chain.
Wallets MUST:
did:key for interoperability.Wallets SHOULD:
A SSIMPL Wallet has certain security scenario's that need to be addressed
In order to mitigate the most dire scenario, where the owner loses both their TA and their BIP39 mnemonic, SSIMPL has a simple solution: a trusted Peer (like a close relative) exchange a complete LedgerEntryRevocation from each other. In case of emergency, either Peer can always revoke the other Peers DID. This is a two-sided solution of course: it provides a nice safety net, but also introduces another safety risk. For these kind of scenario's, there are rarely perfect solutions. Owners are therefore advised to try and avoid this one at all cost.
The Relay Peer is a special kind of Peer in the sense that it is static and reachable over the internet on a fixed hostname. It acts like any other Peer, but it also adds a storage layer for the Ledger and serves as distribution point for the Ledger. All Relay Peers together form a subnetwork on which all other (mobile) Peers 'ride'. This is purely infrastructural to help communication between Peers. It doesn't give any special privileges or authorities to any of the Relay Peers and does therefore still fulfill all requirements to be called decentralized.
In order to establish a stable network, there should always be one well-known Relay Peer, which allows another Relay Peer to find others within the network. It also serves as an entry point for freshly installed Wallets to bootstrap.
To enable deterministic network formation and secure onboarding of Relay Peers, the SSIMPL protocol defines a bootstrap and verification procedure.
The first time a new Relay Peer is bootstrapped, it MUST make itself known to a known (or a well-known Relay Peer,
e.g., root.ssimpl.org) to
obtain the first list of known Relay Peers. This is a hard-coded node that allows the network to kickstart itself
and to
have zero knowledge upfront when adding a new Relay Peer.
Upon first contact with the network, a new Relay Peer:
The SSIMPL ledger is a deterministically canonical, peer-replicated structure tracking valid DIDs, maintained across Peers and Relay Peers.
did_expiry and GRACE_PERIOD.did_expiry then by hash(did).root_hash using a Merkle tree over the current, complete, pruned ledger.
The SSIMPL ledger uses a Merkle tree to enable efficient verification of ledger state and individual entries.
root_hash representing the current canonical ledger state.xyz, a peer can provide the leaf hash and the branch hashes up to
root_hash.
root_hash.
root_hash for a specific epoch.An entry is valid if:
current_time < did_expiry + GRACE_PERIOD.hash(verifiable_credential_root.data) equals verifiable_credential_root.signature_document.message.
signature_document.signature.public_key.verify_signature(
verifiable_credential_root.signature_document.message,
verifiable_credential_root.signature_document.signature.value,
verifiable_credential_root.signature_document.signature.public_key,
verifiable_credential_root.signature_document.signature.algorithm
)Expired or invalid entries are ignored and removed during canonical construction.
Peers MAY remove their own entries and expired entries. To revoke a DID:
Peers MUST NOT remove valid entries or modify others' entries.
{ epoch, root_hash } metadata.To enable efficient verification of ledger history and prevent forks from propagating, the SSIMPL protocol introduces Merkle checkpoints. These checkpoints allow peers to validate that their current ledger state stems from a previously agreed-upon canonical state.
A Merkle checkpoint is a snapshot of the canonical ledger at a given epoch, containing:
Merkle checkpoints serve three main purposes:
To verify a ledger using a checkpoint:
A mismatch indicates ledger tampering or divergence, and the peer MUST reject the inconsistent entries.
SSIMPL provides a self-sovereign identity framework with a deterministic, peer-validated ledger, enabling secure, verifiable DIDs anchored in government-issued credentials.
All entries and operations are canonical, rule-derived, and independently verifiable by peers, ensuring a fully trustworthy and decentralized identity ecosystem.
To ensure that signatures are verifiable and consistent across all peers, every signed object in SSIMPL (including LedgerEntry and VerifiableCredentialRoot) MUST be serialized in a canonical form before hashing and signing. These rules remove ambiguity in encoding and field ordering, preventing mismatches between peers.
Boolean and Null
true, false, and null MUST use JSON literals exactly as shown (case-sensitive).
There are many ways to encode raw bytes or strings, and more are being invented as we speak. It is highly inefficient to make these encodings contract-based. SSIMPL therefore highly recommends the use of the Multibase Data Format, as defined in [[MULTIBASE]], which is deterministic.
To verify a signature:
Canonicalization guarantees that:
All cryptographically signed objects in SSIMPL MUST follow a uniform, canonical structure, known as the SignatureEnvelope**. This ensures consistency across all signed data, including ledger entries, Verifiable Credential Roots (VCR), revocations, and delta payloads.
Each signed object MUST include a SignatureEnvelope with the following structure:
message — The cryptographic hash of the canonical serialization of the
data object.
signature — Object containing the signature itself:
publicKey — Base64url-encoded public key corresponding to the signing private key.algorithm — Signature algorithm used (e.g., EdDSA, ECDSA).value — Base64url-encoded signature value.signer — DID of the entity producing the signature.Example (in JSON for clarity):
{
"message": "<hash-of-canonical-data>",
"signature": {
"publicKey": "<multibase-encoded public key>",
"algorithm": "<algorithm identifier>",
"value": "<multibase-encoded signature>"
},
"signer": "<DID of signer>"
}
This canonical signature object pattern provides a single, consistent approach for proving authorship and integrity across all SSIMPL objects.
This section defines the reference API for Relay Peers in the SSIMPL protocol. It provides endpoints for DID registration, revocation, and ledger synchronization.
All requests MUST be authenticated using a Bearer token, containing a signed
DID in the canonical
SignatureEnvelope format, multibase-encoded.
POST /peer
Purpose: Make a Relay Peer known to another Relay Peer.
Request payload: RelayPeerAnnouncement object
Example:
{
"data": {
"did": did:key:1234abc...example
"hostname": some.hostname.org
},
"signatureEnvelope": {
...
}
}
Response: 201 OK
POST /peer/identity
Purpose: Allows (Relay) Peers to check the health an initial validity of the Relay Peer
Request payload SignedObject:
| Field | Type | Description |
|---|---|---|
| data | string | DID of the Peer |
| signatureEnvelope | object | Envelope containing the signature data |
Response: 200 OK + SignedObject:
| Field | Type | Description |
|---|---|---|
| data | string | DID of the Relay Peer |
| signatureEnvelope | object | Envelope containing the signature data |
POST /ledger/delta
Purpose: Allows a Peer to request ledger entries that are newer than a given epoch, if the peer is out of sync.
Request payload LedgerDeltaRequest:
| Field | Type | Description |
|---|---|---|
| from | integer | Last ledger epoch known to the peer |
| to | integer | (optional) The upper boundary - In case the Peer wants 'chunked' responses |
| rootHash | string | Merkle root hash of the peer's current ledger state - to verify the Relay Peers current Ledger is an extension of the one the Peer has |
Example:
{
"from": 42,
"to": 420,
"rootHash": "abcdef1234567890"
}
Response: 200 OK + LedgerDeltaResponse:
Field Type Description currentEpoch integer Current epoch of the relay peer ledger authoritativeRootHash string Merkle root hash after applying returned entries array Ordered ledger entries newer than lastEpoch
Example:
{
"currentEpoch": 43,
"authoritativeRootHash": "1234abcd5678ef90",
"entries": [
{
"data": {
"verifiableCredentialRoot": {
...
},
"proof": {
...
}
},
"signatureEnvelope": {
...
}
},
"relayPeers": [
{
"data": {
"did": ...,
"hostname" ...,
},
"signatureEnvelope": {
...
}
}
]
}
POST /ledger
Purpose: Register a new DID on the ledger.
Request payload: LedgerEntry
Example:
{
"data": {
"verifiableCredentialRoot": {
...
},
"proof": {
...
}
},
"signatureEnvelope": {
...
}
}
Response: 201 OK
PUT /ledger
Purpose: Revoke a DID by submitting a revocation payload.
Request payload: LedgerEntryRevocation object
Example:
{
"data": {
"did": "did:key:z6Mkw...example"
},
"signatureEnvelope": {
...
}
}
Response: 204 OK
| Field | Type | Description |
|---|---|---|
| data | object | Contains the actual fields used for the signature |
| signatureEnvelope | object | Signature verifying the data |
| Field | Type | Description |
|---|---|---|
| data | object | Contains verifiableCredentialRoot and proof |
| signatureEnvelope | object | Signature verifying the integrity of data |
| Field | Type | Description |
|---|---|---|
| did | object | Contains did and taId (id of the Trust Anchor, e.g. the documentNumber) |
| taId | object | Signature verifying the data |
| Field | Type | Description |
|---|---|---|
| data | object | Contains the DID being revoked |
| signatureEnvelope | object | Signature verifying the revocation |
| Field | Type | Description |
|---|---|---|
| DG15 | string | Data group 15 proof |
| AASignature | string | Active Authentication signature |
| AAChallenge | string | Active Authentication challenge |
| SOD | string | Security Object Document |
| Field | Type | Description |
|---|---|---|
| message | string | Canonical serialized representation of the signed data |
| signature | object | Signature object containing algorithm, publicKey, and
value |
| signer | string | DID or public key identifier of the signer |
| Field | Type | Description |
|---|---|---|
| publicKey | string | Public key of signer |
| algorithm | string | Signing algorithm |
| value | string | Multibase-encoded signature value |