Skip to content

Instantly share code, notes, and snippets.

@charger
Created March 3, 2023 08:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charger/4b054f90fb9fa648177a9355418c4685 to your computer and use it in GitHub Desktop.
Save charger/4b054f90fb9fa648177a9355418c4685 to your computer and use it in GitHub Desktop.
Example how encrypt/decrypt text with private GPG key using password stored in a file (to not store password in source code), and encode/decode with Base64Url.
package main
import (
"bytes"
"encoding/base64"
"fmt"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet"
"io"
"io/ioutil"
"os"
"time"
)
const pubKey = "/path/to/public.asc"
const secretKey = "/path/to/secret.asc"
const passwdFileName = "/path/to/passphrase.txt"
//TODO: open keys once when starting app
func decodeAndDecryptWithTime(message []byte) ([]byte, float64, error) {
var st = time.Now()
bts, err := decodeAndDecrypt(message)
return bts, time.Now().Sub(st).Seconds(), err
}
func decodeAndDecrypt(encodedEncrypted []byte) ([]byte, error) {
//decrypt from Base64Url
var encryptedBytes []byte
encryptedBytes, err := base64.URLEncoding.DecodeString(string(encodedEncrypted))
if err != nil {
return nil, err
}
// Read in public key
var entity2 *openpgp.Entity
var entitylist2 openpgp.EntityList
// read private key
keyringFileBuffer2, err := os.Open(secretKey)
if err != nil {
return nil, err
}
defer func() {
_ = keyringFileBuffer2.Close()
}()
entitylist2, err = openpgp.ReadArmoredKeyRing(keyringFileBuffer2)
if err != nil {
return nil, err
}
entity2 = entitylist2[0]
// Get the passphrase and read the open private key.
passwd, err := readPasswdFile(passwdFileName)
if err != nil {
return nil, err
}
err = entity2.PrivateKey.Decrypt(passwd)
if err != nil {
return nil, err
}
for _, subkey := range entity2.Subkeys {
err = subkey.PrivateKey.Decrypt(passwd)
if err != nil {
return nil, err
}
}
decryptedBytes, err := decrypt(entitylist2, encryptedBytes)
if err != nil {
return nil, err
}
return decryptedBytes, nil
}
func readPasswdFile(fileName string) ([]byte, error) {
passwd, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, err
}
passwd = bytes.TrimRight(passwd, "\n")
return passwd, nil
}
func encryptAndEncodeWithTime(message []byte) ([]byte, float64, error) {
var st = time.Now()
bts, err := encryptAndEncode(message)
return bts, time.Now().Sub(st).Seconds(), err
}
func encryptAndEncode(message []byte) ([]byte, error) {
// Read in public key
recipient, err := readEntity(pubKey)
if err != nil {
return nil, err
}
// read private key
signer, err := readEntity(secretKey)
if err != nil {
return nil, err
}
passwd, err := readPasswdFile(passwdFileName)
if err != nil {
return nil, err
}
err = signer.PrivateKey.Decrypt(passwd)
if err != nil {
return nil, err
}
r := bytes.NewReader(message)
w := bytes.Buffer{}
err = encrypt([]*openpgp.Entity{recipient}, signer, r, &w)
if err != nil {
return nil, err
}
encoded := base64.URLEncoding.EncodeToString(w.Bytes())
return []byte(encoded), nil
}
func readEntity(name string) (*openpgp.Entity, error) {
f, err := os.Open(name)
if err != nil {
return nil, err
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Printf("Error closing a file %s: %v", name, err)
}
}(f)
block, err := armor.Decode(f)
if err != nil {
return nil, err
}
return openpgp.ReadEntity(packet.NewReader(block.Body))
}
func encrypt(recipients []*openpgp.Entity, signer *openpgp.Entity, r io.Reader, w io.Writer) error {
wc, err := openpgp.Encrypt(w, recipients, signer, &openpgp.FileHints{IsBinary: true}, nil)
if err != nil {
return err
}
if _, err := io.Copy(wc, r); err != nil {
return err
}
return wc.Close()
}
func decrypt(keyring openpgp.KeyRing, encrypted []byte) ([]byte, error) {
md, err := openpgp.ReadMessage(bytes.NewReader(encrypted), keyring, nil, nil)
if err != nil {
return nil, err
}
decryptedBytes, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
return nil, err
}
return decryptedBytes, nil
}
@sjdhanasekaran
Copy link

@charger Is there a way that encryptAndSign() , decryptAndVerify() way

@charger
Copy link
Author

charger commented Aug 5, 2023

@charger Is there a way that encryptAndSign() , decryptAndVerify() way

Sorry, I don't get your question.

@SanchaiPengMos
Copy link

Hi @charger How do I encrypt and decrypt files?
Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment