jks
Java KeyStore (JKS) encoder/decoder for Rust. Supports WebAssembly (WASM).
About
jks is a pure Rust library for reading and writing Java KeyStore (JKS) files. It provides compatibility with Java's keytool and can be used to:
- Read existing JKS files (keystores, truststores)
- Create new JKS files with private keys and certificates
- Extract private keys and certificates from JKS files
- Convert JKS to PEM format and vice versa
Note: JKS assumes that private keys are PKCS#8 encoded.
Features
- ✅ Read JKS files - Load existing Java keystores
- ✅ Write JKS files - Create new keystores compatible with Java
- ✅ Password-based encryption - Private keys encrypted using password (XOR + SHA-1)
- ✅ Private Key entries - Support for private keys with certificate chains
- ✅ Trusted Certificate entries - Support for trusted certificates
- ✅ Case-insensitive aliases - Alias matching is case-insensitive by default
- ✅ Ordered aliases - Optional alphabetical sorting of aliases
- ✅ Custom password validation - Configurable minimum password length
- ✅ No external dependencies - Pure Rust implementation
Installation
Add to your Cargo.toml:
[]
= "0.2.2"
Quick Start
Reading a Keystore
use KeyStore;
use File;
Creating a New Keystore
use ;
use File;
use SystemTime;
API Reference
KeyStore
Main struct for working with Java keystores.
Creating a Keystore
use KeyStore;
// Default options
let ks = new;
// With custom options
let ks = with_options;
Loading & Saving
use KeyStore;
use File;
let mut ks = new;
// Load from file
let mut file = open?;
ks.load?;
// Save to file
let mut file = create?;
ks.store?;
Private Key Entries
use ;
let mut ks = new;
// Add a private key entry
let entry = PrivateKeyEntry ;
// Private key will be encrypted before storing
ks.set_private_key_entry?;
// Retrieve and decrypt
let entry = ks.get_private_key_entry?;
// Get certificate chain only
let chain = ks.get_private_key_entry_certificate_chain?;
// Check if entry exists
if ks.is_private_key_entry
Trusted Certificate Entries
use ;
let mut ks = new;
// Add a trusted certificate
let entry = TrustedCertificateEntry ;
ks.set_trusted_certificate_entry?;
// Retrieve
let entry = ks.get_trusted_certificate_entry?;
// Check if entry exists
if ks.is_trusted_certificate_entry
Working with Aliases
use KeyStore;
let ks = new;
// Get all aliases
let aliases = ks.aliases;
// Check number of entries
let count = ks.len;
let empty = ks.is_empty;
// Delete an entry
ks.delete_entry;
// Case sensitivity
let ks = with_options;
Types
PrivateKeyEntry
Represents a private key with its certificate chain.
TrustedCertificateEntry
Represents a trusted certificate without a private key.
Certificate
Represents a single certificate.
KeyStoreOptions
Configuration options for keystore behavior.
Error Handling
All operations return Result<T, KeyStoreError>:
Examples
The library includes several examples demonstrating common usage:
1. PEM to JKS
Convert PEM files to a JKS keystore:
2. Read Keystore
Read and display entries from a keystore:
3. Read Truststore
Read Java's cacerts truststore:
4. JKS to PEM
Convert a JKS keystore to separate PEM files:
# Convert to separate PEM files
# Output files:
# output_private_key.pem - Private key (PKCS#8)
# output_certificate.pem - End-entity certificate
# output_chain.pem - Full certificate chain
5. JKS to PEM Bundle
Convert a JKS keystore to a single combined PEM bundle:
# Convert to single bundle file
# Bundle contains:
# -----BEGIN PRIVATE KEY-----
# -----END PRIVATE KEY-----
# -----BEGIN CERTIFICATE-----
# -----END CERTIFICATE-----
6. Compare Keystores
Test deterministic keystore output:
Password Security
Important: Always zero out passwords after use:
let mut password = b"mysecret".to_vec;
// Use password...
ks.store?;
// Zero out sensitive data
zeroing;
JKS Format Details
This library implements the JKS (Java KeyStore) format:
| Component | Value |
|---|---|
| Magic Number | 0xfeedfeed |
| Version | 2 (latest) |
| Digest Algorithm | SHA-1 |
| Key Encryption | Password-based XOR + SHA-1 |
| Salt Length | 20 bytes |
| Byte Order | Big-endian |
Private Key Encryption
Private keys are encrypted using:
- Generate 20-byte random salt
- Derive encryption key using SHA-1(password + salt) iterated
- XOR private key with derived key
- Append SHA-1 digest for verification
Entry Tags
| Tag | Type | Description |
|---|---|---|
| 1 | Private Key | Private key with certificate chain |
| 2 | Trusted Certificate | Trusted certificate without private key |
Testing
Run the test suite:
# Run all tests
# Run library tests
# Run specific example
WebAssembly (WASM) Support
This library can be compiled to WebAssembly for use in browser environments or Node.js-WASM. Runtime tested and verified working.
Building for WASM
# Build the library for WASM (without rand feature)
# Output: target/wasm32-unknown-unknown/debug/jks.wasm
Using in Your Project
Add to your Cargo.toml:
[]
= { = "0.2", = false }
Providing a Custom RNG for WASM
Since the default RNG isn't available in WASM, you need to provide your own using KeyStoreOptions:
use ;
use ;
;
WASM Runtime Testing
The library has been verified working in WebAssembly runtime environment:
# Run the WASM runtime tests
# Test with Node.js
Test Results (verified):
- ✅
test_create_trusted_cert()- PASSED - ✅
test_alias_count()- PASSED - ✅
test_all()- PASSED
WASM binary size: ~56 KB (release build)
Compatibility
- ✅ Java KeyStore (JKS) format
- ✅ Java
keytoolgenerated keystores - ✅ Java cacerts truststore
- ✅ OpenSSL generated certificates
- ✅ PKCS#8 private keys
Requirements
- Rust 1.70 or later
- No external C dependencies
License
MIT License - see LICENSE for details.
Acknowledgments
This library is a Rust port of the excellent Go implementation:
keystore-go by Pavlo Chernykh
Author
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.