{"id":37231736,"url":"https://github.com/10d9e/vhe","last_synced_at":"2026-01-15T03:45:37.685Z","repository":{"id":332288408,"uuid":"1064732906","full_name":"10d9e/vhe","owner":"10d9e","description":"Verifiable Homomorphic Encryption","archived":false,"fork":false,"pushed_at":"2025-09-26T22:12:54.000Z","size":142,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T09:58:39.381Z","etag":null,"topics":["cryptography"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/10d9e.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-26T13:24:10.000Z","updated_at":"2025-12-14T17:12:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/10d9e/vhe","commit_stats":null,"previous_names":["10d9e/vhe"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/10d9e/vhe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/10d9e%2Fvhe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/10d9e%2Fvhe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/10d9e%2Fvhe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/10d9e%2Fvhe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/10d9e","download_url":"https://codeload.github.com/10d9e/vhe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/10d9e%2Fvhe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28416492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T08:38:59.149Z","status":"ssl_error","status_checked_at":"2026-01-14T08:38:43.588Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography"],"created_at":"2026-01-15T03:45:37.084Z","updated_at":"2026-01-15T03:45:37.668Z","avatar_url":"https://github.com/10d9e.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Verifiable Homomorphic Encryption\n[![Crates.io](https://img.shields.io/crates/v/vhe)](https://crates.io/crates/vhe)\n\nRust implementation of ElGamal homomorphic encryption with non-interactive zero-knowledge proofs (NIZK) for verifiable operations.\n\n## Features\n\n- **Dual-mode operation**: Switch between multiplicative and additive homomorphism\n- **Operator overrides**: Use familiar `+`, `-`, `*`, `/` operators directly on ciphertexts\n- **Verifiable computation**: All operations can be verified with NIZK proofs\n- **Batch operations**: Efficient processing of multiple ciphertexts\n- **Re-randomization**: Generate different ciphertexts for the same plaintext\n- **Zero-knowledge proofs**: Prove correctness without revealing secrets\n- **No trusted setup**: Unlike zk-SNARKs, no ceremony needed\n\n## Installation\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\nvhe = \"0.1.1\"\n```\n\nOr clone and build:\n\n```bash\ngit clone https://github.com/yourusername/vhe\ncd vhe\ncargo build --release\n```\n\n## Quick Start\n\n### Basic Encryption with Operator Overrides\n\n```rust\nuse vhe::{KeyPair, ElGamal, ElGamalOperators, HomomorphicMode};\nuse num_bigint::ToBigUint;\n\n// Generate keys\nlet keypair = KeyPair::load_or_generate(512)?;\n\n// Create ElGamal instance for additive operations\nlet elgamal = ElGamal::new(\n    keypair.public_key.clone(),\n    HomomorphicMode::Additive\n);\n\n// Encrypt values\nlet ct1 = elgamal.encrypt(\u002610u32.to_biguint().unwrap())?;\nlet ct2 = elgamal.encrypt(\u002620u32.to_biguint().unwrap())?;\n\n// Wrap ciphertexts with context for operator overrides\nlet ctx1 = elgamal.wrap_ciphertext(ct1);\nlet ctx2 = elgamal.wrap_ciphertext(ct2);\n\n// Use standard operators!\nlet sum = (\u0026ctx1 + \u0026ctx2)?;        // Addition: 10 + 20\nlet diff = (\u0026ctx1 - \u0026ctx2)?;       // Subtraction: 10 - 20\nlet neg = (-\u0026ctx1)?;               // Negation: -10\nlet scalar_add = (\u0026ctx1 + \u00265u32.to_biguint().unwrap())?; // Scalar addition: 10 + 5\n\n// Decrypt results\nlet sum_result = elgamal.decrypt(\u0026sum, \u0026keypair.private_key)?;\nlet diff_result = elgamal.decrypt(\u0026diff, \u0026keypair.private_key)?;\nlet neg_result = elgamal.decrypt(\u0026neg, \u0026keypair.private_key)?;\nlet scalar_result = elgamal.decrypt(\u0026scalar_add, \u0026keypair.private_key)?;\n\nassert_eq!(sum_result, 30u32.to_biguint().unwrap());\nassert_eq!(scalar_result, 15u32.to_biguint().unwrap());\n```\n\n### Multiplicative Mode with Operators\n\n```rust\n// Create ElGamal instance for multiplicative operations\nlet elgamal_mult = ElGamal::new(\n    keypair.public_key.clone(),\n    HomomorphicMode::Multiplicative\n);\n\n// Encrypt values\nlet ct1 = elgamal_mult.encrypt(\u00267u32.to_biguint().unwrap())?;\nlet ct2 = elgamal_mult.encrypt(\u00263u32.to_biguint().unwrap())?;\n\n// Wrap with context\nlet ctx1 = elgamal_mult.wrap_ciphertext(ct1);\nlet ctx2 = elgamal_mult.wrap_ciphertext(ct2);\n\n// Use operators for multiplicative operations\nlet product = (\u0026ctx1 * \u0026ctx2)?;    // Multiplication: 7 * 3\nlet quotient = (\u0026ctx1 / \u0026ctx2)?;   // Division: 7 / 3\nlet power = (\u0026ctx1 * \u00262u32.to_biguint().unwrap())?; // Exponentiation: 7^2\n\n// Decrypt results\nlet product_result = elgamal_mult.decrypt(\u0026product, \u0026keypair.private_key)?;\nlet quotient_result = elgamal_mult.decrypt(\u0026quotient, \u0026keypair.private_key)?;\nlet power_result = elgamal_mult.decrypt(\u0026power, \u0026keypair.private_key)?;\n\nassert_eq!(product_result, 21u32.to_biguint().unwrap());\nassert_eq!(power_result, 49u32.to_biguint().unwrap());\n```\n\n### Verifiable Operations with Operator Overrides\n\n```rust\nuse vhe::{VerifiableOperations, HomomorphicOperations, ElGamalOperators};\nuse num_bigint::ToBigUint;\n\nlet keypair = KeyPair::load_or_generate(512)?;\nlet elgamal = ElGamal::new(keypair.public_key.clone(), HomomorphicMode::Additive);\n\n// Encrypt values with proofs\nlet value1 = 5u32.to_biguint().unwrap();\nlet value2 = 3u32.to_biguint().unwrap();\nlet (ct1, enc_proof1) = elgamal.encrypt_with_proof(\u0026value1, None)?;\nlet (ct2, enc_proof2) = elgamal.encrypt_with_proof(\u0026value2, None)?;\n\n// Verify encryption proofs\nassert!(elgamal.verify_encryption_proof(\u0026ct1, \u0026value1, \u0026enc_proof1));\nassert!(elgamal.verify_encryption_proof(\u0026ct2, \u0026value2, \u0026enc_proof2));\n\n// Wrap ciphertexts with context for operator overrides\nlet ctx1 = elgamal.wrap_ciphertext(ct1);\nlet ctx2 = elgamal.wrap_ciphertext(ct2);\n\n// Use operators for intuitive computation\nlet sum = (\u0026ctx1 + \u0026ctx2)?;        // Addition: 5 + 3\nlet scalar_add = (\u0026ctx1 + \u00262u32.to_biguint().unwrap())?; // Scalar addition: 5 + 2\n\n// Generate proof for the ciphertext-to-ciphertext operation\nlet (_, sum_proof) = elgamal.homomorphic_operation_with_proof(ctx1.ciphertext(), ctx2.ciphertext())?;\n\n// Verify the operation proof\nassert!(elgamal.verify_operation_proof(ctx1.ciphertext(), ctx2.ciphertext(), \u0026sum, \u0026sum_proof));\n\n// Decrypt and verify results\nlet sum_result = elgamal.decrypt(\u0026sum, \u0026keypair.private_key)?;\nlet scalar_result = elgamal.decrypt(\u0026scalar_add, \u0026keypair.private_key)?;\nassert_eq!(sum_result, 8u32.to_biguint().unwrap());\nassert_eq!(scalar_result, 7u32.to_biguint().unwrap());\n```\n\n### Advanced Verifiable Computation\n\n```rust\n// Multi-step verifiable computation with operators\nlet values = vec![5u32, 10u32, 15u32, 20u32];\nlet mut ciphertexts = Vec::new();\nlet mut enc_proofs = Vec::new();\n\n// Encrypt all values with proofs\nfor value in \u0026values {\n    let (ct, proof) = elgamal.encrypt_with_proof(\u0026value.to_biguint().unwrap(), None)?;\n    ciphertexts.push(ct);\n    enc_proofs.push(proof);\n}\n\n// Verify all encryption proofs\nfor (i, (ct, proof)) in ciphertexts.iter().zip(enc_proofs.iter()).enumerate() {\n    assert!(elgamal.verify_encryption_proof(ct, \u0026values[i].to_biguint().unwrap(), proof));\n}\n\n// Perform verifiable aggregation using operators\nlet mut ctx_sum = elgamal.wrap_ciphertext(ciphertexts[0].clone());\nlet mut operation_proofs = Vec::new();\n\nfor i in 1..ciphertexts.len() {\n    let ctx_next = elgamal.wrap_ciphertext(ciphertexts[i].clone());\n    \n    // Use operator for addition\n    let (new_sum, op_proof) = elgamal.homomorphic_operation_with_proof(\n        \u0026ctx_sum.ciphertext, \n        \u0026ctx_next.ciphertext\n    )?;\n    \n    // Verify the operation\n    assert!(elgamal.verify_operation_proof(\n        \u0026ctx_sum.ciphertext, \n        \u0026ctx_next.ciphertext, \n        \u0026new_sum, \n        \u0026op_proof\n    ));\n    \n    ctx_sum = elgamal.wrap_ciphertext(new_sum);\n    operation_proofs.push(op_proof);\n}\n\n// Final result should be sum of all values\nlet final_result = elgamal.decrypt(\u0026ctx_sum.ciphertext, \u0026keypair.private_key)?;\nlet expected_sum: u32 = values.iter().sum();\nassert_eq!(final_result, expected_sum.to_biguint().unwrap());\n```\n\n## Operator Overrides\n\nThe library provides intuitive operator overrides that make homomorphic operations feel natural:\n\n### CiphertextWithContext\n\nThe recommended approach uses `CiphertextWithContext` to wrap ciphertexts with their ElGamal context:\n\n```rust\nuse vhe::{ElGamal, ElGamalOperators, HomomorphicMode, KeyPair};\nuse num_bigint::ToBigUint;\n\nlet keypair = KeyPair::load_or_generate(512)?;\nlet elgamal = ElGamal::new(keypair.public_key.clone(), HomomorphicMode::Additive);\n\n// Encrypt and wrap with context\nlet ct1 = elgamal.encrypt(\u00265u32.to_biguint().unwrap())?;\nlet ct2 = elgamal.encrypt(\u00263u32.to_biguint().unwrap())?;\nlet ctx1 = elgamal.wrap_ciphertext(ct1);\nlet ctx2 = elgamal.wrap_ciphertext(ct2);\n\n// Use standard operators!\nlet sum = (\u0026ctx1 + \u0026ctx2)?;        // Addition\nlet diff = (\u0026ctx1 - \u0026ctx2)?;       // Subtraction\nlet neg = (-\u0026ctx1)?;               // Negation\nlet scalar_add = (\u0026ctx1 + \u00262u32.to_biguint().unwrap())?; // Scalar addition\nlet scalar_mul = (\u0026ctx1 * \u00262u32.to_biguint().unwrap())?; // Scalar multiplication\n```\n\n### Operators with Verifiable Proofs\n\nYou can combine the intuitive operator syntax with verifiable operations:\n\n```rust\nuse vhe::{VerifiableOperations, ElGamalOperators};\n\n// Encrypt with proofs\nlet (ct1, enc_proof1) = elgamal.encrypt_with_proof(\u00265u32.to_biguint().unwrap(), None)?;\nlet (ct2, enc_proof2) = elgamal.encrypt_with_proof(\u00263u32.to_biguint().unwrap(), None)?;\n\n// Verify encryption proofs\nassert!(elgamal.verify_encryption_proof(\u0026ct1, \u00265u32.to_biguint().unwrap(), \u0026enc_proof1));\nassert!(elgamal.verify_encryption_proof(\u0026ct2, \u00263u32.to_biguint().unwrap(), \u0026enc_proof2));\n\n// Wrap with context for operators\nlet ctx1 = elgamal.wrap_ciphertext(ct1);\nlet ctx2 = elgamal.wrap_ciphertext(ct2);\n\n// Use operators for the computation\nlet sum = (\u0026ctx1 + \u0026ctx2)?;        // Intuitive syntax\nlet diff = (\u0026ctx1 - \u0026ctx2)?;       // Clean and readable\n\n// Generate proof for the operation (ciphertext-to-ciphertext only)\nlet (_, sum_proof) = elgamal.homomorphic_operation_with_proof(ctx1.ciphertext(), ctx2.ciphertext())?;\n\n// Verify the operation proof\nassert!(elgamal.verify_operation_proof(ctx1.ciphertext(), ctx2.ciphertext(), \u0026sum, \u0026sum_proof));\n\n// Decrypt and verify results\nlet sum_result = elgamal.decrypt(\u0026sum, \u0026keypair.private_key)?;\nlet diff_result = elgamal.decrypt(\u0026diff, \u0026keypair.private_key)?;\nassert_eq!(sum_result, 8u32.to_biguint().unwrap());\nassert_eq!(diff_result, 2u32.to_biguint().unwrap());\n```\n\nThis approach gives you the best of both worlds:\n- **Intuitive operators** for clean, readable code\n- **Verifiable proofs** for ciphertext-to-ciphertext operations\n- **Full auditability** of all operations\n- **Note**: Scalar operations use operators for convenience but don't generate verifiable proofs\n\n## Homomorphic Modes\n\n### Multiplicative Mode\n- **Operation**: `Enc(a) × Enc(b) = Enc(a × b)`\n- **Use cases**: Product aggregation, RSA-like operations\n- **Message space**: Full range [0, p-1]\n\n### Additive Mode\n- **Operation**: `Enc(a) ⊗ Enc(b) = Enc(a + b)`\n- **Use cases**: Voting, statistics, counters\n- **Message space**: Limited (configurable, default 1M)\n\n## Available Operations\n\n| Operation | Multiplicative Mode | Additive Mode |\n|-----------|-------------------|---------------|\n| Basic Operation | Multiplication | Addition |\n| Scalar Operation | Exponentiation | Scalar Multiplication |\n| Division | ✓ | ✗ |\n| Subtraction | ✗ | ✓ |\n| Negation | ✗ | ✓ |\n| Batch Operations | ✓ | ✓ |\n| Linear Combination | ✗ | ✓ |\n| Re-randomization | ✓ | ✓ |\n\n## Zero-Knowledge Proofs\n\nThe library includes several NIZK proof types:\n\n1. **Proof of Knowledge**: Prove you know a secret without revealing it\n2. **Proof of Correct Encryption**: Prove a ciphertext encrypts a specific plaintext\n3. **Proof of Equality**: Prove two ciphertexts encrypt the same value\n4. **Proof of Correct Operation**: Prove operations were performed correctly\n5. **Proof of Re-randomization**: Prove ciphertext was correctly re-randomized\n\n## Running Examples\n\n```bash\n# Basic encryption demo\ncargo run --example basic_encryption\n\n# Operator overrides demonstration\ncargo run --example operator_overrides\n\n# Verifiable operators with proofs\ncargo run --example verifiable_operators\n\n# Privacy-preserving voting system\ncargo run --example voting_system\n\n# Verifiable computation with proofs\ncargo run --example verifiable_computation\n\n# Private statistics computation\ncargo run --example private_statistics\n```\n\n## Testing\n\n```bash\n# Run all tests\ncargo test\n\n# Run with verbose output\ncargo test -- --nocapture\n\n# Run benchmarks\ncargo bench\n```\n\n## Security Considerations\n\n- **Discrete Log Assumption**: Security based on hardness of discrete logarithm\n- **Random Oracle Model**: Proofs rely on hash function as random oracle\n- **Safe Primes**: Uses safe primes (p = 2q + 1) for strong security\n- **No Trusted Setup**: Unlike zk-SNARKs, no ceremony or trusted parameters needed\n\n## Performance\n\n- **Key Generation**: ~100-500ms for 1024-bit keys\n- **Encryption**: ~5-10ms per value\n- **Homomorphic Operations**: ~1-2ms per operation\n- **Proof Generation**: ~10-20ms per proof\n- **Proof Verification**: ~5-10ms per verification\n\n## Use Cases\n\n- **E-Voting**: Privacy-preserving electronic voting\n- **Private Analytics**: Compute statistics without accessing raw data\n- **Secure Auctions**: Sealed-bid auctions with verifiable fairness\n- **GDPR Compliance**: Process encrypted personal data\n- **Multi-party Computation**: Collaborative computation without sharing inputs\n- **Blockchain**: Private smart contracts and confidential transactions\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is dual-licensed under MIT OR Apache-2.0.\n\n## References\n\n- [ElGamal Encryption](https://en.wikipedia.org/wiki/ElGamal_encryption)\n- [Exponential ElGamal](https://crypto.stanford.edu/pbc/notes/crypto/additive.html)\n- [Schnorr Identification Protocol](https://en.wikipedia.org/wiki/Schnorr_signature)\n- [Chaum-Pedersen Protocol](https://link.springer.com/chapter/10.1007/3-540-48285-7_24)\n- [Fiat-Shamir Heuristic](https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic)\n\n## Contact\n\nFor questions or suggestions, please open an issue on GitHub.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F10d9e%2Fvhe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F10d9e%2Fvhe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F10d9e%2Fvhe/lists"}