C#调用C++生成的DLL——DES加解密工具

0x00 密码学

最近密码学课留了作业,要写一个DES加解密工具,原理部分给了可以参考的C代码,剩下的就需要自己写了。想着用MFC写界面自己不会,于是就用C#写界面。遇到很多问题,写下来做个记录。

0x01 基本代码

基本代码部分比较简单,在控制台下测试了拿到结果符合要求,于是就着手搜索怎么用C#调用C++的代码了。

其中遇到一个问题,加密的结果我是用16进制存在txt中的,于是会导致单独解密时读入密文遇到困难。选择了一个比较简便的方法,在每个16进制之间用空格隔开就可以了,当然为了更好的效果你也可以写一个字符串的parse等等。

0x02 代码封装

查了一些资料后,发现c#无法直接调用CPP文件,这让我这个不懂C#的人有些退缩,不过为了简化界面的写法,这能用C#写了。
最终查阅到的方案是将CPP和头文件做成动态库供C#调用,为了简化大多步骤,只做了两个接口函数。

extern "C" _declspec(dllexport) int __stdcall   Encrypt(char* pfp, char*cfp, char* kfp);
extern "C" _declspec(dllexport) int __stdcall Decrypt(char* pfp, char*cfp, char* kfp);

几乎将所有功能代码都封装在dll里面了,只留出来三个传递文件路径的参数,便于获取明文文件等路径。

0x03 封装细节

在封装中步骤还是比较简单的,将原来写好的控制台程序抽象为两个函数,做好接口即可。这里参考了songyi160的博客。
在VS2015中用C++创建动态库并用C#调用
在VS2015中用C++创建DLL并用C#调用且同时实现对DLL的调试
两篇博文给出了两种解决方案下的封装调用办法。
在写程序的过程中,先尝试了第一种办法,遇到了一些麻烦,可能是char*类型在c++和c#之间传递有困难,一直有问题。于是换成了第二种。
CPP:

int __stdcall Encrypt(char* pfp, char*cfp, char* kfp){
encrypt(pfp, cfp, kfp);
return 0;
}
 int __stdcall Decrypt(char* pfp, char*cfp, char* kfp){
decrypt(pfp, cfp, kfp);
return 0;
}

.H:

extern "C" _declspec(dllexport) int __stdcall Encrypt(char* pfp, char*cfp, char* kfp);
extern "C" _declspec(dllexport) int __stdcall Decrypt(char* pfp, char*cfp, char* kfp);

def文件:

LIBRARY "CPPDLL"

EXPORTS

Encrypt @ 1
Decrypt @ 2

上面的三个示例就是封装之后的接口。

0x04 C#调用

对于3中的步骤,不同的方法有不同的调用方法,这里以第二种为例子。
当然第二种也解决了C#调用DLL需要传递char*参数的问题。

[DllImport(@"CPPDLL.dll", EntryPoint = "Encrypt", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]//, CallingConvention = CallingConvention.Cdecl)]
extern static int Encrypt(StringBuilder pfp, StringBuilder cfp, StringBuilder kfp);

[DllImport(@"CPPDLL.dll", EntryPoint = "Decrypt", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
extern static int Decrypt(StringBuilder pfp, StringBuilder cfp, StringBuilder kfp);

其中需要注意的是,相对路径是以可执行文件所在目录为准。
可以看出在C++中char*的的接口我们传入参数时使用的StringBuilder,理论上使用String也可以。关于传出参数和返回值的接口引用可以自行百度或谷歌。

0x05 界面

界面就直接用C#拖放,添加代码即可,难度很低。(给一个渣界面参考)

xmsec

Updated At: Author:xmsec
Chief Water dispenser Manager of Lancet, delivering but striving.
Github
comments powered by Disqus