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;
begin
aClass := CoTestClass.Create;
aClass.YourProcedure('参数');
end;
b.不需生成tlb文件,仿照调用Excel的方式。代码如下:
var aClass: Variant;
begin
aClass:= 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(