Blockchain-verified educational credentials on zkSync Era
zkCredentials is a decentralized platform for issuing, managing, and verifying educational credentials using blockchain technology. Built on zkSync Era for fast, low-cost transactions with Ethereum-level security.
- π Role-Based Authentication - Guided auth methods optimized for each user type
- π‘οΈ Privacy-Preserving - ZK-proof authentication for private login after one-time setup
- π Tamper-Proof - Certificates stored as cryptographic hashes on-chain
- β‘ Instant Verification - Verify any certificate in seconds
- ποΈ Institution Management - Verified institutions issue credentials
- π° Low Cost - zkSync Era enables affordable transactions
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Frontend ββββββΆβ Smart Contracts ββββββΆβ The Graph β
β React + wagmi β β zkSync Era β β Subgraph β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
- InstitutionRegistry - Manages verified educational institutions
- CertificateRegistry - Issues and tracks certificates
| Layer | Technology |
|---|---|
| Blockchain | zkSync Era (Sepolia Testnet / Mainnet) |
| Smart Contracts | Solidity 0.8.24, OpenZeppelin 5.x |
| Frontend | React 18, TypeScript, Vite |
| Wallet | wagmi v2, RainbowKit |
| Styling | Tailwind CSS |
| Indexing | The Graph |
- Node.js 18+
- npm or yarn
- MetaMask or compatible Web3 wallet
- (Optional) Testnet ETH for Sepolia deployment
Recommended: Hardhat local (localHardhat, chain 1337)
# Terminal 1: start Hardhat local node
cd contracts && npx hardhat node
# Terminal 2: deploy and auto-configure frontend/.env.local
cd contracts && npm run deploy:local
# Terminal 3: start frontend
cd frontend && npm run devYour app will be running at http://localhost:5173 π
Alternative local modes
# zkSync in-memory node (anvil-zksync, chain 260)
cd contracts && npm run node:local:zksync
cd contracts && npm run deploy:local:zksync
# zkSync docker local L2 (chain 270)
cd contracts && npm run deploy:local:dockerπ See docs/SETUP_CHECKLIST.md for detailed verification steps
π Documentation index: See docs/README.md for the current authoritative guides and the historical-docs policy.
β οΈ Development Mode: The app includes a visual "Development Mode" indicator showing that ZK authentication is running with simplified proofs for testing. See frontend/DEVELOPMENT_MODE.md for details.
# Clone the repository
cd ~/src/zkp/project/zksync-zzlogin-dapp-Sep-2025-d
# Install contract dependencies
cd contracts
npm install
# Install frontend dependencies
cd ../frontend
npm installFor localHardhat (Development):
# Contracts - Use test private key
cd contracts
cat > .env << 'EOF'
DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
EOF
# Frontend
cd ../frontend
# Will be auto-configured by `cd ../contracts && npm run deploy:local`For Sepolia Testnet:
cd contracts
cat > .env << 'EOF'
DEPLOYER_PRIVATE_KEY=your_actual_private_key_here
EOF
cd ../frontend
cat > .env.local << 'EOF'
VITE_WALLETCONNECT_PROJECT_ID=39e2e3d2a23e2049152548d5c1e9ad6a
VITE_CERTIFICATE_REGISTRY_ADDRESS=<deployed_address>
VITE_INSTITUTION_REGISTRY_ADDRESS=<deployed_address>
VITE_CHAIN_ID=300
EOFπ See docs/ENVIRONMENT_SETUP.md for switching between environments
# Compile contracts
cd contracts
npm run compile
# Run tests
npm test
# Deploy to testnet
npm run deploy:staging
# Start frontend
cd ../frontend
npm run devzksync-zzlogin-dapp/
βββ contracts/ # Smart contracts
β βββ contracts/ # Solidity source files
β βββ deploy/ # Deployment scripts
β βββ test/ # Contract tests
βββ frontend/ # React application
β βββ src/
β β βββ components/ # React components
β β βββ hooks/ # Custom hooks
β β βββ lib/ # Utilities
β β βββ pages/ # Page components
β β βββ store/ # Zustand stores
β βββ public/
βββ subgraph/ # The Graph indexer
βββ docs/ # Documentation
βββ .cursor/rules/ # Cursor AI rules
zkCredentials implements role-based authentication with guided defaults for optimal security and user experience.
| User Type | Default Method | Available Methods | Rationale |
|---|---|---|---|
| Admin | Web3 Only | Web3 | Public accountability and transparency |
| University | Web3 Only | Web3 | Public institution + high transaction volume |
| Student | ZKP (Privacy) | ZKP, Web3 | Privacy for authentication after one-time setup |
| Employer | Web3 (Standard) | Web3, ZKP | Flexibility for different hiring contexts |
For Students (Privacy-First):
- Connect Web3 wallet
- System auto-detects student role (if certificate exists)
- Private Login (ZK) shown by default
- π One-time setup - wallet visible during registration
- π‘οΈ Private authentication - ZK proofs hide secret key during login (wallet pseudonymous on-chain)
- βοΈ Setup takes ~30 seconds, then login forever privately
- π‘ Pro Tip: Use a dedicated "registration wallet" for maximum privacy
- Web3 fallback available if needed
- Access student dashboard
For Employers (Flexible):
- Connect Web3 wallet
- Standard Login (Web3) shown by default
- π Simple & Fast - no setup required
- β‘ Instant Access - login in seconds
- Upgrade to ZKP for executive search/competitive hiring
- Access verification dashboard
For Universities:
- Connect Web3 wallet (required by admin)
- Standard Login (Web3) only
- Public accountability as educational institution
- Cost-efficient for high-volume certificate issuance
- Access institution dashboard
For Admin:
- Connect Web3 wallet (predefined address)
- Standard Login (Web3) only
- Public accountability and transparency
- Administrative oversight requires visibility
- Access admin dashboard
π See DUAL-AUTH-SYSTEM.md for detailed authentication guide
π See AUTH-WORKFLOWS-BY-USER-TYPE.md for complete workflow definitions
- Choose authentication method
- Connect wallet (if using Standard Login)
- Register institution with name and email domain
- Wait for admin approval
- Issue certificates by uploading PDF and entering student wallet
- Upload certificate PDF
- System generates SHA-256 hash
- Hash is verified against blockchain
- View certificate status (valid/invalid/revoked)
| Function | Description |
|---|---|
registerInstitution(name, emailDomain) |
Register new institution |
approveInstitution(wallet) |
Admin approves institution |
suspendInstitution(wallet) |
Suspend an institution |
canIssueCertificates(wallet) |
Check if institution can issue |
| Function | Description |
|---|---|
issueCertificate(hash, student, uri) |
Issue new certificate |
revokeCertificate(id, reason) |
Revoke a certificate |
isValidCertificate(hash) |
Verify certificate validity |
getCertificatesByStudent(wallet) |
Get student's certificates |
- Role-Based Authentication - ZK proofs for students, Web3 for institutions/admin
- Zero-Knowledge Privacy Model:
- Setup Phase: Wallet visible during one-time commitment registration
- Auth Phase: Login privately with ZK proofs (secret key hidden; wallet pseudonymous on-chain via msg.sender)
- Usage Phase: User controls when to reveal wallet for specific actions
- Best Practice: Use dedicated registration wallet for maximum privacy
- All contracts use OpenZeppelin's battle-tested libraries
- UUPS upgradeable pattern for contract upgrades
- AccessControl for role-based permissions
- ReentrancyGuard on state-changing functions
- Custom errors for gas-efficient reverts
π See DUAL-AUTH-SYSTEM.md for security details
For Maximum Privacy with ZK Authentication:
-
Use a Dedicated Registration Wallet
- Create a fresh wallet specifically for ZK registration
- Don't use this wallet for any other transactions
- After registration, only login using ZK proofs (wallet stays hidden)
-
Understand the Privacy Model
Phase 1 - Registration (One-Time): ββ Your wallet IS visible on-chain ββ Commitment is registered publicly ββ This is a necessary step for cryptographic setup Phase 2 - Authentication (Every Login): ββ Login using zero-knowledge proofs ββ Your secret key is NOT revealed ββ Pseudonymous authentication (wallet visible as msg.sender, but secrets stay private) Phase 3 - Usage (Your Control): ββ Choose when to reveal wallet ββ Required for: receiving certificates, transactions ββ Optional for: viewing, verification -
Transaction Privacy Tips
- Use privacy-focused wallets for registration (e.g., fresh address)
- Consider using a relayer service in the future (Phase 2)
- Separate your "registration wallet" from your "usage wallet"
-
What's Private vs. What's Public
Private (Hidden):
- β Secret key (never leaves browser, proved via ZK)
- β Salt and private inputs (hidden by zero-knowledge property)
- β Identity verification without revealing secrets
- β Per-session nullifiers (unlinkable at the nullifier level)
Public (Visible on-chain):
β οΈ Registration transaction (commitment creation)β οΈ Wallet that registered the commitment (msg.sender)β οΈ Wallet that authenticates (msg.sender visible in startSession tx)β οΈ Any transactions you make after login
-
Why This Model?
- One-time wallet exposure for cryptographic commitment is unavoidable in Phase 1
- After setup, you gain permanent private authentication
- Future enhancements (Phase 2) will add meta-transactions for truly anonymous registration
- This is more private than standard Web3 auth (100% wallet exposure)
Example Workflow:
# 1. Create fresh wallet for registration
New Wallet: 0xABC... (dedicated for registration only)
# 2. Register with ZK Auth (wallet visible)
On-chain: 0xABC... β registerCommitment(commitment123)
Result: Public can see 0xABC registered commitment123
# 3. Login privately (secret key hidden)
ZK Proof: "I know the secret behind commitment123"
Result: Secret key stays private; wallet is pseudonymous on-chain
# 4. Use the system
Future actions: You choose when to reveal walletπ‘ Coming in Phase 2: Meta-transaction support for truly anonymous registration via relayers
MIT License - see LICENSE for details.
Contributions are welcome! Please read our contributing guidelines before submitting PRs.