欢迎光临
我们一直在努力

搞了半天,SM3 摘要到底是干嘛的?加密和签名能是一回事吗?

关于密码学,国际算法和国密算法到底有啥区别? 公钥加密,私钥解密?私钥加密,公钥解密?哪个对? BJCA 数字信封和 BouncyCastle 签名格式,是个啥?


前面几篇文章把 SM2、SM4、数字信封、数字签名都聊过了,但每次提到 SM3,可能大家都有疑问:“这玩意到底有啥用?”“我用 SM2 私钥加密不就完了吗?”“数字信封不就能保护数据了,搞个 SM3 签名不是多此一举?”。今天专门开一篇,把这些疑问一次讲透。


一、SM3 是啥?一句话:绞肉机

SM3 是一种哈希算法(也叫摘要算法、散列算法),叫法很多,但干的事就一件:

不管你丢进去什么东西,它都给你搅成一坨固定大小的"肉馅"。

SM3("你好")32 字节的"肉馅"
SM3("这是一份 5000 字的病历")32 字节的"肉馅"
SM3("这是一份 50MB 的影像报告")32 字节的"肉馅"
SM3("随便塞多少进去")32 字节的"肉馅"

不管你往绞肉机里塞一头牛还是一根葱,出来的肉馅永远是 32 字节(256 位)。

而且这台绞肉机有三个特别牛的性质:

性质一:不可逆

你看到一坨肉馅,能还原出原来那块肉是啥样的吗?

不能。SM3 也一样,从摘要反推不出原文。

性质二:雪崩效应(防篡改)

SM3("Hello") → a1b2c3d4e5
SM3("hello") → f9e8d7c6b5

就改了一个字母 H→h,出来的摘要完全变了,没有一个字节是相同的。
就像你往绞肉机里多扔了一粒花椒,出来的味道完全不同。

性质三:抗碰撞

想找两块不同的肉,搅出来的肉馅一模一样?

理论上存在这种可能,但概率低到可以忽略(2128次方分之一)。
实际工程中可以认为:不同的输入,不会产生相同的摘要。

所以 SM3 的外号叫数字指纹。就像人的指纹一样,每个人不同,且没法从指纹反推出长相。


二、SM3 到底用在哪?——它是签名的第一步

很多人以为签名就是"用私钥把数据加密一下",这个理解在 SM2 这里是不对的。

SM2 签名算法的标准流程(GM/T 0003 标准白纸黑字写着的):

步骤 1:e = SM3(原始数据) ← 第一步就是 SM3 摘要
步骤 2:选随机数 k
步骤 3:椭圆曲线点运算
步骤 45:一堆数学运算
步骤 6:输出签名 (r, s)

SM3 是写死在 SM2 签名算法里的第一步,不是可选的,不是额外加的。

没有 SM3,SM2 签名算法连第一步都跑不起来。就好比你做红烧肉,第一步是"把肉切块",你说"我不想切,直接整块炖"——那后面就没法做了。


三、灵魂拷问:直接用 SM2 私钥"加密"原始数据当签名不行吗?

这个问题我听过不下二十次了。拆开来回答。

先说结论:SM2 压根没有"私钥加密"这个操作

大家应该都听过,RSA 的数学结构天然对称(加密和签名都是模幂运算),所以"私钥加密当签名"在 RSA 里表面上说得通。

但 SM2 不一样。SM2 基于椭圆曲线,它的加密算法和签名算法是两套完全不同的数学公式:

SM2 加密:点乘 + 密钥派生 + 异或 → 输出一串密文
SM2 签名:摘要 + 模逆 + 模乘 → 输出两个整数 (r, s)

公式不一样,步骤不一样,输入输出格式不一样。
根本不存在"把加密反过来用就是签名"这回事。

所以"用 SM2 私钥加密数据当签名"这个操作,在 SM2 的世界里根本不存在。

就算存在,也走不通

假设技术上能做到(其实做不到),咱们推演一下会怎样:

走不通的第一关:数据太大,塞不进去

SM2 一次能处理的数据量大概只有几十个字节。【非对称加密处理小数据,对称加密处理大数据】

一份电子处方 1~5KB → 塞不进去
一份住院病历 10~100KB → 更塞不进去

SM3 摘要后 → 固定 32 字节 → SM2 一下就签完了

走不通的第二关:慢得离谱

SM2 非对称运算(单次)→ 几毫秒
SM3 哈希(1MB 数据) → 几微秒

如果 SM2 能处理大数据,签一份 1MB 的病历需要几分钟。
SM3 + SM2 签名呢?几毫秒搞定。

差了几千倍,这个性能差距在医院这种高并发场景下是不能接受的。

走不通的第三关:不安全

这个是最要命的。直接对原始数据做签名(不经过哈希),数学上存在存在性伪造攻击:

简单说就是攻击者可以利用签名的数学性质,
构造出一个"你从没签过的数据"的合法签名。

经过 SM3 之后再签 → 切断了数据和签名之间的数学关联 → 伪造变得不可能。

所以 SM3 存在的理由总结下来就三条:

1. SM2 根本签不了大数据(容量限制)
2. 签大数据太慢(性能限制)
3. 直接签原始数据不安全(数学攻击)


四、SM3withSM2 到底是啥组合?

搞明白了 SM3 的作用,SM3withSM2 这个名字就很好理解了:

SM3withSM2 = 先用 SM3 做摘要,再用 SM2 对摘要做签名

就是一个"两步走"的组合套餐,起个名字方便调用。

密码学里的命名都是这个套路:

算法名 实际操作
──────────────────────────────────
SM3withSM2 SM3 摘要 + SM2 签名(国密)
SHA256withRSA SHA256 摘要 + RSA 签名(国际)
SHA256withECDSA SHA256 摘要 + ECDSA 签名(国际)
MD5withRSA MD5 摘要 + RSA 签名(已经不安全了)

规则就是:[摘要算法] with [签名算法]

在代码里,你只需要指定算法名,内部两步自动完成:

// 你只需要告诉它用 SM3withSM2,内部自动先 SM3 再 SM2
Signature sig = Signature.getInstance("SM3withSM2", "BC");
sig.initSign(privateKey);
sig.update(prescriptionData); // 原始处方数据直接扔进去
byte[] signature = sig.sign(); // 内部自动完成:SM3 摘要 → SM2 签名

验签也是一样:

Signature sig = Signature.getInstance("SM3withSM2", "BC");
sig.initVerify(publicKey);
sig.update(prescriptionData); // 原始处方数据扔进去
boolean ok = sig.verify(signature); // 内部自动:SM3 摘要 → SM2 验签


五、重头戏:加密和签名到底是不是一回事?

搞明白 SM3 的作用之后,必须把另一个更根本的误解也澄清了。

很多人把"加密/解密"和"签名/验签"搅在一起,觉得是一回事。其实差别大了去了。

加密 ≠ 签名,它们解决的问题完全不同

加密(数字信封)= 你把东西锁进保险箱

你:把处方放进保险箱,锁上,钥匙用对方公钥加密
对方:用自己私钥解开钥匙,打开保险箱,看到处方

解决的问题:处方在运输过程中,别人看不到
这叫保密性

签名(SM3+SM2= 你在处方上按了手印

你:把处方内容算个指纹(SM3),用私钥对指纹盖章(SM2
对方:重新算指纹,用公钥比对盖章上的指纹

解决的问题:
→ 这处方确实是你开的(认证性)
→ 处方一个字都没被改过(完整性)
→ 你事后赖不掉(不可否认性)

一个是"加锁防偷看",一个是"盖章防篡改"
完全不同的事,解决完全不同的问题。

解密 ≠ 验签,它们的操作完全不同

解密验签
目的 看到内容 确认身份 + 确认没被改过
回答的问题 “里面写了啥?” “这东西谁写的?有没有被改过?”
用什么操作 私钥解密密文 公钥验证签名
结果 输出原始明文 输出 true 或 false
失败意味着什么 密钥不对或数据损坏 数据被篡改或签名是伪造的

解密是"把锁打开看内容",验签是"对比指纹确认身份"。

两者的操作对象完全不同:

解密:操作的是密文 → 还原出明文
验签:操作的是签名 + 明文的摘要 → 对比两个摘要是否一致

那问题来了:光有加密够不够?

光有加密,没有签名:

药房收到加密的处方,用自己的私钥解开了。

但是:

❓ 这处方真的是张医生开的吗?
→ 不知道。谁都能用药房的公钥加密一份假处方发过来。

❓ 处方在传输过程中有没有被改过?
→ 不知道。加密只保证别人看不到,不保证内容没被换过。

❓ 以后张医生说"我没开过这个处方"怎么办?
→ 没办法反驳,因为没有他的签名。

光有签名,没有加密:

药房收到签名的处方,验签通过,确认是张医生签的,内容也没被改。

但是:

❓ 网络上所有人都能看到处方内容
→ 患者的隐私泄露了

所以两个都要有,各管各的,谁也替代不了谁。

那 SM3 在这里到底是干嘛的?

你可能会问:数字信封里已经用 SM2 加密 SM4 密钥了,SM4 加密处方数据了。那 SM3 摘要签名又是干嘛的?

答案很简单:

数字信封(SM2 + SM4)只负责"加密"
→ 保证处方在传输过程中不被别人看到
→ 但不保证处方是谁写的
→ 也不保证处方有没有被篡改

数字签名(SM3 + SM2)负责"认证+防篡改"
→ 用 SM3 给整个处方算一个指纹
→ 用医生的 SM2 私钥对指纹签名
→ 任何人拿到处方,都能验证:是这个医生签的,且没改过一个字

SM3 摘要的是整个处方的明文内容,不是 SM4 密钥。为什么?因为你要防篡改的是处方本身:

假设你只对 SM4 密钥做签名(不用 SM3 摘要整个处方):

签名 = SM2 签名(SM4 密钥)

攻击者在传输过程中:
偷偷把信封里的处方内容改了(比如把药量从 1 改成 10
SM4 密钥没变 → 对密钥的签名依然有效 → 验签通过!

→ 处方被篡改了,但验签发现不了 ❌

正确做法:

签名 = SM2 签名(SM3(整个处方明文))

攻击者改了处方的任何一个字:
SM3 算出来的摘要完全不同
→ 签名验证失败
→ 药房立刻发现处方被篡改 → 拒绝接收 ✅


六、三个算法各管什么

┌─────────┬──────────────┬──────────────────────────────────┐
│ 算法 │ 类型 │ 管什么事 │
├─────────┼──────────────┼──────────────────────────────────┤
│ │ │ 给任意数据生成"指纹"
SM3 │ 摘要算法 │ 签名之前必须先做这一步 │
│ │ (绞肉机) │ 本身不加密,不签名,只出指纹(防篡改)│
├─────────┼──────────────┼──────────────────────────────────┤
│ │ │ ① 签名验签:签名→盖章,验签→对指纹 │
SM2 │ 非对称算法 │ ② 加密小数据:锁住 SM4 密钥 │
│ │ (公私钥) │ 不能直接对大数据操作 │
├─────────┼──────────────┼──────────────────────────────────┤
│ │ │ 加密大数据(处方、病历等) │
SM4 │ 对称算法 │ 速度快,适合大量数据 │
│ │ (一把钥匙) │ 密钥本身靠 SM2 保护 │
└─────────┴──────────────┴──────────────────────────────────┘

一句话记住它们的关系:

SM3 负责"压缩出指纹(防篡改)"
SM2 负责"盖章保护指纹""锁住 SM4 的钥匙"
SM4 负责"加密大量数据"

SM3 让签名成为可能,SM2 让签名和密钥保护成为可能,SM4 让大数据加密成为可能。
三个配合起来,才是一套完整的安全体系。


说到底,密码学这些东西概念多,但核心就一句话:不同的工具解决不同的问题,搞清楚每个工具是干什么的,就不会混了。 加密和签名不是一回事,解密和验签也不是一回事。就像菜刀和砧板都是厨房工具,但你不能拿砧板切菜,也不能拿菜刀垫着剁肉。

赞(0)
未经允许不得转载:171主机测评 » 搞了半天,SM3 摘要到底是干嘛的?加密和签名能是一回事吗?
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址