加密算法

 

3DESC

请求参数和响应参数全采用3des加密规则,由于我是用.NET对接的,而第三方是Java开发的,所以两种程序之间采用的算法有一点差异,java的3des加密采用的是"DESede/CBC/PKCS5Padding"规则,所以对应的C#规则是"PaddingMode.PKCS7和CipherMode.CBC",使用CBC模式的话在C#下必须传入加密向量IV(固定长度8位),默认"12345678",加密密钥和IV双方约定好即可,如果是ECB编码模式,那么就无须使用加密向量。

这里的KEY采用Base64编码,便用分发,因为Java的Byte范围为-128至127,c#的Byte范围是0-255
核心是确定Mode和Padding,关于这两个的意思可以搜索3DES算法相关文章
一个是C#采用CBC Mode,PKCS7 Padding,Java采用CBC Mode,PKCS5Padding Padding,
另一个是C#采用ECB Mode,PKCS7 Padding,Java采用ECB Mode,PKCS5Padding Padding,
Java的ECB模式不需要IV

对字符加密时,双方采用的都是UTF-8编码

DesIv: 3FEB40B6
DesKey: 3FD5F52BEA57D4B03FE9CF73

/// <summary> 
/// DES3加密解密 
/// </summary> 
public class Des3 
{ 
    #region CBC模式** 
    /// <summary> 
    /// DES3 CBC模式加密 
    /// </summary> 
    /// <param name="key">密钥</param> 
    /// <param name="iv">IV</param> 
    /// <param name="data">明文的byte数组</param> 
    /// <returns>密文的byte数组</returns> 
    public static byte[] Des3EncodeCBC( byte[] key, byte[] iv, byte[] data ) 
    { 
        //复制于MSDN 
        try 
        { 
            // Create a MemoryStream. 
            MemoryStream mStream = new MemoryStream(); 
            TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 
            tdsp.Mode = CipherMode.CBC;             //默认值 
            tdsp.Padding = PaddingMode.PKCS7;       //默认值 
            // Create a CryptoStream using the MemoryStream  
            // and the passed key and initialization vector (IV). 
            CryptoStream cStream = new CryptoStream( mStream, 
                tdsp.CreateEncryptor( key, iv ), 
                CryptoStreamMode.Write ); 
            // Write the byte array to the crypto stream and flush it. 
            cStream.Write( data, 0, data.Length ); 
            cStream.FlushFinalBlock(); 
            // Get an array of bytes from the  
            // MemoryStream that holds the  
            // encrypted data. 
            byte[] ret = mStream.ToArray(); 
            // Close the streams. 
            cStream.Close(); 
            mStream.Close(); 
            // Return the encrypted buffer. 
            return ret; 
        } 
        catch ( CryptographicException e ) 
        { 
            Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 
            return null; 
        } 
    } 
    /// <summary> 
    /// DES3 CBC模式解密 
    /// </summary> 
    /// <param name="key">密钥</param> 
    /// <param name="iv">IV</param> 
    /// <param name="data">密文的byte数组</param> 
    /// <returns>明文的byte数组</returns> 
    public static byte[] Des3DecodeCBC( byte[] key, byte[] iv, byte[] data ) 
    { 
        try 
        { 
            // Create a new MemoryStream using the passed  
            // array of encrypted data. 
            MemoryStream msDecrypt = new MemoryStream( data ); 
            TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 
            tdsp.Mode = CipherMode.CBC; 
            tdsp.Padding = PaddingMode.PKCS7; 
            // Create a CryptoStream using the MemoryStream  
            // and the passed key and initialization vector (IV). 
            CryptoStream csDecrypt = new CryptoStream( msDecrypt, 
                tdsp.CreateDecryptor( key, iv ), 
                CryptoStreamMode.Read ); 
            // Create buffer to hold the decrypted data. 
            byte[] fromEncrypt = new byte[data.Length]; 
            // Read the decrypted data out of the crypto stream 
            // and place it into the temporary buffer. 
            csDecrypt.Read( fromEncrypt, 0, fromEncrypt.Length ); 
            //Convert the buffer into a string and return it. 
            return fromEncrypt; 
        } 
        catch ( CryptographicException e ) 
        { 
            Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 
            return null; 
        } 
    } 
    #endregion 
    #region ECB模式 
    /// <summary> 
    /// DES3 ECB模式加密 
    /// </summary> 
    /// <param name="key">密钥</param> 
    /// <param name="iv">IV(当模式为ECB时,IV无用)</param> 
    /// <param name="str">明文的byte数组</param> 
    /// <returns>密文的byte数组</returns> 
    public static byte[] Des3EncodeECB( byte[] key, byte[] iv, byte[] data ) 
    { 
        try 
        { 
            // Create a MemoryStream. 
            MemoryStream mStream = new MemoryStream(); 
            TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 
            tdsp.Mode = CipherMode.ECB; 
            tdsp.Padding = PaddingMode.PKCS7; 
            // Create a CryptoStream using the MemoryStream  
            // and the passed key and initialization vector (IV). 
            CryptoStream cStream = new CryptoStream( mStream, 
                tdsp.CreateEncryptor( key, iv ), 
                CryptoStreamMode.Write ); 
            // Write the byte array to the crypto stream and flush it. 
            cStream.Write( data, 0, data.Length ); 
            cStream.FlushFinalBlock(); 
            // Get an array of bytes from the  
            // MemoryStream that holds the  
            // encrypted data. 
            byte[] ret = mStream.ToArray(); 
            // Close the streams. 
            cStream.Close(); 
            mStream.Close(); 
            // Return the encrypted buffer. 
            return ret; 
        } 
        catch ( CryptographicException e ) 
        { 
            Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 
            return null; 
        } 
    } 
    /// <summary> 
    /// DES3 ECB模式解密 
    /// </summary> 
    /// <param name="key">密钥</param> 
    /// <param name="iv">IV(当模式为ECB时,IV无用)</param> 
    /// <param name="str">密文的byte数组</param> 
    /// <returns>明文的byte数组</returns> 
    public static byte[] Des3DecodeECB( byte[] key, byte[] iv, byte[] data ) 
    { 
        try 
        { 
            // Create a new MemoryStream using the passed  
            // array of encrypted data. 
            MemoryStream msDecrypt = new MemoryStream( data ); 
            TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider(); 
            tdsp.Mode = CipherMode.ECB; 
            tdsp.Padding = PaddingMode.PKCS7; 
            // Create a CryptoStream using the MemoryStream  
            // and the passed key and initialization vector (IV). 
            CryptoStream csDecrypt = new CryptoStream( msDecrypt, 
                tdsp.CreateDecryptor( key, iv ), 
                CryptoStreamMode.Read ); 
            // Create buffer to hold the decrypted data. 
            byte[] fromEncrypt = new byte[data.Length]; 
            // Read the decrypted data out of the crypto stream 
            // and place it into the temporary buffer. 
            csDecrypt.Read( fromEncrypt, 0, fromEncrypt.Length ); 
            //Convert the buffer into a string and return it. 
            return fromEncrypt; 
        } 
        catch ( CryptographicException e ) 
        { 
            Console.WriteLine( "A Cryptographic error occurred: {0}", e.Message ); 
            return null; 
        } 
    } 
    #endregion 
    /// <summary> 
    ///<a href="http://lib.csdn.net/base/softwaretest" class='replace_word' title="软件测试知识库" target='_blank' style='color:#df3434; font-weight:bold;'>测试</a> 
    /// </summary> 
    public static void Test() 
    { 
        System.Text.Encoding utf8 = System.Text.Encoding.UTF8; 
        //key为abcdefghijklmnopqrstuvwx的Base64编码 
        byte[] key = Convert.FromBase64String( "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" ); 
        byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };      //当模式为ECB时,IV无用 
        byte[] data = utf8.GetBytes( "中国ABCabc123" ); 
        System.Console.WriteLine( "ECB模式:" ); 
        byte[] str1 = Des3.Des3EncodeECB( key, iv, data ); 
        byte[] str2 = Des3.Des3DecodeECB( key, iv, str1 ); 
        System.Console.WriteLine( Convert.ToBase64String( str1 ) ); 
        System.Console.WriteLine( System.Text.Encoding.UTF8.GetString( str2 ) ); 
        System.Console.WriteLine(); 
        System.Console.WriteLine( "CBC模式:" ); 
        byte[] str3 = Des3.Des3EncodeCBC( key, iv, data ); 
        byte[] str4 = Des3.Des3DecodeCBC( key, iv, str3 ); 
        System.Console.WriteLine( Convert.ToBase64String( str3 ) ); 
        System.Console.WriteLine( utf8.GetString( str4 ) ); 
        System.Console.WriteLine(); 
    } 
} 
C# 3DESC

 

package com.mes.util;
 
import java.security.Key;
import java.util.HashMap;
import java.util.Map;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
 
import sun.misc.BASE64Decoder;
 
@SuppressWarnings("restriction")
public class ThreeDESCBC {
    /**
     *
     * @Description ECB加密,不要IV
     * @param key 密钥
     * @param data 明文
     * @return Base64编码的密文
     * @throws Exception
     * @author Shindo  
     * @date 2016年11月15日 下午4:42:56
     */
    public static byte[] des3EncodeECB(byte[] key, byte[] data) throws Exception {
        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, deskey);
        byte[] bOut = cipher.doFinal(data);
        return bOut;
    }
 
    /**
     *
     * @Description ECB解密,不要IV
     * @param key 密钥
     * @param data Base64编码的密文
     * @return 明文
     * @throws Exception
     * @author Shindo  
     * @date 2016年11月15日 下午5:01:23
     */
    public static byte[] ees3DecodeECB(byte[] key, byte[] data) throws Exception {
        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        byte[] bOut = cipher.doFinal(data);
        return bOut;
    }
 
    /**
     *
     * @Description CBC加密
     * @param key 密钥
     * @param keyiv IV
     * @param data 明文
     * @return Base64编码的密文
     * @throws Exception
     * @author Shindo  
     * @date 2016年11月15日 下午5:26:46
     */
    public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {
        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);
        return bOut;
    }
 
    /**
     *
     * @Description CBC解密
     * @param key 密钥
     * @param keyiv IV
     * @param data Base64编码的密文
     * @return 明文
     * @throws Exception
     * @author Shindo  
     * @date 2016年11月16日 上午10:13:49
     */
    public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data) throws Exception {
        Key deskey = null;
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
        deskey = keyfactory.generateSecret(spec);
        Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
        IvParameterSpec ips = new IvParameterSpec(keyiv);
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
        byte[] bOut = cipher.doFinal(data);
        return bOut;
    }
 
    /**
     *
     * @Description 浦发所属渠道入口3DES解密方法
     * @param paras 加密参数
     * @param key 3DES密钥
     * @return 解密明文
     * @author Shindo  
     * @throws Exception
     * @date 2016年11月22日 上午9:34:07
     */
    public Map<String, String> parasDecryptCBC(Map<String, String> paras, String key) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        try {
            byte[] pf_3des_key = new BASE64Decoder().decodeBuffer(key);
            byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };// 3DES解密IV值
            String telePhone = paras.get("telePhone");// 浦发新接口电话不加密
 
            byte[] card = new BASE64Decoder().decodeBuffer(ControllerUtils.URLDecode(paras.get("cardNo")));
            byte[] cert = new BASE64Decoder().decodeBuffer(ControllerUtils.URLDecode(paras.get("certNo")));
 
            String cardNo = new String(des3DecodeCBC(pf_3des_key, keyiv, card), "UTF-8");// 卡号
            String certNo = new String(des3DecodeCBC(pf_3des_key, keyiv, cert), "UTF-8");// 证件号码
            map.put("telePhone", telePhone);
            map.put("cardNo", cardNo);
            map.put("certNo", certNo);
        } catch (Exception e) {
            throw new Exception(" 浦发所属渠道入口参数3DES CBC解密失败!");
        }
        return map;
    }
 
    /**
     *
     * @Description 调试方法
     * @param args
     * @throws Exception
     * @author Shindo  
     * @date 2016年11月22日 上午9:28:22
     */
    public static void main(String[] args) throws Exception {
        byte[] key = new BASE64Decoder().decodeBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4");
        byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };
//        byte[] data = "420106198203279258".getBytes("UTF-8");
        /*System.out.println("ECB加密解密");
        byte[] str3 = des3EncodeECB(key, data);
        byte[] str4 = ees3DecodeECB(key, str3);
        System.out.println(new BASE64Encoder().encode(str3));
        System.out.println(new String(str4, "UTF-8"));
        System.out.println();*/
 
        /*System.out.println("CBC加密解密");
        byte[] str5 = des3EncodeCBC(key, keyiv, data);
        byte[] str6 = des3DecodeCBC(key, keyiv, str5);
        System.out.println(new BASE64Encoder().encode(str5));
        System.out.println(new String(str6, "UTF-8"));*/
 
        String str7 = "uHrew7Thp2taL2NJpSJhF2mdFMP7BZ1W";
        byte[] str8 = new BASE64Decoder().decodeBuffer(str7);
        byte[] str9 = des3DecodeCBC(key, keyiv, str8);
        System.out.println(new String(str9, "UTF-8"));
 
    }
 
}
JAVA 3DESC

转:https://www.cnblogs.com/shindo/p/6346655.html

AESHelper:

    public class AESHelper
    {
        /// <summary>
        /// 获取密钥
        /// </summary>
        private static string Key
        {
            get
            {
                return "abcdef1234567890";    ////必须是16位
            }
        }
        //默认密钥向量
        private static byte[] _key1 = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        /// <summary>
        /// AES加密算法
        /// </summary>
        /// <param name="plainText">明文字符串</param>
        /// <returns>将加密后的密文转换为Base64编码,以便显示</returns>
        public static string AESEncrypt(string plainText)
        {
            //分组加密算法
            SymmetricAlgorithm des = Rijndael.Create();
            byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText);//得到需要加密的字节数组
                                                                      //设置密钥及密钥向量
            des.Key = Encoding.UTF8.GetBytes(Key);
            des.IV = _key1;
            byte[] cipherBytes = null;
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cipherBytes = ms.ToArray();//得到加密后的字节数组
                    cs.Close();
                    ms.Close();
                }
            }
            return Convert.ToBase64String(cipherBytes);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="cipherText">密文字符串</param>
        /// <returns>返回解密后的明文字符串</returns>
        public static string AESDecrypt(string showText)
        {
            byte[] cipherText = Convert.FromBase64String(showText);

            SymmetricAlgorithm des = Rijndael.Create();
            des.Key = Encoding.UTF8.GetBytes(Key);
            des.IV = _key1;
            byte[] decryptBytes = new byte[cipherText.Length];
            using (MemoryStream ms = new MemoryStream(cipherText))
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    cs.Read(decryptBytes, 0, decryptBytes.Length);
                    cs.Close();
                    ms.Close();
                }
            }
            return Encoding.UTF8.GetString(decryptBytes).Replace("\0", "");   ///将字符串后尾的'\0'去掉
        }


        #region 第二

        /// <summary>
        /// 默认密钥-密钥的长度必须是32
        /// </summary>
        private const string PublicKey = "1234567890123456";

        /// <summary>
        /// 默认向量
        /// </summary>
        private const string Iv = "abcdefghijklmnop";
        /// <summary>  
        /// AES加密  
        /// </summary>  
        /// <param name="str">需要加密字符串</param>  
        /// <returns>加密后字符串</returns>  
        public static String Encrypt(string str)
        {
            return Encrypt(str, PublicKey);
        }

        /// <summary>  
        /// AES解密  
        /// </summary>  
        /// <param name="str">需要解密字符串</param>  
        /// <returns>解密后字符串</returns>  
        public static String Decrypt(string str)
        {
            return Decrypt(str, PublicKey);
        }
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="str">需要加密的字符串</param>
        /// <param name="key">32位密钥</param>
        /// <returns>加密后的字符串</returns>
        public static string Encrypt(string str, string key)
        {
            Byte[] keyArray = System.Text.Encoding.UTF8.GetBytes(key);
            Byte[] toEncryptArray = System.Text.Encoding.UTF8.GetBytes(str);
            var rijndael = new System.Security.Cryptography.RijndaelManaged();// Aes.Create();

            rijndael.Key = keyArray;
            rijndael.Mode = System.Security.Cryptography.CipherMode.ECB;
            rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
            rijndael.IV = System.Text.Encoding.UTF8.GetBytes(Iv);
            System.Security.Cryptography.ICryptoTransform cTransform = rijndael.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="str">需要解密的字符串</param>
        /// <param name="key">32位密钥</param>
        /// <returns>解密后的字符串</returns>
        public static string Decrypt(string str, string key)
        {
            Byte[] keyArray = System.Text.Encoding.UTF8.GetBytes(key);
            Byte[] toEncryptArray = Convert.FromBase64String(str);
            //var rijndael = new System.Security.Cryptography.RijndaelManaged();// Aes.Create();
            var rijndael = Aes.Create();
            rijndael.Key = keyArray;
            rijndael.Mode = System.Security.Cryptography.CipherMode.ECB;
            rijndael.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
            rijndael.IV = System.Text.Encoding.UTF8.GetBytes(Iv);
            System.Security.Cryptography.ICryptoTransform cTransform = rijndael.CreateDecryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return System.Text.Encoding.UTF8.GetString(resultArray);
        }

        #endregion
    }
AESHelper

多种加密算法:

    public class StringSecurity
    {
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">加密字符</param>
        /// <returns></returns>
        public static string GenerateMD5(string input)
        {
            // Use input string to calculate MD5 hash
            using (MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                // Convert the byte array to hexadecimal string
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("X2"));
                    // To force the hex string to lower-case letters instead of
                    // upper-case, use he following line instead:
                    // sb.Append(hashBytes[i].ToString("x2")); 
                }
                return sb.ToString();
            }
        }

        /// <summary>
        /// MD5流加密
        /// </summary>
        /// <param name="inputStream"></param>
        /// <returns></returns>
        public static string GenerateMD5(Stream inputStream)
        {
            using (MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                //开始加密
                byte[] newBuffer = md5.ComputeHash(inputStream);
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < newBuffer.Length; i++)
                {
                    sb.Append(newBuffer[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }

        //// <summary>
        /// MD5 16位加密 加密后密码为小写
        /// </summary>
        /// <param name="convertString"></param>
        /// <returns></returns>
        public static string GetMd5Str(string convertString)
        {
            //MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            using (MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(convertString);
                byte[] hashBytes = md5.ComputeHash(inputBytes, 4, 8);
                //var str = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(convertString)), 4, 8);
                string t2 = BitConverter.ToString(hashBytes);
                t2 = t2.Replace("-", "");

                t2 = t2.ToLower();

                return t2;
            }
            
            
        }

        /// <summary>
        /// Sha1加密
        /// </summary>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static string Sha1Encryption(string pwd)
        {
            //创建SHA1加密算法对象
            SHA1 sha1 = SHA1.Create();
            //将原始密码转换为字节数组
            byte[] originalPwd = Encoding.UTF8.GetBytes(pwd);
            //执行加密
            byte[] encryPwd = sha1.ComputeHash(originalPwd);

            //StringBuilder builder = new StringBuilder();
            //foreach (byte hashByte in encryPwd)
            //{
            //    builder.AppendFormat("{0:x2}", hashByte);
            //}
            //var str = builder.ToString();

            //将加密后的字节数组转换为小写字符串
            return string.Join("", encryPwd.Select(b => string.Format("{0:x2}",b)).ToArray()).ToLower();
        }


        /// <summary>
        /// AES解密:从小程序中 getPhoneNumber 返回值中,解析手机号码
        /// </summary>
        /// <param name="encryptedData">包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法</param>
        /// <param name="Session_key"></param>
        /// <param name="iv">加密算法的初始向量</param>
        /// <returns>手机号码</returns>
        public static string AESEncrypt(string encryptedData, string sessionKey, string iv)
        {
            byte[] encryData = Convert.FromBase64String(encryptedData);  // strToToHexByte(text);
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Key = Convert.FromBase64String(sessionKey); // Encoding.UTF8.GetBytes(AesKey);
            rijndaelCipher.IV = Convert.FromBase64String(iv);// Encoding.UTF8.GetBytes(AesIV);
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
            byte[] plainText = transform.TransformFinalBlock(encryData, 0, encryData.Length);
            string result = Encoding.Default.GetString(plainText);
            ////动态解析result 成对象
            //dynamic model = Newtonsoft.Json.Linq.JToken.Parse(result) as dynamic;
            //return model.phoneNumber;
            return result;
        }

        /// <summary>
        /// Aes解密
        /// </summary>
        /// <param name="str">需要解密的字符串</param>
        /// <param name="key">密钥,长度不够时空格补齐,超过时从左截取</param>
        /// <param name="iv">偏移量,长度不够时空格补齐,超过时从左截取</param>
        /// <param name="keyLenth">秘钥长度,16 24 32</param>
        /// <param name="aesMode">解密模式</param>
        /// <param name="aesPadding">填充方式</param>
        /// <returns></returns>
        public static string AesDecode(string str, string key, string iv, int keyLenth = 16, CipherMode aesMode = CipherMode.CBC, PaddingMode aesPadding = PaddingMode.PKCS7)
        {
            str = str.Replace(" ", "+");
            key = key.Replace(" ", "+");
            iv = iv.Replace(" ", "+");
            if (!new List<int> { 16, 24, 32 }.Contains(keyLenth))
            {
                return null;//密钥的长度,16位密钥 = 128位,24位密钥 = 192位,32位密钥 = 256位。
            }
            var oldBytes = Convert.FromBase64String(str);
            var bKey = new Byte[keyLenth];
            Array.Copy(Convert.FromBase64String(key.PadRight(keyLenth)), bKey, keyLenth);
            var bIv = new Byte[16];
            Array.Copy(Convert.FromBase64String(iv.PadRight(16)), bIv, 16);

            var rijalg = new RijndaelManaged
            {
                Mode = aesMode,
                Padding = aesPadding,
                Key = bKey,
                IV = bIv,
            };
            var decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV);
            var rtByte = decryptor.TransformFinalBlock(oldBytes, 0, oldBytes.Length);
            return Encoding.UTF8.GetString(rtByte);
        }

        #region AES加密解密

        /// <summary>
        ///  加密AES 参数:string
        /// </summary>
        /// <param name="strCon">加密内容</param>
        /// <param name="key">密钥</param>
        /// <returns>string:密文</returns>
        public static string Encrypt(string strCon, string key)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(strCon))
                {
                    return null;
                }

                byte[] byCon = Encoding.UTF8.GetBytes(strCon);
                var rm = new RijndaelManaged
                {
                    IV = Encoding.UTF8.GetBytes(key),
                    Key = Encoding.UTF8.GetBytes(key),
                    Mode = CipherMode.CBC,
                    Padding = PaddingMode.PKCS7
                };
                ICryptoTransform cTransform = rm.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(byCon, 0, byCon.Length);
                return Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 解密AES
        /// </summary>
        /// <param name="strCon"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Decrypt(string strCon, string key)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(strCon))
                {
                    return null;
                }

                byte[] byCon = Convert.FromBase64String(strCon);
                var rm = new RijndaelManaged
                {
                    IV = Encoding.UTF8.GetBytes(key),
                    Key = Encoding.UTF8.GetBytes(key),
                    Mode = CipherMode.CBC,
                    Padding = PaddingMode.PKCS7
                };
                ICryptoTransform cTransform = rm.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(byCon, 0, byCon.Length);
                return Encoding.UTF8.GetString(resultArray);
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        ///  AES 加密
        /// </summary>
        /// <param name="str">明文</param>
        /// <param name="aesKey">密钥</param>
        /// <returns></returns>
        public static string AesEncrypt(string str, string aesKey)
        {
            string data = string.Empty;
            if (!string.IsNullOrEmpty(str) && !string.IsNullOrEmpty(aesKey))
            {
                byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
                Aes aes = Aes.Create();
                aes.Key = Encoding.UTF8.GetBytes(aesKey);
                byte[] resultArray = aes.EncryptEcb(toEncryptArray, PaddingMode.PKCS7);
                data = Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            return data;
        }

        /// <summary>
        ///  AES 解密
        /// </summary>
        /// <param name="str">密文</param>
        /// <param name="aesKey">密钥</param>
        /// <returns></returns>
        public static string AesDecrypt(string str, string aesKey)
        {
            string data = string.Empty;
            if (!string.IsNullOrEmpty(str) && !string.IsNullOrEmpty(aesKey))
            {
                byte[] toEncryptArray = Convert.FromBase64String(str);
                Aes aes = Aes.Create();
                aes.Key = Encoding.UTF8.GetBytes(aesKey);
                byte[] resultArray = aes.DecryptEcb(toEncryptArray, PaddingMode.PKCS7);
                data = Encoding.UTF8.GetString(resultArray);
            }
            return data;
        }

        /// <summary>
        /// AES加密解密
        /// </summary>
        /// <param name="str"></param>
        /// <param name="aesKey"></param>
        /// <returns></returns>
        public static string AesEnDecrype(string str, string aesKey)
        {
            //byte[] plaintext = new byte[] { 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
            byte[] plaintext = Encoding.UTF8.GetBytes(str);
            using (var aes = new RijndaelManaged())
            {
                aes.Key = Encoding.UTF8.GetBytes(aesKey);//new byte[] { 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 };
                aes.IV = new byte[16];
                //aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.None;
                var cryptoTransform = aes.CreateEncryptor();
                byte[] resultBuff = cryptoTransform.TransformFinalBlock(plaintext, 0, plaintext.Length);
                foreach (byte i in resultBuff)
                    Console.Write("{0:X2}", i);
                //将加密后的字节数组转换为小写字符串
                Console.WriteLine( string.Join("", resultBuff.Select(b => string.Format("{0:X2}", b)).ToArray()).ToLower());
                var res1 = Convert.ToBase64String(resultBuff, 0, resultBuff.Length);    //  加密结果
                
                //解密
                cryptoTransform = aes.CreateDecryptor();
                resultBuff = cryptoTransform.TransformFinalBlock(resultBuff, 0, resultBuff.Length);
                foreach (byte i in resultBuff)
                    Console.Write("{0:X2}", i);
                Console.WriteLine(string.Join("", resultBuff.Select(b => string.Format("{0:X2}", b)).ToArray()).ToLower());
                var res2 = Encoding.UTF8.GetString(resultBuff);

                return res1 +","+ res2;
            }
        }

        #endregion

        #region RSA

        /// <summary>
        /// 获取加密所使用的key,RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
        /// </summary>
        public static string GetKey()
        {
            string PublicKey = string.Empty;
            string PrivateKey = string.Empty;
            RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider();
            PublicKey = rSACryptoServiceProvider.ToXmlString(false);
            // 获取公匙,用于加密
            PrivateKey = rSACryptoServiceProvider.ToXmlString(true);
            // 获取公匙和私匙,用于解密

            //Console.WriteLine("PublicKey is {0}", PublicKey);        // 输出公匙
            //Console.WriteLine("PrivateKey is {0}", PrivateKey);     // 输出密匙

            //密匙中含有公匙,公匙是根据密匙进行计算得来的。
            using (StreamWriter streamWriter = new StreamWriter("PublicKey.xml"))
            {
                streamWriter.Write(rSACryptoServiceProvider.ToXmlString(false));// 将公匙保存到运行目录下的PublicKey
            }
            using (StreamWriter streamWriter = new StreamWriter("PrivateKey.xml"))
            {
                streamWriter.Write(rSACryptoServiceProvider.ToXmlString(true)); // 将公匙&私匙保存到运行目录下的PrivateKey
            }

            return $"{DateTime.Now}:{PublicKey},{PrivateKey}";
        }

        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string RSAEncryption(string str)
        {
            RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider();
            using (StreamReader streamReader = new StreamReader("PublicKey.xml")) // 读取运行目录下的PublicKey.xml
            {
                rSACryptoServiceProvider.FromXmlString(streamReader.ReadToEnd()); // 将公匙载入进RSA实例中
            }

            byte[] buffer = Encoding.UTF8.GetBytes(str); // 将明文转换为byte[]

            // 加密后的数据就是一个byte[] 数组,可以以 文件的形式保存 或 别的形式(网上很多教程,使用Base64进行编码化保存)
            byte[] EncryptBuffer = rSACryptoServiceProvider.Encrypt(buffer, false); // 进行加密
            return Convert.ToBase64String(EncryptBuffer); // 如果使用base64进行明文化,在解密时 需要再次将base64 转换为byte[]
        }

        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="strEncryptBase64"></param>
        /// <returns></returns>
        public static string RSADecrypt(string strEncryptBase64)
        {
            RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider();
            using (StreamReader streamReader = new StreamReader("PrivateKey.xml")) // 读取运行目录下的PrivateKey.xml
            {
                rSACryptoServiceProvider.FromXmlString(streamReader.ReadToEnd()); // 将私匙载入进RSA实例中
            }

            byte[] buffer = Convert.FromBase64String(strEncryptBase64);
            // 解密后得到一个byte[] 数组
            byte[] DecryptBuffer = rSACryptoServiceProvider.Decrypt(buffer, false); // 进行解密
            string str = Encoding.UTF8.GetString(DecryptBuffer); // 将byte[]转换为明文

            return str;
        }

        #region 解决长字符加密的异常,我们采取分段加密的方法进行字符串加密

        /// <summary>
        /// 分段加密
        /// </summary>
        /// <param name="xmlPublicKey"></param>
        /// <param name="enptStr"></param>
        /// <returns></returns>
        public static string SubRSAEncrypt(string xmlPublicKey, string enptStr)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(xmlPublicKey);
            byte[] bytes = Encoding.UTF8.GetBytes(enptStr);
            int MaxBlockSize = provider.KeySize / 8 - 11;  //加密块最大长度限制​
            if (bytes.Length <= MaxBlockSize)
            {
                var str = Convert.ToBase64String(provider.Encrypt(bytes, false));
                return str;
            }
            using (MemoryStream PlaiStream = new MemoryStream(bytes))
            {
                using (MemoryStream CrypStream = new MemoryStream())
                {

                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    while (BlockSize > 0)
                    {
                        byte[] ToEncrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
                        byte[] Cryptograph = provider.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }
                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
        }

        /// <summary>
        /// 分段解密
        /// </summary>
        /// <param name="xmlPublicKey"></param>
        /// <param name="enptStr"></param>
        /// <returns></returns>
        public static string SubRSADecrypt(string xmlPublicKey, string enptStr)
        {
            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(xmlPublicKey);
            byte[] bytes = Convert.FromBase64String(enptStr);
            int MaxBlockSize = provider.KeySize / 8//解密块最大长度限制​
            if (bytes.Length <= MaxBlockSize)
            {
                return Encoding.UTF8.GetString(provider.Decrypt(bytes, false));
            }
            using (MemoryStream CrypStream = new MemoryStream(bytes))
            using (MemoryStream PlaiStream = new MemoryStream())
            {
                byte[] Buffer = new byte[MaxBlockSize];
                int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                while (BlockSize > 0)
                {
                    byte[] ToDecrypt = new byte[BlockSize];
                    Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);
                    byte[] Plaintext = provider.Decrypt(ToDecrypt, false);
                    PlaiStream.Write(Plaintext, 0, Plaintext.Length);
                    BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                }
                return Encoding.UTF8.GetString(PlaiStream.ToArray());
            }
        }

        #endregion

        #endregion
    }
StringSecurity

 

SM4:

    public class SM4
    {
        /// <summary>
        /// 加密 非线性τ函数B=τ(A)
        /// </summary>
        /// <param name="b"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        private static long GetULongByBe(byte[] b, int i)
        {
            long n = (long)(b[i] & 0xff) << 24 |
                (long)((b[i + 1] & 0xff) << 16) |
                (long)((b[i + 2] & 0xff) << 8) |
                (long)(b[i + 3] & 0xff) & 0xffffffffL;
            return n;
        }
        /// <summary>
        /// 解密 非线性τ函数B=τ(A)
        /// </summary>
        /// <param name="n"></param>
        /// <param name="b"></param>
        /// <param name="i"></param>
        private static void PutULongToBe(long n, byte[] b, int i)
        {
            b[i] = (byte)(int)(0xFF & n >> 24);
            b[i + 1] = (byte)(int)(0xFF & n >> 16);
            b[i + 2] = (byte)(int)(0xFF & n >> 8);
            b[i + 3] = (byte)(int)(0xFF & n);
        }

        /// <summary>
        /// 循环移位,为32位的x循环左移n位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        private static long Rotl(long x, int n)
        {
            return ((x & 0xFFFFFFFF) << n) | x >> (32 - n);
        }

        /// <summary>
        /// 将密钥逆序
        /// </summary>
        /// <param name="sk"></param>
        /// <param name="i"></param>
        private static void Swap(long[] sk, int i)
        {
            long t = sk[i];
            sk[i] = sk[(31 - i)];
            sk[(31 - i)] = t;
        }
        /// <summary>
        /// S盒 
        /// </summary>
        public byte[] SboxTable = new byte[] {
         //   0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f
            0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
            0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
            0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
            0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
            0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
            0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
            0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
            0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
            0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
            0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
            0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
            0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
            0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
            0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
            0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
            0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
        };

        /// <summary>
        /// 系统参数FK
        /// </summary>
        public uint[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
        /// <summary>
        /// 固定参数CK
        /// </summary>
        public uint[] CK = {
            0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
            0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
            0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
            0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
            0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
            0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
            0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
            0x10171e25,0x2c333a41,0x484f565d,0x646b7279
        };

        /// <summary>
        /// Sm4的S盒取值
        /// </summary>
        /// <param name="inch"></param>
        /// <returns></returns>
        private byte Sm4Sbox(byte inch)
        {
            int i = inch & 0xFF;
            byte retVal = SboxTable[i];
            return retVal;
        }

        /// <summary>
        /// 线性变换 L
        /// </summary>
        /// <param name="ka"></param>
        /// <returns></returns>
        private long Sm4Lt(long ka)
        {
            byte[] a = new byte[4];
            byte[] b = new byte[4];
            PutULongToBe(ka, a, 0);
            b[0] = Sm4Sbox(a[0]);
            b[1] = Sm4Sbox(a[1]);
            b[2] = Sm4Sbox(a[2]);
            b[3] = Sm4Sbox(a[3]);
            long bb = GetULongByBe(b, 0);
            long c = bb ^ Rotl(bb, 2) ^ Rotl(bb, 10) ^ Rotl(bb, 18) ^ Rotl(bb, 24);
            return c;
        }
        /// <summary>
        /// 轮函数 F
        /// </summary>
        /// <param name="x0"></param>
        /// <param name="x1"></param>
        /// <param name="x2"></param>
        /// <param name="x3"></param>
        /// <param name="rk"></param>
        /// <returns></returns>
        private long Sm4F(long x0, long x1, long x2, long x3, long rk)
        {
            return x0 ^ Sm4Lt(x1 ^ x2 ^ x3 ^ rk);
        }

        /// <summary>
        /// 轮密钥rk
        /// </summary>
        /// <param name="ka"></param>
        /// <returns></returns>
        private long Sm4CalciRk(long ka)
        {
            byte[] a = new byte[4];
            byte[] b = new byte[4];
            PutULongToBe(ka, a, 0);
            b[0] = Sm4Sbox(a[0]);
            b[1] = Sm4Sbox(a[1]);
            b[2] = Sm4Sbox(a[2]);
            b[3] = Sm4Sbox(a[3]);
            long bb = GetULongByBe(b, 0);
            long rk = bb ^ Rotl(bb, 13) ^ Rotl(bb, 23);
            return rk;
        }

        /// <summary>
        /// 加密密钥
        /// </summary>
        /// <param name="SK"></param>
        /// <param name="key"></param>
        private void SetKey(long[] SK, byte[] key)
        {
            //加密密钥长度为 128 比特
            long[] MK = new long[4];
            int i = 0;
            MK[0] = GetULongByBe(key, 0);
            MK[1] = GetULongByBe(key, 4);
            MK[2] = GetULongByBe(key, 8);
            MK[3] = GetULongByBe(key, 12);

            long[] k = new long[36];
            //轮密钥生成方法
            k[0] = MK[0] ^ (long)FK[0];
            k[1] = MK[1] ^ (long)FK[1];
            k[2] = MK[2] ^ (long)FK[2];
            k[3] = MK[3] ^ (long)FK[3];
            for (; i < 32; i++)
            {
                k[(i + 4)] = (k[i] ^ Sm4CalciRk(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long)CK[i]));
                SK[i] = k[(i + 4)];
            }
        }
        /// <summary>
        /// 解密函数
        /// </summary>
        /// <param name="sk">轮密钥</param>
        /// <param name="input">输入分组的密文</param>
        /// <param name="output">输出的对应的分组明文</param>
        private void Sm4OneRound(long[] sk, byte[] input, byte[] output)
        {
            int i = 0;
            long[] ulbuf = new long[36];
            ulbuf[0] = GetULongByBe(input, 0);
            ulbuf[1] = GetULongByBe(input, 4);
            ulbuf[2] = GetULongByBe(input, 8);
            ulbuf[3] = GetULongByBe(input, 12);
            while (i < 32) //开始32轮解密 ,一次进行4轮,共计八次
            {
                ulbuf[(i + 4)] = Sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
                i++;
            }
            PutULongToBe(ulbuf[35], output, 0);
            PutULongToBe(ulbuf[34], output, 4);
            PutULongToBe(ulbuf[33], output, 8);
            PutULongToBe(ulbuf[32], output, 12);
        }

        /// <summary>
        /// 补足 16 进制字符串的 0 字符,返回不带 0x 的16进制字符串
        /// </summary>
        /// <param name="input"></param>
        /// <param name="mode">1表示加密,0表示解密</param>
        /// <returns></returns>
        private static byte[] Padding(byte[] input, int mode)
        {
            if (input == null)
            {
                return null;
            }

            byte[] ret;
            if (mode == 1)
            {
                int p = 16 - input.Length % 16;
                ret = new byte[input.Length + p];
                Array.Copy(input, 0, ret, 0, input.Length);
                for (int i = 0; i < p; i++)
                {
                    ret[input.Length + i] = (byte)p;
                }
            }
            else
            {
                int p = input[^1];
                ret = new byte[input.Length - p];
                Array.Copy(input, 0, ret, 0, input.Length - p);
            }
            return ret;
        }
        /// <summary>
        /// 设置加密的key
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="key"></param>
        public void SetKeyEnc(Sm4Context ctx, byte[] key)
        {
            ctx.Mode = 1;
            SetKey(ctx.Key, key);
        }
        /// <summary>
        /// 设置解密的key
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="key"></param>
        public void Sm4SetKeyDec(Sm4Context ctx, byte[] key)
        {
            ctx.Mode = 0;
            SetKey(ctx.Key, key);
            int i;
            for (i = 0; i < 16; i++)
            {
                Swap(ctx.Key, i);
            }
        }
        /// <summary>
        /// ECB
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public byte[] Sm4CryptEcb(Sm4Context ctx, byte[] input)
        {
            if (ctx.IsPadding && (ctx.Mode == 1))
            {
                input = Padding(input, 1);
            }

            int length = input.Length;
            byte[] bins = new byte[length];
            Array.Copy(input, 0, bins, 0, length);
            byte[] bous = new byte[length];
            for (int i = 0; length > 0; length -= 16, i++)
            {
                byte[] inBytes = new byte[16];
                byte[] outBytes = new byte[16];
                Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
                Sm4OneRound(ctx.Key, inBytes, outBytes);
                Array.Copy(outBytes, 0, bous, i * 16, length > 16 ? 16 : length);
            }

            if (ctx.IsPadding && ctx.Mode == 0)
            {
                bous = Padding(bous, 0);
            }
            return bous;
        }

        /// <summary>
        /// CBC
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="iv"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public byte[] Sm4CryptCbc(Sm4Context ctx, byte[] iv, byte[] input)
        {
            if (ctx.IsPadding && ctx.Mode == 1)
            {
                input = Padding(input, 1);
            }

            int length = input.Length;
            byte[] bins = new byte[length];
            Array.Copy(input, 0, bins, 0, length);
            List<byte> bousList = new List<byte>();

            int i;
            if (ctx.Mode == 1)
            {
                for (int j = 0; length > 0; length -= 16, j++)
                {
                    byte[] inBytes = new byte[16];
                    byte[] outBytes = new byte[16];
                    byte[] out1 = new byte[16];

                    Array.Copy(bins, j * 16, inBytes, 0, length > 16 ? 16 : length);
                    for (i = 0; i < 16; i++)
                    {
                        outBytes[i] = ((byte)(inBytes[i] ^ iv[i]));
                    }
                    Sm4OneRound(ctx.Key, outBytes, out1);
                    Array.Copy(out1, 0, iv, 0, 16);
                    for (int k = 0; k < 16; k++)
                    {
                        bousList.Add(out1[k]);
                    }
                }
            }
            else
            {
                byte[] temp = new byte[16];
                for (int j = 0; length > 0; length -= 16, j++)
                {
                    byte[] inBytes = new byte[16];
                    byte[] outBytes = new byte[16];
                    byte[] out1 = new byte[16];

                    Array.Copy(bins, j * 16, inBytes, 0, length > 16 ? 16 : length);
                    Array.Copy(inBytes, 0, temp, 0, 16);
                    Sm4OneRound(ctx.Key, inBytes, outBytes);
                    for (i = 0; i < 16; i++)
                    {
                        out1[i] = ((byte)(outBytes[i] ^ iv[i]));
                    }
                    Array.Copy(temp, 0, iv, 0, 16);
                    for (int k = 0; k < 16; k++)
                    {
                        bousList.Add(out1[k]);
                    }
                }

            }

            if (ctx.IsPadding && ctx.Mode == 0)
            {
                byte[] bous = Padding(bousList.ToArray(), 0);
                return bous;
            }
            else
            {
                return bousList.ToArray();
            }
        }
    }

    public class Sm4Context
    {
        public Sm4Context()
        {
            Mode = 1;
            IsPadding = true;
            Key = new long[32];
        }
        /// <summary>
        /// 1表示加密,0表示解密
        /// </summary>
        public int Mode;
        /// <summary>
        /// 密钥
        /// </summary>
        public long[] Key;
        /// <summary>
        /// 是否补足16进制字符串
        /// </summary>
        public bool IsPadding;
    }

    /// <summary>
    /// Sm4算法的调用  
    /// 对标国际DES算法
    /// </summary>
    public class Sm4Crypto
    {
        public Sm4Crypto()
        {
            Key = "98145489617106616498";
            //Iv = "0000000000000000";
            Iv = "";    
            HexString = false;
            CryptoMode = Sm4CryptoEnum.ECB;
        }
        /// <summary>
        /// 数据
        /// </summary>
        public string Data { get; set; }
        /// <summary>
        /// 秘钥
        /// </summary>
        public string Key { get; set; }
        /// <summary>
        /// 向量
        /// </summary>
        public string Iv { get; set; }
        /// <summary>
        /// 明文是否是十六进制
        /// </summary>
        public bool HexString { get; set; }

        /// <summary>
        /// 加密模式(默认ECB)
        /// </summary>
        public Sm4CryptoEnum CryptoMode { get; set; }

        /// <summary>
        /// 编码
        /// </summary>
        private static Encoding encoding = Encoding.UTF8;

        #region 加密

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public string Encrypt(Sm4Crypto entity)
        {
            return entity.CryptoMode == Sm4CryptoEnum.CBC ? EncryptCBC(entity) : EncryptECB(entity);
        }
        /// <summary>
        /// ECB加密
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static string EncryptECB(Sm4Crypto entity)
        {
            Sm4Context ctx = new Sm4Context
            {
                IsPadding = true
            };

            byte[] keyBytes = entity.HexString ? Hex.Decode(entity.Key) : encoding.GetBytes(entity.Key);

            SM4 sm4 = new SM4();
            sm4.SetKeyEnc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4CryptEcb(ctx, encoding.GetBytes(entity.Data));

            return encoding.GetString(Hex.Encode(encrypted));
        }
        /// <summary>
        /// CBC加密
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static string EncryptCBC(Sm4Crypto entity)
        {
            Sm4Context ctx = new Sm4Context
            {
                IsPadding = true
            };

            byte[] keyBytes = entity.HexString ? Hex.Decode(entity.Key) : encoding.GetBytes(entity.Key);
            byte[] ivBytes = entity.HexString ? Hex.Decode(entity.Iv) : encoding.GetBytes(entity.Iv);

            SM4 sm4 = new SM4();
            sm4.SetKeyEnc(ctx, keyBytes);
            byte[] encrypted = sm4.Sm4CryptCbc(ctx, ivBytes, encoding.GetBytes(entity.Data));

            return Convert.ToBase64String(encrypted);
        }
        #endregion


        #region 解密

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public object Decrypt(Sm4Crypto entity)
        {
            return entity.CryptoMode == Sm4CryptoEnum.CBC ? DecryptCBC(entity) : DecryptECB(entity);
        }
        /// <summary>
        ///  ECB解密
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static string DecryptECB(Sm4Crypto entity)
        {
            Sm4Context ctx = new Sm4Context
            {
                IsPadding = true,
                Mode = 0
            };

            byte[] keyBytes = entity.HexString ? Hex.Decode(entity.Key) : encoding.GetBytes(entity.Key);

            SM4 sm4 = new SM4();
            sm4.Sm4SetKeyDec(ctx, keyBytes);
            byte[] decrypted = sm4.Sm4CryptEcb(ctx, Hex.Decode(entity.Data));
            return encoding.GetString(decrypted);
        }
        /// <summary>
        /// CBC解密
        /// </summary>
        /// <param name="cipherText"></param>
        /// <returns></returns>
        public static string DecryptCBC(Sm4Crypto entity)
        {
            Sm4Context ctx = new Sm4Context
            {
                IsPadding = true,
                Mode = 0
            };

            byte[] keyBytes = entity.HexString ? Hex.Decode(entity.Key) : encoding.GetBytes(entity.Key);
            byte[] ivBytes = entity.HexString ? Hex.Decode(entity.Iv) : encoding.GetBytes(entity.Iv);

            SM4 sm4 = new SM4();
            sm4.Sm4SetKeyDec(ctx, keyBytes);
            byte[] decrypted = sm4.Sm4CryptCbc(ctx, ivBytes, Convert.FromBase64String(entity.Data));
            return encoding.GetString(decrypted);
        }
        #endregion

        /// <summary>
        /// 加密类型
        /// </summary>
        public enum Sm4CryptoEnum
        {
            /// <summary>
            /// ECB(电码本模式)
            /// </summary>
            [Description("ECB模式")]
            ECB = 0,
            /// <summary>
            /// CBC(密码分组链接模式)
            /// </summary>
            [Description("CBC模式")]
            CBC = 1
        }
    }
SM4

 https://www.cnblogs.com/guanshan/p/guan2022-5-5_002.html

 

posted @ 2019-12-18 16:49  bxzjzg  阅读(953)  评论(0编辑  收藏  举报