2017-08-15 100 views
4

根據DES規範,密鑰的每個字節的最後一位用於錯誤檢測(每個字節應該有奇數奇偶校驗)。因此有效密鑰長度是56位,而不是64位。DESKey是否保留無效奇偶校驗位?

但是,在許多使用情況下,這些奇偶校驗位未被檢查。有時它們甚至用於完全不同的目的:例如,即使原始錯誤糾正目的丟失,Mifare DESFire卡也會將密鑰版本存儲在這些位中。

Java Card實現如何處理這些位?讓我們來看看這個代碼:

DESKey desKey = ... //a single DES key instance 
byte[] inputKey = new byte[8]; 
inputKey[7] = (byte) 0x03; //explicitly invalid parity bit in the last byte 
desKey.setKey(inputKey, (short) 0); 
byte[] outputKey = new byte[8]; 
desKey.getKey(outputKey, (short) 0); 

能夠保證所有的inputKeyoutputKey陣列將包含相同的數據到底,即使在inputKey無效的奇偶校驗位?我用幾種卡片類型進行了幾次實驗,它們都保留了我放入這些奇偶校驗位的任何數據,但是我沒有在Java Card規範中發現這種行爲是有保證的。

這條信息對我來說非常重要;否則我將不得不存儲與密鑰實例分離的「無效奇偶校驗位」。

+2

我有完全相同的困境,並決定將密鑰版本存儲在單獨的字段中以確保。我無法在規格中找到任何保證 - 我敢打賭,它是不確定的,因此很危險。我的卡片保持奇偶校驗位不變......祝你好運! – vlp

回答

3

如果不符合規範,則不能保證。這真的很簡單,沒有另外說明的卡實施者的單獨規範(並且如果有的話,可能在不觸及原始定義的情況下改變)。

對密鑰的操作在攻擊方面可能會很棘手。因此,要保持關鍵數據的完整性並且不使用通用CPU迭代關鍵位,還有很多需要說明的內容。此外,當對關鍵數據執行其他操作時(例如使用散列函數計算密鑰校驗值或將相同密鑰用作MAC(對稱簽名)的輸入),可能會非常棘手。

當然,完全可以使用您自己的代碼對關鍵位執行奇偶校驗操作。您可以將結果與測試向量或使用Java SecretKeyFactory生成的密鑰進行比較。但是,由於奇偶校驗位未在密鑰計算中使用,因此只有在您要將密鑰導出設備時才需要。但是請注意,對關鍵數據執行其他操作是危險的,可能會破壞各種安全測試/證明/認證。

請注意,無論如何,大多數Java卡實現(或更確切地說,底層芯片的硬件)很可能會在所有持久性(EEPROM /閃存)內存上執行校驗和。密鑰也很可能受Java Card實現(或其中一個底層)的保護。所以在防範數據不可預見的變化方面:我不會太擔心。你不需要DES奇偶校驗位。


OK,我覺得像做一些位擺弄,所以這裏的Java卡代碼來設置奇偶自己(我會讓你做的for循環和內聯之類的東西,如果你不介意)。這些計算應該是(接近)恆定時間。

/** 
* This method takes byte value <code>b</code> and then sets or unsets the least significant bit 
* of that value in such a way that the parity of <code>b</code> is odd. 
* So this method returns either <code>b</code> or <code>b^1</code>. 
* 
* @param b the byte value 
* @return <code>b</code> with DES parity 
*/ 
public static byte makeDESParity(final byte b) { 
    byte x = b; 
    // trick to calculate odd parity in the lsb of x 
    x ^= x >>> 4; 
    x ^= x >>> 2; 
    x ^= x >>> 1; 
    // but we want even parity in the lsb: ~x 
    // get the least significant bit: ~x & 1 
    // xor that with b: ~x & 1^b 
    return (byte) (~x & 1^b); 
} 

/** 
* This method takes byte value <code>b</code> and returns true if and only if 
* the byte has odd parity. 
* 
* @param b the byte value 
* @return true if <code>b</code> has DES parity 
*/ 
public static boolean hasDESParity(byte b) { 
    // trick to calculate odd parity in the lsb of b 
    b ^= b >>> 4; 
    b ^= b >>> 2; 
    b ^= b >>> 1; 
    // check if last bit has indeed been set 
    return (b & 1) != 0; 
} 
+0

例如,你可以做一些可怕的事情,並使用一張表[像MBED_TLS一樣](https://www.google.cz/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwjMgeTditrVAhUBthoKHYsJAkQQFggzMAE&url=https%3A %2F%2Ftls.mbed。有機%2Fapi%2Fdes_8c_source.html&USG = AFQjCNFC5Um5PfILYbTQSCs9ZOdlBVGPIw)。 Ouch - 你好旁邊的頻道,再見128字節。 –

+1

謝謝你的「小提琴」。在使用硬編碼字節數組時,我沒有看到任何旁道,請您詳細說明一下。 – Shuckey

+0

(我認爲這與問題無關,但是,)@Shuckey說 - 預先計算的256字節數組是(IMHO)的有效途徑。 hasDESParity()可能如下所示:'return makeDESParity(b)== b;' – vlp