第十八章:加密与哈希基础——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 加密与哈希的知识体系
下面这张图展示了加密与哈希的核心知识结构:
18.6 避坑指南
这些年我在加密上踩过的坑,总结一下:
- 密钥硬编码:我曾经见过有人把密钥直接写在代码里,结果代码泄露后所有数据都暴露了。密钥应该从配置文件或密钥管理服务获取。
- 使用不安全的算法:MD5和SHA-1已经不安全了,别再用了。DES也过时了,用AES。
- 忘记加盐:存储密码哈希时一定要加盐,否则彩虹表攻击分分钟破解。
- 忽略随机数质量:OpenSSL提供了安全的随机数生成函数,别用rand()。
我的习惯:每次使用OpenSSL,我都会先调用OpenSSL_add_all_algorithms()初始化所有算法。虽然现在新版OpenSSL会自动初始化,但显式调用更保险。
18.7 总结
加密和哈希是安全编程的基础。OpenSSL虽然API复杂,但功能强大。记住几个要点:
- 对称加密用AES-256-GCM
- 非对称加密用RSA-2048以上
- 哈希用SHA-256
- 密码存储一定要加盐
- 永远不要自己实现加密算法
嗯,这些经验都是我用真金白银换来的。希望你能少走些弯路。