【JAVA - 基礎】之數據加密和解密

一、Base64工具類(可逆):

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

/**
 * Base64加解密算法
 * </p>
 * Base64加密算法:<br/>
 * 一、獲取字符串中每一個字符的ASCII碼;<br/>
 * 二、按照每3個8bit的字符爲一組來分組,即每組24bit;<br/>
 * 三、將這24bit劃分紅4個6bit的4個單位,每一個單位前面添加2個0,獲得4個8bit的單位;<br/>
 * 四、將每一個8bit的單位轉換成十進制數字,對照Base64編碼表找到對應的字符進行拼接,獲得最終的加密後的字符串。<br/>
 * </p>
 * Base64解密算法:<br/>
 * 一、讀入4個字符,對照Base64編碼表找到字符對應的索引,生成4個6爲的值;<br/>
 * 二、將這4個6爲的值拼接起來,造成一個24爲的值;<br/>
 * 三、將這個24位的值按照8位一組截斷成3個8位的值;<br/>
 * 四、對照ASCII表找到這三個8位的值對應的字符,即解碼後的字符。<br/>
 * </p>
 * 注意事項:<br/>
 * 一、被編碼的字符必須是8bit的,即必須在ASCII碼範圍內,中文不行;<br/>
 * 二、若是被編碼的字符長度不是3的倍數,則在最後添加1或2個0,對應的輸出字符爲「=」;
 * 三、給定一個字符串,用Base64方法對其進行加密後解密,獲得的結果就不是開始時候的字符串了。<br/>
 */
public class BASE64Util {
    private static final Map<Integer, Character> base64CharMap = new HashMap<>();
    private static final String base64CharString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    private static BASE64Util instance;

    private BASE64Util() {
        for (int i = 0; i < base64CharString.length(); i++) {
            char c = base64CharString.charAt(i);
            base64CharMap.put(new Integer(i), new Character(c));
        }
    }

    public static BASE64Util getInstance() {
        if (instance == null) {
            synchronized (BASE64Util.class) {
                if (instance == null) {
                    instance = new BASE64Util();
                }
            }
        }
        return instance;
    }

    /**
     * This method is used to encode a normal string to base64 string @param
     * origin The String to be encoded @return The String after encoded.
     */
    public String encode(String origin) {
        if (origin == null) {
            return null;
        }
        if (origin.length() == 0) {
            return "";
        }
        int length = origin.length();
        String binaryString = "";
        // to binary String
        for (int i = 0; i < length; i++) {
            int ascii = origin.charAt(i);
            String binaryCharString = Integer.toBinaryString(ascii);
            while (binaryCharString.length() < 8) {
                binaryCharString = "0" + binaryCharString;
            }
            binaryString += binaryCharString;
        }

        // to base64 index
        int beginIndex = 0;
        int endIndex = beginIndex + 6;
        String base64BinaryString = "";
        String charString = "";
        while ((base64BinaryString = binaryString.substring(beginIndex, endIndex)).length() > 0) {
            // if length is less than 6, add "0".
            while (base64BinaryString.length() < 6) {
                base64BinaryString += "0";
            }
            int index = Integer.parseInt(base64BinaryString, 2);
            char base64Char = base64CharMap.get(index);
            charString = charString + base64Char;
            beginIndex += 6;
            endIndex += 6;
            if (endIndex >= binaryString.length()) {
                endIndex = binaryString.length();
            }
            if (endIndex < beginIndex) {
                break;
            }
        }
        if (length % 3 == 2) {
            charString += "=";
        }
        if (length % 3 == 1) {
            charString += "==";
        }
        return charString;
    }

    public String decode(String encodedString) {
        if (encodedString == null) {
            return null;
        }
        if (encodedString.length() == 0) {
            return "";
        }
        // get origin base64 String
        String origin = encodedString.substring(0, encodedString.indexOf("="));
        String equals = encodedString.substring(encodedString.indexOf("="));

        String binaryString = "";
        // convert base64 string to binary string
        for (int i = 0; i < origin.length(); i++) {
            char c = origin.charAt(i);
            int ascii = base64CharString.indexOf(c);
            String binaryCharString = Integer.toBinaryString(ascii);
            while (binaryCharString.length() < 6) {
                binaryCharString = "0" + binaryCharString;
            }
            binaryString += binaryCharString;
        }
        // the encoded string has 1 "=", means that the binary string has append
        // 2 "0"
        if (equals.length() == 1) {
            binaryString = binaryString.substring(0, binaryString.length() - 2);
        }
        // the encoded string has 2 "=", means that the binary string has append
        // 4 "0"
        if (equals.length() == 2) {
            binaryString = binaryString.substring(0, binaryString.length() - 4);
        }

        // convert to String
        String charString = "";
        String resultString = "";
        int beginIndex = 0;
        int endIndex = beginIndex + 8;
        while ((charString = binaryString.substring(beginIndex, endIndex)).length() == 8) {
            int ascii = Integer.parseInt(charString, 2);
            resultString += (char) ascii;
            beginIndex += 8;
            endIndex += 8;
            if (endIndex > binaryString.length()) {
                break;
            }
        }
        return resultString;
    }
}

 

二、MD5工具類(不可逆):

import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class MD5Util {
    public static final String MD5 = "MD5";
    public static final String HmacMD5 = "HmacMD5";
    public static final String charset = null; // 編碼格式;默認null爲GBK

    private static MD5Util instance;

    private MD5Util() {
    }

    // 單例
    public static MD5Util getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new MD5Util();
                }
            }
        }
        return instance;
    }

    /**
     * 使用 MD5 方法加密(無密碼)
     */
    public String encode(String res) {
        try {
            MessageDigest md = MessageDigest.getInstance(MD5);
            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用 MD5 方法加密(能夠設密碼)
     */
    public String encode(String res, String key) {
        try {
            SecretKey sk = null;
            if (key == null) {
                KeyGenerator kg = KeyGenerator.getInstance(HmacMD5);
                sk = kg.generateKey();
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                sk = new SecretKeySpec(keyBytes, HmacMD5);
            }
            Mac mac = Mac.getInstance(HmacMD5);
            mac.init(sk);
            byte[] result = mac.doFinal(res.getBytes());
            return BASE64Util.getInstance().encode(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

 

三、SHA1工具類(不可逆):

import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 使用 SHA1 方法進行加密<br/>
 * SHA1方法加密是不可逆的,不能解密,要想解密就必須使用暴力解密<br/>
 * <p/>
 * 方法中的 res 參數:原始的數據<br/>
 * 方法中的 key 參數:密鑰,能夠隨便寫<br/>
 */
public class SHA1Util {
    public static final String SHA1 = "SHA1";
    public static final String HmacSHA1 = "HmacSHA1";
    public static final String charset = null; // 編碼格式;默認null爲GBK

    private static SHA1Util instance;

    private SHA1Util() {
    }

    // 單例
    public static SHA1Util getInstance() {
        if (instance == null) {
            synchronized (SHA1Util.class) {
                if (instance == null) {
                    instance = new SHA1Util();
                }
            }
        }
        return instance;
    }

    /**
     * 使用 SHA1 方法加密(無密碼)
     */
    public String encode(String res) {
        try {
            MessageDigest md = MessageDigest.getInstance(SHA1);
            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用 SHA1 方法加密(能夠設密碼)
     */
    public String encode(String res, String key) {
        try {
            SecretKey sk = null;
            if (key == null) {
                KeyGenerator kg = KeyGenerator.getInstance(HmacSHA1);
                sk = kg.generateKey();
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                sk = new SecretKeySpec(keyBytes, HmacSHA1);
            }
            Mac mac = Mac.getInstance(HmacSHA1);
            mac.init(sk);
            byte[] result = mac.doFinal(res.getBytes());
            return BASE64Util.getInstance().encode(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

 

四、AES工具類(可逆):

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
    public static final String AES = "AES";
    public static final String charset = null; // 編碼格式;默認null爲GBK
    public static final int keysizeAES = 128;

    private static AESUtil instance;

    private AESUtil() {
    }

    // 單例
    public static AESUtil getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new AESUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 使用 AES 進行加密
     */
    public String encode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, true);
    }

    /**
     * 使用 AES 進行解密
     */
    public String decode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, false);
    }

    // 使用KeyGenerator雙向加密,DES/AES,注意這裏轉化爲字符串的時候是將2進制轉爲16進制格式的字符串,不是直接轉,由於會出錯
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 將二進制轉換成16進制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 將16進制轉換爲二進制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}

 

五、DES工具類(可逆):

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class DESUtil {
    public static final String DES = "DES";
    public static final String charset = null; // 編碼格式;默認null爲GBK
    public static final int keysizeDES = 0;

    private static DESUtil instance;

    private DESUtil() {
    }

    // 單例
    public static DESUtil getInstance() {
        if (instance == null) {
            synchronized (MD5Util.class) {
                if (instance == null) {
                    instance = new DESUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 使用 DES 進行加密
     */
    public String encode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, true);
    }

    /**
     * 使用 DES 進行解密
     */
    public String decode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, false);
    }

    // 使用KeyGenerator雙向加密,DES/AES,注意這裏轉化爲字符串的時候是將2進制轉爲16進制格式的字符串,不是直接轉,由於會出錯
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 將二進制轉換成16進制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 將16進制轉換爲二進制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}

 

六、XOR(異或加密)工具類(可逆):

public class XORUtil {
    private static XORUtil instance;

    private XORUtil() {
    }

    // 單例
    public static XORUtil getInstance() {
        if (instance == null) {
            synchronized (XORUtil.class) {
                if (instance == null) {
                    instance = new XORUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 對一個數字進行異或加解密
     */
    public int code(int res, String key) {
        return res ^ key.hashCode();
    }

    /**
     * 異或加密
     */
    public String encode(String res, String key) {
        byte[] bs = res.getBytes();
        for (int i = 0; i < bs.length; i++) {
            bs[i] = (byte) ((bs[i]) ^ key.hashCode());
        }
        return parseByte2HexStr(bs);
    }

    /**
     * 異或解密
     */
    public String decode(String res, String key) {
        byte[] bs = parseHexStr2Byte(res);
        for (int i = 0; i < bs.length; i++) {
            bs[i] = (byte) ((bs[i]) ^ key.hashCode());
        }
        return new String(bs);
    }

    // 將二進制轉換成16進制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 將16進制轉換爲二進制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}

 

七、測試:

public class Test {
    public static void main(String[] args) {
        int xorNum = 12345;
        String res = "I am the text to be encoded and decoded.";
        String key = "我是密鑰key";
        System.out.println("-------------------------BASE64--------------------------");
        String base64_encodedStr = BASE64Util.getInstance().encode(res);
        System.out.println("加密:" + base64_encodedStr);
        System.out.println("解密:" + BASE64Util.getInstance().decode(base64_encodedStr));
        System.out.println("-------------------------MD5--------------------------");
        String md5_encodedStr = MD5Util.getInstance().encode(res);
        System.out.println("無密碼加密:" + md5_encodedStr);
        System.out.println("有密碼加密:" + MD5Util.getInstance().encode(md5_encodedStr, key));
        System.out.println("-------------------------SHA1--------------------------");
        String sha1_encodedStr = SHA1Util.getInstance().encode(res);
        System.out.println("無密碼加密:" + sha1_encodedStr);
        System.out.println("有密碼加密:" + SHA1Util.getInstance().encode(sha1_encodedStr, key));
        System.out.println("-------------------------AES--------------------------");
        String aes_encodedStr = AESUtil.getInstance().encode(res, key);
        System.out.println("加密:" + aes_encodedStr);
        System.out.println("解密:" + AESUtil.getInstance().decode(aes_encodedStr, key));
        System.out.println("-------------------------DES--------------------------");
        String des_encodedStr = DESUtil.getInstance().encode(res, key);
        System.out.println("加密:" + des_encodedStr);
        System.out.println("解密:" + DESUtil.getInstance().decode(des_encodedStr, key));
        System.out.println("-------------------------XOR--------------------------");
        String xor_encodedStr = XORUtil.getInstance().encode(res, key);
        System.out.println("文本加密:" + xor_encodedStr);
        System.out.println("文本解密:" + XORUtil.getInstance().decode(xor_encodedStr, key));
        int xor_encodedNum = XORUtil.getInstance().code(xorNum, key);
        System.out.println("數字加密:" + xor_encodedNum);
        System.out.println("數字解密:" + XORUtil.getInstance().code(xor_encodedNum, key));
    }
}

測試結果:java

相關文章
相關標籤/搜索