使用时,只需要跟android端和后端定义好里面的编码表即可。


import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: Base64Custom
 * @Description: base64自定义加密
 * @author: xiaofei
 */
public class Base64Custom {

    /**
     * 编码表
     */
    private static final byte[] STANDARD_ENCODE_TABLE = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    };


    /**
     * 替换16进制的后六位字母
     */
    public static final HashMap<Integer, String> hexMap = new HashMap<>();

    static {
        hexMap.put(10, "A");
        hexMap.put(11, "B");
        hexMap.put(12, "C");
        hexMap.put(13, "D");
        hexMap.put(14, "E");
        hexMap.put(15, "F");
    }


    /**
     * 加密
     */
    public static class Encoder {


        /**
         * 加密
         *
         * @param str 加密字符串
         * @return
         */
        public static String encode(String str) {
            return encode(str.getBytes());
        }

        public static String encode(byte[] b) {
            String strArr[] = new String[b.length];
            for (int i = 0; i < b.length; i++) {
                strArr[i] = decimalToOther(2, String.valueOf((byte) b[i] & 0xff));
            }
            String encodeByte = encode0(strArr);
            return encodeByte;
        }

        /**
         * Base 64 编码规则:
         * --:错误1.将byte数组中的值转为二进制,将所有二进制数的长度相加,看长度是否为8的倍数,如果不足,则在每个数组元素的二进制前面补0,直到长度满足8的倍数
         * 1. 将byte数组的值转为二进制并放入数组,将数组中的每个元素的长度变成8个bit位,(即如果长度是6,则在值前面补两个0),最后按顺序拼接成一个完整的字符串
         * 2.将字符串以6位分组,不足的,要在末尾补0,达到6的倍数(记下补0的次数)
         * 3.将 每个分组的字符串拿出来,转为十进制以这个为下标,去查表,取得所需的对应编码值
         * 4.将值(可以拼接成字符串,也可以byte数组的形式返回)如果第二部在末尾补0了,每补"00",就在值后拼接一个'='
         *
         * @param binaryStrArr
         * @return
         */
        private static String encode0(String[] binaryStrArr) {
            // 标记第二部,以6分组加 0 的次数
            int len = 0;
            String binaryStr = "";
            int strArrLength = getStringArrLength(binaryStrArr);
            // 将二进制的编码,以8位为一组,//不足的前面补0
            for (int i = 0; i < binaryStrArr.length; i++) {
                binaryStrArr[i] = addZeroFirst(binaryStrArr[i], 8);
            }
            binaryStr = getLongStrToStrArr(binaryStrArr);
            // 分成6 位一组的字符串,不足末尾补0
            int mod6 = binaryStr.length() % 6;
            if (mod6 != 0) {
                len = 6 - mod6;
                binaryStr = binaryStr.concat(addZero(len));
            }
            // 按6个长度分组
            String[] splitForNum = splitForLength(binaryStr, 6);
            StringBuffer sbf = new StringBuffer();
            int lastLen = len / 2;
            // 将截取的二进制字符串 转十进制
            for (int i = 0; i < splitForNum.length; i++) {
                int index = Integer.valueOf(otherToDecimal(2, splitForNum[i]));
                sbf.append((char) STANDARD_ENCODE_TABLE[index]);
            }
            // 每加 00;则输出结果 加 =
            for (int i = splitForNum.length; i < splitForNum.length + lastLen; i++) {
                sbf.append('=');
            }
            return sbf.toString();
        }
    }

    /**
     * 解密
     */
    public static class Decoder {
        /**
         * 解密
         *
         * @param str 解密字符串
         * @return
         */
        public static String decodeByte(String str) {
            String longStr = decode0(str);
            // 按8分组
            String[] binaryEightStr = splitForLength(longStr, 8);
            byte[] b = new byte[binaryEightStr.length];
            for (int i = 0; i < binaryEightStr.length; i++) {
                // 去除前面多余的0
                binaryEightStr[i] = removeStartingNumStr(binaryEightStr[i], 0);
                // 转为十进制
                int decimalValue = Integer.valueOf(otherToDecimal(2, binaryEightStr[i]));
                b[i] = (byte) decimalValue;
            }
            return new String(b);
        }

        /**
         * 1. 去除字符串中的"=",并记录下"="出现的次数
         * 2. 去除后的字符串,分成字符串数组,每个值去查 base64标准表,得到对应的下标索引,放入到一个数组中
         * 3. 将数组拼接成一个完整的二进制字符串,并且去除末尾多余的0(通过"="出现的次数*2)
         *
         * @return
         */
        private static String decode0(String str) {
            int indexOf = str.indexOf("=");
            int equalsCount = 0;
            if (indexOf != -1) {
                str = str.substring(0, indexOf);
                equalsCount = str.length() - indexOf;
            }
            byte[] bytes = str.getBytes();
            String[] strArr = new String[bytes.length];
            String[] binaryStrArr = new String[bytes.length];
            for (int i = 0; i < bytes.length; i++) {
                // 返回 -1 的原因,二分查找,要求查找的数组是有序的....
                strArr[i] = String.valueOf(searchIndex(STANDARD_ENCODE_TABLE, bytes[i]));
                String strIndex = decimalToOther(2, strArr[i]);
                binaryStrArr[i] = addZeroFirst(strIndex, 6);
            }
            String longStr = getLongStrToStrArr(binaryStrArr);
            // 去除末尾添加的0
            longStr.substring(0, longStr.length() - (equalsCount << 1));
            return longStr;
        }
    }


    /* ******************************** 公共方法 ******************************** */


    /**
     * 无序数组的查找
     * 如果是有序的,Arrays.binarySearch()二分查找
     *
     * @param b
     * @param key
     * @return 返回该元素在数组中的下标, 如果有数组中要查询的值有多个, 则返回第一次出现的索引 -1:表示数组中不存在该值
     */
    public static int searchIndex(byte[] b, byte key) {
        byte[] b2 = {key};
        String str = new String(b);
        String keyStr = new String(b2);
        if (str.contains(keyStr)) {
            return str.indexOf(keyStr);
        } else {
            return -1;
        }
    }

    /**
     * 返回string 的单个字符的String 数组形式,而不是字符数组形式
     *
     * @param str
     * @return
     */
    public static String[] getStrings(String str) {
        int j = str.length();
        String[] strArr = new String[j];
        for (int i = 0; i < j; i++) {
            strArr[i] = str.substring(i, i + 1);
        }
        return strArr;
    }

    /**
     * 反转
     *
     * @param result
     * @return
     */
    public static String reverse(String result) {
        StringBuffer sbf = new StringBuffer();
        for (int i = 0, j = result.length(); i < j; i++) {
            sbf.append(result.substring(j - i - 1, j - i));
        }
        return sbf.toString();
    }

    /**
     * 返回传入的数量的"0"字符串
     *
     * @param size
     * @return
     */
    public static String addZero(int size) {
        StringBuffer sbf = new StringBuffer();
        for (int i = 0; i < size; i++) {
            sbf.append("0");
        }
        return sbf.toString();
    }

    /**
     * 根据位数自动添加缺少的0,将0补在开头
     * 补全二进制的0
     *
     * @return 返回补全后的字符串
     */
    public static String addZeroFirst(String str, int num) {
        int mod = str.length() % num;
        int len = 0;
        if (mod == 0) {
            return str;
        } else if (mod != 0) {
            len = num - mod;
        }
        StringBuffer sbf = new StringBuffer();
        for (int i = 0; i < len; i++) {
            sbf.append("0");
        }
        return sbf.toString().concat(str);
    }


    /**
     * 根据传入长度截取字符串,返回字符串数组
     * 注意,位数不够的请自行补0
     *
     * @param str
     * @param num
     * @return
     */
    public static String[] splitForLength(String str, int num) {
        String[] strArr = new String[str.length() / num];
        for (int i = 0; i < strArr.length; i++) {
            strArr[i] = str.substring((0 + i) * num, (1 + i) * num);
        }
        return strArr;

    }

    /**
     * 获得string数组的数组各个元素的长度之和
     *
     * @param strArr
     * @return
     */
    public static int getStringArrLength(String[] strArr) {
        int count = 0;
        for (String str : strArr) {
            count += str.length();
        }
        return count;
    }

    /**
     * 获得字符串数组的各个下标拼接的长字符串
     *
     * @param strArr
     * @return
     */
    public static String getLongStrToStrArr(String[] strArr) {
        return getLongStrToIndex(strArr, 0, strArr.length);
    }


    public static String getLongStrToIndex(String[] strArr, int startIndex, int endIndex) {
        String longStr = "";
        for (int i = startIndex; i < endIndex; i++) {
            longStr += strArr[i];
        }
        return longStr;
    }

    /**
     * 去除以特定数字开头的子字符串,直到后面跟着的是其他子字符串,
     * 返回一个去除后的新字符串
     *
     * @param str
     * @param num 单个数字,范围:0-9
     */
    public static String removeStartingNumStr(String str, int num) {
        return removeStartingStr(str, String.valueOf(num));
    }


    /**
     * 去除以特定字符(注意:只能是单个字符)开头的子字符串,直到后面跟着的是其他子字符串,
     * 返回一个去除后的新字符串
     *
     * @param str
     * @param childrenStr
     * @return
     */
    public static String removeStartingStr(String str, String childrenStr) {
        String[] strings = getStrings(str);
        Integer index = null;
        for (int i = 0; i < strings.length; i++) {
            if (strings[i].equals(childrenStr)) {
                index = i;
            } else {
                break;
            }
        }
        if (null != index) {
            str = str.substring(index + 1);
        }
        return str;
    }


    /**
     * 十进制转其他进制 方法:辗转相除,取余数的反值
     *
     * @param radix  进制类型
     * @param numStr 要转换字符串的string 形式
     * @return
     */
    public static String decimalToOther(int radix, String numStr) {
        if (radix == 0 || radix > 16) {
            return null;
        }
        // 返回为2需要转换
        int regex = judgeInteger(radix, numStr.trim());
        if (regex == 2) {
            String result = reverse(division(numStr.trim(), radix));
            if (radix == 8) {
                result = "0".concat(result);
            } else if (radix == 16) {
                result = "0x".concat(result);
            }
            return result;
        } else {
            // 不处理, 1或0
            return numStr;
        }
    }

    /**
     * 其他进制转十进制
     *
     * @param radix  进制类型:
     * @param numStr 需要转换的数
     * @return 方法:阶乘法
     */
    public static String otherToDecimal(int radix, String numStr) {
        if (radix == 0 || radix > 16) {
            return null;
        }
        numStr = numStr.trim();
        if (radix == 16) {
            // 去除16进制字符的标记0x,并将字母转为大写
            numStr = numStr.replaceFirst("0x", "").toUpperCase();
        } else if (radix == 8) {
            // 去除8进制字符标记 : 第一位是0
            if (numStr.indexOf(0) == 0) {
                numStr = numStr.substring(1);
            }
        }
        return factorial(numStr, radix);
    }


    /**
     * 辗转除radix法
     *
     * @param numStr
     * @return
     */
    public static String division(String numStr, int radix) {
        BigInteger bigStr = new BigInteger(numStr);
        BigInteger bigDix = new BigInteger(String.valueOf(radix));
        StringBuffer sbf = new StringBuffer();
        while (bigStr.compareTo(bigDix) >= 0) {
            // 商是0,余数是1
            BigInteger[] result = bigStr.divideAndRemainder(bigDix);
            BigInteger temp = result[0];
            // 余数不会大于除数,所以可以转为int类型
            int temp2 = Integer.valueOf(result[1].toString());
            // 如果16进制则转为字母
            if (radix == 16 && hexMap.containsKey(temp2)) {
                sbf.append(hexMap.get(temp2));
            } else {
                sbf.append(temp2);
            }
            bigStr = temp;
        }
        sbf.append(bigStr.toString());
        return sbf.toString();
    }

    /**
     * 按位取值 乘 进制的次方,相加
     *
     * @param numStr
     * @param radix
     * @return
     */
    public static String factorial(String numStr, int radix) {
        BigInteger sum = new BigInteger("0");
        BigInteger bitValue = new BigInteger("0");
        // 从最高位开始取,取值*进制^位数-1
        for (int i = 0, numLen = numStr.length(); i < numLen; i++) {
            String bitString = numStr.substring(i, i + 1);
            if (radix == 16 && hexMap.containsValue(bitString)) {
                for (Map.Entry<Integer, String> entry : hexMap.entrySet()) {
                    if (entry.getValue().equals(bitString)) {
                        bitValue = new BigInteger(String.valueOf(entry.getKey()));
                    }
                }
            } else {
                bitValue = new BigInteger(bitString);
            }
            // int b = radix;
            BigInteger b = new BigInteger(String.valueOf(radix));
            BigInteger bRadix = new BigInteger(String.valueOf(radix));
            for (int k = 1; k < numLen - i - 1; k++) {
                b = b.multiply(bRadix);
            }
            if (i == numLen - 1) {
                // 最后一位的次方结果总是1
                b = new BigInteger("1");
            }
            // sum += bitValue*b;//位置*for循环次方的结果,然后相加这些结果
            sum = sum.add(bitValue.multiply(b));
        }
        return sum.toString();

    }

    /**
     * 判断是否需要进行转换
     *
     * @param numStr 待转换的数字
     * @param radix  进制类型
     * @return 0:代表为0; 1:代表小于要转换的进制位,无需转换
     * 2:需要转换
     */
    public static int judgeInteger(int radix, String numStr) {
        // 判断是否和0相等
        if (String.valueOf(0).equals(numStr)) {
            return 0;
        }
        // 判断数字有无小数点
        if (numStr.contains(".")) {
            // 暂时无处理小数功能
            return 1;
        } else {
            BigDecimal bg = new BigDecimal(numStr);
            int i = bg.compareTo(new BigDecimal(radix));
            if (i == -1) {
                return 1;
            } else {
                return 2;
            }
        }
    }


    /**
     * 测试
     *
     * @param args
     */
    public static void main(String[] args) {
        String encode = Encoder.encode("sss");
        String decode = Decoder.decodeByte("BDUsBJ==");
        System.out.println(encode);
        System.out.println(decode);
    }

}