A command-line interface for the leanSig library - a prototype implementation of hash-based signatures for post-quantum cryptography.
This CLI tool provides a user-friendly interface to work with hash-based signatures, keeping the main leanSig repository focused on cryptography while providing practical tooling in a separate codebase.
- Rust >= 1.87
- Internet connection (to fetch the
leanSigdependency from GitHub)
cargo build --releaseGenerate validator key pairs for hash-based signatures:
Indexed format (default, index-based naming):
cargo run --release --bin hashsig -- generate \
--num-validators 5 \
--log-num-active-epochs 18 \
--output-dir ./generated_keys \
--export-format bothDistributed format (first-3 last-3 bytes naming):
cargo run --release --bin hashsig -- generate \
--num-validators 5 \
--log-num-active-epochs 18 \
--output-dir ./generated_keys \
--export-format both \
--distributedParameters:
--num-validators: Number of validator key pairs to generate--log-num-active-epochs: Log2 of the number of active epochs (e.g., 18 for 2^18 = 262,144 active epochs)--output-dir: Directory where keys will be saved--export-format: Key export format, one of:both(default): export SSZ binaries (.ssz) and legacy JSON (.json)ssz: export only SSZ binaries (.ssz)
--create-manifest: Create a manifest file (optional, defaults totrue)--distributed: Use distributed naming format based on first-3 and last-3 bytes of public key (e.g.,validator-987678-de4578-pk.ssz). When enabled, the manifest will not include theindexfield.
Output (default --export-format both):
Indexed format (default, without --distributed):
The tool creates a directory with key pairs exported as SSZ-encoded binary files plus legacy JSON:
generated_keys/
├── validator-keys-manifest.yaml # Manifest file (if --create-manifest is true)
├── validator_0_pk.ssz # Public key for validator 0 (SSZ bytes)
├── validator_0_sk.ssz # Secret key for validator 0 (SSZ bytes)
├── validator_0_pk.json # Public key for validator 0 (legacy JSON)
├── validator_0_sk.json # Secret key for validator 0 (legacy JSON)
├── validator_1_pk.ssz # Public key for validator 1 (SSZ bytes)
├── validator_1_sk.ssz # Secret key for validator 1 (SSZ bytes)
├── validator_1_pk.json # Public key for validator 1 (legacy JSON)
├── validator_1_sk.json # Secret key for validator 1 (legacy JSON)
└── ...
Distributed format (with --distributed):
When using --distributed, validators are named using the first-3 and last-3 bytes of the public key (hex-encoded):
generated_keys/
├── validator-keys-manifest.yaml # Manifest file (if --create-manifest is true)
├── validator-987678-de4578-pk.ssz # Public key (SSZ bytes)
├── validator-987678-de4578-sk.ssz # Secret key (SSZ bytes)
├── validator-987678-de4578-pk.json # Public key (legacy JSON)
├── validator-987678-de4578-sk.json # Secret key (legacy JSON)
├── validator-52d9eb-dd0a4f-pk.ssz # Public key (SSZ bytes)
├── validator-52d9eb-dd0a4f-sk.ssz # Secret key (SSZ bytes)
├── validator-52d9eb-dd0a4f-pk.json # Public key (legacy JSON)
├── validator-52d9eb-dd0a4f-sk.json # Secret key (legacy JSON)
└── ...
Manifest Format:
Indexed format manifest (default, without --distributed):
# Hash-Signature Validator Keys Manifest
# Generated by hash-sig-cli
key_scheme: SIGTopLevelTargetSumLifetime32Dim64Base8
hash_function: Poseidon2
encoding: TargetSum
lifetime: 4294967296
log_num_active_epochs: 18
num_active_epochs: 262144
num_validators: 2
validators:
- index: 0
pubkey_hex: 0x...
privkey_file: validator_0_sk.ssz
- index: 1
pubkey_hex: 0x...
privkey_file: validator_1_sk.sszDistributed format manifest (with --distributed):
# Hash-Signature Validator Keys Manifest
# Generated by hash-sig-cli
key_scheme: SIGTopLevelTargetSumLifetime32Dim64Base8
hash_function: Poseidon2
encoding: TargetSum
lifetime: 4294967296
log_num_active_epochs: 18
num_active_epochs: 262144
num_validators: 2
validators:
- pubkey_hex: 0x...
privkey_file: validator-987678-de4578-sk.ssz
- pubkey_hex: 0x...
privkey_file: validator-52d9eb-dd0a4f-sk.sszKey differences:
- Indexed format: Manifest includes an
indexfield for each validator - Distributed format: Manifest does not include the
indexfield (onlypubkey_hexandprivkey_file)
The .ssz files contain the canonical SSZ serialization (to_bytes()) of the underlying key types from leanSig, written directly as raw bytes (not JSON or hex).
The .json files are provided only for backwards compatibility and may be removed in a future version once all clients consume SSZ.
Currently uses the SIGTopLevelTargetSumLifetime32Dim64Base8 scheme:
- Hash Function: Poseidon2 (ZK-friendly)
- Encoding: Target Sum
- Lifetime: 2^32 epochs (4,294,967,296)
Apache Version 2.0 (same as leanSig)
This is a separate codebase from the main leanSig library to keep the cryptography-focused repository minimal and focused. Feel free to contribute CLI enhancements here.