在合約錢包的 Recovery 機制中會有 Owner 及 Guardian 兩種角色。
Owner 是錢包的主人,也就是使用者。可以同時有多個 Owner,像是多簽錢包,但以下都會以單一 Owner 為例
Guardian 是負責進行 Recovery 的角色,使用者可以同時指定多個 Guardian 以及 Guardian 操作能生效的門檻值。以下描述 Guardian 的操作都會假設已經超過門檻值數量的 Guardian 的同意,不會再細分有無超過門檻值討論
不同於 EOA Recovery 中的 Guardian 可能會和使用者有複雜的互動,例如 Guardian 會負責保管使用者加密過的 Share 並在使用者需要時交還加密的 Share,讓使用者還原出私鑰、完成 Recovery。合約錢包裡的 Guardian 都是和合約進行互動來完成 Recovery,所以接下來的內容都是圍繞在 Owner 及 Guardian 兩個角色各自和合約錢包之間的互動而不是 Owner 和 Guardian 之間的互動。
updateGuardians
:Owner 可以透過 updateGuardians
更新 Guardian 的名單,新增新的 Guardian 或移除舊的 Guardian
resetOwner
:Guardian 可以透過 resetOwner
更新 Owner 地址,也就是執行 Recovery
以上是 Recovery 機制裡的角色及相關操作介紹,看起來不會很複雜 – 兩個角色與兩種操作。但隨著引入對不同角色的信任假設(例如不相信 Guardian),就會需要加上不同的檢查措施與反制機制,這時 Recovery 機制就會越來越複雜。這也是本文的目的:藉由分析不同角色的安全假設並列舉出相對應的反制方法,讓 Recovery 機制的設計變得清晰、讓分析 Recovery 機制變得簡單。
如果假設 Owner 和 Guardian 都是可信的話,那 Recovery 機制真的就會非常簡單,但 Web3 世界裡的使用者及開發者可不會輕易地做出這樣的假設。接下來會分別假設 (1) Guardian 可能是惡意的以及 (2) Owner 可能是惡意的(待會會解釋為什麼)兩種情況,並分別討論當有了這樣的假設,合約錢包的 Recovery 機制該怎麼配合做調整。
如果我們不放心 Guardian 有任意 resetOwner
的權力,可以在 resetOwner
裡加上時間鎖,在惡意 Guardian 觸發 resetOwner
時讓 Owner 有時間反應並取消 resetOwner
。
但請記得 時間鎖並不能免除對 Guardian 的信任,只要 Owner 沒有在時間鎖結束之前去取消 Reset,那 Reset 一樣會生效,惡意的 Guardian 一樣可以奪走使用者的錢包控制權
答案是:沒有,這是因為「合約本身沒辦法知道使用者是否遺失私鑰」,所以它必須要授權 Guardian 有完全的權力來 resetOwner
。除非我們能假設私鑰不會遺失。
但如果私鑰不會遺失,我們還需要 Recovery 機制嗎?雖然「私鑰不會遺失」這種假設非常少見,或甚至沒有實際意義,但錢包設計者在設計規則時還是會考慮到「私鑰遺失」以外的情況,例如「私鑰被盜」。接下來馬上就會介紹到,多了這個「私鑰被盜」的假設將會大大改變 Recovery 設計,或甚至在最後我們會發現:沒有一個 Recovery 機制能同時應付「私鑰遺失」、「私鑰被盜」與「惡意 Guardian」的情況。接下來,讓我們先討論「Owner 可能是惡意的」的情況,再一步一步揭曉「私鑰遺失」、「私鑰被盜」與「惡意 Guardian」這三個假設對 Recovery 設計的影響。
📖 Recap:如果假設 Guardian 可能是惡意的,那可以為
resetOwner
操作加上時間鎖。但記得加上時間鎖並不代表能免除對 Guardian 的信任。
你可能會覺得奇怪,為什麼會假設 Owner(基本上就是使用者自己)可能是惡意的?這是當我們假設 Owner 的私鑰可能會被盜所需考慮的情況。因為我們賦予 Owner updateGuardians
的權力,讓 Owner 可以更新 Guardian 名單,所以如果 Owner 私鑰可能被盜,那就會導致攻擊者拿到 Owner 私鑰後直接把 Guardian 名單換掉,接著再換掉 Owner,如此使用者就等於失去錢包控制權了。即便使用者設定了再多 Guardian、用了再複雜的 Recovery 機制都毫無用處 – Owner 私鑰變成安全的破口,只要一被盜就等於失去錢包控制權。
如果假設 Owner 私鑰可能被盜,那合約錢包的 Recovery 機制就必須要加入額外的保護機制來處理 Owner 私鑰被盜的情況。
因此 Owner 的 updateGuardians
操作會加上時間鎖,且可以由 Owner 自己取消。Owner 可以自己取消的原因是因為私鑰被盜不代表失去私鑰,只是代表攻擊者和使用者同時都能使用同一把私鑰,因此使用者還是能透過 Owner 私鑰去取消攻擊者發起的 updateGuardians
,取消後就是透過 Guardian 執行 resetOwner
讓攻擊者手上的私鑰失去效用。
註:但相反地,攻擊者也可以取消使用者發起的 updateGuardians
,此時只能仰賴 resetOwner
發揮作用,否則就會陷入僵局,例如 Guardian 消失不見或換了一把私鑰,使用者透過 updateGuardians
去更新 Guardian 名單,但接著就被攻擊者取消。
📖 Recap:如果假設 Owner 私鑰可能被盜,那
updateGuardians
操作就需要加上時間鎖,並且是由 Owner 可以來自己取消updateGuardians
,取消之後再透過resetOwner
換掉私鑰,讓攻擊者手上的私鑰失去效用。
而因為假設 Owner 私鑰可能被盜,所以 resetOwner
的設計也需要改變。以下分別以 Guardian 不會是惡意及可能是惡意兩種情況做討論。
因為 Owner 私鑰可能被盜,所以 Guardian 的 resetOwner
操作不能設置時間鎖,因為如果有時間鎖的話,攻擊者就可以每一次都在時間鎖結束前取消 resetOwner
,導致 Recovery 機制永遠卡住。這時如果假設 Guardian 是可信的,resetOwner
就可以直接讓 Guardian 完成,也不需時間鎖。
註:如果 Guardian 不會是惡意的,updateGuardians
操作也可以讓 Guardian 幫忙取消。
📖 Recap:如果假設 Owner 私鑰可能被盜但 Guardian 不會是惡意的,那
resetOwner
就不需要時間鎖,直接由 Guardian 完成。另外 Guardian 也可以幫忙取消updateGuardians
。
如果 Guardian 可能是惡意的,這樣就不行授權 Guardian 可以直接完成 resetOwner
。那要把時間鎖加回去嗎?如同上一段提到,因為 Owner 私鑰有可能被盜所以不能讓 Owner 有完全的權力來取消 resetOwner
,如果我們要求 Owner 和 Guardian 一起同意才能取消時間鎖呢?這雖然可以防止攻擊者有權力直接取消,但如果 Guardian 是惡意的,那它肯定不會同意取消,等於 resetOwner
一定會成功,導致時間鎖形同虛設。因此時間鎖不適用在私鑰可能被盜與 Guardian 可能是惡意的假設前提下。
所以我們不用時間鎖,而是改成調整 resetOwner
的門檻:要求 resetOwner
要由 Owner 及 Guardian 一起同意才能執行。當 Owner 私鑰被盜,使用者會和 Guardian 一起執行 resetOwner
;當 Guardian 是惡意的,Owner 會用 updateGuardians
換掉 Guardian。
如此 私鑰被盜 或是 惡意 Guardian 都沒辦法執行 resetOwner
,但如果 同時發生 Owner 私鑰被盜和 Guardian 是惡意的,那還是會被攻擊者拿走控制權。
📖 Recap:如果假設 Owner 私鑰可能被盜且 Guardian 也有可能是惡意的,那
resetOwner
就不能加上時間鎖,而是要改成要求 Owner 和 Guardian 一起同意才能resetOwner
。如此 私鑰被盜 或是 惡意 Guardian 都沒辦法執行resetOwner
,但如果 同時發生 Owner 私鑰被盜和 Guardian 是惡意的,那還是會被攻擊者拿走控制權。
而且要注意的是:因為要 Owner 及 Guardian 一起同意,這表示 Owner 的私鑰是不能遺失的!這裡就是前面提到的「為什麼會需要考慮私鑰不會遺失的情況」,儘管私鑰不會遺失這種假設非常少見,但如果沒有注意到「私鑰遺失」、「私鑰被盜」與「惡意 Guardian」這些假設彼此之間衝突所產生的陷阱,就會設計出複雜但不安全的 Recovery 機制。
📖 Recap:如果
resetOwner
執行門檻要 Owner 及 Guardian 一起同意,那 Owner 的私鑰就不能遺失!如果resetOwner
使用時間鎖允許 Owner 在時間鎖結束前取消,那 Owner 的私鑰就不能被盜!沒有 Recovery 機制可以同時假設私鑰會遺失、私鑰會被盜與惡意 Guardian。
每個設計或機制都有它的極限,不同安全假設的 Recovery 機制也有各自的極限。就像假設私鑰會遺失的設計裡就無法不相信第三方的角色(Guardian),因為合約無法知道你的私鑰是否遺失,你一定會需要第三方的協助。
如果你不想完全相信 Guardian,你可以加入時間鎖來反制惡意 Guardian 並透過 updateGuardians
來換掉惡意的 Guardian。
如果在惡意 Guardian 的假設之上,又要再多假設 Owner 私鑰可能被盜,那 Recovery 機制又會變得更複雜:(1) Owner 的 updateGuardians
操作要加上時間鎖;(2) Guardian 的 resetOwner
操作要由 Owner 及 Guardian 一起同意,而且 Owner 不能遺失私鑰!
但再多、再複雜的機制都永遠無法同時應付 Owner 私鑰遺失、Owner 私鑰被盜 與 惡意 Guardian 這三種假設,這個就是 Recovery 機制的極限。在知道 Recovery 機制的極限後,剩下的就是按照需求並從這三種假設中選擇(最多)兩種,並按此假設去實作。詳細介紹可以參考後面的附錄。
合約錢包的 Recovery 機制中有 Owner 及 Guardian 兩種角色,各自可以執行 resetOwner
及 updateGuardians
兩個操作。在合約錢包的 Recovery 機制中,Owner 和 Guardian 都是和合約互動,而不是和彼此互動
接著端看對 Guardian 及 Owner 兩個角色的信任的假設,會改變 Recovery 機制的設計。如果 Guardian 不可信,那就要在 resetOwner
操作加上時間鎖,讓 Owner 有時間可以反應並取消
但請記得時間鎖並不是真的能移除對 Guardian 的信任,只要假設私鑰可能會遺失,就會需要賦予 Guardian 完全權力去執行 resetOwner
如果 Owner 不可信,那 updateGuardians
操作也需要加上時間鎖,並讓 Owner 可以自己取消。而 resetOwner
也會因為 Owner 不可信而必須改變設計
如果 Owner 不可信但 Guardian 可信,那 resetOwner
就不能加上時間鎖,而且 Guardian 也可以取消 updateGuardians
如果 Owner 和 Guardian 都不可信(但假設不會同時發生私鑰被盜與惡意 Guardian),那 resetOwner
就不能用時間鎖,而是改成要 Owner 和 Guardian 都同意才能執行。如此可以防止 私鑰被盜 或是 惡意 Guardian 的情況,但如果 同時發生 Owner 私鑰被盜和 Guardian 是惡意的,那還是會被攻擊者拿走控制權
不同的 Recovery 設計都有其極限,但沒有一個 Recovery 設計可以同時應付 Owner 私鑰遺失、Owner 私鑰被盜 與 惡意 Guardian 這三種假設。在這個極限之下,我們按照需求並從這三種假設中去實作我們的 Recovery 機制
讓我們思考看看,以下幾種方法是否能免除對 Guardian 的信任:
resetOwner
但如此除了 Owner 之外就沒有人可以來 resetOwner
了,而 Owner 自己都遺失私鑰了自然是不可能可以更新 Owner 地址,因此這個方法不可行。
resetOwner
要經過使用者同意同樣地,Owner 都遺失私鑰了所以沒辦法簽名同意。那如果請 Owner 預先產生另一把私鑰用來簽名同意呢?那其實等同於使用者直接將另一把私鑰設為 Guardian,基本上就等於是使用者自己在做備份。但不管 Guardian 是第三方或是使用者自己,都改變不了 Guardian 要有完全的權力可以 resetOwner
的事實。
因此我們得到結論:如果私鑰可能會遺失,那一定得信任 Guardian;如果私鑰不會遺失,那就不需信任 Guardian,也就是不需給 Guardian 完全的權利能 resetOwner
。
那就可以應付 Owner 私鑰被盜 或 惡意 Guardian,但這樣的假設實在不太實際
註:但沒辦法應付 Owner 私鑰被盜 與 惡意 Guardian 同時發生。
那就可以應付 Owner 私鑰遺失 或 惡意 Guardian(能透過時間鎖反制惡意 Guardian,但並不能真的移除對 Guardian 的信任)
註:但沒辦法應付 Owner 私鑰遺失 與 惡意 Guardian 同時發生。
那就可以應付 Owner 私鑰遺失 與 Owner 私鑰被盜
那就更簡單了,resetOwner
和 updateGuardians
都不需加上時間鎖