数字转换任意进制 纯数字加密

需求

项目中需要 加密纯数字 (加密id 防止用户随便改比如 URL?id=1 修改成 URL?id=2

就想用 进制转换 10进制转换为 自定义的进制 16进制 32进制 太常见了

网上给的代码都是用 Integer.valueOf(String s, int radix); 实现

满足不了自定义进制密文的要求

只好自己实现一个咯~

网上一搜应该一堆 但我愣是没有搜到… 感叹中文互联网的内容越来越差很多东西都搜不到了

基本实现

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private static String enstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";//62进制
private static char[] array = enstr.toCharArray();
private static int len = array.length;

public static void main(String[] args) {
for(int i = 9999999;i< 999999999;i++) {
String enc = encode(i);
if(decode(enc)!=i) {
System.out.println("error");
}else {
System.out.println(i + " "+ enc);
}
}
}

public static String encode(int id) {
int x = id / len;
int y = id % len;
return encode(x, y, "");
}

public static String encode(int x, int y, String sb) {
sb = array[y] + sb;
if (x == 0)
return sb;
return encode(x / len, x % len, sb);
}

public static int decode(String code) {
int r = 0;
for (int i = 0; i < code.length(); i++) {
int fd = code.length() - i - 1;
int x = enstr.indexOf(code.charAt(i));
if (fd != 0) {
int cur = x * len;
for (int j = 1; j < fd; j++)
cur *= len;
r += cur;
} else
r += x;
} // for
return r;
}

实际使用

上面的代码会有个问题 比如每次生成 id = 61 固定 会生成 id = z

为了没有规律加入随机数放到生成的字符中

为了防止被用户修改 还要再加入校验码

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private static String baseSecret = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static int len = baseSecret.length();
private static Random ran = new Random();

public static String encode(int id) {
int x = id / len;
int y = id % len;
int r = ran.nextInt(baseSecret.length());
String secret = getOffsetSecret(r);
String code = encode(x, y, "", secret) + baseSecret.charAt(r);
return code + getCheckCode(code);
}

public static String encode(int x, int y, String sb, String secret) {
sb = secret.charAt(y) + sb;
if (x == 0)
return sb;
return encode(x / len, x % len, sb, secret);
}// mtehod

public static int decode(String code) throws Exception {
String checkStr = code.substring(code.length() - 1);
code = code.substring(0, code.length() - 1);
if(!checkStr.equals(getCheckCode(code)))
throw new Exception("校验无法通过!");

String offsetStr = code.substring(code.length() - 1);
int offset = baseSecret.indexOf(offsetStr);
String secret = getOffsetSecret(offset);

code = code.substring(0, code.length() - 1);
int r = 0;
for (int i = 0; i < code.length(); i++) {
int fd = code.length() - i - 1;
int x = secret.indexOf(code.charAt(i));
if (fd != 0) {
int cur = x * len;
for (int j = 1; j < fd; j++)
cur *= len;
r += cur;
} else
r += x;
} // for
return r;
}// method

//加入随机数
public static String getOffsetSecret(int offset) {
StringBuffer sb = new StringBuffer();
for (int i = 1; i <= baseSecret.length(); i++) {
int o = (i + offset) % baseSecret.length();
sb.append(baseSecret.charAt(o));
}
return sb.toString();
}// method

//加入校验码
public static String getCheckCode(String str) {
str = str.substring(0, str.length() - 1);
int code = 0;
for (int i = 0; i < str.length(); i++)
code += baseSecret.indexOf(str.charAt(i));
return baseSecret.charAt(code % baseSecret.length()) + "";
}//

拓展

为了长度大致相同 可以给一个基础的数值 比如加密前先 +100000 之后再加密

玩出花来

baseSecret 可以随便换比如 “0aQ1bR2cS3dT4eU5fV6gW7hX8iY9jZAkBlCmDnEoFpGqHrIsJtKuLvMwNxOyPz” 这种没规律的

或者

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
26
27
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; i++) {
int x = 123456;
System.out.println(x + " " + encode(x));
}
}

private static String baseSecret = "ilI";
/*
123456 illiIIllIIlil
123456 lIIliiIIiiIli
123456 IiiIlliilliII
*/

private static String baseSecret = "-=*";
/*
123456 *--*==--==-**
123456 =**=--**--*=-
123456 -==-**==**=-=
*/
private static String baseSecret = "oO0";
/*
123456 0oo0OOooOOo00
123456 O00Ooo00oo0Oo
123456 oOOo00OO00OoO
*/

源码