feat: add derivation index to vault metadata for unique keys - Add VaultMetadata fields: DerivationIndex, LongTermKeyHash, MnemonicHash - Implement GetNextDerivationIndex() to track and increment indices for same mnemonics - Update init and import commands to use proper derivation indices - Add ComputeDoubleSHA256() for hash calculations - Save vault metadata on creation with all derivation information - Add comprehensive tests for metadata functionality. This ensures multiple vaults using the same mnemonic will derive different long-term keys by using incremented derivation indices. The mnemonic is double SHA256 hashed and stored to track which vaults share mnemonics. Fixes TODO item #5
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/secret/internal/secret"
|
||||
"git.eeqj.de/sneak/secret/internal/vault"
|
||||
@@ -164,7 +165,7 @@ func (cli *CLIInstance) VaultImport(vaultName string) error {
|
||||
secret.Debug("Importing mnemonic into vault", "vault_name", vaultName, "state_dir", cli.stateDir)
|
||||
|
||||
// Get the specific vault by name
|
||||
vlt := vault.NewVault(cli.fs, vaultName, cli.stateDir)
|
||||
vlt := vault.NewVault(cli.fs, cli.stateDir, vaultName)
|
||||
|
||||
// Check if vault exists
|
||||
vaultDir, err := vlt.GetDirectory()
|
||||
@@ -193,13 +194,29 @@ func (cli *CLIInstance) VaultImport(vaultName string) error {
|
||||
return fmt.Errorf("invalid BIP39 mnemonic")
|
||||
}
|
||||
|
||||
// Derive long-term key from mnemonic
|
||||
secret.Debug("Deriving long-term key from mnemonic", "index", 0)
|
||||
ltIdentity, err := agehd.DeriveIdentity(mnemonic, 0)
|
||||
// Calculate mnemonic hash for index tracking
|
||||
mnemonicHash := vault.ComputeDoubleSHA256([]byte(mnemonic))
|
||||
secret.Debug("Calculated mnemonic hash", "hash", mnemonicHash)
|
||||
|
||||
// Get the next available derivation index for this mnemonic
|
||||
derivationIndex, err := vault.GetNextDerivationIndex(cli.fs, cli.stateDir, mnemonicHash)
|
||||
if err != nil {
|
||||
secret.Debug("Failed to get next derivation index", "error", err)
|
||||
return fmt.Errorf("failed to get next derivation index: %w", err)
|
||||
}
|
||||
secret.Debug("Using derivation index", "index", derivationIndex)
|
||||
|
||||
// Derive long-term key from mnemonic with the appropriate index
|
||||
secret.Debug("Deriving long-term key from mnemonic", "index", derivationIndex)
|
||||
ltIdentity, err := agehd.DeriveIdentity(mnemonic, derivationIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to derive long-term key: %w", err)
|
||||
}
|
||||
|
||||
// Calculate the long-term key hash
|
||||
ltKeyHash := vault.ComputeDoubleSHA256([]byte(ltIdentity.String()))
|
||||
secret.Debug("Calculated long-term key hash", "hash", ltKeyHash)
|
||||
|
||||
// Store long-term public key in vault
|
||||
ltPublicKey := ltIdentity.Recipient().String()
|
||||
secret.Debug("Storing long-term public key", "pubkey", ltPublicKey, "vault_dir", vaultDir)
|
||||
@@ -209,6 +226,20 @@ func (cli *CLIInstance) VaultImport(vaultName string) error {
|
||||
return fmt.Errorf("failed to store long-term public key: %w", err)
|
||||
}
|
||||
|
||||
// Save vault metadata
|
||||
metadata := &vault.VaultMetadata{
|
||||
Name: vaultName,
|
||||
CreatedAt: time.Now(),
|
||||
DerivationIndex: derivationIndex,
|
||||
LongTermKeyHash: ltKeyHash,
|
||||
MnemonicHash: mnemonicHash,
|
||||
}
|
||||
if err := vault.SaveVaultMetadata(cli.fs, vaultDir, metadata); err != nil {
|
||||
secret.Debug("Failed to save vault metadata", "error", err)
|
||||
return fmt.Errorf("failed to save vault metadata: %w", err)
|
||||
}
|
||||
secret.Debug("Saved vault metadata with derivation index and key hash")
|
||||
|
||||
// Get passphrase from environment variable
|
||||
passphraseStr := os.Getenv(secret.EnvUnlockPassphrase)
|
||||
if passphraseStr == "" {
|
||||
|
||||
Reference in New Issue
Block a user