Encryption

保護端到端加密的基於雲的地址簿

  • May 12, 2017

我正在分析現有的端到端加密的基於雲的服務(例如電子郵件、文件儲存或聊天),該服務還具有基於公共雲的地址簿(用於管理聯繫人),以便雲服務的使用者可以在他們之間安全地通信(例如發送電子郵件、共享數據或聊天)。

要登錄基於雲的服務,使用者只需要記住他們的密碼。登錄時,使用者的密碼被輸入基於密碼的密鑰派生函式,例如 PBKDF2,它產生派生密鑰並用於驗證和解密其帳戶的對稱加密密鑰,例如 AES-256(用於保護使用者自己的數據和帳戶操作) 及其公鑰/私鑰對,例如 RSA 3072(用於與其他使用者共享數據、發送電子郵件或聊天)。這些密鑰在客戶端的帳戶註冊時創建並上傳到雲服務。一切都保存在伺服器上,但在客戶端獲取數據並執行加密操作。使用者可以註銷並在另一台電腦或設備上登錄,並可以訪問他們在註銷之前擁有的所有數據。

對於適當的端到端範例,使用者需要親自驗證彼此的公鑰,但儲存(固定)他們已經看到並已驗證的公鑰的指紋。否則,如果使用者不驗證公鑰,那麼他們將很容易受到網路路徑(例如 Internet)上的某人或云服務本身(雲服務是秘密惡意的,在脅迫下,員工是間諜)的主動 MITM 攻擊,他們被黑客入侵,或者他們收到法院命令等)。因此,從理論上講,雲服務中的任何內容都不應該被信任。從服務中獲取所有內容後,客戶端的使用者都應重新驗證,安全性植根於密碼的保密性和強度。

當使用者將聯繫人(通過電子郵件地址)添加到他們的地址簿時,客戶端也會從伺服器數據庫中獲取該使用者的公鑰。客戶端接受來自伺服器的預設公鑰,然後將數據記錄上傳到伺服器以保留他們已經看到該公鑰指紋的資訊。

users表包含使用者記錄列表,例如

[user id], [user email], [name], [public key], [encrypted private key], [encrypted symmetric key]

使用者 ID/聯繫人 ID 是一個 64 位唯一的十六進制隨機字元串。該users_contacts表包含每個使用者的聯繫人映射,例如

[user id], [contact id]

公鑰指紋記錄儲存在單獨的表中contacts_fingerprints。儲存在伺服器端的記錄通過 MAC 進行身份驗證,例如 HMAC-SHA256,使用使用者的對稱密鑰,例如

[user id], [contact id], [public key fingerprint e.g. 256 bits hex], [verified flag e.g. 0x00 or 0x01], [MAC(user id || contact id || public key fingerprint || verified flag)]

然後由使用者來驗證密鑰是否正確(帶外),然後將驗證標誌設置為真(0x01)。

然而,在分析了這個設計之後,我發現有一些可能的攻擊使得這個設計在端到端範式中並不真正安全:

  1. 雲提供商可以選擇性地刪除 contacts_fingerprints表中的記錄,因此當使用者再次登錄以獲取數據時,他們可能不會注意到正在與之通信的使用者不再經過驗證。例如,客戶端只是重新獲取公鑰並再次保存它,因為它可能認為存在網路錯誤或損壞或其他原因。然後可以使用它對使用者執行 MITM 攻擊。由於記錄也未加密,因此可用於針對特定使用者。
  2. 雲提供商可以存檔並保留以前的數據庫記錄,例如在創建聯繫關係且未驗證指紋時。然後稍後,在使用經過驗證的指紋更新記錄後,他們可以選擇將其回滾到未經驗證的先前版本。然後,當使用者登錄並重新獲取他們下載舊記錄的數據時,他們可能不會注意到使用者不再是未經驗證的。這可以用作服務提供商對 MITM 使用者的優勢,例如,當建立聯繫關係時,提供商總是提供 MITM 公鑰,該公鑰由使用者自動保存。當他們嘗試驗證時,

可以做些什麼來重新設計這個系統並防止這些攻擊?

我想到了幾個想法:

1)為了讓使用者信任他們的聯繫人的詳細資訊(他們的使用者 ID、姓名、電子郵件等),那麼使用者**表記錄也必須由每個使用者使用他們的私鑰簽名。所有聯繫記錄必須在使用者檢索時進行驗證。例如,對於使用者記錄,您將儲存以下內容:

[User ID], [User Email], [Name], [Public Key], [Encrypted Private Key], [Encrypted Symmetric Key], [RSA-SIGN(User ID || User Email || Name || Public Key || Encrypted Private Key || Encrypted Symmetric Key)]

2)應刪除contacts_fingerprints表,將公鑰指紋和驗證標誌分組到users_contacts表上的單個記錄中。然後,如果刪除了一條記錄,使用者會注意到,因為他們將不再是聯繫人,並且如果不重新添加他們就無法與該聯繫人通信。例如:

[User ID], [Contact ID], [Public Key Fingerprint], [Verified Flag], [HMAC-SHA-384(User ID || Contact ID || Public Key Fingerprint || Verified Flag)]

3) users_contacts表記錄應大部分加密,以防止針對個別聯繫人進行中間人攻擊,並確定哪些使用者尚未經過驗證,以使攻擊不那麼明顯。例如:

[User ID], [AES-CTR(Contact ID, Public Key Fingerprint, Verified Flag)], [HMAC-SHA-384(User ID || AES-CTR Encrypted Data)]

**4)**我們可以更進一步,而不是儲存單個數據庫記錄,我們可以將它們全部連接在一起、加密和驗證。如果項目由標籤長度值(甚至逗號分隔或 JSON)分隔,這可能會簡化檢索。這將防止篡改任何联係人,因為它們是一團隨機數據,因此無法定位和刪除特定聯繫人。例如,這可以儲存為:

[User ID], [AES-CTR(Contact ID 1 || Public Key Fingerprint 1 || Verified Flag 1 || ... || Contact ID 24 || Public Key Fingerprint 24 || Verified Flag 24)], [HMAC-SHA-384(User ID || AES-CTR Encrypted Contact Data)]

**5)**為了防止回滾到未驗證聯繫人的先前數據庫記錄,我們應該儲存一個上次更新的時間戳。每當任何联係人的公鑰指紋或驗證標誌發生更改時,時間戳都會更新。該時間戳需要轉換為人類可讀的日期,並在使用者登錄客戶端應用程序並從伺服器獲取數據時以全屏插頁式模式對話框的形式顯示給使用者,例如,消息為:“您的聯繫人數據最後一次修改時間是 2017 年 5 月 7 日 15:34。如果這個時間比您記得的要早,那麼您的通訊錄已被篡改。在對他們執行任何操作之前,請重新驗證您的聯繫人。. 然後他們可以就他們的帳戶是否被篡改做出有根據的決定。例如,他們記得 2 天前與 Bob 驗證了聯繫人,但是當他們再次登錄並從伺服器獲取所有數據時,最後更新日期顯示為兩週前。果然鮑勃在他的聯繫人姓名旁邊缺少他的已驗證檢查/勾選圖示。現在使用者知道發生了一些可疑的事情。例如,要儲存它,您將執行以下操作:

[User ID], [AES-CTR(Last Updated Timestamp || Contact ID 1 || Public Key Fingerprint 1 || Verified Flag 1 || ... || Contact ID 24 || Public Key Fingerprint 24 || Verified Flag 24)], [HMAC-SHA-384(User ID || AES-CTR Encrypted Contact Data)]

**6)**與之前的改進一起最後的改進是防止使用者在沒有先驗證公鑰指紋的情況下創建聯繫關係。這意味著客戶端使用者界面會強制他們在保存聯繫人記錄並允許他們進行通信之前對其進行驗證。這可能對使用者不太友好,但它絕對可以防止完全依賴使用者的記憶。它還可以防止回滾到較早的數據庫記錄,因為如果有回滾,則該聯繫人將消失並且他們無法再與他們通信。他們必須重新添加它們並再次重新驗證公鑰。此外,由於使用者被迫進行驗證,因此服務提供商嘗試執行中間人攻擊的動機較少,因為他們很可能會立即被發現。


總之,目的是讓攻擊者或伺服器盡可能難以篡改伺服器端數據。如果他們確實篡改了它,那麼它將被檢測到,如果**6)**也被實施,它還將防止發生不安全的通信以消除中間人的可能性。

引用自:https://crypto.stackexchange.com/questions/47217