提问人:csharpelestudiente 提问时间:10/1/2023 更新时间:11/8/2023 访问量:76
如何将数据库中的顺序整数编码和解码为伪随机 Base36 6 个字符长的字符串
How to encode and decode sequential integer from DB to a pseudorandom Base36 6 character long string
问:
几天来,我试图找到解决这个问题的方法,但我还没有成功。
我需要实现 2 个功能: 一个用于将整数编码为字符串,一个用于将字符串解码为原始整数。 编码的字符串长度需要为 6 个字符,由大写字母和数字 (Base36) 组成,并且需要随机显示。它不需要高度安全,它只需要看起来足够随机,这样看到它的人就无法在第一眼看到它与原始整数建立连接。 因为我正在尝试对 ID 进行编码,所以对于每个给定的整数,每个字符串都应该是唯一的(没有冲突)。 我发现并实现了一些满足这些要求的算法,但有一个问题:彼此相邻的数字太相似了。基本上它们只差一个字符。尽管它不必非常安全,但接近的数字需要尽可能不同。 实际上,该算法最多只能编码 100k 的整数,因此很可能永远不会使用更高的值,但要使解决方案变得出色,它需要覆盖最多几百万的值。
我需要的示例: 1 -> A39MNY 2 -> HDY19X ... 15 -> 2I8PZ9 等。
我通过使用种子随机对象实现了这一点,但解码部分是问题所在,因为我从输入的整数中制作了种子,通过某种操作修改,因此要在一次迭代中实现编码,必须知道原始整数。通过运行编码功能实现解码,直到找到数字。
如果这些要求无法通过制作某种更简单的算法来实现,我愿意使用某种加密。
我对这个问题非常感兴趣,我仍在积极寻找解决方案。非常感谢任何让我更接近解决方案的帮助。
答:
选择一个大素数。在范围内选择一个随机数。使用费马小定理来扰乱大范围。
您可以对不同的字符串进行编码。寻找比这小一点的素数,我们能做的最好的事情就是.36^6 = 2176782336
p
2176782317
所以现在我们只需要一个大数字.n
import random
print(random.randomint(1, 2176782317))
这给了我.1173770130
做一点算术以找到它的倒数。为此,我们使用 if 是素数并且对 p 相对素数的事实,那么 mod ,所以乘法逆是 。p
a
p
1 = a^(p-1) = a * a^(p-2)
a^(p-2)
def n_pow_m_mod_k (n, m, k):
answer = 1
power = n
while 0 < m:
if 1 == m % 2:
answer = (answer * power) % k
m -= 1
m = m // 2
power = (power * power) % k
return answer
print(n_pow_m_mod_k(1173770130, 2176782317 - 2, 2176782317))
这给出了乘法逆。检查一下。6232931
print((1173770130 * 6232931) % 2176782317)
它给了,这就是我们想要的。1
现在让我们把这些神奇的数字变成工作代码。
# Set up the character/number code.
alphabet = '0123456789ABCDEFGHIJKLMONPQRSTUVWXYZ'
chr_to_pos = {}
for i in range(len(alphabet)):
chr_to_pos[alphabet[i]] = i
def id_to_code (n):
m = (n * 1173770130) % 2176782317
answer = ''
for _ in range(6):
answer += alphabet[m % 36]
m = m // 36
return answer
def code_to_id (code):
m = 0
for i in range(len(code)):
m += chr_to_pos[code[i]] * 36**i
return (m * 6232931) % 2176782317
for i in range(20):
print(i, id_to_code(i), code_to_id(id_to_code(i)))
你有它。易于反转的代码,具有不太容易看到的模式和数十亿的范围。
(免责声明:我听信了你的话,你不需要这个来保证安全。这绝对是不安全的。
评论
上一个:将十六进制值转换为日期
评论