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,搞定收工,拿碗排队打饭!

 

    如果有帮助到你,可以的话请帮我点个赞吧,谢谢~

 

 

 

    

    

posted @ 2020-11-30 10:15  吴所畏惧  阅读(927)  评论(0编辑  收藏  举报