java - 为什么从 Java DES KeyGenerator 生成的密钥大小不正确?
问题描述
我正在使用 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
仍将正确设置它们。您可以通过验证结果键中的Integer.bitCount(b & 0xFF) % 2 == 1
每个字节来测试这一点b
:它应该始终返回true
.
更现代的对称密码尝试使用完全(伪)随机密钥;256 位 AES 或 HMAC 密钥仅由随机字节组成。
对于大多数非对称密码来说,情况并非如此。对大多数非对称密码的公钥或私钥进行编码将导致比密钥大小多得多的位数。非对称密码的密钥大小通常是决定密钥强度的参数的大小,例如 RSA 的模数大小。
笔记:
- DES 只有 56 位的密钥大小(和强度),并且被认为是完全损坏的:使用 128 位或更多的密钥(如果您注意的话,这也排除了两个 112 位三重 DES 密钥)和一个现代密码,如 AES。
- 您的断言测试了应该始终正确且对我来说毫无意义的事情。如果要测试任何东西,那就是用于生成密钥的随机数生成器(不幸的是,众所周知,这些密钥很难测试)。
- 在测试提供者名称时——如果你问我,这是一种危险且不可移植的做法——那么你至少应该使用
Provider#getName()
(可能还有其他返回有关提供者有用信息的 getter)而不是类名。类名是一个实现细节,实际上可能会改变——即使提供者名没有改变。
推荐阅读
- c# - 在运行时添加到功能区一次有效
- google-apps-script - 如何在空行后找到单元格行迭代
- php - Shopify REST API - 如何连接?
- qt - 编译时不存在自定义属性?“不能分配给不存在的财产”
- c# - 如何将 curl 请求转换为具有 --resolve 的 HttpClient
- html - 有没有办法让 GIF 在鼠标悬停时播放并暂停?
- arrays - 我不明白为什么我的代码适用于我的结构数组,但不适用于包含该结构数组的结构?
- sql - 将监视添加到 SQL 选择语句
- perl - 启用用户选项以覆盖变量的值
- python - How can I find the file name in a directory?