This document outlines a mechanism that could enable elision of certain aspects of a DID document. The core idea is that we can define and register new types in the DID Extensions registry for elided content such as verification methods and service endpoints while still being conformant with the DID core data model.
For example we could define and register the type ElidedMultikey.
An ElidedMultikey is a type of verification method. Instead of including the verification material in directly publicKeyMultibase
a SHA256 hash of the verification material (including the multikey prefix) is first computed and then the bytes are multibase encoded using base58-btc.
Question: Should we just reuse the publicKeyMultibase
value, or define a new property e.g. elidedMultibase
.
An ElidedMultikey can be converted into a Multikey if an entity knows the verification material that was elided. First they check the elided publicKeyMultibase
value matches the verification material. Then if equal, they substitute the ElidedMultikey verification method for a Multikey verification method using the verification material.
More precisely we can define two algorithms elide
and reveal
:
Takes as inputs a multikey verification method, vm
and returns the corresponding ElidedMultkey verification method.
elidedVm
to a copy of vm
pkMultibase
to vm.publicKeyMultibase
keyBytes
to the multbase decoding of pkMultibase
elidedBytes
to the SHA256 hash of keyBytes
elidedMultibase
to the base58-btc multibase encoding of elidedBytes
elidedVm.publicKeyMultibase
to elidedMultibase
elidedVm
Takes as inputs an ElidedMultikey verification method, elidedVm
, an a publicKeyMultibase
and returns the corresponding Multikey verification method.
elidedKeyBytes
to the multibase decoding of elidedVm.publicKeyMultibase
keyBytes
to the multibase decoding of publicKeyMultbase
hashKeyBytes
to the SHA256 hash of keyBytes
hashKeyBytes
!= keyBytes
throw an InvalidElidedKey
errorvm
to a copy of elidedVm
vm.publicKeyMultibase
to publicKeyMultibase
vm
An alternative approach might be to define a verification method type ElidedVM or something. Instead of the elided value being the just the publicKeyMultibase, it could be the hash of the entire verification method object which I guess would need to be canonicalized first.
This would be a more generic and flexible approach, so maybe it is better. Not sure.
Reacting to Christophers use case
The first use case is in support of principles of key separation and unnecessary disclosure of correlatable public keys. Best practices of key separation means not using the same keys for everything, and even further, if you have multiple devices, having different keys for each device. For instance, each of my development machines have their own set public keys, one for each proof-purpose which they support. I should not have to disclose all of my public keys for all of my device — instead, only when they are needed for their proof-purpose. With elision, I can commit to a public key and a proof purpose, but only reveal it to a verifier when they need it, and only cthe key that they need to verify. They can know it was committed previously, and that it should be accepted on the ~same trust level as the keys they've already accepted, as they were all committed together.
To achieve this, we would want to elide many keys in a single verification method. I think the proposed ElidedMultikey approach could adapted using merkle trees, such that a elided verificationMethod is a merkle root for a tree of keys.
The idea is still that given some set of data, it is possible to reveal a Multikey verification method that can be verified as being in the DID document. Then proof verification can proceed using that Multikey. In this case the set of data would be the a multikey AND a merkle proof.
Note, this is very similar to how Taproot works. Taproot, is a root of a taptree. A tree of scripts, that can be revealed along with a proof path. That way, you can commit to many different Bitcoin scripts and only reveal certain scripts at spend time.
For example, we could define a VM type ElidedMerkleMultikey
, or something …
To generate a verificationMethod of the type ElidedMerkleMultikey, you would follow roughly these steps.
{
"id": "did:example:123#key1",
"type": "ElidedMerkleMultikey",
"merkleRootMultibase": <merkle-root>
}
To use one of the keys to generate a Data Integrity proof, you use the key as if it were a Multikey and follow whatever Data Integrity cryptosuite algorithm. However, when it comes to identifying the verification method used to generate the proof you must pass in the additional data. Maybe this could be done using query parameters?
The data that needs to be passed is:
Imagine these are both base58-btc multibase encoded. Then perhaps we can use query parameters to identify this key?
For example
did:example:123#key1?multikey=<key_encoding>&merkleProof=<merkle_proof_encoding>
If that is the case, then the proof object would look something like this:
{
"type": "DataIntegrityProof",
"cryptosuite": "bip340-jcs-2025",
"created": "2023-02-24T23:36:38Z",
"verificationMethod": "did:example:123#key1?multikey=<key_encoding>&merkleProof=<merkle_proof_encoding>",
"proofPurpose": "assertionMethod",
"proofValue": "z3P1WFufkFdaA9HM9jd4SYrGFbYYKzymhoYoqLHSG2zVfhjaTXFtdiQ1EwBt8X11x6rPccMdQxmhcYTfd6btY2nWt"
}
I guess the verificationMethod id string might get quite large, depending how big the merkle tree is. But I think it is manageable.
Verifying this proof is relatively simple. The verifier just needs to be able to dereference the verificationMethod
property to get a Multikey
verification method and continue as normal.
So how might we derefence did:example:123#key1?multikey=<key_encoding>&merkleProof=<merkle_proof_encoding>
Some high level steps:
did:example:123
did:example:123#key1?multikey=<key_encoding>&merkleProof=<merkle_proof_encoding>
This would involve, finding the verificationMethod at #key1, which is
{
"id": "did:example:123#key1",
"type": "ElidedMerkleMultikey",
"merkleRootMultibase": <merkle-root>
}
Then attempting to reveal the elided Multikey using the multikey and merkleProof provided by the query. If successful, the result of dereferencing could look like this:
{
"id": "did:example:123#key1?multikey=<key_encoding>&merkleProof=<merkle_proof_encoding>",
"type": "Multikey",
"publicKeyMultibase": <publicKey>
}