我有一堆48位(6字节)值需要对称加密。这两个要求是:
生成的加密值也需要48位(6字节)长。他们关键本身可以(并且最好是)更长时间来防止暴力攻击。
生成的加密值需要是确定性的,即使用密钥B的值A将始终生成加密值C(我们在运行时加密并向用户显示加密数据,因此需要始终显示相同的值)
我发现的所有分组密码都使用了64的最小块大小并且看起来是固定的(不能使用任意块大小)。我应该考虑流密码吗?
我是用Java做的。
注意:我已经看过this question及相关答案,但不清楚这些建议是否符合我的第二个要求。
答案 0 :(得分:5)
答案 1 :(得分:4)
(抱歉,我最初误读了认为需要6个字节的INPUT数据的要求。)
我认为您无法使用标准加密算法完全满足您的需求:
现在,这并不意味着无法开发48位分组密码 - 事实上我敢说有一些密码 - 只是没有经过多年的沼泽标准密码来自加密社区的审查具有该块大小。
所以我建议选项是:
后一种选择的明显问题是,惠斯特标准分组密码通常基于共同的一般原则,它们采用经过相当严格审查的特定设计决策;你的大概不会。
我还建议从问题中稍微退一步(或者或许还要解释一下你正在尝试做的事情),因为它似乎是基于通常违反良好安全措施的要求(具有相同的要求)例如,明文总是加密到相同的密文,这是人们通常会特别避免的。所以你可以拥有世界上设计最好的Feistel密码,但在你如何使用它时会引入一些其他的漏洞。
[*]通常不建议使用TripleDES,因为AES可以更有效地提供更好的安全性(您可能希望看到我在Java中使用的一些comparative timings of block ciphers来查看它有多糟糕)。但是,这可能与您的特定应用无关。
不,只是用您不关心的一些字节“填充”您的数据(但如果这是您的要求则总是相同的),以便达到块的大小。 (如果您使用了适当的padding mode,那么这将为您完成。)
答案 2 :(得分:2)
我相信这就是你要找的东西
http://web.cs.ucdavis.edu/~rogaway/papers/shuffle.html
此算法允许您从安全PRF构建PRP(即任意长度分组密码)(例如sha256,blake2)
CTR模式下的分组密码与流密码具有相同的问题 如果没有合适的MAC(需要增加更多字节),它就容易被翻转 如果没有唯一的IV(也需要添加更多的字节),它将只是一个破碎的实现。
答案 3 :(得分:1)
如果每次加密都有一个唯一的盐,你可以只使用流密码(甚至不要考虑重新使用相同的盐,因为这样做很容易打破)。
如果您有这样的唯一值(例如已经与您的值相关联的序列号),您可以使用例如流密码RC4-drop。
如果您还没有这样的唯一编号,则可能无法使用流密码,因为您的结果只有48位(因此没有留给盐的空间。)
对于48位的分组密码 - 对不起,我也不知道这样的密码。也许你可以做的是将四个48位值组合成一个192位值,产生三个64位块,对它们进行编码,然后再将它们分成四个48位值。 (我不知道,如果你的情况可能会有可能吗?)
答案 4 :(得分:1)
如果您有一个与每个明文值相关联的唯一计数器/序列号,那么您可以在CTR(计数器)模式下使用任何分组密码。
在密钥K下加密序列号为N的值V:
从不使用相同的密钥和序列号来加密两个不同的值。
序列号必须是唯一的。如果序列重新启动,则必须使用新密钥。
答案 5 :(得分:0)
2009年设计了一个48位的80位密钥密码--KATAN48(KTANTAN48的系列版本有一些关键的调度问题。到目前为止,它没有被破坏,并且具有相当高的安全裕度,所以它有通过了时间的考验。
答案 6 :(得分:0)
这是同时满足您两个要求的建议解决方案。
如果您使用32位块大小的密码(例如Skip32)并运行两次,该怎么办,如下所述。
您有一个48位值要编码,例如:
f2800af40110
使用某种方法将其拆分为32位值和16位值。在这里,我们只获取左4个字节和右2个字节(但实际上,您可以使用秘密位掩码,请参见下文)。
32-bit value: f2800af4
16-bit value: 0110
使用Skip32使用密钥K1加密第一个密钥,假设我们得到:
Encrypted 32-bit value: b0daf2b9
将其拆分为两个16位值(同样,您可以使用秘密位掩码,但是在此示例中,我们将获取左右两个字节)。
Value 1: b0da
Value 2: f2b9
将值1与第1步中的16位值结合起来,以获得新的32位值:
b0da0110
再次使用Skip32,用密钥K2对所得的32位值进行加密:
Encrypted 32-bit value: 6135d8f4
将此32位值与第3步中的值2相结合,以获得48位加密结果。
6135d8f4f2b9
结果既是确定性的又是可逆的。没有两个输入将产生相同的输出。
上面的步骤1和3将以可预测的方式拆分值。我不确定这是否会带来任何弱点,但是一种替代方法是使用位掩码。如果我们想将48位输入数字拆分为32位和16位,我们可以提出一个位掩码,本质上是一个带有16 1的数字,它可以指示我们如何将输入数字的位拆分为两个输出数字,如下所示:
INPUT : 111100101000000000001010111101000000000100010000
BITMASK: 001010111001110000100000010001100000011001100000
| | ||| ||| | | || || ||
VALUE 1: 1 0 101 000 0 1 10 00 00 => a860
VALUE 2: 11 1 0 00 0000 010101 110 000000 10 10000 => e015c050
类似地,对于第4步和第6步,您可以通过基于位掩码交织位来组合两个值。
如果每个步骤使用单独的位掩码,而每个步骤使用单独的键,则最终将获得2个密钥和4个位掩码,所有这些都需要加密/解密值。
“” Skip32具有快速,为连续的输入值创建非常不同的加密值以及产生与输入大小相同的输出的罕见特性。这些使得此密码对于混淆一系列连续整数(例如自动-增加的数据库ID)。” -https://docs.rs/skip32/1.0.5/skip32/
对加密方法有什么想法的人比我有经验吗?