二、加密基础原理:四大基石,缺一不可

说实话,很多SDK开发者最头疼的还不是接口怎么调,而是“到底该用哪种加密”。我见过不止一次,有人把AES密钥直接发给对方,还觉得万事大吉。嗯,这就是我们今天要讲的——四种基础原理,搞懂了,你就知道为什么字段级加密里,每个原则都不能乱用。

2.1 对称加密

对称加密,说白了就是加密和解密用同一把钥匙。就像你用一把锁锁门,同一把钥匙也能开门。最简单的例子是AES(高级加密标准),它在字段级加密里几乎无处不在。

// Node.js 示例:AES-256-GCM 加密
const crypto = require('crypto');
const key = crypto.randomBytes(32); // 256位密钥
const iv = crypto.randomBytes(16);  // 初始化向量

function encrypt(plaintext, key, iv) {
    const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
    let encrypted = cipher.update(plaintext, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    const authTag = cipher.getAuthTag().toString('hex');
    return { encrypted, iv: iv.toString('hex'), authTag };
}
我习惯用AES-256-GCM,而不是常见的CBC模式。为什么?GCM自带身份验证,能防止密文被篡改。我在项目中遇到过,有一次用CBC,结果被人改了密文分组,解密出来的数据根本不是原样,查了半天才发现是模式问题。

对称加密的优点是快,非常快。你想想看,AES硬件加速几乎在所有CPU上都支持,加解密一条64字节的字段,也就几十纳秒。缺点呢?密钥分发问题——你得想办法把密钥安全地送到对方手里。

模式 安全性 性能 适用场景
AES-256-GCM 高(认证加密) 快(硬件加速) 字段级加密首选
AES-256-CBC 中(需配合MAC) 中 旧系统兼容
ChaCha20-Poly1305 高 软件实现更快 移动端或低端CPU

2.2 非对称加密

我经常把非对称加密称为“分手快乐加密”。你用公钥加密,只有私钥能解密——哪怕加密的人自己拿着公钥也解不开。RSA和ECC(椭圆曲线)是这里的主角。

在字段级加密SDK里,非对称加密一般不直接加密数据。为什么?太慢。RSA加密256字节,就要几毫秒,而AES加密1MB数据也就这么多时间。所以标准做法是混合加密:用RSA加密AES密钥,再用AES加密具体字段。

// 混合加密实用流程
function hybridEncrypt(plaintext, rsaPublicKey) {
    const aesKey = crypto.randomBytes(32);
    const iv = crypto.randomBytes(16);
    // 1. AES加密字段
    const { encrypted, authTag } = encryptAES(plaintext, aesKey, iv);
    // 2. RSA加密AES密钥
    const encryptedKey = crypto.publicEncrypt(rsaPublicKey, aesKey);
    return {
        ciphertext: encrypted,
        encryptedKey: encryptedKey.toString('base64'),
        iv: iv.toString('base64'),
        authTag
    };
}

我建议你记住:非对称加密不要用于加密大数据,它会让你后悔。我曾经接手过一个项目,某个同事直接拿RSA加密了整条用户记录,结果一次操作卡了3秒,整个系统就崩了。

我曾经踩过一个坑:RSA密钥对生成时,私钥没有用密码保护。结果有人从服务器上拷走了私钥文件,所有历史数据全部暴露。后来我们强制要求——私钥必须加密存储,且启用HSM硬件保护。

2.3 哈希算法

哈希不是加密,这是第一原则。哈希是单向的,你从摘要无法反推出原文。字段级加密里,哈希主要用来做数据完整性校验和派生密钥。

你可能会问:“不做加密,为什么还要学它?”你想想看——你的SDK要校验数据是否被篡改,就需要哈希。你要从密码派生出AES密钥,也要用到哈希(其实是HKDF,但底层依赖哈希)。

// SHA-256 哈希示例
function hashField(data) {
    return crypto.createHash('sha256').update(data).digest('hex');
}
// 注意:永远不要直接对密码做SHA-256,要用bcrypt/scrypt

常用的哈希算法:SHA-256足够安全(至少目前是的),SHA-1已经退役(我记得2017年Google就展示了碰撞攻击)。字段级加密里,我用的最多的是SHA-256和SHA-384。

一个小技巧:哈希可以用来做数据去重,但也带来了安全问题——如果攻击者能猜到原文,就可以暴力枚举。所以我建议,哈希字段时一定要加盐(salt),每个字段加不同的盐。

2.4 密钥派生

密钥派生,说白了就是“从一个不那么随机的输入,生成一个真正随机的密钥”。比如你的用户密码是“abc123”,但AES-256需要256位熵,怎么办?用HKDF(基于HMAC的密钥派生函数)或pbkdf2。

我为什么单独强调这个?因为在SDK开发中,几乎所有密钥泄露问题都出在派生环节。有人直接把用户密码当AES密钥用,还有人从字符串“my-key”直接生成MD5当密钥——你想想看,这跟没加密有什么区别?

// HKDF 标准实现
function deriveKey(masterSecret, salt, info, keyLength) {
    return crypto.hkdfSync('sha256', masterSecret, salt, info, keyLength);
}

// 使用示例
const userKey = deriveKey(
    masterSecret,      // 主密钥,必须从HSM或密钥管理服务获取
    Buffer.from(userId), // 盐,每个用户不同
    Buffer.from('field-encryption-v2'), // 上下文信息
    32                 // 输出32字节 = 256位
);
派生函数 用途 安全等级 我推荐的原因
HKDF 密钥派生(已有高熵密钥) 高 标准可扩展,嵌入SDK的最佳选择
PBKDF2 密码派生(低熵密码) 中高 抗暴力破解,但需要高迭代次数
直接hash 不要用 低 曾经有人用SHA-256直接派生,结果被彩虹表秒破
我遇到过最离谱的事:某团队用UUID作为密钥派生的盐。听起来没问题?但UUID是时间戳+随机数生成的,很多库的随机数生成器不够随机。结果在容器重启后,派生出的密钥居然和上次一样——所有加密数据的密钥都重复了。所以盐一定要用真正的随机数,或者至少是密码学安全的生成器。
加密基础原理:四大基石关系图 对称加密 AES-256-GCM 加密/解密用同一密钥 非对称加密 RSA/ECC 公钥加密,私钥解密 哈希算法 SHA-256/SHA-384 单向不可逆 密钥派生 HKDF / PBKDF2 从主密钥或密码派生工作密钥 关键关系说明 • 对称加密负责具体数据加解密——追求速度和硬件支持 • 非对称加密保护对称密钥的分发——解决密钥配送难题 • 哈希算法提供完整性校验和派生基础——保证数据没被改过 • 密钥派生将不完美的输入变成安全的密钥——避免直接使用密码或UUID

最后,我总结一个简单的对应关系:你开发SDK时,对称加密解决“怎么保护数据”,非对称加密解决“怎么传递密钥”,哈希解决“怎么验证没被改过”,密钥派生解决“怎么生成好密钥”。四者配合,才能构建一个真正可用的字段级加密方案。