Government-grade voting system built on node-ecies-lib with comprehensive cryptographic security and exhaustive testing. Node.js optimized with native crypto and Buffer support.
- Plurality - First-past-the-post (most common) ✅ Fully Implemented
- Approval - Vote for multiple candidates ✅ Fully Implemented
- Weighted - Stakeholder voting with configurable limits ✅ Fully Implemented
- Borda Count - Ranked voting with point allocation ✅ Fully Implemented
- Score Voting - Rate candidates 0-10 ✅ Fully Implemented
- Yes/No - Referendums and ballot measures ✅ Fully Implemented
- Yes/No/Abstain - With abstention option ✅ Fully Implemented
- Supermajority - Requires 2/3 or 3/4 threshold ✅ Fully Implemented
- Ranked Choice (IRV) - Instant runoff with elimination ✅ Fully Implemented
- Two-Round - Top 2 runoff election ✅ Fully Implemented
- STAR - Score Then Automatic Runoff ✅ Fully Implemented
- STV - Single Transferable Vote (proportional representation) ✅ Fully Implemented
- Quadratic - Quadratic voting (requires non-homomorphic operations) ✅ Fully Implemented
- Consensus - Requires 95%+ agreement ✅ Fully Implemented
- Consent-Based - Sociocracy-style (no strong objections) ✅ Fully Implemented
- ✅ Homomorphic Encryption - Votes remain encrypted until tally using Paillier cryptosystem
- ✅ Threshold Decryption - Distributed trust with k-of-n Guardians; no single party can decrypt alone
- ✅ Real-Time Tallies - Configurable interval decryption during voting with ZK proofs
- ✅ Verifiable Receipts - Cryptographically signed confirmations with ECDSA
- ✅ Public Bulletin Board - Transparent, append-only vote publication with Merkle tree integrity
- ✅ Immutable Audit Log - Cryptographic hash chain for all operations
- ✅ Event Logger - Comprehensive event tracking with microsecond timestamps and sequence numbers
- ✅ Role Separation - Poll aggregator cannot decrypt votes (separate PollTallier)
- ✅ Double-Vote Prevention - Each member votes once per poll
- ✅ Attack Resistance - Tested against manipulation attempts
- ✅ Node.js Optimized - Uses native crypto module and Buffer for performance
- ✅ Government-Grade Testing - 1100+ test cases covering all methods and edge cases
┌─────────────────────────────────────────────────────────────┐
│ SECURE ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ Poll (Vote Aggregator) │
│ ├─ Paillier PUBLIC key only ← encrypts & aggregates │
│ ├─ Authority's EC keys ← signs receipts │
│ └─ Cannot decrypt votes │
│ │
│ PollTallier (Separate Entity) │
│ ├─ Paillier PRIVATE key ← decrypts ONLY after close │
│ └─ Computes results │
│ │
│ Voter (Member from node-ecies-lib) │
│ ├─ EC keypair ← verifies receipts │
│ └─ Voting public key ← encrypts votes │
│ │
└─────────────────────────────────────────────────────────────┘
- Poll (
poll-core.ts) - Aggregates encrypted votes, issues receipts, enforces rules - VotingPoll (
poll.ts) - High-level voting with encrypted receipts - PollTallier (
tallier.ts) - Holds private key, decrypts results after close - VoteEncoder (
encoder.ts) - Encrypts votes using Paillier homomorphic encryption - PollFactory (
factory.ts) - Convenient poll creation with method-specific configurations - ImmutableAuditLog (
audit.ts) - Cryptographic hash chain for audit trail (Requirement 1.1) - PublicBulletinBoard (
bulletin-board.ts) - Transparent, append-only vote publication (Requirement 1.2) - PollEventLogger (
event-logger.ts) - Comprehensive event tracking (Requirement 1.3) - VotingSecurityValidator (
security.ts) - Security level validation and enforcement
All 17 voting methods are fully implemented with:
- VoteEncoder: Inherits generic
encode()method from ecies-lib that supports all voting methods - PollFactory: Dedicated methods for core types (
createPlurality,createApproval, etc.) and genericcreate()method for all methods - Node.js Optimization: Uses Buffer instead of Uint8Array for better Node.js performance
- Complete Testing: Full test coverage for all methods and security levels
- Cross-Platform Compatibility: 100% compatible with browser implementation
- Plurality -
createPlurality()/encode(VotingMethod.Plurality, ...)✅ - Approval -
createApproval()/encode(VotingMethod.Approval, ...)✅ - Weighted -
createWeighted()/encode(VotingMethod.Weighted, ...)✅ - Borda Count -
createBorda()/encode(VotingMethod.Borda, ...)✅ - Score Voting -
create(..., VotingMethod.Score, ...)/encode(VotingMethod.Score, ...)✅ - Yes/No -
create(..., VotingMethod.YesNo, ...)/encode(VotingMethod.YesNo, ...)✅ - Yes/No/Abstain -
create(..., VotingMethod.YesNoAbstain, ...)/encode(VotingMethod.YesNoAbstain, ...)✅ - Supermajority -
create(..., VotingMethod.Supermajority, ...)/encode(VotingMethod.Supermajority, ...)✅
- Ranked Choice (IRV) -
createRankedChoice()/encode(VotingMethod.RankedChoice, ...)✅ - Two-Round -
create(..., VotingMethod.TwoRound, ...)/encode(VotingMethod.TwoRound, ...)✅ - STAR -
create(..., VotingMethod.STAR, ...)/encode(VotingMethod.STAR, ...)✅ - STV -
create(..., VotingMethod.STV, ...)/encode(VotingMethod.STV, ...)✅
- Quadratic -
create(..., VotingMethod.Quadratic, ...)/encode(VotingMethod.Quadratic, ...)✅ - Consensus -
create(..., VotingMethod.Consensus, ...)/encode(VotingMethod.Consensus, ...)✅ - Consent-Based -
create(..., VotingMethod.ConsentBased, ...)/encode(VotingMethod.ConsentBased, ...)✅
The Node.js voting system uses a flexible architecture that extends the browser implementation:
- Inherited Methods: Core voting methods inherit from
@digitaldefiance/ecies-libbase classes - Buffer Specialization: All binary data uses Node.js Buffer instead of Uint8Array
- Generic Support: The generic
encode()method handles all 17 voting methods - Dedicated Factories: Core methods have dedicated factory methods for convenience
- Cross-Platform: 100% binary compatible with browser implementation
import { VotingSecurityValidator, SecurityLevel, VotingMethod } from '@digitaldefiance/node-ecies-lib';
// Check security level
const level = VotingSecurityValidator.getSecurityLevel(VotingMethod.Plurality);
// Returns: SecurityLevel.FullyHomomorphic
// Validate before use
VotingSecurityValidator.validate(VotingMethod.Quadratic); // Throws error
VotingSecurityValidator.validate(VotingMethod.Quadratic, { allowInsecure: true }); // OK| Method | Security | Implementation Status | Use Case | Multi-Winner |
|---|---|---|---|---|
| Plurality | ✅ Full | ✅ Complete | General elections | No |
| Approval | ✅ Full | ✅ Complete | Committee selection | No |
| Weighted | ✅ Full | ✅ Complete | Shareholder voting | No |
| Borda | ✅ Full | ✅ Complete | Ranked preferences | No |
| Score | ✅ Full | ✅ Complete | Rating candidates | No |
| YesNo | ✅ Full | ✅ Complete | Referendums | No |
| YesNoAbstain | ✅ Full | ✅ Complete | Referendums with abstention | No |
| Supermajority | ✅ Full | ✅ Complete | Constitutional changes | No |
| RankedChoice | ✅ Complete | Modern elections | No | |
| TwoRound | ✅ Complete | Presidential elections | No | |
| STAR | ✅ Complete | Hybrid score/runoff | No | |
| STV | ✅ Complete | Proportional representation | Yes | |
| Quadratic | ❌ None | ✅ Complete | Budget allocation | No |
| Consensus | ❌ None | ✅ Complete | Small groups | No |
| ConsentBased | ❌ None | ✅ Complete | Cooperatives | No |
import { ImmutableAuditLog } from '@digitaldefiance/node-ecies-lib';
const auditLog = new ImmutableAuditLog(authority);
// Record poll creation
auditLog.recordPollCreated(pollId, { choices: ['A', 'B'] });
// Record vote cast
auditLog.recordVoteCast(pollId, voterIdHash);
// Record poll closure
auditLog.recordPollClosed(pollId, { finalTally: [100n, 200n] });
// Verify chain integrity
const isValid = auditLog.verifyChain();Features:
- Cryptographically signed entries
- Hash-chained for immutability
- Microsecond-precision timestamps
- Verifiable chain of custody
import { PublicBulletinBoard } from '@digitaldefiance/node-ecies-lib';
const board = new PublicBulletinBoard(authority);
// Publish encrypted vote
const entry = board.publishVote(pollId, encryptedVote, voterIdHash);
// Publish tally with proof
const proof = board.publishTally(
pollId,
tallies,
choices,
encryptedVotes
);
// Any observer can download and verify
const allEntries = board.getAllEntries();
const isValid = board.verifyEntry(entry);
const isTallyValid = board.verifyTallyProof(proof);
// Export for archival
const archive = board.export();Features:
- Append-only publication
- Merkle tree for structural integrity
- Zero-knowledge proofs of correct decryption
- Public verification by any observer
- Complete export for archival
import { PollEventLogger, EventType } from '@digitaldefiance/node-ecies-lib';
const eventLogger = new PollEventLogger();
// Log poll creation
eventLogger.logPollCreated(pollId, creatorId, {
method: 'plurality',
choices: ['Alice', 'Bob', 'Charlie'],
});
// Log vote cast
eventLogger.logVoteCast(pollId, voterToken, {
ipAddress: '192.168.1.1',
});
// Log poll closure
eventLogger.logPollClosed(pollId, tallyHash, {
totalVotes: 100,
});
// Query events
const allEvents = eventLogger.getEvents();
const pollEvents = eventLogger.getEventsForPoll(pollId);
const voteEvents = eventLogger.getEventsByType(EventType.VoteCast);
// Verify sequence integrity
const isValid = eventLogger.verifySequence();
// Export for archival
const archive = eventLogger.export();Features:
- Microsecond-precision timestamps
- Sequential event numbering
- Comprehensive event types (creation, voting, closure, verification, tally, audit)
- Anonymized voter tokens
- Poll configuration tracking
- Sequence integrity verification
import { Member, ECIESService } from '@digitaldefiance/node-ecies-lib';
import { MemberType, EmailString } from '@digitaldefiance/ecies-lib';
import {
PollFactory,
VoteEncoder,
PollTallier,
VotingMethod,
VotingSecurityValidator
} from '@digitaldefiance/node-ecies-lib';
const eciesService = new ECIESService();
// Create authority with voting keys
const { member: authority, mnemonic } = Member.newMember(
eciesService,
MemberType.System,
'Election Authority',
new EmailString('authority@example.com')
);
await authority.deriveVotingKeys();
// Create voters
const { member: voter1 } = Member.newMember(
eciesService,
MemberType.Individual,
'Alice',
new EmailString('alice@example.com')
);
await voter1.deriveVotingKeys();import { Member, ECIESService } from '@digitaldefiance/node-ecies-lib';
import { PollFactory, VoteEncoder, PollTallier } from '@digitaldefiance/node-ecies-lib';
// 1. Create authority
const eciesService = new ECIESService();
const { member: authority, mnemonic } = Member.newMember(
eciesService,
MemberType.System,
'Election Authority',
new EmailString('authority@example.com')
);
await authority.deriveVotingKeys();
// 2. Create poll
const poll = PollFactory.createPlurality(
['Alice', 'Bob', 'Charlie'],
authority
);
// 3. Create voters and cast votes
const { member: voter } = Member.newMember(/* ... */);
await voter.deriveVotingKeys();
const encoder = new VoteEncoder(authority.votingPublicKey!);
const vote = encoder.encodePlurality(0, 3); // Vote for Alice
const receipt = poll.vote(voter, vote);
// 4. Close and tally
poll.close();
const tallier = new PollTallier(
authority,
authority.votingPrivateKey!,
authority.votingPublicKey!
);
const results = tallier.tally(poll);
console.log('Winner:', results.choices[results.winner!]);const poll = PollFactory.createRankedChoice(
['Alice', 'Bob', 'Charlie', 'Diana'],
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
// Voter ranks: Alice > Bob > Charlie
const vote = encoder.encodeRankedChoice([0, 1, 2], 4);
poll.vote(voter, vote);
// ... more votes ...
poll.close();
const results = tallier.tally(poll);
// Results include elimination rounds
console.log('Winner:', results.choices[results.winner!]);
console.log('Rounds:', results.rounds);
console.log('Eliminated:', results.eliminated);const poll = PollFactory.createWeighted(
['Proposal A', 'Proposal B'],
authority,
1000n // Maximum weight
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
// Large stakeholder votes with weight 500
const vote = encoder.encodeWeighted(0, 500n, 2);
poll.vote(whale, vote);const poll = PollFactory.create(
['Candidate A', 'Candidate B', 'Candidate C'],
VotingMethod.Score,
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
// Rate candidates 0-10
const vote = encoder.encode(
VotingMethod.Score,
{ choiceIndex: 0, score: 8 }, // Give Candidate A a score of 8
3
);
poll.vote(voter, vote);const poll = PollFactory.create(
['Approve Budget Increase'],
VotingMethod.YesNo,
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
const vote = encoder.encode(
VotingMethod.YesNo,
{ choiceIndex: 0 }, // Vote yes (0 = yes, 1 = no)
2
);
poll.vote(voter, vote);const poll = PollFactory.create(
['Constitutional Amendment'],
VotingMethod.Supermajority,
authority,
{ supermajorityThreshold: { numerator: 2, denominator: 3 } } // Requires 2/3 majority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
const vote = encoder.encode(
VotingMethod.Supermajority,
{ choiceIndex: 0 },
1
);
poll.vote(voter, vote);
poll.close();
const results = tallier.tally(poll);
// results.winner is only set if 2/3 threshold is metconst poll = PollFactory.create(
['Alice', 'Bob', 'Charlie'],
VotingMethod.STAR,
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
// First round: score all candidates
const vote = encoder.encode(
VotingMethod.STAR,
{ scores: [8, 6, 9] }, // Score each candidate 0-10
3
);
poll.vote(voter, vote);const poll = PollFactory.create(
['Alice', 'Bob', 'Charlie', 'Diana'],
VotingMethod.TwoRound,
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
const vote = encoder.encode(
VotingMethod.TwoRound,
{ choiceIndex: 0 }, // Vote for Alice in first round
4
);
poll.vote(voter, vote);const poll = PollFactory.create(
['Alice', 'Bob', 'Charlie', 'Diana'],
VotingMethod.STV,
authority
);
const encoder = new VoteEncoder(authority.votingPublicKey!);
const vote = encoder.encode(
VotingMethod.STV,
{ rankings: [0, 2, 1] }, // Alice > Charlie > Bob (Diana not ranked)
4
);
poll.vote(voter, vote);// Using Buffer for poll and voter IDs
const pollId = Buffer.from('poll-12345', 'utf8');
const voterIdHash = Buffer.from(crypto.createHash('sha256').update(voter.id).digest());
// All voting operations work with Buffer
const poll = new Poll(
pollId,
['Option A', 'Option B'],
VotingMethod.Plurality,
authority,
authority.votingPublicKey!
);// Check security level before creating poll
const level = VotingSecurityValidator.getSecurityLevel(VotingMethod.Quadratic);
console.log(level); // SecurityLevel.Insecure
// Validate method (throws if insecure)
try {
VotingSecurityValidator.validate(VotingMethod.Quadratic);
} catch (error) {
console.error('Method is not secure!');
}
// Allow insecure methods explicitly
VotingSecurityValidator.validate(VotingMethod.Quadratic, { allowInsecure: true });// Check security level before creating poll
const level = VotingSecurityValidator.getSecurityLevel(VotingMethod.Quadratic);
console.log(level); // SecurityLevel.Insecure
// Validate method (throws if insecure)
try {
VotingSecurityValidator.validate(VotingMethod.Quadratic);
} catch (error) {
console.error('Method is not secure!');
}
// Allow insecure methods explicitly
VotingSecurityValidator.validate(VotingMethod.Quadratic, { allowInsecure: true });
// Require fully secure methods only
VotingSecurityValidator.validate(VotingMethod.RankedChoice, { requireFullySecure: true });
// Throws: RankedChoice requires intermediate decryption| Export | Type | Purpose |
|---|---|---|
Poll |
Class | Core poll with vote aggregation |
VotingPoll |
Class | High-level voting with encrypted receipts |
PollTallier |
Class | Decrypts and tallies votes |
VoteEncoder |
Class | Encrypts votes by method |
PollFactory |
Class | Convenient poll creation |
VotingSecurityValidator |
Class | Security level validation |
ImmutableAuditLog |
Class | Hash-chained audit trail |
PublicBulletinBoard |
Class | Append-only vote publication |
PollEventLogger |
Class | Event tracking with timestamps |
VotingMethod |
Enum | All 17 voting methods |
SecurityLevel |
Enum | Security classifications |
EventType |
Enum | Event types for logging |
AuditEventType |
Enum | Audit event types |
VoteReceipt |
Interface | Cryptographic vote receipt |
PollResults |
Interface | Tally results with winner(s) |
EncryptedVote |
Interface | Encrypted vote structure |
The system includes 1100+ government-grade test cases across multiple test files:
# Run all voting tests
yarn test voting.spec.ts # Core voting functionality
yarn test voting-stress.spec.ts # Stress tests with large datasets
yarn test poll-core.spec.ts # Poll core functionality
yarn test poll-audit.spec.ts # Audit log integration
yarn test factory.spec.ts # Poll factory
yarn test encoder.spec.ts # Vote encoding
yarn test security.spec.ts # Security validation
yarn test audit.spec.ts # Audit log
yarn test bulletin-board.spec.ts # Bulletin board
yarn test event-logger.spec.ts # Event logger
yarn test poll.spec.ts # VotingPoll with encrypted receipts- ✅ All 17 Methods: Plurality, Approval, Weighted, Borda, Score, YesNo, YesNoAbstain, Supermajority, RankedChoice, TwoRound, STAR, STV, Quadratic, Consensus, ConsentBased
- ✅ Security validation (fully homomorphic, multi-round, insecure classifications)
- ✅ Attack resistance (vote manipulation, double voting, unauthorized decryption)
- ✅ Cryptographic correctness (homomorphic addition, receipt signatures)
- ✅ Edge cases (ties, single voter, unanimous votes, empty rankings)
- ✅ Large scale (1000 voters, 100 choices)
- ✅ Boundary conditions (max weights, zero votes, partial rankings)
- ✅ Determinism (same votes = same results)
- ✅ Receipt verification (signature validation, tampering detection)
- ✅ Multi-round elimination (IRV, STAR, STV, Two-Round)
- ✅ Government requirements (audit log, bulletin board, event logger)
- ✅ Stress testing (concurrent operations, memory limits)
- ✅ Cross-platform compatibility (Node.js Buffer ↔ Browser Uint8Array)
- ✅ Buffer operations (Node.js-specific binary data handling)
This Node.js implementation (@digitaldefiance/node-ecies-lib) extends the browser implementation (@digitaldefiance/ecies-lib) with Node.js-specific optimizations:
// VoteEncoder extends the browser VoteEncoder with Buffer specialization
export class VoteEncoder extends BaseVoteEncoder<Buffer> {
constructor(votingPublicKey: PublicKey) {
super(votingPublicKey);
}
// All encoding methods inherited from base class
// Generic type parameter TID specialized to Buffer
}
// PollFactory extends browser PollFactory to return Node.js Poll instances
export class PollFactory extends BasePollFactory {
static override create<TID extends PlatformID = Buffer>(
choices: string[],
method: VotingMethod,
authority: Member<TID>,
options?: { maxWeight?: bigint },
): Poll<TID> {
// Returns node-ecies-lib Poll instance with Buffer support
}
}The Node.js implementation extends the PlatformID type to include mongoose ObjectIds:
// From platform-id.ts
export type PlatformID =
| BasePlatformID // Uint8Array | GuidV4 | ObjectId | string
| Buffer // Node.js Buffer
| Types.ObjectId; // Mongoose ObjectIdThis allows seamless integration with MongoDB and mongoose-based applications:
import { Types } from '@digitaldefiance/mongoose-types';
// Use mongoose ObjectId as poll/voter ID
const pollId = new Types.ObjectId();
const poll = PollFactory.create(['A', 'B'], VotingMethod.Plurality, authority);The Node.js implementation supports all 17 voting methods through inheritance:
- Dedicated Methods (5):
encodePlurality,encodeApproval,encodeWeighted,encodeBorda,encodeRankedChoice - Generic Method:
encode(method, data, choiceCount)handles all 17 methods - Factory Methods: Both dedicated (
createPlurality, etc.) and generic (create) methods available
Complete Method List:
- Plurality, Approval, Weighted, Borda, Score ✅
- YesNo, YesNoAbstain, Supermajority ✅
- RankedChoice, TwoRound, STAR, STV ✅
- Quadratic, Consensus, ConsentBased ✅
All voting operations use Node.js Buffer instead of Uint8Array for better performance:
// Poll IDs, voter IDs, and hashes are all Buffers
const pollId = Buffer.from([1, 2, 3, 4]);
const voterIdHash = Buffer.from(crypto.createHash('sha256').update(voter.id).digest());Uses Node.js native crypto module for:
- SHA-256 hashing (audit log, bulletin board)
- Random bytes generation (nonces, IDs)
- Microsecond timestamps via
process.hrtime.bigint()
The voting system in node-ecies-lib is 100% compatible with the browser-based ecies-lib voting system:
- Same Paillier encryption parameters
- Same vote encoding formats
- Same receipt structures
- Same audit log format
Data encrypted in Node.js can be tallied in the browser and vice versa.
- README.md (this file) - Overview and quick start
- docs/GOVERNMENT-REQUIREMENTS.md - Complete EARS specification with implementation status
- docs/PHASE2-README.md - Voter registration and eligibility system (design phase)
- docs/PHASE2-SUMMARY.md - Executive summary of Phase 2 features
The examples.ts file contains comprehensive usage examples:
Basic Voting Methods:
examplePlurality()- Simple majority votingexampleRankedChoice()- Instant runoff voting (IRV)exampleWeighted()- Stakeholder voting with weightsexampleBorda()- Ranked voting with point allocationexampleApproval()- Multi-choice approval votingexampleReceipts()- Receipt generation and verification
Node.js-Specific Examples:
exampleFilePersistence()- Save/load encrypted votes to/from diskexampleStreamProcessing()- Process large voter datasets using streamsexampleBufferCrypto()- Cryptographic operations with BufferexampleAuditLogExport()- Export audit logs to JSON files
import {
examplePlurality,
exampleFilePersistence,
exampleBufferCrypto
} from '@digitaldefiance/node-ecies-lib/voting/examples';
// Run examples
await examplePlurality();
await exampleFilePersistence();
await exampleBufferCrypto();This Node.js implementation differs from the browser implementation in these ways:
| Feature | Browser (ecies-lib) | Node.js (node-ecies-lib) |
|---|---|---|
| Binary Data | Uint8Array |
Buffer |
| Crypto API | Web Crypto API | Node.js crypto module |
| File I/O | Not available | Native fs module |
| Streams | Not available | Native Node.js streams |
| Performance | Browser-optimized | V8-optimized |
All cryptographic operations, security properties, and voting methods are identical between platforms.
The threshold voting module enables real-time, distributed vote tallying where no single party can decrypt votes alone. The Node.js implementation extends the browser ecies-lib threshold module with Buffer support for improved performance.
For full API documentation, see the ecies-lib Threshold Voting documentation. All shared APIs (GuardianRegistry, CeremonyCoordinator, IntervalScheduler, DecryptionCombiner, PublicTallyFeed, TallyVerifier) are re-exported from ecies-lib and work identically.
The following classes extend the ecies-lib base with Node.js Buffer support:
| Export | Purpose |
|---|---|
ThresholdKeyGenerator |
Buffer-based key share handling (BufferKeyShare, BufferThresholdKeyPair) |
PartialDecryptionService |
Buffer-based partial decryption serialization (BufferPartialDecryption) |
ThresholdPoll |
Threshold poll specialized for Buffer-based PlatformID |
ThresholdPollFactory |
Creates threshold polls with Buffer support |
ThresholdAuditLog |
Audit logging with Buffer-based entry handling |
ThresholdPrecinctAggregator |
Precinct-level threshold aggregation with Buffer |
ThresholdCountyAggregator |
County-level threshold aggregation with Buffer |
ThresholdStateAggregator |
State-level threshold aggregation with Buffer |
ThresholdNationalAggregator |
National-level threshold aggregation with Buffer |
import {
ThresholdKeyGenerator,
GuardianRegistry,
GuardianStatus,
ThresholdPollFactory,
IntervalTriggerType,
} from '@digitaldefiance/node-ecies-lib';
// 1. Generate threshold keys (3-of-5 configuration)
const keyGen = new ThresholdKeyGenerator();
const keyPair = await keyGen.generate({ totalShares: 5, threshold: 3 });
// Key shares use Buffer for serialization
const serialized: Buffer = keyGen.serializeKeyShare(keyPair.keyShares[0]);
const deserialized = keyGen.deserializeKeyShare(serialized);
// 2. Register Guardians (uses Buffer-based PlatformID)
const registry = new GuardianRegistry<Buffer>({ totalShares: 5, threshold: 3 });
keyPair.keyShares.forEach((share, i) => {
registry.register({
id: Buffer.from([i + 1]),
name: `Guardian ${i + 1}`,
shareIndex: share.index,
verificationKey: share.verificationKey,
status: GuardianStatus.Online,
});
});
// 3. Create threshold poll with Buffer support
const factory = new ThresholdPollFactory(auditLog);
const poll = factory.createThresholdPoll(
['Alice', 'Bob', 'Charlie'],
VotingMethod.Plurality,
authority,
{
thresholdConfig: { totalShares: 5, threshold: 3 },
intervalConfig: {
triggerType: IntervalTriggerType.TimeBased,
timeIntervalMs: 3600000,
minimumIntervalMs: 60000,
ceremonyTimeoutMs: 300000,
},
guardianRegistry: registry,
keyPair,
}
);Threshold voting data is fully interoperable between Node.js and browser environments:
// Serialize in Node.js with Buffer
const partialService = new PartialDecryptionService();
const serialized: Buffer = partialService.serialize(partial);
// Deserialize in browser with Uint8Array (ecies-lib)
const deserialized = browserPartialService.deserialize(new Uint8Array(serialized));The Node.js voting system in @digitaldefiance/node-ecies-lib provides a complete implementation of all 17 voting methods with government-grade security:
- All 17 Methods: Every voting method from Plurality to ConsentBased is fully implemented and tested
- Node.js Optimized: Uses Buffer instead of Uint8Array for better Node.js performance
- Cross-Platform: 100% binary compatible with browser implementation
- Extended PlatformID: Supports Buffer and mongoose ObjectId in addition to base types
- Homomorphic Encryption: Paillier cryptosystem for privacy-preserving vote aggregation
- Immutable Audit Log: Cryptographic hash chain for complete audit trail
- Public Bulletin Board: Transparent, verifiable vote publication
- Event Logging: Microsecond-precision event tracking
- Role Separation: Poll aggregators cannot decrypt votes until closure
- 1100+ Tests: Comprehensive test coverage for all methods and edge cases
- Stress Tested: Handles 1000+ voters and complex elimination scenarios
- Attack Resistant: Prevents double voting, vote manipulation, and unauthorized decryption
- Documentation: Complete API reference and usage examples
The system is ready for production use in government elections, corporate governance, and any application requiring secure, verifiable voting.
MIT