概述
服务器端使用的是nodejs编写的代码,对明文进行加密,客户端使用的是QT4.5.3编写代码,调用openssl crypto库函数,对密文进行解密。
注意:加解密要对等,即加解密的秘钥相同,向量也要相同,由于是两种不同的语言写的代码,因此两边都要做好一致性检查,比如秘钥的处理,密文的编码方式等等。
这里两边都对秘钥进行了MD5加密,并设置向量和秘钥一样(可自由设置秘钥和向量,我们的代码中处理成一样的比较便捷),密文采用base64编码,因此在QT那边一定要用fromBase64()来获取密文,否则会出错。
以下是nodejs加密端的代码:
function encChangeFuzzy(data) {
var key = "test";
var secretKey = new Buffer(key, "utf8");
secretKey = crypto.createHash("md5").update(secretKey).digest("hex");
secretKey = new Buffer(secretKey, "hex");
iv = secretKey;//设置向量和秘钥相同
var cipher = crypto.createCipheriv("aes-128-cbc", secretKey, iv), coder = [];
coder.push(cipher.update(data, "utf8", "base64"));
coder.push(cipher.final("base64"));
return coder.join("");
}
以下是QT端解密的代码:
#include<QObject>
#include <QtCore>
#include <openssl/aes.h>
int aes_decrypt(unsigned char *in, unsigned char *key, unsigned char* ivec, unsigned char *out)
{
if(!in || !key || !out) return 0;
AES_KEY aes;
if(AES_set_decrypt_key(key, 128, &aes) < 0)//设置解密秘钥
{
return 0;
}
int dateSize = strlen( (char*)in );
AES_cbc_encrypt(in, out, dateSize, &aes, ivec, AES_DECRYPT);//解密
/**pack5padding,获取最后一位数,以该数为个数,将out指向区域的最后位数用0替代**/
int out_len = strlen((char*)out);
int last_value = (unsigned char)out[out_len-1];
memset(out+out_len-last_value, 0, last_value);
return 1;
}
QString deCode( QString key,QString ivec, QString code)
{
int MSG_LEN = code.size();
//对秘钥进行MD5加密
QByteArray byteArray;
byteArray = key.toLatin1();
QByteArray hash = QCryptographicHash::hash(byteArray, QCryptographicHash::Md5);
//QByteArray strMD5 = hash.toHex();
//qDebug()<<"strMD5"<<strMD5.constData()<<" hash"<<hash;
//将加密后的秘钥转为unsigned char*类型
unsigned char keyArray[AES_BLOCK_SIZE];
memset((unsigned char*)keyArray, 0x00 ,AES_BLOCK_SIZE);
strcpy( (char*)keyArray, hash.constData() );
//对向量进行MD5加密
// QByteArray byteArrayIv;
// byteArrayIv = ivec.toLatin1();
// QByteArray hashIv = QCryptographicHash::hash(byteArrayIv, QCryptographicHash::Md5);
// //加密后的向量转为unsigned char*类型
// unsigned char ivArray[AES_BLOCK_SIZE];
// memset((unsigned char*)ivArray, 0x00 ,AES_BLOCK_SIZE);
// strcpy( (char*)ivArray, hashIv.constData() );
//将QString类型的密文转为unsigned char*型,注意拿到的密文要先使用toLatin1()转码
unsigned char sourceStringTemp[MSG_LEN];
memset((unsigned char*)sourceStringTemp, 0x00 ,MSG_LEN);
strcpy( (char*)sourceStringTemp, code.toLatin1().constData() );
//密文是使用base64编码的,这里使用fromBase64()获取正确的编码
QByteArray by_result = (char*)sourceStringTemp;
QByteArray base64Result = QByteArray::fromBase64(by_result);
//给明文分配内存
unsigned char result[MSG_LEN];
memset((unsigned char*)result, 0x00 ,MSG_LEN);
//解密:此处秘钥和向量设置成一样的了
if( !aes_decrypt((unsigned char *)base64Result.constData(),keyArray,keyArray,result) ) {
qDebug() << "Decode Error";
return "";
}
//将unsigned char*型的明文转换为QString类型
QString s_result = (char*)result;
memset((char*)sourceStringTemp, 0x00 ,MSG_LEN);
return s_result;
}
调用方法:
QString key = "test";//密钥
QString ivec = "test";//偏移量
qDebug()<<"n解密后的内容 :" <<deCode( key, ivec, EnResult );
****************************************************************************************分割线************************************
上面是nodejs加密,QT端解密,另外贴出QT端加解密的全过程代码:
#include <QtCore>
#include <stdio.h>
#include "global.h"
#include <openssl/aes.h>
// AES_BLOCK_SIZE 16
int aes_encrypt(unsigned char *in, unsigned char *key ,unsigned char* ivec, unsigned char *out)
{
if(!in || !key || !out) return 0;
AES_KEY aes;
if(AES_set_encrypt_key(key, 128, &aes) < 0)//设置加密秘钥
{
return 0;
}
/// pkcs5padding ///
// int dateSize = strlen( (char*)in ) + 1;
int nLen = strlen( (char*)in );
int nBei = nLen / AES_BLOCK_SIZE + 1;
int nTotal = nBei * AES_BLOCK_SIZE;
char *enc_s = (char*)malloc(nTotal);
int nNumber;
if (nLen % 16 > 0)
nNumber = nTotal - nLen;
else
nNumber = 16;
memset(enc_s, nNumber, nTotal);
memcpy(enc_s, in, nLen);
AES_cbc_encrypt((unsigned char*)enc_s, out, nTotal, &aes, ivec, AES_ENCRYPT);//加密
return 1;
}
QString enCode(QString key, QString ivec, QString code)
{
int len = code.size() / 1024;
int MSG_LEN = ( len + 1 ) * 1024;
//对秘钥进行MD5加密并转换为unsigned char*类型
QByteArray byteArray;
byteArray = key.toLatin1();
//若单用QT加解密,此处可以不用MD5来加密秘钥,这是因为服务器使用nodejs对秘钥做了MD5加密,对了对等才做了MD5加密
QByteArray hash = QCryptographicHash::hash(byteArray, QCryptographicHash::Md5);
unsigned char keyArray[AES_BLOCK_SIZE];
memset((unsigned char*)keyArray, 0x00 ,AES_BLOCK_SIZE);
strcpy( (char*)keyArray, hash.constData() );
//对向量进行MD5加密并转换为unsigned char*类型
// QByteArray byteArrayIv;
// byteArrayIv = ivec.toLatin1();
// QByteArray hashIv = QCryptographicHash::hash(byteArray, QCryptographicHash::Md5);
// unsigned char ivArray[AES_BLOCK_SIZE];
// memset((unsigned char*)ivArray, 0x00 ,AES_BLOCK_SIZE);
// strcpy( (char*)ivArray, hashIv.constData() );
//获取明文并转换为正确的类型
unsigned char sourceStringTemp[MSG_LEN];
memset((unsigned char*)sourceStringTemp, 0x00 ,MSG_LEN);
strcpy( (char*)sourceStringTemp, code.toLatin1().constData() );
//加密:此处秘钥和向量设置成一样的了
unsigned char result[MSG_LEN];
memset((unsigned char*)result, 0x00 ,MSG_LEN);
if( !aes_encrypt(sourceStringTemp,keyArray,keyArray,result) ) {
qDebug() << "Encode Error";
return "";
}
//密文转码转为base64编码格式
QByteArray by_result = (char*)result;
QString s_result(by_result.toBase64());
memset((char*)sourceStringTemp, 0x00 ,MSG_LEN);
return s_result;
}
int aes_decrypt(unsigned char *in, unsigned char *key, unsigned char* ivec, unsigned char *out)
{
if(!in || !key || !out) return 0;
AES_KEY aes;
if(AES_set_decrypt_key(key, 128, &aes) < 0)//设置解密秘钥
{
return 0;
}
int dateSize = strlen( (char*)in );
AES_cbc_encrypt(in, out, dateSize, &aes, ivec, AES_DECRYPT);//解密
pack5padding,获取最后一位数,以该数为个数,将out指向区域的最后位数用0替代/
int out_len = strlen((char*)out);
int last_value = (unsigned char)out[out_len-1];
memset(out+out_len-last_value, 0, last_value);
return 1;
}
QString deCode( QString key,QString ivec, QString code)
{
int MSG_LEN = code.size();
//对秘钥进行MD5加密
QByteArray byteArray;
byteArray = key.toLatin1();
QByteArray hash = QCryptographicHash::hash(byteArray, QCryptographicHash::Md5);
//QByteArray strMD5 = hash.toHex();
//qDebug()<<"strMD5"<<strMD5.constData()<<" hash"<<hash;
//将加密后的秘钥转为unsigned char*类型
unsigned char keyArray[AES_BLOCK_SIZE];
memset((unsigned char*)keyArray, 0x00 ,AES_BLOCK_SIZE);
strcpy( (char*)keyArray, hash.constData() );
//对向量进行MD5加密
// QByteArray byteArrayIv;
// byteArrayIv = ivec.toLatin1();
// QByteArray hashIv = QCryptographicHash::hash(byteArrayIv, QCryptographicHash::Md5);
// //加密后的向量转为unsigned char*类型
// unsigned char ivArray[AES_BLOCK_SIZE];
// memset((unsigned char*)ivArray, 0x00 ,AES_BLOCK_SIZE);
// strcpy( (char*)ivArray, hashIv.constData() );
//将QString类型的密文转为unsigned char*型,注意拿到的密文要先使用toLatin1()转码
unsigned char sourceStringTemp[MSG_LEN];
memset((unsigned char*)sourceStringTemp, 0x00 ,MSG_LEN);
strcpy( (char*)sourceStringTemp, code.toLatin1().constData() );
//密文是使用base64编码的,这里使用fromBase64()获取正确的编码
QByteArray by_result = (char*)sourceStringTemp;
QByteArray base64Result = QByteArray::fromBase64(by_result);
//给明文分配内存
unsigned char result[MSG_LEN];
memset((unsigned char*)result, 0x00 ,MSG_LEN);
//解密:此处秘钥和向量设置成一样的了
if( !aes_decrypt((unsigned char *)base64Result.constData(),keyArray,keyArray,result) ) {
qDebug() << "Decode Error";
return "";
}
//将unsigned char*型的明文转换为QString类型
QString s_result = (char*)result;
memset((char*)sourceStringTemp, 0x00 ,MSG_LEN);
return s_result;
}
调用方法:
QString key = "testKey";//密钥
QString ivec = "testIv";//偏移量
QString code = "sgd.2010"; //待加密内容
QString EnResult = enCode( key, ivec, code );
qDebug()<<"encode :"<<EnResult; //加密后内容
qDebug()<<"ndecode :" <<deCode( key, ivec, EnResult );//解密后的内容
********************************************************************分割线***********************************************************
再贴一个C语言写的AES-128-CBC加解密方法,这个是查找到别人的博客资料测试通过了的,但是再找就找不到了,要是原作者看到可以联系我声明原地址及版权。
也是使用openssl 的aes-128-cbc加解密:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/aes.h>
int main(int argc, char** argv) {
AES_KEY aes;
unsigned char key[AES_BLOCK_SIZE]; // AES_BLOCK_SIZE = 16
unsigned char iv[AES_BLOCK_SIZE]; // init vector
unsigned char* input_string;
unsigned char* encrypt_string;
unsigned char* decrypt_string;
unsigned int len; // encrypt length (in multiple of AES_BLOCK_SIZE)
unsigned int i;
// check usage
if (argc != 2) {
fprintf(stderr, "%s <plain text>n", argv[0]);
exit(-1);
}
// set the encryption length
//加密块必须是16的整数倍,若不是要进行填充
len = 0;
if ((strlen(argv[1]) + 1) % AES_BLOCK_SIZE == 0) {
len = strlen(argv[1]) + 1;
} else {
len = ((strlen(argv[1]) + 1) / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE;
}
// set the input string
input_string = (unsigned char*)calloc(len, sizeof(unsigned char));
if (input_string == NULL) {
fprintf(stderr, "Unable to allocate memory for input_stringn");
exit(-1);
}
strncpy((char*)input_string, argv[1], strlen(argv[1]));
// Generate AES 128-bit key
for (i=0; i<16; ++i) {
key[i] = 32 + i;
}
// Set encryption key
for (i=0; i<AES_BLOCK_SIZE; ++i) {
iv[i] = 0;
}
//设置加密秘钥
if (AES_set_encrypt_key(key, 128, &aes) < 0) {
fprintf(stderr, "Unable to set encryption key in AESn");
exit(-1);
}
// alloc encrypt_string
encrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));
if (encrypt_string == NULL) {
fprintf(stderr, "Unable to allocate memory for encrypt_stringn");
exit(-1);
}
// encrypt (iv will change)加密
AES_cbc_encrypt(input_string, encrypt_string, len, &aes, iv, AES_ENCRYPT);
// alloc decrypt_string
decrypt_string = (unsigned char*)calloc(len, sizeof(unsigned char));
if (decrypt_string == NULL) {
fprintf(stderr, "Unable to allocate memory for decrypt_stringn");
exit(-1);
}
// Set decryption key 偏移量要重新设置
for (i=0; i<AES_BLOCK_SIZE; ++i) {
iv[i] = 0;
}
//设置解密私钥
if (AES_set_decrypt_key(key, 128, &aes) < 0) {
fprintf(stderr, "Unable to set decryption key in AESn");
exit(-1);
}
// decrypt 解密
AES_cbc_encrypt(encrypt_string, decrypt_string, len, &aes, iv, AES_DECRYPT);
// print
printf("input_string = %sn", input_string);
printf("encrypted string = ");
for (i=0; i<len; ++i) {
printf("%x%x", (encrypt_string[i] >> 4) & 0xf,
encrypt_string[i] & 0xf);
}
printf("n");
printf("decrypted string = %sn", decrypt_string);
return 0;
}
makefile文件:
CC=g++
CFLAGS=-Wall -g -O2
LIBS=-lcrypto
all: aes
aes: aes.cpp
$(CC) $(CFLAGS) aes.cpp -o $@ $(LIBS)
clean:
@rm -f aes
调用方法:(这里明文字符串不能有空格,可以自己修改源代码实现需要的明文输入方式)
最后
以上就是舒心咖啡豆为你收集整理的AES-128-CBC加解密方法:nodejs加密QT解密(附C语言版加解密全过程)的全部内容,希望文章能够帮你解决AES-128-CBC加解密方法:nodejs加密QT解密(附C语言版加解密全过程)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复