1. 程式人生 > >加密方式-對稱加密(AES)

加密方式-對稱加密(AES)

對稱加密中AES是比較常用,DES因為安全性比不上AES已經用的較少
對稱加密:是指加密解密都是一個金鑰,通過改金鑰加密,也通過它解密。

1.加密

/**
 * 加密
 * 
 * @param content 需要加密的內容
 * @param key 金鑰
 * @return
 */
    public static byte[] encrypt(String content, String key) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128
, new SecureRandom(key.getBytes())); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec keys = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");//建立密碼器 byte[] byteContent = content.getBytes("utf-8"
); cipher.init(Cipher.ENCRYPT_MODE, keys);// 初始化 byte[] result = cipher.doFinal(byteContent); return result; // 加密 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch
(InvalidKeyException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return null; }

2.解密

/**
 * 解密
 * 
 * @param content 待解密內容
 * @param key 解密金鑰
 * @return
 */
    public static byte[] decrypt(byte[] content, String key) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128, new SecureRandom(key.getBytes()));
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec keys = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES");//建立密碼器
            cipher.init(Cipher.DECRYPT_MODE, keys);// 初始化
            byte[] result = cipher.doFinal(content);
            return result; // 加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

3.測試

下面提供兩種方式(原來避免轉字串亂碼)


 1. 通過Base64(強烈推薦)來轉
         org.apache.commons.codec.binary.Base64

        public static void main(String[] args) {

            //1.字串經過加密得到byte陣列
            String content = "my name is libra_ts";
            String key = "1234567812345678";
            byte[] result = encrypt(content, key);

            //2.將byte陣列用base64轉碼成字串
            String strs = Base64.encodeBase64String(result);

            //3.傳輸(我這裡直接列印了,專案中一般是進行網路傳輸)
            System.out.println("==經過加密和BASE64轉碼後=="+ strs);

            //4.將字串用base64解碼成byte陣列
            byte[]b1 = Base64.decodeBase64(strs);

            //5.解密
            byte[]j1 = decrypt(b1, key);

            //6.輸出加密之前的內容
            System.out.println(new String(j1));

        }


 2. 通過進位制轉換
    /**
     * 將二進位制轉換成16進位制
     * 
     * @param buf
     * @return
     */
    public static 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進位制轉換為二進位制
     * 
     * @param hexStr
     * @return
     */
    public static 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 static void main(String[] args) {
        String content = "name=\"libra_ts\"";
        String key = "FTGYHUJKML56SYTWsddd=8n2ndsn3SE6Bnh";

        byte[] result = encrypt(content, key);
        // 二進位制轉16進位制
        String encryptResultStr = parseByte2HexStr(result); 
        System.out.println("==加密後==" + new String(results));

        // 16進位制轉二進位制
        byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);
        byte[] results = decrypt(decryptFrom, key);
        System.out.println("==解密後==" + new String(results));
    }

因為加密後的byte陣列是不能強制轉換成字串的,也就是說字串和byte陣列在這種情況下不是互逆的;要避免這種情況,我們需要做一些修改,推薦採用Base64轉碼,也可以考慮將二進位制資料轉換成十六進位制