Files
metacrypt/cmd/metacrypt/init.go
Kyle Isom bbe382dc10 Migrate module path from kyle/ to mc/ org
All import paths updated to git.wntrmute.dev/mc/. Bumps mcdsl to v1.2.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:05:59 -07:00

97 lines
2.1 KiB
Go

package main
import (
"context"
"fmt"
"log/slog"
"os"
"syscall"
"github.com/spf13/cobra"
"golang.org/x/term"
"git.wntrmute.dev/mc/metacrypt/internal/barrier"
"git.wntrmute.dev/mc/metacrypt/internal/config"
"git.wntrmute.dev/mc/metacrypt/internal/crypto"
"git.wntrmute.dev/mc/metacrypt/internal/db"
"git.wntrmute.dev/mc/metacrypt/internal/seal"
)
var initCmd = &cobra.Command{
Use: "init",
Short: "Interactive first-time setup",
Long: "Initialize Metacrypt with a seal password. This must be run before the server can be used.",
RunE: runInit,
}
func init() {
rootCmd.AddCommand(initCmd)
}
func runInit(cmd *cobra.Command, args []string) error {
configPath := cfgFile
if configPath == "" {
configPath = "/srv/metacrypt/metacrypt.toml"
}
cfg, err := config.Load(configPath)
if err != nil {
return err
}
database, err := db.Open(cfg.Database.Path)
if err != nil {
return err
}
defer func() { _ = database.Close() }()
if err := db.Migrate(database); err != nil {
return err
}
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
b := barrier.NewAESGCMBarrier(database)
sealMgr := seal.NewManager(database, b, nil, logger)
if err := sealMgr.CheckInitialized(); err != nil {
return err
}
if sealMgr.State() != seal.StateUninitialized {
return fmt.Errorf("already initialized")
}
fmt.Print("Enter seal password: ")
pw1, err := term.ReadPassword(int(syscall.Stdin))
fmt.Println()
if err != nil {
return fmt.Errorf("reading password: %w", err)
}
fmt.Print("Confirm seal password: ")
pw2, err := term.ReadPassword(int(syscall.Stdin))
fmt.Println()
if err != nil {
return fmt.Errorf("reading password: %w", err)
}
if !crypto.ConstantTimeEqual(pw1, pw2) {
return fmt.Errorf("passwords do not match")
}
params := crypto.Argon2Params{
Time: cfg.Seal.Argon2Time,
Memory: cfg.Seal.Argon2Memory,
Threads: cfg.Seal.Argon2Threads,
}
fmt.Println("Initializing (this may take a moment)...")
if err := sealMgr.Initialize(context.Background(), pw1, params); err != nil {
return err
}
crypto.Zeroize(pw1)
crypto.Zeroize(pw2)
fmt.Println("Metacrypt initialized and unsealed successfully.")
return nil
}