Files
semaphore/docs/howitworks.html
2020-03-03 23:23:23 +02:00

331 lines
17 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>How it works - </title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div id="sidebar-scrollbox" class="sidebar-scrollbox">
<ol class="chapter"><li class="expanded "><a href="about.html"><strong aria-hidden="true">1.</strong> About</a></li><li class="expanded "><a href="howitworks.html" class="active"><strong aria-hidden="true">2.</strong> How it works</a></li><li class="expanded "><a href="quickstart.html"><strong aria-hidden="true">3.</strong> Quick start</a></li><li class="expanded "><a href="usage.html"><strong aria-hidden="true">4.</strong> Usage</a></li><li class="expanded "><a href="api.html"><strong aria-hidden="true">5.</strong> Contract API</a></li><li class="expanded "><a href="libsemaphore.html"><strong aria-hidden="true">6.</strong> libsemaphore</a></li><li class="expanded "><a href="trustedsetup.html"><strong aria-hidden="true">7.</strong> Trusted setup</a></li><li class="expanded "><a href="audit.html"><strong aria-hidden="true">8.</strong> Security audit</a></li><li class="expanded "><a href="creditsandresources.html"><strong aria-hidden="true">9.</strong> Credits and resources</a></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div id="menu-bar-sticky-container">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title"></h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1><a class="header" href="#how-it-works" id="how-it-works">How it works</a></h1>
<h2><a class="header" href="#inserting-identities" id="inserting-identities">Inserting identities</a></h2>
<p>An identity is comprised of the following information:</p>
<ol>
<li>An <a href="https://en.wikipedia.org/wiki/EdDSA">EdDSA</a> private key. Note that it is
<em>not</em> an Ethereum private key.</li>
<li>An identity nullifier, whih is a random 32-byte value.</li>
<li>An identity trapdoor, whih is a random 32-byte value.</li>
</ol>
<p>An identity commitment is the Pedersen hash of:</p>
<ol>
<li>The public key associated with the identity's private key.</li>
<li>The identity nullifier.</li>
<li>The identity trapdoor.</li>
</ol>
<p>To register an identity, the user must insert their identity commitment into
Semaphore's identity tree. They can do this by calling the Semaphore contract's
<code>insertIdentity(uint256 _identityCommitment)</code> function. See the <a href="./api.html">API
reference</a> for more information.</p>
<h2><a class="header" href="#broadcasting-signals" id="broadcasting-signals">Broadcasting signals</a></h2>
<p>To broadcast a signal, the user must invoke this Semaphore contract function:</p>
<pre><code>broadcastSignal(
bytes memory _signal,
uint256[8] memory _proof,
uint256 _root,
uint256 _nullifiersHash,
uint232 _externalNullifier
)
</code></pre>
<ul>
<li><code>_signal</code>: the signal to broadcast.</li>
<li><code>_proof</code>: a zk-SNARK proof (see below).</li>
<li><code>_root</code>: The root of the identity tree, where the user's identity commitment
is the last-inserted leaf.</li>
<li><code>_nullifiersHash</code>: A uniquely derived hash of the external nullifier, user's
identity nullifier, and the Merkle path index to their identity commitment.
It ensures that a user cannot broadcast a signal with the same external
nullifier more than once.</li>
<li><code>_externalNullifier</code>: The external nullifier at which the signal is
broadcast.</li>
</ul>
<p>To zk-SNARK proof must satisfy the constraints created by Semaphore's zk-SNARK
circuit as described below:</p>
<h3><a class="header" href="#the-zk-snark-circuit" id="the-zk-snark-circuit">The zk-SNARK circuit</a></h3>
<p>The <a href="./circuits/circom/semaphore-base.circom">semaphore-base.circom</a> circuit
helps to prove the following:</p>
<h3><a class="header" href="#that-the-identity-commitment-exists-in-the-merkle-tree" id="that-the-identity-commitment-exists-in-the-merkle-tree">That the identity commitment exists in the Merkle tree</a></h3>
<p><strong>Private inputs:</strong></p>
<ul>
<li><code>identity_pk</code>: the user's EdDSA public key</li>
<li><code>identity_nullifier</code>: a random 32-byte value which the user should save</li>
<li><code>identity_trapdoor</code>: a random 32-byte value which the user should save</li>
<li><code>identity_path_elements</code>: the values along the Merkle path to the
user's identity commitment</li>
<li><code>identity_path_index[n_levels]</code>: the direction (left/right) per tree level
corresponding to the Merkle path to the user's identity commitment</li>
</ul>
<p><strong>Public inputs:</strong></p>
<ul>
<li><code>root</code>: The Merkle root of the identity tree</li>
</ul>
<p><strong>Procedure:</strong></p>
<p>The circuit hashes the public key, identity nullifier, and identity trapdoor to
generate an <strong>identity commitment</strong>. It then verifies the Merkle proof against
the Merkle root and the identity commitment.</p>
<h3><a class="header" href="#that-the-signal-was-only-broadcasted-once" id="that-the-signal-was-only-broadcasted-once">That the signal was only broadcasted once</a></h3>
<p><strong>Private inputs:</strong></p>
<ul>
<li><code>identity_nullifier</code>: as above</li>
<li><code>identity_path_index</code>: as above</li>
</ul>
<p><strong>Public inputs:</strong></p>
<ul>
<li><code>external_nullifier</code>: the 29-byte external nullifier - see above</li>
<li><code>nullifiers_hash</code>: the hash of the identity nullifier, external nullifier,
and Merkle path index (<code>identity_path_index</code>)</li>
</ul>
<p><strong>Procedure:</strong></p>
<p>The circuit hashes the given identity nullifier, external nullifier, and Merkle
path index, and checks that it matches the given nullifiers hash. Additionally,
the smart contract ensures that it has not previously seen this nullifiers
hash. This way, double-signalling is impossible.</p>
<h3><a class="header" href="#that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof" id="that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof">That the signal was truly broadcasted by the user who generated the proof</a></h3>
<p><strong>Private inputs:</strong></p>
<ul>
<li><code>identity_pk</code>: as above</li>
<li><code>auth_sig_r</code>: the <code>r</code> value of the signature of the signal</li>
<li><code>auth_sig_s</code>: the <code>s</code> value of the signature of the signal</li>
</ul>
<p><strong>Public inputs:</strong></p>
<ul>
<li><code>signal_hash</code>: the hash of the signal</li>
<li><code>external_nullifier</code>: the 29-byte external nullifier - see above</li>
</ul>
<p><strong>Procedure:</strong></p>
<p>The circuit hashes the signal hash and the external nullifier, and verifies
this output against the given public key and signature. This ensures the
authenticity of the signal and prevents front-running attacks.</p>
<h2><a class="header" href="#cryptographic-primitives" id="cryptographic-primitives">Cryptographic primitives</a></h2>
<p>Semaphore uses MiMC for the Merkle tree, Pedersen commmitments for the identity
commitments, Blake2 for the nullifiers hash, and EdDSA for the signature.</p>
<p>MiMC is a relatively new hash function. We use the recommended MiMC
construction from <a href="https://eprint.iacr.org/2016/492.pdf">Albrecht et al</a>, and
there is a prize to break MiMC at <a href="http://mimchash.org">http://mimchash.org</a>
which has not been claimed yet.</p>
<p>We have also implemented a version of Semaphore which uses the Poseidon hash
function for the Merkle tree and EdDSA signature verification. This may have
better security than MiMC, allows identity insertions to save about 20% gas,
and roughly halves the proving time. Note, however, that the Poseidon-related
circuits and EVM bytecode generator have not been audited, so use it with
caution. To use it, checkout the <code>feat/poseidon</code> branch of this repository.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="about.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="quickstart.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a href="about.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a href="quickstart.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playpen_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>