首先,我这的所谓加密,指的是后端给前端的值和后端接收前端传入的值不相同

我先贴上代码

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"才能登录成功