FR EN

Documents DID

Un vérificateur résout deux documents DID pour contrôler un reçu : le document de l'entreprise pour companySig, et le document du citoyen pour l'assertion WebAuthn. Ils utilisent des méthodes DID différentes et exposent les clés différemment.

Le document DID de l'entreprise

Résolu depuis did:web:agreely.ca:c:{slug} à https://agreely.ca/c/{slug}/did.json. Il ne se résout que lorsque l'entreprise a un domaine vérifié et une clé de signature active.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/data-integrity/v2"
  ],
  "id": "did:web:agreely.ca:c:acme",
  "alsoKnownAs": ["did:web:acme.com"],
  "verificationMethod": [
    {
      "id": "did:web:agreely.ca:c:acme#kms-1",
      "type": "Multikey",
      "controller": "did:web:agreely.ca:c:acme",
      "publicKeyMultibase": "z6Mk...base58btc..."
    }
  ],
  "assertionMethod": ["did:web:agreely.ca:c:acme#kms-1"],
  "authentication": ["did:web:agreely.ca:c:acme#kms-1"]
}
Champ Signification
id Le DID d'entreprise hébergé par Agreely.
alsoKnownAs Le DID du domaine réel et vérifié de l'entreprise, la liaison qui prouve que l'identifiant hébergé par Agreely appartient à l'organisation réelle.
verificationMethod[].type Multikey.
verificationMethod[].publicKeyMultibase La clé publique Ed25519 en base58btc préfixée par z de `(ed25519-pub multicodec 0xed01
assertionMethod / authentication Référencent le fragment de la clé de signature.

La clé d'accès racine et la délégation (additives)

Lorsqu'une entreprise a enregistré une clé d'accès racine et signé une délégation, le même document publie additivement deux éléments de plus. Une entreprise sans racine ni délégation produit exactement le document ci-dessus.

{
  "verificationMethod": [
    { "id": "did:web:agreely.ca:c:acme#kms-1", "type": "Multikey", "controller": "did:web:agreely.ca:c:acme", "publicKeyMultibase": "z6Mk..." },
    {
      "id": "did:web:agreely.ca:c:acme#root-1",
      "type": "WebAuthnAuthenticationKey2024",
      "controller": "did:web:agreely.ca:c:acme",
      "publicKeyCose": "0xa5010203262001...",
      "rpId": "agreely.ca"
    }
  ],
  "capabilityDelegation": ["#root-1"],
  "delegation": {
    "type": "agreely.keyDelegation.v1",
    "body": { "type": "agreely.keyDelegation.v1", "companyDid": "did:web:agreely.ca:c:acme", "delegatee": { "keyId": "0x..." }, "rootKeyId": "0x...", "registry": "0x...", "chainId": "8453", "rpId": "agreely.ca", "nonce": "0x...", "validFrom": "2026-07-20T15:00:00Z", "validUntil": "2027-07-20T15:00:00Z" },
    "proof": {
      "type": "WebAuthnDelegationProof2026",
      "verificationMethod": "did:web:agreely.ca:c:acme#root-1",
      "authenticatorData": "<base64url>",
      "clientDataJSON": "<base64url>",
      "signature": "<base64url>"
    }
  }
}
Champ Signification
#root-1 La clé d'accès racine de l'entreprise, sous capabilityDelegation (la relation W3C correcte : « la racine délègue une capacité à une clé subordonnée »). Son publicKeyCose est la clé publique COSE brute en 0x-hex; son empreinte keccak doit égaler le root= du DNS de l'entreprise.
capabilityDelegation Référence #root-1 : la seule capacité de la racine est de déléguer, jamais de signer un consentement ni d'authentifier.
delegation.body Le corps canonique sans nombre exact que le défi WebAuthn a haché (challenge = keccak(JCS(body))), de sorte qu'un vérificateur recompose le défi lui-même.
delegation.proof Le type de preuve propriétaire documenté WebAuthnDelegationProof2026 : les artéfacts d'assertion WebAuthn bruts (base64url) vérifiés par rapport à la clé COSE de #root-1. Il n'existe pas de cryptosuite WebAuthn Data Integrity ratifiée, d'où une recette de vérification publiée.

Une clé de récupération enrôlée, s'il y en a une, apparaît en plus comme Ed25519VerificationKey2020 sous capabilityInvocation (autorisée uniquement à faire tourner la racine).

Le document DID du citoyen

Résolu depuis did:agreely:citizen:.... Il est public, non authentifié et sans locataire par conception (tout vérificateur peut le résoudre). Il est assemblé à partir de l'historique complet des clés, de sorte que chaque clé que le DID a détenue apparaît avec sa fenêtre d'autorité.

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B",
  "verificationMethod": [
    {
      "id": "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B#passkey-1",
      "controller": "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B",
      "validFrom": "2026-01-10T14:00:00Z",
      "validUntil": null,
      "type": "WebAuthnAuthenticationKey2024",
      "publicKeyCose": "0xa5010203262001..."
    },
    {
      "id": "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B#recovery-1",
      "controller": "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B",
      "validFrom": "2026-01-10T14:00:00Z",
      "validUntil": null,
      "type": "Ed25519VerificationKey2020",
      "publicKeyMultibase": "z6Mk...base58btc..."
    }
  ],
  "authentication": [
    "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B#passkey-1"
  ],
  "capabilityInvocation": [
    "did:agreely:citizen:9F8K2M4P7Q1R3T5V8W0X2Y4Z6B#recovery-1"
  ]
}
Champ Signification
validFrom / validUntil La fenêtre d'autorité de la clé. validUntil est présent même lorsqu'il vaut null, afin qu'un vérificateur distingue « encore valide » de « expirée à T ». Un reçu signé au temps T se résout vers la clé qui faisait autorité à T.
WebAuthnAuthenticationKey2024 Une clé d'accès. Son publicKeyCose est la clé publique encodée en COSE sous forme 0x-hex; vérifiez-en l'assertion WebAuthn du reçu.
Ed25519VerificationKey2020 Une clé de récupération, exposée comme publicKeyMultibase.
authentication Fragments de clés d'accès (autorisés à signer un consentement).
capabilityInvocation Fragments de clés de récupération, autorisés uniquement pour la rotation du DID, jamais pour signer un consentement.

La fenêtre est ce qui garde valides les anciens reçus

Lorsque vous vérifiez proof[1] d'un reçu, prenez son fragment verificationMethod, trouvez cette méthode dans le document citoyen, et confirmez que sa fenêtre [validFrom, validUntil] contient le grantedAt du reçu. Vérifiez ensuite l'assertion par rapport à la clé COSE de cette méthode. Une clé retirée par rotation vérifie toujours ses reçus historiques.

Ensuite