Base64加解密

概述:base64加解密

對英文字符的base64加解密,非英文字符由於編碼問題,本文未支持。

base64的加密過程規則是這樣的:
    1.將字符串中的每一個字符,轉換成其對應的ASCII碼值的二進制表示,每個字符的二進制長度爲8位,得到二進制字符串;
    2.若得到的二進制字符串長度不是6的整數倍,末尾添加0,使其爲6的倍數;
    3.在步驟2得到的字符串中,每6位截取,其對應的數值爲0-63,從base64轉換表查找對應的字符([A-Za-z0-9/+]),重新拼接成字符串;
    4.若步驟三得到的字符串長度不是4的倍數,則在末尾添加等號("="),使其爲4的倍數。1個字符加密後是2個字符,2個字符加密後是3個字符,3個字符加密後是4個字符……由於8和6的最小公倍數是24,所以等號個數只有0、1、2個。

代碼如下:

import java.util.HashMap;
import java.util.Map;

public class Base64 {
    private static char[] base64 = {'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', '+', '/'};
    private static Map<Character, Integer> deBase64 = new HashMap<Character, Integer>(
            base64.length);

    static {
        for (int index = 0; index < base64.length; index++) {
            deBase64.put(base64[index], index);
        }
    }

    /**
     * base64加密
     * 
     * @param input
     *            加密前字符串
     * @return 加密後字符串
     */
    public static String encrypt(String input) {
        StringBuilder output = new StringBuilder();
        StringBuilder binString = new StringBuilder();
        for (int index = 0; index < input.length(); index++) {
            binString.append(getFixLenBin(input.charAt(index), 8));
        }
        // 二進制字符串長度不夠時在末尾補0
        while (binString.length() % 6 != 0) {
            binString.append("0");
        }
        for (int index = 0; index < binString.length(); index += 6) {
            output.append(
                    base64[bin2Num(binString.substring(index, index + 6))]);
        }
        while (output.length() % 4 != 0) {
            output.append("=");
        }
        return output.toString();
    }

    /**
     * 得到固定長度的二進制串
     * 
     * @param num
     *            十進制數
     * @param len
     *            長度
     * @return 固定長度的二進制串
     */
    private static String getFixLenBin(int num, int len) {
        String bin = num2bin(num);
        while (bin.length() < len) {
            bin = "0".concat(bin);
        }
        return bin;
    }

    /**
     * 十進制轉二進制
     * 
     * @param num
     *            十進制數
     * @return 二進制字符串
     */
    private static String num2bin(int num) {
        StringBuilder sb = new StringBuilder();
        String bin = getBin(num / 2, sb, num % 2);
        bin = bin.replaceAll("^[0]*", "");
        return bin.length() != 0 ? bin : "0";
    }

    /**
     * 用於得到初步的二進制字符串的遞歸函數
     * 
     * @param num
     *            十進制數/2
     * @param sb
     *            二進制字符串
     * @param mod
     *            十進制數%2
     * @return 初步的二進制字符串
     */
    private static String getBin(int num, StringBuilder sb, int mod) {
        sb.append(mod);
        return num / 2 == 0
                ? sb.append(num % 2).reverse().toString()
                : getBin(num / 2, sb, num % 2);
    }

    /**
     * 二進制轉十進制
     * 
     * @param bin
     *            二進制字符串
     * @return 十進制數
     */
    private static int bin2Num(String bin) {
        int num = 0;
        int len = bin.length();
        for (int index = 0; index < len; index++) {
            if (bin.charAt(len - 1 - index) == '1') {
                num += Math.pow(2, index);
            }
        }
        return num;
    }

    /**
     * base64解密
     * 
     * @param input
     *            解密前字符串
     * @return 解密後字符串
     */
    public static String decrypt(String input) {
        input = input.replaceAll("[^A-Za-z0-9+/=]*", "");
        // 密文長度是4的倍數
        if (input.length() % 4 != 0) {
            return "密文格式錯誤:長度錯誤";
        }
        // 等號個數只能爲0、1、2個,對應的餘數爲0、3、2,所以餘數爲1是有三個等號,不符合base64的規範
        input = input.replaceAll("=", "");
        if (input.length() % 4 == 1) {
            return "密文格式錯誤:末尾等號錯誤";
        }

        StringBuilder binString = new StringBuilder();
        for (int index = 0; index < input.length(); index++) {
            binString.append(getFixLenBin(
                    deBase64.get(input.charAt(index)).intValue(), 6));;
        }
        StringBuilder output = new StringBuilder();
        int len = binString.length();
        for (int index = 0; index < len; index += 8) {
            // 丟棄加密時末尾補的0
            if (index + 8 > len) {
                break;
            }
            output.append(
                    (char) bin2Num(binString.substring(index, index + 8)));
        }
        return output.toString();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章