轉自:http://blog.chinaunix.net/uid-9543173-id-3921143.html
利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
1. 利用RSA安全传输AES生成密钥所需的Seed(32字节)
2. 利用AES_encrypt/AES_decrypt对Socket上面的业务数据进行AES加密/解密
理论上只需要AES就能保证全部流程,但由于AES加密所需要的AES-KEY是一个结构。 这个一个结构,如果通过网络进行传输,就需要对它进行网络编码,OpenSSL里面没有现成的API
所以就引入RSA来完成首次安全的传输,保证Seed不会被窃听。同样,只使用RSA也能完成全部流程,但由于RSA的处理效率比AES低,所以在业务数据传输加密上还是使用AES
下面的代码包含了上述传输加密流程所需的所有步骤(OpenSSL部分)
在实际的Socket应用开发时,需要将这些步骤插入到Client/Server网络通信的特定阶段
所需的OpenSSL主要的API及功能描述
1. RSA_generate_key() 随机生成一个RSA密钥对,供RSA加密/解密使用
2. i2d_RSAPublicKey() 将RSA密钥对里面的公钥提出到一个BUF,用于网络传输给对方
3. d2i_RSAPublicKey() 将从网络传过来的公钥信息生成一个加密使用的RSA(它里面只有公钥)
4. RSA_public_encrypt() 使用RSA的公钥对数据进行加密
5. RSA_private_decrypt() 使用RSA的私钥对数据进行解密
6. AES_set_encrypt_key() 根据Seed生成AES密钥对中的加密密钥
7. AES_set_decrypt_key() 根据Seed生成AES密钥对中的解密密钥
8. AES_encrypt() 使用AES加密密钥对数据进行加密
9. AES_decrypt() 使用AES解密密钥对数据进行解密
一个典型的安全Socket的建立流程, 其实就是如何将Server随机Seed安全发给Client
C: Client S:Server
C: RSA_generate_key() --> RSAKey --> i2d_RSAPublicKey(RSAKey) --> RSAPublicKey
C: Send(RSAPublicKey) TO Server
S: Recv() --> RSAPublicKey --> d2i_RSAPublicKey(RSAPublicKey) --> RSAKey
S: Rand() --> Seed --> RSA_public_encrypt(RSAKey, Seed) --> EncryptedSeed
S: Send(EncryptedSeed) TO Client
C: Recv() --> EncryptedSeed --> RSA_private_decrypt(RSAKey, EncryptedSeed) --> Seed
--- 到此, Client和Server已经完成完成传输Seed的处理
--- 后面的流程是它们怎样使用这个Seed来进行业务数据的安全传输
C: AES_set_encrypt_key(Seed) --> AESEncryptKey
C: AES_set_decrypt_key(Seed) --> AESDecryptKey
S: AES_set_encrypt_key(Seed) --> AESEncryptKey
S: AES_set_decrypt_key(Seed) --> AESDecryptKey
--- Client传输数据给Server
C: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> Server
S: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data
--- Server传输数据给Client
S: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> Client
C: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data
流程图如下:
aaarticlea/png;base64,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" alt="" />
相关的代码实现如下:
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/aes.h> int main()
{
// 1. 产生RSA密钥对
// 产生512字节公钥指数为RSA_F4的密钥对,公钥指数有RSA_F4和RSA_3两种
// 我不清楚它们的区别,就随便选定RSA_F4
// 可以使用RSA_print_fp()看看RSA里面的东西
RSA *ClientRsa = RSA_generate_key(, RSA_F4, NULL, NULL); // ---------
// 2. 从RSA结构中提取公钥到BUFF,以便将它传输给对方
// 512位的RSA其公钥提出出来长度是74字节,而私钥提取出来有超过300字节
// 为保险起见,建议给它们预留一个512字节的空间
unsigned char PublicKey[];
unsigned char *PKey = PublicKey; // 注意这个指针不是多余,是特意要这样做的,
int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PKey); // 不能采用下面的方法,因为i2d_RSAPublicKey()会修改PublicKey的值
// 所以要引入PKey,让它作为替死鬼
// unsigned char *PublicKey = (unsigned char *)malloc(512);
// int PublicKeyLen = i2d_RSAPublicKey(ClientRsa, &PublicKey); // 逐个字节打印PublicKey信息
printf("PublicKeyBuff, Len=%d\n", PublicKeyLen);
for (int i=; i<PublicKeyLen; i++)
{
printf("0x%02x, ", *(PublicKey+i));
}
printf("\n"); // ---------
// 3. 跟据上面提出的公钥信息PublicKey构造一个新RSA密钥(这个密钥结构只有公钥信息)
PKey = PublicKey;
RSA *EncryptRsa = d2i_RSAPublicKey(NULL, (const unsigned char**)&PKey, PublicKeyLen); // ---------
// 4. 使用EncryptRsa加密数据,再使用ClientRsa解密数据
// 注意, RSA加密/解密的数据长度是有限制,例如512位的RSA就只能最多能加密解密64字节的数据
// 如果采用RSA_NO_PADDING加密方式,512位的RSA就只能加密长度等于64的数据
// 这个长度可以使用RSA_size()来获得
unsigned char InBuff[], OutBuff[]; strcpy((char *)InBuff, "1234567890abcdefghiklmnopqrstuvwxyz.");
RSA_public_encrypt(, (const unsigned char*)InBuff, OutBuff, EncryptRsa, RSA_NO_PADDING); // 加密 memset(InBuff, , sizeof(InBuff));
RSA_private_decrypt(, (const unsigned char*)OutBuff, InBuff, ClientRsa, RSA_NO_PADDING); // 解密
printf("RSADecrypt OK: %s \n", InBuff); // ----------
// 5. 利用随机32字节Seed来产生256位的AES密钥对
unsigned char Seed[]; // 可以采用Rand()等方法来构造随机信息
AES_KEY AESEncryptKey, AESDecryptKey;
AES_set_encrypt_key(Seed, , &AESEncryptKey);
AES_set_decrypt_key(Seed, , &AESDecryptKey); // ----------
// 6. 使用AES密钥对来加密/解密数据
// 注意,256位的AES密钥只能加密/解密16字节长的数据
strcpy((char *)InBuff, "a1b2c3d4e5f6g7h8?");
AES_encrypt(InBuff, OutBuff, &AESEncryptKey); memset(InBuff, , sizeof(InBuff));
AES_decrypt(OutBuff, InBuff, &AESDecryptKey);
printf("AESDecrypt OK: %s \n", InBuff); // ----------
// 7. 谨记要释放RSA结构
RSA_free(ClientRsa);
RSA_free(EncryptRsa); return();
}
利用OpenSSL库对Socket传输进行安全加密(RSA+AES)的更多相关文章
-
linux以下C 利用openssl的AES库加密,解密
OpenSSL提供了AES加解密算法的API const char *AES_options(void); AES算法状态,是所有支持或者是部分支持. 返回值:"aes(full)" ...
-
Java开发笔记(一百一十四)利用Socket传输文本消息
前面介绍了HTTP协议的网络通信,包括接口调用.文件下载和文件上传,这些功能固然已经覆盖了常见的联网操作,可是HTTP协议拥有专门的通信规则,这些规则一方面有利于维持正常的数据交互,另一方面不可避免地 ...
-
Qt开发笔记:OpenSSL库介绍、windows上mingw32版本的OpenSSL编译模块化
前言 Windows上mingw32版本的openssl的编译是属于比较棘手的,OpenSSL本身不提供支持.. OpenSSL 介绍 OpenSSL是一个开放源代码的软件库包,应用程序可 ...
-
JS和利用openssl的object C加密得到相同的aes加密密文
这是之前接到的一个工作内容,项目原本的登录操作是获得账号和密码以后,对密码进行一遍MD5加密,然后传递账号和密文到cgi文件.在c中获取到账户以后,从数据库中获取到密码,对密码进行一次MD5的加密,然 ...
-
CocoaPods的安装及使用/利用开源库Diplomat实现分享及第三方登录/git的使用
<<史上最简洁版本>> 1.gem sources -l查看 当前的源 //1.1 sudo -i..以下都是以管理员的身份来操作的 2.gem sources --remov ...
-
使用openssl库实现RSA、AES数据加密
openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密.可以使用非对称加密:公钥加密,私钥解密.openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所 ...
-
linux下利用openssl来实现证书的颁发(详细步骤)--转载和修改
原文地址:http://www.cnblogs.com/firtree/p/4028354.html linux下利用openssl来实现证书的颁发(详细步骤) 1.首先需要安装openssl,一个开 ...
-
[C#技术参考]Socket传输结构数据
最近在做一个机器人项目,要实时的接收机器人传回的坐标信息,并在客户端显示当前的地图和机器人的位置.当然坐标的回传是用的Socket,用的是C++的结构体表示的坐标信息.但是C#不能像C++那样很eas ...
-
[转]使用openssl库实现RSA、AES数据加密
openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密.可以使用非对称加密:公钥加密,私钥解密.openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所以一般的做 ...
随机推荐
-
kindle型号
这篇文章为 Kindle 新手解决三个问题:怎么辨别Kindle 型号?通过 Kindle 外观判断准确吗?Kindle序列号在那里? 贴吧吧友提问的原话"在咸鱼看到一台,那哥们说也不知道K ...
-
Sql的decimal、float、double类型的区别
三者的区别介绍 float:浮点型,含字节数为4,32bit,数值范围为-3.4E38~3.4E38(7个有效位) double:双精度实型,含字节数为8,64bit数值范围-1.7E308~1.7E ...
-
my97DatePicker日期控件——日期输入框联动,使用focus使第二个输入框没展示出日期控件
描述问题场景: 1.jquery使用的版本是jquery-1.7.2.min.js 2.代码不是写在页面上的,是通过事件后追加的 <!DOCTYPE html> <html> ...
-
PHP流程控制之特殊结构
在前两节介绍的循环结构中,都是通过循环语句本身提供的条件表达式来指定循环次数执行代码块直到停止循环.但如果想在循环体执行过程中中止循环,或是跳过一些循环继续执行其他代码块,我们就需要一些特殊的流程控制 ...
-
[tem]树状数组
通过差分可以玩区间: bi=ai-a(i-1) 查询时考虑位置对答案的贡献 推导一下 #include<iostream> #include<cstdio> #include& ...
-
javascript 对象初探 (四)--- 内建对象之旅之Array
我们不要去纠结神马是内建对象,神马是內建构造器.到后来你们便会发现其实她们都是对象. Array()是一个构建数组的內建构造器函数: var arr = new Array(); 与下面的是等效的: ...
-
[转载]面向对象设计(OOD)思想(C#)
有了思想才能飞翔,缺乏灵活就象少了*的汽车,难以飞奔.为了更好的理解设计思想,结合一个尽可能简洁的实例来说明OOD.设计模式及重构.通过下面的代码,详细地阐述面向对象设计思想. 一.传统过程化设计思 ...
-
Hive的Metastore contains multiple versions
hive 客户端报错:Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeExcepti ...
-
Jquery CSS 与 Attr
今天用Jquery想动态更改一张位图的src发现css不好用,查看Jquery文档好像是css是设置样式的属性的,如颜色,字体,背景等,而attr貌似是能操作所有属性,包括Jquery未封装的属性. ...
-
关于个人网站选择虚拟主机还是VPS服务器的讨论
还记得当初才开始学习建站的时候,选择的第一款虚拟主机是全HTML的主机,那时候的虚拟主机还分为HTML或者是ASP,PHP的都很少,在国内接触的学习较多还是以ASP为主,PHP是最近几年才开始流行.如 ...