使用openssl库实现RSA、AES数据加密

使用openssl库实现RSA、AES数据加密

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, 0, 0) == NULL)
        {
            assert(false);
            return "";
        }

        int nLen = RSA_size(pRSAPublicKey);
        char* pEncode = new char[nLen + 1];
        int ret = RSA_public_encrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pEncode, pRSAPublicKey, RSA_PKCS1_PADDING);
        if (ret >= 0)
        {
            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, 0, 0) == NULL)
        {
            assert(false);
            return "";
        }
        int nLen = RSA_size(pRSAPriKey);
        char* pDecode = new char[nLen+1];

        int ret = RSA_private_decrypt(strData.length(), (const unsigned char*)strData.c_str(), (unsigned char*)pDecode, pRSAPriKey, RSA_PKCS1_PADDING);
        if(ret >= 0)
        {
            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() * 8, &aes_key) < 0)
        {
            assert(false);
            return "";
        }
        std::string strRet;
        std::string data_bak = data;
        unsigned int data_length = data_bak.length();
        int padding = 0;
        if (data_bak.length() % AES_BLOCK_SIZE > 0)
        {
            padding =  AES_BLOCK_SIZE - data_bak.length() % AES_BLOCK_SIZE;
        }
        data_length += padding;
        while (padding > 0)
        {
            data_bak += ‘\0‘;
            padding--;
        }
        for(unsigned int i = 0; 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, 0, 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() * 8, &aes_key) < 0)
        {
            assert(false);
            return "";
        }
        std::string strRet;
        for(unsigned int i = 0; 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, 0, 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.

  

一些资料:

http://www.ibm.com/developerworks/cn/linux/l-openssl.html

http://www.cnblogs.com/aLittleBitCool/archive/2011/09/22/2185418.html

明文长度限制:

http://bbs.chinaunix.net/thread-1860492-1-1.html

AES加密例子:

http://blog.csdn.net/wklnewlife/article/details/8244893

http://www.lovelucy.info/openssl-aes-encryption.html

http://www.thinkemb.com/wordpress/?p=18

编译资料补充:

http://developer.covenanteyes.com/building-openssl-for-visual-studio/

时间: 2024-10-23 14:30:34

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

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

直接上代码.默认生成的是pkcs#1格式 // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 1024 // 密钥长度 #define PUB_KEY_FILE "pubkey.pem" // 公钥路径 #define PRI_KEY_FILE "prikey.pem" // 私钥路径 // 函数方法生成密钥对 void generateRSAKey(std::string strKey[2]) { // 公私密钥对 size_

polarssl rsa &amp; aes 加密与解密

上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES 加密和解密,我用起来了,crypto++各种模板,各种多继承,看的头大,而且对各种常用的加密算法也不了解,所以这个库我在折腾了一天之后就放弃了:cyassl这个库现在没什么印象了:openssl没什么好说的,用起来很方便,尤其是使用win32openssl,都不用自己编译,下载下来安装好了就能用,着实方便:

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

前提:秘钥长度=1024 ============================================== 对一片(117字节)明文加密  私加 ============================================== // 私钥加密 std::string rsa_pri_encrypt(const std::string &clearText, std::string &pubKey) { std::string strRet; BIO *keybio

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

1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很难推算出私人密钥 根据非对称加密算法的特点,可用户数字签名.密钥交换.数据加密.但是由于非对称加密算法较对称加密算法加密速度慢很多,故最常用的用途是数字签名和密钥交换. 目前常用的非对称加密算法有RSA, DH和DSA三种,但并非都可以用于密钥交换和数字签名.而是RSA可用于数字签名和密钥交换,DH

lua 与 php 通过AES数据加密进行通讯

最近公司有款<围住神经猫>的微信小游戏火爆的不行!公司又决定开发一系列的神经猫的小游戏,于是,我被拉过来了. 后来使用cocos-2dx 开发一款小游戏,客户端用的是lua脚本,为了服务器与客户端交互的安全性,我们决定对API接口 传输的JSON数据进行加密.解密.一般情况就是客户端加密,服务器段进行解密: lua客户端使用的是一个纯lua写的库:aeslua,下载地址:http://luaforge.net/projects/aeslua/ 但是该库是有问题的:用该库加密解密是没有问题的,但

Linux下C语言使用openssl库进行加密

在这里插一小节加密的吧,使用openssl库进行加密. 使用MD5加密 我们以一个字符串为例,新建一个文件filename.txt,在文件内写入hello ,然后在Linux下可以使用命令md5sum filename.txt计算md5值 ==> b1946ac92492d2347c6235b4d2611184  .虽然写入的是hello这5个字符,但是我们使用命令xxd filename.txt后可以看出文件结尾处会有个0x0a这个回车符.所以在下面的代码中才会有\n. 1 //打开/usr/

iOS App中 使用 OpenSSL 库

转自:http://blog.csdn.net/kmyhy/article/details/6534067 在你的 iOS App中 使用 OpenSSL 库 ——译自x2on的“Tutorial: iPhone App with compiled OpenSSL 1.0.0a Library” 原文地址:http://www.x2on.de/2010/07/13/tutorial-iphone-app-with-compiled-openssl-1-0-0a-library/,本文有少许地方做

在你的 iOS App中 使用 OpenSSL 库

在你的 iOS App中 使用 OpenSSL 库 ——译自x2on的“Tutorial: iPhone App with compiled OpenSSL 1.0.0a Library” 原文地址:http://www.x2on.de/2010/07/13/tutorial-iphone-app-with-compiled-openssl-1-0-0a-library/ ,本文有少许地方做了调整. 1.下载OpenSSL源代码库: http://www.openssl.org/source/

自己动手编译OpenSSL库

因为工作需要,要实现一个基于SSL的通信程序.之前没有接触过SSL协议通讯,这次学习了一下如何自己编译OpenSSL库. 我使用的环境是Windows 10 + VS2015 1.首先打开VS2015的命令行编译工具,想编译成32位的就打开x86版本,想编译成64位的就打开x64版本. 2.解压下载下来的openssl的压缩包,进入解压文件夹,输入命令:perl Configure VC-WIN64A:(32位:VC-WIN32) 3.输入命令ms\do_win64a:(32位:ms\do_ms