FISCO BCOS 零知识证明 Fiat-Shamir 实例源码

Posted 软件工程小施同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FISCO BCOS 零知识证明 Fiat-Shamir 实例源码相关的知识,希望对你有一定的参考价值。

Fiat-Shamir 零知识证明协议

场景介绍

一般用户在网站注册账号的时候,网站会要求用户设置一个密码,然后在后台保存这个密码,用户登录网站的时候要求再输入这个密码,与后台保存的密码进行比较,确定是否给用户登录权限,但这种时候用户的密码容易受到字典攻击,有一些安全意识的网站会加盐保存密码的hash,增加敌手穷举用户密码或撞库的难度。但用户密码保存在网站后台服务器上始终增加了泄露的风险,Fiat-Shamir零知识证明协议可以允许用户向注册的网站证明自己知道自己的密码,而不向网站泄露任何关于密码的信息。

Fiat-Shamir with secret password

首先Peggy(证明者,Prover)与Victor(验证者,Verifier)就公开参数(一个素数n,一个模n群的生成元g)达成共识。

  1. Peggy首先选择她的密码,然后对密码进行哈希,把结果转成整型数值x。
x=int(Hash(passowrd))
y=g^x mod n

Peggy 把y的值发给 Victor,让他保存

  1. 现在Peggy想要登录,她选择一个随机数v,计算
t = g^v mod n

然后把t的值发给Victor

  1. Victor收到t,然后发送随机数c给Peggy
  2. Peggy生成随机数v,计算
r =v -cx mod (n-1) 

Peggy把r发送给Victor

  1. Victor计算
val=(g^r)(y^c) mod n

然后判断val与t是否相等,若相等,则Peggy证明了自己知道密码,然后允许Peggy登录。

使用

源码

SmartDev-Contract/contracts/common_tools/privacy_computation/Fiat-Shamir-ZK at master · WeBankBlockchain/SmartDev-Contract · GitHub

将FiatShamir.sol部署到区块链

0x0a49ecf4d04e32769bdb210ee5be64e5171d5b59

1. 在链下使用contract_step1.py 计算 y值,然后在FiatShamir.sol中调用Step1_register 将y值登记。

2. 在链下使用contract_step2.py 计算 t值, 然后在FiatShamir.sol中调用Step2_login 传递t值。

 3. 在FiatShamir.sol中调用Step3_randomchallenge 生成c值。

4. 查看c值并使用contract_step45.py 计算r值。

v是一个随机数,在第2步中生成

5.在FiatShamir.sol中调用Step45_verify ,输入r值,输出true 或 false,表示验证通过与否。

结果通过

 尝试一个其它的

其中各个函数的输入通过 链下运行 contract_step1.py 计算 y,contract_step2.py 计算t, contract_step45.py 计算r 。

fiat_shamir_1.py 为整个交互过程的参考代码

参考文献

[1] Fiat, Amos, and Adi Shamir. “How to prove yourself: Practical solutions to identification and signature problems.” Conference on the Theory and Application of Cryptographic Techniques. Springer, Berlin, Heidelberg, 1986.

文档:

Fiat-Shamir 零知识证明协议 — WeBankBlockchain-SmartDev-Doc v2.6.0 文档

contract_step1.py

import libnum
import hashlib
n=8269
g=11

password = "Hello"

print("Password:\\t\\t",password)
x = int(hashlib.sha256(password.encode()).hexdigest()[:8], 16) % n
print("Password hash(x):\\t",x,"\\t (last 8 bits)")

print('\\n======Phase 1: Peggy sends y to Victor,Victor store y as Peggy\\' token==================')
y= pow(g,x,n)
print('y= g^x mod P=\\t\\t',y)

contract_step2.py

import libnum
import hashlib
import random
n=8269
g=11

v = random.randint(1,n)

print('\\n======Phase 2: Peggy wants to login , She send t to Victor==================')
v = random.randint(1,n)
t = pow(g,v,n)
print('v=',v,'\\t(Peggy\\'s random value)')
print('t=g**v % n =\\t\\t',t)

contract_step45.py

import libnum
import hashlib
import random
n=8269
g=11

password = "Hello"
x = int(hashlib.sha256(password.encode()).hexdigest()[:8], 16) % n


print('\\n======Phase 4: Peggy recieves c and calculate r=v-cx, sends r to Victor==================')
c = input("c= ")
v = input("v= ")
r = (int(v) - int(c) * x) % (n-1)

print('c=\\t\\t',c)
print('v=\\t\\t',v)
print('r=v-cx =\\t\\t',r)

fiat_shamir_1.py

import sys
import random
import hashlib
import libnum

n=8269
password="Hello"
g= 11

v = random.randint(1,n)
c = random.randint(1,n)


print("Password:\\t\\t",password)
x = int(hashlib.sha256(password.encode()).hexdigest()[:8], 16) % n
print("Password hash(x):\\t",x,"\\t (last 8 bits)")


y= pow(g,x,n)

t = pow(g,v,n)

r = (v - c * x) % (n-1)

Result = ( pow(g,r,n) * pow(y,c,n))  % n

print('\\n======Phase 0: Agreed parameters============')
print('P=',n,'\\t(Prime number)')
print('G=',g,'\\t(Generator)')

print('\\n======Phase 1: Peggy sends y to Victor,Victor store y with Peggy ==================')
print('y= g^x mod P=\\t\\t',y)

print('\\n======Phase 2: Peggy wants to login , She send t to Victor==================')
print('v=',v,'\\t(Peggy\\'s random value)')
print('t=g**v % n =\\t\\t',t)

print('\\n======Phase 3: Victor choose c randomly ,and sends it to Peggy==================')
print('c=',c,'\\t(Vitor\\' random challenge)')

print('\\n======Phase 4: Peggy recieves c and calculate r=v-cx, sends r to Victor==================')
print('r=v-cx =\\t\\t',r)

print('\\n======Phase 5: Victor calculates (g^r)*(y^c)== t? ==================')
print('t= % n =\\t\\t',t)
print('( (g**r) * (y**c) )=\\t',Result)
if (t==Result):
	print('\\nPeggy has proven she knows password')
else:
	print('\\nPeggy has not proven she knows x')

FiatShamir.sol

pragma solidity >=0.4.16 <0.9.0;

contract FiatShamir 
    //============Phase 0: Agreed parameters===================
    // prime
    uint public n = 8269;
    // generator
    uint public g = 11;
    //=========================================================
    
    // g^x mod n
    uint y;
    // Victor's random challenge
    uint public c;
    // peggy sends random t 
    uint t;
    
    //======Phase 1: Peggy sends y to Victor,Victor store y as Peggy' token==================
    // peggy registers with y,  y = g^x mod n
    function Step1_register( uint _y) public 
        y = _y;
    
    //=======================================================================================
    
    //======Phase 2: Peggy wants to login , She send t to Victor=============================
    function Step2_login(uint _t) public 
        t = _t;
    
    //=======================================================================================
    
    //======Phase 3: Victor choose c randomly ,and sends it to Peggy=========================
    function Step3_randomchallenge() external returns (uint)
        c = randomgen();
        return c;
    

    //TODO : NOT secure , low entropy ,change random source.
    function randomgen() private view returns (uint) 
        return uint(keccak256(abi.encodePacked(block.timestamp))) % n;
    
    //=======================================================================================
    
    //======Phase 4: Peggy recieves c and calculate r=v-cx, sends r to Victor================
    //======Phase 5: Victor calculates (g^r)*(y^c)== t? =====================================
    function Step45_verify(uint r) public  returns (bool)
        uint256 result = 0;
        
        result = (modExp(g,r,n)*modExp(y,c,n)) % n;
        
        return t == result;
    
    //=======================================================================================
    

    // modular algorithm : calculate  b**e mod m
    function modExp(uint256 _b, uint256 _e, uint256 _m) private returns (uint256 result) 
        assembly 
            // Free memory pointer
            let pointer := mload(0x40)

            // Define length of base, exponent and modulus. 0x20 == 32 bytes
            mstore(pointer, 0x20)
            mstore(add(pointer, 0x20), 0x20)
            mstore(add(pointer, 0x40), 0x20)

            // Define variables base, exponent and modulus
            mstore(add(pointer, 0x60), _b)
            mstore(add(pointer, 0x80), _e)
            mstore(add(pointer, 0xa0), _m)

            // Store the result
            let value := mload(0xc0)

            // Call the precompiled contract 0x05 = bigModExp
            if iszero(call(not(0), 0x05, 0, pointer, 0xc0, value, 0x20)) 
                revert(0, 0)
            

            result := mload(value)
        
    

以上是关于FISCO BCOS 零知识证明 Fiat-Shamir 实例源码的主要内容,如果未能解决你的问题,请参考以下文章

FISCO-BCOS平台共识

FISCO BCOS源码基本概念

FISCO BCOS源码编译源码 获取FISCO BCOS可执行程序

区块链入门教程--FISCO BCOS单机四节点联盟链安装

FISCO BCOS 负载均衡

安装FISCO-BCOS的那些坑