DESKey 是不是保留无效的奇偶校验位?
Posted
技术标签:
【中文标题】DESKey 是不是保留无效的奇偶校验位?【英文标题】:Does DESKey preserve invalid parity bits?DESKey 是否保留无效的奇偶校验位? 【发布时间】:2017-08-15 06:20:14 【问题描述】:根据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 规范中没有发现任何提及这种行为是可以保证的。
这条信息对我来说很重要;否则我将不得不将我的“无效奇偶校验位”与密钥实例分开存储。
【问题讨论】:
我遇到了完全相同的困境,并决定将密钥版本存储在一个单独的字段中以确保安全。我也无法在规范中找到任何保证——我敢打赌,它是未定义的,因此很危险。我的卡片也完好无损地保持了奇偶校验位......祝你好运! 【参考方案1】:如果不在规格中,则无法保证。真的就这么简单;没有针对卡实现者的单独规范另有说明(如果有,可能会在不触及原始定义的情况下发生变化)。
在攻击方面,对键的操作可能很棘手。因此,关于保持关键数据完整且不使用通用 CPU 对关键位进行迭代,有很多话要说。此外,当对密钥数据执行其他操作时可能会很棘手,例如使用散列函数计算密钥校验值或使用相同的密钥作为 MAC 的输入(对称签名)。
当然,完全可以使用您自己的代码对密钥位执行奇偶校验操作。您可以将结果与测试向量或使用 Java SecretKeyFactory
生成的键进行比较。但是,由于奇偶校验位不会在密钥计算中使用,因此只有在您想将密钥导出设备时才需要这样做。但同样请注意,对关键数据执行额外操作是危险的,可能会破坏各种安全测试/证明/认证。
请注意,大多数 Java Card 实现(或者更确切地说,底层芯片的硬件)很可能会在所有持久性(EEPROM/闪存)内存上执行校验和。密钥也很可能受到 Java Card 实现(或底层之一)的保护。因此,关于防止数据发生不可预见的变化:我不会过分担心。您不需要 DES 奇偶校验位。
好的,我想做点小事,所以这里是用于自己设置奇偶校验的 Java Card 代码(如果你不介意的话,我会让你做 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;
【讨论】:
例如,您可以做一些可怕的事情并使用表格like MBED_TLS does。哎哟 - 你好侧通道,再见了 128 字节。 感谢您的“摆弄”。使用硬编码字节数组时,我没有看到任何侧通道,您能详细说明一下吗? (恐怕这与问题无关。但是,)正如@Shuckey所说——预先计算的256字节数组是(恕我直言)有效的方法。 hasDESParity() 可能看起来像这样:return makeDESParity(b)==b;
如果内存访问触发了缓存更新,那么它可能会泄漏信息。如果表可以在内存中移动,那么每个字节值都可以单独测试。
@MaartenBodewes:你说的很有道理。我想知道这是否是实际的想法。如果您有一些关于现实世界智能卡安全控制器缓存定时攻击的链接,我将不胜感激......以上是关于DESKey 是不是保留无效的奇偶校验位?的主要内容,如果未能解决你的问题,请参考以下文章