Volt CLI: source-available under AGPSL v5.0

Complete infrastructure platform CLI:
- Container runtime (systemd-nspawn)
- VoltVisor VMs (Neutron Stardust / QEMU)
- Stellarium CAS (content-addressed storage)
- ORAS Registry
- GitOps integration
- Landlock LSM security
- Compose orchestration
- Mesh networking

Copyright (c) Armored Gates LLC. All rights reserved.
Licensed under AGPSL v5.0
This commit is contained in:
Karl Clinger
2026-03-21 00:30:23 -05:00
commit 0ebe75b2ca
155 changed files with 63317 additions and 0 deletions

243
pkg/encryption/age.go Normal file
View File

@@ -0,0 +1,243 @@
/*
AGE Encryption — Core encrypt/decrypt operations using AGE (x25519 + ChaCha20-Poly1305).
AGE is the encryption standard for Volt CDN blob storage. All blobs are
encrypted before upload to BunnyCDN and decrypted on download. This ensures
zero-knowledge storage — the CDN operator cannot read blob contents.
AGE uses x25519 for key agreement and ChaCha20-Poly1305 for symmetric
encryption. This works on edge hardware without AES-NI instructions,
making it ideal for ARM/RISC-V edge nodes.
Architecture:
- Encrypt to multiple recipients (platform key + master recovery key + optional BYOK)
- Identity (private key) stored on the node for decryption
- Uses the `age` CLI tool (filippo.io/age) as subprocess — no CGO, no heavy deps
Copyright (c) Armored Gates LLC. All rights reserved.
*/
package encryption
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
)
// ── Constants ────────────────────────────────────────────────────────────────
const (
// AgeBinary is the path to the age encryption tool.
AgeBinary = "age"
// AgeKeygenBinary is the path to the age-keygen tool.
AgeKeygenBinary = "age-keygen"
)
// ── Core Operations ──────────────────────────────────────────────────────────
// Encrypt encrypts plaintext data to one or more AGE recipients (public keys).
// Returns the AGE-encrypted ciphertext (binary armor).
// Recipients are AGE public keys (age1...).
func Encrypt(plaintext []byte, recipients []string) ([]byte, error) {
if len(recipients) == 0 {
return nil, fmt.Errorf("encrypt: at least one recipient required")
}
ageBin, err := findAgeBinary()
if err != nil {
return nil, err
}
// Build args: age -e -r <key1> -r <key2> ...
args := []string{"-e"}
for _, r := range recipients {
r = strings.TrimSpace(r)
if r == "" {
continue
}
args = append(args, "-r", r)
}
cmd := exec.Command(ageBin, args...)
cmd.Stdin = bytes.NewReader(plaintext)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("age encrypt: %s: %w", strings.TrimSpace(stderr.String()), err)
}
return stdout.Bytes(), nil
}
// Decrypt decrypts AGE-encrypted ciphertext using a private key (identity) file.
// The identity file is the AGE secret key file (contains AGE-SECRET-KEY-...).
func Decrypt(ciphertext []byte, identityPath string) ([]byte, error) {
if _, err := os.Stat(identityPath); err != nil {
return nil, fmt.Errorf("decrypt: identity file not found: %s", identityPath)
}
ageBin, err := findAgeBinary()
if err != nil {
return nil, err
}
cmd := exec.Command(ageBin, "-d", "-i", identityPath)
cmd.Stdin = bytes.NewReader(ciphertext)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("age decrypt: %s: %w", strings.TrimSpace(stderr.String()), err)
}
return stdout.Bytes(), nil
}
// EncryptToFile encrypts plaintext and writes the ciphertext to a file.
func EncryptToFile(plaintext []byte, recipients []string, outputPath string) error {
ciphertext, err := Encrypt(plaintext, recipients)
if err != nil {
return err
}
return os.WriteFile(outputPath, ciphertext, 0600)
}
// DecryptFile reads an encrypted file and decrypts it.
func DecryptFile(encryptedPath, identityPath string) ([]byte, error) {
ciphertext, err := os.ReadFile(encryptedPath)
if err != nil {
return nil, fmt.Errorf("decrypt file: %w", err)
}
return Decrypt(ciphertext, identityPath)
}
// EncryptStream encrypts data from a reader to a writer for multiple recipients.
func EncryptStream(r io.Reader, w io.Writer, recipients []string) error {
if len(recipients) == 0 {
return fmt.Errorf("encrypt stream: at least one recipient required")
}
ageBin, err := findAgeBinary()
if err != nil {
return err
}
args := []string{"-e"}
for _, rec := range recipients {
rec = strings.TrimSpace(rec)
if rec == "" {
continue
}
args = append(args, "-r", rec)
}
cmd := exec.Command(ageBin, args...)
cmd.Stdin = r
cmd.Stdout = w
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("age encrypt stream: %s: %w", strings.TrimSpace(stderr.String()), err)
}
return nil
}
// DecryptStream decrypts data from a reader to a writer using an identity file.
func DecryptStream(r io.Reader, w io.Writer, identityPath string) error {
ageBin, err := findAgeBinary()
if err != nil {
return err
}
cmd := exec.Command(ageBin, "-d", "-i", identityPath)
cmd.Stdin = r
cmd.Stdout = w
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("age decrypt stream: %s: %w", strings.TrimSpace(stderr.String()), err)
}
return nil
}
// ── AGE Binary Discovery ─────────────────────────────────────────────────────
// findAgeBinary locates the age binary on the system.
func findAgeBinary() (string, error) {
// Try PATH first
if path, err := exec.LookPath(AgeBinary); err == nil {
return path, nil
}
// Check common locations
for _, candidate := range []string{
"/usr/bin/age",
"/usr/local/bin/age",
"/snap/bin/age",
} {
if _, err := os.Stat(candidate); err == nil {
return candidate, nil
}
}
return "", fmt.Errorf("age binary not found. Install with: apt install age")
}
// findAgeKeygenBinary locates the age-keygen binary.
func findAgeKeygenBinary() (string, error) {
if path, err := exec.LookPath(AgeKeygenBinary); err == nil {
return path, nil
}
for _, candidate := range []string{
"/usr/bin/age-keygen",
"/usr/local/bin/age-keygen",
"/snap/bin/age-keygen",
} {
if _, err := os.Stat(candidate); err == nil {
return candidate, nil
}
}
return "", fmt.Errorf("age-keygen binary not found. Install with: apt install age")
}
// IsAgeAvailable checks if the age binary is installed and working.
func IsAgeAvailable() bool {
_, err := findAgeBinary()
return err == nil
}
// AgeVersion returns the installed age version string.
func AgeVersion() (string, error) {
ageBin, err := findAgeBinary()
if err != nil {
return "", err
}
cmd := exec.Command(ageBin, "--version")
var stdout bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stdout
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("age version: %w", err)
}
return strings.TrimSpace(stdout.String()), nil
}