服务器加密算法

HTTP服务器加密算法详解

1. 概述与历史演化

1.1 HTTP安全的历史演化

在互联网发展初期,HTTP协议是明文传输的,这带来了严重的安全隐患:

  • 1990年代初期:HTTP/1.0 完全明文传输,任何人都可以截获和查看数据
  • 1994年:Netscape公司开发了SSL (Secure Sockets Layer,安全套接字层)
  • 1999年:SSL演化为TLS (Transport Layer Security,传输层安全协议)
  • 2000年代:HTTPS成为标准,结合HTTP和TLS/SSL
  • 现在:TLS 1.3成为主流,提供更强的安全性和更好的性能

1.2 加密算法在HTTP服务器中的作用

HTTP服务器中的加密算法主要解决以下问题:

  • 机密性:确保数据不被未授权者读取
  • 完整性:确保数据在传输过程中未被篡改
  • 身份认证:确认通信双方的身份
  • 不可否认性:防止发送方否认已发送的信息

2. HTTP服务器请求-响应过程中的加密流程

2.1 完整的HTTPS握手过程

复制代码
客户端                                    服务器
   |                                        |
   |-------- 1. Client Hello -------------->|
   |                                        |
   |<------- 2. Server Hello ---------------|
   |<------- 3. Certificate ----------------|
   |<------- 4. Server Key Exchange -------|
   |<------- 5. Server Hello Done ---------|
   |                                        |
   |-------- 6. Client Key Exchange ------>|
   |-------- 7. Change Cipher Spec ------->|
   |-------- 8. Finished ------------------>|
   |                                        |
   |<------- 9. Change Cipher Spec --------|
   |<------- 10. Finished ------------------|
   |                                        |
   |====== 加密的应用数据传输 ===============|

2.2 各阶段使用的加密算法

阶段1:握手阶段
  • RSA/ECDSA:用于数字签名和密钥交换
  • SHA-256/SHA-384:用于证书签名和消息摘要
  • ECDHE/DHE:用于密钥协商,提供前向安全性
阶段2:数据传输阶段
  • AES-GCM/ChaCha20-Poly1305:对称加密算法,用于数据加密
  • HMAC:消息认证码,确保数据完整性

3. 核心加密算法详解

3.1 SHA-256 (Secure Hash Algorithm 256-bit)

全称:Secure Hash Algorithm 256-bit(安全哈希算法256位)

作用:将任意长度的输入数据转换为固定长度(256位)的哈希值

特点

  • 单向性:无法从哈希值推导出原始数据
  • 确定性:相同输入总是产生相同输出
  • 雪崩效应:输入的微小变化导致输出的巨大变化
  • 抗碰撞性:很难找到两个不同的输入产生相同的哈希值

在HTTP服务器中的应用

  • 密码存储:存储用户密码的哈希值而非明文
  • 数据完整性校验:验证传输数据是否被篡改
  • 数字签名:作为签名算法的一部分

3.2 HMAC (Hash-based Message Authentication Code)

全称:Hash-based Message Authentication Code(基于哈希的消息认证码)

作用:结合密钥和哈希函数,生成消息认证码

工作原理

复制代码
HMAC(K, M) = H((K ⊕ opad) || H((K ⊕ ipad) || M))
  • K:密钥
  • M:消息
  • H:哈希函数(如SHA-256)
  • opad:外部填充(0x5c重复)
  • ipad:内部填充(0x36重复)
  • ||:连接操作
  • ⊕:异或操作

在HTTP服务器中的应用

  • API认证:验证请求的合法性
  • JWT签名:JSON Web Token的签名验证
  • Cookie完整性:防止Cookie被篡改

3.3 Base64编码

全称:Base64 Encoding(64进制编码)

作用:将二进制数据转换为ASCII字符串

编码原理

  • 将3个字节(24位)分成4组,每组6位
  • 每组6位对应一个Base64字符(0-63)
  • 使用字符集:A-Z, a-z, 0-9, +, /
  • 填充字符:=

在HTTP服务器中的应用

  • HTTP Basic认证:编码用户名和密码
  • 数据传输:在文本协议中传输二进制数据
  • 证书编码:PEM格式证书的编码方式

4. OpenSSL库详解

4.1 OpenSSL简介

全称:Open Secure Sockets Layer(开放安全套接字层)

OpenSSL是一个强大的加密库,提供了:

  • 对称加密算法(AES、DES等)
  • 非对称加密算法(RSA、ECC等)
  • 哈希算法(SHA系列、MD5等)
  • 消息认证码(HMAC)
  • 数字签名和证书处理
  • 随机数生成

4.2 OpenSSL核心结构体

EVP_MD_CTX(消息摘要上下文)
c 复制代码
typedef struct evp_md_ctx_st {
    const EVP_MD *digest;     // 指向哈希算法的指针
    void *md_data;            // 算法特定的数据
    EVP_PKEY_CTX *pctx;      // 公钥上下文(用于签名)
    int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
} EVP_MD_CTX;
EVP_CIPHER_CTX(加密上下文)
c 复制代码
typedef struct evp_cipher_ctx_st {
    const EVP_CIPHER *cipher; // 指向加密算法的指针
    int encrypt;              // 加密(1)或解密(0)标志
    int buf_len;              // 缓冲区长度
    unsigned char oiv[EVP_MAX_IV_LENGTH];  // 原始IV
    unsigned char iv[EVP_MAX_IV_LENGTH];   // 当前IV
    unsigned char buf[EVP_CIPHER_CTX_BUF_LEN]; // 缓冲区
    int num;                  // 已处理的字节数
    void *app_data;           // 应用程序数据
    int key_len;              // 密钥长度
    unsigned long flags;      // 标志位
} EVP_CIPHER_CTX;

5. 实际应用场景

5.1 用户认证流程

  1. 用户注册

    • 接收用户密码
    • 生成随机盐值
    • 使用SHA-256计算密码哈希
    • 存储用户名、盐值和哈希值
  2. 用户登录

    • 接收用户名和密码
    • 从数据库获取对应的盐值和哈希值
    • 使用相同的盐值计算输入密码的哈希
    • 比较计算结果与存储的哈希值

5.2 API请求签名验证

  1. 客户端签名

    • 构造待签名字符串(通常包含时间戳、请求参数等)
    • 使用HMAC-SHA256和密钥生成签名
    • 将签名添加到请求头或参数中
  2. 服务器验证

    • 提取请求中的签名
    • 使用相同方法重新计算签名
    • 比较计算结果与请求中的签名

5.3 数据传输加密

  1. 对称加密

    • 使用AES算法加密大量数据
    • 密钥通过非对称加密安全传输
    • 使用CBC或GCM模式提供额外安全性
  2. 完整性保护

    • 计算数据的哈希值
    • 使用HMAC保护哈希值
    • 接收方验证数据完整性

6. 安全最佳实践

6.1 密钥管理

  • 使用强随机数生成器生成密钥
  • 定期轮换密钥
  • 安全存储密钥(使用HSM或密钥管理服务)
  • 实施密钥分离原则

6.2 算法选择

  • 优先使用经过验证的标准算法
  • 避免使用已知有漏洞的算法(如MD5、SHA-1)
  • 选择合适的密钥长度
  • 考虑性能和安全性的平衡

6.3 实现注意事项

  • 防止时序攻击:使用常数时间比较
  • 正确处理错误和异常
  • 清理敏感数据的内存
  • 使用安全的随机数生成器

7. 性能考虑

7.1 算法性能对比

  • 哈希算法:SHA-256 > SHA-512 > SHA-1(安全性考虑)
  • 对称加密:AES-GCM > AES-CBC > 3DES
  • 非对称加密:ECC > RSA(相同安全级别下)

7.2 优化策略

  • 使用硬件加速(AES-NI指令集)
  • 批量处理数据
  • 缓存计算结果
  • 选择合适的工作模式

这个详细的介绍为您提供了HTTP服务器中加密算法的全面理解,接下来我将为您提供具体的代码实现。

cpp 复制代码
#include "crypto.h"
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <cstring>
#include <memory>
#include <stdexcept>

// CryptoUtils类的实现
// 这个类封装了常用的加密算法功能,包括SHA-256哈希、HMAC签名和Base64编码

/**
 * 计算SHA-256哈希值
 * @param data 输入数据的指针
 * @param len 输入数据的长度(字节)
 * @return 返回32字节的SHA-256哈希值的十六进制字符串表示
 * 
 * 函数流程:
 * 1. 创建EVP_MD_CTX上下文对象
 * 2. 初始化SHA-256算法
 * 3. 更新数据到哈希计算器
 * 4. 完成计算并获取结果
 * 5. 将二进制结果转换为十六进制字符串
 */
std::string CryptoUtils::sha256(const unsigned char* data, size_t len) {
    // EVP_MD_CTX: OpenSSL的消息摘要上下文结构体
    // 包含算法信息、状态数据等
    EVP_MD_CTX* ctx = EVP_MD_CTX_new();
    if (!ctx) {
        throw std::runtime_error("Failed to create EVP_MD_CTX");
    }

    // 使用RAII管理资源,确保异常安全
    std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)> ctx_guard(ctx, EVP_MD_CTX_free);

    // EVP_DigestInit_ex: 初始化摘要计算
    // 参数1: 上下文对象
    // 参数2: 摘要算法(EVP_sha256()返回SHA-256算法的EVP_MD结构)
    // 参数3: 引擎(NULL表示使用默认引擎)
    if (EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) != 1) {
        throw std::runtime_error("Failed to initialize SHA-256");
    }

    // EVP_DigestUpdate: 向摘要计算器输入数据
    // 参数1: 上下文对象
    // 参数2: 数据指针
    // 参数3: 数据长度
    // 可以多次调用来处理大量数据
    if (EVP_DigestUpdate(ctx, data, len) != 1) {
        throw std::runtime_error("Failed to update SHA-256");
    }

    // 存储最终的哈希值(SHA-256产生32字节输出)
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hash_len;

    // EVP_DigestFinal_ex: 完成摘要计算并获取结果
    // 参数1: 上下文对象
    // 参数2: 输出缓冲区
    // 参数3: 输出长度的指针
    if (EVP_DigestFinal_ex(ctx, hash, &hash_len) != 1) {
        throw std::runtime_error("Failed to finalize SHA-256");
    }

    // 将二进制哈希值转换为十六进制字符串
    return bytesToHex(hash, hash_len);
}

/**
 * 计算字符串的SHA-256哈希值(重载版本)
 * @param data 输入字符串
 * @return SHA-256哈希值的十六进制字符串
 */
std::string CryptoUtils::sha256(const std::string& data) {
    return sha256(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
}

/**
 * 计算HMAC-SHA256签名
 * @param key 密钥数据指针
 * @param key_len 密钥长度
 * @param data 待签名数据指针
 * @param data_len 待签名数据长度
 * @return HMAC-SHA256签名的十六进制字符串
 * 
 * HMAC工作原理:
 * 1. 如果密钥长度大于块大小,先对密钥进行哈希
 * 2. 如果密钥长度小于块大小,用零填充
 * 3. 计算内部哈希:H((key ⊕ ipad) || message)
 * 4. 计算外部哈希:H((key ⊕ opad) || inner_hash)
 */
std::string CryptoUtils::hmacSha256(const unsigned char* key, size_t key_len,
                                   const unsigned char* data, size_t data_len) {
    unsigned char result[EVP_MAX_MD_SIZE];
    unsigned int result_len;

    // HMAC: 基于哈希的消息认证码函数
    // 参数1: 哈希算法(EVP_sha256())
    // 参数2: 密钥指针
    // 参数3: 密钥长度
    // 参数4: 数据指针
    // 参数5: 数据长度
    // 参数6: 输出缓冲区
    // 参数7: 输出长度指针
    unsigned char* hmac_result = HMAC(EVP_sha256(), key, key_len, data, data_len, result, &result_len);
    
    if (!hmac_result) {
        throw std::runtime_error("Failed to compute HMAC-SHA256");
    }

    return bytesToHex(result, result_len);
}

/**
 * 计算字符串的HMAC-SHA256签名(重载版本)
 * @param key 密钥字符串
 * @param data 待签名数据字符串
 * @return HMAC-SHA256签名的十六进制字符串
 */
std::string CryptoUtils::hmacSha256(const std::string& key, const std::string& data) {
    return hmacSha256(reinterpret_cast<const unsigned char*>(key.c_str()), key.length(),
                     reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
}

/**
 * Base64编码
 * @param data 输入数据指针
 * @param len 输入数据长度
 * @return Base64编码后的字符串
 * 
 * Base64编码原理:
 * 1. 将输入数据按3字节为一组进行分组
 * 2. 每组3字节(24位)分成4个6位的组
 * 3. 每个6位组对应Base64字符表中的一个字符
 * 4. 不足3字节的组用'='字符填充
 */
std::string CryptoUtils::base64Encode(const unsigned char* data, size_t len) {
    // BIO: OpenSSL的I/O抽象层
    // BIO_s_mem(): 内存BIO,数据存储在内存中
    BIO* bio = BIO_new(BIO_s_mem());
    if (!bio) {
        throw std::runtime_error("Failed to create BIO");
    }

    // BIO_f_base64(): Base64过滤器BIO
    // 可以自动进行Base64编码/解码
    BIO* b64 = BIO_new(BIO_f_base64());
    if (!b64) {
        BIO_free(bio);
        throw std::runtime_error("Failed to create Base64 BIO");
    }

    // BIO_push: 将两个BIO连接成链
    // 数据流向:输入 -> Base64编码器 -> 内存存储
    bio = BIO_push(b64, bio);

    // BIO_set_flags: 设置BIO标志
    // BIO_FLAGS_BASE64_NO_NL: 不在输出中添加换行符
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);

    // BIO_write: 向BIO写入数据
    // 数据会自动经过Base64编码
    if (BIO_write(bio, data, len) <= 0) {
        BIO_free_all(bio);
        throw std::runtime_error("Failed to write to Base64 BIO");
    }

    // BIO_flush: 刷新BIO缓冲区
    if (BIO_flush(bio) <= 0) {
        BIO_free_all(bio);
        throw std::runtime_error("Failed to flush Base64 BIO");
    }

    // 获取编码后的数据
    BUF_MEM* buffer_ptr;
    BIO_get_mem_ptr(bio, &buffer_ptr);
    
    std::string result(buffer_ptr->data, buffer_ptr->length);
    
    // 释放BIO资源
    BIO_free_all(bio);
    
    return result;
}

/**
 * Base64编码字符串版本
 * @param data 输入字符串
 * @return Base64编码后的字符串
 */
std::string CryptoUtils::base64Encode(const std::string& data) {
    return base64Encode(reinterpret_cast<const unsigned char*>(data.c_str()), data.length());
}

/**
 * Base64解码
 * @param encoded Base64编码的字符串
 * @return 解码后的二进制数据字符串
 * 
 * Base64解码原理:
 * 1. 将Base64字符转换回6位数值
 * 2. 将4个6位数值组合成3个8位字节
 * 3. 处理填充字符'='
 */
std::string CryptoUtils::base64Decode(const std::string& encoded) {
    // 创建内存BIO并写入编码数据
    BIO* bio = BIO_new_mem_buf(encoded.c_str(), encoded.length());
    if (!bio) {
        throw std::runtime_error("Failed to create memory BIO");
    }

    // 创建Base64解码器BIO
    BIO* b64 = BIO_new(BIO_f_base64());
    if (!b64) {
        BIO_free(bio);
        throw std::runtime_error("Failed to create Base64 BIO");
    }

    // 连接BIO链:内存 -> Base64解码器
    bio = BIO_push(b64, bio);
    
    // 设置不处理换行符
    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);

    // 读取解码后的数据
    char buffer[1024];
    std::string result;
    int len;
    
    while ((len = BIO_read(bio, buffer, sizeof(buffer))) > 0) {
        result.append(buffer, len);
    }

    BIO_free_all(bio);
    return result;
}

/**
 * 生成安全随机数
 * @param len 随机数长度(字节)
 * @return 随机数的十六进制字符串表示
 * 
 * 使用OpenSSL的CSPRNG(密码学安全伪随机数生成器)
 */
std::string CryptoUtils::generateRandomHex(size_t len) {
    std::vector<unsigned char> buffer(len);
    
    // RAND_bytes: 生成密码学安全的随机字节
    // 参数1: 输出缓冲区
    // 参数2: 字节数
    // 返回值: 1表示成功,0表示失败
    if (RAND_bytes(buffer.data(), len) != 1) {
        throw std::runtime_error("Failed to generate random bytes");
    }

    return bytesToHex(buffer.data(), len);
}

/**
 * 生成随机盐值(用于密码哈希)
 * @param len 盐值长度,默认16字节
 * @return 盐值的十六进制字符串
 */
std::string CryptoUtils::generateSalt(size_t len) {
    return generateRandomHex(len);
}

/**
 * 带盐值的密码哈希
 * @param password 原始密码
 * @param salt 盐值(十六进制字符串)
 * @return 密码哈希值的十六进制字符串
 * 
 * 流程:
 * 1. 将盐值从十六进制转换为二进制
 * 2. 将密码和盐值连接
 * 3. 计算SHA-256哈希
 */
std::string CryptoUtils::hashPassword(const std::string& password, const std::string& salt) {
    // 将十六进制盐值转换为二进制
    std::vector<unsigned char> salt_bytes = hexToBytes(salt);
    
    // 构造待哈希的数据:密码 + 盐值
    std::string data = password + std::string(salt_bytes.begin(), salt_bytes.end());
    
    return sha256(data);
}

/**
 * 验证密码
 * @param password 输入的密码
 * @param salt 存储的盐值
 * @param stored_hash 存储的密码哈希值
 * @return 密码是否正确
 */
bool CryptoUtils::verifyPassword(const std::string& password, 
                                const std::string& salt, 
                                const std::string& stored_hash) {
    std::string computed_hash = hashPassword(password, salt);
    return secureCompare(computed_hash, stored_hash);
}

/**
 * 安全字符串比较(防止时序攻击)
 * @param a 字符串a
 * @param b 字符串b
 * @return 字符串是否相等
 * 
 * 时序攻击:攻击者通过测量比较操作的时间来推断信息
 * 常数时间比较:无论字符串是否相等,比较时间都相同
 */
bool CryptoUtils::secureCompare(const std::string& a, const std::string& b) {
    if (a.length() != b.length()) {
        return false;
    }

    volatile unsigned char result = 0;
    for (size_t i = 0; i < a.length(); ++i) {
        result |= a[i] ^ b[i];
    }

    return result == 0;
}

/**
 * 将字节数组转换为十六进制字符串
 * @param data 字节数组指针
 * @param len 数组长度
 * @return 十六进制字符串(小写)
 */
std::string CryptoUtils::bytesToHex(const unsigned char* data, size_t len) {
    std::string result;
    result.reserve(len * 2);  // 预分配空间提高性能
    
    const char hex_chars[] = "0123456789abcdef";
    
    for (size_t i = 0; i < len; ++i) {
        result += hex_chars[data[i] >> 4];      // 高4位
        result += hex_chars[data[i] & 0x0F];    // 低4位
    }
    
    return result;
}

/**
 * 将十六进制字符串转换为字节数组
 * @param hex 十六进制字符串
 * @return 字节数组
 */
std::vector<unsigned char> CryptoUtils::hexToBytes(const std::string& hex) {
    if (hex.length() % 2 != 0) {
        throw std::invalid_argument("Hex string length must be even");
    }

    std::vector<unsigned char> result;
    result.reserve(hex.length() / 2);

    for (size_t i = 0; i < hex.length(); i += 2) {
        unsigned char byte = 0;
        
        // 处理高4位
        char high = hex[i];
        if (high >= '0' && high <= '9') {
            byte = (high - '0') << 4;
        } else if (high >= 'a' && high <= 'f') {
            byte = (high - 'a' + 10) << 4;
        } else if (high >= 'A' && high <= 'F') {
            byte = (high - 'A' + 10) << 4;
        } else {
            throw std::invalid_argument("Invalid hex character");
        }
        
        // 处理低4位
        char low = hex[i + 1];
        if (low >= '0' && low <= '9') {
            byte |= (low - '0');
        } else if (low >= 'a' && low <= 'f') {
            byte |= (low - 'a' + 10);
        } else if (low >= 'A' && low <= 'F') {
            byte |= (low - 'A' + 10);
        } else {
            throw std::invalid_argument("Invalid hex character");
        }
        
        result.push_back(byte);
    }

    return result;
}

// JWT工具类实现
// JWT (JSON Web Token): 一种用于安全传输信息的开放标准

/**
 * 创建JWT令牌
 * @param payload JWT载荷(JSON字符串)
 * @param secret 签名密钥
 * @param algorithm 签名算法(默认HS256)
 * @return JWT令牌字符串
 * 
 * JWT结构:header.payload.signature
 * - header: 包含算法和令牌类型信息
 * - payload: 包含声明(claims)
 * - signature: 使用header中指定的算法对header和payload的签名
 */
std::string JWTUtils::createToken(const std::string& payload, 
                                 const std::string& secret,
                                 const std::string& algorithm) {
    // 构造JWT头部
    std::string header = R"({"alg":")" + algorithm + R"(","typ":"JWT"})";
    
    // Base64编码头部和载荷
    std::string encoded_header = CryptoUtils::base64Encode(header);
    std::string encoded_payload = CryptoUtils::base64Encode(payload);
    
    // 移除Base64编码中的填充字符(JWT规范要求)
    encoded_header = removeBase64Padding(encoded_header);
    encoded_payload = removeBase64Padding(encoded_payload);
    
    // 构造待签名字符串
    std::string signing_input = encoded_header + "." + encoded_payload;
    
    // 生成签名
    std::string signature;
    if (algorithm == "HS256") {
        signature = CryptoUtils::hmacSha256(secret, signing_input);
        // 将十六进制签名转换为字节,再进行Base64编码
        std::vector<unsigned char> sig_bytes = CryptoUtils::hexToBytes(signature);
        signature = CryptoUtils::base64Encode(sig_bytes.data(), sig_bytes.size());
        signature = removeBase64Padding(signature);
    } else {
        throw std::invalid_argument("Unsupported algorithm: " + algorithm);
    }
    
    // 组装最终的JWT
    return signing_input + "." + signature;
}

/**
 * 验证JWT令牌
 * @param token JWT令牌
 * @param secret 签名密钥
 * @return 验证是否成功
 */
bool JWTUtils::verifyToken(const std::string& token, const std::string& secret) {
    try {
        // 分割JWT的三个部分
        std::vector<std::string> parts = splitString(token, '.');
        if (parts.size() != 3) {
            return false;
        }
        
        std::string header = parts[0];
        std::string payload = parts[1];
        std::string signature = parts[2];
        
        // 重新计算签名
        std::string signing_input = header + "." + payload;
        std::string expected_signature = CryptoUtils::hmacSha256(secret, signing_input);
        
        // 将存储的签名转换为十六进制格式进行比较
        std::string padded_signature = addBase64Padding(signature);
        std::string decoded_signature = CryptoUtils::base64Decode(padded_signature);
        std::string hex_signature = CryptoUtils::bytesToHex(
            reinterpret_cast<const unsigned char*>(decoded_signature.c_str()), 
            decoded_signature.length()
        );
        
        // 使用安全比较防止时序攻击
        return CryptoUtils::secureCompare(expected_signature, hex_signature);
        
    } catch (const std::exception&) {
        return false;
    }
}

/**
 * 解析JWT载荷
 * @param token JWT令牌
 * @return 解码后的载荷字符串
 */
std::string JWTUtils::getPayload(const std::string& token) {
    std::vector<std::string> parts = splitString(token, '.');
    if (parts.size() != 3) {
        throw std::invalid_argument("Invalid JWT format");
    }
    
    std::string padded_payload = addBase64Padding(parts[1]);
    return CryptoUtils::base64Decode(padded_payload);
}

/**
 * 移除Base64填充字符
 * @param base64_str Base64字符串
 * @return 移除填充后的字符串
 */
std::string JWTUtils::removeBase64Padding(const std::string& base64_str) {
    std::string result = base64_str;
    while (!result.empty() && result.back() == '=') {
        result.pop_back();
    }
    return result;
}

/**
 * 添加Base64填充字符
 * @param base64_str 无填充的Base64字符串
 * @return 添加填充后的字符串
 */
std::string JWTUtils::addBase64Padding(const std::string& base64_str) {
    std::string result = base64_str;
    while (result.length() % 4 != 0) {
        result += '=';
    }
    return result;
}

/**
 * 分割字符串
 * @param str 待分割的字符串
 * @param delimiter 分隔符
 * @return 分割后的字符串数组
 */
std::vector<std::string> JWTUtils::splitString(const std::string& str, char delimiter) {
    std::vector<std::string> result;
    std::string current;
    
    for (char c : str) {
        if (c == delimiter) {
            result.push_back(current);
            current.clear();
        } else {
            current += c;
        }
    }
    
    if (!current.empty()) {
        result.push_back(current);
    }
    
    return result;
}
相关推荐
sunz_dragon5 分钟前
Claude Code / Codex Git 版本管理完整使用指南
服务器·人工智能
SPC的存折28 分钟前
3、主从复制实现同步数据过滤
linux·运维·服务器
SPC的存折30 分钟前
openEuler 24.03 MariaDB Galera 集群部署指南(cz)
linux·运维·服务器·数据库·mysql
SPC的存折43 分钟前
MySQL 8.0 分库分表
linux·运维·服务器·数据库·mysql
风吹迎面入袖凉1 小时前
【Redis】Redisson分布式锁原理
java·服务器·开发语言
day day day ...2 小时前
MyBatis条件误写引发的查询条件污染分析与防范
java·服务器·tomcat
TechMasterPlus3 小时前
Linux U-Boot 与内核启动流程深度解析:从上电到 Shell 的完整之旅
linux·运维·服务器
大白菜和MySQL3 小时前
Linux下dhcp服务搭建
linux·运维·服务器
SPC的存折3 小时前
1、MySQL故障排查与运维案例
linux·运维·服务器·数据库·mysql
Deitymoon3 小时前
linux——TCP服务器获取客户端IP地址
linux·服务器·tcp/ip