新闻开发人员企业区块链解释事件和会议新闻时事通讯
订阅我们的新闻.
电子邮件地址
我们尊重您的隐私
主页博客区块链开发
zk-SNARKs简介
零知识证明概述以及如何将zk-SNARKs集成到以太坊。由ConsenSys 2017年3月27日发布于2017年3月27日
在这篇文章中,我们旨在从实际角度概述zk-SNARK。我们将把实际的数学视为一个黑匣子,并尝试就如何使用它们产生一些直觉。我们还将简单应用一下有关以下方面的最新工作: 在以太坊中整合zk-SNARKs.
零知识证明
零知识证明的目的是使验证者能够说服自己证明者具有秘密参数(称为见证人)的知识,并且满足某种关系,而无需向验证者或其他任何人透露见证人。.
我们可以更具体地认为它有一个表示为C的程序,它接受两个输入:C(x,w)。输入x是公共输入,而w是秘密见证人输入。程序的输出是布尔值,即true或false。然后为目标提供特定的公共输入x,证明证明者知道秘密输入w,使得C(x,w)== true.
我们将专门讨论非交互式零知识证明。这意味着证明本身就是一堆数据,无需证明者的任何交互就可以对其进行验证。.
范例程序
假设给Bob某个哈希值H,并且他希望证明Alice知道散列到H的值s。通常,Alice可以通过给s Bob来证明这一点,然后Bob将计算哈希值并检查它等于H.
但是,假设爱丽丝(Alice)不想向鲍勃(Bob)透露价值,而是只想证明自己知道价值。她可以为此使用zk-SNARK.
我们可以使用以下程序(描述为Javascript函数)来描述Alice的情况:
函数C(x,w){return(sha256(w)== x);}代码语言:JavaScript(javascript)
换句话说:程序接受一个公共哈希x和一个秘密值w,并且如果w的SHA–256哈希等于x,则返回true。.
使用函数C(x,w)转换爱丽丝的问题,我们看到爱丽丝需要创建一个证明她拥有s的证明,使得C(H,s)== true,而不必透露s。这是zk-SNARK解决的一般问题.
zk-SNARK的定义
zk-SNARK由三种算法G,P,V组成,其定义如下:
密钥生成器G接收一个秘密参数lambda和一个程序C,并生成两个公共可用的密钥,一个验证密钥pk和一个验证密钥vk。这些密钥是公共参数,对于给定的程序C仅需要生成一次.
证明人P将证明密钥pk,公开输入x和私人见证人w作为输入。该算法生成证明人知道证人w并且证人满足程序的证明prf = P(pk,x,w).
验证者V计算V(vk,x,prf),如果证明正确则返回true,否则返回false。因此,如果证明者知道证人w(C(x,w)== true),则此函数返回true.
请注意此处在生成器中使用的秘密参数lambda。有时,此参数使在实际应用程序中使用zk-SNARK变得棘手。这样做的原因是,知道此参数的任何人都可以生成伪造的证明。具体来说,给定任何程序C和公共输入x,知道lambda的人可以生成fake_prf证明,从而在不了解秘密的情况下V(vk,x,fake_prf)评估为true w.
因此,实际运行生成器需要非常安全的过程,以确保没有人知道并保存该参数到任何地方。这就是 精心制作的仪式 Zcash团队为了生成证明密钥和验证密钥而进行,同时确保在此过程中销毁了“有毒废物”参数lambda.
我们的示例程序的zk-SNARK
爱丽丝和鲍勃在实践中将如何使用zk-SNARK以便爱丽丝证明她知道上述示例中的秘密价值?
首先,如上所述,我们将使用由以下功能定义的程序:
函数C(x,w){return(sha256(w)== x); }代码语言:JavaScript(javascript)
第一步是让鲍勃运行发生器G,以创建证明密钥pk和验证密钥vk。首先,随机生成lambda并将其用作输入:
(pk,vk)= G(C,lambda)
请谨慎处理参数lambda,因为如果Alice了解了lambda的值,她将能够创建伪造的证明。鲍勃将与爱丽丝分享pk和vk.
爱丽丝现在将扮演证明者的角色。她需要证明自己知道散列到已知哈希H的值s。她使用输入pk,H和s运行证明算法P以生成证明prf:
prf = P(pk,H,s)
接下来,爱丽丝将证明prf提供给运行验证函数V(vk,H,prf)的鲍勃,在这种情况下,由于爱丽丝正确地知道秘密s,所以它将返回true。鲍勃(Bob)可以确信爱丽丝(Alice)知道秘密,但爱丽丝(Alice)无需向鲍勃(Bob)透露秘密。.
可重复使用的验证和验证密钥
在上面的示例中,如果Bob想要向Alice证明他知道秘密,则无法使用zk-SNARK,因为Alice无法知道Bob没有保存lambda参数。鲍勃貌似可以伪造证据.
如果某个程序对许多人有用(例如Zcash的示例),那么与Alice和Bob分开的受信任的独立组可以运行生成器并创建证明密钥pk和验证密钥vk,从而使任何人都不了解lambda。.
任何相信该小组没有作弊的人都可以使用这些密钥进行将来的交互.
以太坊中的zk-SNARK
开发人员已经开始将zk-SNARKs集成到以太坊中。看起来像什么?具体来说,您可以以预编译合同的形式将验证算法的组成部分添加到以太坊。方法如下:脱机运行生成器以生成证明密钥和验证密钥。然后,任何证明者都可以使用证明密钥来创建证明,也可以是脱链的。然后,您可以使用证明,验证密钥和公共输入作为输入参数,在智能合约中运行常规验证算法。然后,您可以使用验证算法的结果来触发其他链上活动.
示例:机密交易
这是zk-SNARKs如何帮助以太坊的隐私保护的简单示例。假设我们有一个简单的令牌合同。通常,令牌合约的核心是从地址到余额的映射:
映射(地址=> uint256)天平;代码语言:JavaScript(javascript)
我们将保留相同的基本核心,只是用balance的hash替换balance:
映射(地址=> bytes32)balanceHashes;代码语言:JavaScript(javascript)
我们不会隐藏交易的发送者或接收者。但是,我们将隐藏余额和已发送的金额。此属性有时称为 保密交易.
我们将使用两个zk-SNARK将令牌从一个帐户发送到另一个帐户。一份证明是由发送者创建的,而另一份是由接收者创建的.
通常,在令牌合约中,要使大小值有效的交易有效,我们需要验证以下内容:
余额[fromAddress] >=值
我们的zk-SNARK需要证明其成立,以及更新后的哈希值与更新后的余额匹配.
主要思想是发件人将其初始余额和交易价值用作私人输入。作为公共投入,他们使用开始余额,结束余额和价值的哈希值。同样,接收方将使用起始余额和值作为秘密输入。作为公共投入,他们使用起始余额,期末余额和价值的哈希值.
下面是我们将用于发送方zk-SNARK的程序,其中x代表公共输入,w代表私有输入.
函数senderFunction(x,w){return(w.senderBalanceBefore > 值 && sha256(w.value)== x.hashValue && sha256(w.senderBalanceBefore)== x.hashSenderBalanceBefore && sha256(w.senderBalanceBefore-w.value)== x.hashSenderBalanceAfter)}代码语言:JavaScript(javascript)
接收器使用的程序如下:
函数receiveFunction(x,w){return(sha256(w.value)== x.hashValue && sha256(w.receiverBalanceBefore)== x.hashReceiverBalanceBefore && sha256(w.receiverBalanceBefore + w.value)== x.hashReceiverBalanceAfter)}代码语言:JavaScript(javascript)
程序检查发送余额是否大于发送的值,并检查所有哈希是否匹配。一组受信任的人员将为我们的zk-SNARK生成证明和验证密钥。我们称它们为confTxSenderPk,confTxSenderVk,confTxReceiverPk和confTxReceiverVk.
在令牌合约中使用zk-SNARK看起来像这样:
函数传递(地址_to,bytes32 hashValue,bytes32 hashSenderBalanceAfter,bytes32 hashReceiverBalanceAfter,字节zkProofSender,字节zkProofReceiver){bytes32 hashSenderBalanceBefore = balanceHashes [msg.sender]; bytes32 hashReceiverBalanceBefore = balanceHashes [_to]; bool senderProofIsCorrect = zksnarkverify(confTxSenderVk,[hashSenderBalanceBefore,hashSenderBalanceAfter,hashValue],zkProofSender); bool receiverProofIsCorrect = zksnarkverify(confTxReceiverVk,[hashReceiverBalanceBefore,hashReceiverBalanceAfter,hashValue],zkProofReceiver);如果(senderProofIsCorrect && receiverProofIsCorrect){balanceHashes [msg.sender] = hashSenderBalanceAfter; balanceHashes [_to] = hashReceiverBalanceAfter; }}代码语言:JavaScript(javascript)
因此,区块链上唯一的更新是余额的哈希,而不是余额本身。但是,我们可以知道所有余额均已正确更新,因为我们可以检查自己是否已验证该证明。.
细节
上述机密交易方案主要是提供一个实际示例,说明如何在以太坊上使用zk-SNARK。要创建可靠的机密交易方案,我们需要解决许多问题:
- 用户将需要在客户端跟踪其余额,如果您丢失了余额,则这些令牌将不可恢复。可以使用从签名密钥派生的密钥将余额加密存储在链上加密状态.
- 天平需要使用32个字节的数据并对熵进行编码,以防止通过反向散列来找出天平的能力.
- 需要处理发送到未使用地址的极端情况.
- 发送方需要与接收方进行交互才能发送。可能会有一个系统,其中发件人使用其证据来发起交易。然后,接收者可以在区块链上看到他们有一个“待处理的传入交易”并可以完成交易.
订阅我们的时事通讯以获取最新的以太坊新闻,企业解决方案,开发人员资源等信息。网络研讨会
如何构建成功的区块链产品
网络研讨会
如何设置和运行以太坊节点
网络研讨会
如何构建自己的以太坊API
网络研讨会
如何创建社交令牌
网络研讨会
在智能合约开发中使用安全工具
网络研讨会