2017-08-15 62 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