技术

AES算法

2017-10-20  本文已影响0人  flycloud_hz

0x0 AES介绍

AES对数据对称加密,key大小为16,24,32个字节,每次加/解密输入16个字节,数据要做padding拼接,默认PKCS5Padding方式。

OpenSSL可以选择aes.h或evp.h实现。

0x1 代码实现

h文件

class AesCrypt {
public:
    enum Mode {
        ENCRYPT = 0,
        DECRYPT
    };
public:
    AesCrypt();
    ~AesCrypt();
    bool Init(Mode mode, const std::string& pass);

    bool Encrypt(const std::string& input, std::string& output);
    bool Decrypt(const std::string& input, std::string& output);

private:
    Mode mode_;
    bool initialized_;
    AES_KEY ase_key_;
};

cpp文件

AesCrypt::AesCrypt()
: mode_(AesCrypt::DECRYPT), initialized_(false){

}

AesCrypt::~AesCrypt() {

}

bool AesCrypt::Encrypt(const std::string &input, std::string &output) {
    if (!initialized_) {
        LOGE("init not done");
        return  false;
    }

    if (mode_ == AesCrypt::DECRYPT) {
        LOGE("mode mismatch");
        return  false;
    }

    unsigned char buf[AES_BLOCK_SIZE];
    int inputLen = input.length();
    const unsigned char* inputPtr = (const unsigned char*)input.c_str();
    int i = 0;
    for (i = 0; i < inputLen / AES_BLOCK_SIZE; i ++) {
        AES_encrypt(inputPtr + i * AES_BLOCK_SIZE, buf, &ase_key_);
        output += std::string((const char*)buf, AES_BLOCK_SIZE);
    }

    // PKCS5Padding
    // 1. left > 0 : add paddding with (16 - left)
    // 2. left == 0 : add padding with 16
    int left = inputLen - i * AES_BLOCK_SIZE;
    if (left > 0) {
        unsigned char leftBuf[AES_BLOCK_SIZE];
        memset(leftBuf, AES_BLOCK_SIZE - left, AES_BLOCK_SIZE);
        memcpy(leftBuf, inputPtr + i * AES_BLOCK_SIZE, left);
        AES_encrypt(leftBuf, buf, &ase_key_);
        output += std::string((const char*)buf, AES_BLOCK_SIZE);
    } else {
        unsigned char leftBuf[AES_BLOCK_SIZE];
        memset(leftBuf, 16, AES_BLOCK_SIZE);
        AES_encrypt(leftBuf, buf, &ase_key_);
        output += std::string((const char*)buf, AES_BLOCK_SIZE);
    }
    return true;
}

bool AesCrypt::Decrypt(const std::string &input, std::string &output) {
    if (!initialized_) {
        LOGE("init not done");
        return  false;
    }
    if (mode_ == AesCrypt::ENCRYPT) {
        LOGE("mode mismatch");
        return  false;
    }

    unsigned char buf[AES_BLOCK_SIZE];
    int inputLen = input.length();
    const unsigned char* inputPtr = (const unsigned char*)input.c_str();

    for (int i = 0; i < inputLen / AES_BLOCK_SIZE; i ++) {
        AES_decrypt(inputPtr + i * AES_BLOCK_SIZE, buf, &ase_key_);
        output += std::string((const char*)buf, AES_BLOCK_SIZE);
    }

    // PKCS5Padding
    if (!output.empty() && output.length() >= 16) {
        int last = output.at(output.length() - 1);
        if (last <= 16) {
            output.erase(output.length() - last, last);
        } else {
            LOGE("decrypt data error");
        }
    }
    return true;
}

bool AesCrypt::Init(AesCrypt::Mode mode, const std::string &pass) {
    if (initialized_) {
        LOGE("init already done");
        return true;
    }
    int result;
    mode_ = mode;
    if (mode_ == AesCrypt::DECRYPT) {
        result = AES_set_decrypt_key((const unsigned char*)pass.c_str(), pass.length() * 8, &ase_key_);
    } else {
        result = AES_set_encrypt_key((const unsigned char*)pass.c_str(), pass.length() * 8, &ase_key_);
    }
    if (result < 0) {
        LOGE("AesCrypt constructor error");
    } else {
        initialized_ = true;
    }
    return initialized_;
}
上一篇下一篇

猜你喜欢

热点阅读