Implementation

JVM 語言中的時序安全

  • July 6, 2017

如何用 JVM 語言(Java、Scala、Clojure…)編寫時間安全程式碼?是否有可能使像 BouncyCastle 這樣的庫能夠安全地抵禦時間攻擊?

我知道即使在 C 語言中,也很難把這些事情做好——在 C 語言中,您可以查看生成的彙編程式碼,至少可以預測您的目標 CPU 將如何執行它。

在 JVM 語言中,您不知道 JVM 將如何將您的程式碼轉換為機器程式碼或將執行哪些執行時優化。

編輯:我並不真正擔心本地定時攻擊,而是擔心遠端可利用的攻擊。

理論是:不要試圖用 JVM 語言或其他本質上解釋但可能有時編譯的語言編寫時間安全程式碼;相當

  • 使用舒適的 JVM 語言呼叫的時序安全庫。典型範例:在通過 AVA_VAN.5 擴充將通用標準評估傳遞給 EAL5+ 的 JavaCard 中,可以肯定的是 AES(如果可用)是時序安全的。
  • 盡可能避免首先需要時間安全。典型範例:與其嘗試在恆定時間內將所謂的 16 字節值與參考 16 字節值進行比較,不如繪製一個新的 AES 密鑰,使用此 AES 密鑰加密所謂的和參考值(使用恆定時間 AES 實現) ,然後使用手頭的任何方法比較結果。
  • 作為上述的變體,使用降低定時攻擊效率的對策,例如致盲

上述方法也傾向於對抗時序以外的側通道攻擊,例如功率分析。


當市場壓力另有規定時,期權應盡可能少地進行相對安全的押注;當一個人有幸知道實際目標時,仔細檢查它們。例如,寫的時候

// 比較兩個字節數組,這樣時間就不會在差異所在的地方洩漏
公共靜態布爾 myEqualByteArrays[(byte[] a, byte[] b) {
int j = a.length;
如果 (j != b.length)
返回假;// 數組長度不同
詮釋 r = 0; // 將保持為零,直到發現差異
而 (--j>=0)
r |= a[j] ^ b[j];
返回 r==0; // 當且僅當數組匹配時為真
}

僅假設

  • 二元運算^|是恆定時間的(&一元~也可能是,儘管我們在這個例子中不需要它);
  • 即使對以下內容的深入分析表明它們可以退出,循環也不會退出。

到目前為止,如果我遇到任何打破這些假設的事情,我還沒有意識到!


不能安全地假定為常數時間的事情的例子:

  • 任何使用if, switch..
  • 短路運算符 &&||
  • 邏輯不!
  • 數組訪問(例如由於記憶體)。
  • 整數乘法(包括常數):一些 CPU 的乘法時間取決於一個參數;範例包括這個這個32 位 CPU(感謝製造商記錄它)。
  • 當然,除法(包括常數)。
  • +對比編譯器、執行時和硬體組合支持的更大數據類型的操作:可以想像,即使在內部使用 32位-變數的某些 64 位類型中,某些內部進位也可能導致數據相關的時序依賴性。這比增量更不用擔心變數添加,增量可以在執行時實現或自動過度優化為:增加低半部分,如果不是零,則增加高半部分。
  • 班次:時間通常取決於班次計數。
  • 通過常量移位右移:這可能取決於移位參數的符號或高位(對於無符號類型不太可能;在 Java 中,使用無符號運算符的可能性低於有符號>>>運算符移位運算符>>)。
  • 選擇運算符 ?:;但是,在 Java 中,僅限於內置有符號2 的補碼32 位類型int,替代品d = (a==0) ? b : c;可能是
// 計算 a 中所有位到 d 低位的 OR
d = (a >>> 1) | 一個;
d = (d >>> 2) | d;
d = (d >>> 4) | d;
d = (d >>> 8) | d;
d = (d >>>16) | d;
d = -(d&1); // 在整個 d 上複製 d 的低位
d = ((b^c)&d)^b; // 如果 a==0 選擇 b,否則選擇 c

如果效率確實是次要的,那麼該技術可以擴展到,例如,在橢圓曲線上的某個二進制域上的恆定時間點乘法。

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