Рыба проекта. Минимальная функциональность

This commit is contained in:
2026-08-03 22:22:24 +03:00
commit 8c8631ac9c
80 changed files with 10618 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
package main
import (
"crypto/rand"
"fmt"
"os"
"github.com/spf13/cobra"
"git.tswf.io/infra/go-synapse-backupper/pkg/adapters/crypto/keymanager"
"git.tswf.io/infra/go-synapse-backupper/pkg/adapters/crypto/mlkem768"
"git.tswf.io/infra/go-synapse-backupper/pkg/adapters/crypto/x25519"
"git.tswf.io/infra/go-synapse-backupper/pkg/domain/crypto"
)
func newRegistry() crypto.Registry {
reg := crypto.NewRegistry()
_ = reg.Register(0x0006, func() crypto.KEM { return mlkem768.New() })
_ = reg.Register(0x0007, func() crypto.KEM { return x25519.New() })
return reg
}
func newKeygenCmd() *cobra.Command {
return newKeygenCmdWithDeps(newRegistry())
}
func newKeygenCmdWithDeps(reg crypto.Registry) *cobra.Command {
var (
keyType string
outPrefix string
force bool
)
cmd := &cobra.Command{
Use: "keygen",
Short: "Generate encryption key pairs",
RunE: func(cmd *cobra.Command, args []string) error {
schemes := []struct {
name string
schemeID uint16
}{}
switch keyType {
case "pq":
schemes = append(schemes, struct {
name string
schemeID uint16
}{"pq", 0x0006})
case "classical":
schemes = append(schemes, struct {
name string
schemeID uint16
}{"classical", 0x0007})
case "both":
schemes = append(
schemes,
struct {
name string
schemeID uint16
}{"pq", 0x0006},
struct {
name string
schemeID uint16
}{"classical", 0x0007},
)
default:
return fmt.Errorf("invalid --type %q; must be pq, classical, or both", keyType)
}
if !force {
for _, s := range schemes {
pubPath := outPrefix + "." + s.name + ".pub.pem"
privPath := outPrefix + "." + s.name + ".priv.pem"
for _, p := range []string{pubPath, privPath} {
if _, err := os.Stat(p); err == nil {
return fmt.Errorf("file already exists: %s (use --force to overwrite)", p)
}
}
}
}
km := keymanager.NewKeyManager(reg)
for _, s := range schemes {
pubPath := outPrefix + "." + s.name + ".pub.pem"
privPath := outPrefix + "." + s.name + ".priv.pem"
pubFile, err := os.OpenFile(pubPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
if err != nil {
return fmt.Errorf("create public key file %s: %w", pubPath, err)
}
privFile, err := os.OpenFile(privPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
_ = pubFile.Close()
return fmt.Errorf("create private key file %s: %w", privPath, err)
}
if err := km.Generate(s.schemeID, pubFile, privFile, rand.Reader); err != nil {
_ = pubFile.Close()
_ = privFile.Close()
return fmt.Errorf("generate %s keys: %w", s.name, err)
}
if err := pubFile.Close(); err != nil {
return fmt.Errorf("close public key file %s: %w", pubPath, err)
}
if err := privFile.Close(); err != nil {
return fmt.Errorf("close private key file %s: %w", privPath, err)
}
}
return nil
},
}
cmd.Flags().StringVar(&keyType, "type", "both", "Key type to generate (pq|classical|both)")
cmd.Flags().StringVar(&outPrefix, "out-prefix", "", "Output file path prefix")
cmd.Flags().BoolVar(&force, "force", false, "Overwrite existing files")
return cmd
}