我正在使用Java的SunJCE提供程序来生成一个7位密钥:
KeyGenerator v = KeyGenerator.getInstance("DES")
Provider p = v.getProvider
assert(p.getClass().getSimpleName() == "SunJCE")
v.init(56)
Key k = v.generateKey()
assert(k.getEncoded().getLength == 7)
当我运行上面的程序时,我得到的错误表明k
的长度实际上是 8(64 位(而不是 56 位,奇怪的是KeyGenerator
被初始化为只生成 56 位密钥,那么为什么k
的实际长度不正确呢?
DES 密钥的编码方式为每 7 位使用 8 位,其中每个字节的最低有效位用于使位数为奇数。因此,如果前 7 位将 6、4 或 2 位设置为 1,则设置最不重要的位(设置为 1(。否则,它将重置/取消设置/保留为零。因此,56 位 DES 密钥编码为 64 位/8 字节,用于三重 DES 的 112 位 2 密钥编码为 128 位,168 位 DES 密钥使用 192 位编码。
奇偶校验位可以用作某种检查,以查看 DES 密钥是否未被更改(尽管它也不是很好(。如今,大多数DES实现将完全忽略奇偶校验位,但JavaKeyGenerator
仍然可以正确设置它们。您可以通过验证结果键中每个字节b
的Integer.bitCount(b & 0xFF) % 2 == 1
来测试这一点:它应始终返回true
。
更现代的对称密码尝试使用完全(伪(随机密钥;256位AES或HMAC密钥仅由随机字节组成。
对于大多数非对称密码来说,情况并非如此;对大多数非对称密码的公钥或私钥进行编码将导致比密钥大小多得多的位。非对称密码的密钥大小通常是确定密钥强度的参数的大小,例如RSA的模数大小。
笔记:
- DES 只有 56 位的密钥大小(和强度(,并且被认为是完全损坏的:使用 128 位或更多的密钥(如果您注意的话,这也排除了双密钥 112 位三重 DES 密钥(和现代密码,如 AES。
- 你的断言测试的事情应该永远是真实的,对我来说没有什么意义。如果有什么应该测试的话,那就是用于生成密钥的随机数生成器(不幸的是,这些密钥是出了名的难以测试(。
- 在测试提供程序名称时 - 如果您问我,这是一种危险且不可移植的做法 - 那么您至少应该使用
Provider#getName()
(可能还有其他返回有关提供程序的有用信息的 getter(而不是类名。类名是一个实现细节,实际上可能会更改 - 即使提供程序名称没有更改。