我需要加密32位整数,因此它们由32位整数表示。是否可以使用32位块大小的块密码,因此输出为32位?
我目前正在使用DES但结果是64位整数。我不想将XOR加密作为最后的手段。
答案 0 :(得分:6)
Skip32,它基于Skipjack algorithm,是我所知道的唯一32位块密码:据称是Java实现here。
为安全起见,64位通常被认为是绝对最小块大小。
答案 1 :(得分:4)
要使用通用密码安全地使用此类工作,您可以在OFB,CFB或CTR等“流”模式下操作分组密码。这意味着您需要为要加密的每个整数提供合适的(不可预测的)初始化向量,或者(在CTR模式下)具有明确定义的消息顺序。
我假设你想稍后解密这些数字。如果您只是想创建一个周期为2 32 的伪随机生成器,您可以尝试其他技术。
答案 2 :(得分:2)
你可以将所有整数写入单字节数组并加密它们, 另一个想法是使用64位整数,在需要时将它们转换为32位。
答案 3 :(得分:2)
如果你不关心安全性,只想要一个非常小的32位分组密码,你可以尝试这个。我用它来生成整数的排列,以便创建哈希函数族,我认为它非常适合于此目的。
static uint syfer(uint key, uint data)
{
uint R = (data^key) & 0xFFFF, L = (data>>16) ^ (((((R>>5)^(R<<2)) + ((R>>3)^(R<<4))) ^ ((R^0x79b9) + R)) & 0xFFFF);
key = (key>>3) | (key<<29);
R ^= ((((L>>5)^(L<<2)) + ((L>>3)^(L<<4))) ^ ((L^0xf372) + (L^key))) & 0xFFFF;
return ((L ^ ((((R>>5)^(R<<2)) + ((R>>3)^(R<<4))) ^ ((R^0x6d2b) + (R^((key>>3)|(key<<29)))))) << 16) | R;
}
我可以尝试将它拆开,清理它,并将其扩展为更具可读性的东西。 (希望我没有犯错误。 超过我的睡觉时间。: - )
static uint Cipher(uint key, uint data)
{
uint L = data >> 16, R = data & 0xFFFF, S = 0x79b9;
for(int round=0; round<24; round++)
{
uint F = L ^ (((((R>>5)^(R<<2)) + ((R>>3)^(R<<4))) ^ ((R^S) + (R^key))) & 0xFFFF);
L = R;
R = F;
S += 0x79b9;
key = (key>>3) | (key<<29);
}
return (R<<16) | L;
}
你可以通过增加轮数来增加强度,但是如果你真的想要安全性(就你可以用32位块和密钥大小来获得它),你最好使用skip32,如上所述由格雷格斯。 (请注意,他发布的链接已损坏,但此页面包含C源:http://metacpan.org/pod/Crypt::Skip32)。该函数具有完全自包含的优点,但没有查找表或其他依赖项。
[编辑:我刚才意识到我没有发布解密代码。但后来你没有说解密。 ;-)如果有人想看,我可以写出来。它实际上恰好与上述相反......]
答案 4 :(得分:2)
您还可以考虑Speck,这是一种轻量级分组密码,有多种大小,包括32位块大小和64位密钥的版本。
答案 5 :(得分:1)
有点晚了,但32位分组密码是KATAN。它在软件中的表现是非常不可接受的。
答案 6 :(得分:0)
我将使用具有CTR密码模式的现代分组密码(例如AES,Twofish,Serpent)。埃里克森(Erickson)的回答已经提到了这个方向。我会在这里详细说明一下。
虽然密码模式的主要目标(*)是为了保护您免受密码块的统计分析(例如,防止连续的相同块产生相同的密码块),但您也可以使用CTR传输比密码块大小短的数据块。
上述所有块密码的块大小均为128位。只需在消息末尾添加额外的96位(例如零)即可(没关系)。以CTR模式对邮件进行编码。您需要提供一个IV块(初始化向量)。您无需保守其价值秘密。但是,对于安全应用,应该为每次传输随机选择一个新的。考虑到您对32位代码的限制,我假设您的安全性较低,可传输数据限制为32位,因此您可能会坚持使用固定的IV值。只需将结果裁剪为32位并传输即可。
要进行解码,请再次填充96位任意值,并使用具有上述IV值的CTR模式进行常规解码,然后将该值裁剪回32位。你完成了!
在类似Python的伪代码中(很抱歉,我没有进入.net)
# encode for plain_msg of length 32, key and iv
padded_plain_msg = plain_msg + [0]*96
padded_crypted_msg = encrypt(padded_plain_msg, key, mode=CTR, iv=iv)
crypted_msg = padded_crypted_msg[0:32]
# decode for crypted_msg of length 32, key and iv
padded_crypted_msg = crypted_msg + [0]*96
padded_decrypted_msg = encrypt(padded_crypted_msg, key, mode=CTR, iv=iv)
decrypted_msg = padded_decrypted_msg[0:32]
之所以可行,是因为CTR模式不会将密码直接应用于消息,而是应用于正在运行的计数器(CTR:CounTeR),并将结果与消息相加:
# CTR mode pseudocode on msg_blocks[0], msg_blocks[1], ..., msg_blocks[n-1]
# to crypted_block[0], crypted_block[1], ..., crypted_block[n]
for i in range(n): # i = 0, 1, ..., n-1:
# one implementation variant--there are others counter sequences, e. g.
# appending half-block sized iv & a half-block chunk containing i
crypted_block[i] = encrypt(iv+i, key) ^ msg_blocks[i]
请注意,如果您使用固定的IV值,则本质上您将拥有32位密码(如您所要求的),并且如果对手收集了足够的加密数据,则该密码始终是可攻击的。正如James K Polk指出的那样,如果您关心安全性,就永远不要使用小于64位的分组密码。
(*)ECB(电子代码簿)模式除外,这是一种奇妙的方式,可以说您将编码应用于每个块而没有任何依赖性