本文介绍了如何使用 Rust 编写零知识证明(ZKP)并在 WebAssembly (WASM) 中集成,从而在浏览器中运行 ZKP。文章展示了如何使用 wasm-pack 构建 WASM 文件,并在 HTML 中通过 JavaScript 桥接调用 Rust 代码实现 ZKP 的生成、证明和验证过程,使得在 Web 应用中实现隐私保护和可信计算成为可能。
随着数据泄露事件的增加,许多人梦想着这样一个世界:我们可以在不泄露敏感数据的情况下信任事物。为此,一个私有和可信世界的关键要素之一是使用零知识证明 (ZKP)。但是,由于安全性和性能问题,区块链和 Web 的世界可能是分离的。主要的改变是 WebAssembly 的使用,它使我们有机会在浏览器中运行原生代码,并在客户端的机器上运行。这包括与 Rust 和 C 的集成。有了这个,我们现在可以暴露复杂的软件库,而无需将代码翻译成 JavaScript。
因此,作为一名 Rust 程序员,可以想象一下用 Rust 构建代码,然后简单地在 HTML 中创建一个桥梁来调用代码。那么,让我们用 WebAssembly 实现一个 ZKP,并使用 Rust 编码来实现 ZKP。
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]:
演示在这里:
[1] https://github.com/xonoxitron/zk-wasm/tree/main
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!