How the Badger KV Store Persists Encrypted Key Shares in mpcium
mpcium transparently encrypts every TSS key share at rest using BadgerDB’s built-in encryption, deriving a 32-byte key from a user-supplied badger_password to ensure LocalPartySaveData never touches disk as plaintext.
The fystack/mpcium repository implements a secure multi-party computation (MPC) wallet daemon that must protect sensitive key material between sessions. According to the source code, the project leverages BadgerDB’s native encryption capabilities to persist LocalPartySaveData structs—generated by the tss-lib library—while maintaining a simple Put/Get interface for the rest of the application.
Configuring the Encrypted Badger Store
When the daemon starts, the user-provided password is converted into an encryption key and injected into the Badger configuration.
Deriving the Encryption Key from CLI Input
In cmd/mpcium/main.go, the initialization logic creates a BadgerConfig struct that holds the 32-byte encryption key derived from the badger_password flag:
// cmd/mpcium/main.go → NewBadgerKVStore
config := kvstore.BadgerConfig{
NodeID: nodeName,
DBPath: dbPath,
EncryptionKey: []byte(badgerPassword), // 32-byte key from user password
BackupEncryptionKey: []byte(backupPassword),
BackupDir: backupDir,
}
badgerKv, err := kvstore.NewBadgerKVStore(config)
This configuration object is passed to the constructor that builds the underlying Badger options.
Initializing Badger with AES Encryption
Inside pkg/kvstore/badger.go (lines 40‑44), the constructor applies the encryption key to Badger’s option builder using WithEncryptionKey:
// pkg/kvstore/badger.go
opts := badger.DefaultOptions(config.DBPath).
WithEncryptionKey(config.EncryptionKey)
Badger then transparently encrypts every value using AES before writing it to the LSM tree files, ensuring at-rest encryption without additional application logic.
Persisting Encrypted Key Shares
After a key-generation round completes, the session serializes the share and stores it via the generic KV interface.
Serializing LocalPartySaveData
In pkg/mpc/ecdsa_keygen_session.go, the session marshals the saveData struct to JSON and calls Put with a versioned key:
// pkg/mpc/ecdsa_keygen_session.go → after receiving end data
keyBytes, _ := json.Marshal(saveData) // serialize share
err = s.kvstore.Put(
s.composeKey(walletIDWithVersion(s.walletID, s.GetVersion())),
keyBytes) // encrypted write
The same pattern appears in pkg/mpc/eddsa_keygen_session.go for EdDSA shares and across signing and resharing workflows. Because Badger handles encryption transparently, the application code treats keyBytes as plaintext while the underlying store encrypts it automatically.
Retrieving and Decrypting Key Shares
When a signing or resharing session starts, it must load the previously persisted share. The decryption happens transparently inside Badger during the Get operation.
The loadOldShareDataGeneric Helper
In pkg/mpc/session.go (lines 41‑74), the loadOldShareDataGeneric method constructs the versioned lookup key, fetches the encrypted payload, and unmarshals it:
// pkg/mpc/session.go → loadOldShareDataGeneric
key := s.composeKey(walletIDWithVersion(walletID, version))
keyData, err := s.kvstore.Get(key) // transparently decrypted read
json.Unmarshal(keyData, dest) // decode back to LocalPartySaveData
Because the encryption key was provided at startup, Badger decrypts the value during the Get call, returning plaintext JSON to the session handler.
Encrypted Backup Operations
The repository also supports encrypted backups using a separate key. In pkg/kvstore/badger_backup.go (line 96), the executor creates an AES-GCM cipher from the BackupEncryptionKey field of BadgerConfig before writing the dump to disk, ensuring backups remain encrypted even when exported from the live database.
Summary
- BadgerDB provides transparent AES encryption via
WithEncryptionKey, ensuring all values are encrypted before reaching LSM files. - The encryption key is derived from the
badger_passwordsupplied at daemon startup and stored inBadgerConfig.EncryptionKey. - Key shares are stored as JSON blobs via
kvstore.Putinpkg/mpc/ecdsa_keygen_session.goand sibling files, using versioned keys to handle wallet updates. - Retrieval uses
kvstore.Getinpkg/mpc/session.go, which transparently decrypts the data before unmarshaling intoLocalPartySaveData. - Backups are independently encrypted using AES-GCM with a separate backup password defined in
BadgerConfig.
Frequently Asked Questions
What encryption algorithm does Badger use for key shares?
BadgerDB uses AES encryption with the key provided via WithEncryptionKey. In mpcium, this key is the 32-byte slice derived from the user’s badger_password, ensuring standardized AES encryption at rest without custom crypto code in the application layer.
How is the encryption key derived from the badger_password?
The daemon treats the user-supplied badger_password string as a byte slice and passes it directly to BadgerConfig.EncryptionKey. According to cmd/mpcium/main.go, this occurs during NewBadgerKVStore initialization; the password must be 32 bytes (or Badger will hash/pad it internally) to serve as the AES key.
Where exactly are the encrypted shares stored in the codebase?
The encrypted shares are persisted in the BadgerDB directory specified by DBPath in the configuration. The write path is pkg/mpc/ecdsa_keygen_session.go (and EdDSA equivalent) which calls s.kvstore.Put, while the read path is pkg/mpc/session.go via loadOldShareDataGeneric.
Can I rotate the encryption key for existing Badger databases?
BadgerDB itself does not support in-place encryption key rotation. To rotate keys in mpcium, you would need to export data using the old key (leveraging the backup functionality in pkg/kvstore/badger_backup.go), create a new Badger instance with the new badger_password, and re-import the shares.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →