加密算法
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(); } }
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")); } }
转: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 }
多种加密算法:
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 }
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 } }
https://www.cnblogs.com/guanshan/p/guan2022-5-5_002.html