如何将 DB 中的连续整数编码和解码为伪随机 Base36 6 个字符长字符串

问题描述 投票:0回答:1

这几天我一直在努力寻找解决这个问题的方法,但还没有成功。

我需要实现2个功能: 一种用于将整数编码为字符串,另一种用于将字符串解码为原始整数。 编码字符串需要有 6 个字符长,由大写字母和数字 (Base36) 组成,并且需要随机出现。它不需要高度安全,只需要显得足够随机,这样看到它的人第一眼就无法与原始整数建立联系。 因为我正在尝试对 ID 进行编码,所以每个字符串对于每个给定的整数都应该是唯一的(无冲突)。 我发现并实现了一些满足这些要求的算法,但有一个问题:彼此相邻的数字太相似。基本上它们只有一个字符不同。尽管不一定非常安全,但接近的数字需要尽可能不同。 实际上,该算法最多可对高达 100k 的整数进行编码,因此很可能永远不会使用更高的值,但为了使解决方案变得出色,需要覆盖高达几百万的值。

我需要的示例: 1 -> A39MNY 2 -> HDY19X …… 15 -> 2I8PZ9 等等

我通过使用种子随机对象实现了这一点,但解码部分是问题,因为我通过某种操作修改了输入的整数来制作种子,因此为了在一次迭代中实现编码,原始整数必须是已知。解码是通过运行编码函数直到找到数字来实现的。

如果通过设计某种更简单的算法无法满足这些要求,我愿意使用某种加密。

我对这个问题非常感兴趣,并且仍在积极寻找解决方案。非常感谢任何让我更接近解决方案的帮助。

algorithm encoding decoding
1个回答
0
投票

选择一个大素数。在范围内选择一个随机数。使用费马小定理来打乱一个大范围。

您可以对

36^6 = 2176782336
不同的字符串进行编码。寻找比它小一点的素数
p
,我们能做的最好的就是
2176782317

所以现在我们只需要大量

n

import random
print(random.randomint(1, 2176782317))

这给了我

1173770130

做一些算术来找到它的倒数。

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, 2176782315, 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)))

现在就完成了。易于逆向代码,具有不太容易看到的模式和数十亿的范围。

(免责声明:我相信你的话,你不需要这个来确保安全。它绝对不安全。)

© www.soinside.com 2019 - 2024. All rights reserved.