DESKey是否保留无效的奇偶校验位?

时间:2017-08-15 06:20:14

标签: cryptography smartcard javacard des

根据DES规范,密钥的每个字节的最后一位用于错误检测(每个字节应具有奇校验)。因此,有效密钥长度为56位,而不是64位。

但是,在许多用例中,不会检查这些奇偶校验位。有时它们甚至用于完全不同的目的: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规范中找到任何提及这种行为的保证。

这条信息对我来说非常重要;否则我将不得不存储我的"无效的奇偶校验位"与密钥实例分开。

1 个答案:

答案 0 :(得分:3)

如果不符合规格,则无法保证。它真的那么简单;对于卡实施者而言,没有另外说明的说明(如果有的话,可能会改变而不触及原始定义)。

关于攻击,关键操作可能很棘手。因此,关于保持密钥数据的完整性并且不使用通用CPU迭代密钥位,有很多要说的。此外,在对关键数据执行其他操作(例如使用散列函数计算密钥检查值)或使用相同的密钥作为MAC输入(对称签名)时,可能会非常棘手。

当然,完全可以使用您自己的代码对密钥位执行奇偶校验操作。您可以将结果与测试向量或使用Java SecretKeyFactory生成的密钥进行比较。但是,由于奇偶校验位不会用于密钥计算,因此只有在您想要将密钥导出设备时才需要这样做。但请注意,对关键数据执行额外操作非常危险,可能会破坏各种安全测试/校样/认证。

请注意,大多数Java Card实现(或者更确切地说,底层芯片的硬件)很可能无论如何都会对所有持久性(EEPROM /闪存)内存执行校验和。密钥也很可能受Java Card实现(或其中一个底层)的保护。因此,关于防止不可预见的数据更改:我不会过分担心。你不需要DES奇偶校验位。

好吧,我觉得自己有点小提琴,所以这里有Java Card代码来自己设置奇偶校验(我会让你做for循环和内联和东西,如果你没有&# 39; t mind)。这些计算应该(接近)恒定时间。

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