DenisBytes/zig-jks
Pure Zig implementation of Java KeyStore (JKS) encoder/decoder. Read/write JKS files with zero dependencies. Compatible with Java's keytool.
Java KeyStore (JKS) encoder/decoder in pure Zig.
Read and write JKS files (the keystore format used by Java). Fully compatible with Java's keytool and the JKS spec.
Add this to your build.zig.zon:
.dependencies = .{
.jks = .{
.url = "https://github.com/yourusername/zig-jks/archive/main.tar.gz",
.hash = "...",
},
},
And in your build.zig:
const jks = b.dependency("jks", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("jks", jks.module("jks"));
const std = @import("std");
const jks = @import("jks");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Create a new keystore
var keystore = jks.Jks.init(allocator);
defer keystore.deinit();
// Add a trusted certificate
const cert = jks.Certificate{
.type = "X.509",
.content = certificate_der_bytes,
};
const entry = jks.TrustedCertificateEntry{
.creation_time = std.time.milliTimestamp(),
.certificate = cert,
};
try keystore.setTrustedCertificateEntry("my-cert", entry);
// Save to file
const file = try std.fs.cwd().createFile("keystore.jks", .{});
defer file.close();
try keystore.store(file.writer().any(), "storepassword");
}
const file = try std.fs.cwd().openFile("keystore.jks", .{});
defer file.close();
var keystore = jks.Jks.init(allocator);
defer keystore.deinit();
try keystore.load(file.reader().any(), "storepassword");
// Retrieve a certificate
const cert_entry = try keystore.getTrustedCertificateEntry("my-cert");
defer cert_entry.deinit(allocator);
std.debug.print("Certificate type: {s}\n", .{cert_entry.certificate.type});
// Add a private key entry
const chain = [_]jks.Certificate{cert};
const pk_entry = jks.PrivateKeyEntry{
.creation_time = std.time.milliTimestamp(),
.private_key = pkcs8_key_bytes,
.certificate_chain = &chain,
};
try keystore.setPrivateKeyEntry("my-key", pk_entry, "keypassword");
// Retrieve and decrypt the private key
const retrieved = try keystore.getPrivateKeyEntry("my-key", "keypassword");
defer retrieved.deinit(allocator);
// Use the decrypted private key
std.debug.print("Private key size: {d} bytes\n", .{retrieved.private_key.len});
var keystore = jks.Jks.initWithOptions(allocator, .{
.ordered = true, // Sort aliases alphabetically
.case_exact = false, // Case-insensitive aliases (default)
.min_password_len = 8, // Minimum password length
});
defer keystore.deinit();
init(allocator) - Create a new keystore with default optionsinitWithOptions(allocator, options) - Create with custom optionsdeinit() - Free all resourcessetPrivateKeyEntry(alias, entry, password) - Add a private key entrygetPrivateKeyEntry(alias, password) - Retrieve and decrypt a private key entrysetTrustedCertificateEntry(alias, entry) - Add a trusted certificategetTrustedCertificateEntry(alias) - Retrieve a trusted certificateisPrivateKeyEntry(alias) - Check if entry is a private keyisTrustedCertificateEntry(alias) - Check if entry is a trusted certificatedeleteEntry(alias) - Remove an entryaliases() - Get list of all aliasesstore(writer, password) - Write keystore to a writerload(reader, password) - Read keystore from a readerCertificate - X.509 or other certificate typePrivateKeyEntry - Private key with certificate chainTrustedCertificateEntry - Standalone trusted certificatedeinit()The examples/ directory contains practical demonstrations:
Run examples with:
zig build create # Create a keystore
zig build inspect # Inspect keystore contents
zig build manage # Manage entries
zig build workflow # Load/modify/save workflow
zig build passwords # Password handling
The testdata/ directory contains various JKS files for testing:
# Generate all test files
zig build generate-testdata
This creates keystores with:
Run the test suite:
zig build test
Works with keystores from:
keytool (Java's CLI tool)java.security.KeyStore APIThis project is released under the MIT License. See LICENSE file for details.
Contributions are welcome! Please feel free to submit issues or pull requests.