什么加密方案满足十进制明文的要求&密文并保留长度?

时间:2009-12-08 21:41:53

标签: c++ encryption cryptography aes

我需要一种加密方案,其中明文和密文完全由十进制数字组成。

此外,明文和密文的长度必须相同。

此外,基础加密算法应该是行业标准。 我不介意它是对称的(例如AES)还是非对称的(例如RSA) - 但它必须是一个公认的算法,我可以获得FIPS-140批准的库。 (否则它将无法通过安全审查阶段)。

使用AES OFB可以保留基于十六进制的输入的长度(即每个字节有256个可能的值:0x00 - > 0xFF)。但是,这对我来说无效,因为明文和密文必须完全是十进制的。

注意:“完全小数”可以用两种方式解释 - 这两种方式都可以满足我的要求:

  1. 输入&输出字节是字符'0' - > '9'(即字节值:0x30 - > 0x39)
  2. 输入&输出字节具有100(十进制)值:0x00 - > 0x99(即BCD)
  3. 更多信息: 最大明文&密文长度可能是10位十进制数。 (即如果使用'0' - >>'9'则为10个字节,如果使用BCD则为5个字节)

    请考虑以下示例以了解AES失败的原因: 输入字符串是8位数字。 最大8位数字是:99999999 在十六进制中,这是:0x5f5e0ff

    这可以视为4个字节:< 0x05>< 0xf5>< 0xe0>< 0xff>

    如果我使用AES OFB,我将得到4字节输出。

    最高可能的4字节密文输出为< 0xFF>< 0xFF>< 0xFF>< 0xFF>

    将此转换回整数给出:4294967295 即一个10位数字。

    ==>两位数太长了。

    最后一件事 - 所需的任何键/ IV的长度没有限制。

9 个答案:

答案 0 :(得分:7)

使用AES / OFB或任何其他流密码。它将生成伪随机位的密钥流。通常,您可以使用明文对这些位进行异或。代替:

For every decimal digit in the plaintext
  Repeat
    Take 4 bits from the keystream
  Until the bits form a number less than 10
  Add this number to the plaintext digit, modulo 10

要解密,请执行相同操作,但在最后一步中减去。

我认为这应该与正常使用流密码一样安全。如果数字0-15的序列与随机无法区分,则只有小于10的数字的子序列仍应是随机的。如果其中一个输入是随机的,使用加/减而不是XOR仍应产生随机输出。

答案 1 :(得分:1)

我不是一个密码大师,但是一个明显的问题浮现在脑海中:你会被允许使用One Time Pad加密吗?然后,您可以在解码系统中包含一大块真正随机的位,并使用随机数据以可逆的方式转换十进制数字。

如果这是可以接受的,我们只需要弄清楚解码器如何知道随机区块中的哪个位置来获取解码任何特定消息的密钥。如果您可以使用密文发送明文时间戳,那么很容易:将时间戳转换为数字,例如自纪元日期以来的秒数,模数该随机性块的长度,以及您在块。

具有足够大的随机性块,这应该是不可破解的。你可以让随机位本身用强加密加密,这样用户必须输入一个长密码来解锁解码器;这样,即使解密了解密软件,打破系统仍然不容易。

如果您对此感兴趣并希望我进一步扩展,请告诉我。我不想花很多时间在一个完全不符合你需求的答案上。

编辑:好的,带着微小的鼓励(“你可能会做某事”)我正在扩大我的答案。

这个想法是你得到一块随机性。一种简单的方法是将数据从Linux /dev/random设备中提取出来。现在,我将假设我们有办法为每条消息找到这个随机性块的索引。

索引随机性块并提取10个字节的数据。每个字节都是0到255之间的数字。将这些数字中的每一个添加到明文中的相应数字,模数为10,并且您具有密文的数字。只要你有随机数据块和索引就可以轻松地反转这个:你得到随机位并从密码数中减去它们,模数为10。

您可以将此视为在一个环中排列0到9之间的数字。添加是围绕环顺时针计数,减去逆时针计数。您可以添加或减去任何数字,它将起作用。 (我的这个答案的原始版本建议每个数字只使用3位。不够,正如下面@Baffe Boyois所指出的那样。谢谢你的修正。)

如果纯文本数字是6,随机数是117,那么:6 + 117 == 123,模10 == 3. 3 - 117 == - 114,模10 = = 6.

正如我所说,如果您可以使用外部明文信息(如时间戳),则查找索引的问题很容易。即使你的对手知道你正在使用时间戳来帮助解码消息,如果没有随机性块也没有用。

如果始终传递消息,找到索引的问题也很容易;你可以有一个商定的系统来生成一系列索引,然后说“这是我收到的第四条消息,所以我使用了系列中的第四个索引。”作为一个简单的例子,如果这是收到的第四个消息,您可以同意使用索引值16(第四个消息为4,每个一次性填充为4个字节)。但是你也可以使用批准的伪随机数生成器中的数字,用一个约定的常量值作为种子进行初始化,然后你会在随机性块中获得一些不可预测的索引。

根据您的需要,您可能拥有真正大量的随机数据(数百兆甚至更多)。如果您使用10个字节作为一次性打击垫,并且您从不使用重叠打击垫或重复使用打击垫,那么1兆字节的随机数据将产生超过100,000个一次性打击垫。

答案 2 :(得分:1)

一个潜在的候选人是FFX加密模式,最近已提交给NIST。

答案 3 :(得分:1)

流密码需要nonce才能获得安全性;必须永远不要将相同的密钥流状态重用于不同的消息。该随机数增加了有效的密文长度。

流模式中使用的分组密码基本上存在相同的问题:密码文本中必须包含唯一的初始化向量。

许多流密码也容易受到密文操作的影响,在密文中稍微翻转不可察觉地翻转明文中的相应位。

如果随机选择数字,每个数字只加密一次,数字比块大小短,ECB提供了良好的安全性。在这些条件下,我建议在ECB模式下使用AES作为最小化密文长度的解决方案,同时提供强大的隐私和完整性保护。

如果在密文的上下文中有一些其他信息可以用作初始化向量(或nonce),那么这可能有效。这可能是明确的,例如购买期间的交易标识符,或者隐含的信息,例如消息的序列号(可以在CTR模式下用作计数器)。我想VeriShield正在做这样的事情。

答案 4 :(得分:0)

您可以使用八进制格式,它使用数字0-7,三个数字组成一个字节。这不是最节省空间的解决方案,但它快速而简单。

示例:

Text: Hello world!
Hexadecimal: 48 65 6C 6C 6F 20 77 6F 72 6C 64 21
Octal: 110 145 154 154 157 040 167 157 162 154 144 041

(为了清晰起见添加了空格以分隔字节)

答案 5 :(得分:0)

我不相信你的要求能够得到满足(无论如何都很容易),尽管可能会非常接近。

AES(与大多数加密算法一样)被编写为使用八位字节(即8位字节),并且它将产生8位字节。一旦完成它的事情,将结果转换为仅使用十进制数字或BCD值是不可能的。因此,您唯一的选择是将输入从十进制或BCD数字转换为尽可能完全填充八位字节的数字。然后,您可以对其进行加密,最后将输出重新编码为仅使用十进制或BCD数字。

当您转换ASCII数字以填充八位字节时,它会稍微“压缩”输入。然后加密将产生与输入相同的输出大小。然后,您将对其进行编码,仅使用十进制数字,这会将其扩展回原始大小。

问题在于10和100都不是一个你很容易完全适合一个字节的数字。 1到100之间的数字可以用7位编码。因此,您基本上将它们视为比特流,一次将它们分为7位,但一次取出8位以获取加密字节。

它使用的空间稍微好一点,但它仍然不完美。 7位可以编码0到127之间的值,而不仅仅是0到99,所以即使你将使用所有8位,你也不会使用这8位的所有可能组合。同样,在结果中,一个字节将变成三个十进制数字(0到255),这显然浪费了一些空间。因此,您的输出将略大于您的输入。

为了更接近这一点,您可以在加密之前使用Huffman或LZ *压缩(或两者)压缩输入。然后你会做大致相同的事情:加密字节,并使用0到9或0到99之间的值对字节进行编码。这样可以更好地使用加密字节中的位,因此浪费很少该转换中的空间,但没有改善输出端的编码。

答案 6 :(得分:0)

对于那些怀疑FFX模式AES的人,请随时与我联系以获取更多详细信息。我们的实现是AES模式,有效地位于现有密码之上。 NIST模式网站上有证明/验证的规范。 FFSEM模式AES包含在FFX模式下。

http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ffx/ffx-spec.pdf

如果它有意义,您还可以直接与NIST进行对话,了解他们在模式提交/ AES模式接受方面的状态,以解决您的FIPS问题。 FFX具有安全性证明,独立的加密审查,并不是“新密码”。然而,它基于可追溯到20多年的方法 - 经过验证的技术。在实现中,我们能够加密数据,同时保留长度,结构,完整性,类型和格式。例如,指定显式格式策略,输出将为NNN-NN-NNNN。

因此,作为AES模式,我们可以在大型机环境中实现,我们可以简单地在z10上使用本机AES处理器。类似于使用HSM设备的开放系统 - 我们可以坐在现有的AES实现之上。

以这种方式保存加密格式(通常称为加密)已经在工业中使用,并且可以在现成的产品中使用,而且可以快速部署 - 已经在POS设备等中使用,付款系统,企业部署等。

马克·鲍尔 产品管理副总裁 电压安全 如需更多信息,请发送电子邮件至info@voltage.com或查看我们的网站了解更多信息。

答案 7 :(得分:0)

类似Feistel密码的东西应该符合您的要求。将您的输入数字拆分为两部分(每个部分为8位数字),通过一个不必要的可逆或双射函数传递一部分,并从该函数的结果中减去另一部分(模数为100,000,000)。然后以某种方式重新排列数字并重复一遍。理想情况下,应该稍微改变每次使用的功能。解密类似于加密,除了通过撤消上一个重新排列步骤开始,然后从使用消息的第一部分上使用的最后一个函数(再次,模数100,000,000)的结果中减去消息的第二部分,然后撤消以前的重新排列步骤等。

Feistel密码的最大困难是找到一个功能,通过合理数量的轮次实现良好的加密,并确定实现良好加密需要多少轮。如果速度不重要,可以使用AES之类的东西来执行加扰功能(因为它不必是双射的,你可以在每个AES步骤之前任意填充数据,并将结果解释为一个大的二进制数模数100,000,000)个。对于轮数,10可能太少,1000可能过多。我不知道最好的之间会有什么价值。

答案 8 :(得分:-1)

仅使用10位数作为输入/输出是完全不安全的。它是如此不安全,很可能会在实际应用中破解,所以考虑使用至少39位数(相​​当于128位)如果你只使用10位数,那么在这种情况下使用AES是没有意义的发明你自己的(不安全的)算法的机会。

唯一可以解决这个问题的方法是使用STREAM密码。使用256位密钥“SecureKey”和初始化向量IV,在开始季节的每个开始时应该是不同的。 将此数字转换为77位(十进制)数字,并使用“加上白色溢出”,每个数字以10为模数。

例如

 AES(IV,KEY) =      4534670 //and lot more
 secret_message =   01235
                          + and mod 10 
 ---------------------------------------------
 ciphertext     =   46571 // and you still have 70 for next message

当您用完来自流密码的数字时 - >> AES(IV,KEY)增加IV并重复IV = IV + 1

请记住,你应该绝对不会两次使用相同的IV,所以你应该有一些方案来防止这种情况。

另一个问题也在于生成Streams。如果您生成的数字高于10 ^ 77,则应丢弃该数字增加IV并再次尝试使用新的IV。另一方面,你很有可能会有偏见的数字和漏洞。

此计划中也很可能存在缺陷,或者您的实施中存在缺陷