什么类型的加密用于48位到48位?

时间:2010-09-02 16:48:54

标签: java encryption cryptography

我有一堆48位(6字节)值需要对称加密。这两个要求是:

  1. 生成的加密值也需要48位(6字节)长。他们关键本身可以(并且最好是)更长时间来防止暴力攻击。

  2. 生成的加密值需要是确定性的,即使用密钥B的值A将始终生成加密值C(我们在运行时加密并向用户显示加密数据,因此需要始终显示相同的值)

  3. 我发现的所有分组密码都使用了64的最小块大小并且看起来是固定的(不能使用任意块大小)。我应该考虑流密码吗?

    我是用Java做的。

    注意:我已经看过this question及相关答案,但不清楚这些建议是否符合我的第二个要求。

7 个答案:

答案 0 :(得分:5)

答案 1 :(得分:4)

(抱歉,我最初误读了认为需要6个字节的INPUT数据的要求。)

我认为您无法使用标准加密算法完全满足您的需求:

  • 流密码的问题在于,标准的密码通过从密钥生成伪随机位流然后用明文对这些位进行异或来有效地工作。实际上这意味着你永远不应该使用相同的位流两次(例如,如果你这样做,那么XORing两个密文给你的结果与对相应的明文相同;并且在任何情况下都有48位,只有2 ^ 48可能比特流,所以你可以通过蛮力来测试它们;
  • 块密码的问题在于,据我所知,块大小为48位,没有标准密码。

现在,这并不意味着无法开发48位分组密码 - 事实上我敢说有一些密码 - 只是没有经过多年的沼泽标准密码来自加密社区的审查具有该块大小。

所以我建议选项是:

  • 放宽了对48位密文的要求;例如,TripleDES具有64位块大小并且“相当”安全(相当于112位安全性)[*];
  • 原则上,您可以使用您需要的任何块大小来实现自己的分组密码,尽可能贴近标准设计,例如:遵循一些通常推荐的设计原则的Feistel网络 - 作为起点,参见Schneier,“应用密码学”,第346页,“分组密码设计理论”。

后一种选择的明显问题是,惠斯特标准分组密码通常基于共同的一般原则,它们采用经过相当严格审查的特定设计决策;你的大概不会。

我还建议从问题中稍微退一步(或者或许还要解释一下你正在尝试做的事情),因为它似乎是基于通常违反良好安全措施的要求(具有相同的要求)例如,明文总是加密到相同的密文,这是人们通常会特别避免的。所以你可以拥有世界上设计最好的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:

  • 将N展开为块的大小;
  • 使用分组密码和密钥K加密N;
  • 取结果的前48位并用V XOR对它们进行异或。
解密是一样的。使用此方法最重要的事情是:

从不使用相同的密钥和序列号来加密两个不同的值。

序列号必须是唯一的。如果序列重新启动,则必须使用新密钥。

答案 5 :(得分:0)

2009年设计了一个48位的80位密钥密码--KATAN48(KTANTAN48的系列版本有一些关键的调度问题。到目前为止,它没有被破坏,并且具有相当高的安全裕度,所以它有通过了时间的考验。

答案 6 :(得分:0)

这是同时满足您两个要求的建议解决方案。

如果您使用32位块大小的密码(例如Skip32)并运行两次,该怎么办,如下所述。

您有一个48位值要编码,例如:

f2800af40110

步骤1:

使用某种方法将其拆分为32位值和16位值。在这里,我们只获取左4个字节和右2个字节(但实际上,您可以使用秘密位掩码,请参见下文)。

32-bit value: f2800af4
16-bit value: 0110

步骤2:

使用Skip32使用密钥K1加密第一个密钥,假设我们得到:

Encrypted 32-bit value: b0daf2b9

步骤3:

将其拆分为两个16位值(同样,您可以使用秘密位掩码,但是在此示例中,我们将获取左右两个字节)。

Value 1: b0da
Value 2: f2b9

步骤4:

将值1与第1步中的16位值结合起来,以获得新的32位值:

b0da0110

步骤5:

再次使用Skip32,用密钥K2对所得的32位值进行加密:

Encrypted 32-bit value: 6135d8f4

步骤6:

将此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及其使用案例的简短说明

“” Skip32具有快速,为连续的输入值创建非常不同的加密值以及产生与输入大小相同的输出的罕见特性。这些使得此密码对于混淆一系列连续整数(例如自动-增加的数据库ID)。” -https://docs.rs/skip32/1.0.5/skip32/

对加密方法有什么想法的人比我有经验吗?