2011-09-02

再玩一下 AES 加密解密

上次在這篇「玩了一下AES加密解密」裡面寫的程式碼有些缺點,就是加密過後的結果是 byte[] 而不是 String,對於 Java 的操作上不是很方便。看了幾位高手的博文,自己做了些改良,同時也將程式碼放上來拋磚引玉。主要的改良是透過 BASE64Encoder 和 BASE64Decoder 將 byte[] 轉為可讀的英文字母 + 數字字串,這在網址的傳遞上也有好處,不需要變成%xx%xx的 UTF-8 形式,更容易偵錯與閱讀,也不減少其安全性。
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder; 

public class Base64AES {

    public static String decrypt( String key, String text ) throws Exception {
        byte [] results = decrypt( key.getBytes(), new BASE64Decoder().decodeBuffer( text ) );
        return new String( results );
    }

    public static String encrypt( String key, String text ) throws Exception {
        byte[] results = encrypt( key.getBytes(), text.getBytes() );
        return new BASE64Encoder().encode( results );
    } 
    
    public static byte[] encrypt( byte[] key, byte[] msg ) throws Exception {
        if ( key.length != 16 ) {
            throw new IllegalArgumentException( "Key length should be 16." );
        }
        SecretKeySpec spec = new SecretKeySpec( key, "AES" );
        IvParameterSpec ivSpec = new IvParameterSpec( key );
        Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
        cipher.init( Cipher.ENCRYPT_MODE, spec, ivSpec );
        return cipher.doFinal( msg );
    }
    
    public static byte[] decrypt( byte[] key, byte[] msg ) throws Exception {
        if ( key.length != 16 ) {
            throw new IllegalArgumentException( "Key length should be 16." );
        }
        SecretKeySpec spec = new SecretKeySpec( key, "AES" );
        Cipher cipher = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
        IvParameterSpec ivSpec = new IvParameterSpec( key );
        cipher.init( Cipher.DECRYPT_MODE, spec, ivSpec );
        return cipher.doFinal( msg );
    }
    
    public static void main( String[] args ) throws Exception {
        String msg = "This is so easy.";
        
        System.out.println( "原字串: " + msg );
        System.out.println( "加密後: " + encrypt( "vegafish12345678" , msg ) );
        System.out.println( "解密後: " + decrypt( "vegafish12345678", encrypt( "vegafish12345678" , msg ) ) );
    }

}
執行結果如下:
原字串: This is so easy.
加密後: KczRl5uSsrgfwWRKpfR5FoKEIVU0jPvxX1VsEYl/jl0=
解密後: This is so easy.

沒有留言: