首先,我这的所谓加密,指的是后端给前端的值和后端接收前端传入的值不相同
我先贴上代码
package util;
/**
* @author Canser
* 镜像加密,只针对数字和大小写字母进行简单的镜像加密
* 数字0对应数字9,小写字母a对应小写字母z,大写字母B对应大写字母Y
*/
public class ImageEncryptionUtil {
/**
* 数字0在ASCII表中对应的值
*/
private static final int MIN_NUMBER_ASCII = 48;
/**
* 数字9在ascii表中对应的值
*/
private static final int MAX_NUMBER_ASCII = 57;
/**
* 大写字母A在ASCII表中对应的值
*/
private static final int MIN_POWER_CASE_ASCII = 65;
/**
* 大写字母Z在ASCII表中对应的值
*/
private static final int MAX_POWER_CASE_ASCII = 90;
/**
* 小写字母a在ASCII表中对应的值
*/
private static final int MIN_LOWER_CASE_ASCII = 97;
/**
* 小写字母z在ASCII表中对应的值
*/
private static final int MAX_LOWER_CASE_ASCII = 122;
/**
* 加密
*
* @param str 需要加密的字符串
* @param overturn 是否翻转字符串
* @return 返回加密后的字符串
*/
public static String encrypt(String str, boolean overturn) {
return disorganize(init(str, overturn));
}
/**
* 加密
* 默认不翻转字符串
*
* @param str 需要加密的字符串
* @return 返回加密后的字符串
*/
public static String encrypt(String str) {
return disorganize(init(str, false));
}
/**
* 解密
*
* @param str 需要解密的字符串
* @return 返回解密后的字符串
*/
public static String decrypt(String str) {
return init(disorganize(str), false);
}
/**
* 解密
*
* @param str 需要解密的字符串
* @param overturn 是否翻转字符串
* @return 返回解密后的字符串
*/
public static String decrypt(String str, boolean overturn) {
return init(disorganize(str), overturn);
}
/**
* 加密主方法
*
* @param str 需要加密的字符串
* @param overturn 是否翻转字符串
* @return 返回加密后的字符串
*/
private static String init(String str, boolean overturn) {
StringBuilder builder = new StringBuilder();
if (overturn) {
for (int i = 0; i < str.length(); i++) {
builder.append(transform(str.charAt(str.length() - i - 1)));
}
} else {
for (int i = 0; i < str.length(); i++) {
builder.append(transform(str.charAt(i)));
}
}
return builder.toString();
}
/**
* 将字符进行转换
*
* @param current 需要转换的字符ASCII码
* @return 返回转换后的字符
*/
private static char transform(int current) {
if (isInRange(MIN_NUMBER_ASCII, MAX_NUMBER_ASCII, current)) {
return (char) (MIN_NUMBER_ASCII + MAX_NUMBER_ASCII - current);
} else if (isInRange(MIN_POWER_CASE_ASCII, MAX_POWER_CASE_ASCII, current)) {
return (char) (MIN_POWER_CASE_ASCII + MAX_POWER_CASE_ASCII - current);
} else if (isInRange(MIN_LOWER_CASE_ASCII, MAX_LOWER_CASE_ASCII, current)) {
return (char) (MIN_LOWER_CASE_ASCII + MAX_LOWER_CASE_ASCII - current);
}
return (char) current;
}
/**
* 判断数值是否在指定范围内
*
* @param min 范围最小值
* @param max 范围最大值
* @param current 需要判断的数值
* @return 返回结果
*/
private static boolean isInRange(int min, int max, int current) {
return Math.max(min, current) == Math.min(max, current);
}
/**
* 打乱字符串
*
* @param str 需要打乱的字符串
* @return 返回打乱后的字符串
*/
private static String disorganize(String str) {
StringBuilder builder = new StringBuilder();
// 将循环长度设为字符串长度的一半并向上取整
int max = str.length();
// 设置i的跨度为2
int iDuration = 2;
// 余数,判断字符串长度奇偶
int remainder = max % 2;
// 首次从尾取数的位置由字符串长度的奇偶决定
int oDuration = remainder == 0 ? 1 : 2;
for (int i = 0; i < max; i += iDuration) {
// 从头开始截取奇数位并添加字符
builder.append(str.charAt(i));
// 若字符串长度为奇数位时,当最后一次循环防止越界直接结束
if (remainder == 1 && i == max - 1) {
break;
}
// 从尾开始截取偶数位并添加字符
// 若字符串长度为奇数位,则从倒数第二个开始,若为偶数位,则从倒数第一个开始
builder.append(str.charAt(max - i - oDuration));
}
return builder.toString();
}
}
这个加密,我给他取名叫镜像加密,过程是这样的:
首先,所有的加密算法都是在ASCII码的基础上进行的,因为ASCII码是我们学习计算机技术最开始接触到的编码(准确来讲应该是二进制才对),所以这次加密我将这个作为标准;
假设我需要加密字符串"123abc",首先对字符'1'进行加密,我将字符'1'看作为数字,数字的范围为0-9,数字1为从头开始的第二位数字,所以我取从尾开始的第二位数字8作为数字的加密字符;
同理,我将字符'a'看作为小写字母,小写字母的范围为a-z,字母a为从头开始的第一位字母,所以我取从尾开始的第一位字母z作为字母a的加密字符。
结束之后,字符串"123abc"经过加密后应该为"876zyx",但这个字符串从结构上和加密前的字符串基本一致,所以我对其进行的打乱操作(其实打的并不是很乱...):
首先从加密后的字符串取从头开始的第一位字符,接着取从尾开始的第二位字符,然后取从头开始的第三位字符,接着取从尾开始的第三位字符...换言之,即为从头取奇数位,再从尾取偶数位
这样一来,字符串"123abc"经过一系列操作后就变成了"8x6zy7",这样虽然看上去依旧很简单,但当需要加密的字符串为随机产生的字符串时,就不那么明显了(产生随机字符串的代码我之前也有发过,直达连接:根据不同的需求(数字、小写字母、大写字母组合,新增汉字,特殊字符、数字、大小写字母组合)产生指定位数的随机数_hjh70983704的博客),譬如字符串"68TG151I2C16"经过加密后为”33GX8R847T81“
ps:从实用和可读性角度出发,这个加密只涉及了数字0-9、小写字母a-z及大写字母A-Z的加密
方法调用:
int strLength = 12;
int strType = RandomStringUtil.FIGURE_POWER_CASE;
// 原字符串
String str = RandomStringUtil.createRandomString(strLength, strType);
System.out.println(str);
// 加密后的字符串
str = ImageEncryptionUtil.encrypt(str);
System.out.println(str);
// 解密后的字符串
str = ImageEncryptionUtil.decrypt(str);
System.out.println(str);
本方法里还包含了加密前是否将字符串反转,譬如字符串"123abc"若设置了反转,则将对字符串"cba321"进行加密,若在加密中设置了反转,则在解密中也必须设置反转:
int strLength = 12;
int strType = RandomStringUtil.FIGURE_POWER_CASE;
// 原字符串
String str = RandomStringUtil.createRandomString(strLength, strType);
System.out.println(str);
// 加密后的字符串
str = ImageEncryptionUtil.encrypt(str, true);
System.out.println(str);
// 解密后的字符串
str = ImageEncryptionUtil.decrypt(str, true);
System.out.println(str);
这个加密可用在登录密码加密,譬如:数据库存入的密码为"123abc",但是在前端需要输入"8x6zy7"才能登录成功