base64加密原理代码实现

/*Conversion.java*/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
 * @创建者 CSDN_LQR
 * @创建时间 2016-5-19 下午9:06:43
 * @描述 base64加密原理代码实现
 */
public class Conversion {
    private static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6",
            "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    public static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n = 256 + n;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    //######################### 以下是base64加密原理实现 begin ##############################

    public static String byteArrayToHexString(byte[] b) {
        String result = "";
        for (int i = 0; i < b.length; ++i)
            result += byteToHexString(b[i]);
        return result;
    }

    // 创建base64对应的map
    public static Map base64Map = new HashMap();
    static {
        // 前26个
        for (int i = 0; i < 26; i++) {
            base64Map.put(i,
                    String.valueOf(Character.valueOf((char) ('A' + i))));
        }

        // 再26个
        int j = 0;
        for (int i = 0; i < 26; i++) {
            base64Map.put(26 + i,
                    String.valueOf(Character.valueOf((char) ('a' + j++))));
        }

        // 再10个数字
        j = 0;
        for (int i = 0; i < 10; i++) {
            base64Map.put(52 + i,
                    String.valueOf(Character.valueOf((char) ('0' + j++))));
        }

        // 最后添加2个符号
        base64Map.put(62, "+");
        base64Map.put(63, "/");

    }

    /**
     * 将byte转成bit[]
     * 
     * @param b
     * @return
     */
    public static byte[] byteToBitArr(byte b) {

        byte[] bitArr = new byte[8];
        for (int i = 0; i < 8; i++) {
            bitArr[i] = (byte) ((b >> 7 - i) & 0x1);
        }
        return bitArr;
    }

    /**
     * 将byte[]转成bit[]
     * 
     * @param bArr
     * @return
     */
    public static byte[] byteArrToBitArr(byte[] bArr) {

        ArrayList<byte[]> list = new ArrayList<byte[]>();
        for (int i = 0; i < bArr.length; i++) {
            byte[] bitArr = byteToBitArr(bArr[i]);
            list.add(bitArr);
        }

        byte[] bitAtt = new byte[list.size() * 8];
        for (int i = 0; i < list.size(); i++) {
            // 得到要填充的起始位置
            int begin = 8 * i;
            byte[] bs = list.get(i);
            for (int j = 0; j < bs.length; j++) {
                bitAtt[begin++] = bs[j];
            }
        }

        return bitAtt;
    }

    /**
     * 把二进制字节数组转按Base64进行编码
     * 
     * @param b
     *            二进制字节数组
     * @return 按Base64编码的字符串
     */
    public static String byteArrayToBase64String(byte[] b) {
        // ===================1、计算有效的base64字符的个数 =====================
        // 得到二进制数的全部位数
        int len = b.length * 8;

        // 记录原先位数除6得到的整数,如果有余数,说明长度要补位,base64正确转换次数要加1
        int changeCount;
        if (len % 6 != 0) {
            changeCount = len / 6 + 1;
        } else {
            changeCount = len / 6;
        }

        // System.out
        // .println("1、计算最后有效的base64字符的个数为:changeCount = " + changeCount);

        // ===================2、计算当前需要补充的bit位的个数,及位数总长 =====================
        // 得到要被6整除的需要补多少位
        int temp = len;
        while (temp % 6 != 0) {
            temp += 8;
        }

        // System.out.println("2、计算当前需要补充的bit位的个数为:" + (temp - len)
        // + ",当前总的位数是:temp = " + temp);

        // ===================3、计算最终经base64编码后会得到的字符数 =====================
        // 记录得到补位后能整除6的数
        int nowCount = temp / 6;

        // System.out.println("3,计算补位后,最终经base64编码后会得到的字符数为:nowCount = "
        // + nowCount);

        // ===================4、创建对应补位后长度的字节数组,补充最后补位字节为0 =====================
        // 创建新的二进制数组(已经补位)
        byte[] b1 = new byte[temp / 8];

        // System.out.println("4、因为总的bit有" + temp + "位,所以创建一个存放" + temp / 8
        // + "个字节的byte[],然后对该byte[]进行原数据填充及补位0数据填充");

        // 填充该二进制数组数据
        for (int i = 0; i < b.length; i++) {
            b1[i] = b[i];
        }

        for (int i = b.length; i < temp / 8; i++) {
            b1[i] = 0;
        }

        // System.out.println();
        // System.out.println("\t#####原先字节数组的数据#####");
        // System.out.print("\t");
        for (byte b2 : b) {
            // System.out.print(b2 + " ");
        }
        // System.out.println("对应的bit为:");
        // System.out.print("\t");
        for (int i = 0; i < byteArrToBitArr(b).length; i++) {
            byte b2 = byteArrToBitArr(b)[i];
            // System.out.print(b2 + "");
            if ((i + 1) % 8 == 0) {
                // System.out.print(" ");
            }
        }
        // System.out.println("\n");
        // System.out.println("\t#####新的字节数组的数据#####");
        // System.out.print("\t");
        for (byte b2 : b1) {
            // System.out.print(b2 + " ");
        }
        // System.out.println("对应的bit为:");
        // System.out.print("\t");
        for (int i = 0; i < byteArrToBitArr(b1).length; i++) {
            byte b2 = byteArrToBitArr(b1)[i];
            // System.out.print(b2 + "");
            if ((i + 1) % 8 == 0) {
                // System.out.print(" ");
            }
        }

        // System.out.println("\n");

        // ===================5、根据所有的bit,每6位计算值后,对表查值(base64核心),最后拼接成加密后的字符串=====================
        byte[] byteArrToBitArr = byteArrToBitArr(b1);
        String base64Str = "";

        // System.out.println("5、循环" + nowCount + "次,每次计算6个bit的总值");
        for (int i = 0; i < nowCount; i++) {
            int begin = 6 * i;
            // System.out.println("\t>>循环第" + i + "次,起始位置是:" + begin);
            int sixCount = 0;
            if (i < changeCount) {
                for (int j = 0; j < 6; j++) {
                    sixCount += (byteArrToBitArr[begin++]) << (5 - j);
                }
                base64Str += base64Map.get(sixCount);
                // System.out.println("\t得到当前6个bit的总值(sixCount)是:" + sixCount
                // + ",对表查值结果为:" + base64Map.get(sixCount));
            } else {
                base64Str += "=";
                // System.out.println("\t这次是补位部分,结果为:=");
            }

        }

        // System.out.println();
        // System.out.println("得到的总的base64加密的字符串为:base64Str为: \"" + base64Str
        // + "\"");

        return base64Str;
    }

    /**
     * 把Base64字符转换为字节数组
     * 
     * @param s
     *            按照Base64编码的字符
     * @return 二进制字节数组
     */
    public static byte[] base64StringToByteArray(String s) {

        // 记录=号的个数
        int equalCount = 0;

        // 存放bit[]的集合
        ArrayList<byte[]> list = new ArrayList<byte[]>();

        // ===================1、对传入字条串进行字符拆分 =====================
        // 把字符串切割成多个单个的Char
        char[] charArray = s.toCharArray();

        // System.out.print("1、对" + s + "进行字符拆分,结果为:");
        for (int i = 0; i < charArray.length; i++) {
            // System.out.print(charArray[i] + " ");
        }

        // ===================2、对每个字符进行对表查键 =====================
        // System.out.println();
        // System.out.println("2、对每个字符进行对表查键");
        // 遍历每个char
        for (int i = 0; i < charArray.length; i++) {
            // 如果是=就equalCount加1
            if (charArray[i] == '=') {
                equalCount++;
                // System.out.println("\t>>当前字符是=号,=号计数器(equalCount)加1");
                // 如果是别的char
            } else {
                // 则遍历map,得到char对应map中的key
                for (Entry entry : base64Map.entrySet()) {
                    if (entry.getValue().equals(String.valueOf(charArray[i]))) {
                        int key = entry.getKey();
                        // 把key转成byte
                        byte bK = (byte) key;
                        // 再把byte转成bit[],并添加到bit[]集合中
                        list.add(byteToBitArr(bK));
                        // System.out.println("\t>>当前字符是" + charArray[i]
                        // + ",对表查键结果为:" + key);
                    }
                }
            }
        }
        // System.out.println();

        // ===================3、根据字符数组长度 * 6,计算出总的bit位数 =====================
        // 计算所有bit的个数
        int allCount = charArray.length * 6;
        // 创建一个存放bit的数组
        byte[] bArr = new byte[allCount];
        // System.out.println("3、根据字符数组长度 * 6,计算出总的bit位数为:" + allCount
        // + ",创建对应长度的bit数组bArr");

        // ===============4、把有效的字符转换成bit数组,保存到bit数组bArr中 =================
        // 把list中的bit[]遍历后,取后6位保存到bArr中
        // System.out.println("4、把上面对表查键得到的" + list.size() + "个键转换成" +
        // list.size()
        // + "  * 6位的bit,依次填充到bit数组中");

        for (int i = 0; i < list.size(); i++) {
            byte[] cs = list.get(i);
            int begin = 6 * i;
            for (int j = 0; j < cs.length - 2; j++) {
                bArr[begin++] = cs[2 + j];
            }
        }

        // ===============5、根据=号的个数,用0填充完bit数组bArr =================
        // 再根据=号的个数,把后面的0填充上
        for (int i = 0; i < equalCount * 6; i++) {
            bArr[allCount - 1 - i] = 0;
        }
        // System.out.println("5,根据=号的个数,用" + (equalCount * 6) + "个0填充完bit数组");

        // System.out.println();
        // System.out.println("\t#####填充完得到的bit数组是:#####");
        // System.out.print("\t");
        for (int i = 0; i < bArr.length; i++) {
            // System.out.print(bArr[i]);
            if ((i + 1) % 8 == 0) {
                // System.out.print(" ");
            }
        }

        // ============6、根据=号的个数,计算未加密原字节数组的bit位数,并创建bit数组tempArr ==============
        // 未经base64编码前的字节个数
        int byteCount = (bArr.length - equalCount * 8) / 8;
        byte[] tempArr = new byte[bArr.length - equalCount * 8];

        // System.out.println("\n");
        // System.out.println("6、因为=号有" + equalCount + "个,说明之前多补充了" + equalCount
        // + "个字节(" + equalCount * 8 + "个bit位)。计算出原先只有"
        // + (bArr.length - equalCount * 8) + "位,即" + byteCount
        // + "个字节,故创建一个长度为" + (bArr.length - equalCount * 8)
        // + "的bit数组tempArr");

        // ============7、用bit数组bArr中前面所有有效的bit填充bit数组tempArr ==============
        for (int i = 0; i < tempArr.length; i++) {
            tempArr[i] = bArr[i];
        }

        // System.out.println("7、将bit数组bArr的前" + (bArr.length - equalCount * 8)
        // + "位存入到bit数组finalArr中");

        // System.out.println();

        // System.out.println("\t#####填充完得到的最终bit数组finalArr是:#####");
        // System.out.print("\t");
        for (int i = 0; i < tempArr.length; i++) {
            // System.out.print(tempArr[i]);
            if ((i + 1) % 8 == 0) {
                // System.out.print(" ");
            }
        }
        // System.out.println();

        // ============8、对bit数组tempArr进行每8位计算总值后保存到字节数组finalArr中 ==============
        byte[] finalArr = new byte[byteCount];
        // System.out.println();
        // System.out.println("8、循环" + byteCount + "次,每次计算8个bit的总值");
        for (int i = 0; i < byteCount; i++) {
            int begin = 8 * i;
            // System.out.print("\t>>循环第" + i + "次,起始位置是:" + begin);
            byte eightCount = 0;
            for (int j = 0; j < 8; j++) {
                eightCount += (tempArr[begin++]) << (7 - j);
            }
            // System.out.println(",结果为:" + eightCount);
            finalArr[i] = eightCount;
        }

        return finalArr;
    }

    public static void main(String[] args) {
        // base64加密解密演示
        String str = "X";
        System.out
                .println("######################################进行Base64加密######################################");
        String base64String = byteArrayToBase64String(str.getBytes());

        for (int i = 0; i < 4; i++) {
            System.out.println();
        }
        System.out
                .println("######################################进行Base64解密######################################");
        base64StringToByteArray(base64String);
    }
}

你可能感兴趣的:(JavaEE)