snapkitty
agents
idris2
lean4
File size: 3,164 Bytes
1cdfc83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// 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);
}