使用openssl實現對稱性加解密AES128並封裝成動態庫

項目github地址:項目地址

頭文件 aes128.h

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <openssl/aes.h>
#include <iostream>

namespace aes128 {
using UCHAR = unsigned char;
using UCHARPTR = unsigned char*;

class AES128 {
  public:
    AES128 ();
    int InitIv(UCHARPTR iv);   //隨機初始化偏移量iv
    int ZeroPaddingLength(UCHARPTR raw_str);    //設置加解密字符串長度,非16字節倍數則用0補齊
    inline int GetDataLen() {return set_data_len_;}
    // UCHARPTR GetIv();
    // void SetIv(UCHARPTR iv);

    /*AES加密:
    入參:明文、偏移量、加密祕鑰
    出參:密文
    */
    int AES_Encrypt(UCHARPTR raw_str, UCHARPTR iv, UCHARPTR key, UCHARPTR encrypt_data);

    /*AES解密:
    入參:密文、偏移量、解密祕鑰
    出參:明文
    */
    int AES_Decrypt(UCHARPTR raw_str, UCHARPTR iv, UCHARPTR key, UCHARPTR decrypt_data);

  private:
    // UCHARPTR iv_;
    // UCHARPTR key_;
    AES_KEY aes_key_;
    int set_data_len_;
};
}

源文件 aes128.cc

#include "aes128.h"

using namespace std;

namespace aes128 {
    AES128::AES128():set_data_len_(0) {
        memset(&aes_key_, 0x00, sizeof(AES_KEY));
    }

    int AES128::InitIv(UCHARPTR iv) {
        int up_case(0), ascii_code(0);
        if (iv == nullptr) {
            return -1;
        }
        srand((int)time(0));
        for(int i = 0; i < AES_BLOCK_SIZE; i++) {
            up_case = rand() % 3; //隨機爲2或1或0,爲2就是數字,爲1就是大寫,爲0就是小寫 
            if (up_case == 2) {
                ascii_code = rand()%('9'-'0'+1) + '0';
            } else if (up_case == 1) {
                ascii_code = rand()%('Z'-'A'+1) + 'A'; 
            } else {
                ascii_code = rand()%('z'-'a'+1) + 'a';
            }
            
            iv[i] = (unsigned char)ascii_code;
            // iv[i] = 0;
        }
        return 0;
    }

    int AES128::ZeroPaddingLength(UCHARPTR raw_str) {
        if (raw_str == nullptr) {
            return -1;
        }
        int data_len = 0;
        while (*(raw_str++)) {
            ++data_len;
        }
        if ((data_len%AES_BLOCK_SIZE) == 0) {
            set_data_len_ = data_len;
        } else {
            set_data_len_ = ((data_len/AES_BLOCK_SIZE)+1) * AES_BLOCK_SIZE;
        }
        return 0;
    }

    int AES128::AES_Encrypt(UCHARPTR raw_str, UCHARPTR iv, UCHARPTR key, UCHARPTR encrypt_data) {
        if (raw_str == nullptr || iv == nullptr || key == nullptr || encrypt_data == nullptr) {
            return -1;
        }
        // printf("iv: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", iv[i]);
        // }
        // printf("\n");
        //設置加密密鑰
        memset(&aes_key_, 0x00, sizeof(AES_KEY));
        if (AES_set_encrypt_key(key, 128, &aes_key_) < 0) {
            std::cout << "Unable to set encryption key in AES..." << std::endl;
            return -1;
        }
        // printf("raw_str: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", raw_str[i]);
        // }
        // printf("\n");
        // printf("key: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", key[i]);
        // }
        //加密
        AES_cbc_encrypt(raw_str, encrypt_data, set_data_len_, &aes_key_, iv, AES_ENCRYPT);   
        return 0;
    }
    
    int AES128::AES_Decrypt(UCHARPTR raw_str, UCHARPTR iv, UCHARPTR key, UCHARPTR decrypt_data) {
        if (raw_str == nullptr || iv == nullptr || key == nullptr || decrypt_data == nullptr) {
            return -1;
        }
        // printf("iv: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", iv[i]);
        // }
        // printf("\n");
        //設置解密密鑰
        memset(&aes_key_, 0x00, sizeof(AES_KEY));
        if(AES_set_decrypt_key(key, 128, &aes_key_) < 0) {
            std::cout << "Unable to set decryption key in AES..." << std::endl;
            return -1;
        }
        // printf("raw_str: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", raw_str[i]);
        // }
        // printf("\n");
        // printf("key: ");
        // for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        //     printf("%02x", key[i]);
        // }
        //解密
        AES_cbc_encrypt(raw_str, decrypt_data, set_data_len_, &aes_key_, iv, AES_DECRYPT); 
        return 0;
    }
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(AES128)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
set(CMAKE_BUILD_TYPE  DEBUG)

# option(PLATFORM "compile platform" arm) #默認arm平臺
add_definitions(-DNDEBUG) #屏蔽DEBUG信息

#include_directories
include_directories(
    ${PROJECT_SOURCE_DIR}/include
)

#link_directories
link_directories(
    ${PROJECT_SOURCE_DIR}/lib
)

set(SOURCES
	${PROJECT_SOURCE_DIR}/src/aes128.cc
)

#.so
add_library(aes128 SHARED ${SOURCES})

# target libraries
target_link_libraries(
    aes128
    
    m 
    crypto
    dl
)

測試文件 test.cc

#include "../include/aes128.h"

int main() {
    int resCode(0);
    aes128::AES128 aes;
    aes128::UCHAR iv[AES_BLOCK_SIZE];
    aes128::UCHAR iv_dec[AES_BLOCK_SIZE];
    aes128::UCHAR key[AES_BLOCK_SIZE+1] = "AaBbCcDd1234!@#$";
    aes128::UCHAR raw_str[3][AES_BLOCK_SIZE] = {"admin", "abc123456", "123456cba"};
    aes128::UCHARPTR input_data = nullptr;
    aes128::UCHARPTR encrypt_data = nullptr;
    aes128::UCHARPTR decrypt_data = nullptr;

    resCode = aes.InitIv(iv);
    printf("iv init: ");
    for(int i = 0; i < AES_BLOCK_SIZE; i++) {
        printf("%02x", iv[i]);
    }
    printf("\n");
    memcpy(iv_dec, iv, AES_BLOCK_SIZE);

    for (int k = 0; k < 3; ++k) {
        aes.ZeroPaddingLength(raw_str[k]);
        input_data = (aes128::UCHARPTR)calloc(aes.GetDataLen()+1, sizeof(aes128::UCHARPTR));
        memcpy(input_data, raw_str[k], strlen((char *)raw_str[k]));
        //加密測試
        encrypt_data = (aes128::UCHARPTR)calloc(aes.GetDataLen()+1, sizeof(aes128::UCHARPTR));
        resCode = aes.AES_Encrypt(input_data, iv, key, encrypt_data);
        printf("\nencrypt_data: ");
        for(int i = 0; i < aes.GetDataLen(); i++) {
            printf("%02x", encrypt_data[i]);
        }
        printf("\n");
        //解密測試
        decrypt_data = (aes128::UCHARPTR)calloc(strlen((char *)encrypt_data), sizeof(aes128::UCHARPTR));
        resCode = aes.AES_Decrypt(encrypt_data, iv_dec, key, decrypt_data);
        // printf("\ndecrypt_data: ");
        // for(int i = 0; i < strlen((char *)encrypt_data); i++) {
        //     printf("%02x", decrypt_data[i]);
        // }
        printf("\ndecrypt_data: %s\n", (char *)decrypt_data);

        if (input_data != nullptr) {
            free(input_data);
            input_data = nullptr;
        }
        if (encrypt_data != nullptr) {
            free(encrypt_data);
            encrypt_data = nullptr;
        }
        if (decrypt_data != nullptr) {
            free(decrypt_data);
            decrypt_data = nullptr;
        }
    }
    return 0;
}

//g++ --std=c++11 test.cc -o test -L ../build/ -laes128 
//export LD_LIBRARY_PATH=/home/zzg/AES128/build/:$LD_LIBRARY_PATH
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章