j-bitcoin
Version:
Comprehensive JavaScript cryptocurrency wallet library for Bitcoin (BTC), Bitcoin Cash (BCH), and Bitcoin SV (BSV) with custodial and non-custodial wallet support, threshold signatures, and multiple address formats
2,729 lines (898 loc) • 85.1 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: ThresholdSignature</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: ThresholdSignature</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>ThresholdSignature<span class="signature">()</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="ThresholdSignature"><span class="type-signature"></span>new ThresholdSignature<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
<p>Threshold Signature Scheme implementation for distributed cryptography</p>
<p>This class implements a complete threshold signature scheme that allows any subset
of participants (meeting the threshold) to collaboratively generate valid ECDSA
signatures without ever reconstructing the private key. The scheme is based on
Shamir's Secret Sharing and provides the following security guarantees:</p>
<p><strong>Security Properties:</strong></p>
<ul>
<li><strong>Threshold Security</strong>: Requires exactly t participants to generate signatures</li>
<li><strong>Information-Theoretic Privacy</strong>: < t participants learn nothing about the private key</li>
<li><strong>Robustness</strong>: Works even if some participants are unavailable (up to n-t)</li>
<li><strong>Unforgeability</strong>: Signatures are cryptographically secure and unforgeable</li>
</ul>
<p><strong>Key Features:</strong></p>
<ul>
<li>Distributed key generation without trusted dealer</li>
<li>Threshold ECDSA signature generation</li>
<li>Support for linear and multiplicative operations on shared secrets</li>
<li>Compatible with standard ECDSA verification</li>
<li>Efficient polynomial-based secret sharing</li>
</ul>
<p><strong>Use Cases:</strong></p>
<ul>
<li>Multi-signature wallets and escrow services</li>
<li>Corporate treasury management with distributed control</li>
<li>Cryptocurrency exchanges with operator separation</li>
<li>Secure key management for high-value assets</li>
<li>Compliance requirements for multi-party authorization</li>
</ul>
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line48">line 48</a>
</li></ul></dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Create a 2-of-3 threshold signature scheme
const tss = new ThresholdSignature(3, 2);
// Generate a threshold signature
const signature = tss.sign("Transfer $1000 to Alice");
// Verify the signature
const isValid = ThresholdSignature.verify_threshold_signature(
tss.public_key,
signature.msgHash,
signature.sig
);</code></pre>
<pre class="prettyprint"><code>// Corporate treasury with 3-of-5 executive approval
const corporateTSS = new ThresholdSignature(5, 3);
const executiveShares = corporateTSS.shares;
// Distribute shares to 5 executives
// Any 3 can authorize transactions
const authSignature = corporateTSS.sign("Quarterly dividend payment");</code></pre>
<pre class="prettyprint"><code>// Escrow service with dispute resolution
const escrowTSS = new ThresholdSignature(3, 2);
const [buyerShare, sellerShare, arbiterShare] = escrowTSS.shares;
// Normal case: buyer + seller release funds
// Dispute case: buyer/seller + arbiter resolve</code></pre>
</div>
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="group_size"><span class="type-signature">(readonly) </span>group_size<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Total number of participants in the threshold scheme</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line161">line 161</a>
</li></ul></dd>
</dl>
<h4 class="name" id="polynomial_order"><span class="type-signature">(readonly) </span>polynomial_order<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Polynomial degree (threshold - 1) for secret sharing</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line168">line 168</a>
</li></ul></dd>
</dl>
<h4 class="name" id="threshold"><span class="type-signature">(readonly) </span>threshold<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Minimum number of participants needed for cryptographic operations</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line175">line 175</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addss"><span class="type-signature"></span>addss<span class="signature">(a_shares<span class="signature-attributes">opt</span>, b_shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {BN}</span></h4>
<div class="description">
<p>Additive Secret Sharing (ADDSS) - combines two sets of shares additively</p>
<p>ADDSS enables secure addition of two shared secrets without revealing
the individual secrets. Each participant adds their corresponding shares,
and the result can be reconstructed to obtain the sum of the original secrets.</p>
<p><strong>Mathematical Foundation:</strong></p>
<ul>
<li>If secret A is shared as (a₁, a₂, ..., aₙ)</li>
<li>And secret B is shared as (b₁, b₂, ..., bₙ)</li>
<li>Then A + B is shared as (a₁+b₁, a₂+b₂, ..., aₙ+bₙ)</li>
</ul>
<p><strong>Applications:</strong></p>
<ul>
<li>Combining multiple randomness sources</li>
<li>Adding constants to shared secrets</li>
<li>Building complex cryptographic protocols</li>
<li>Secure multi-party computation primitives</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>a_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>First set of secret shares</p></td>
</tr>
<tr>
<td class="name"><code>b_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>Second set of secret shares</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line343">line 343</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<dl>
<dt>
<div class="param-desc">
<p>If share arrays have different lengths</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>The sum of the two original secrets</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">BN</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(3, 2);
// Generate two sets of shares
const [shares1, _] = tss.jvrss();
const [shares2, __] = tss.jvrss();
// Add the shared secrets
const sum = tss.addss(shares1, shares2);
// Verify: sum should equal individual secret sum
const secret1 = tss.privite_key(shares1);
const secret2 = tss.privite_key(shares2);
const expectedSum = secret1.add(secret2).umod(N);
console.log(sum.eq(expectedSum)); // true</code></pre>
<pre class="prettyprint"><code>// Adding a constant to a shared secret
const constant = new BN(42);
const constantShares = Array(tss.group_size).fill(new BN(0));
constantShares[0] = constant; // Only first share gets the constant
const result = tss.addss(tss.shares, constantShares);
// result = original_secret + 42</code></pre>
<h4 class="name" id="invss"><span class="type-signature"></span>invss<span class="signature">(a_shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {Array.<BN>}</span></h4>
<div class="description">
<p>Inverse Secret Sharing (INVSS) - computes modular inverse of shared secret</p>
<p>INVSS computes the modular inverse of a shared secret without revealing the secret.
This is crucial for threshold ECDSA signatures where we need to compute k⁻¹
(inverse of the nonce) as part of the signature generation process.</p>
<p><strong>Algorithm:</strong></p>
<ol>
<li>Generate a fresh random secret b using JVRSS</li>
<li>Compute c = a × b using PROSS (where a is the input secret)</li>
<li>Reconstruct c (this reveals c but not a or b individually)</li>
<li>Compute c⁻¹ using standard modular inverse</li>
<li>Multiply b shares by c⁻¹ to get shares of a⁻¹</li>
</ol>
<p><strong>Security:</strong></p>
<ul>
<li>The intermediate value c is revealed but provides no information about a</li>
<li>The randomness b masks the original secret a</li>
<li>Final result is properly shared according to the threshold scheme</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>a_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>Shares of the secret to invert</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line466">line 466</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Shares of the modular inverse of the original secret</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Array.<BN></span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(5, 3);
// Compute inverse of shared secret
const inverseShares = tss.invss(tss.shares);
// Verify: secret × inverse = 1 (mod N)
const product = tss.pross(tss.shares, inverseShares);
console.log(product.eq(new BN(1))); // true</code></pre>
<pre class="prettyprint"><code>// Use in threshold signature (simplified)
const message = Buffer.from("Hello World!");
const msgHash = new BN(createHash('sha256').update(message).digest());
// Generate nonce shares
const [kShares, kPubKey] = tss.jvrss();
// Compute inverse of nonce
const kInvShares = tss.invss(kShares);
// This would be used in signature computation
// s = k⁻¹(hash + r × private_key)</code></pre>
<h4 class="name" id="jvrss"><span class="type-signature"></span>jvrss<span class="signature">()</span><span class="type-signature"> → {Array|Array.<BN>|Object}</span></h4>
<div class="description">
<p>Joint Verifiable Random Secret Sharing (JVRSS) protocol implementation</p>
<p>JVRSS is the core protocol for distributed key generation without a trusted dealer.
It combines multiple random polynomials from all participants to create a
shared secret that no single party knows or can control.</p>
<p><strong>Protocol Steps:</strong></p>
<ol>
<li><strong>Polynomial Generation</strong>: Each participant conceptually generates a random polynomial</li>
<li><strong>Share Distribution</strong>: Each polynomial contributes to every participant's final share</li>
<li><strong>Linear Combination</strong>: Shares are combined additively to create the final distribution</li>
<li><strong>Public Key Derivation</strong>: The aggregate public key is computed from polynomial constants</li>
</ol>
<p><strong>Security Properties:</strong></p>
<ul>
<li>No single participant controls the final secret</li>
<li>The secret is uniformly random over the field</li>
<li>Shares are properly distributed according to Shamir's scheme</li>
<li>Public key is verifiable and corresponds to the shared secret</li>
</ul>
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line267">line 267</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<ul>
<li>
<div class="param-desc">
<p>Tuple containing shares array and aggregate public key</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Array</span>
</dd>
</dl>
</li>
<li>
<div class="param-desc">
<p>returns.0 - Array of secret shares for each participant</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Array.<BN></span>
</dd>
</dl>
</li>
<li>
<div class="param-desc">
<p>returns.1 - Aggregate elliptic curve public key point</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Object</span>
</dd>
</dl>
</li>
</ul>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(5, 3);
const [shares, publicKey] = tss.jvrss();
console.log(shares.length); // 5 shares
console.log(publicKey.constructor.name); // ProjectivePoint
// Shares are properly distributed
const points = tss.shares_to_points(shares);
const secret = Polynomial.interpolate_evaluate(points, 0);
const derivedPubKey = secp256k1.ProjectivePoint.fromPrivateKey(secret.toBuffer());
// Public keys should match
console.log(publicKey.equals(derivedPubKey)); // true</code></pre>
<pre class="prettyprint"><code>// Manual JVRSS execution for understanding
const groupSize = 3, threshold = 2;
const polynomials = Array(groupSize).fill(null)
.map(() => Polynomial.fromRandom(threshold - 1));
// Each participant's share is sum of evaluations
let manualShares = Array(groupSize).fill(new BN(0));
for (let i = 0; i < groupSize; i++) {
for (let j = 0; j < groupSize; j++) {
manualShares[j] = manualShares[j].add(polynomials[i].evaluate(j + 1));
}
}
// This produces the same result as jvrss()</code></pre>
<h4 class="name" id="privite_key"><span class="type-signature"></span>privite_key<span class="signature">(a_shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {BN}</span></h4>
<div class="description">
<p>Reconstructs the private key from secret shares using polynomial interpolation</p>
<p>This method recovers the original private key from the distributed shares.
It should be used with caution as it reconstructs the full private key,
defeating the purpose of the threshold scheme. Typically used only for
specific operations like computing WIF format or for emergency recovery.</p>
<p><strong>Security Warning:</strong></p>
<ul>
<li>Reconstructing the private key centralizes control</li>
<li>Should only be done when absolutely necessary</li>
<li>Consider using threshold operations instead when possible</li>
<li>Ensure secure deletion of reconstructed key after use</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>a_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="description last"><p>Secret shares to reconstruct from (defaults to this.shares)</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line537">line 537</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>The reconstructed private key as a BigNumber</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">BN</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(3, 2);
// Reconstruct private key (use with caution!)
const privateKey = tss.privite_key();
// Verify it corresponds to the public key
const derivedPubKey = secp256k1.ProjectivePoint.fromPrivateKey(privateKey.toBuffer());
console.log(derivedPubKey.equals(tss.public_key)); // true</code></pre>
<pre class="prettyprint"><code>// Partial reconstruction with threshold shares only
const thresholdShares = tss.shares.slice(0, tss.threshold);
const partialKey = tss.privite_key(thresholdShares);
// Should equal full reconstruction
const fullKey = tss.privite_key();
console.log(partialKey.eq(fullKey)); // true</code></pre>
<pre class="prettyprint"><code>// Emergency recovery scenario
function emergencyRecovery(shareHolders) {
if (shareHolders.length < tss.threshold) {
throw new Error("Insufficient shares for recovery");
}
const recoveredKey = tss.privite_key(shareHolders.slice(0, tss.threshold));
// Use recovered key for emergency operations
// ... perform emergency actions ...
// Securely delete the key
recoveredKey.fill(0);
}</code></pre>
<h4 class="name" id="pross"><span class="type-signature"></span>pross<span class="signature">(a_shares<span class="signature-attributes">opt</span>, b_shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {BN}</span></h4>
<div class="description">
<p>Polynomial Reconstruction Secret Sharing (PROSS) - computes product of shared secrets</p>
<p>PROSS enables secure multiplication of two shared secrets. This is more complex
than addition because the product of two degree-t polynomials yields a degree-2t
polynomial, requiring more shares for reconstruction.</p>
<p><strong>Mathematical Foundation:</strong></p>
<ul>
<li>Product of degree-t polynomials has degree 2t</li>
<li>Requires 2t+1 shares for reconstruction (vs t+1 for addition)</li>
<li>Uses polynomial interpolation on the product values</li>
<li>Result is the product of the original secrets</li>
</ul>
<p><strong>Security Note:</strong></p>
<ul>
<li>Requires more participants for security than addition</li>
<li>Product shares reveal more information than additive shares</li>
<li>Should be used carefully in cryptographic protocols</li>
</ul>
<p><strong>Applications:</strong></p>
<ul>
<li>Computing multiplicative inverses (used in INVSS)</li>
<li>Secure polynomial evaluation</li>
<li>Advanced threshold cryptographic protocols</li>
<li>Zero-knowledge proof systems</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>a_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>First set of secret shares</p></td>
</tr>
<tr>
<td class="name"><code>b_shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>Second set of secret shares</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line407">line 407</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>The product of the two original secrets</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">BN</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(5, 2); // Need larger group for PROSS
// Generate two secrets
const [shares1, _] = tss.jvrss();
const [shares2, __] = tss.jvrss();
// Compute product
const product = tss.pross(shares1, shares2);
// Verify result
const secret1 = tss.privite_key(shares1);
const secret2 = tss.privite_key(shares2);
const expectedProduct = secret1.mul(secret2).umod(N);
console.log(product.eq(expectedProduct)); // true</code></pre>
<pre class="prettyprint"><code>// Squaring a shared secret
const squared = tss.pross(tss.shares, tss.shares);
const originalSecret = tss.privite_key();
const expectedSquare = originalSecret.mul(originalSecret).umod(N);
console.log(squared.eq(expectedSquare)); // true</code></pre>
<h4 class="name" id="shares_to_points"><span class="type-signature"></span>shares_to_points<span class="signature">(shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {<a href="global.html#SharePoints">SharePoints</a>}</span></h4>
<div class="description">
<p>Converts share values to coordinate points for polynomial interpolation</p>
<p>Transforms an array of share values into the coordinate format required
for Lagrange interpolation. Each share at index i becomes a point (i+1, share)
since polynomial evaluation uses 1-based indexing (x=0 is reserved for secrets).</p>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>shares</code></td>
<td class="type">
<span class="param-type">Array.<BN></span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
[]
</td>
<td class="description last"><p>Array of BigNumber share values to convert</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line210">line 210</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Array of [x, y] coordinate pairs for interpolation</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="global.html#SharePoints">SharePoints</a></span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(3, 2);
const points = tss.shares_to_points(tss.shares);
console.log(points);
// [[1, share1_value], [2, share2_value], [3, share3_value]]
// Use for secret reconstruction
const secret = Polynomial.interpolate_evaluate(points, 0);</code></pre>
<pre class="prettyprint"><code>// Partial reconstruction with threshold shares
const partialShares = tss.shares.slice(0, tss.threshold);
const thresholdPoints = tss.shares_to_points(partialShares);
const reconstructed = Polynomial.interpolate_evaluate(thresholdPoints, 0);</code></pre>
<h4 class="name" id="sign"><span class="type-signature"></span>sign<span class="signature">(message)</span><span class="type-signature"> → {<a href="global.html#ThresholdSignatureResult">ThresholdSignatureResult</a>}</span></h4>
<div class="description">
<p>Generates a threshold signature for a given message</p>
<p>This is the core method that produces threshold ECDSA signatures. The signature
is generated collaboratively using the threshold scheme without reconstructing
the private key. The process follows the threshold ECDSA protocol:</p>
<p><strong>Threshold ECDSA Algorithm:</strong></p>
<ol>
<li><strong>Nonce Generation</strong>: Create shared random nonce k using JVRSS</li>
<li><strong>R Value Computation</strong>: Compute R = k×G and extract r = R.x mod n</li>
<li><strong>Inverse Computation</strong>: Compute k⁻¹ using INVSS without revealing k</li>
<li><strong>Signature Shares</strong>: Each party computes their share of s = k⁻¹(hash + r×private)</li>
<li><strong>Reconstruction</strong>: Combine shares to get final signature (r, s)</li>
<li><strong>Validation</strong>: Ensure signature is valid and non-zero</li>
</ol>
<p><strong>Security Properties:</strong></p>
<ul>
<li>Private key never reconstructed during signing</li>
<li>Nonce is generated distributively and remains secret</li>
<li>Resulting signature is indistinguishable from single-party ECDSA</li>
<li>Compatible with standard ECDSA verification</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>message</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last"><p>Message to sign (will be SHA256 hashed)</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line612">line 612</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>Complete signature with metadata</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="global.html#ThresholdSignatureResult">ThresholdSignatureResult</a></span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>const tss = new ThresholdSignature(3, 2);
// Generate threshold signature
const signature = tss.sign("Transfer $1000 to Alice");
console.log(signature.sig.r); // BigInt r value
console.log(signature.sig.s); // BigInt s value
console.log(signature.serialized_sig); // Base64 compact format
console.log(signature.recovery_id); // 0-3 for public key recovery
// Verify signature
const isValid = ThresholdSignature.verify_threshold_signature(
tss.public_key,
signature.msgHash,
signature.sig
);
console.log(isValid); // true</code></pre>
<pre class="prettyprint"><code>// Corporate authorization workflow
const corporateTSS = new ThresholdSignature(5, 3);
const authMessage = JSON.stringify({
action: "wire_transfer",
amount: 1000000,
recipient: "operations_account",
timestamp: Date.now()
});
const authorization = corporateTSS.sign(authMessage);
console.log("Authorization signature:", authorization.serialized_sig);</code></pre>
<pre class="prettyprint"><code>// Escrow release with buyer + seller
const escrowTSS = new ThresholdSignature(3, 2);
const releaseMessage = "Release escrow funds to seller";
const escrowSignature = escrowTSS.sign(releaseMessage);
// This signature can be verified by anyone
const verified = ThresholdSignature.verify_threshold_signature(
escrowTSS.public_key,
escrowSignature.msgHash,
escrowSignature.sig
);</code></pre>
<h4 class="name" id=".verify_threshold_signature"><span class="type-signature">(static) </span>verify_threshold_signature<span class="signature">(public_key, msgHash, sig)</span><span class="type-signature"> → {boolean}</span></h4>
<div class="description">
<p>Verifies a threshold signature against a public key and message hash</p>
<p>This static method verifies threshold signatures using standard ECDSA verification.
Threshold signatures are indistinguishable from regular ECDSA signatures, so
standard verification algorithms work without modification.</p>
<p><strong>Verification Algorithm:</strong></p>
<ol>
<li><strong>Input Validation</strong>: Ensure signature components r and s are valid</li>
<li><strong>Hash Processing</strong>: Use the provided message hash (already computed)</li>
<li><strong>Inverse Computation</strong>: Compute w = s⁻¹ mod n</li>
<li><strong>Point Calculation</strong>: Compute u₁ = w×hash and u₂ = w×r</li>
<li><strong>Point Addition</strong>: Compute point = u₁×G + u₂×PublicKey</li>
<li><strong>Verification</strong>: Check if point.x ≡ r (mod n)</li>
</ol>
<p><strong>Compatibility:</strong></p>
<ul>
<li>Works with any ECDSA signature, threshold or single-party</li>
<li>Uses standard secp256k1 curve parameters</li>
<li>Compatible with Bitcoin and Ethereum signature formats</li>
<li>Can be used by third parties without threshold scheme knowledge</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>public_key</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last"><p>Elliptic curve public key point</p></td>
</tr>
<tr>
<td class="name"><code>msgHash</code></td>
<td class="type">
<span class="param-type">Buffer</span>
</td>
<td class="description last"><p>SHA256 hash of the original message</p></td>
</tr>
<tr>
<td class="name"><code>sig</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last"><p>Signature object with r and s components</p>
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>r</code></td>
<td class="type">
<span class="param-type">bigint</span>
</td>
<td class="description last"><p>Signature r value</p></td>
</tr>
<tr>
<td class="name"><code>s</code></td>
<td class="type">
<span class="param-type">bigint</span>
</td>
<td class="description last"><p>Signature s value</p></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line738">line 738</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
<p>True if signature is valid, false otherwise</p>
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">boolean</span>
</dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Verify a threshold signature
const tss = new ThresholdSignature(3, 2);
const signature = tss.sign("Hello World!");
const isValid = ThresholdSignature.verify_threshold_signature(
tss.public_key,
signature.msgHash,
signature.sig
);
console.log(isValid); // true</code></pre>
<pre class="prettyprint"><code>// Third-party verification (doesn't need threshold scheme)
function verifyTransaction(publicKey, messageHash, signature) {
return ThresholdSignature.verify_threshold_signature(
publicKey,
messageHash,
signature
);
}
// Works with any ECDSA signature
const valid = verifyTransaction(
somePublicKey,
someMessageHash,
someSignature
);</code></pre>
<pre class="prettyprint"><code>// Batch verification for multiple signatures
function verifyBatch(signatures) {
return signatures.every(({ publicKey, msgHash, sig }) =>
ThresholdSignature.verify_threshold_signature(publicKey, msgHash, sig)
);
}</code></pre>
<pre class="prettyprint"><code>// Integration with Bitcoin transaction verification
function verifyBitcoinTransaction(transaction, publicKey) {
const messageHash = computeTransactionHash(transaction);
const signature = extractSignature(transaction);
return ThresholdSignature.verify_threshold_signature(
publicKey,
messageHash,
signature
);
}</code></pre>
</article>
</section>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>ThresholdSignature<span class="signature">(group_size<span class="signature-attributes">opt</span>, threshold<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="ThresholdSignature"><span class="type-signature"></span>new ThresholdSignature<span class="signature">(group_size<span class="signature-attributes">opt</span>, threshold<span class="signature-attributes">opt</span>)</span><span class="type-signature"></span></h4>
<div class="description">
<p>Creates a new threshold signature scheme instance</p>
<p>Initializes the threshold cryptographic system with specified parameters
and generates the initial shared secret distribution. The constructor
performs the following operations:</p>
<ol>
<li><strong>Parameter Validation</strong>: Ensures threshold constraints are met</li>
<li><strong>JVRSS Execution</strong>: Runs Joint Verifiable Random Secret Sharing</li>
<li><strong>Key Generation</strong>: Creates distributed private key shares</li>
<li><strong>Public Key Derivation</strong>: Computes the corresponding public key</li>
</ol>
<p><strong>Threshold Constraints:</strong></p>
<ul>
<li>threshold ≥ 2 (minimum for meaningful security)</li>
<li>threshold ≤ group_size (cannot exceed total participants)</li>
<li>group_size ≥ 2 (minimum for distribution)</li>
</ul>
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th>Default</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>group_size</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
3
</td>
<td class="description last"><p>Total number of participants in the scheme</p></td>
</tr>
<tr>
<td class="name"><code>threshold</code></td>
<td class="type">
<span class="param-type">number</span>
</td>
<td class="attributes">
<optional><br>
</td>
<td class="default">
2
</td>
<td class="description last"><p>Minimum number of participants needed for operations</p></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line155">line 155</a>
</li></ul></dd>
</dl>
<h5>Throws:</h5>
<dl>
<dt>
<div class="param-desc">
<p>"Threshold is too high or low" if constraints are violated</p>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Error</span>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<h5>Examples</h5>
<pre class="prettyprint"><code>// Create a 2-of-3 threshold scheme
const tss = new ThresholdSignature(3, 2);
console.log(tss.group_size); // 3
console.log(tss.threshold); // 2
console.log(tss.shares.length); // 3 shares generated</code></pre>
<pre class="prettyprint"><code>// Create a 5-of-7 corporate scheme
const corporateTSS = new ThresholdSignature(7, 5);
console.log(corporateTSS.polynomial_order); // 4 (threshold - 1)</code></pre>
<pre class="prettyprint"><code>// Error cases
try {
new ThresholdSignature(3, 5); // threshold > group_size
} catch (error) {
console.log(error.message); // "Threshold is too high or low"
}
try {
new ThresholdSignature(3, 1); // threshold < 2
} catch (error) {
console.log(error.message); // "Threshold is too high or low"
}</code></pre>
</div>
<h3 class="subsection-title">Members</h3>
<h4 class="name" id="group_size"><span class="type-signature">(readonly) </span>group_size<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Total number of participants in the threshold scheme</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line161">line 161</a>
</li></ul></dd>
</dl>
<h4 class="name" id="polynomial_order"><span class="type-signature">(readonly) </span>polynomial_order<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Polynomial degree (threshold - 1) for secret sharing</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line168">line 168</a>
</li></ul></dd>
</dl>
<h4 class="name" id="threshold"><span class="type-signature">(readonly) </span>threshold<span class="type-signature"> :number</span></h4>
<div class="description">
<p>Minimum number of participants needed for cryptographic operations</p>
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">number</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="src_Threshold-signature_threshold_signature.js.html">src/Threshold-signature/threshold_signature.js</a>, <a href="src_Threshold-signature_threshold_signature.js.html#line175">line 175</a>
</li></ul></dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="addss"><span class="type-signature"></span>addss<span class="signature">(a_shares<span class="signature-attributes">opt</span>, b_shares<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {BN}</span></h4>
<div class="description">
<p>Additive Secret Sharing (ADDSS) - combines two sets of shares additively</p>
<p>ADDSS enables secure addition of two shared secrets without revealing
the individual secrets. Each participant adds their corresponding shares,
and the result can be reconstructed to obtain the sum of the original secrets.</p>
<p><strong>Mathematical Foundation:</strong></p>
<ul>
<li>If secret A is shared as (a₁, a₂, ..., aₙ)</li>
<li>And secret B is shared as (b₁, b₂, ..., bₙ)</li>
<li>Then A + B is shared as (a₁+b₁, a₂+b₂, ..., aₙ+bₙ)</li>
</ul>
<p><strong>Applications:</strong></p>
<ul>
<li>Combining multiple randomness sources</li>
<li>Adding constants to shared secrets</li>
<li>Building complex cryptographic protocols</li>
<li>Secure multi-party computation primitives</li>
</ul>
</div>
<h5>Parameters:</h5>