将30位数字加密为6个字符的字母数字字符串
我在寻找一种方法来加密或混淆一个30位的数字。
结果会被分成3组,并以6个字符的字母数字形式展示给用户,这些字符会用一种叫做base32的编码方式表示,但用户不应该能从这些字母数字字符串中发现任何规律。例如,用户可能会看到3个字符串:ASDFGH、LKJHGF、ZXCVBN,而这些字符串可能对应的数字是1073741821、1073741822、1073741823。但用户应该很难轻易找出这种规律。
我看过一些加密算法,比如DES。这是一个不太好的、简单的尝试:
import struct
from Crypto.Cipher import DES
from .baseconv import base32_urlsafe
_KEY = '\x81\x98\xe1\x14<\xb3\xe8\x10'
_encryptor = DES.new(_KEY)
def encrypt_number(number):
encrypted_i64 = struct.unpack(
'!Q', _encryptor.encrypt(struct.pack('!Q', number))
)[0]
encrypted_i30 = encrypted_i64 >> 34
return base32_urlsafe.encode(encrypted_i30)
但显然,如果需要解密这个字符串,我是做不到的,而且这种方法会失去唯一性。我也考虑过使用异或(XOR)操作,但这太容易预测了,因为数字往往是连续的。
我从来没有需要过像这样的编码。所以,我在寻找一些加密算法或方法来研究和考虑。我使用的是Python,但其他语言的想法或例子也很欢迎。
3 个回答
你可以自己动手做一个30位的块加密器,使用Luby-Rackoff结构。
你可以随便选择一个哈希函数来作为“F”盒子(比如,取你数据的低15位和一个秘密钥匙结合起来的murmurhash),然后可以运行任意多的轮次,最后得到的结果就是一个可逆的伪随机排列,适用于30位数字。
当然,这样的加密方式可能不会“在密码学上很强”,但用30位的数字确实没办法做到这一点。
一种方法是创建一个包含10亿(2的30次方)个独特随机数字的表格,然后用你的30位数字作为这个表格的索引。
如果这个表格太大了,你可以做一个小一点的,比如有32768个条目,然后分别对下半部分和上半部分进行索引。
为了避免上半部分在连续的值中不变,可以在查找表格之前,把下半部分的加密值加到上半部分。
加密
t = table of 32768 random values
upper15 = input_value >> 15
lower15 = input_value & 0x7FFF
lowercoded = t[lower15]
uppercoded = t[ ( lowercoded + upper15 ) % 32768 ]
result = uppercoded << 15 + lowercoded
解密
upper15 = input_value >> 15
lower15 = input_value & 0x7FFF
lowereddecoded = t.index(lower15)
tmp = t.index(upper15)
tmp -= lower15
if tmp< 0: tmp += 32768
upperdecoded = tmp
result = upperdecoded << 15 + lowerdecoded
格式保留加密可能在这里会有帮助。
比如,Black和Rogaway在他们的论文《任意有限域的密码》中提到的循环行走方法,似乎是一个可行的解决方案。举个例子,使用一个32位的密码(比如Greg Rose的Skip32)。用这个密码对你的30位输入进行加密。如果结果是一个30位的整数(也就是说,前面2位是0),那就完成了;如果不是,就继续用这个密码加密,直到得到一个30位的结果。解密的过程也是这样进行的。
如果你不需要特别安全的解决方案,那么Hasty Pudding密码可能是一个替代选择。它可以加密任意大小的输入。这个密码曾经参加过AES竞赛,但没有走得太远,所以分析得不多。不过,我认为它比这里在stackoverflow上提出的任何临时解决方案都要合适得多。