165 lines
6.0 KiB
Markdown
165 lines
6.0 KiB
Markdown
![]() |
### Step 1: Define Scope and Tools
|
|||
|
#### Objective
|
|||
|
Build an MVP where users can register, get eligibility credentials, and submit anonymous opinions on a single legislative matter, with public verification.
|
|||
|
|
|||
|
#### Tech Stack Suggestions
|
|||
|
- **Programming Language**: Python (for rapid prototyping, with libraries for crypto) or Rust (for performance and security in production).
|
|||
|
- **Cryptography Libraries**:
|
|||
|
- `py-ecc` or `circom` (for ZKPs like zk-SNARKs).
|
|||
|
- `blind-signatures` (Python) or `rsa-blind-signatures` (custom implementation).
|
|||
|
- **Public Ledger**:
|
|||
|
- Local database (e.g., SQLite) for the MVP.
|
|||
|
- Optionally, Ethereum (with a testnet like Sepolia) for blockchain integration later.
|
|||
|
- **Frontend**: Flask (Python) or a simple CLI for the MVP; React/Vue.js later for a user interface.
|
|||
|
- **Development Environment**: Docker (to containerize components), Git (version control).
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Step 2: Design the Core Components
|
|||
|
Break the system into modular pieces you can build and test independently:
|
|||
|
|
|||
|
1. **Trusted Authority Module**
|
|||
|
- **Purpose**: Issues credentials and blind signatures.
|
|||
|
- **How**:
|
|||
|
- Simulate a credential issuer with a key pair (public/private).
|
|||
|
- Implement a blind signature scheme (e.g., RSA-based).
|
|||
|
- **Starting Point**: Use `blind-signatures` in Python or code a basic RSA blind signature:
|
|||
|
```python
|
|||
|
from blind_signatures import BlindSignature
|
|||
|
authority = BlindSignature(bits=2048)
|
|||
|
```
|
|||
|
|
|||
|
2. **Participant Module**
|
|||
|
- **Purpose**: Generates tokens, commitments, and ZKPs.
|
|||
|
- **How**:
|
|||
|
- Generate a random token and secret key per user per matter.
|
|||
|
- Create a commitment: `commitment = hash(token || secret || matter_id)` (e.g., SHA-256).
|
|||
|
- Use a ZKP library like `circom` to prove knowledge of the secret without revealing it.
|
|||
|
- **Starting Point**: Use `hashlib` for commitments:
|
|||
|
```python
|
|||
|
import hashlib
|
|||
|
token = "random123"
|
|||
|
secret = "secret456"
|
|||
|
matter_id = "Law001"
|
|||
|
commitment = hashlib.sha256((token + secret + matter_id).encode()).hexdigest()
|
|||
|
```
|
|||
|
|
|||
|
3. **Public Ledger**
|
|||
|
- **Purpose**: Stores commitments and submissions.
|
|||
|
- **How**: Use SQLite to store `(commitment, blind_signature, matter_id)` tuples for now.
|
|||
|
- **Starting Point**:
|
|||
|
```python
|
|||
|
import sqlite3
|
|||
|
conn = sqlite3.connect("ledger.db")
|
|||
|
conn.execute("CREATE TABLE commitments (id INTEGER PRIMARY KEY, commitment TEXT, signature TEXT, matter_id TEXT)")
|
|||
|
```
|
|||
|
|
|||
|
4. **Verification Module**
|
|||
|
- **Purpose**: Validates submissions.
|
|||
|
- **How**: Check blind signatures and ZKPs; ensure token uniqueness.
|
|||
|
- **Starting Point**: Mock a verifier that checks `authority.verify()` output.
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Step 3: Build the MVP Workflow
|
|||
|
#### Workflow
|
|||
|
1. **Setup Phase**:
|
|||
|
- User registers with the authority, gets a credential.
|
|||
|
- User generates token, secret, and commitment for a matter (e.g., "Law001").
|
|||
|
- User blinds the commitment, gets a signature from the authority, unblinds it, and stores it in the ledger.
|
|||
|
2. **Submission Phase**:
|
|||
|
- User submits an opinion (e.g., "Yes") with their token and a ZKP.
|
|||
|
- System verifies the ZKP and ensures the token is unused.
|
|||
|
- Opinion is recorded.
|
|||
|
|
|||
|
#### Prototype Code (Python Example)
|
|||
|
```python
|
|||
|
import hashlib
|
|||
|
from blind_signatures import BlindSignature
|
|||
|
|
|||
|
# Authority setup
|
|||
|
authority = BlindSignature(bits=2048)
|
|||
|
|
|||
|
# User setup
|
|||
|
token = "token123"
|
|||
|
secret = "secret789"
|
|||
|
matter_id = "Law001"
|
|||
|
commitment = hashlib.sha256((token + secret + matter_id).encode()).hexdigest()
|
|||
|
|
|||
|
# Blind and sign
|
|||
|
blinded, unblinder = authority.blind(commitment)
|
|||
|
signature = authority.sign(blinded)
|
|||
|
unblinded_signature = authority.unblind(signature, unblinder)
|
|||
|
|
|||
|
# Store in ledger
|
|||
|
import sqlite3
|
|||
|
conn = sqlite3.connect("ledger.db")
|
|||
|
conn.execute("INSERT INTO commitments (commitment, signature, matter_id) VALUES (?, ?, ?)",
|
|||
|
(commitment, unblinded_signature, matter_id))
|
|||
|
conn.commit()
|
|||
|
|
|||
|
# Submission (simplified ZKP placeholder)
|
|||
|
opinion = "Yes"
|
|||
|
# In practice, generate a ZKP here with circom or similar
|
|||
|
submitted_token = token
|
|||
|
print(f"Opinion: {opinion}, Token: {submitted_token}")
|
|||
|
```
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Step 4: Add Zero-Knowledge Proofs
|
|||
|
#### Why ZKPs?
|
|||
|
They prove the token matches a commitment without revealing which one, ensuring anonymity.
|
|||
|
|
|||
|
#### How to Start
|
|||
|
- **Tool**: Use `circom` (a ZK circuit compiler) with `snarkjs` for zk-SNARKs.
|
|||
|
- **Circuit**: Define a simple circuit to prove `hash(token, secret, matter_id) == commitment`.
|
|||
|
- **Steps**:
|
|||
|
1. Install `circom` and `snarkjs` (via npm).
|
|||
|
2. Write a circuit in `circom`:
|
|||
|
```circom
|
|||
|
template CommitmentCheck() {
|
|||
|
signal input token;
|
|||
|
signal input secret;
|
|||
|
signal input matter_id;
|
|||
|
signal input commitment;
|
|||
|
signal output valid;
|
|||
|
|
|||
|
// Simplified hash (use Poseidon or MiMC in practice)
|
|||
|
valid <== commitment === hash([token, secret, matter_id]);
|
|||
|
}
|
|||
|
```
|
|||
|
3. Compile and generate a proof with `snarkjs`.
|
|||
|
4. Verify the proof in your Python verifier.
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Step 5: Test and Iterate
|
|||
|
#### Test Plan
|
|||
|
- **Unit Tests**: Verify each module (authority, participant, ledger).
|
|||
|
- **Integration Test**: Run a full cycle with 5-10 mock users.
|
|||
|
- **Edge Cases**: Test duplicate submissions, invalid signatures.
|
|||
|
|
|||
|
#### Tools
|
|||
|
- `pytest` for Python unit tests.
|
|||
|
- Manual checks via CLI output.
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Step 6: Next Steps
|
|||
|
Once the MVP works:
|
|||
|
- **Scalability**: Switch to a blockchain (e.g., Ethereum testnet) for the ledger.
|
|||
|
- **User Interface**: Build a Flask or React frontend.
|
|||
|
- **Efficiency**: Optimize ZKPs with zk-STARKs or precomputed trusted setups.
|
|||
|
- **Security Audit**: Review crypto implementations with an expert.
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### Recommendations
|
|||
|
- **Start Small**: Focus on blind signatures and a basic ledger first; add ZKPs after.
|
|||
|
- **Learn by Doing**: Experiment with `circom` tutorials (e.g., on GitHub) to grasp ZKPs.
|
|||
|
- **Resources**:
|
|||
|
- “Mastering Zero-Knowledge Proofs” (online guides).
|
|||
|
- Ethereum’s zk-SNARK docs.
|
|||
|
- GitHub repos like `iden3/circom`.
|