ccy
6 天以前 a715f9c49f732908691341951b1643f7b8fae91b
将加密字符修改为全部是英文大小写,去掉之前奇怪的标识符号
2个文件已修改
81 ■■■■■ 已修改文件
shortcrypto.cpp 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shortcrypto.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shortcrypto.cpp
@@ -12,6 +12,10 @@
const char *ShortCrypto::V3_CHARS =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// V2 字符集:大小写字母(52字符),设备ID只含字母、不含数字与特殊字符
const char *ShortCrypto::BASE52_CHARS =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
namespace {
    QByteArray pkcs7Pad(const QByteArray &data, int blockSize) {
        int padLen = blockSize - (data.size() % blockSize);
@@ -63,8 +67,8 @@
                    reinterpret_cast<const uint8_t*>(adjustedIv.constData()));
    AES_CBC_encrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(encrypted.data()), encrypted.size());
    // 3. Base85 编码,缩短字符数
    QByteArray encoded = base85Encode(encrypted);
    // 3. 纯字母编码(52字符集):48字节密文 → 68字符
    QByteArray encoded = baseNEncode(encrypted, BASE52_CHARS, 52);
    return QString::fromLatin1(encoded);
}
@@ -83,10 +87,18 @@
        adjustedIv.append(QByteArray(16 - adjustedIv.size(), '\0'));
    }
    // 1. Base85 解码
    QByteArray encrypted = base85Decode(ciphertext);
    // 1. 优先按纯字母表(52字符集)解码;52^字符数 与 256字节界 的头空间不足1字节,
    //    真值至多丢失1个前导零字节,长度不对齐时补回
    QByteArray encrypted = baseNDecodeVar(ciphertext, BASE52_CHARS, 52);
    if (!encrypted.isEmpty() && encrypted.size() % 16 != 0) {
        encrypted.prepend('\0');
    }
    if (encrypted.isEmpty() || encrypted.size() % 16 != 0) {
        // 回退:早期Base85版密文
        encrypted = base85Decode(ciphertext);
    }
    if (encrypted.isEmpty()) {
        qWarning() << "ShortCrypto::decrypt: base85 decode failed";
        qWarning() << "ShortCrypto::decrypt: decode failed";
        return QByteArray();
    }
@@ -234,6 +246,44 @@
    return num;
}
QByteArray ShortCrypto::baseNDecodeVar(const QString &text, const char *alphabet, int base)
{
    // 建立字符索引表
    int charToVal[256];
    memset(charToVal, -1, sizeof(charToVal));
    for (int i = 0; i < base; ++i) {
        charToVal[static_cast<unsigned char>(alphabet[i])] = i;
    }
    // 小端动态字节数组执行 Horner:num = num * base + v
    // num[0] 为最低字节,进位向尾部(高位)传播
    QByteArray num(1, '\0');
    QByteArray input = text.toLatin1();
    for (int i = 0; i < input.size(); ++i) {
        int v = charToVal[static_cast<unsigned char>(input.at(i))];
        if (v < 0) {
            qWarning() << "ShortCrypto::baseNDecodeVar: invalid character:" << QChar(input.at(i));
            return QByteArray();
        }
        unsigned int carry = static_cast<unsigned int>(v);
        for (int b = 0; b < num.size(); ++b) {
            unsigned int cur = (static_cast<unsigned int>(static_cast<unsigned char>(num.at(b))) * static_cast<unsigned int>(base)) + carry;
            num[b] = static_cast<char>(cur & 0xFF);
            carry = cur >> 8;
        }
        while (carry != 0) {
            num.append(static_cast<char>(carry & 0xFF));
            carry >>= 8;
        }
    }
    // 转大端并去掉前导零(变长模式下前导零的真实个数由调用方补齐规则恢复)
    std::reverse(num.begin(), num.end());
    int firstNonZero = 0;
    while (firstNonZero < num.size() - 1 && num.at(firstNonZero) == 0) ++firstNonZero;
    return num.mid(firstNonZero);
}
QByteArray ShortCrypto::base85Encode(const QByteArray &data)
{
    QByteArray result;
shortcrypto.h
@@ -6,23 +6,25 @@
/**
 * @brief 最短密文加密工具类
 * 流程:明文 → PKCS7填充 → AES-128-CBC加密 → Base85编码
 * 流程:明文 → PKCS7填充 → AES-128-CBC加密 → 纯字母编码(52字符集)
 * V3许可密钥另用无填充变体(encryptRaw),输出纯大写26字符集
 */
class ShortCrypto
{
public:
    /**
     * @brief 加密
     * @param plaintext 原始明文
     * @brief 加密(V2设备ID等,含PKCS7填充)
     * @param plaintext 原始明文(任意长度)
     * @param key 16字节密钥(AES-128)
     * @param iv 16字节初始向量,可为空(内部自动补零)
     * @return Base85编码的密文字符串
     * @return 纯字母编码的密文字符串(A-Z/a-z,52字符集,密文每48字节→68字符)
     * @note 解密端自动回退兼容早期Base85版密文
     */
    static QString encrypt(const QByteArray &plaintext, const QByteArray &key, const QByteArray &iv = QByteArray());
    /**
     * @brief 解密
     * @param ciphertext Base85编码的密文
     * @brief 解密(V2设备ID等,含PKCS7验证)
     * @param ciphertext 纯字母编码的密文(兼容早期Base85版密文,自动回退)
     * @param key 16字节密钥(AES-128)
     * @param iv 16字节初始向量,必须与加密时一致
     * @return 原始明文
@@ -54,12 +56,19 @@
    // V3 密文字符集:纯大写字母,不含数字/小写/特殊字符(26字符集,16字节→28字符)
    static const char *V3_CHARS;
    // V2 密文字符集:大小写字母,不含数字/特殊字符(52字符集,48字节→68字符)
    static const char *BASE52_CHARS;
    static QByteArray base85Encode(const QByteArray &data);
    static QByteArray base85Decode(const QString &text);
    // 任意进制的大数编解码(整段字节序作为大整数,前导零以alphabet[0]补齐固定位数)
    static QByteArray baseNEncode(const QByteArray &data, const char *alphabet, int base);
    static QByteArray baseNDecode(const QString &text, const char *alphabet, int base);
    // 变长版解码:返回去掉前导零的最短字节序(供长度不固定的V2密文使用,
    // 调用方需自行补齐对齐;52字符集下真值至多丢失1个前导零字节)
    static QByteArray baseNDecodeVar(const QString &text, const char *alphabet, int base);
};
#endif // SHORTCRYPTO_H