第十八章:加密与哈希基础——OpenSSL库的基本使用

加密这东西,说白了就是给数据穿上一件防弹衣。我做了这么多年安全,见过太多因为加密没做好导致数据泄露的案例。今天咱们就聊聊OpenSSL这个C语言里最常用的加密库。

18.1 为什么是OpenSSL?

你想想看,如果让你自己实现AES或者RSA算法,那得踩多少坑?我记得刚入行那会儿,有个同事自己手写了个加密算法,结果上线第一天就被破解了。嗯,专业的事还是交给专业的库来做。

OpenSSL是目前最广泛使用的开源加密库。它支持:

  • 对称加密:AES、DES、3DES等
  • 非对称加密:RSA、DSA、ECC等
  • 哈希函数:MD5、SHA-1、SHA-256等
  • 数字证书:X.509证书处理
个人建议:虽然OpenSSL功能强大,但API设计确实有点复杂。我习惯在项目里封装一层简单的接口,这样调用起来更顺手。

18.2 对称加密:AES实战

对称加密,就是加密和解密用同一个密钥。AES是目前最主流的对称加密算法。我个人习惯用AES-256-GCM模式,因为它既加密又认证,安全性更高。

来看一个简单的AES加密示例:

#include <openssl/evp.h>
#include <string.h>

int aes_encrypt(const unsigned char *plaintext, int plaintext_len,
                const unsigned char *key, const unsigned char *iv,
                unsigned char *ciphertext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int ciphertext_len;

    // 创建并初始化上下文
    ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return -1;

    // 初始化加密操作
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv))
        return -1;

    // 加密数据
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        return -1;
    ciphertext_len = len;

    // 结束加密
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
        return -1;
    ciphertext_len += len;

    EVP_CIPHER_CTX_free(ctx);
    return ciphertext_len;
}
我曾经踩过的坑:有一次我忘了检查EVP_EncryptInit_ex的返回值,结果密钥长度不对,加密出来的数据全是乱的。记住,OpenSSL的每个函数都要检查返回值!

18.3 非对称加密:RSA的使用

非对称加密,说白了就是公钥加密、私钥解密。RSA是最经典的非对称加密算法。我在项目中常用RSA来加密对称密钥,这样既安全又高效。

生成RSA密钥对:

#include <openssl/rsa.h>
#include <openssl/pem.h>

RSA *generate_rsa_keypair(int bits) {
    RSA *rsa = NULL;
    BIGNUM *bn = NULL;

    // 创建RSA对象
    rsa = RSA_new();
    if (!rsa) return NULL;

    // 设置公钥指数
    bn = BN_new();
    BN_set_word(bn, RSA_F4);  // 65537

    // 生成密钥对
    if (1 != RSA_generate_key_ex(rsa, bits, bn, NULL)) {
        RSA_free(rsa);
        BN_free(bn);
        return NULL;
    }

    BN_free(bn);
    return rsa;
}

使用RSA加密数据时要注意,它不能加密超过密钥长度的数据。我一般用它加密AES密钥,然后用AES加密实际数据。这叫混合加密,是业界标准做法。

18.4 哈希函数:安全应用

哈希函数,就是把任意长度的数据映射成固定长度的摘要。SHA-256是目前最常用的哈希算法。MD5和SHA-1已经被证明不安全,我建议不要再用了。

计算SHA-256哈希:

#include <openssl/sha.h>

void compute_sha256(const unsigned char *data, size_t len,
                    unsigned char *hash) {
    SHA256_CTX ctx;
    
    SHA256_Init(&ctx);
    SHA256_Update(&ctx, data, len);
    SHA256_Final(hash, &ctx);
}
哈希的安全应用场景:
  • 密码存储:不要存明文密码,存哈希值
  • 数据完整性:验证文件是否被篡改
  • 数字签名:对哈希值签名,而不是对原始数据签名

18.5 加密与哈希的知识体系

下面这张图展示了加密与哈希的核心知识结构:

加密与哈希知识体系 对称加密 非对称加密 哈希函数 AES-256-GCM(推荐) 密钥管理:安全存储 IV初始化向量随机生成 RSA-2048/4096 公钥加密,私钥解密 混合加密:RSA+AES SHA-256(推荐) 密码存储加盐 数据完整性校验 核心原则:永远不要自己实现加密算法

18.6 避坑指南

这些年我在加密上踩过的坑,总结一下:

  1. 密钥硬编码:我曾经见过有人把密钥直接写在代码里,结果代码泄露后所有数据都暴露了。密钥应该从配置文件或密钥管理服务获取。
  2. 使用不安全的算法:MD5和SHA-1已经不安全了,别再用了。DES也过时了,用AES。
  3. 忘记加盐:存储密码哈希时一定要加盐,否则彩虹表攻击分分钟破解。
  4. 忽略随机数质量:OpenSSL提供了安全的随机数生成函数,别用rand()。
我的习惯:每次使用OpenSSL,我都会先调用OpenSSL_add_all_algorithms()初始化所有算法。虽然现在新版OpenSSL会自动初始化,但显式调用更保险。

18.7 总结

加密和哈希是安全编程的基础。OpenSSL虽然API复杂,但功能强大。记住几个要点:

  • 对称加密用AES-256-GCM
  • 非对称加密用RSA-2048以上
  • 哈希用SHA-256
  • 密码存储一定要加盐
  • 永远不要自己实现加密算法

嗯,这些经验都是我用真金白银换来的。希望你能少走些弯路。


公众号:蓝海资料掘金营,微信deep3321