herolib-vault

Crates.ioherolib-vault
lib.rsherolib-vault
version0.3.13
created_at2025-12-27 20:03:29.434139+00
updated_at2026-01-24 05:33:51.435626+00
descriptionSecure vault for managing cryptographic keys with Redis backend - supports Ed25519, Sr25519, and symmetric encryption
homepage
repositoryhttps://github.com/herolib/herolib_rust
max_upload_size
id2007731
size250,754
kristof de spiegeleer (despiegk)

documentation

README

herolib-vault

Secure vault for managing cryptographic keys with Redis backend.

Overview

The vault provides a secure way to store and manage cryptographic keys for multiple blockchain ecosystems:

  • Ed25519: Used by Near Protocol and many other chains
  • Sr25519: Used by Polkadot, Kusama, and Substrate-based chains (including ThreeFold)

Features

  • Redis Backend: Keys are stored encrypted in Redis for distributed access
  • Multiple Vaults: Open multiple vaults with different names on the same Redis
  • XChaCha20-Poly1305: Authenticated encryption for key storage
  • Argon2id: Memory-hard key derivation from secrets (GPU-resistant)
  • Crypt Integration: Full access to herolib-crypt primitives

Quick Start

Rust

use herolib_vault::Vault;

// Open a vault (uses default Redis connection from environment)
let vault = Vault::open("my_vault", "my-secret-password")?;

// Generate keys
let ed25519_pubkey = vault.generate_ed25519("near_key")?;
let sr25519_pubkey = vault.generate_sr25519("polkadot_key")?;

// Sign messages
let signature = vault.sign("near_key", b"Hello, Near!")?;
let signature_hex = vault.sign_hex("near_key", b"Hello, Near!")?;

// Verify signatures
let valid = vault.verify("near_key", b"Hello, Near!", &signature)?;

// Get addresses
let near_address = vault.near_address("near_key")?;
let polkadot_address = vault.polkadot_address("polkadot_key")?;

// Use symmetric encryption (using the vault's secret)
let encrypted = vault.encrypt_string("secret data")?;
let decrypted = vault.decrypt_string(&encrypted)?;

Rhai

// Open a vault
let vault = vault_open("my_vault", "my-secret");

// Generate keys
let ed25519_pubkey = vault.generate_ed25519("near_key");
let sr25519_pubkey = vault.generate_sr25519("polkadot_key");

// Import existing keys
vault.import_ed25519("imported_near", "hex_private_key_here");
vault.import_sr25519("imported_dot", "hex_private_key_here");

// Sign a message
let signature = vault.sign("near_key", "Hello, Near!");
let signature_hex = vault.sign_hex("near_key", "Hello, Near!");

// Verify a signature
let valid = vault.verify("near_key", "Hello, Near!", signature);

// Get public key
let pubkey = vault.public_key("near_key");
let key_type = vault.key_type("near_key");  // "Ed25519" or "Sr25519"

// Get addresses
let near_addr = vault.near_address("near_key");
let polkadot_addr = vault.polkadot_address("polkadot_key");
let kusama_addr = vault.kusama_address("polkadot_key");
let substrate_addr = vault.substrate_address("polkadot_key");
let custom_addr = vault.ss58_address("polkadot_key", 42);  // Custom network ID

// Symmetric encryption
let encrypted = vault.encrypt_string("secret data");
let decrypted = vault.decrypt_string(encrypted);

// Key management
let keys = vault.list();
print(`Keys in vault: ${keys}`);

if vault.exists("near_key") {
    print("Key exists!");
}

vault.delete("old_key");

// Get vault name
let name = vault.name();

// Standalone encryption functions
let keypair = generate_encryption_keypair();
let encrypted = encrypt_for_recipient("secret", keypair.public_key);
let decrypted = decrypt_with_private_key(encrypted, keypair.private_key);

// Password-based encryption (standalone)
let encrypted = encrypt_with_password("data", "password");
let decrypted = decrypt_with_password(encrypted, "password");

Redis Configuration

The vault uses environment variables for Redis connection:

Variable Description Default
REDIS_HOST Redis host 127.0.0.1
REDIS_PORT Redis port 6379
REDIS_PASSWORD Redis password (none)
REDIS_USERNAME Redis username (6.0+) (none)
REDISDB Redis database number 0

Or use a Unix socket at ~/hero/var/myredis.sock if it exists.

Custom Redis Configuration

use herolib_vault::{Vault, RedisConfigBuilder};

let config = RedisConfigBuilder::new()
    .host("redis.example.com")
    .port(6380)
    .password("secret")
    .db(1);

let vault = Vault::open_with_config(config, "my_vault", "my-secret")?;

Using an Existing Redis Client

use herolib_vault::Vault;
use herolib_clients::redis::get_redis_client;
use std::sync::Arc;

let redis = get_redis_client()?;
let vault = Vault::open_with_client(redis, "my_vault", "my-secret")?;

API Reference

Vault Methods

Opening a Vault

Method Description
Vault::open(name, secret) Open vault with default Redis connection
Vault::open_with_config(config, name, secret) Open vault with custom Redis config
Vault::open_with_client(redis, name, secret) Open vault with existing Redis client

Key Generation

Method Description
generate_ed25519(key_name) Generate new Ed25519 keypair, returns public key hex
generate_sr25519(key_name) Generate new Sr25519 keypair, returns public key hex

Key Import

Method Description
import_ed25519(key_name, private_key_bytes) Import Ed25519 from bytes
import_ed25519_hex(key_name, private_key_hex) Import Ed25519 from hex string
import_sr25519(key_name, private_key_bytes) Import Sr25519 from bytes
import_sr25519_hex(key_name, private_key_hex) Import Sr25519 from hex string

Key Operations

Method Description
public_key(key_name) Get public key as hex string
public_key_bytes(key_name) Get public key as bytes
key_type(key_name) Get key type (Ed25519 or Sr25519)
sign(key_name, message) Sign message, returns signature bytes
sign_hex(key_name, message) Sign message, returns signature hex
verify(key_name, message, signature) Verify signature

Address Generation

Method Description
near_address(key_name) Get Near format address (ed25519:...)
ss58_address(key_name, network_id) Get SS58 address with custom prefix
polkadot_address(key_name) Get Polkadot address (SS58 prefix 0)
kusama_address(key_name) Get Kusama address (SS58 prefix 2)
substrate_address(key_name) Get generic Substrate address (SS58 prefix 42)

Key Management

Method Description
exists(key_name) Check if key exists
delete(key_name) Delete a key
list() List all key names
name() Get vault name

Symmetric Encryption

Method Description
encrypt(plaintext_bytes) Encrypt bytes
decrypt(ciphertext_bytes) Decrypt bytes
encrypt_string(plaintext) Encrypt string, returns base64
decrypt_string(ciphertext_base64) Decrypt base64 string

Standalone Functions

Function Description
generate_encryption_keypair() Generate X25519 keypair for asymmetric encryption
encrypt_for_recipient(message, public_key_hex) Encrypt message for recipient
decrypt_with_private_key(encrypted, private_key_hex) Decrypt with private key
encrypt_with_password(data, password) Password-based encryption
decrypt_with_password(encrypted, password) Password-based decryption

Key Types

Ed25519 (Near Protocol)

Ed25519 keys provide:

  • Fast signing and verification
  • Deterministic signatures
  • 32-byte public keys
  • Near-format addresses: ed25519:<base58_public_key>
let vault = Vault::open("my_vault", "secret")?;

// Generate key
vault.generate_ed25519("my_near_key")?;

// Or import existing key
vault.import_ed25519_hex("imported_key", "your_private_key_hex")?;

// Get Near address
let address = vault.near_address("my_near_key")?;
// Returns: "ed25519:Abc123..."

// Sign and verify
let sig = vault.sign("my_near_key", b"message")?;
let valid = vault.verify("my_near_key", b"message", &sig)?;

Sr25519 (Polkadot/Substrate)

Sr25519 keys provide:

  • VRF (Verifiable Random Function) support
  • Better security properties for some use cases
  • SS58 address encoding for different networks
let vault = Vault::open("my_vault", "secret")?;

// Generate key
vault.generate_sr25519("my_dot_key")?;

// Get addresses for different networks
let polkadot = vault.polkadot_address("my_dot_key")?;  // SS58 prefix 0
let kusama = vault.kusama_address("my_dot_key")?;      // SS58 prefix 2
let substrate = vault.substrate_address("my_dot_key")?; // SS58 prefix 42

// Custom network (e.g., ThreeFold)
let threefold = vault.ss58_address("my_dot_key", 42)?;

Encryption

Symmetric Encryption (Vault Secret)

The vault can encrypt/decrypt data using its own secret:

let vault = Vault::open("my_vault", "secret")?;

// Encrypt bytes
let encrypted = vault.encrypt(b"binary data")?;
let decrypted = vault.decrypt(&encrypted)?;

// Encrypt strings (returns base64)
let encrypted = vault.encrypt_string("sensitive data")?;
let decrypted = vault.decrypt_string(&encrypted)?;

Password-Based Encryption

Encrypt data with a standalone password:

use herolib_vault::{encrypt_with_password, decrypt_with_password};

let encrypted = encrypt_with_password(b"data", "password")?;
let decrypted = decrypt_with_password(&encrypted, "password")?;

Asymmetric Encryption (X25519)

For public-key encryption:

use herolib_vault::{generate_encryption_keypair, encrypt_for_recipient, decrypt_with_private_key};

// Generate keypair
let (private_key, public_key) = generate_encryption_keypair()?;

// Encrypt for recipient
let encrypted = encrypt_for_recipient("secret message", &public_key)?;

// Decrypt with private key
let decrypted = decrypt_with_private_key(&encrypted, &private_key)?;

Security

  • All private keys are encrypted before storage using XChaCha20-Poly1305
  • Encryption keys are derived from secrets using Argon2id (GPU-resistant)
  • Each vault has its own unique salt stored in Redis
  • Private keys are zeroized from memory when dropped
  • Keys stored in Redis are prefixed with vault:<name>:keys: for isolation

Building

cd packages/vault
cargo build
cargo test
cargo doc --open

Dependencies

  • herolib-crypt: Cryptographic primitives (XChaCha20-Poly1305, Argon2id, X25519)
  • herolib-clients: Redis client
  • ed25519-dalek: Ed25519 signatures
  • schnorrkel: Sr25519 (Schnorrkel) signatures
  • rhai: Scripting support
Commit count: 0

cargo fmt