jks
Java KeyStore (JKS) and PKCS12 encoder/decoder for Rust. Supports WebAssembly (WASM).
About
jks is a Rust library for reading and writing Java KeyStore (JKS) and PKCS12 files. It provides compatibility with Java's keytool and Android keystores, and can be used to:
- Read JKS files (keystores, truststores)
- Read PKCS12 files (Android
.keystore,.p12,.pfx) - Create new JKS files with private keys and certificates
- Extract private keys and certificates from keystores
- Convert keystores to PEM format and vice versa
Note: Private keys are assumed to be PKCS#8 encoded.
Features
- ✅ Read JKS files - Load existing Java keystores
- ✅ Read PKCS12 files - Load Android keystores,
.p12,.pfxfiles (withopensslfeature) - ✅ Auto-detect format - Automatically detects JKS vs PKCS12 format
- ✅ 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
Installation
Add to your Cargo.toml:
[]
= "0.3.1"
Features
- default - Includes
randandopenssl(PKCS12 support) - rand - Enable random number generation for JKS encryption
- openssl - Enable PKCS12 support (for Android keystores)
- wasm - Build for WebAssembly (without
randoropenssl)
To disable PKCS12 support (reduce dependencies):
[]
= { = "0.3", = false, = ["rand"] }
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 (JKS format)
let mut file = open?;
ks.load?;
// Auto-detect format (JKS or PKCS12)
let mut file = open?;
ks.load_auto_detect?;
// Load PKCS12 file (Android .keystore, .p12, .pfx)
let mut file = open?;
ks.load_pkcs12?;
// Save to file
let mut file = create?;
ks.store?;
PKCS12 Support (Android Keystores)
use KeyStore;
use File;
let mut ks = new;
// Load Android keystore (PKCS12 format)
let mut file = open?;
ks.load_pkcs12?;
// Or use auto-detect (works for both JKS and PKCS12)
let mut file = open?;
ks.load_auto_detect?;
// Get private key entry (already decrypted for PKCS12)
let alias = "key_0"; // PKCS12 entries use generic aliases
if ks.is_private_key_entry
Note: PKCS12 files (like Android keystores) are supported via the openssl feature. The private keys from PKCS12 are already decrypted, so use get_raw_private_key_entry() instead of get_private_key_entry().
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.