openssl的安裝與簡單使用

    openssl是一個功能豐富且自包含的開源安全工具箱。它提供的主要功能有:SSL協議實現 (包括SSLv二、SSLv3和TLSv1)、大量軟算法(對稱/非對稱/摘要)、大數運算、非對稱算法密鑰生成、ASN.1編解碼庫、證書請求 (PKCS10)編解碼、數字證書編解碼、CRL編解碼、OCSP協議、數字證書驗證、PKCS7標準實現和PKCS12我的數字證書格式實現等功能。上述知識各位能夠去官網看看,或參考網上資料。html

    本文只針對本人實踐過的openssl的安裝過程以及關於RSA、AES的兩種加解密算法的簡單使用實例linux


1、Linux下安裝過程(本人是Centos 64bit系統)

一、 官方下載相應的源碼,相應的安裝教程,網上應該能找到不少的,這裏就不在累贅了。c++

     須要提醒的是,安裝完openssl後,發現程序編譯提示-lcrypto 沒法連接,表示缺乏crypto庫,此時參照該篇帖子http://blog.chinaunix.net/uid-14704264-id-4204452.html 完成便可。本人選擇直接yum安裝openssl-develweb

即 yum install openssl-devel算法


2、Windows7 64bit 操做系統下編譯openssl過程

(僅講述本人機器環境下,編譯成功的一些步驟,如有誤差,請動腦筋本身找解決方案)windows

     在windows下,咱們能夠選擇要編譯openssl爲32bit仍是64bit,以便後期VS2010開發時候,既能夠WIN32程序使用,也能夠X64程序使用。安裝openssl以前,咱們須要先下載安裝Windows版本的Perl,由於後期須要使用它來進行編譯連接。 (PS:若是你想看看原始的INSTALL文件,那麼請打開OpenSSL的解壓縮目錄,下面有兩個文件INSTALL.W32和INSTALL.W64,用記事本方式打開,你能夠看到詳細的關於安裝的解釋,這也是最正規的學習方式咯哦,下面只是咱們實踐以後,幫您快速安裝的指南而已)安全

一、好了,如今開始先講解下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文件。

二、下面介紹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」(若安裝成功則能夠使用此命令來驗證)



3、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++目錄->庫目錄

相關文章
相關標籤/搜索