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