DIDComm

PAM 1.0

Summary

A DIDComm v2 protocol for publishing cryptographically secure app manifests using zero-knowledge proofs (PoE) that bind packages to signing certificates, publisher DIDs, and secure execution environments. Prevents fake signatures and key compromise attacks through TEE-backed attestation.

Summary

The Publisher Authority Manifest (PAM) 1.0 protocol enables Registered Entities (publishers) to publish cryptographically secure manifests that authoritatively bind their application packages to signing certificates, publisher DIDs, and secure execution environments. PAM leverages the Proof of Execution (PoE) 1.0 protocol to provide verifiable, tamper-proof evidence that manifests are created in trusted environments with proper authorization, preventing fake signatures and key compromise attacks.

Verifiers (SDKs, app stores, MDMs) fetch and validate both the manifest structure and its embedded PoE proof before installation or during runtime to establish trust.


Goals

  • Bind app packages to publisher DIDs and signing certificates with cryptographic proofs
  • Prevent key compromise attacks using TEE-backed PoE proofs
  • Support multiple platforms (Android, iOS, web extensions, desktop, server)
  • Enable both HTTPS-based (.well-known) and DIDComm-based manifest distribution
  • Provide certificate rotation with grace periods
  • Support revocation of compromised certificates and packages
  • Integrate device attestation (Play Integrity, App Attest, TPM) into proofs
  • Maintain privacy through zero-knowledge proofs

Roles

  • publisher (Registered Entity): Owns the domain and app, controls a Publisher DID, hosts PAM at /.well-known/app-auth.json. Generates PoE proofs during manifest creation.

  • verifier: Client SDK/app or service that validates PAM structure, PoE proofs, and compares to observed package metadata.

  • attester (optional): TEE-backed secure execution environment (SGX, TrustZone, Secure Enclave) that generates PoE proofs on behalf of the Publisher, proving the manifest was created with proper authorization and device attestation.

  • re-agent (optional): Serves PAM via DIDComm for pairwise/air-gapped/offline flows.


Transport & Security

HTTPS Path

Verifier MUST GET https://<domain>/.well-known/app-auth.json over TLS 1.2+.

The payload MUST be a JSON structure containing the manifest data and an embedded PoE proof.

PoE Integration

The manifest MUST include a PoE proof generated by the program_id didcomm.pam.legitimacy.v1 that cryptographically proves:

  • The manifest was created in a secure execution environment
  • The Publisher had proper authorization at creation time
  • Device/platform attestation passed (Play Integrity, App Attest, or equivalent)
  • The manifest content integrity is bound to the proof via context_hash

Domain ↔ DID Binding

Publisher MUST publish a DID Configuration (Domain Linkage Credential) at /.well-known/did-configuration.json. Verifiers MUST validate domain linkage before trusting the manifest.

DIDComm Path (Optional)

pam/fetch over DIDComm v2 authcrypt. Content SHOULD be encrypted (JWE). The PoE proof provides signature guarantees, so additional JWS wrapping is redundant.

Clock & Freshness

Verifiers MUST enforce nbf/exp in the PAM payload, validate the PoE proof's nonce freshness, and MUST fail closed on clock-skew greater than policy (default 5 minutes).


Data Model

Top-Level Structure

{
  "iss": "did:example:publisher",
  "sub": "https://example.com",
  "jti": "pam-2b0d-…",
  "iat": 1731350400,
  "nbf": 1731350400,
  "exp": 1734032400,
  "pam": {
    "version": "1.0",
    "publisher": {
      "did": "did:example:publisher",
      "org": "Example Corp",
      "contact": "[email protected]"
    },
    "artifacts": [ /* see Artifacts section */ ],
    "policies": { /* see Policies section */ },
    "rotation": { /* see Rotation section */ },
    "revocations": { /* see Revocations section */ },
    "evidence": { /* optional */ }
  },
  "poe_proof": {
    "program_id": "didcomm.pam.legitimacy.v1",
    "result": "pass",
    "public": {
      "schema": "didcomm.pam.legitimacy.v1/public@1",
      "nonce": "0x<32-byte-hex>",
      "context_hash": "0x<32-byte-hex>",
      "session_id": "0x<16-byte-hex>",
      "publisher_did": "did:example:publisher",
      "domain": "https://example.com",
      "manifest_hash": "0x<32-byte-hex>",
      "timestamp": 1731350400,
      "vk_hash": "0x<32-byte-hex>"
    },
    "zk": {
      "scheme": "stark",
      "circuit_id": "didcomm-pam-legitimacy-v1",
      "vk_hash": "0x<32-byte-hex>",
      "proof_b64": "base64(urlsafe)…"
    },
    "attestation": {
      "platform": "android",
      "attestation_type": "play_integrity",
      "attester_did": "did:example:attester",
      "attestation_timestamp": 1731350400
    }
  }
}

Artifacts (per platform package binding)

{
  "platform": "android|ios|webext|desktop|server",
  "package_id": "com.example.app",
  "signing": {
    "cert_sha256": ["ABCD…", "…"],
    "sig_alg": "SHA256withRSA|ECDSA_P256"
  },
  "distribution": {
    "channels": ["play", "appstore", "direct", "chrome_web_store"],
    "urls": ["https://play.google.com/…", "https://example.com/downloads/app.apk"]
  },
  "versions": {
    "min": "1.2.3",
    "max": "2.*",
    "pinned": []
  },
  "integrity": {
    "hash_alg": "sha256",
    "apk_digest": [],
    "sri": []
  },
  "policy_hints": {
    "min_sdk": 26,
    "permissions_max": ["CAMERA", "BLUETOOTH"],
    "risk_flags": ["needs_camera_for_liveness"]
  },
  "attestation_policy": {
    "android": {
      "play_integrity": {
        "require_cts_profile_match": true,
        "require_basic_integrity": true,
        "package_name": "com.example.app",
        "certificate_digests": ["ABCD…"]
      }
    },
    "apple": {
      "app_attest": { "require_pass": true }
    }
  },
  "metadata": {
    "support_url": "https://example.com/security",
    "privacy_policy": "https://example.com/privacy"
  }
}

Policies

{
  "install": {
    "must_match_signing": true,
    "must_match_distribution_channel": false
  },
  "runtime": {
    "require_attestation": true,
    "refresh_interval_hours": 24
  },
  "verification": {
    "allow_clock_skew_seconds": 300,
    "require_strict_tls": true
  }
}

Rotation

{
  "next_manifest_at": "https://example.com/.well-known/app-auth-next.json",
  "grace_period_hours": 168,
  "allowed_overlap_cert_sha256": ["…"]
}

Revocations

{
  "cert_sha256": ["REVOKED_FINGERPRINT…"],
  "package_ids": ["com.example.badapp"],
  "advisories": [
    {
      "id": "ADV-2025-0001",
      "severity": "high",
      "reason": "supply-chain incident date …",
      "effective": "2025-11-01T00:00:00Z"
    }
  ]
}

Evidence (Optional)

Pointers to transparency logs, notarization receipts, or signed build attestations (SLSA, Sigstore).


PoE Program Specification

Program ID: didcomm.pam.legitimacy.v1

Purpose: Prove that a PAM was created by an authorized Publisher in a secure execution environment with valid device attestation.

Private Inputs (not revealed in proof)

  • Publisher's signing keys
  • Device attestation tokens (Play Integrity response, App Attest assertion, TPM quote)
  • Authorization credentials (MFA tokens, access control proofs)
  • Environment secrets

Public Inputs (revealed in proof)

  • publisher_did: The Publisher's DID
  • domain: The domain hosting the PAM
  • manifest_hash: SHA256 of the entire pam object
  • timestamp: Unix timestamp of manifest creation
  • nonce: Fresh random nonce (prevents replay)
  • context_hash: SHA256(iss||sub||jti||pam) binding proof to this specific manifest
  • session_id: Unique session identifier

Proof Requirements

  1. MUST verify that the private signing key corresponds to publisher_did
  2. MUST verify that the device attestation is valid and current (not expired, not revoked)
  3. MUST verify that the manifest_hash matches SHA256(pam object)
  4. MUST verify that context_hash correctly binds all public fields
  5. MUST verify that authorization credentials are valid at timestamp
  6. Result MUST be "pass" for the manifest to be accepted

Circuit Constraints

  • Device attestation timestamp MUST be within 5 minutes of manifest timestamp
  • Publisher DID MUST match the attested identity
  • All cryptographic signatures MUST verify correctly

Validation Algorithm (Verifier)

Step 1 - Fetch: GET /.well-known/app-auth.json over HTTPS.

Step 2 - Domain Link: Fetch and verify DID Configuration at /.well-known/did-configuration.json to assert domain ↔ iss (Publisher DID).

Step 3 - PoE Registry Check:

  • Verify program_id "didcomm.pam.legitimacy.v1" is in the verifier's trusted program registry
  • Verify vk_hash from poe_proof.zk.vk_hash matches an allowed verifying key for circuit_id "didcomm-pam-legitimacy-v1"
  • Reject if program or vk_hash is not in registry

Step 4 - PoE Proof Verification:

  • Verify ZK proof using: verify_zk(proof_b64, public, circuit_id, vk_hash)
  • Verify context_hash = SHA256(iss||sub||jti||pam)
  • Verify manifest_hash = SHA256(pam object)
  • Verify nonce is fresh (not previously seen, within acceptable time window)
  • Verify timestamp is within nbf/exp bounds
  • Verify result = "pass"
  • MUST reject if any verification fails

Step 5 - Freshness: Enforce nbf/exp timestamps in PAM payload.

Step 6 - Attestation Policy: Verify attestation.attestation_type matches required platform attestation (e.g., Play Integrity for Android, App Attest for iOS).

Step 7 - Artifact Match: Locate artifact matching observed platform, package_id, cert_sha256 (and optional version).

Step 8 - Policies: Enforce policies.install/runtime and attestation_policy requirements.

Step 9 - Rotation: If next_manifest_at present and within grace period, accept either manifest while overlapping certs are listed in rotation.allowed_overlap_cert_sha256.

Step 10 - Revocations: If any cert_sha256 or package_id matches revocations → BLOCK.

Decision

Return structured verdict:

  • trusted: All checks passed, PoE proof valid, artifact matches
  • untrusted: PoE proof invalid, revoked, or attestation failed
  • unknown: Artifact not found in manifest or registry check failed

CRITICAL: Verifiers MUST fail closed. Any error in PoE verification MUST result in "untrusted" verdict.


Message Reference

All messages use DIDComm v2 with type = https://didcomm.org/pam/1.0/<message-name>, standard headers (id, thid, from, to, expires_time). Use authcrypt.

fetch

Message Type URI: https://didcomm.org/pam/1.0/fetch

Purpose: Request PAM manifest from Publisher or RE Agent.

From: verifier → publisher/re-agent

Body:

{
  "domain": "example.com",
  "nonce": "0x<32-byte-hex>"
}

The nonce parameter allows the Requester to request a fresh PoE proof bound to their specific verification session.


publish

Message Type URI: https://didcomm.org/pam/1.0/publish

Purpose: Deliver PAM manifest with PoE proof.

From: publisher/re-agent → verifier

Body:

{
  "domain": "example.com",
  "pam_payload": { /* full PAM structure with poe_proof */ },
  "served_at": "2025-11-12T10:30:00Z"
}

MUST be authcrypt (DIDComm v2 encrypted). The embedded PoE proof provides authenticity, so additional JWS wrapping is not required.


Interactive PoE Generation (Advanced)

For high-security use cases, Requesters MAY invoke the PoE protocol directly:

  1. Send poe/request-poe with program_id="didcomm.pam.legitimacy.v1"
  2. Include bind_to_context with nonce, context_hash, session_id
  3. Receive poe/submit-poe with the ZK proof
  4. Construct the PAM manifest with the received proof
  5. Optionally cache the manifest at /.well-known/app-auth.json

This flow allows real-time proof generation and verification for air-gapped or pairwise scenarios.


Error Codes

Error codes (using DIDComm problem-report):

  • auth/unauthorized: Publisher authentication failed
  • did-linkage/missing: DID Configuration not found or invalid
  • poe/invalid: PoE proof verification failed
  • poe/vk_unknown: Verifying key not in registry
  • poe/program_not_supported: Program ID not supported
  • expired: Manifest or proof expired
  • cert/mismatch: Certificate doesn't match artifact
  • rotation/not-yet-valid: Rotation window not yet active
  • attestation/failed: Device attestation verification failed
  • too-large: Payload exceeds size limits

Security Analysis

Protection Against Key Compromise

Traditional JWS-only manifests are vulnerable to key compromise attacks. If an attacker obtains the Publisher's signing key, they can create fake manifests that pass JWS verification.

PAM with PoE integration prevents this attack vector:

Attack Scenario: Attacker steals Publisher's signing key

  • Traditional PAM: Attacker signs fake manifest → passes verification ✗
  • PoE-secured PAM: Attacker cannot generate valid PoE proof without:
    1. Access to the secure execution environment (TEE)
    2. Valid device attestation at signing time
    3. Authorization credentials (MFA, access controls)
    4. Ability to bind proof to current timestamp and fresh nonce

Result: Even with stolen keys, attackers cannot create valid manifests.

Replay Attack Prevention

The PoE proof binds to:

  • nonce: Prevents replaying old proofs
  • context_hash: Binds proof to specific manifest content
  • session_id: Prevents cross-session replay
  • timestamp: Enforces temporal validity

Verifiers MUST maintain a nonce cache and reject previously-seen nonces within the validity window.

Device Attestation Integrity

The PoE circuit verifies device attestation inside the proof without revealing:

  • Attestation tokens or responses
  • Device identifiers or hardware fingerprints
  • Authorization credentials

This provides strong device binding while preserving privacy.

Supply Chain Security

The combination of:

  • PoE proof of secure signing environment
  • Device attestation
  • DID Configuration domain linkage
  • Certificate pinning in artifacts[]
  • Optional transparency log evidence

Creates a multi-layered defense against supply chain attacks, compromised build systems, and malicious package injection.

Threat Model

Protected Against:

  • ✓ Stolen signing keys (requires TEE + attestation)
  • ✓ Replay attacks (nonce + context binding)
  • ✓ Manifest tampering (context_hash integrity)
  • ✓ Unauthorized signers (authorization proof required)
  • ✓ Compromised servers (attestation proves signing environment)
  • ✓ Time-based attacks (timestamp binding + freshness checks)

Not Protected Against:

  • ✗ Complete compromise of TEE/secure enclave
  • ✗ Publisher's intentional malicious manifest creation
  • ✗ Verifier implementation bugs
  • ✗ Registry poisoning (verifiers must maintain secure registries)

Mitigation: Use trusted attester services, transparency logs, and multi-party verification for high-value applications.


Composition

Supported Goal Code Notes
poe/programs PAM uses PoE program didcomm.pam.legitimacy.v1
  • Proof of Execution (PoE) 1.0: Core dependency for ZK proofs
  • DID Configuration: Domain ↔ DID binding
  • Report Problem 2.0: Error reporting
  • Discover Features 2.0: Capability negotiation

References


Endnotes

This protocol provides a foundation for establishing cryptographic trust in software distribution by combining DIDs, zero-knowledge proofs, and device attestation. It is designed to work alongside existing app distribution infrastructure while adding strong security guarantees against supply chain attacks.

PIURI
https://didcomm.org/pam/1.0
Status
Proposed
Version
1.0
License
MIT
Last modified
2026 Jul 22, 15:07 PM