2017-08-15 3 views
4

Gemäß DES-Spezifikation wird das letzte Bit jedes Bytes des geheimen Schlüssels zur Fehlererkennung verwendet (jedes Byte sollte eine ungerade Parität haben). Daher ist die effektive Schlüssellänge 56 Bits, nicht 64 Bits.Behält DESKey ungültige Paritätsbits?

In vielen Anwendungsfällen werden diese Paritätsbits jedoch nicht überprüft. Manchmal werden sie sogar für einen ganz anderen Zweck verwendet: Mifare DESFire-Karten speichern beispielsweise die Schlüsselversion in diesen Bits, obwohl der ursprüngliche Zweck der Fehlerkorrektur verloren geht.

Wie behandeln Java Card-Implementierungen diese Bits? Lassen Sie uns an diesem Code einen Blick:

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); 

ist sichergestellt, dass inputKey und outputKey Arrays die gleichen Daten am Ende enthalten, auch mit ungültigen Paritätsbits im inputKey? Ich habe mehrere Experimente mit ein paar Kartentypen durchgeführt und sie behalten alle Daten, die ich in diese Paritätsbits geschrieben habe, aber ich habe in der Java Card-Spezifikation keine Erwähnung gefunden, dass dieses Verhalten garantiert ist.

Diese Information ist sehr wichtig für mich; andernfalls müsste ich meine "ungültigen Paritätsbits" getrennt von der Schlüsselinstanz speichern.

+2

Ich hatte genau das gleiche Dilemma und beschloss, die Schlüsselversion in einem separaten Feld zu speichern, nur um sicher zu gehen. Ich konnte auch keine Garantien in den Spezifikationen finden - meine Wette ist, dass es undefiniert ist, also gefährlich. Meine Karten hielten die Paritätsbits auch intakt ... Viel Glück! – vlp

Antwort

3

Wenn es nicht in den Spezifikationen ist, dann ist es nicht garantiert. Es ist wirklich so einfach. Es gibt keine separate Spezifikation für Kartenimplementierer, die etwas anderes sagt (und falls es welche gab, könnte sich das ändern, ohne die ursprüngliche Definition zu berühren).

Operationen auf Schlüsseln können in Bezug auf Angriffe schwierig sein. Es muss also viel darüber gesagt werden, dass die Schlüsseldaten intakt bleiben und nicht über die Schlüsselbits mit der generischen CPU iteriert werden. Es kann auch schwierig sein, wenn andere Operationen über die Schlüsseldaten ausgeführt werden, wie z. B. das Berechnen eines Schlüsselprüfwerts mit einer Hash-Funktion oder die Verwendung desselben Schlüssels als Eingabe für eine MAC (symmetrische Signatur).

Es ist natürlich durchaus möglich, die Paritätsoperation auf den Schlüsselbits mit Ihrem eigenen Code durchzuführen. Sie können Ihr Ergebnis mit Testvektoren oder mit Schlüsseln vergleichen, die mit Java SecretKeyFactory generiert wurden. Da die Paritätsbits in den Schlüsselberechnungen jedoch nicht verwendet werden, ist dies nur erforderlich, wenn Sie den Schlüssel aus dem Gerät exportieren möchten. Beachten Sie jedoch, dass die Durchführung zusätzlicher Operationen mit Schlüsseldaten gefährlich ist und alle Arten von Sicherheitstests/-proofs/-zertifizierungen durchbrechen kann.

Beachten Sie, dass die meisten Java-Card-Implementierungen (oder vielmehr die Hardware des zugrunde liegenden Chips) sehr wahrscheinlich Prüfsummen über alle persistenten (EEPROM/Flash) -Speicher ausführen werden. Es ist auch sehr wahrscheinlich, dass die Schlüssel durch die Java Card-Implementierung (oder einen der darunter liegenden Layer) geschützt sind. Also im Hinblick auf den Schutz vor unvorhergesehenen Änderungen der Daten: Ich würde mir nicht allzu viele Sorgen machen. Sie brauchen die DES-Paritätsbits dafür nicht.


OK, ich habe das Gefühl, etwas wenig Fummelei tun, also hier ist der Java-Card-Code, um die Parität setzen Sie sich (ich lassen Sie die for-Schleife und den inlining und Dinge zu tun, wenn Sie nichts dagegen haben). Diese Berechnungen sollten (nahezu) konstante Zeit sein.

/** 
* 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

Zum Beispiel können Sie etwas Schreckliches tun und eine Tabelle verwenden [wie MBED_TLS] (https://www.google.cz/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwjMgeTditrVAhUBthoKHYsJAkQQFggMAE&url=https%3A % 2F% 2Ftls.mmb.org% 2Fapi% 2Fdes_8c_source.html & usg = AFQjCNFC5Um5PfILYbTQSCs9ZOdlBVGPIw). Ouch - hallo Seitenkanal, tschüss 128 Bytes für nichts. –

+1

Vielen Dank für Ihr "bisschen fummeln". Ich sehe keinen Seitenkanal, wenn ein hartkodiertes Byte-Array verwendet wird, können Sie das bitte ausführen? – Shuckey

+0

(Ich fürchte, das ist irrelevant für die Frage. Aber,) wie @Shuckey sagt - vorberechneten 256 Byte-Array ist (IMHO) der effektive Weg zu gehen. Und hasDESParity() könnte so aussehen: 'return makeDESParity (b) == b;' – vlp