openssl的安装与简单使用

拜拜、爱过 提交于 2019-12-17 21:40:06

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

    openssl是一个功能丰富且自包含的开源安全工具箱。它提供的主要功能有:SSL协议实现 (包括SSLv2、SSLv3和TLSv1)、大量软算法(对称/非对称/摘要)、大数运算、非对称算法密钥生成、ASN.1编解码库、证书请求 (PKCS10)编解码、数字证书编解码、CRL编解码、OCSP协议、数字证书验证、PKCS7标准实现和PKCS12个人数字证书格式实现等功能。上述知识各位可以去官网看看,或参考网上资料。

    本文只针对本人实践过的openssl的安装过程以及关于RSA、AES的两种加解密算法的简单使用实例


一、Linux下安装过程(本人是Centos 64bit系统)

1、 官方下载相应的源码,相应的安装教程,网上应该能找到很多的,这里就不在累赘了。

     需要提醒的是,安装完openssl后,发现程序编译提示-lcrypto 无法链接,表示缺少crypto库,此时参照该篇帖子http://blog.chinaunix.net/uid-14704264-id-4204452.html 完成即可。本人选择直接yum安装openssl-devel

即 yum install openssl-devel


二、Windows7 64bit 操作系统下编译openssl过程

(仅讲述本人机器环境下,编译成功的一些步骤,若有偏差,请动脑筋自己找解决方案)

     在windows下,我们可以选择要编译openssl为32bit还是64bit,以便后期VS2010开发时候,既可以WIN32程序使用,也可以X64程序使用。安装openssl之前,我们需要先下载安装Windows版本的Perl,因为后期需要使用它来进行编译链接。 (PS:如果你想看看原始的INSTALL文件,那么请打开OpenSSL的解压缩目录,下面有两个文件INSTALL.W32和INSTALL.W64,用记事本方式打开,你可以看到详细的关于安装的解释,这也是最正规的学习方式咯哦,下面只是我们实践之后,帮您快速安装的指南而已)

1、好了,现在开始先讲解下win64位下的openssl编译安装步骤

    1.1 安装好perl后,进入perl目录下的eg文件夹下,执行example.pl,安装成功会显示出来相应的信息

    1.2 打开vs2010的工具中命令提示行,运行C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64下的vcvars64.bat, 此步骤主要是完成vs的64bit的环境变量配置

    1.3 进入openssl的目录下,依次执行如下命令即可

         > perl Configure VC-WIN64A
         > ms\do_win64a
         > nmake -f ms\ntdll.mak        ()

         > nmake -f ms\ntdll.mak test   检查上一步编译是否成功
         > nmake -f ms\ntdll.mak install  安装编译后的openssl到指定目录

    说明:编译分两种情况,生成静态库和动态库
  (1) 如果是编译OpenSSL动态库,则在命令行键入 nmake -f ms\ntdll.mak
    编译成功课在文件夹out32dll里面查看输出的文件,包括应用程序的exe文件、lib文件、dll文件。
  (2) 如果是编译OpenSSL静态库,则在命令行键入 nmake -f ms\nt.mak
    编译成功课在文件夹out32里面查看输出的文件,包括应用程序的exe文件、lib文件。

2、下面介绍32bit下的openssl安装配置

    2.1 首先设定好环境变量

        设定环境变量:桌面计算机图标右键->属性->高级系统设置->环境变量->在系统变量当中找到变量名称为path的变量 (如果没有找到这新建)点击编辑->在变量名称中填入"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin;C:\Perl64\bin;c:\windows\system32"->点击确定完成设定。(说明:C: \Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin路径是VS2010的路径。C:\Perl64\bin是运行perl的路径,不若不设定那么perl命令将找不到。c: \windows\system32这个路径很少提到但是很重要,如果不设置那么会造成后面vcvars32.bat环境变量执行出错。)到此环境变量路 径设置好之后重启下电脑才能生效。


    2.2 使用Visual Studio命令提示(2010)进入控制台模式:开始菜单->所有程序->Microsoft Visual Studio 2010->Visual Studio Tools->Visual Studio命令提示(2010),(PS:以管理员身份运行), 使用cd命令将目录指向C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin(PS:自己的VC安装路径), 命令行键入vcvars32,运行vcvars32.bat..完成后进入OpenSSL源码的 目录(C:\openssl)


    2.3 执行Configure命令(配置编译参数)(需将目录跳到OpenSSL源码目录下)

            在命令行中键入"perl configure VC-WIN32 no-asm --prefix=c:\openssl"

            (PS:--prefix=c:\openssl命令为指定安装位置)


    2.4 运行ms\do_ms命令(需将目录跳到OpenSSL源码目录下)

            在命令行中键入”ms\do_nasm


    2.5 运行nmake -f ms\ntdll.mak -a”命令进行代码编译(需将目录跳到OpenSSL源码目录下)


    2.6 测试使用命令“nmake -f ms\ntdll.mak test”(若安装成功则可以使用此命令来验证)



三、RSA与AES的简单代码示例

//AES加密,不足128位的需要在前面补0,再加上128bit来表示补零的长度
std::string EncodeAES( const std::string& password, const std::string& data )
{
    unsigned char Iv[17]="12345678abcdefgh";
    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;

    //此函数在p0处插入n个字符c(前补零)
    data_bak.insert(0, padding, '\0');

    //用128位告知补了多少个0
    char* padding_zero_length = new char[AES_BLOCK_SIZE];
    memset(padding_zero_length, 0, AES_BLOCK_SIZE-1);
    padding_zero_length[AES_BLOCK_SIZE-1] = padding * 8 ;

    std::string num_head(padding_zero_length, AES_BLOCK_SIZE);
    delete[] padding_zero_length;
    data_bak.insert(0,num_head);
    data_length +=AES_BLOCK_SIZE;

    //加密的明文一定要是AES_BLOCK_SIZE的整数倍
    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_cbc_encrypt((const unsigned char*)str16.c_str(),out,AES_BLOCK_SIZE,
            &aes_key,Iv,AES_ENCRYPT);

        strRet += std::string((const char*)out, AES_BLOCK_SIZE);
    }
    return strRet;
}

//AES解密
std::string DecodeAES( const std::string& strPassword, const std::string& strData )
{
    //双方指定就好
    unsigned char Iv[17]="12345678abcdefgh";
    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_cbc_encrypt((const unsigned char*)str16.c_str(),out,AES_BLOCK_SIZE,
          &aes_key,Iv,AES_DECRYPT);

        strRet += std::string((const char*)out, AES_BLOCK_SIZE);
    }

    // 解密后跳过补零的长度
    unsigned char num_head = strRet[AES_BLOCK_SIZE-1];
    int len=num_head/8;

    strRet = strRet.substr(AES_BLOCK_SIZE+len);
    return strRet;
}

//RSA加密,加解密使用的都是公钥
std::string EncodeRSAKeyFile( const std::string& strRsaPubkey, const std::string& strData )
{
    if (strRsaPubkey.empty() || strData.empty())
    {
        assert(false);
        return "";
    }

    std::string strRet;
    RSA* pRSAPublicKey = NULL;
    BIO    *bio = NULL;

    /* 从内存数据读 */
    bio = BIO_new(BIO_s_mem());
    BIO_puts(bio, strRsaPubkey.c_str());

    pRSAPublicKey = PEM_read_bio_RSA_PUBKEY(bio, &pRSAPublicKey, NULL, NULL);
    if (pRSAPublicKey == NULL) 
    {
        return NULL;
    }


    int nLen = RSA_size(pRSAPublicKey);
    int iblock_size = nLen - 11;
    int oblock_size = nLen ;
    int nblocks = (strData.length() / iblock_size) + 
         ((strData.length() % iblock_size == 0) ? 0 : 1);  

    char* pEncode = new char[nblocks*nLen + 1];
    for (int i = 0; i < nblocks ; ++i)
    {
        int ret=0;
        if (i == nblocks - 1) 
        { 
          ret = RSA_public_encrypt(strData.length() % iblock_size,
                 (const unsigned char*)(strData.c_str()+(i * iblock_size)),
                 (unsigned char*)(&pEncode[i*oblock_size]),
                  pRSAPublicKey, 
                  RSA_PKCS1_PADDING); 
        } 
        else 
        {
          ret = RSA_public_encrypt(iblock_size,
                  (const unsigned char*)(strData.c_str()+(i * iblock_size)), 
                  (unsigned char*)(&pEncode[i*oblock_size]), 
                  pRSAPublicKey, 
                  RSA_PKCS1_PADDING); 
        } 
        strRet = strRet + std::string(&pEncode[i*oblock_size], ret);
    }
    delete[] pEncode;
    BIO_free(bio);
    RSA_free(pRSAPublicKey);
    CRYPTO_cleanup_all_ex_data(); 
    return strRet;
}

//RSA解密,加解密使用的都是公钥
std::string DecodeRSAKeyFile( const std::string& strRsaPubkey, const std::string& strData )
{
    if (strRsaPubkey.empty() || strData.empty())
    {
        assert(false);
        return "";
    }
    std::string strRet;
    RSA* pRSAPublicKey = NULL;
    BIO    *bio = NULL;

    /* 从内存数据读秘钥 */
    bio = BIO_new(BIO_s_mem());
    BIO_puts(bio, strRsaPubkey.c_str());

    pRSAPublicKey = PEM_read_bio_RSA_PUBKEY(bio, &pRSAPublicKey, NULL, NULL);
    if (pRSAPublicKey == NULL) 
    {
        return NULL;
    }

    int nLen = RSA_size(pRSAPublicKey);
    int block_size = nLen; 
    int nblocks =  strData.length() / block_size; 
    char* pDecode = new char[nLen+1];
    for (int i= 0; i < nblocks; i++) 
    { 
        //加解密使用的都是公钥
        int ret = RSA_public_decrypt(block_size, 
                        (const unsigned char*)(strData.c_str()+(i * block_size)),
                         (unsigned char*)pDecode, 
                         pRSAPublicKey, 
                         RSA_PKCS1_PADDING); 
        if(ret >= 0)
        {
            strRet = strRet + std::string((char*)pDecode, ret);
        }
    } 
    delete [] pDecode;
    BIO_free(bio);
    RSA_free(pRSAPublicKey);
    CRYPTO_cleanup_all_ex_data(); 
    return strRet;
}



其中例子中rsa加解密都是用公钥来加解密的哦,至于如何按私钥来,自主思考或查阅资料吧

linux编译选项需要加上: -lcrypto -lssl

windows下需要在VS2010中配置相应的项目属性,即

项目->属性->配置属性->vc++目录->包含目录

项目->属性->配置属性->vc++目录->库目录











易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!