Web 3 的世界近在咫尺

本文介绍了如何使用 Rust 编写零知识证明(ZKP)并在 WebAssembly (WASM) 中集成,从而在浏览器中运行 ZKP。文章展示了如何使用 wasm-pack 构建 WASM 文件,并在 HTML 中通过 JavaScript 桥接调用 Rust 代码实现 ZKP 的生成、证明和验证过程,使得在 Web 应用中实现隐私保护和可信计算成为可能。

Web 3 的世界近在咫尺

浏览器中的 ZKP!

随着数据泄露事件的增加,许多人梦想着这样一个世界:我们可以在不泄露敏感数据的情况下信任事物。为此,一个私有和可信世界的关键要素之一是使用零知识证明 (ZKP)。但是,由于安全性和性能问题,区块链和 Web 的世界可能是分离的。主要的改变是 WebAssembly 的使用,它使我们有机会在浏览器中运行原生代码,并在客户端的机器上运行。这包括与 Rust 和 C 的集成。有了这个,我们现在可以暴露复杂的软件库,而无需将代码翻译成 JavaScript。

因此,作为一名 Rust 程序员,可以想象一下用 Rust 构建代码,然后简单地在 HTML 中创建一个桥梁来调用代码。那么,让我们用 WebAssembly 实现一个 ZKP,并使用 Rust 编码来实现 ZKP。

ZK-WASM

ZK-WASM 将 Rust 中的零知识证明 (ZKP) 集成到 WebAssembly (WASM) [1] 中。Rust 可执行代码之间的一个桥梁,它在 HTML 文件中提供了一个 JavaScript 桥梁,与 ZK-WASM 功能进行交互。

要构建 WASM 文件,我们首先使用以下命令安装 wasm-pack:

cargo install wasm-pack

然后我们下载 [1] 中的代码,然后运行 wasm-pack:

> wasm-pack build --target web --out-dir ./bridge
[INFO]: Checking for the Wasm target...
info: downloading component 'rust-std' for 'wasm32-unknown-unknown'
info: installing component 'rust-std' for 'wasm32-unknown-unknown'
 19.7 MiB /  19.7 MiB (100 %)  11.4 MiB/s in  1s
[INFO]: Compiling to Wasm...
   Compiling autocfg v1.4.0
   Compiling proc-macro2 v1.0.95
   Compiling unicode-ident v1.0.18
   Compiling num-traits v0.2.19
   Compiling proc-macro2 v0.4.30
   Compiling unicode-xid v0.1.0
   Compiling quote v1.0.40
...

这将生成一个包含所有 WASM 制品的 bridge 文件夹:

package.json
README.md
zk-wasm.html
zk_wasm.d.ts
zk_wasm.js
zk_wasm_bg.wasm
zk_wasm_bg.wasm.d.ts

然后可以将它们放置在服务器上,并与 HTML 文件链接。

代码的集成非常容易:

<script type="module">
    import init, { generate, prove, verify } from "/zk_wasm.js";
    init().then(() => {
        window.generate = generate;
        window.prove = prove;
        window.verify = verify;
    }).catch((e) => {
        console.error(e);
    });
</script>

最耗时的任务是生成密钥:

 function getSeed() {
                    var seed = new Uint32Array(8);
                    self.crypto.getRandomValues(seed);
                    return seed;
                }

async function execGenerate() {
           const key = await generate(getSeed()).params;

           document.getElementById("Key").innerHTML = "Length:" + key.length+"\n";
           document.getElementById("Key").innerHTML += "Key (showing first 500 bytes):" +key.substring(0, 1000);
           window.key = key;
           document.getElementById("genkey").style.visibility = "visible";

                }

生成证明并验证代码是:


async function execProve() {
           var xln = document.getElementById("message").value;
                    let p = await window.prove(getSeed(), window.key,xln);
                    window.h = p.h;
                    window.proof = p.proof;

           document.getElementById("H").innerHTML = p.h ;
           document.getElementById("Proof").innerHTML =  p.proof;
                     const v = await window.verify(window.key, window.proof, window.h);

          document.getElementById("Verify").innerHTML =  v.result.toString();

}

代码如下:

<style>
    .dropdown {
        font-size: 16px;
        border: 2px solid grey;
        width: 100%;
        border-left: 12px solid green;
        border-radius: 5px;
        padding: 14px;
    }pre {
        font-size: 16px;
        border: 2px solid grey;
        width: 100%;
        border-left: 12px solid green;
        border-radius: 5px;
        padding: 14px;
    }
    textarea {
        font-size: 20px;
        border: 2px solid grey;
        width: 100%;
        border-radius: 5px;
        padding: 14px;
    }
</style>

<div class="indented">

    <h2>zkSnark</h2>
    <table width="100%">
        <tr>
            <th width="15%" valign="top">Generate key</th>
            <td style="text-align:left">
                <p>
                    <input id="genkey" class="btn btn-large btn-primary" type="button" value="Generate Key" />
                    <input id="proof" class="btn btn-large btn-primary" type="button" value="Proof" />
                    <input id="verify" class="btn btn-large btn-primary" type="button" value="Verify" />
                </p>

            </td>
        </tr>

    </table>
    <h2>Generated keys</h2>
    <table width="100%">
        <tr>
            <th width="15%" valign="top">Value to prove</th>
            <td>
                <textarea cols="20" id="message" name="message" rows="1" style="width:100%"></textarea>
            </td>
        </tr>
        <tr>
            <th width="15%" valign="top">Key</th>
            <td>
                <pre id="Key"></pre>

            </td>
        </tr>
        <tr>
            <th width="15%" valign="top">H</th>
            <td>
                <pre id="H"></pre>

            </td>
        </tr>
        <tr>
            <th width="15%" valign="top">Proof</th>
            <td>
                <pre id="Proof"></pre>

            </td>
        </tr>
        <tr>
            <th width="15%" valign="top">Verify</th>
            <td>
                <pre id="Verify"></pre>

            </td>
        </tr>

    </table>

</div>
<script type="module">
    import init, { generate, prove, verify } from "/zk_wasm.js";
    init().then(() => {
        window.generate = generate;
        window.prove = prove;
        window.verify = verify;
    }).catch((e) => {
        console.error(e);
    });
</script>
   <script>

            const toHexString = (bytes) => {
                return Array.from(bytes, (byte) => {
                    return ('0' + (byte & 0xff).toString(16)).slice(-2);
                }).join('');
            };

                function getSeed() {
                    var seed = new Uint32Array(8);
                    self.crypto.getRandomValues(seed);
                    return seed;
                }
       function hidebutton() {
           document.getElementById("genkey").style.visibility = "hidden";
       }
       async function execGenerate() {
           const key = await generate(getSeed()).params;

           document.getElementById("Key").innerHTML = "Length:" + key.length+"\n";
           document.getElementById("Key").innerHTML += "Key (showing first 500 bytes):" +key.substring(0, 1000);
           window.key = key;
           document.getElementById("genkey").style.visibility = "visible";

                }
       async function execProve() {
           var xln = document.getElementById("message").value;
                    let p = await window.prove(getSeed(), window.key,xln);
                    window.h = p.h;
                    window.proof = p.proof;

           document.getElementById("H").innerHTML = p.h ;
           document.getElementById("Proof").innerHTML =  p.proof;
                     const v = await window.verify(window.key, window.proof, window.h);

          document.getElementById("Verify").innerHTML =  v.result.toString();

                }

       document.getElementById("message").innerHTML = "42";
       document.getElementById("genkey").addEventListener("click", hidebutton);
       document.getElementById("genkey").addEventListener("click", execGenerate);
       document.getElementById("proof").addEventListener("click", execProve);

         document.getElementById("message").addEventListener("input",  execProve);

</script>

证明值为 12 的示例运行位于[ here]:

证明值为 43232 的示例运行位于[ here]:

演示在这里:

ZK-WASM with JavaScript \ \ ZK-WASM integrates a Zero Knowledge Proofs (ZKP) in Rust, into WebAssembly (WASM) [1]. A bridge between the Rust…\ \ asecuritysite.com

参考

[1] https://github.com/xonoxitron/zk-wasm/tree/main

  • 原文链接: billatnapier.medium.com/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
billatnapier
billatnapier
江湖只有他的大名,没有他的介绍。