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_;
}