“
这是一篇自我放飞文,因为严肃起来我啥也不懂。我就想看看,substrate 说的高度模块化,到底有多高。demo 地址:
https://github.com/hammeWang/substrate-sm2github.com[1]
Substrate 一出道的定位就是:一个高度模块化的区块链开发框架。但是 高度模块化
这五个字,就像是李佳琪口中的 "amazing" 一样:平均每 10 个口红中,就会产生 11 个 amazing.
我想用自己为数不多的知识,挑战一下 Substrate 模块化的“天花板”到底在哪里(都说有新手光环,作为一个菜鸡就应该有 就算遇到 bug 也要让 bug 后悔出现
的勇气)。所以,给自己定了一个小目标,给 substrate 新增一个签名方式:国密算法。
作为密码学小白(纯白),毫无疑问第一步是研究一下国密。
一言以蔽之:我国自主研发风险可控的一系列密码标准 SM 系列:包括 SM1, SM2, SM3, SM4, SM7, SM9...
其中 SM2 和 SM9 是非对称算法,SM3 是哈希算法。SM2 和 SM3 是配合使用的。
国家密码管理局关于发布《SM2 椭圆曲线公钥密码算法》公告(国密局公告第 21 号)_国家密码管理局 www.sca.gov.cn[2]
毫无疑问接下来,我需要一个轮子。这里感谢 CITA[3] 团队,已经写好了 SM2 和 SM3 的 Rust 实现。
选好了算法和轮子,但是如果一点加密学的基础知识都没有的话,也是没法看懂代码的。这里推荐经典的入门系列短文:
ECC: agentle Introductionandrea.corbellini.name[4]
看完之后至少得明白以下几个概念:
只要耐心读完一遍的话,这些概念是不难懂的,完全不劝退。懂了这些点之后,就可以看懂 SM2 的代码结构了。
参考了一下 Substrate 里已经集成的 ecdsa, ed25519 和 sr25519
,发现模块化的天花板,果然还是比我站起来还要高几倍的:只要实现了 crypto
中的两个 trait
就可以了:Public
和 Pair
。看命名就知道,一个定义了公钥相关的操作,就一个定义了公私钥对的相关操作。
具体代码在:
paritytech/substrategithub.com
理论上只要为 SM2 的公私钥实现了对应的方法,然后就没问题了。
因为 SM2 和 ecdsa 比较相似,包括签名和公私钥的格式和 ECC 概念的理解,所以这里我们参考了 ecdsa 中的 Public 和 Signature 的数据类型。缩短了原型验证的时间。当然想完全重新自定义也是没有毛病的,来倾听下 bug 的内心 OS:
img
“
“不了不了,我不飘,你也放下刀。”
我一开始很纠结要不要重新实现一遍 no-std 版本的 libsm,后来看到 substrate 中验证的逻辑都要走 #[runtime_interface]
,就不纠结了。
这一步的难点在于如何把 substrate 中的新类型和 libsm 中的原有类型做相互转换,所以看懂 ECC 中的相关概念在这里就起了很大帮助。
在实现了 Public 和 Pair
trait 之后,我们需要像 substrate 一样封装出一个 MultiSignature
和 MultiSigner
, 这样就可以兼容不同的签名算法。
在 MultiSigner
、MultiSignature
和 SM2 的 Signature 之间,如之前提到过,我们需要自定义一个 #[runtime_interface]
来帮助减少对 libsm 的修改的工作量。
在实现完 SM2 到 MultiSigner 和 MultiSignature 的封装之后,我们只需要简单的把 runtime/lib.rs
里的 MultiSignature
换成自定义类型即可。
这里主要是 fork 了:
paritytech/substrate-subxtgithub.com
Subxt 可以理解成给 substrate node 发送和监听交易的工具。
关于 substrate-subxt 的介绍,可以参考吴博的:
网页链接 mp.weixin.qq.com
fork 的原因主要是以下两点:
MultiSignature
耦合很紧,必须魔改了才可以用如果 subxt 可以用 SM2 中的方法签名并且交易执行成功,那我们的原型就基本可行了。这里我们就测试一下基本的 balances.transfer
的方法。
这里需要注意一下的是,操作转账的账户里得有足够的余额,所以我们需要先在 node/hide/chain_spec.rs
里为我们的信仰(账户)充值。
在 Subxt 里只要把 signer 和 dest 修改成 SM2 中的相关类型就可以了 (signer 必须有余额)。
魔改之后,只需要启动 node-template --dev
之后,再执行 subxt 中的 main 就可以了。这时如果成功,交易发送和验证执行成功,控制台就会出现:
Balance transfer success: value: 10000
虽然 SM2 和 ecdsa 原理很相似,但是最大的不同是 SM2 没办法从签名 recover 出公钥,这就意味着在验证的时候,我们要不然就得把全局变量 AccountId32
改成 AccountId33 (33bytes)
,但是这样就和 Substrate 的地址格式会冲突,详见:
https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)github.com
要不然我们就得把 33bytes 的公钥压缩成 32 位。
如果修改 AccoutId32
,等待我们的将是巨大的工作量,所以在理解了公钥的字段含义,这里选择了牺牲性能,每笔交易做了两次验证。
作为加密学小白,并且在完全不用理解 Substrate 中消息的发送和验证环节的情况下,我们还是简单地实现了 SM2 的集成,奇迹的背后貌似只有【高度模块化】这个答案了。感谢新手光环~!
期待可以看到社区中更加魔幻的作品。
img
友情提醒,不要直接用于生产环境。
demo 地址:
https://github.com/hammeWang/substrate-sm2github.com[5]
@ 金晓 [6]
关于 substrate std 和 no-std 边界的深刻分析,这里推荐金晓的:
金晓:Substrate 入门 - Runtime 的 wasm 与 native -(九)
@ 冯力全 [7]
时机绝佳的资料推荐,wink~
声明:本文经作者「王大锤」授权,转载自知乎专栏「Substrate 101」,原文 https://zhuanlan.zhihu.com/p/134138900
[1]
[2]
国家密码管理局关于发布《SM2 椭圆曲线公钥密码算法》公告(国密局公告第 21 号)国家密码管理局 www.sca.gov.cn:_https://link.zhihu.com/?target=http%3A//www.sca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml
[3]
CITA:https://link.zhihu.com/?target=https%3A//github.com/citahub/libsm
[4]
ECC: agentle Introductionandrea.corbellini.name:https://link.zhihu.com/?target=https%3A//andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/
[5]
[6]
@ 金晓 :https://www.zhihu.com/people/cb3b97fbae2e613fba0f76e7bd23fc76
[7]
@ 冯力全 :https://www.zhihu.com/people/aa86e9f179d6f1448781aed6027a81c9
https://github.com/paritytech/substrate
https://github.com/paritytech/polkadot
https://bootcamp.web3.foundation/
更多内容:
Substrate VS Smart Contracts 1
扫码关注公众号,回复 “1” 加入波卡群
关注 PolkaWorld
发现 Web 3.0 时代新机遇
点个 “在看” 再走吧!
声明:本内容为作者独立观点,不代表 CoinVoice 立场,且不构成投资建议,请谨慎对待,如需报道或加入交流群,请联系微信:VOICE-V。
简介:波卡(Polkadot)第一中文社区,带你寻找 Web 3.0 时代新机遇!
评论0条