Files
pentapass/internal/crypto/age/age.go
2024-10-10 10:37:35 +02:00

116 lines
3.1 KiB
Go

package age
import (
"fmt"
"os"
"io"
"bytes"
"errors"
"filippo.io/age"
. "github.com/k4lipso/pentapass/internal/log"
)
var (
ageKeyFileName = "age.key"
)
func GenerateAgeKey(filename string) (*age.X25519Identity, error) {
// Generate a new X25519 identity (private key)
identity, err := age.GenerateX25519Identity()
if err != nil {
return nil, fmt.Errorf("failed to generate identity: %w", err)
}
// Convert the identity to its string representation
privateKey := identity.String()
// Write the private key to a file
err = os.WriteFile(filename, []byte(privateKey), 0600)
if err != nil {
return nil, fmt.Errorf("failed to save private key to file: %w", err)
}
Logger.Infof("Private key saved to %s\n", filename)
return identity, nil
}
func LoadAgeKey(filename string) (*age.X25519Identity, error) {
// Read the private key from the file
privateKeyBytes, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read private key from file: %w", err)
}
// Parse the private key
identity, err := age.ParseX25519Identity(string(privateKeyBytes))
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
return identity, nil
}
func LoadOrGenerateKeys(filename string) (*age.X25519Identity, error) {
_, err := os.Open(filename)
if errors.Is(err, os.ErrNotExist) {
Logger.Info("No Key found. Generating Key")
return GenerateAgeKey(filename)
}
return LoadAgeKey(filename)
}
func Decrypt(encryptedData []byte, identity *age.X25519Identity) ([]byte, error) {
// Create a new decryptor using the recipient's identity
decryptor, err := age.Decrypt(bytes.NewReader(encryptedData), identity)
if err != nil {
return nil, fmt.Errorf("failed to create decryptor: %w", err)
}
// Read the decrypted data
decryptedData, err := io.ReadAll(decryptor)
if err != nil {
return nil, fmt.Errorf("failed to decrypt data: %w", err)
}
return decryptedData, nil
}
func Encrypt(data []byte, recipientKeys []string) ([]byte, error) {
var recipients []age.Recipient
// Parse all recipient keys
for _, key := range recipientKeys {
recipient, err := age.ParseX25519Recipient(key)
if err != nil {
return nil, fmt.Errorf("failed to parse recipient key: %w", err)
}
recipients = append(recipients, recipient)
}
// Create a new buffer to hold the encrypted data
var encryptedData bytes.Buffer
// Create a new age encryptor for the recipients
encryptor, err := age.Encrypt(&encryptedData, recipients...)
if err != nil {
return nil, fmt.Errorf("failed to create encryptor: %w", err)
}
// Write the data to the encryptor
_, err = encryptor.Write(data)
if err != nil {
return nil, fmt.Errorf("failed to encrypt data: %w", err)
}
// Close the encryptor to finalize the encryption process
if err := encryptor.Close(); err != nil {
return nil, fmt.Errorf("failed to finalize encryption: %w", err)
}
return encryptedData.Bytes(), nil
}