Visual Studio C++ RSA加解密方案

本文的应用场景是,Unity c#向vc++ 工程传递用户名和密码,可能会面临的安全性问题:

假如第三方对dll进行替换,c#的账号密码直接往下传,可能导致用户密码泄露的风险。

针对此种情况,对用户名和密码在C#层进行加密,并在C++ dll库中进行解密,从而在一定程度上规避此风险。

C++ RSA加解密方案

  1. 支持.net的RSACryptoServiceProvider

  2. cryto++ library

  3. openssl

第一种方案,C++RSA 跟C#版的RSA配套,用起来极为方便,但是依赖.net架构。需要依赖.net环境,将工程设置为支持clr。

后两种方案,是第三方集成库。当前使用较为广泛的方法是openssl,下面着重介绍openssl在RSA上的使用。

Openssl编译配置

按顺序执行下列命令

d:\openssl-1.0.1e> perl Configure VC-WIN32 no-asm –prefix=d:\openssl_lib (存放编译后的库文文件目录)

d:\openssl-1.0.1e> ms\do_ms
d:\openssl-1.0.1e> nmake -f ms\ntdll.mak (编译动态库)
d:\openssl-1.0.1e> nmake -f ms\nt.mak (编译静态库)
装载openssl到指定的目录d:\opensll_lib中

d:\openssl-1.0.1e> nmake -f ms\ntdll.mak install

d:\openssl-1.0.1e> nmake -f ms\nt.mak install
(b)继续编译, 提示错误:

cryptlib.obj : error LNK2001: unresolved external symbol _OPENSSL_ia32_cpuid

out32dll/libeay32.dll : fatal error LNK1120: 1 unresolved externals

解决办法: 修改do_ms文件如下:

perl util/mkfiles.pl >MINFO
perl util/mk1mf.pl debug no-asm VC-WIN32 >ms/nt.mak
perl util/mk1mf.pl debug dll no-asm VC-WIN32 >ms/ntdll.mak
perl util/mk1mf.pl debug no-asm VC-CE >ms/ce.mak
perl util/mk1mf.pl debug dll no-asm VC-CE >ms/cedll.mak
perl util/mkdef.pl 32 libeay > ms/libeay32.def
perl util/mkdef.pl 32 ssleay > ms/ssleay32.def

集成OpenSSL

这里写图片描述

打开Project Property面板:

  1. Configuration Properties——VC++ Directories——Include Directories新增”d:\openssl_lib\include”(存放编译后的库文件的目录中);

  2. VC++ Directories ——”Library files”选择中新增目录”d:\openssl_lib\lib”;

  3. Configuration Properties ——Linker——Input——Additional Dependencies,添加libeay32.lib 和ssleay32.lib两个库即可。

Openssl生成公私密钥和证书

安装openssl,cmd执行openssl

OpenSSL>genrsa -out rsa_private_key.pem 1024

生成的pem文件如下:

-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQDJsiBpRxfPFRh9DbmWizZbm5/HKxhpOOQMlmGo2LIuVWxXuzYj

TyQ9Jfn+zDfIGG3NLkAHrpcW0U8figjCXb/dXptc/MabgwPIP1jL1uqTLgIYeVsT

Jm6vEzd7c/t81VaOJDjFkQlrlqdOsH5JnAlGtqITqXHSimbgBDUjtJW+qwIDAQAB

AoGAICuGGeSZ+pCd0ExhHo7jw6bFzEmmYhoN3agauYiemt9LIY8dqnIUEKC/CBHg

j8y9rq1CzzbcqGoIGbq1fPLhCBAn1dkRePKKqSd1BM99oVwDP2YYBqzaUtPz1TYN

q0Q9QqKuQgkWkPC+7QugnDzIuzlqO9+/wdugLd2UateZZqECQQD4qtEsMPrSu9g8

yTjJOnyChYhQuUXbLalFlqSRnHWM7eIxqNkMjhPoK3sxGWWMNT410kNhxgWUZnMT

bbXjO2E7AkEAz6S5JjIY/GhFxer9vxY3yjUW7Agtnk0zyi70RpbuvttdNjUxeXiG

f/q3ilNJE2eWt2PaICb/c32PdCO5P5RBUQJBANZnmiErPikTM/f9W8wNdKupbQaF

KNk5fpj0sYKnT6equHwu5K5xlnJ5gyeriSYiBjirydN0xPzWdORMlSaO3V8CQCob

c1hljF+THaMXFkHr1YBx56YRun6BlWEIyIyQCvY1Md/ORawmXtARHas1XHpM5Wln

HFKs1dyrt62LmQNloyECQAZEeNq5AyRGRq+oAPjMlGEUrKR/7w3zXdCO2nyCYtQX

YkE4+ZBUeKBFgPEoHGUqY+yOD9xIg5d6rbf71Hh2kx0=

-----END RSA PRIVATE KEY-----

2)把RSA私钥转换成PKCS8格式

OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

writing RSA key

OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM –nocrypt

Enter Encryption Password:

Verifying - Enter Encryption Password:

-----BEGIN ENCRYPTED PRIVATE KEY-----

MIICoTAbBgkqhkiG9w0BBQMwDgQIsz6q/2JpXSACAggABIICgHPkfKkuH+Dn18q0

k0xUIDmnKvApJlXlaRF1jo4wF1hbO0RThwr2r//AlScy5yoEeUMyhh5ae4yEzT7r

U3nGYcnVV64AkwV/JMthpYNVPpb4OL8xbOyGbmU3UigoAhLo4/bDkiGDs9ZTRyDW

p0QyOyFJZ0L7NhvWmkYsDUAahY/xjYQy3Cghk5pvhSQjhbAu3yaF3UtJNZhqGZCN

/p7nrwG9Vt0Ys6nzUC4PQFafyZzdfl4l9f0WlCwWSRNy+s3hxLavJySt6ycGAbNL

ue3lGpnVPLCgwh5p5I3w9Aym96hDsAvMdqXg92mbeO22Tqz8MccVQqIYO+HpPXn7

uH3aYx4sxjV/p+wUK/XlNL/XEoyw+WVJ4wxBBFGtZvk5lurCODdgFsZbfzGWO9gW

5Y2kXp4FK9iVzhiS1YI5fn6yaKAUPB+jtj5xSrmtxhV7Q7N5YuJeFsGhXNpuQKxy

XWyEbU2gbsuI0LYAr+r7M5LWSouYLne3NDfB1Op2oFwoz9j+p+drEgoByDWZQMo6

ay4T928LdHQFgKYajtBkch2Z5lNwwUdaZwe8AalJVTM2otDE9QSpiOq4Sjmyu5Od

Kt3SesMEoCQSJ2SM3dqMqEIBf/YDtL4juFId0uffNW2BcpVrq5muJ0+xTtWmC75Z

SsULmCwWzYTKe+OiG8r/Z7DVXY30onWfJnPJEGl3vyMGDDgacYQrN3qGMUGoJxzL

MeEdt9xfTlpY4XO/DIUAPEWJtLN0XvHSKlqMtk/m124ugugLzi4SmWusYDTs1rS3

MjpnNpSFYw12jBVcM95PCtuLmP7Ts9LXc5zbtpYIv8IP/S5RlasSQpCNfRLlADbB

d6pH+PA=

-----END ENCRYPTED PRIVATE KEY-----

3) 生成RSA公钥

输入命令rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem,

-----BEGIN PUBLIC KEY-----

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJsiBpRxfPFRh9DbmWizZbm5/H

KxhpOOQMlmGo2LIuVWxXuzYjTyQ9Jfn+zDfIGG3NLkAHrpcW0U8figjCXb/dXptc

/MabgwPIP1jL1uqTLgIYeVsTJm6vEzd7c/t81VaOJDjFkQlrlqdOsH5JnAlGtqIT

qXHSimbgBDUjtJW+qwIDAQAB

-----END PUBLIC KEY-----

创建证书请求

openssl req -new -out cert.csr -key rsa_private_key.pem

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Country Name (2 letter code) [AU]:86

State or Province Name (full name) [Some-State]:Guangdong

Locality Name (eg, city) []:Shenzhen

Organization Name (eg, company) [Internet Widgits Pty Ltd]:Xfiction

Organizational Unit Name (eg, section) []:K

Common Name (eg, YOUR name) []:fiction

Email Address []:xfiction@gmail.com

Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:xfiction8989

An optional company name []:xfiction

这里写图片描述

自签署根证书(自签署,就是不通过CA认证中心自行进行证书签名,这里用是x509)

openssl x509 -req -in cert.csr -out public.der -outform der -signkey rsa_private_key.pem -days 3650

Signature ok

subject=/C=86/ST=Guangdong/L=Shenzhen/O=Xfiction/OU=K/CN=fiction/emailAddress=xfiction@gmail.com

Getting Private key

XML到PEM的转换:

由于C#的RSACryptoServiceProvider所使用的是xml格式,openssl使用pem格式的秘钥。需要对秘钥进行转换。

可以直接通过线上转换工具RSA Key Converter(https://superdry.apphb.com/tools/online-rsa-key-converter)进行转换。

附上代码

RSAEncryptService rasService = new RSAEncryptService();
string psdEncrpted = rasService.RSAEncryptStr(pwd); 



RSA* pPrivateRSA = createRSAWithMem(strPrivateKeyPerm);
//string strPubEncode = "ZfBe7UOZzjdoKsnf90vQe47klfj9+EmmlBUA86IMhFIpceKB0NxLeGSivw0JUk7s9QN+CFPIRTkr1Z7gXgniGNlkbuZzZcIoao1kWkvRGM81KTPt0YS8v/2RAE83re/c6zby4fGmELx9S+t8HdiUovDQaKZgz2ycgomfCxyI7mw=";
string strPubEncode = pwd;
string strPrivateDecode;

char strOrgData[1024] = { 0 };
Private_Decrypt(pPrivateRSA, strPubEncode, strPrivateDecode);

const char* decryptPwd = strPrivateDecode.c_str();

C#和c++代码见附件

参考文章

http://www.jianshu.com/p/faefcc58c79b

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值