首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用ZoKrates写电路证明年龄超过21岁

用ZoKrates写电路证明年龄超过21岁
EN

Stack Overflow用户
提问于 2018-07-31 03:46:05
回答 2查看 539关注 0票数 4

我试图看看我是否可以在这样一个场景中使用ZoKrates,即用户可以向验证者证明年龄超过21岁,而不透露出生日期。我认为这是零知识证明的一个很好的用例,但我喜欢理解实现它的最佳方法。

电路代码(示例)将用户的名称作为公共输入(名称认证由DMV这样的可信机构完成,是脱机/在线机制的最有可能的组合),然后是一个私有输入的出生日期。

代码语言:javascript
复制
//8297122105 = "Razi" is decimal.
def main(pubName,private yearOfBirth, private centuryOfBirth):
  x = 0
  y = 0
  z = 0
  x = if centuryOfBirth == 19 then 1 else 0 fi
  y = if yearOfBirth < 98 then 1 else 0 fi
  z = if pubName == 8297122105 then 1 else 0 fi
  total =  x + y + z 
  result = if total == 3 then 1 else 0 fi

  return result 

现在,使用./target/release/zokrates generate-proof命令获取可用作verifier.sol输入的输出。

代码语言:javascript
复制
A = Pairing.G1Point(0x24cdd31f8e07e854e859aa92c6e7f761bab31b4a871054a82dc01c143bc424d, 0x1eaed5314007d283486826e9e6b369b0f1218d7930cced0dd0e735d3702877ac);
A_p = Pairing.G1Point(0x1d5c046b83c204766f7d7343c76aa882309e6663b0563e43b622d0509ac8e96e, 0x180834d1ec2cd88613384076e953cfd88448920eb9a965ba9ca2a5ec90713dbc);
B = Pairing.G2Point([0x1b51d6b5c411ec0306580277720a9c02aafc9197edbceea5de1079283f6b09dc, 0x294757db1d0614aae0e857df2af60a252aa7b2c6f50b1d0a651c28c4da4a618e], [0x218241f97a8ff1f6f90698ad0a4d11d68956a19410e7d64d4ff8362aa6506bd4, 0x2ddd84d44c16d893800ab5cc05a8d636b84cf9d59499023c6002316851ea5bae]);
B_p = Pairing.G1Point(0x7647a9bf2b6b2fe40f6f0c0670cdb82dc0f42ab6b94fd8a89cf71f6220ce34a, 0x15c5e69bafe69b4a4b50be9adb2d72d23d1aa747d81f4f7835479f79e25dc31c);
C = Pairing.G1Point(0x2dc212a0e81658a83137a1c73ac56d94cb003d05fd63ae8fc4c63c4a369f411c, 0x26dca803604ccc9e24a1af3f9525575e4cc7fbbc3af1697acfc82b534f695a58);
C_p = Pairing.G1Point(0x7eb9c5a93b528559c9b98b1a91724462d07ca5fadbef4a48a36b56affa6489e, 0x1c4e24d15c3e2152284a2042e06cbbff91d3abc71ad82a38b8f3324e7e31f00);
H = Pairing.G1Point(0x1dbeb10800f01c2ad849b3eeb4ee3a69113bc8988130827f1f5c7cf5316960c5, 0xc935d173d13a253478b0a5d7b5e232abc787a4a66a72439cd80c2041c7d18e8);
K = Pairing.G1Point(0x28a0c6fff79ce221fccd5b9a5be9af7d82398efa779692297de974513d2b6ed1, 0x15b807eedf551b366a5a63aad5ab6f2ec47b2e26c4210fe67687f26dbcc7434d);

问题

考虑一个场景,当用户(例如Razi)能够获得上面的证据(可能以QR代码的形式)并在一台机器上扫描它(确认年龄超过21岁),该机器将在合同上运行verifierTx方法。由于证据中明确含有"Razi“的证据和合同,可以在不知道实际出生日期的情况下对年龄进行核实,从而获得更好的隐私。然而,现在的挑战是,其他任何人都可以重用该证据,因为它是在事务中使用的。缓解这一问题的一种方法是确保证据在有限的时间内有效,或者(可能只适合一次性使用)。另一种方法是确保用户身份的证明("Razi"),其方式是毫无疑问地得到满足(例如,在区块链上确认身份等)。

是否有办法确保用户可以不止一次使用证明?

我希望这个问题和解释是有意义的。很高兴对此作更详细的说明,所以请告诉我。

EN

回答 2

Stack Overflow用户

发布于 2019-01-09 21:43:17

你需要的是:

  • Razi拥有ethereum公钥/私钥
  • (咸的)指纹事实(如生日为unix时间戳),与Razi的公共地址相关,并由权威机构在链上签名

现在您可以编写这样的ZoKrates程序了

代码语言:javascript
复制
def main(private field salt, private field birthdayAsUnixTs, field pubFactHashA, field pubFactHashB, field ts) -> (field)
    // check that the fact is corresponding to the endorsed salted fact fingerprint onchain
    h0, h1 = sha256packed(0,0,salt,birthdayAsUnixTs)
    h0 == pubFactHashA
    h1 == pubFactHashB

    // 18 years is pseudo code only!
    field ok = if birthdayAsUnixTs * 18 years <= ts then 1 else 0 fi

    return ok

现在在你的合同里你可以

  • 检查msg.sender是否拥有认可的事实
  • 要求(ts,<=,现在)
  • 具有证明和公共输入的调用验证器:(factHash,ts,1)
票数 1
EN

Stack Overflow用户

发布于 2019-12-31 16:02:40

您可以通过散列该证明并将该散列添加到“使用过的证据”列表中来实现这一点,因此没有人可以再次使用它。

现在,ZoKrates在生成证据时增加了随机性,以防止发现使用了相同的证人,因为about没有显示任何关于证人的信息。所以,如果你想阻止这个人不止一次地使用他的证书(授权他超过21岁),你必须使用一个否定者(参见“如何应用zk-SNARKs来创建一个屏蔽的事务”部分中的ZCash方法)。

基本上,您使用一个字符串和Razi nullifier_string = centuryOfBirth+yearOfBirth+pubName的数据,然后在一个表中发布Hash nullifier = H(nullifier_string)。在ZoKrates方案中,必须将零值作为公共输入添加,然后验证零值符是否对应于所提供的数据。就像这样:

代码语言:javascript
复制
import "utils/pack/unpack128.code" as unpack
import "hashes/sha256/256bitPadded.code" as hash
import "utils/pack/nonStrictUnpack256.code" as unpack256

def main(pubName,private yearOfBirth, private centuryOfBirth, [2]field nullifier):

  field x = if centuryOfBirth == 19 then 1 else 0 fi
  field y = if yearOfBirth < 98 then 1 else 0 fi
  field z = if pubName == 8297122105 then 1 else 0 fi
  total =  x + y + z 
  result = if total == 3 then 1 else 0 fi

  null0 = unpack(nullifier[0])
  null1 = unpack(nullifier[1])
  nullbits = [...null0,...null1]

  nullString = centuryOfBirth+yearOfBirth+pubName
  unpackNullString = unpack256(nullString)

  nullbits == hash(unpackNullString)


  return result 

为了防止Razi提供一个与他的数据无关的随机零值器,必须这样做。

一旦您这样做了,您可以检查是否已经使用了所提供的否定符,如果它已注册在显示的否定符表中。

在你的例子中,这个问题是出生年份是一个薄弱的数字。有人可以对否认者进行暴力攻击,并透露Razi出生的年份。您必须在验证中添加一个强数字(Razi秘密ID?数字签名?)以防止这次袭击。

Note1:我有一个旧版本的ZoKrates,所以检查导入路径正确。

Note2:检查ZoKrates哈希函数实现,您可能有输入填充的问题,ZoKrates函数阻止了这一点,但是您可以反复检查以防止错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51605174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档