Java進行AES/DES加密,C#對其進行解密

    加密有很多種方式(如:AES、DES等),在不同語言間進行加密對接時,由於各語言間類庫的不同,而導致翻譯有困難,從而對接失敗。因此我們要做的,是先了解對方的加密特點,然後在這邊用自己的語言翻譯出來。

 

    帥帥最近就遇到了這樣一個問題,場景是:

    我們做了一個系統A,現在有另一個系統B,要和我們進行單點登錄的整合,由於A系統和B系統,有個居村的code,是一樣的,因此他們只傳居村code(加密後)過來,從而實現登錄。

    

    拿到這個問題,我就首先分析了B系統的Java加密類代碼,他們是這樣寫的:

 1 import java.math.BigInteger;
 2 
 3 import javax.crypto.Cipher;
 4 import javax.crypto.KeyGenerator;
 5 import javax.crypto.spec.SecretKeySpec;
 6 
 7 import org.apache.commons.codec.binary.Base64;
 8 import org.apache.commons.lang3.StringUtils;
 9 
10 import sun.misc.BASE64Decoder;
11 /**
12  * AES的加密和解密
13  * @author libo
14  */
15 public class Aes {
16     //密鑰 (需要前端和後端保持一致)
17     public static final String KEY = "key";
18     //算法
19     private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
20 
21 
22     /** 
23      * base 64 encode 
24      * @param bytes 待編碼的byte[] 
25      * @return 編碼後的base 64 code 
26      */  
27     public static String base64Encode(byte[] bytes){  
28         return Base64.encodeBase64String(bytes);  
29     }  
30 
31     /**
32      * AES加密爲base 64 code 
33      * @param content 待加密的內容 
34      * @param encryptKey 加密密鑰 
35      * @return 加密後的base 64 code 
36      * @throws Exception
37      */
38     public static String aesEncrypt(String content, String encryptKey) throws Exception {
39         return base64Encode(aesEncryptToBytes(content, encryptKey));
40     }
41 
42     /** 
43      * AES加密 
44      * @param content 待加密的內容 
45      * @param encryptKey 加密密鑰 
46      * @return 加密後的byte[] 
47      * @throws Exception 
48      */  
49     public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {  
50         KeyGenerator kgen = KeyGenerator.getInstance("AES");  
51         kgen.init(128);  
52         Cipher cipher = Cipher.getInstance(ALGORITHMSTR);  
53         cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));  
54   
55         return cipher.doFinal(content.getBytes("utf-8"));  
56     }  
57 }

 

    百度了半天,找到一段我覺得比較簡潔易懂的代碼,試試效果:

/// <summary>
/// AES解密
/// </summary>
/// <param name="encryptedContent">加密的內容</param>
/// <param name="key">密鑰</param>
/// <returns>解密後的內容</returns>
public string AESDecrypt(string encryptedContent, string key)
{
    using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
    {
        aesProvider.Key = Convert.FromBase64String(key);
        aesProvider.Mode = CipherMode.ECB;
        aesProvider.Padding = PaddingMode.PKCS7;

        using (ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor())
        {
            byte[] inputBuffers = Convert.FromBase64String(encryptedContent);
            byte[] results = cryptoTransform.TransformFinalBlock(inputBuffers, 0, inputBuffers.Length);
            aesProvider.Clear();
            return Encoding.UTF8.GetString(results);
        }
    }
}

    但是,運行起來報錯:

System.Security.Cryptography.CryptographicException:“指定的密鑰大小對於此算法無效。”

 欲哭無淚~

 

    後來,我通過下面這篇文章,找到了啓示:https://www.cnblogs.com/yetiea/articles/3858669.html

    

    修改了下我的C#解密代碼,運行一看,您猜怎麼着,解決啦!

    正確代碼如下

 1 /// <summary>
 2 /// AES解密
 3 /// </summary>
 4 /// <param name="encryptedContent">加密的內容</param>
 5 /// <param name="key">密鑰</param>
 6 /// <returns>解密後的內容</returns>
 7 public string AESDecrypt(string encryptedContent, string key)
 8 {
 9     using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
10     {
11         aesProvider.BlockSize = 128; //這句可以不寫,因爲默認128;寫出來只是爲了和上面Java的kgen.init(128)做個比對
12         aesProvider.Key = Encoding.UTF8.GetBytes(key);
13         aesProvider.Mode = CipherMode.ECB;
14         aesProvider.Padding = PaddingMode.PKCS7;
15 
16         using (ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor())
17         {
18             byte[] inputBuffers = Convert.FromBase64String(encryptedContent);
19             byte[] results = cryptoTransform.TransformFinalBlock(inputBuffers, 0, inputBuffers.Length);
20             aesProvider.Clear();
21             return Encoding.UTF8.GetString(results);
22         }
23     }
24 }

 

    總結:

    1.Java的AES,對應C#的AesCryptoServiceProvider

       這裏可以舉一反三,如:Java的DES,對應C#的DESCryptoServiceProvider 等等。

    2.注意Java加密裏這段代碼:

       String ALGORITHMSTR = "AES/ECB/PKCS5Padding";   //算法

       Cipher.getInstance(ALGORITHMSTR);  

       算法裏的DES、ECB、PKCS5Padding,分別解釋如下:

       AES,我們就不說了,上面已經闡述過了;

       ECB,對應C#寫法的CipherMode.ECB(參考上方C#代碼第13行);

       PKCS5Padding,對應C#寫法的PaddingMode.PKCS7(參考上方C#代碼第14行)

    3.注意key是不是base64加密了

       如果沒加密,用Encoding.UTF8.GetBytes(key) 轉爲byte[](當然,要注意java那邊的編碼形式),

       如果加密了,用Convert.FromBase64String(key) 轉爲byte[]

 

    OK,搞定收工,拿碗排隊打飯!

 

    如果有幫助到你,可以的話請幫我點個贊吧,謝謝~

 

 

 

    

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章