{"id":32398995,"url":"https://github.com/denisbytes/zig-jks","last_synced_at":"2026-06-19T16:01:18.316Z","repository":{"id":320342038,"uuid":"1081286363","full_name":"DenisBytes/zig-jks","owner":"DenisBytes","description":"  Pure Zig implementation of Java KeyStore (JKS) encoder/decoder. Read/write JKS files with zero dependencies. Compatible with Java's keytool.","archived":false,"fork":false,"pushed_at":"2025-10-23T09:12:58.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-23T09:27:54.593Z","etag":null,"topics":["certificate","cryptography","java-keystore","jks","keystore","security","zig"],"latest_commit_sha":null,"homepage":"","language":"Zig","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/DenisBytes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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-10-22T15:09:26.000Z","updated_at":"2025-10-23T09:13:01.000Z","dependencies_parsed_at":"2025-10-23T09:27:56.543Z","dependency_job_id":"bffafb25-b33c-4069-9260-82e99cc36d3f","html_url":"https://github.com/DenisBytes/zig-jks","commit_stats":null,"previous_names":["denisbytes/zig-jks"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/DenisBytes/zig-jks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenisBytes%2Fzig-jks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenisBytes%2Fzig-jks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenisBytes%2Fzig-jks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenisBytes%2Fzig-jks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DenisBytes","download_url":"https://codeload.github.com/DenisBytes/zig-jks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DenisBytes%2Fzig-jks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34538480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["certificate","cryptography","java-keystore","jks","keystore","security","zig"],"created_at":"2025-10-25T08:15:53.141Z","updated_at":"2026-06-19T16:01:18.310Z","avatar_url":"https://github.com/DenisBytes.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zig-jks\n\nJava KeyStore (JKS) encoder/decoder in pure Zig.\n\n## Overview\n\nRead and write JKS files (the keystore format used by Java). Fully compatible with Java's keytool and the JKS spec.\n\n## Features\n\n- Read/write JKS v1 and v2 files\n- Private key entries and trusted certificates\n- Sun's proprietary key encryption algorithm\n- Configurable alias handling (case-sensitive, ordered)\n- Password policies (minimum length, etc)\n- Zero dependencies - just Zig stdlib\n- Comprehensive test suite\n\n## Requirements\n\n- Zig 0.15.1 or later\n\n## Installation\n\nAdd this to your `build.zig.zon`:\n\n```zig\n.dependencies = .{\n    .jks = .{\n        .url = \"https://github.com/yourusername/zig-jks/archive/main.tar.gz\",\n        .hash = \"...\",\n    },\n},\n```\n\nAnd in your `build.zig`:\n\n```zig\nconst jks = b.dependency(\"jks\", .{\n    .target = target,\n    .optimize = optimize,\n});\nexe.root_module.addImport(\"jks\", jks.module(\"jks\"));\n```\n\n## Quick Start\n\n### Creating a KeyStore\n\n```zig\nconst std = @import(\"std\");\nconst jks = @import(\"jks\");\n\npub fn main() !void {\n    var gpa = std.heap.GeneralPurposeAllocator(.{}){};\n    defer _ = gpa.deinit();\n    const allocator = gpa.allocator();\n\n    // Create a new keystore\n    var keystore = jks.Jks.init(allocator);\n    defer keystore.deinit();\n\n    // Add a trusted certificate\n    const cert = jks.Certificate{\n        .type = \"X.509\",\n        .content = certificate_der_bytes,\n    };\n\n    const entry = jks.TrustedCertificateEntry{\n        .creation_time = std.time.milliTimestamp(),\n        .certificate = cert,\n    };\n\n    try keystore.setTrustedCertificateEntry(\"my-cert\", entry);\n\n    // Save to file\n    const file = try std.fs.cwd().createFile(\"keystore.jks\", .{});\n    defer file.close();\n\n    try keystore.store(file.writer().any(), \"storepassword\");\n}\n```\n\n### Loading a KeyStore\n\n```zig\nconst file = try std.fs.cwd().openFile(\"keystore.jks\", .{});\ndefer file.close();\n\nvar keystore = jks.Jks.init(allocator);\ndefer keystore.deinit();\n\ntry keystore.load(file.reader().any(), \"storepassword\");\n\n// Retrieve a certificate\nconst cert_entry = try keystore.getTrustedCertificateEntry(\"my-cert\");\ndefer cert_entry.deinit(allocator);\n\nstd.debug.print(\"Certificate type: {s}\\n\", .{cert_entry.certificate.type});\n```\n\n### Working with Private Keys\n\n```zig\n// Add a private key entry\nconst chain = [_]jks.Certificate{cert};\nconst pk_entry = jks.PrivateKeyEntry{\n    .creation_time = std.time.milliTimestamp(),\n    .private_key = pkcs8_key_bytes,\n    .certificate_chain = \u0026chain,\n};\n\ntry keystore.setPrivateKeyEntry(\"my-key\", pk_entry, \"keypassword\");\n\n// Retrieve and decrypt the private key\nconst retrieved = try keystore.getPrivateKeyEntry(\"my-key\", \"keypassword\");\ndefer retrieved.deinit(allocator);\n\n// Use the decrypted private key\nstd.debug.print(\"Private key size: {d} bytes\\n\", .{retrieved.private_key.len});\n```\n\n## Configuration Options\n\n```zig\nvar keystore = jks.Jks.initWithOptions(allocator, .{\n    .ordered = true,           // Sort aliases alphabetically\n    .case_exact = false,       // Case-insensitive aliases (default)\n    .min_password_len = 8,     // Minimum password length\n});\ndefer keystore.deinit();\n```\n\n## API Reference\n\n### Jks\n\n- `init(allocator)` - Create a new keystore with default options\n- `initWithOptions(allocator, options)` - Create with custom options\n- `deinit()` - Free all resources\n- `setPrivateKeyEntry(alias, entry, password)` - Add a private key entry\n- `getPrivateKeyEntry(alias, password)` - Retrieve and decrypt a private key entry\n- `setTrustedCertificateEntry(alias, entry)` - Add a trusted certificate\n- `getTrustedCertificateEntry(alias)` - Retrieve a trusted certificate\n- `isPrivateKeyEntry(alias)` - Check if entry is a private key\n- `isTrustedCertificateEntry(alias)` - Check if entry is a trusted certificate\n- `deleteEntry(alias)` - Remove an entry\n- `aliases()` - Get list of all aliases\n- `store(writer, password)` - Write keystore to a writer\n- `load(reader, password)` - Read keystore from a reader\n\n### Entry Types\n\n- `Certificate` - X.509 or other certificate type\n- `PrivateKeyEntry` - Private key with certificate chain\n- `TrustedCertificateEntry` - Standalone trusted certificate\n\n## Notes\n\n- Private keys must be PKCS#8 encoded\n- Passwords are zeroed after use\n- Uses SHA-1 (JKS requirement, yeah it's legacy)\n- Caller owns all returned data - remember to `deinit()`\n\n## Examples\n\nThe `examples/` directory contains practical demonstrations:\n\n- **01_create_keystore.zig** - Creating a keystore from scratch\n- **02_inspect_keystore.zig** - Inspecting keystore contents\n- **03_manage_entries.zig** - Managing entries (add/update/delete)\n- **04_load_modify_save.zig** - Complete workflow example\n- **05_working_with_passwords.zig** - Password handling and security\n\nRun examples with:\n```bash\nzig build create     # Create a keystore\nzig build inspect    # Inspect keystore contents\nzig build manage     # Manage entries\nzig build workflow   # Load/modify/save workflow\nzig build passwords  # Password handling\n```\n\n## Test Data\n\nThe `testdata/` directory contains various JKS files for testing:\n\n```bash\n# Generate all test files\nzig build generate-testdata\n```\n\nThis creates keystores with:\n- Empty keystore\n- Single/multiple certificates\n- Private keys with different passwords\n- Mixed content\n- Special alias formats\n- Large keystores (50+ entries)\n- Various password configurations\n\n## Testing\n\nRun the test suite:\n\n```bash\nzig build test\n```\n\n## Compatibility\n\nWorks with keystores from:\n- `keytool` (Java's CLI tool)\n- `java.security.KeyStore` API\n- Any JKS-compatible tool\n\n## License\n\nThis project is released under the MIT License. See LICENSE file for details.\n\n## References\n\n- [Java KeyStore Specification](https://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/CryptoSpec.html#KeyManagement)\n\n## Contributing\n\nContributions are welcome! Please feel free to submit issues or pull requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisbytes%2Fzig-jks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdenisbytes%2Fzig-jks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdenisbytes%2Fzig-jks/lists"}