密码学基础回顾:对称加密、非对称加密、哈希、数字签名原理

做 HSM 签名验签接口,说到底就是跟这四个密码学“老伙计”打交道。我个人习惯先把它们的关系理清楚——不是孤立背概念,而是理解它们怎么配合。今天就从实战角度,带你把它们串一遍。

对称加密:一把钥匙开一把锁

对称加密最直观。发送方和接收方共用同一个密钥,加密解密都用它。速度快、效率高,适合大量数据加密。我在项目中遇到过用 AES-256 加密数据库中的敏感字段,吞吐量比公钥方案快两个数量级。

算法密钥长度典型场景
AES128/192/256 bit文件加密、VPN 数据通道
SM4128 bit国产商用密码,金融系统
DES56 bit已淘汰,别用了

我曾经帮一个客户排查签名速度慢的问题,发现他们居然用 RSA 加密整个 10MB 文件……嗯,这是典型的设计失误。对称加密才是量大管饱的选择。

非对称加密:公钥私钥两把锁

非对称加密用一对密钥:公钥公开,私钥自己藏好。公钥加密、私钥解密,或者反过来签名。核心优势是解决密钥分发难题。不过速度比对称加密慢好几个数量级,所以实战中通常用它加密对称密钥,再用对称密钥加密业务数据。

举个例子:你收到一个来自银行服务器的消息,用银行公钥加密后只有银行掌握私钥能解密。反过来,银行用私钥签名的数据,任何持有公钥的人都能验证来源。

哈希(Hash):消息的“指纹”

哈希函数能把任意长度数据压缩成固定长度的摘要。单向性——从摘要反推原始数据几乎不可能。碰撞概率极低。我用 SHA-256 做文件完整性校验,一旦检测到哪怕一个字节改动,摘要都会变得面目全非。

你想想看,数字签名为什么需要哈希?因为直接用私钥加密长消息太慢,而且存在理论攻击面。先哈希,再把摘要签名,既快又安全。

哈希算法摘要长度安全强度
SHA-256256 bit高(推荐)
SHA-3可配置高
MD5128 bit已破解,严禁使用

数字签名:哈希 + 非对称加密的组合拳

数字签名就是用私钥对消息的哈希值进行加密(实际上是签名算法)。验证时用公钥解密摘要,再与重新计算的哈希对比。如果一致,证明消息未被篡改且来源可信。

核心流程(我习惯把它分成两步):

  1. 签名方:原文 → 哈希 → 摘要 → 私钥签名 → 签名值(附在原文后发送)
  2. 验签方:原文 + 签名值 → 公钥解密签名 → 得到摘要A;原文重新哈希 → 得到摘要B;比较A与B。

我在对接国密 SM2 签名时,发现很多开发者混淆了“哈希算法”和“签名算法”。实际上签名算法内部已经包含了哈希这一步,但接口参数要求显式传入哈希结果——这是最容易被坑的地方。

避坑提示:HSM 签名字段通常要求先对原文做哈希,再调用签名 API。不要传入原文本身,否则 HSM 内部帮你哈希一遍,你自己又哈希一遍,导致签名值错误。我曾经因为这个低级 bug 查了一天日志……

四者关系一览

下面这张图概括了它们如何在一次数字签名场景里协作。

数字签名流程中的密码学原语关系 原始消息 哈希运算 消息摘要 私钥签名 数字签名 原文 + 签名 验签过程反向执行: 用公钥解密签名得到摘要 → 对原文重新哈希 → 两个摘要一致则验签通过

实际接口调用的内存布局

如果你只记理论,写代码时会懵。我建议你把签名/验签接口的输入输出数据布局记清楚:

// 签名接口(以 PKCS#11 C_Sign 为例)
CK_BYTE  data[256];      // 原文(或哈希值,视算法而定)
CK_BYTE  signature[64];  // 签名值(长度因算法而异)
CK_ULONG sigLen = sizeof(signature);

C_SignInit(hSession, &mechanism, hPrivateKey);
C_Sign(hSession, data, 256, signature, &sigLen);

// 验签接口
C_VerifyInit(hSession, &mechanism, hPublicKey);
C_Verify(hSession, data, 256, signature, sigLen); // 返回 CKR_OK 则通过

注意:很多 HSM 要求 mechanism 里指定哈希算法,比如 CKM_SHA256_RSA_PKCS。别传错类型,否则返回 CKR_MECHANISM_INVALID。

常见的误解与纠正

  • 对称加密比非对称加密“弱”——不对。AES-256 的安全强度远高于 RSA-2048,只是密钥管理麻烦。HSM 里常用对称加密做数据加密,非对称做密钥封装和签名。
  • 哈希就是加密——哈希不可逆,加密可逆。别把 MD5/SHA 当密码存,那是固定长度的摘要,不是加密。
  • 数字签名等于加密——签名用私钥,加密用公钥。虽然 RSA 签名在数学上跟加密操作类似,但目的和协议完全不同。签名不隐藏原文,只提供认证和完整性。

一句话总结:你在 HSM 上配置签名任务时,核心流程就是“哈希摘要是原料,私钥签名是加工,公钥验签是质检”。理解了这个,接口调用的参数该填什么,心里就有底了。