根据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);
是否保证inputKey
和outputKey
数组最终会包含相同的数据,即使inputKey
中的奇偶校验位无效?我用几种卡类型进行了几次实验,它们都保留了我在这些奇偶校验位中放入的任何数据,但我没有在Java Card规范中找到任何提及这种行为的保证。
这条信息对我来说非常重要;否则我将不得不存储我的"无效的奇偶校验位"与密钥实例分开。
答案 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;
}