http://docker:8085Create N-of-M wallets where each signer gets an independent ML-DSA-65 keypair. No single point of compromise.
ML-DSA-65 (FIPS 204)Create proposals that require threshold signatures. Proposal data becomes the canonical bytes all signers sign.
ML-DSA-65 (FIPS 204)When threshold signatures accumulate, execute the proposal. Every signature verified with provider.verify() before execution.
ML-DSA-65 (FIPS 204)This service demonstrates quantum-safe multi-signature governance — the same patterns you'll implement using the Qudo JNI provider in your DAO / treasury / DeFi protocol.
Multi-sig wallet creation: Each signer gets their own provider.generateKeyPair("ML-DSA-65")
Proposal signing: Each signer independently calls provider.sign(proposalData, theirPrivKey, "ML-DSA-65")
Threshold execution: Proposal executes when signatures from N-of-M signers accumulate — each verified with provider.verify()
/api/defi/create-multisig
Create N-of-M multi-sig wallet
/api/defi/create-proposal
Create a governance proposal
/api/defi/sign-proposal
Signer signs a proposal
/api/defi/execute-proposal
Execute proposal if threshold met
/api/defi/wallets
List all multi-sig wallets
/api/defi/proposals
List all proposals
/api/defi/health
Service health
Migrate your DAO / treasury / DeFi governance to quantum-safe multi-signature. Use this playground to try PQC multi-sig operations, then use the Qudo JNI provider in your governance contracts and signing clients.
Signers (N-of-M) Multi-Sig Wallet | | | 1. Each signer has own ML-DSA-65 keypair | | signer[i].keys = provider.generateKeyPair(...) | | | | 2. Proposal created (canonical bytes) | | proposalData = "transfer 1000 USDC to 0xabc" | | | | 3. Each signer independently signs: | | sig[i] = provider.sign(proposalData, | | signer[i].privKey, | | "ML-DSA-65") | | | |---- signatures accumulate on-chain ----------------->| | | | 4. Execute when threshold met: | | for each sig[i]: | | provider.verify(proposalData, sig[i], | | signer[i].pubKey, | | "ML-DSA-65") | | Count valid sigs >= threshold -> execute
Unlike BLS aggregation, ML-DSA signatures are independent per signer. Each signer has their own keypair from provider.generateKeyPair(). No single point of compromise.
Governance contract counts valid signatures via provider.verify(). Executes only when count ≥ threshold. Quantum-safe DAO governance.
Replace ECDSA multi-sig (Gnosis Safe pattern) with Qudo JNI per-signer keys. Proposal/voting logic stays the same.
import com.qudo.crypto.QudoCrypto;
import com.qudo.crypto.QudoKeyPair;
import java.util.List;
import java.util.ArrayList;
QudoCrypto provider = QudoCrypto.create();
// ============================================================
// 1. Set up multi-sig wallet (2-of-3 treasury)
// ============================================================
int threshold = 2;
List<QudoKeyPair> signers = new ArrayList<>();
for (int i = 0; i < 3; i++) {
signers.add(provider.generateKeyPair("ML-DSA-65"));
// Each signer stores THEIR private key in their own HSM
// Public keys published on-chain as wallet signer set
}
// ============================================================
// 2. Create and sign a proposal
// ============================================================
String proposalData = "transfer 1000 USDC to 0xabc123";
byte[] canonicalBytes = proposalData.getBytes();
List<byte[]> collectedSigs = new ArrayList<>();
// Signer 0 signs (from their client):
collectedSigs.add(provider.sign(canonicalBytes,
signers.get(0).getPrivateKeyPem(), "ML-DSA-65"));
// Signer 1 signs (from their client):
collectedSigs.add(provider.sign(canonicalBytes,
signers.get(1).getPrivateKeyPem(), "ML-DSA-65"));
// Signer 2 does NOT sign — only 2-of-3 needed
// ============================================================
// 3. Execute proposal (contract verifies threshold)
// ============================================================
int validCount = 0;
for (int i = 0; i < collectedSigs.size(); i++) {
if (provider.verify(canonicalBytes, collectedSigs.get(i),
signers.get(i).getPublicKeyPem(), "ML-DSA-65")) {
validCount++;
}
}
if (validCount >= threshold) executeProposal();
else rejectProposal();
provider.close();
provider.verify() and executes when the threshold is met.
| Operation | ML-DSA-65 | ECDSA multi-sig |
|---|---|---|
| Signer key generation | ~55ms per signer (once) | ~3ms per signer (once) |
| Proposal sign (per signer) | ~10ms | <1ms |
| Verify all signatures (N=3) | ~15ms total | ~3ms total |
| On-chain signature size (N=3) | ~9.9KB | ~192 bytes |
Cause: If signers sign different byte representations of the same proposal (whitespace, key order), signatures don't aggregate.
Fix: Define canonical serialization (RFC 8785 JSON, or Protobuf) and have all clients use it before calling provider.sign().
Cause: ML-DSA doesn't support signature aggregation. N signers = N signatures stored on-chain.
Mitigation: Use fewer signers (e.g., 3-of-5 instead of 10-of-15), or aggregate off-chain with a single executor signature committing to the set.
A: Yes — the governance logic is identical. Replace the signature verification module in your Safe-like contract to call provider.verify() with ML-DSA-65 public keys instead of ECDSA.
A: BLS is not quantum-safe. Use ML-DSA-65 per signer. For very large signer sets, consider SNARK-based aggregation or rotate to a smaller governance council.
Analyze any endpoint's cryptographic configuration. Enter a host:port to scan its TLS setup and identify what's quantum-safe vs what needs migration.