Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to allowing portable=true #173

Open
ankurdotb opened this issue Feb 5, 2025 · 2 comments
Open

Default to allowing portable=true #173

ankurdotb opened this issue Feb 5, 2025 · 2 comments

Comments

@ankurdotb
Copy link

The issue

The spec currently states:

portable: A boolean (true / false) indicating if the DID is portable and thus can be renamed to change the Web location of the DID.
The value can ONLY be set to true in the first log entry, the initial version of the DID.
If not explicitly set in the first log entry, it MUST be set to false.
Once the value has been explicitly set to false in a DID log entry, it MUST NOT be set back to true.

It's big ask to expect a user to know beforehand whether they want portability or not, and explicitly ask for. In general, the Web has defaulted to allowing things to be portable: you can move hosts, domain registrars, etc.

I can see the security argument for locking it, but I see this as similar to DNSSEC or HSTS. Crucially, neither DNSSEC or HSTS are usually on by default. If a user so chooses, like using these two mechanisms, to set portable=false that's fine but we should not expect people by default to have their DIDs as non-portable.

Example scenario

It's very unlikely that the user would have anticipated this "need" to have their DID portable many years in advance of needing to move it, and choosing at the time. Therefore, the default setting for portable should be true.

Portable, after timelock

An associated thought is that even for users who chose to not opt-in to portability, only being able to choose it once - at genesis - is a bad idea. An alternative suggestion here is to allow for portability even after genesis, while balancing security.

As an analogy, this would be similar to HSTS or DNSSEC: instead of portability being possible immediately, it would only be possible after the passage of a defined period of time set when portability is turned on (whether at genesis or some point after genesis). This would mean in addition to portable=true/false there would also be a parameter like portabilityLockDuration=XXXXX (I would use seconds like in HSTS). In HSTS, for example, HSTS preloading is only done if the max age for HSTS timelock is at least one year.. In practice this means if someone compromises the TLS certificates, there's a certain minimum duration, e.g., 1 year that the certificate can be pinned for.

This would sufficient time in case of a malicious portability request was made for the DID author to off-channel be able to signal/inform people that there was something wrong, and can't immediately be use by an attacker to port the DID. The spec already talks about DID to HTTPS transformation, so aligning with HSTS preload time as a lock duration is also conceptually close.

If timelocks are play

We can modify the spec as follows to take into account portability by default and timelocks as:

  • Have portability set to true by default
  • Optionally, allow the user to set a lock duration before which porting can be done. Don't make this a long duration by default. If the user chooses, they opt in to this (just like HSTS)
  • Setting portability=false is kinda like setting portability to infinity seconds, so perhaps they can be combined, although I do like the idea of keeping them separate.
  • If set to false, recommend setting a timelock so that that if it's flipped from false to true, this action can only be done after lock duration expires.
@swcurran
Copy link
Collaborator

swcurran commented Feb 6, 2025

So two parts — changing the default to “true” for portable on creation, and a “lock” mechanism.

A DID Controller that is not certain can set ”portable”: true in the first record to handle the default issue, but as noted, they have to explicitly do that. We can discuss changing that. We should do that change before 1.0 if we are going to.

Assumption: The lock mechanism would be something like: ”portablity_lock”: 5 where 5 is the number of days after setting the lock before the DID can be changed. Not sure we would need more precise timing than days.

A challenge with that is that it would have to be based on version_time, which is self-declared by the DID Controller, and the only checks on it are that it is increasing and earlier than “now()” (for any resolver) — not that it is accurate. For example, we don’t have a check in the witnesses verification that the new entry’s versionTime is “recent”. As such, once set, a lock could only be extended.

I think that did:plc has kind of the reverse in its design — 72 hours to “undo” an update to a DID.

@ankurdotb
Copy link
Author

Yeah, two different things, but I wanted to raise the idea of a lock mechanism along with changing default, as it might address the concerns of people who wanted it false by default.

Specifying lock-in period: I would suggest sticking to seconds like HSTS does with max-age= 31536000 which is 1 year. Rationale: it allows people to specify hours/minutes (less than a day) as the lock period. Guess that's technically possible by saying "0.5 (days)" but since a lot of systems/languages natively count in seconds from epoch time, it leaves less to interpret about edge cases and at least if you specify in seconds you can always make it add up to days/months/years but not as easily the other way round starting with a large unit and specifying smaller. But yes certainly up for debate on whether a minimum of 1 day is good enough and make it whole numbers!

I think that did:plc has kind of the reverse in its design — 72 hours to “undo” an update to a DID.

True, there's a 72-hour window in which a "higher authority rotation key" can override a change:

The PLC server provides a 72hr window during which a higher authority rotation key can “rewrite” history, clobbering any operations (or chain of operations) signed by a lower-authority rotation key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants