1. 程式人生 > >Java加密與解密筆記(二) 對稱加密

Java加密與解密筆記(二) 對稱加密

解決 理解 span ring println key ted utf-8 rate

前面的僅僅是做了編碼或者摘要,下面看看真正的加密技術。

DES

public class DESUtil {

    static final String ALGORITHM = "DES";
    
    /**
     * 生成文本格式的DES Key
     * @return
     * @throws Exception
     */
    public static String getKey() throws Exception{
        KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);
        generator.init(
new SecureRandom());//加鹽 return Base64Util.encode(generator.generateKey().getEncoded()); } /** * 從文本 格式DES Key轉換成SecretKey對象 * @param key * @return */ public static SecretKey parseKeyFromString(String key)throws Exception{ DESKeySpec desKeySpec = new
DESKeySpec(Base64Util.decode(key)); SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); SecretKey secretKey = factory.generateSecret(desKeySpec); return secretKey; } /** * DES 加密 * @param data * @param key * @return * @throws
Exception */ public static String encrypt(String data,String key)throws Exception{ SecretKey secretKey = parseKeyFromString(key); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] bytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64Util.encode(bytes); } /** * DES 解密 * @param data * @param key * @return * @throws Exception */ public static String decrypt(String data,String key)throws Exception{ SecretKey secretKey = parseKeyFromString(key); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] bytes = cipher.doFinal(Base64Util.decode(data)); return new String(bytes,"UTF-8"); } public static void main(String[] args)throws Exception { String str = "Hello,DES"; String key = getKey(); System.out.println("原文:" + str); System.out.println("密鑰:" + key); String encryptedStr = encrypt(str, key); System.out.println("加密後:" + encryptedStr); String decryptedStr = decrypt(encryptedStr, key); System.out.println("解密後:" + decryptedStr); } }

類似DESKeySpec,Java中很多*KeySpec的類都實現了KeySpec的空接口,Java只關心某個類是否是一種Key的實現,至於具體如何實現的是具體加密解密算法要關心的。

再次看到Base64的身影,由此可以看出,Base64其實充當著字符串和byte數組之間的轉換器,真實的的密鑰數據其實是byte類型的,但是在閱讀和傳輸過程中字符串比較方便,所以我們能看到的很多密鑰信息其實都是Base64編碼。

Ciper為密文工具類,它是一個很高級的抽象類,有很多種Cipher的實現,可以通過Cipher.getInstance()方法獲取到。

getInstance方法接收的算法名稱非常多:

技術分享

測試:

原文:Hello,DES
密鑰:8ePQx0m1I4k=
加密後:bM06WR8OIL2sQOB8SUSXRA==
解密後:Hello,DES

AES

AES是DES的升級版,解決了DES的很多不足,上述DES代碼改成AES的改動很小:

static final String ALGORITHM = "AES";    
   /**
     * 從文本 格式AES Key轉換成SecretKey對象
     * @param key
     * @return
     */
    public static SecretKey parseKeyFromString(String key)throws Exception{
        SecretKey secretKey = new SecretKeySpec(Base64Util.decode(key), ALGORITHM);
        return secretKey;
    }    

PBE

PBE與DES、AES同屬對稱加密,不同之處在於其密鑰可以由用戶管理,即密鑰可以不用通過KeyGenerator來生成,可以是任意字符。為了增強安全性,PBE強制必須要有參數(java.security.spec.AlgorithmParameterSpec),可以理解為強制加鹽,否則將報錯。

public class PBEUtil {

    static final String ALGORITHM = "PBEWITHMD5andDES";
    
    private static SecretKey parseKeyFromString(String key) throws Exception{
        PBEKeySpec pbeKey = new PBEKeySpec(key.toCharArray());
        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
        return factory.generateSecret(pbeKey);
    }
    
    /**
     * PBE 加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String encrypt(String data,String key,byte[] salt)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        PBEParameterSpec params = new PBEParameterSpec(salt, 100);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey,params);
        byte[] bytes = cipher.doFinal(data.getBytes("UTF-8"));
        return Base64Util.encode(bytes);
    }
    
    /**
     * DES 解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String decrypt(String data,String key,byte[] salt)throws Exception{
        SecretKey secretKey = parseKeyFromString(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM); 
        PBEParameterSpec params = new PBEParameterSpec(salt, 100);
        cipher.init(Cipher.DECRYPT_MODE, secretKey,params);
        byte[] bytes = cipher.doFinal(Base64Util.decode(data));
        return new String(bytes,"UTF-8");
    }
    
    public static void main(String[] args)throws Exception {
        String str = "Hello,PBE";
        String key = "abc";
        byte[] salt = new byte[8];
        new Random().nextBytes(salt);
        System.out.println("原文:" + str);
        System.out.println("密鑰:" + key);
        String encryptedStr = encrypt(str, key,salt);
        System.out.println("加密後:" + encryptedStr);
        String decryptedStr = decrypt(encryptedStr, key,salt);
        System.out.println("解密後:" + decryptedStr);
    }
    
}


參考資料:

http://snowolf.iteye.com/blog/380034

http://snowolf.iteye.com/blog/380761

Java加密與解密筆記(二) 對稱加密