2024-09-10 22:59:28 +02:00
|
|
|
|
// Package pkg /
|
|
|
|
|
|
/*****
|
|
|
|
|
|
@author Jonas Kaninda
|
|
|
|
|
|
@license MIT License <https://opensource.org/licenses/MIT>
|
|
|
|
|
|
@Copyright © 2024 Jonas Kaninda
|
|
|
|
|
|
**/
|
2024-07-29 23:03:28 +02:00
|
|
|
|
package pkg
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2024-10-08 11:04:46 +02:00
|
|
|
|
"errors"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
2024-07-29 23:03:28 +02:00
|
|
|
|
"github.com/jkaninda/pg-bkup/utils"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"os/exec"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// decryptWithGPGSymmetric decrypts backup file using a passphrase
|
|
|
|
|
|
func decryptWithGPGSymmetric(inputFile string, passphrase string) error {
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Decrypting backup using passphrase...")
|
|
|
|
|
|
|
2024-08-30 13:47:50 +02:00
|
|
|
|
//Create gpg home dir
|
2024-09-28 09:48:37 +02:00
|
|
|
|
err := utils.MakeDirAll(gpgHome)
|
2024-08-30 13:47:50 +02:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
utils.SetEnv("GNUPGHOME", gpgHome)
|
2024-07-29 23:03:28 +02:00
|
|
|
|
cmd := exec.Command("gpg", "--batch", "--passphrase", passphrase, "--output", RemoveLastExtension(inputFile), "--decrypt", inputFile)
|
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
|
|
2024-08-30 13:47:50 +02:00
|
|
|
|
err = cmd.Run()
|
2024-07-29 23:03:28 +02:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Decrypting backup using passphrase...done")
|
2024-07-29 23:03:28 +02:00
|
|
|
|
utils.Info("Backup file decrypted successful!")
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// encryptWithGPGSymmetric encrypts backup using a passphrase
|
|
|
|
|
|
func encryptWithGPGSymmetric(inputFile string, passphrase string) error {
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Encrypting backup using passphrase...")
|
|
|
|
|
|
|
2024-08-30 13:47:50 +02:00
|
|
|
|
//Create gpg home dir
|
2024-09-28 09:48:37 +02:00
|
|
|
|
err := utils.MakeDirAll(gpgHome)
|
2024-08-30 13:47:50 +02:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
utils.SetEnv("GNUPGHOME", gpgHome)
|
2024-07-29 23:03:28 +02:00
|
|
|
|
cmd := exec.Command("gpg", "--batch", "--passphrase", passphrase, "--symmetric", "--cipher-algo", algorithm, inputFile)
|
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
|
|
2024-08-30 13:47:50 +02:00
|
|
|
|
err = cmd.Run()
|
2024-07-29 23:03:28 +02:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Encrypting backup using passphrase...done")
|
|
|
|
|
|
utils.Info("Backup file encrypted successful!")
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// encryptWithGPGPublicKey encrypts backup using a public key
|
|
|
|
|
|
func encryptWithGPGPublicKey(inputFile string, publicKey string) error {
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Encrypting backup using public key...")
|
|
|
|
|
|
// Read the public key
|
|
|
|
|
|
pubKeyBytes, err := os.ReadFile(publicKey)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error reading public key: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
// Create a new keyring with the public key
|
|
|
|
|
|
publicKeyObj, err := crypto.NewKeyFromArmored(string(pubKeyBytes))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error parsing public key: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
keyRing, err := crypto.NewKeyRing(publicKeyObj)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error creating key ring: %v", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// Read the file to encryptWithGPGPublicKey
|
2024-10-08 11:04:46 +02:00
|
|
|
|
fileContent, err := os.ReadFile(inputFile)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error reading file: %v", err))
|
|
|
|
|
|
}
|
2024-07-29 23:03:28 +02:00
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// encryptWithGPGSymmetric the file
|
2024-10-08 11:04:46 +02:00
|
|
|
|
message := crypto.NewPlainMessage(fileContent)
|
|
|
|
|
|
encMessage, err := keyRing.Encrypt(message, nil)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error encrypting file: %v", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Save the encrypted file
|
|
|
|
|
|
err = os.WriteFile(fmt.Sprintf("%s.%s", inputFile, gpgExtension), encMessage.GetBinary(), 0644)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error saving encrypted file: %v", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
utils.Info("Encrypting backup using public key...done")
|
2024-07-29 23:03:28 +02:00
|
|
|
|
utils.Info("Backup file encrypted successful!")
|
|
|
|
|
|
return nil
|
2024-10-08 11:04:46 +02:00
|
|
|
|
|
2024-07-29 23:03:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// decryptWithGPGPrivateKey decrypts backup file using a private key and passphrase.
|
2024-10-08 11:04:46 +02:00
|
|
|
|
// privateKey GPG private key
|
|
|
|
|
|
// passphrase GPG passphrase
|
2024-10-08 21:27:53 +02:00
|
|
|
|
func decryptWithGPGPrivateKey(inputFile, privateKey, passphrase string) error {
|
2024-10-08 11:04:46 +02:00
|
|
|
|
utils.Info("Encrypting backup using private key...")
|
|
|
|
|
|
|
|
|
|
|
|
// Read the private key
|
|
|
|
|
|
priKeyBytes, err := os.ReadFile(privateKey)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error reading private key: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Read the password for the private key (if it’s password-protected)
|
|
|
|
|
|
password := []byte(passphrase)
|
|
|
|
|
|
|
|
|
|
|
|
// Create a key object from the armored private key
|
|
|
|
|
|
privateKeyObj, err := crypto.NewKeyFromArmored(string(priKeyBytes))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error parsing private key: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Unlock the private key with the password
|
|
|
|
|
|
if passphrase != "" {
|
|
|
|
|
|
// Unlock the private key with the password
|
|
|
|
|
|
_, err = privateKeyObj.Unlock(password)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error unlocking private key: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create a new keyring with the private key
|
|
|
|
|
|
keyRing, err := crypto.NewKeyRing(privateKeyObj)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error creating key ring: %v", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Read the encrypted file
|
|
|
|
|
|
encFileContent, err := os.ReadFile(inputFile)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error reading encrypted file: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-08 21:27:53 +02:00
|
|
|
|
// decryptWithGPGSymmetric the file
|
2024-10-08 11:04:46 +02:00
|
|
|
|
encryptedMessage := crypto.NewPGPMessage(encFileContent)
|
|
|
|
|
|
message, err := keyRing.Decrypt(encryptedMessage, nil, 0)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error decrypting file: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Save the decrypted file
|
|
|
|
|
|
err = os.WriteFile(RemoveLastExtension(inputFile), message.GetBinary(), 0644)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return errors.New(fmt.Sprintf("Error saving decrypted file: %s", err))
|
|
|
|
|
|
}
|
|
|
|
|
|
utils.Info("Encrypting backup using public key...done")
|
|
|
|
|
|
fmt.Println("File successfully decrypted!")
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2024-07-29 23:03:28 +02:00
|
|
|
|
func RemoveLastExtension(filename string) string {
|
|
|
|
|
|
if idx := strings.LastIndex(filename, "."); idx != -1 {
|
|
|
|
|
|
return filename[:idx]
|
|
|
|
|
|
}
|
|
|
|
|
|
return filename
|
|
|
|
|
|
}
|