Implementation
我應該從記憶體中刪除加密數據嗎?
在處理加密數據時,攻擊者是否有可能恢復我在程序中使用的部分數據?我是否應該嘗試刪除我使用的每一位密鑰和加密數據,用零覆蓋它?
還有一點,在 Python 或 Java 等具有垃圾收集功能的語言中,情況有何不同?
《密碼學工程》這本書用一章的一部分來討論這個主題。用零覆蓋敏感數據是一個好的開始,但還有許多其他考慮因素。
- 如果您依賴語言的預設對象破壞行為來將記憶體歸零,那麼意外錯誤可能會過早停止程序的執行,而不會自行清理。在 Java 中,異常處理可以丟棄對象引用,而無需清理對象本身。
$$ Not sure if this is still the case $$
- 有時編譯器會優化掉用於覆蓋記憶體的程式碼,因為它作用於一塊記憶體,在程序中沒有其他用途。有幾種方法可以誘使編譯器不執行這種“死儲存消除”。
- 作業系統記憶體管理可以通過將數據分頁到系統硬碟來阻止您刪除數據的嘗試。有一些方法可以防止這種情況,但它們是特定於語言和平台的。
- 如果作業系統進行上下文切換,則寄存器中的值將儲存在記憶體中的其他位置,直到執行恢復。這可能會導致敏感數據最終出現在奇怪的地方。現代處理器還具有多個記憶體,可以保存敏感數據。
- 在記憶體管理是自動的語言中,更難知道您分配的記憶體在系統中的確切位置(以及多長時間)。在 Java 中,對像都存在於堆中,並且作為垃圾回收的一部分被引用計數。當沒有更多對該對象的引用時,可以通過垃圾收集器的下一次傳遞將其刪除。但是,如果沒有呼叫 System.gc(),就無法知道垃圾收集何時會發生。即使您強制進行垃圾收集,它仍然可能不會立即執行。這個SO question 談到了一些關於 System.gc 的行為。
- 當密鑰總是被寫入電腦記憶體的同一物理區域時,就會發生冷啟動攻擊。隨著時間的推移,電磁力會導致記憶體在斷電後保持狀態。
這可能不是您的應用程序的全部範圍,但它應該讓您對具有物理系統訪問權限的攻擊者的能力有一個很好的了解。您可以做的最重要的事情是非常非常了解您的語言和平台。為了進一步閱讀,這篇Wikipedia 文章應該會給您一個良好的開端。