服务器加密算法

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;
}
相关推荐
KFCcrazy42 小时前
嵌入式学习日记(36)TCP并发服务器构建——epoll
服务器·学习·tcp/ip
qq_297075672 小时前
网络安全测试(一)Kali Linux
linux·运维·服务器
diablobaal4 小时前
云计算学习100天-第28天
运维·服务器·学习
阳光阴郁大boy5 小时前
前端实现Linux查询平台:打造高效运维工作流
linux·运维·服务器
卓码软件测评5 小时前
【第三方网站运行环境测试:服务器配置(如Nginx/Apache)的WEB安全测试重点】
运维·服务器·前端·网络协议·nginx·web安全·apache
开开心心就好5 小时前
PDF转长图工具,一键多页转图片
java·服务器·前端·数据库·人工智能·pdf·推荐算法
Json_5 小时前
使用Docker部署ZLMediaKit流媒体服务器实现gb/t28181协议的设备
服务器·docker·容器
key_Go6 小时前
02.<<设备登录管理:掌握华为网络设备的本地与远程登录技巧>>
运维·服务器·网络·华为
幸运狗头7 小时前
Linux学习-TCP并发服务器构建
linux·服务器·学习