一般而言,密码学承诺的应用涉及承诺方、验证方两个参与方,以及以下两个使用阶段。
第一阶段为承诺生成(Commit)阶段,承诺方选择一个敏感数据v,计算出对应的承诺c,然后将承诺c发送给验证方。通过承诺c,验证方确定承诺方对于还未解密的敏感数据v只能有唯一的解读方式,无法违约。
第二阶段为承诺披露(Reveal)阶段,学术界通常也称之为承诺打开-验证(Open-Verify)阶段。承诺方公布敏感数据v的明文和盲化因子(相当于秘钥),验证方重复承诺生成的计算过程,比较新生成的承诺与之前接收到的承诺c是否一致,一致则表示验证成功,否则失败。
一个设计良好的密码学承诺具备如下特性:
所以,密码学承诺可以起到与日常生活中的承诺行为类似的效果,一旦做出承诺,就必须在披露阶段使用之前已经承诺的敏感数据。对应地,在业务系统中,承诺生成阶段通常被用来生成密文形式的业务数据,而承诺披露阶段则多被用于在特定业务流程中进行数据校验。除了直接公布敏感数据明文之外,承诺披露阶段所需的数据校验,也可以在不公布敏感数据明文的前提下,构造零知识证明来完成。
Pedersen承诺是一个满足完美隐藏、计算绑定的同态承诺协议,其完美隐藏性不依赖与任何困难性假设,计算绑定依赖于离散对数假设(DLA),其构造分为3个阶段:
Pedersen承诺的同态性是指,如果comm1,comm2分别是使用盲因子r1,r2的对v1,v2的承诺,则comm (comm=comm1*comm2)是使用盲因子 r1+r2 对 v1+v2 的承诺,即 comm=comm(v1,r1)*comm(v2,r2)=(g^{v_1}h^{r_1})*(g^{v_2}h^{r_2})=g^{v_1+v_2}h^{r_1+r_2}
设v1+v2=v3,向验证者提供证明v1,v2,v3的关系,但是又不能让验证者知道v1,v2,v3的明文值,因此可以使用Pedersen承诺的同态性来解决这个问题,即只需要验证其盲因子r1+r2 ?= r3。
如果证明方知道验证方的验证方式是验证 r1+r2=?r3,故意构造一个r3==r1+r2,验证方如何防止证明方作弊呢?由于元祖(g,h,q)是公开的,验证方可以根据盲因子r1来构造一个承诺 comm'(v1,r1) ,验证与接收到的comm(v1,r1)是否是相等。
每个银行 i 还会生成一个Schnorr签名密钥对,该密钥对由秘密密钥 sk_i 和公共密钥 pk_i=h^{sk_i} 组成,并将公共密钥 pk_i 分发给所有其他系统参与者。
图1显示了zkLedger的总体设计。 有些银行可以确定交易范围,然后通过将交易追加到分布式账本来进行结算。分布式帐本确保所有银行和任何审计员都看到新交易。 每个银行和审计师都维护一个承诺缓存。 每个银行还具有纯文本交易数据的专用存储。
总共有三个主体对象,分别是银行,账本和审计员。前两者有自己的本地数据库,存储自己的私密信息。三者通过分布式账本连在一起。
审计一个银行当前的资产?考虑查询被审计银行所在列中的值的总和。
方法一:根据 Pedersen Commitment, 可以构造这样的等式 comm(v_1,r_1)*comm(v_2,r_2)...*comm(v_m,r_m)=(g^{v_1}h^{r_1})*(g^{v_2}h^{r_2})*...*(g^{v_m}h^{r_m})=g^{v_1+v_2+...+v_m}h^{r_1+r_2+...+r_m}=g^{\sum^m_{i=1} v_i}h^{\sum^m_{i=1} r_i}
m表示从开始到当前某个银行的所有交易数量,vi表示第i交易的数额,ri表示第i交易的致盲因子(或者说密钥)。
所以首先银行 Bank_k 提供 \sum v_k,\sum r_k 。 然后,审核员将简单地检查这些原始值是否与同态计算值是否一致? \prod cm_k ?= g^{\sum v_k} h^{\sum r_k} 如果等式成立,表示该银行的账单没问题。
存在的问题:但是,银行不一定知道所有的承诺随机数rk(特别是对于银行不参与的任何交易,这些值都是未知的),账单表格中的每一行数据是由该交易的发起者构建生成的,其它银行是不知情的,也就是每一个单元格中的致盲因子 r_k 只有该行交易的发起者知道。这就有问题了,因为根据上面所述的方法,在审计员审计一个银行的时候,需要该银行提供给审计员 \sum v_k 。
方法二:在每一个单元格中增加一个Token,计算方法为 Token_k=(pk_k)^{r_k} , 其中 pk_k 是椭圆曲线上一个点,也是银行 Bank_k的公钥,r_k 表示致盲因子(椭圆曲线算法)。
银行不需要 \sum r_k 计算 h^{\sum r_k}即可证明 \sum v_k 是正确的。银行向审计员提供的 \sum v_k 。
审计员计算s=\prod cm_k, s'=s/g^{\sum v_k} 和 t=\prod_k Token_k=h^{{sk}_k\sum r_k}。 审计员判断 log_{s'}\ t?=log_h \ pk 。
证明:如果相等的话,则 s=g^{\sum v_k}h^{\sum r_k} ,s'=h^{\sum r_k} ,则 log_{s'}\ t=log_h \ pk \Longrightarrow log_{h^{\sum r_k}}\ h^{sk_k\sum r_k}=log_h\ h^{sk_k}\Longrightarrow \frac{sk_k\sum r_k}{\sum r_k}=sk_k 。证明结束。
这里,审计令牌(audit token)仅对银行履行承诺有用。 尽管是公开的,但恶意银行无法使用其他银行的令牌成功打开错误的结果或了解有关其他银行交易的信息。
对于行 m 中的一条转帐交易,每个条目 i 包含以下项目:
事务中是否可以包含其他纯文本格式的元数据。 例如,银行可能希望包括加密的帐号,地址或代表客户的识别信息,以满足1970年《银行保密法》中指定的规则。 zkLedger也支持对事务中的元数据进行审计,但是它没有公开验证其他元数据的方法。
zkLedger可以支持动态添加或删除银行。 参与者(或其他机构)将已签名的交易追加到分布式账本,以指示应添加或删除的银行,以及对应列。 例如,要将新的银行添加到图2所示的分类帐中,涉及的银行将向交易记录追加一笔交易,指示有意添加 Bank_{n+1}。 从那时起,所有交易应包含 n + 1 个条目。 每个交易中 Bank{n+1} 条目的资产证明将从添加 Bank{n+1} 的行开始。 同样,如果银行被移走,以后的交易不应包括该银行的分录。 由于所有参与者都可以看到添加或删除了哪些银行,因此他们可以相应地调整其证明和验证。
1.缓存 2.提前计算交易值0。
考虑一个审计师想要知道给定银行和资产的平均交易规模。 审计员不能简单地通过合计银行列的承诺总值除以行数来验证银行的答案,因为这样的计算会有不正确的分母。 即,当银行不参与交易时,交易所在行中的承诺列值将为0。为了确定正确的分母,审计员和银行执行以下协议:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。