在 C# 工程中使用 OPENSSL

C# 工程中使用 OPENSSL

                      C# C++/CLI 的结合

 

建议读者范围:有一定的 C#2.0 C 或者 C++ 的语言基础,并且对 .Net 互操作性有一定的了解

源程序下载地址: http://files.cnblogs.com/sleepingwit/Certificate.rar

总述

         OPENSSL 是一个开源的广为使用的开源信息安全 SDK ,然而该 SDK 的官方版本是用 C/C++ 语言编写的,因此该 SDK 的程序不能直接在 .Net 的虚拟机上运行。笔者最近的一个项目需要生成 PKCS#12 *.pfx )的数字证书 , 并且要提供 PKCS#12 证书到 X509(*.cer) 证书的转换功能 . 由于 .NET 的功能不够完善等诸多原因,笔者不能够很好的使用 .Net Framework 2.0 来完成上述功能。 OPENSSL 可以实现笔者需要的功能,但是无法做到与我们的 C# 程序交互,经过多次试验,笔者最终采用了 C# C++/CLI 结合的方式来实现上述功能—— C# 程序生成 pfx 证书并提供 pfx cer 证书的转换。

 

C++/CLI

         .Net Framework 2.0 中,微软将 Manage C++ 升级为 C++/CLI ,我们且不关注该改进的优缺点,在这里我们只关心我们需要的功能。 C++/CLI 之所以能够满足我们的需要,是因为他提供了一个很好的源代码级的 .Net 与本机代码的互操作功能。 .Net 与本机互操作可以有三种方式 [2]

         1 )基于 P/Invoke DLL 互操作;

         2 COM 互操作;

         3 C++ Interop.

第三种 C++ Interop C++/CLI 独有的源代码级在操作,该机制允许我们在有源代码的情况下轻松的高性能的实现本机( Native )与托管( .Net )程序的交互。当然,尽管 C++ Interop 是三者中性能最高的,但是在没有源代码的情况下是无法使用这中机制的。对于笔者的这个项目, C++ Interop 刚好能满足笔者的需要。

 

项目实例

Native C++ 使用 OPENSSL 生成数字证书

         笔者使用的 OPENSSL 版本为 0.9.8 下载页面为 http://www.openssl.org/source/

下载并编译好 OPENSSL 后导入我们的 C++ 工程中,我们使用如下的代码来生成证书

 

具体的源代码请参考附件





Code


/*
**********************************************************************************************************



FileName: CertificateCLI.h



Author: Lu Wei



CreateDate:2008-07-19



Description: class defination of certificate implement



*********************************************************************************************************

*/









#pragma
once





using

namespace
System;




using

namespace
System::Runtime::InteropServices;








namespace
CertificateCLI {








//
C++/CLI class implement certificate operation






static

class
CertificateNative



{




private
:



CertificateNative(){}




private
:








//
Generate Priva key , in this project it used for generate CA private key






static

int
GeneratePrivateKey(BYTE
*
bpPriKey,
int

*
ipPriKeyLen);




//
Generate PKCS#12 certificate






static

int
CreateP12FromPrivateKey(BYTE
*
bpCAPriKey,
int
iCAPriKeyLen,
int
iValidDay, BYTE
*
bpP12,
int

*
ipP12Len,
char

*
pszP12Pwd,
char
*
pszName,
char

*
pszSubjectName,
char

*
pszOrganizational,
char

*
pszOrganizationName,
char

*
pszEmail,
char

*
pszCountryRegion );




//
Export PKCS#12 information to X509 certificate






static

int
ParseP12Certificate(
char

*
szP12Pwd,BYTE
*
bpP12,
int
iP12Len,BYTE
*
bpOutCert,
int

*
ipCertLen);








public
:




//
mid-interface with .NET lanuguage and native C++














static

int
GenerateP12Certificate(
char
*
strName,
char
*
strOrganizational,
char
*
strOrganizationName,
char
*
strEmail,
char
*
strCountryRegion,
char
*
strPassword,
char
*
strSavePath);




static

int
ExportX509Certificate(
char
*
strSource,
char
*
strSavePath,
char
*
strPassword);







};








//
.NET class that supply Interface used by .Net language






public

ref

class
CertificateNet



{




private
:



CertificateNet(){}




public
:




static
System::Int32 GenerateP12Certificate(System::String
^
strName, System::String
^
strOrganizational, System::String
^
strOrganizationName, System::String
^
strEmail, System::String
^
strCountryRegion,



System::String

^
strPassword, System::String
^
strSavePath);




static
System::Int32 ExportX509Certificate(System::String
^
strSource,System::String
^
strSavePath,System::String
^
strPassword);



};







}









大家可以看到我使用了两个类来封装需要的功能,一个是 native C++ 类,用来实现 native C++ openssl 的交互,另一个是 C++/CLI 类,用来实现 Native C++ .Net Framework 的交互。从下面这小段代码可以看出我是如何做的交互( CertificateCLI.cpp ):

    对了,就是这个 static_cast <char *> 。实现了我们需要的功能,不过笔者的交互比较简单,如果需要更深入交互,可能带来更多的问题,比如内存泄露之类的,更深入的研究需要读者参考 MSDN 。现在我们来看看怎么在 C# 中使用它。




Code


System::Int32 CertificateNet::ExportX509Certificate(System::String
^
strSource, System::String
^
strSavePath, System::String
^
strPassword)



{



IntPtr ipSource

=
Marshal::StringToHGlobalAnsi(strSource);



IntPtr ipSavePath

=
Marshal::StringToHGlobalAnsi(strSavePath);



IntPtr ipPassword

=
Marshal::StringToHGlobalAnsi(strPassword);




char

*
szSource
=
static_cast
<
char
*>
(ipSource.ToPointer());




char

*
szSavePath
=
static_cast
<
char
*>
(ipSavePath.ToPointer());




char

*
szPassword
=
static_cast
<
char
*>
(ipPassword.ToPointer());







System::Int32 status

=
CertificateNative::ExportX509Certificate(szSource,szSavePath,szPassword);




return
status;







}





 

C# 中使用封装后的代码

         .Net 的公共语言接口( CLI )使得我们很容易能够用 C# 来调用上面的代码

 

    




Code


///

<summary>





///
Export PKCS#12 file to X509 certificate




///

</summary>





///

<param name="strSource">
the pfx file path
</param>





///

<param name="strSavePath">
where to save exported certificate
</param>





///

<param name="strPassword">
password
</param>





///

<returns></returns>






public

static

int
ExportP12Certificate(
string
strSource,
string
strSavePath,
string
strPassword)



{




int
status
=
CertificateNet.ExportX509Certificate(strSource, strSavePath, strPassword);




return
status;



}





这段代码显示了我们是如何调用 C++/CLI 生成的 DLL 中的方法。至此,我们实现了在 C# 工程中使用 OPENSSL

 

结束

         在笔者的项目中,只使用很小的一部分 OPENSSL 代码,因此维护起来较为容易,对于更复杂的代码,需要读者更加仔细。因为在 Visual Studio 2005 中,当你在写 C# 程序时,调式程序是不可以进入到 C++/CLI DLL 的源代码中去的,从而使得使用笔者的方法来使用 OPENSSL 时必须尽可能更加严格的保证 C++/CLI 写的 DLL 的不会出错。

附录

         [1] OPENSSL 的官方网站是 http://www.openssl.org/ ,如果读者想要进一步了解 OPENSSL 可以去访问,不过上面的资料较少, http://www.infosecurity.org.cn/forum/index.php 中国信息安全组织论坛上面有很多不错的资料,推荐给感兴趣的读者。笔者的项目中只用到了 OPENSSL 中很小的一个功能,冰山一角不足以窥全貌,有不足之处,望大家海涵。

         [2] .Net 互操作性的相关资料可以参考 MSDN, 笔者的资料来源于李建忠老师的 C++/CLI 视频讲座—— Visual C++ 2005 系列教 参考课程: VC++ 2005(9):非托管互操作    

[3] 由于博客园的文件大小限制,笔者无法提供编译好的 LIB 文件( OPENSSL ),不过所有的代码都在附件里面,笔者使用的是 Visual Studio 2005 SP1 编译 C++ C#


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值