modulo(mod)的一种简单加密用法
业务场景
将用户id
加密为8位以内的数字码code
,并且可以通过code
还原对应的id
,其中id
为从1开始递增的正整数。
实现思路
我们可以选择取模运算的方式来实现这一功能。
其中,我选择公式code = (id * a + b) mod c
作为我的函数映射,由于code
为8位以内的数字码,所以c
应选择8位以内最大的素数99999989
,a
和b
可以为任意小于c
的素数。
数学证明
\[定理一:不存在id_1, id_2 \in[1, c], id_1 \neq id_2使得code_1 == code_2,其中code_1为id_1的映射结果,code_2为id_2的映射结果。\]由于我们的
c
选择了99999989,因此为保证唯一性,我们的id最大为99999989,以做到{ id }域和{ code }域中的元素一一对应。
证:
我们可以使用反证法。
\[我们假设存在id_1, id_2 \in[1, c], id_1 \neq id_2使得code_1 == code_2,则\]- \[(id_1 \times a + b) \bmod c == (id_2 \times a + b) \bmod c\]
- \[id_1 \times a + b - (id_2 \times a + b) = n \times c,\,n\in N\]
- \[id_1 - id_2 = n \times c \div a\]
- \[由于a和c都是素数,且id_1-id_2 \in N,因此n = m \times a, m \in N,则n \times c \div a = n \times m \times c\]
- \[id_1 - id_2 = n \times c \div a = n \times m \times c,由于n,m \in N且id_1 - id_2 \neq 0,则\left| id_1-id_2 \right| \geq c\]
- \[又因id_1, id_2 \in[1, c],则\left| id_1-id_2 \right| < c\]
5
与6
的结论冲突,因此假设不成立,故定理一成立
证:
- \[由code = (id \times a + b) \bmod c,可得code \in [0, c-1]\]
- \[由定理一,任取id_1, id_2 \in[1, c], id_1 \neq id_2,必有code_1 \neq code_2\]
- \[由 id \in [1, c],则id域的大小为c,由code \in [0, c-1],则code域的大小也为c\]
- 结合
2
和3
,可得定理二成立
实验
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package experiment
import "testing"
const (
a int64 = 9967
b int64 = 9973
c int64 = 99999989
)
func IdHash(id int) int64 {
return (a*int64(id) + b) % c
}
func TestIdHash(t *testing.T) {
codeSet := map[int64]int{}
for id := 1; id < int(c); id++ {
code := idHash(id)
if old_id, ok := codeSet[code]; !ok {
codeSet[code] = id
} else {
t.Fatalf("old_id: %v, new_id: %v", old_id, id)
}
}
}
参考
This post is licensed under CC BY 4.0 by the author.