Skip to content

About

A multi-chain keystore library for Rust supporting Ethereum and Solana with the Web3 Secret Storage format.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

28 Commits

Folders and files

Repository files navigation

crypto-keystore-rs

Warning

This repo has not been audited -- use at your own risk!

A multi-chain keystore library for Rust supporting Ethereum and Solana with the Web3 Secret Storage format.

This library extends the core web3 keystore spec ref but supports address schemes other than Ethereum.

Features

  • Multi-chain support: Ethereum (secp256k1) and Solana (Ed25519) keys
  • Web3 compatibility: Authenticated v5 format, with legacy v3 (Ethereum) and v4 (chain-neutral) support
  • Secure: Uses audited cryptographic libraries from RustCrypto
  • Memory cleanup: Temporary secret buffers are zeroized on drop
  • Opt-in functionality: Only compile what you need (ethereum, solana, or both)

Installation

This README includes unreleased v5 changes on main; published 0.2 releases use the legacy default format.

Add this to your Cargo.toml:

[dependencies]
crypto-keystore-rs = "0.2"

Feature Flags

By default, both Ethereum and Solana support are enabled. You can opt into specific chains:

[dependencies]
# Only Ethereum
crypto-keystore-rs = { version = "0.2", default-features = false, features = ["ethereum"] }

# Only Solana
crypto-keystore-rs = { version = "0.2", default-features = false, features = ["solana"] }

# Both (default)
crypto-keystore-rs = "0.2"

Usage

Import limits

Keystore imports default to a 64 KiB JSON/file limit and bounded KDF work. To configure input size separately from KDF budgets:

use crypto_keystore_rs::{EthereumKeystore, ImportLimits, KdfLimits};

let limits = ImportLimits {
    max_input_bytes: 4096,
    kdf: KdfLimits {
        max_pbkdf2_iterations: 600_000,
        ..KdfLimits::default()
    },
};
let loaded = EthereumKeystore::load_from_file_with_import_limits(
    "keystore.json", "password", limits,
)?;

from_json_with_import_limits applies the same policy to JSON strings. Existing *_with_limits methods still accept KdfLimits and use the default input cap. Oversized input returns KeystoreError::InputTooLarge before JSON parsing.

Ethereum Example

use crypto_keystore_rs::EthereumKeystore;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let password = "secure_password_123";

    // Create a new Ethereum keystore with a random key
    let keystore = EthereumKeystore::new(password)?;
    let address = keystore.key()?.address();
    println!("Ethereum address: {}", address);

    // Save to file
    let uuid = keystore.save_to_file("./keystores")?;
    println!("Saved keystore with ID: {}", uuid);

    // Load from file
    let loaded = EthereumKeystore::load_from_file(
        format!("./keystores/{}.json", uuid),
        password
    )?;

    assert_eq!(loaded.key()?.address(), address);

    Ok(())
}

Solana Example

use crypto_keystore_rs::SolanaKeystore;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let password = "secure_password_123";

    // Create a new Solana keystore with a random key
    let keystore = SolanaKeystore::new(password)?;
    let address = keystore.key()?.address();
    println!("Solana address: {}", address);

    // Save to file
    let uuid = keystore.save_to_file("./keystores")?;
    println!("Saved keystore with ID: {}", uuid);

    // Load from file
    let loaded = SolanaKeystore::load_from_file(
        format!("./keystores/{}.json", uuid),
        password
    )?;

    assert_eq!(loaded.key()?.address(), address);

    Ok(())
}

Architecture

ChainKey Trait

The library uses a trait-based design in order to encapsulate different key encodings on a per chain/VM basis.

pub trait ChainKey: Sized + Clone {
    const SECRET_KEY_SIZE: usize;
    const KEYSTORE_SIZE: usize;
    const CHAIN_ID: &'static str;

    fn to_keystore_bytes(&self) -> zeroize::Zeroizing<Vec<u8>>;
    fn from_keystore_bytes(bytes: &[u8]) -> Result<Self>;
    fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self;
    fn address(&self) -> String;
}

Keystore Format

New keystores use version 5, with AES-256-GCM authenticating the nonce, ciphertext, UUID, chain, and cryptographic parameters. See format and migration details. Legacy v3/v4 files remain readable; their MACs do not authenticate the IV.

The library uses a JSON-based keystore format inspired by the Web3 Secret Storage Definition, but extended to support chains other than Ethereum.

Legacy version 4 (chain-neutral):

{
  "crypto": {
    "cipher": "aes-128-ctr",
    "cipherparams": { "iv": "..." },
    "ciphertext": "...",
    "kdf": "scrypt",
    "dklen": 32,
    "n": 262144,
    "p": 1,
    "r": 8,
    "salt": "...",
    "mac": "..."
  },
  "id": "uuid-v4",
  "version": 4,
  "chain": "ethereum"
}

Version 3 (Ethereum backward compatible):

The library can also read standard Ethereum Web3 Secret Storage v3 keystores.

Development

Building

make build          # Build the library
make release        # Build optimized release
make test           # Run tests
make check          # Run fmt, clippy, tests
make fix            # Auto-fix formatting and clippy warnings

Running Tests

cargo test                                     # All tests
cargo test --no-default-features --features ethereum  # Ethereum only
cargo test --no-default-features --features solana    # Solana only
make coverage                                  # Source coverage; requires cargo-llvm-cov
make branch-coverage                           # 95% source-branch gate; nightly-2026-06-08 + llvm-tools-preview
make mutations                                 # Requires cargo-mutants and Python 3
make fuzz                                      # Requires cargo-fuzz and nightly Rust
make interop                                   # Requires Node.js 22 (OpenSSL)

About

A multi-chain keystore library for Rust supporting Ethereum and Solana with the Web3 Secret Storage format.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages