From d5423cd8bd0d8cca7a06905e9cb165de5ec8987b Mon Sep 17 00:00:00 2001
From: Johan de Klerk <johan@shiplogic.com>
Date: Mon, 7 Nov 2022 13:42:40 +0200
Subject: [PATCH] Encrypt/decrypt struct

---
 encryption/encryption.go | 63 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/encryption/encryption.go b/encryption/encryption.go
index a940f01..cda03b4 100644
--- a/encryption/encryption.go
+++ b/encryption/encryption.go
@@ -8,6 +8,7 @@ import (
 	"crypto/rand"
 	"crypto/sha256"
 	"encoding/base64"
+	"encoding/json"
 	"fmt"
 	"gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/errors"
 	"io"
@@ -26,6 +27,68 @@ func Md5HashString(bytesToHash []byte) string {
 	return hashString
 }
 
+func EncryptStruct(object any, key string) (string, error) {
+	if len(key) != 32 {
+		return "", errors.New("key should be 32 bytes")
+	}
+
+	block, err := aes.NewCipher([]byte(key))
+	if err != nil {
+		return "", err
+	}
+
+	aesGcm, err := cipher.NewGCM(block)
+	if err != nil {
+		return "", err
+	}
+
+	nonce := make([]byte, aesGcm.NonceSize())
+	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
+		return "", err
+	}
+
+	jsonValue, err := json.Marshal(object)
+	if err != nil {
+		return "", err
+	}
+
+	encryptedValue := string(aesGcm.Seal(nonce, nonce, jsonValue, nil))
+	return base64.StdEncoding.EncodeToString([]byte(encryptedValue)), nil
+}
+
+func DecryptStruct(encryptedStruct string, key string, object any) error {
+	if len(key) != 32 {
+		return errors.New("key should be 32 bytes")
+	}
+
+	decodedStruct, _ := base64.StdEncoding.DecodeString(encryptedStruct)
+	decodedStructString := string(decodedStruct)
+
+	block, err := aes.NewCipher([]byte(key))
+	if err != nil {
+		return err
+	}
+
+	aesGcm, err := cipher.NewGCM(block)
+	if err != nil {
+		return err
+	}
+
+	nonceSize := aesGcm.NonceSize()
+	if len(decodedStructString) < nonceSize {
+		return errors.New("ciphertext too short")
+	}
+
+	nonce, ciphertext := decodedStructString[:nonceSize], decodedStructString[nonceSize:]
+	value, err := aesGcm.Open(nil, []byte(nonce), []byte(ciphertext), nil)
+
+	err = json.Unmarshal(value, object)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func Encrypt(plaintext string, key string) (string, error) {
 	if len(key) != 32 {
 		return "", errors.New("key should be 32 bytes")
-- 
GitLab