700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Delphi调用C#的加密解密(Base64/AES/DES/MD5可扩充)

Delphi调用C#的加密解密(Base64/AES/DES/MD5可扩充)

时间:2023-07-02 09:27:43

相关推荐

Delphi调用C#的加密解密(Base64/AES/DES/MD5可扩充)

1. 背景:

近期,由于工作上与第三方公司传输数据的时候需要采取数据加密,但是我们采用的时较低版本的Delphi 6;由于加密算法等差异,导致在传输的加密数据第三方一致解析不了(具体问题表现为base64加密中文乱码,AES加密方式的运算模式Mode,填充模式padding);限于代码的管理规范不能使用加密的插件,且网上搜索相关的delphi加密资料少之又少;故决定采取Visual Studio来写加密解密算法的动态库,由Delphi调用。

2. 行动:

(1)C#端的代码实现,首先在vs中创建一个“类库”项目TestDll:

using System.Runtime.InteropServices;namespace TestDll{public interface ITestClass{void YourProcedure(stirng param1);}[ClassInterface(ClassInterfaceType.None)]public classTestClass:ITestClass{public void YourProcedure(stirng param1);{ //自己的代码 }} }

(2)C#端的配置实现:

a.选中该项目右击,选择【属性】,然后在【应用程序】中选择【程序集信息】如图:

b.同样是选中该项目右击,选择【属性】,然后在【生成】中选择【为COM互操作注册】保存,如图:

c.接下来是dll的注册,可以采用cmd命令框,也可以采用Bat文件:

(3)接下来是Delphi端的实现,Delphi程序调用此Dll方式有两种:

a.打开vs自带的工具“Visual Studio命令提示”,输入 TlbExp 路径\TestClass.dll 得到一个TestClass.tlb 文件(这个文件其实在编译的时候就会生成,可不做)。打开Delphi,选择“Project”–“import type library”找到刚才的TestClass.tlb,点击 CreateUnit,向delphi中引入一个com接口。

delphi 调用代码如下:

var aClass:TestClass;beginaClass := CoTestClass.Create;aClass.YourProcedure('参数');end;

b.不需生成tlb文件,仿照调用Excel的方式。代码如下:

var aClass: Variant;beginaClass:= CreateOleObject('TestDll.TestClass');aClass.YourProcedure('参数');end;

以上两种方法都可以调用成功,其中调用regasm.exe向系统注册dll是必需的。第一种方法需要生成tlb文件,并引入delphi中,操作繁琐,但可以看到接口的定义。第二种方法操作简单,但看不到接口的定义。

AES加解密code:

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices;using System.Security.Cryptography;using System.Text;using System.Threading.Tasks;namespace Encryption{public interface IAES{string AesEncrypt(string value, string key, int mode, int paddingMode, string iv = "");string AesDecrypt(string value, string key, int mode, int paddingMode, string iv = "");}[ClassInterface(ClassInterfaceType.None)]public class AES : IAES{/// <summary>/// AES加密/// </summary>/// <param name="value">待加密的字符串</param>/// <param name="key">秘钥(16,24,32位)</param>/// <param name="mode">运算模式(CBC = 1,ECB = 2,OFB = 3,CFB = 4,CTS = 5)</param>/// <param name="paddingMode">填充模式(None = 1,PKCS7 = 2,Zeros = 3,ANSIX923 = 4,ISO10126 = 5)/// <param name="iv">初始化向量(至少16位)</param>/// <returns>加密后的字符串</returns>public string AesEncrypt(string value, string key, int mode, int paddingMode, string iv = ""){if (string.IsNullOrEmpty(value)) return string.Empty;if (key == null) throw new Exception("未将对象引用设置到对象的实例。");if (key.Length < 16) throw new Exception("指定的密钥长度不能少于16位。");if (key.Length > 32) throw new Exception("指定的密钥长度不能多于32位。");if (key.Length != 16 && key.Length != 24 && key.Length != 32) throw new Exception("指定的密钥长度不明确。");if (!string.IsNullOrEmpty(iv)){if (iv.Length < 16) throw new Exception("指定的向量长度不能少于16位。");}var _keyByte = Encoding.UTF8.GetBytes(key);var _valueByte = Encoding.UTF8.GetBytes(value);using (var aes = new RijndaelManaged()){aes.IV = !string.IsNullOrEmpty(iv) ? Encoding.UTF8.GetBytes(iv) : Encoding.UTF8.GetBytes(key.Substring(0, 16));aes.Key = _keyByte;switch(mode) {case 1:aes.Mode = CipherMode.CBC;break;case 2:aes.Mode = CipherMode.ECB;break;case 3:aes.Mode = CipherMode.OFB;break;case 4:aes.Mode = CipherMode.CFB;break;case 5:aes.Mode = CipherMode.CTS;break;default:aes.Mode = CipherMode.CBC;break;}switch (paddingMode){case 1:aes.Padding = PaddingMode.None;break;case 2:aes.Padding = PaddingMode.PKCS7;break;case 3:aes.Padding = PaddingMode.Zeros;break;case 4:aes.Padding = PaddingMode.ANSIX923;break;case 5:aes.Padding = PaddingMode.ISO10126;break;default:aes.Padding = PaddingMode.PKCS7;break;}var cryptoTransform = aes.CreateEncryptor();var resultArray = cryptoTransform.TransformFinalBlock(_valueByte, 0, _valueByte.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);}}/// <summary>/// AES解密/// </summary>/// <param name="value">待解密的字符串</param>/// <param name="key">秘钥(16,24,32位)</param>/// <param name="mode">运算模式(CBC = 1,ECB = 2,OFB = 3,CFB = 4,CTS = 5)</param>/// <param name="paddingMode">填充模式(None = 1,PKCS7 = 2,Zeros = 3,ANSIX923 = 4,ISO10126 = 5)/// <param name="iv">初始化向量(至少16位)</param>/// <returns>解密后的字符串</returns>public string AesDecrypt(string value, string key, int mode, int paddingMode, string iv = ""){if (string.IsNullOrEmpty(value)) return string.Empty;if (key == null) throw new Exception("未将对象引用设置到对象的实例。");if (key.Length < 16) throw new Exception("指定的密钥长度不能少于16位。");if (key.Length > 32) throw new Exception("指定的密钥长度不能多于32位。");if (key.Length != 16 && key.Length != 24 && key.Length != 32) throw new Exception("指定的密钥长度不明确。");if (!string.IsNullOrEmpty(iv)){if (iv.Length < 16) throw new Exception("指定的向量长度不能少于16位。");}var _keyByte = Encoding.UTF8.GetBytes(key);var _valueByte = Convert.FromBase64String(value);using (var aes = new RijndaelManaged()){aes.IV = !string.IsNullOrEmpty(iv) ? Encoding.UTF8.GetBytes(iv) : Encoding.UTF8.GetBytes(key.Substring(0, 16));aes.Key = _keyByte;switch (mode){case 1:aes.Mode = CipherMode.CBC;break;case 2:aes.Mode = CipherMode.ECB;break;case 3:aes.Mode = CipherMode.OFB;break;case 4:aes.Mode = CipherMode.CFB;break;case 5:aes.Mode = CipherMode.CTS;break;default:aes.Mode = CipherMode.CBC;break;}switch (paddingMode){case 1:aes.Padding = PaddingMode.None;break;case 2:aes.Padding = PaddingMode.PKCS7;break;case 3:aes.Padding = PaddingMode.Zeros;break;case 4:aes.Padding = PaddingMode.ANSIX923;break;case 5:aes.Padding = PaddingMode.ISO10126;break;default:aes.Padding = PaddingMode.PKCS7;break;} var cryptoTransform = aes.CreateDecryptor();var resultArray = cryptoTransform.TransformFinalBlock(_valueByte, 0, _valueByte.Length);return Encoding.UTF8.GetString(resultArray);}}}}

Base64加解密code:

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices;using System.Text;using System.Threading.Tasks;namespace Encryption{public interface IBase64{string UnBase64String(string value);string ToBase64String(string value);}[ClassInterface(ClassInterfaceType.None)]public class Base64 : IBase64{ public string UnBase64String(string value){if (value == null || value == ""){return "";}byte[] bytes = Convert.FromBase64String(value);return Encoding.UTF8.GetString(bytes);}public string ToBase64String(string value){if (value == null || value == ""){return "";}byte[] bytes = Encoding.UTF8.GetBytes(value);return Convert.ToBase64String(bytes);}}}

DES加解密code:

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Threading.Tasks;namespace Encryption{interface IDES{string Encrypt(string entryStr, string key, int mode, int paddingMode);string Decrypt(string entryStr, string key, int mode, int paddingMode);}public class DES:IDES{/// <summary>/// DES 加密/// </summary>/// <param name="entryStr">待加密字符串</param>/// <param name="key">8位16进制密钥字符串</param>/// <param name="mode">运算模式(CBC = 1,ECB = 2,OFB = 3,CFB = 4,CTS = 5)</param>/// <param name="paddingMode">填充模式(None = 1,PKCS7 = 2,Zeros = 3,ANSIX923 = 4,ISO10126 = 5)/// <returns></returns>public string Encrypt(string entryStr, string key, int mode, int paddingMode){DESCryptoServiceProvider des = new DESCryptoServiceProvider();switch (mode){case 1:des.Mode = CipherMode.CBC;break;case 2:des.Mode = CipherMode.ECB;break;case 3:des.Mode = CipherMode.OFB;break;case 4:des.Mode = CipherMode.CFB;break;case 5:des.Mode = CipherMode.CTS;break;default:des.Mode = CipherMode.ECB;break;}switch (paddingMode){case 1:des.Padding = PaddingMode.None;break;case 2:des.Padding = PaddingMode.PKCS7;break;case 3:des.Padding = PaddingMode.Zeros;break;case 4:des.Padding = PaddingMode.ANSIX923;break;case 5:des.Padding = PaddingMode.ISO10126;break;default:des.Padding = PaddingMode.Zeros;break;}var _keyByte = Encoding.UTF8.GetBytes(key);var _valueByte = Encoding.UTF8.GetBytes(entryStr);des.Key = _keyByte;using (MemoryStream ms = new MemoryStream()){byte[] bytes = _valueByte;using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)){cs.Write(bytes, 0, bytes.Count());cs.FlushFinalBlock();}return System.Text.Encoding.Default.GetString(ms.ToArray()); }}/// <summary>/// DES 解密 /// </summary>/// <param name="bytes">待解密加密的字符串</param>/// <param name="key">8位16进制密钥字符串</param>/// <param name="mode">运算模式(CBC = 1,ECB = 2,OFB = 3,CFB = 4,CTS = 5)</param>/// <param name="paddingMode">填充模式(None = 1,PKCS7 = 2,Zeros = 3,ANSIX923 = 4,ISO10126 = 5)/// <returns></returns>public string Decrypt(string entryStr, string key, int mode, int paddingMode){DESCryptoServiceProvider des = new DESCryptoServiceProvider();switch (mode){case 1:des.Mode = CipherMode.CBC;break;case 2:des.Mode = CipherMode.ECB;break;case 3:des.Mode = CipherMode.OFB;break;case 4:des.Mode = CipherMode.CFB;break;case 5:des.Mode = CipherMode.CTS;break;default:des.Mode = CipherMode.ECB;break;}switch (paddingMode){case 1:des.Padding = PaddingMode.None;break;case 2:des.Padding = PaddingMode.PKCS7;break;case 3:des.Padding = PaddingMode.Zeros;break;case 4:des.Padding = PaddingMode.ANSIX923;break;case 5:des.Padding = PaddingMode.ISO10126;break;default:des.Padding = PaddingMode.Zeros;break;}var _keyByte = Encoding.UTF8.GetBytes(key);var _valueByte = Encoding.UTF8.GetBytes(entryStr);des.Key = _keyByte;using (MemoryStream ms = new MemoryStream()){using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)){cs.Write(_valueByte, 0, _valueByte.Count());cs.FlushFinalBlock();}return System.Text.Encoding.Default.GetString(ms.ToArray()); }}}}

MD5加密code:

using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Threading.Tasks;namespace Encryption{interface IMD5Encryt{string GetMd5Str(string ConvertString);string UserMd5(string str);}class MD5Encryt : IMD5Encryt{/// <summary>/// MD5 16位加密/// </summary>/// <param name="ConvertString"></param>/// <returns></returns>public string GetMd5Str(string ConvertString){MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();string t2 = BitConverter.ToString(puteHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);t2 = t2.Replace("-", "");return t2;}/// <summary>/// MD532位加密/// </summary>/// <param name="str"></param>/// <returns></returns>public string UserMd5(string str){string cl = str;string pwd = "";MD5 md5 = MD5.Create();//实例化一个md5对像// 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择byte[] s = puteHash(Encoding.UTF8.GetBytes(cl));// 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得for (int i = 0; i < s.Length; i++){// 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符 pwd = pwd + s[i].ToString("X");}return pwd;}}}

3. 测试:

(1)Delphi端调用C#的base64加密:

(2)Delphi端调用C#的base64解密:

4.报错与解决

(1)按照配置生成了,也regasm注册成功了,但是在调用的时候会报错:

原因:虽然说我们用命令行注册时提示成功,但是我们所进入的Framework有问题,如图文件夹下面有两个版本的Framework,请选择和自己计算机位数相同的版本,或者说可以逐个尝试一下。

另外:选择regasm所在的目录也要根据vs输出的Framework版本一致,例如我的是4.5,那么需要进入v4.0.30319:

输出的目标框架在属性中可以看到:

5.感谢:

感谢您看到了这儿,请收下测试通过的源码(包含Base64/AES/DES的加密解密(可指定运算模式Mode,填充模式Padding,向量V),MD5的加密):

链接:/s/1CLnwtGOFf0oGzCvyNef0YA 密码:hyuj

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。