// Application 3: Threshold Cryptography — Cardinality-Revealing Aggregation // In k-of-n threshold schemes: DSS-weighted shares produce an aggregate // where the sum reveals k (signer count) without revealing WHICH k signed. 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(); // Simulate signing rounds 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) { // Show that multiple signer sets could produce this cardinality // but the DSS property guarantees the COUNT is unambiguous 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); }