KIP | Title | Author | Status | Type | Category | Created |
---|---|---|---|---|---|---|
0022 |
Disable guard rotation for coin-contract principal accounts |
Greg Hale @imalsogreg |
Draft |
Standard |
Interface |
2023-09-28 |
The ability for an account holder to rotate their guard is granted by the rotate
function in the coin contract.
This is a natural operation to want for a normal username/secret governance
model. But it is not safe for use on Principal accounts, because Principal
account names are meant to be derivable from the guard that governs them. The
guard is the source of truth about the Principal account string. Rotating
to a new guard therefore breaks a Pact invariant. A Principal account with a
rotated guard would not be recognized by Pact as a Principal account, which
would cause it to fail a number of common safety checks in coin contract.
This KIP proposes to add an assertion to the rotate
function during the next
upgrade of the coin contract, to protect principal account users from the
negative effects of rotating their account guard.
To diable guard rotations on principal accounts, we will add an assertion to the rotate function:
(defun rotate:string (account:string new-guard:guard)
(with-capability (ROTATE account)
; **************************************
; *** Add this new enforce statement ***
; **************************************
(enforce (or (not (is-principal account))
(validate-principal new-guard account))
"It is unsafe for principal accounts to rotate their guard")
(with-read coin-table account
{ "guard" := old-guard }
(enforce-guard old-guard)
(update coin-table account
{ "guard" : new-guard }
)))
)
The enforce
call enforces that either the account is not a principal account,
or if the account is a principal then we are rotating to the (original) correct
guard for the principal.
This change will roll out with the next deployment of coin contract, which is scheduled for December 2023.
Non-principal accounts (e.g. vanity accounts) are unaffected by this change. Principal accounts that have already rotated their guards are unaffected by this change.
Principal accounts for whom guard rotation is an important part of their expected workflow need to identify a new workflow. Since most accounts are principal accounts, this means all accounts should expect not to be able to rotate guards under an account. Please see Workarounds for alternative solutions.
Principal account holders (most accounts, including all "k:" accounts, are principal, accounts), may want some way to rotate their guard, analogous to the common security measure of regularly changing your password or rotating certificates or other security credentials. But the invariants that relate Principal account names to their guards explicitly preclude this. How else can credentials be rotated?
The simplest solution is to rotate your principal account, not your guard; namely, create a new account and transfer funds to it.
Another option, "keyset-guards" allows safe credential rotation without using the
rotate
function, if you create your account as a r:
(KeySet Principal) account.
Account names are derived from the name of the KeySet that guards them, and
you are free to update the keys in that KeySet.
(coin.create-account
(create-principal (keyset-ref-guard "<some keyset name>"))
(keyset-ref-guard "<some keyset name>"))