跳至主要内容

🔐 錢包安全性

作為使用者,無疑希望確保自己的數位資產能在一個安全和可靠的環境中存儲和交易;有鑑於此,KryptoGO 在錢包的創建、使用、備份與還原等等操作環節中,都採用了先進的技術和多層安全措施,以減少被破解的風險。

KryptoGO 為錢包提供了多種備份和恢復選項,每種選項都伴隨著特定的風險和保護措施。本節旨在比較這些差異,為使用者提供更清晰的理解,以幫助他們選擇自己偏好的錢包備份和恢復方法。

提示

本節專門介紹 KryptoGO 錢包應用程式的安全性。如果您想了解 KryptoGO 網頁 SDK 的安全措施,請參閱網頁 SDK 安全性

詞彙表

閱讀本節時,以下是一些有用的詞彙:

詞彙定義
私鑰用戶的私鑰,一長串的數字和字母。
助記詞用戶的助記詞,通常是一組由 12 個英文單詞組成的詞組。
帳戶解鎖密鑰基於用戶密碼生成的密鑰加密密鑰(KEK)。
帳戶公鑰每個用戶的唯一公鑰。與帳戶私鑰形成一對密鑰。
帳戶私鑰每個用戶的唯一私鑰。與帳戶公鑰形成一對密鑰。
加密帳戶私鑰使用帳戶解鎖密鑰對帳戶私鑰進行加密,得到加密帳戶私鑰。
鹽值用於加密和解密的隨機字符串。每個 KryptoGO 帳戶都有一個用作鹽值的唯一字符串。
保險庫存儲用戶的帳戶公鑰、加密帳戶私鑰和鹽值的數據結構。
加密錢包數據使用帳戶私鑰對錢包數據進行加密。
設備加密密鑰用於將錢包存儲在本地設備存儲中的加密密鑰。

註冊 KryptoGO 帳戶

當使用者初次註冊 KryptoGO 錢包時,會在設備上本地生成一個 Curve25519 帳戶公鑰、帳戶私鑰和鹽。

  • 帳戶公鑰是公開的,任何人都可以知道。
  • 帳戶私鑰永遠不會離開使用者的設備。
  • 鹽是在本地設備上隨機生成的字符串。
PriKey,PubKeyKeyGen25519()saltRandBytes(32)\begin{align*} \mathbf{PriKey}, \mathbf{PubKey} &\leftarrow \text{KeyGen25519()} \\ \mathbf{salt}&\leftarrow \text{RandBytes(32)} \end{align*}

創建或導入錢包

使用者可以選擇導入一個錢包或創建一個新的錢包。無論哪種情況,KryptoGO 錢包都會生成一個設備加密密鑰,用於加密新錢包,並將加密的數據存儲在設備的本地存儲中。

設備加密密鑰將存儲在設備的安全存儲中,即 iOS 的 Keychain 和 Android 的 Keystore。

  • 安全存儲旨在將敏感數據與一般應用程序存儲隔離開來,確保未經授權的應用程序或外部實體無法訪問它。
  • 使用者需要使用生物識別解鎖設備,以檢索設備加密密鑰。

使用錢包進行交易

一旦使用者成功登錄並通過生物識別驗證,設備加密密鑰將用於解密錢包數據,包括私鑰,並存儲在本地設備的存儲中以進行交易簽名。

錢包備份和還原

KryptoGO 錢包為使用者提供兩種備份選項:密碼備份雲端備份。當然,這兩種方法都有相應的錢包還原方法:使用密碼還原錢包從雲端還原錢包

密碼備份

當使用者選擇密碼備份並輸入密碼時,將啟動密鑰衍生過程。此過程生成一個帳戶解鎖密鑰(AUK),用於加密和解密使用者的帳戶私鑰。

p使用者提供的帳戶密碼s本地儲存的鹽值p正規化(trim(p))AUKPBKDF2(p,s,310000)\begin{align*} \mathbf{p} &\leftarrow \text{使用者提供的帳戶密碼} \\ s &\leftarrow \text{本地儲存的鹽值} \\ \mathbf{p} &\leftarrow \text{正規化}(\text{trim}(\mathbf{p})) \\ \mathbf{AUK} &\leftarrow \text{PBKDF2}(\mathbf{p}, s, 310000) \\ \end{align*}

密鑰衍生過程如下:

  1. 首先,密碼會被修剪掉空白字符,並使用 Unicode 兼容分解規範(NFCD)進行正規化。這一步是為了防止因不同設備上相同 Unicode 的不同編碼而導致的解密問題。
  2. 為了進一步增強對暴力破解攻擊的防護,採用了一種慢速哈希算法,具體是 PBKDF2-HMAC-SHA256(基於密碼的密鑰衍生函數)。這涉及 310,000 輪的哈希運算,以生成帳戶解鎖密鑰。
選擇 PBKDF2-HMAC-SHA256 是因為它與廣泛的移動設備兼容,提供了一種高效的算法,既保證了安全性,又不會有任何妥協。
PBKDF2(password,salt,iterations,dkLen):U1=HMAC(password,saltINT_to_BYTE(1))U2=HMAC(password,U1)Uiterations=HMAC(password,Uiterations1)T1=U1U2UiterationsTn=(以與 T1 類似的方式計算)DK=T1T2Tnreturn DK[0dkLen]\begin{align*} \text{PBKDF2}&(password, salt, iterations, dkLen) : \\ &U_1 = \text{HMAC}(password, salt || \text{INT\_to\_BYTE}(1)) \\ &U_2 = \text{HMAC}(password, U_1) \\ &\dots \\ &U_{iterations} = \text{HMAC}(password, U_{iterations-1}) \\ &T_1 = U_1 \oplus U_2 \oplus \dots \oplus U_{iterations} \\ &\dots \\ &T_n = \dots \text{(以與 \( T_1 \) 類似的方式計算)} \\ &DK = T_1 || T_2 || \dots || T_n \\ &\text{return } DK[0 \dots dkLen]\end{align*}
選擇 310,000 輪作為工作因子是基於 NIST FIPS-140 標準的建議。

計算出帳戶解鎖密鑰(AUK)後,使用它來使用 AES-256 加密使用者的帳戶私鑰,從而得到加密的帳戶私鑰。

EncPriKeyEncAES-256(PriKey,AUK)\begin{aligned} EncPriKey \leftarrow \text{Enc}_{\text{AES-256}}(\text{PriKey}, \text{AUK}) \end{aligned}

然後,使用帳戶私鑰對所有錢包數據進行 AES-256 加密。

EncWalletsfor xWallets        yiEncAES-256(PriKey,x)        EncWalletsEncWallets{yi}endforreturn EncWallets\begin{aligned} &EncWallets \leftarrow \emptyset \\ &\text{for } x \in \textit{Wallets} \\ &\;\;\;\; y_i \leftarrow Enc_{\text{AES-256}}(PriKey, x) \\ &\;\;\;\; EncWallets \leftarrow EncWallets \cup \{y_i\} \\ &\text{endfor} \\ &\text{return }EncWallets \end{aligned}

備份過程是將加密的錢包、鹽、帳戶公鑰和加密的帳戶私鑰備份到雲端。

使用密碼還原錢包

在密碼備份後,用戶可以在其他設備上登錄 KryptoGO 錢包並使用密碼還原所有的私鑰和種子短語。

使用密碼還原錢包的過程如下:

  1. 在本地使用正確的密碼計算帳戶解鎖密鑰。
  2. 使用帳戶解鎖密鑰,結合從雲端備份中檢索的加密帳戶私鑰,在本地解密帳戶私鑰。
  3. 使用帳戶私鑰進一步解密所有錢包私鑰和種子短語。
EncWallets,Salt,EncPriKey雲端備份p用戶輸入的密碼AUKPBKDF2(p,Salt,310000)PriKeyDecAES-256(AUK,EncPriKey)for xEncWallets        yiDecAES-256(PriKey,x)        WalletsWallets{yi}endforreturn Wallets\begin{aligned} &EncWallets, Salt, EncPriKey \leftarrow \text{雲端備份} \\ &\mathbf{p} \leftarrow \text{用戶輸入的密碼} \\ &AUK \leftarrow \text{PBKDF2}(\mathbf{p}, Salt, 310000) \\ &PriKey \leftarrow Dec_{\text{AES-256}}(AUK, EncPriKey) \\ &\text{for } x \in \textit{EncWallets} \\ &\;\;\;\; y_i \leftarrow Dec_{\text{AES-256}}(PriKey, x) \\ &\;\;\;\; Wallets \leftarrow Wallets \cup \{y_i\} \\ &\text{endfor} \\ &\text{return }Wallets \end{aligned}

密碼備份問答

為什麼選擇 AES-256?

我們特意選擇了 AES-256,這是 AES 算法的一種模式,以其對攻擊的更高抵抗力而聞名。這個選擇對於防止密文在特定條件下易受破解攻擊(如選擇密文攻擊)至關重要。

破解所使用的密鑰衍生方法有多困難?
  1. 截至2023年,考慮到GPU計算能力,計算2322^{32}個哈希的成本約為$6。對於具有40位熵的密碼,使用兩個GPU破解它大約需要4-16周,估計破解成本約為$770
  2. 在 KryptoGO 錢包中,使用密碼備份時,用戶需要設置至少12個字符長的密碼,包括大寫字母、小寫字母和數字。這樣的密碼的位熵計算為log2(6212)=12log2(62)71.45 bits.log_2(62^{12}) = 12log_2(62) ≈ 71.45\ bits.
  3. **每增加一位熵,破解的時間或成本就會加倍。**因此,破解 KryptoGO 錢包密碼的估計成本至少為770271.4540=2.261012770 ⋅ 2^{71.45-40} = 2.26 ⋅ 10^{12},約等於2.26萬億美元。以時間計算,至少需要4271.4540/52=2.251084 ⋅ 2^{71.45-40}/52 = 2.25 ⋅ 10^8年,約為2.25億年

實際破解的困難程度超過了這些估計,因為它們只考慮了對帳戶解鎖密鑰進行哈希的過程。這並不包括驗證該帳戶解鎖密鑰是否能夠解密加密的錢包數據。包括這個驗證步驟將顯著增加破解的困難程度。

為什麼在生成帳戶私鑰和帳戶公鑰時使用Curve25519橢圓曲線?
  1. 計算效率

    使用Curve 25519,當用戶輸入密碼解密帳戶私鑰時,帳戶公鑰可以快速驗證帳戶私鑰是否對應。這種方法避免了在輸入錯誤密碼時使用帳戶私鑰執行解密過程的需要。

  2. 社交恢復

    社交恢復允許用戶A指定另一個人B作為緊急聯絡人。A和B可以通過Diffie-Hellman密鑰交換算法生成一個共享密鑰,並使用該共享密鑰對A的帳戶私鑰進行加密,並將結果備份到雲端。

    SharedKeyPubKeyBPriKeyAEncPriKeyABEncAES-256(SharedKey,PriKeyA)\begin{aligned} &SharedKey \leftarrow PubKey_B^{PriKey_A} \\ &EncPriKey_{AB} \leftarrow Enc_{\text{AES-256}}(SharedKey, PriKey_A) \\ \end{aligned}

    如果A忘記了他們的密碼並需要B的幫助來恢復錢包,一旦B收到A的加密帳戶私鑰,B可以使用以下過程解密該密鑰:

    SharedKeyPubKeyAPriKeyBPriKeyADecAES-256(SharedKey,EncPriKeyAB)\begin{aligned} &SharedKey \leftarrow PubKey_A^{PriKey_B} \\ &PriKey_A \leftarrow Dec_{\text{AES-256}}(SharedKey, EncPriKey_{AB}) \\ \end{aligned}

    完成社交恢復過程後,A可以生成一對新的帳戶私鑰和帳戶公鑰。這一步是為了減輕A的帳戶私鑰被破壞的風險。

雲端備份

覺得密碼很麻煩嗎?為了提供更方便的選擇,我們引入了一個無需密碼的雲端備份選項。用戶可以選擇加入使用雲端儲存來安全保護他們的私鑰和種子短語。

提示

雲端備份是選擇性的。未經您的同意,不會將任何內容保存到雲端。

雲端備份的基本概念是將帳戶私鑰分割成多個片段,稱為金鑰分享,並將它們備份到不同的雲端存儲中。這些金鑰分享的一個重要特點是,只要擁有其中任意兩個片段,就可以恢復用戶的帳戶私鑰。

這個過程的底層算法是Shamir的秘密分享方案(SSS),它是一種高效且安全的秘密分享方法。SSS從機密數據(秘密)生成nn個獨立的片段(秘密分享)。只要擁有nn個片段中的任意k(kn)k (k ≤ n)個,就可以通過計算重構出原始的秘密。

以下是Shamir的秘密分享的工作原理:

  1. 假設原始秘密為SS。 隨機生成一個k1k-1次的多項式f(x)f(x),滿足f(x)=a0+a1x+a2x2+...+ak1xk1f(x)=a_0+a_1x+a_2x^2+...+a_{k-1}x^{k-1},其中a0=Sa_0=S

    對於每個i (0in1)i\ (0≤i≤n-1),隨機生成相應的金鑰分享(xi,f(xi))(x_i, f(x_i))

  2. 當用戶獲得kk個金鑰分享時,可以使用拉格朗日插值多項式來恢復原始多項式f(x)f(x)

    假設,不失一般性,用戶獲得kk個金鑰分享x0,x1,...,xk1x_0, x_1,...,x_{k-1}。可以推導出以下公式:

    f(x)=i=0k1f(xi)0j<k,jixxjxixj f(x) = \sum_{i=0}^{k-1} f(x_i) \prod_{0 \leq j \lt k, j \neq i} \frac{x-x_j}{x_i-x_j}

    因此,可以計算出原始秘密f(0)f(0)

從雲端恢復錢包

在實際應用中,我們選擇k=2k = 2,這意味著任意兩個片段都可以恢復原始秘密,例如帳戶私鑰。只要nn是大於2的任意數字,就可以生成多個金鑰分享並存儲在不同的雲端備份中。只需要兩個金鑰分享,用戶就可以恢復其帳戶私鑰並解密加密錢包的數據,從而獲取完整的私鑰或種子短語。

用戶可以選擇將金鑰分享存儲在KryptoGO以外的雲端存儲中,包括iCloud和Google Drive。這種方法確保用戶不僅僅依賴於KryptoGO的雲端備份,從而提供了最高的數據可用性保證。

雲端備份問答

k=2k=2 是否足夠安全?

使用 n-choose-k 雲端備份方法,當黑客存取 k1k-1 個金鑰分享時,無法獲取最終的秘密值,這意味著破解秘密的難度保持不變。風險只有在同時暴露 kk 個金鑰分享時才會出現。考慮到主要雲端服務提供商的強大安全性,多個雲端帳戶同時被入侵的可能性非常低。因此,k=2k = 2 的設置被認為是足夠安全的,前提是您相信 Google 和 Apple 等主要雲端服務提供商的安全性。

如果使用者無法存取秘密分享會發生什麼?

假設在其中一個雲端平台上丟失了一個秘密分享,例如因為意外刪除。在這種情況下,使用者仍然可以使用現有的秘密和存儲在本地設備上的 k1k-1 個金鑰分享的值來生成新的金鑰分享。

通過持續監控備份的金鑰分享數據,我們可以保證使用者始終能夠從這些雲端平台恢復他們的私鑰或種子短語。