2013年7月30日 星期二

程式Memo - JAVA AES加密及Silverlight AES解密

JAVA端:

byte[] iv = new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

private String encrypt(String plaintext, String key){
        String ret ="";
        try{
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
       
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec( key.getBytes(), "AES");
            cipher.init( Cipher.ENCRYPT_MODE, spec, paramSpec);
           
            byte[] encryptData = cipher.doFinal(plaintext.getBytes());
            ret = ByteTransfer.toHex(encryptData);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

          return ret;
 }


Silverlight端:

private string decryptAES_Silverlight(string encryptedContent)
        {
            string AES_key = MY_KEY;
            byte[] iv = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
           
            string decryptedContent = "";
            byte[] b_encryptedContent = HexStrToByteArray(encryptedContent);

            AesManaged aes = new AesManaged();
            aes.BlockSize = 128;
            aes.KeySize = 128;
            aes.Padding = PaddingMode.PKCS7;

            aes.Key = UTF8Encoding.UTF8.GetBytes(AES_key);
            aes.IV = iv;

            ICryptoTransform decryptTrans = aes.CreateDecryptor();
            MemoryStream decryptStream = new MemoryStream();
            CryptoStream decryptor = new CryptoStream(decryptStream, decryptTrans, CryptoStreamMode.Write);

            decryptor.Write(b_encryptedContent, 0, b_encryptedContent.Length);
            decryptor.FlushFinalBlock();

            //解密後的byte[]
            byte[] decryptBytes = decryptStream.ToArray();
            decryptedContent = UTF8Encoding.UTF8.GetString(decryptBytes);
            return decryptedContent;
        }

Note:
1. 看起來JAVA的預設應該是使用Rijndael,不需要設定Initialization Vector;只是Silverlight端不支援Rijndael,而AES的另一個class - AESManaged卻必須設定IV,為了配合在Silverlight使用AESManaged類別,所以在JAVA加密端也要加入IV的設定。

2. Cipher.getInstance()內若不傳入參數,預設應該是AES/ECB/NoPadding;AES/CBC/PKCS5Padding的設定是為了配合Silverlight端,因為AESManaged只能用CBC mode;至於padding的部分,因為要加密的資料不一定會是16 bytes的倍數,padding就少不了了,JAVA端設定PKCS5,C#端相對的必須設定PKCS7,這兩個mode運作方式在此情況下是一樣的。

3. JAVA端的String.getBytes()若不指定Encoding,預設應該為UTF-8或ISO-8859_1(此處看來是UTF-8),在silverlight端必須將Key以及解碼結果的byte陣列也做UTF-8的編碼處理。

4. HexStrToByteArray、ByteTransfer.toHex()方法均為另外寫的十六進位陣列轉換。

沒有留言: