用点外卖,讲透SM2、SM3、SM4是干什么的
你每天在快餐店App上点外卖时,一笔简单的订单,背后经过了三道国密算法的保护:
SM3帮你生成订单防伪码
SM4把快餐装进密封快递袋
SM2给订单贴上你的电子指纹,证明是你本人下的单
这篇文章不讲复杂的数学公式,用点外卖这件事,一次性搞懂国密三兄弟的分工。
一、SM3:订单防伪码
你在App上选好辣堡、薯条、可乐,点击下单。App生成一份订单,同时根据订单内容算出一个校验码,你可以把它理解成订单的"防伪标签",比如#A37。
快餐店收到的是加密订单,解密后得到明文(辣堡+薯条+可乐),按这个备餐。同时用SM3给订单内容算一个校验码跟订单一起存——一旦有人篡改订单(比如把辣堡换成满汉全席),校验码就对不上,系统直接拒单。
你拿到的是校验码#A37,凭这个号取餐。
这个校验码有三个特点:
看不出你点了什么:给你
#A37,你猜不出是辣堡还是鸡翅饭换一样菜,号码就完全变了:把可乐换成九珍果汁,
#A37可能变成#B52长度固定:不管你点多少东西,校验码都一样长
一次完整的点餐:你提交订单 → 快餐店解密后用SM3算防伪码、同时按明文备餐 → 你收到防伪码凭号取餐。这个号是订单的"防伪标记",不是备餐依据。
二、SM4:外卖打包
你点完外卖,厨房按订单备餐。但在送出之前,餐食要经过一套打包流程——把菜品分装进盒子,再封进快递袋,外面看不见里面是什么。
2.1 分装盒
SM4按16字节一组处理数据。就像把菜品按份分装,每份装一个盒子,每盒固定放一份(16字节)。不管这份是辣堡还是一包薯条,盒子大小都一样。
2.2 填充:卫生隔板填满盒子
仅ECB和CBC模式需要填充,CTR和GCM不需要。
如果最后一份只有5个字节,塞不满标准盒子怎么办?缺多少补多少——缺11个字节就放11块卫生隔板把盒子填满。收件人拆袋后,隔板扔掉,只取菜。
2.3 四种打包方式
ECB——不安全,不要用
每个盒子独立封口。两盒都装辣堡,封口方式一模一样。坏人买过一次,知道封口长这样的盒子里是辣堡。下次在别人订单里看到一模一样的封口,就知道里面也是辣堡。
CBC——可用,但需要额外验货
第N盒封口时,参考第N-1盒封好之后的样子(密文)来决定封口方式。两盒都装辣堡,但因为前面那盒的密文不同,封口方式也完全不同。
第一盒需要一个随机初始样式(IV),确保即使两单点的菜完全一样,封口效果也完全不同。
但如果整个袋子被掉包,收件人发现不了。
CTR——推荐
每个盒子贴一个流水号(001、002、003...),每盒按自己的编号独立封装。一盒破损不影响其他盒,速度也快。但同样存在"整个袋子被掉包发现不了"的问题。
GCM——首选
CTR + 防伪封条。每个盒子贴流水号独立封装,同时快递袋口贴一张防伪封条。
收件人收到外卖:
封条破损或对不上 →直接拒收,不拆袋
封条完好 → 拆袋,取出各盒,看到菜品
"密封+防伪"一步到位。
⚠️致命警告:GCM虽好,但IV(初始化向量)绝不能重复!同一把钥匙+同一个IV加密两次,密钥直接泄露,后果比ECB还严重。开发时务必用安全的随机数生成器。
一句话:新系统无脑选GCM,ECB直接拉黑。
三、SM2:订单签名
SM4解决了"外卖不被偷看"的问题,但还有一个问题:快餐店怎么确认这单是你本人下的,而不是别人用你的账号冒用的?
SM2的核心是两把钥匙:
私钥:只存在你手机里,相当于你的电子指纹(保密)
公钥:存在快餐店服务器上,相当于你的指纹验证器(公开)
这两把钥匙成对生成,你用私钥在订单上按下指纹,只有配对的公钥能验证这个指纹。
下单流程:
你选好菜,点击下单 → App生成订单数据
App用你的私钥给订单按指纹(签字画押)
订单连同指纹发给快餐店
快餐店用你的公钥验证指纹
通过 → 确认是你本人,接单做菜
不通过 → 拒绝
为什么安全?
不可抵赖:你没法否认下过这单,因为只有你的私钥能按出这个指纹
防篡改:订单内容被改,指纹就失效
防冒用:别人没有你的私钥,没法冒充你
四、三兄弟如何协同工作?
一笔完整的点外卖:
| 步骤 | 谁 | 做什么 | 用什么 |
|---|---|---|---|
| ① | 你 | 选好菜,点击下单 | - |
| ② | App | 生成订单,同时算防伪码 | SM3 |
| ③ | App | 加密订单内容,贴防伪封条 | SM4-GCM |
| ④ | App | 用你的私钥按指纹 | SM2 |
| ⑤ | App | 把"加密订单+防伪码+指纹"发给快餐店 | - |
| ⑥ | 快餐店 | 验指纹→确认是你本人 | SM2 |
| ⑦ | 快餐店 | 验封条→确认订单没被改 | SM4-GCM |
| ⑧ | 快餐店 | 验SM3校验码→确认未被篡改→备餐 | SM3 |
| ⑨ | 你 | 凭防伪码取餐 | - |
五、常见问题
Q1:SM3和SM4有什么区别?
SM3是哈希——从校验码推不出你点了什么,是单向的。SM4是加密——用密钥可以拆袋取餐,也能重新封上,是双向的。
Q2:SM2的签名和加密有什么区别?
签名:用自己的私钥签,别人用你的公钥验 → 证明"这是我下的单"
加密:用别人的公钥加密,别人用自己的私钥解 → 保证"只有你能看"
点外卖用的是签名。
Q3:为什么不直接用SM2加密订单?
SM2比SM4慢几百到几千倍。实际做法是:SM4打包订单,SM2只加密SM4的钥匙(数字信封),又快又安全。
Q4:ECB为什么还在?
历史遗留。新系统绝对不要用,无脑选GCM。
Q5:SM3能存密码吗?
千万别直接用!SM3算得太快,坏人用显卡一秒能试几亿次,加盐也扛不住。
正确做法:存密码必须用慢速哈希(如bcrypt、scrypt、Argon2)。如果合规要求必须用国密,用SM3 + 大量迭代(如10万次)+ 盐,或者使用专门的国密KDF算法,绝不能只存一次 SM3(密码+盐)。
Q6:GCM的IV为什么不能重复?
GCM的IV(初始化向量)必须是随机的、且每个密钥下只能用一次。如果同一把钥匙配合同一个IV加密了两次,攻击者通过比较两次密文就能推算出密钥。这是一个容易被忽视但后果极其严重的坑。开发时务必用安全的随机数生成器。
Q7:现实中的App点餐真的用SM2签名吗?
实际工程中,SM2签名更多出现在国密SSL/TLS握手或设备认证等底层环节。科普文为了便于理解,把SM2简化成"用户App签名单笔订单"。实际App更常用登录后的会话令牌(Token)标识身份,国密算法封装在底层的安全通道里。
六、三条铁律
SM4只用GCM,ECB直接拉黑
SM2私钥死守,谁拿到就能冒充你
存密码用慢速哈希,SM3必须加迭代+盐
现在你知道了——每次在快餐店App上点外卖,订单号、快递袋、电子指纹,就是国密算法的日常运转。🍔📱🔐