|
|
|
|
|
|
|
|
| import { computeGreedySequence, buildCardinalityTable } from './greedy.mjs';
|
|
|
| export function runThresholdCryptoDemo() {
|
| console.log('='.repeat(70));
|
| console.log(' THRESHOLD SIGNATURE — DSS CARDINALITY ORACLE');
|
| console.log(' "How many signed?" without "Who signed?"');
|
| console.log('='.repeat(70));
|
| console.log();
|
|
|
| const NUM_SIGNERS = 10;
|
| const THRESHOLD = 6;
|
| const weights = computeGreedySequence(NUM_SIGNERS);
|
| const table = buildCardinalityTable(weights);
|
|
|
| const signerNames = [
|
| 'Alice', 'Bob', 'Carol', 'Dave', 'Eve',
|
| 'Frank', 'Grace', 'Heidi', 'Ivan', 'Judy'
|
| ];
|
|
|
| console.log(`Threshold scheme: ${THRESHOLD}-of-${NUM_SIGNERS}`);
|
| console.log(`Signers: [${signerNames.join(', ')}]`);
|
| console.log(`DSS commitment weights: [${weights.join(', ')}]`);
|
| console.log();
|
|
|
|
|
| const rounds = [
|
| { name: 'Exactly threshold (6/10)', signers: [0, 2, 4, 5, 7, 9] },
|
| { name: 'Over threshold (8/10)', signers: [0, 1, 2, 3, 5, 6, 8, 9] },
|
| { name: 'Under threshold (4/10)', signers: [1, 3, 6, 8] },
|
| { name: 'All signed (10/10)', signers: [0,1,2,3,4,5,6,7,8,9] },
|
| { name: 'Minimal quorum (6/10) different set', signers: [1, 3, 5, 7, 8, 9] },
|
| ];
|
|
|
| console.log('VERIFICATION ROUNDS:');
|
| console.log('-'.repeat(70));
|
|
|
| for (const round of rounds) {
|
| const activeWeights = round.signers.map(i => weights[i]);
|
| const aggregate = activeWeights.reduce((a, b) => a + b, 0);
|
| const detectedK = table.get(aggregate) ?? -1;
|
| const valid = detectedK >= THRESHOLD;
|
| const activeNames = round.signers.map(i => signerNames[i]);
|
|
|
| console.log(`\n Round: ${round.name}`);
|
| console.log(` Signers: [${activeNames.join(', ')}]`);
|
| console.log(` Aggregate commitment: ${aggregate}`);
|
| console.log(` DSS Oracle: "${detectedK} signers participated"`);
|
| console.log(` Threshold met: ${valid ? 'VALID' : 'REJECTED'}`);
|
|
|
| if (valid) {
|
|
|
|
|
| const possibleSets = comb(NUM_SIGNERS, detectedK);
|
| console.log(` Privacy: ${possibleSets} possible ${detectedK}-signer sets (identity hidden)`);
|
| }
|
| }
|
|
|
| console.log('\n' + '-'.repeat(70));
|
| console.log('\nSECURITY PROPERTIES:');
|
| console.log(' 1. SOUNDNESS: Cannot fake k signatures with fewer (DSS prevents sum collision across cardinalities)');
|
| console.log(' 2. PRIVACY: Aggregate reveals count, not identity');
|
| console.log(' 3. EFFICIENCY: O(1) threshold check vs O(C(n,k)) verification');
|
| console.log();
|
|
|
| return { weights, rounds, table };
|
| }
|
|
|
| function comb(n, k) {
|
| if (k > n) return 0;
|
| if (k === 0 || k === n) return 1;
|
| let result = 1;
|
| for (let i = 0; i < k; i++) {
|
| result = result * (n - i) / (i + 1);
|
| }
|
| return Math.round(result);
|
| }
|
|
|