我是靠谱客的博主 舒心咖啡豆,最近开发中收集的这篇文章主要介绍AES-128-CBC加解密方法:nodejs加密QT解密(附C语言版加解密全过程),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

服务器端使用的是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语言版加解密全过程)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部