Skip to content

Instantly share code, notes, and snippets.

@clementlecorre
Created May 19, 2021 10:11
Show Gist options
  • Save clementlecorre/6ff0a42eb270dc7ab5e270dc823fe5a5 to your computer and use it in GitHub Desktop.
Save clementlecorre/6ff0a42eb270dc7ab5e270dc823fe5a5 to your computer and use it in GitHub Desktop.
Golang gpg decrypt (crypto/openpgp)
package gpg
import (
"bytes"
"encoding/base64"
"errors"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
"io/ioutil"
"os"
)
type DecryptOption struct {
PrivateKeyPath string
FileToDecrypt string
PassPhraseBase64 string
OutputFileName string
}
type Decrypt struct {
DecryptOption
privateKeyEntity *openpgp.Entity
privateKeyEntityList openpgp.EntityList
}
func NewGpgDecrypt(gpgDecryptOption DecryptOption) (*Decrypt, error) {
gpgDecrypt := Decrypt{DecryptOption: gpgDecryptOption}
if gpgDecrypt.PrivateKeyPath == "" {
return nil, errors.New("you must reference a private key")
}
if gpgDecrypt.FileToDecrypt == "" {
return nil, errors.New("you must reference file to encrypt")
}
if gpgDecrypt.PassPhraseBase64 == "" {
return nil, errors.New("you must reference pass phrase (base64)")
}
if gpgDecrypt.OutputFileName == "" {
return nil, errors.New("you must reference output file name")
}
gpgDecrypt.openPrivateKey()
return &gpgDecrypt, nil
}
func (g *Decrypt) openPrivateKey() error {
privateKeyFile, err := os.Open(g.PrivateKeyPath)
if err != nil {
return err
}
defer privateKeyFile.Close()
g.privateKeyEntityList, err = openpgp.ReadKeyRing(privateKeyFile)
if err != nil {
return err
}
g.privateKeyEntity = g.privateKeyEntityList[0]
return g.decryptingPrivateKeyWithPassPhrase()
}
func (g *Decrypt) decryptingPrivateKeyWithPassPhrase() error {
passphraseDecodedByte, err := g.PassPhraseDecode()
if err != nil {
return err
}
err = g.privateKeyEntity.PrivateKey.Decrypt(passphraseDecodedByte)
if err != nil {
return err
}
for _, subkey := range g.privateKeyEntity.Subkeys {
err = subkey.PrivateKey.Decrypt(passphraseDecodedByte)
if err != nil {
return err
}
}
return nil
}
func (g *Decrypt) PassPhraseDecode() ([]byte, error) {
decodedPassPhrase, err := base64.StdEncoding.DecodeString(g.PassPhraseBase64)
if err != nil {
return []byte{}, err
}
return decodedPassPhrase, nil
}
func (g *Decrypt) saveDecodedFile(content []byte) error {
f, err := os.Create(g.OutputFileName)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(content)
return err
}
func (g *Decrypt) Decrypt() error {
content, err := ioutil.ReadFile(g.FileToDecrypt)
if err != nil {
return err
}
md, err := openpgp.ReadMessage(bytes.NewBuffer(content), g.privateKeyEntityList, nil, &packet.Config{DefaultCipher:packet.CipherAES256})
if err != nil {
return err
}
fileDecoded, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
return err
}
return g.saveDecodedFile(fileDecoded)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment