字符编码的本质

目的

最近做一个加密方面的研究,加密之后的二进制,通过转码之后,再也找不回之前的二进制了。

怎么试都不行,真是非常得奇怪!!!!

先说说字符编码基础知识

在信息技术的海洋中,字符编码是数据表示的基本桥梁,它使计算机能够存储和传输文本信息。字符编码的本质,是对字符集进行数字化的一种方式,通过特定的编码规则将文字转换为计算机可以处理的二进制代码。理解字符编码的工作原理对于从事软件开发、数据处理等IT行业的专业人员来说至关重要。

字符集与编码

字符集是一组符号和编码的集合,而编码则是这些字符集的数字化表示(这句话有理,编码就是二进制,转化编码就是更改二进制 )。不同的编码方式有不同的特性,它们决定了数据存储、网络传输及文件处理的效率和范围。

常见字符编码

字符编码的种类繁多,常见的包括ASCII、GBK、UTF-8等。每种编码都有其特定的使用背景和适用场景。掌握这些基础知识,有助于我们更好地处理国际化文本、网络数据交换等问题。

情况分析

实例分析

点击加密之后显示:

点击解密之后:

解密里没显示什么,后台提示了报错:

怎么回事,那就跟踪代码看看情况:

先看加密的代码:

源码如下:

cpp 复制代码
QByteArray AesUtil::encrypt(const QString& plaintext, const QString& key) {
    qDebug("enter function AesUtil::encrypt");
    qDebug()<< "plaintext="<< plaintext << "key.hex()=" << key.toLocal8Bit().toHex();
    try {
        QByteArray hashKey = QCryptographicHash::hash(
            key.toUtf8(),
            QCryptographicHash::Sha256
        );
        hashKey = hashKey.left(16);
        qDebug() << "hashKey.toHex()=" << hashKey.toHex();
        //std::string plain = qtToStdString(plaintext);
        std::string plain = plaintext.toUtf8();
        //std::string plain2 = plaintext.toUtf8().constData();
        //std::string keyStr = qtToStdString(key);
        byte iv[CryptoPP::AES::BLOCKSIZE] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
        CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor((byte*)hashKey.data(), hashKey.size(), iv);
        std::string cipher;
        CryptoPP::StringSource(plain, true,new CryptoPP::StreamTransformationFilter(encryptor,new CryptoPP::StringSink(cipher)));
        // 将二进制密文转换为十六进制字符串便于显示和传输
        /*
        string encoded;
        StringSource(cipher, true,
            new HexEncoder(
                new StringSink(encoded)
            )
        );
        */
        QByteArray ar1 = QByteArray::fromStdString(cipher);
        std::string cipher2 = ar1.toStdString();
        QString str1 = QString::fromLocal8Bit(cipher.c_str());
        QString str3 = QString::fromUtf8(cipher.c_str());
        QString str2 = ar1;
        QByteArray byteArray1 = QByteArray::fromStdString(cipher);
        qDebug() << "byteArray1.toHex()=" << byteArray1.toHex();
        QString qstr1 = QString::fromUtf8(byteArray1);
        qDebug() << "qstr1.toUtf8().toHex()= " << qstr1.toUtf8().toHex();
        qDebug() << "qstr1.toLocal8Bit().toHex()= " << qstr1.toLocal8Bit().toHex();
        QByteArray byteArray2 = qstr1.toUtf8();
        qDebug() << "byteArray2.toHex()=" << byteArray2.toHex();
        QByteArray byteArray3 = qstr1.toLatin1();
        qDebug() << "byteArray3.toHex()=" << byteArray3.toHex();
        qDebug("exit function AesUtil::encrypt");
        return QByteArray::fromStdString(cipher);
    }
    catch (const CryptoPP::Exception& e) {
        cerr << "加密失败: " << e.what() << endl;
        return "";
    }
    qDebug("exit function AesUtil::encrypt");
}

跟踪代码的情况:

调试情况:

下面把密文转化为QByteArray类型:

QByteArray的数据与原始二进制数据是一致的,因为负号的处理方式不同,所以有些显示不一样,但二进制数据是一样的。

到了QString数据明显不一样了,但表示的编码是一致的。

可以对比一下看看:(第一张图是原始加密二进制数据,第二张图是转化为QString的加密二进制数据)

上面最显著的区别是:原始数据[1][3][8][10]数值是不一样的,但到了QString 却成了一样的了是65533,并且都显示为?号。

这证明了QString进行了utf8的转化,这种编码转化是以字符为标准的进行更改相应的二进制数,也可以说是以显示的东西为标准,更改后面的二进制数,当然,也有相同的,相同是因为巧合而已,所以这说明了,要想保持二进制一样,就不能进行编码相关的转化。

因为编码的本质是以显示的东西一样为要求,对存储的二进制数进行更改。

解密时变化会更为明显:

解码的相关代码:

关于常用的编码

UTF-8 和 GBK 编码的本质区别在于‌字符集覆盖范围‌和‌编码方式‌:

字符集覆盖范围

‌GBK‌:基于 GB2312 扩展,支持21003个汉字及682个符号,主要用于中文信息处理。 ‌

‌UTF-8‌:基于 Unicode 标准,理论上支持任何字符(包括中文、英文、数字等),兼容 ASCII 字符,广泛应用于多语言场景。 ‌

编码方式

‌GBK‌:采用双字节编码,首字节为0x81-0xFE,尾字节为0x40-0xFE,通过高位字节扩展汉字数量。 ‌

‌UTF-8‌:可变长度编码(1-4字节),第一个字节与ASCII兼容,后续字节用于扩展字符范围。 ‌

应用场景

‌GBK‌:适合中文系统内部处理(如Windows系统默认中文编码)。 ‌

‌UTF-8‌:优先用于国际化和跨平台数据交换(如网页、邮件)。

总结

之所以出现了上面的错误,还是没理解字符编码的本质,编码就是用数字对应字符,就是这么简单。

比如ASCII编码:

最后总结:

相关推荐
洲覆9 小时前
C++ constexpr 修饰符与函数
开发语言·数据结构·c++
会跑的葫芦怪9 小时前
Golang 赋值运算符与短声明 (= 与 :=)使用场景
开发语言·后端·golang
数据知道9 小时前
Go基础:Go语言函数和方法详解
开发语言·后端·golang·go语言
木觞清10 小时前
补环境-JS原型链检测:在Node.js中完美模拟浏览器原型环境
开发语言·javascript·node.js
或与且与或非10 小时前
rust使用sqlx示例
开发语言·数据库·rust
软件黑马王子11 小时前
C#练习题——泛型实现单例模式和增删改查
开发语言·单例模式·c#
嵌入式小李.man12 小时前
C++第十篇:const关键字
开发语言·c++
码界筑梦坊12 小时前
194-基于Python的脑肿瘤患者数据分析可视化
开发语言·python·数据分析·sqlite·毕业设计·echarts·fastapi
郝学胜-神的一滴12 小时前
基于Linux,看清C++的动态库和静态库
linux·服务器·开发语言·c++·程序人生
江上清风山间明月12 小时前
flutter 编译报错java.util.zip.ZipException: zip END header not found
java·开发语言·flutter