openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密。可以使用非对称加密:公钥加密,私钥解密。openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所以一般的做法是使用对称密钥加密数据,然后再把这个只在当前有效的临时生成的对称密钥用非对称密钥的公钥加密之后传递给目标方,目标方使用约定好的非对称密钥中的私钥解开,得到数据加密的密钥,再进行数据解密,得到数据,这种使用方式很常见,可以认为是对HTTPS的裁剪。对称密钥加密可以选择AES,比DES更优秀。
     openssl库来自http://www.openssl.org/,下载到openssl源码之后,开始编译:
      产生动态库的做法
1、安装ActivePerl
2、进入OpenSSL所在文件夹,运行:perl Configure VC-WIN32 --prefix=C:\openssl-dll
3、进入VC/BIN目录,运行 VCVARS32.BAT 设置环境变量
4、返回OpenSSL目录,运行 ms\do_ms
5、在OpenSSL目录下执行编译 nmake -f ms\ntdll.mak
6、把必要生成物拷贝到prefix定义的目录中 nmake -f ms\ntdll.mak install
注意:可以通过修改ntdll.mak文件中的CFLAG,确定编译MT、MD库
     产生静态库的做法
1、安装ActivePerl
2、perl configure VC-WIN32 --prefix=C:\openssl-lib
3、ms\do_ms.bat
4、nmake -f ms\nt.mak
5、nmake -f ms\nt.mak install
注意:可以通过修改nt.mak文件中的CFLAG,确定编译MT、MD库。重编的时候把生成物删掉。
     RSA加解密需要先用openssl工具生成RSA公钥和RSA私钥。方法:
1、产生私钥:openssl genrsa -out privkey.pem 1024;
2、根据私钥产生公钥:openssl rsa -in privkey.pem -pubout。
1024只是测试用,使用2048位才比较安全。
     RSA加密部分代码demo
    std::string EncodeRSAKeyFile( const std::string& strPemFileName, const std::string& strData )
{
if (strPemFileName.empty() || strData.empty())
{
assert(false);
return "";
}
FILE* hPubKeyFile = NULL;
if(fopen_s(&hPubKeyFile, strPemFileName.c_str(), "rb") || hPubKeyFile == NULL)
{
assert(false);
return "";
}
std::string strRet;
RSA* pRSAPublicKey = RSA_new();
if(PEM_read_RSA_PUBKEY(hPubKeyFile, &pRSAPublicKey, , ) == NULL)
{
assert(false);
return "";
} int nLen = RSA_size(pRSAPublicKey);
char* pEncode = new char[nLen + ];
int ret = RSA_public_encrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPublicKey, RSA_PKCS1_PADDING);
if (ret >= )
{
strRet = std::string(pEncode, ret);
}
delete[] pEncode;
RSA_free(pRSAPublicKey);
fclose(hPubKeyFile);
CRYPTO_cleanup_all_ex_data();
return strRet;
}
     RSA解密部分代码demo
    std::string DecodeRSAKeyFile( const std::string& strPemFileName, const std::string& strData )
{
if (strPemFileName.empty() || strData.empty())
{
assert(false);
return "";
}
FILE* hPriKeyFile = NULL;
if(fopen_s(&hPriKeyFile, strPemFileName.c_str(),"rb") || hPriKeyFile == NULL)
{
assert(false);
return "";
}
std::string strRet;
RSA* pRSAPriKey = RSA_new();
if(PEM_read_RSAPrivateKey(hPriKeyFile, &pRSAPriKey, , ) == NULL)
{
assert(false);
return "";
}
int nLen = RSA_size(pRSAPriKey);
char* pDecode = new char[nLen+]; int ret = RSA_private_decrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pDecode, pRSAPriKey, RSA_PKCS1_PADDING);
if(ret >= )
{
strRet = std::string((char*)pDecode, ret);
}
delete [] pDecode;
RSA_free(pRSAPriKey);
fclose(hPriKeyFile);
CRYPTO_cleanup_all_ex_data();
return strRet;
}
     RSA的API中当使用参数RSA_PKCS1_PADDING时,明文长度不能大于密文长度-11;当使用参数RSA_NO_PADDING时,明文长度需要正好是128。
     AES加密部分代码
    std::string EncodeAES( const std::string& password, const std::string& data )
{
AES_KEY aes_key;
if(AES_set_encrypt_key((const unsigned char*)password.c_str(), password.length() * , &aes_key) < )
{
assert(false);
return "";
}
std::string strRet;
std::string data_bak = data;
unsigned int data_length = data_bak.length();
int padding = ;
if (data_bak.length() % AES_BLOCK_SIZE > )
{
padding = AES_BLOCK_SIZE - data_bak.length() % AES_BLOCK_SIZE;
}
data_length += padding;
while (padding > )
{
data_bak += '\0';
padding--;
}
for(unsigned int i = ; i < data_length/AES_BLOCK_SIZE; i++)
{
std::string str16 = data_bak.substr(i*AES_BLOCK_SIZE, AES_BLOCK_SIZE);
unsigned char out[AES_BLOCK_SIZE];
::memset(out, , AES_BLOCK_SIZE);
AES_encrypt((const unsigned char*)str16.c_str(), out, &aes_key);
strRet += std::string((const char*)out, AES_BLOCK_SIZE);
}
return strRet;
}
     AES解密部分代码
    std::string DecodeAES( const std::string& strPassword, const std::string& strData )
{
AES_KEY aes_key;
if(AES_set_decrypt_key((const unsigned char*)strPassword.c_str(), strPassword.length() * , &aes_key) < )
{
assert(false);
return "";
}
std::string strRet;
for(unsigned int i = ; i < strData.length()/AES_BLOCK_SIZE; i++)
{
std::string str16 = strData.substr(i*AES_BLOCK_SIZE, AES_BLOCK_SIZE);
unsigned char out[AES_BLOCK_SIZE];
::memset(out, , AES_BLOCK_SIZE);
AES_decrypt((const unsigned char*)str16.c_str(), out, &aes_key);
strRet += std::string((const char*)out, AES_BLOCK_SIZE);
}
return strRet;
}
     AES加密,块大小必须为128位(16字节),如果不是,则要补齐,密钥长度可以选择128位、192位、256位。
 
     不同语言解密补充
  使用python解密的时候,public key可能要求是PKCS#1格式,而openssl是不支持的,openssl默认是x509格式的public key,为此,如果要把上边生成的public key提供给python使用,需要先从x509格式转换为PKCS#1格式。网络上的资料显示,php有一个api支持这种转换,但我没试过。由于我的私钥是2048位的,所以可以很方便的实现x509转PKCS#1,转换是可逆的,说下PKCS#1转x509的方法:首先删除head和foot的“RSA”,然后在第二行开头增加文本“MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A”,最后,对齐文本。如果私钥不是2048的怎么办呢?可以使用php的api转一下了,或者到网上查找转换的资料解决。RSA key Formats。 2013.11.27.
  
 
 
一些资料:
 
明文长度限制:
 
AES加密例子:
 
编译资料补充:

使用openssl库实现RSA、AES数据加密的更多相关文章

  1. [转]使用openssl库实现RSA、AES数据加密

    openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密.可以使用非对称加密:公钥加密,私钥解密.openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所以一般的做 ...

  2. C++调用openssl库生成RSA加密秘钥对

    直接上代码.默认生成的是pkcs#1格式 // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 1024 // 密钥长度 #define PUB_KEY_FILE ...

  3. polarssl rsa & aes 加密与解密

    上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES ...

  4. polarssl rsa & aes 加密与解密<转>

    上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES ...

  5. 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)

    轉自:http://blog.chinaunix.net/uid-9543173-id-3921143.html 利用OpenSSL库对Socket传输进行安全加密(RSA+AES) 1. 利用RSA ...

  6. RSA加解密 私钥加密公钥解密 私加公解 && C++ 调用openssl库 的代码实例

    前提:秘钥长度=1024 ============================================== 对一片(117字节)明文加密  私加 ===================== ...

  7. C++ 使用openssl库实现 DES 加密——CBC模式 && RSA加密——公加私解——私加公解

    之前工作上需要用C++把软件生成的用户序列号用des加密cbc的模式,加密后为二进制,转化为十六进制,然后提供给java写的授权码管理平台. java平台会根据用户序列号,生成一个授权码,授权码是用r ...

  8. openssl 非对称加密算法RSA命令详解

    1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...

  9. Qt开发笔记:OpenSSL库介绍、windows上mingw32版本的OpenSSL编译模块化

    前言   Windows上mingw32版本的openssl的编译是属于比较棘手的,OpenSSL本身不提供支持..   OpenSSL 介绍   OpenSSL是一个开放源代码的软件库包,应用程序可 ...

随机推荐

  1. hdu 4123 Bob’s Race 树的直径+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  2. 数据结构B树

    B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...

  3. 漫谈 Greenplum 开源背后的动机

    漫谈 Greenplum 开源背后的动机  Greenplum是一家总部位于美国加利福尼亚州,为全球大型企业用户提供新型企业级数据仓库(EDW).企业级数据云(EDC)和商务智能(BI)提供解决方案和 ...

  4. web设计经验<七>13步打造优雅的WEB字体

    今天,大多数浏览器已经默认支持Web字体,日趋增多的字体特性被嵌入最新版HTML和CSS标准中,Web字体即将迎来一个趋于复杂的崭新时代.下面是一些基本的关于字体的规则,特别适用于Web字体. 原文地 ...

  5. poj1859The Perfect Symmetry

    链接 按x或y排序,假如有对称点的话,头尾相对. #include <iostream> #include<cstdio> #include<cstring> #i ...

  6. Python学习笔记12—类

    典型的类和调用方法: #!/usr/bin/env Python # coding=utf-8 __metaclass__ = type #新式类 class Person: #创建类 def __i ...

  7. 转:strcpy实现的考察要点

    strcpy函数的实现 已知strcpy函数的原型是: char *strcpy(char *dst, const char *src); 实现strcpy函数 解释为什么要返回char * 假如考虑 ...

  8. hibernate.properties和hibernate.cfg.xml

    hibernate.properties和hibernate.cfg.xml 博客分类: 框架技术 HibernateXMLSQLOracleJDBC     hibernate配置文件可以有两种方式 ...

  9. shell脚本中获取本机ip地址的方法

    ipaddr='172.0.0.1' ipaddr=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/ ...

  10. Linux定时任务Crontab详解_定时备份

    文章来源:http://blog.chinaunix.net/uid-7552018-id-182133.html 今天做了个数据库的备份脚本,顺便系统得学习一下Linux下定时执行脚本的设置.Lin ...