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

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

        

        

  • 相关阅读:
    从万元户到千万富翁:6招助你蜕变
    16款有助于提升工作效率的工具
    8个身家百万的儿童创业者
    关于航模无刷电机发热问题的假想解决方案
    折腾了2个晚上无刷电调(ESC),电机终于转起来了,特此记录一下
    PWM占空比和分辨率(转)
    MSB与LSB(转)
    树莓派3uart wifi模块调试 (浪费了我3天时间的宝贵经验)
    USB加minicom使用串口
    【转】使用BBB的device tree和cape(重新整理版)
  • 原文地址:https://www.cnblogs.com/donkeysmall/p/14059550.html
Copyright © 2020-2023  润新知