ProtonMail/gopenpgp

How to decrypt file when already encrypted

Opened this issue · 5 comments

Hi all, i'm little bit confuse when using this library
first thing what i am todo is receive file then i need to reupload encrypted file

so far i was already created public key and private key using passphrase for encrypted using Func EncryptAttachmentWithKey and then a have to rename file into encrypted.zip.gpg

and now i want to decrypt that file using Func DecryptAttachmentWithKey and my question is

  1. where i can get keyPacket and dataPacket for parameter DecryptAttachmentWithKey, because EncryptAttachmentWithKey already pass at differenct Func of this decrypt Func.

  2. I saw func crypto.SplitMessageFromArmored returned *crypto.PGPSplitMessage that have function to GetBinaryKeyPacket() and GetBinaryDataPacket() for decrypt, but when i use this function return error openpgp: invalid argument: no armored data found, parameter what i'm pass is string([]byte(of the encrypted file))

if please let me know anybody have example encrypt and decrypt file using this library.

thank you for answer,

@twiss
Same question here, how can we use DecryptAttachmentWithKey in the right way?

package main

import (
	"os"
	"strings"
	"testing"

	"github.com/ProtonMail/gopenpgp/v2/crypto"
	"github.com/ProtonMail/gopenpgp/v2/helper"
)

func TestCreate(t *testing.T) {
	arqByte, _ := os.ReadFile("/tmp/a.pdf")

	/* */
	privkey, _ := helper.GenerateKey("comment", "myEmail@mail.com", []byte("password"), "x25519", 0)
	t.Log(privkey) // private key

	keyRing, _ := crypto.NewKeyFromArmoredReader(strings.NewReader(privkey))
	publicKey, _ := keyRing.GetArmoredPublicKey()

	t.Log(publicKey) // public key

	messagePGP, _ := helper.EncryptAttachmentWithKey(publicKey, "test.pdf.pgp", arqByte) //encrypting file
	f, _ := os.Create("test.pdf.pgp")
	defer f.Close()
	f.Write(messagePGP.GetBinary()) // saving encrypted file

	publicKeyObj, _ := crypto.NewKeyFromArmored(publicKey)
	publicKeyRing, _ := crypto.NewKeyRing(publicKeyObj)
	sessionKey, _ := crypto.GenerateSessionKey()
	keyPacket, _ := publicKeyRing.EncryptSessionKey(sessionKey)

	b, _ := os.ReadFile("test.pdf.pgp") // reading encrypted file to []byte
	c, e := helper.DecryptAttachmentWithKey(privkey, []byte("password"), keyPacket, b)
	t.Log(c, e)
}

Result:
gopenpgp: unable to decrypt attachment: gopengpp: unable to read attachment: openpgp: invalid data: parsing error

Thanks

Hi. messagePGP already contains a key packet with the encrypted session key.

keyPacket  := messagePGP.GetBinaryKeyPacket()
dataPacket  := messagePGP.GetBinaryDataPacket()
...
... := helper.DecryptAttachmentWithKey(privkey, []byte("password"), keyPacket, dataPacket)

Hi. messagePGP already contains a key packet with the encrypted session key.

keyPacket  := messagePGP.GetBinaryKeyPacket()
dataPacket  := messagePGP.GetBinaryDataPacket()
...
... := helper.DecryptAttachmentWithKey(privkey, []byte("password"), keyPacket, dataPacket)

But where I'll input the bytes from encrypted file? messagePGP is a return from EncryptAttachmentWithKey , in another part of my client I have to read the bytes from encrypted file then decrypt.

This method is intended for attachments where the key packet is stored in a different place than the file (data packet).
If you just want to encrypt to a file, I would recommend the following:

plaintextFile, _ := os.Open("test.txt")

privateKey, _ := crypto.GenerateKey("comment", "myEmail@mail.com", "x25519", 0)
publicKey, _ := privateKey.ToPublic()

keyRingPrivate, _ := crypto.NewKeyRing(privateKey)
keyRingPublic, _ := crypto.NewKeyRing(publicKey)

ciphertext, _ := os.Create("test.pdf.pgp")

ctWriter, _ := keyRingPublic.EncryptStream(ciphertext, nil, nil)

_, _ = io.Copy(ctWriter, plaintextFile)
ctWriter.Close()
plaintextFile.Close()
ciphertext.Close()

ciphertextReader, _ := os.Open("test.pdf.pgp")
defer ciphertextReader.Close()

plaintextReader, _ := keyRingPrivate.DecryptStream(ciphertextReader, nil, 0)

decryptedData, _ := io.ReadAll(plaintextReader)

fmt.Println(decryptedData)

All the code here:
Generating key pairs;
Encrypting;
Decrypting.

package main

import (
	"io"
	"os"
	"testing"

	"github.com/ProtonMail/gopenpgp/v2/crypto"
)

func TestCreatePGPkeys(t *testing.T) {
	//It happens ONLY in server side

	privateKey, _ := crypto.GenerateKey("comment", "myEmail@mail.com", "x25519", 0)
	publicKey, _ := privateKey.ToPublic()

	privk, _ := privateKey.Armor()
	pubk, _ := publicKey.GetArmoredPublicKey()

	privkFile, _ := os.Create("priv.key")
	defer privkFile.Close()
	privkFile.Write([]byte(privk))

	pubkFile, _ := os.Create("pub.key") // return to you JUST the public key to encrypt the files
	defer pubkFile.Close()
	pubkFile.Write([]byte(pubk))
}

func TestEnc(t *testing.T) {
	plaintextFile, _ := os.Open("path_to_your_file")

	ciphertext, _ := os.Create("yourFileEncrypted.enc")

	newReader, _ := os.ReadFile("pub.key") // read and use public key to encrypt the files
	armored, _ := crypto.NewKeyFromArmored(string(newReader))
	keyRingPublic, _ := crypto.NewKeyRing(armored)
	ctWriter, _ := keyRingPublic.EncryptStream(ciphertext, nil, nil)

	_, _ = io.Copy(ctWriter, plaintextFile)
	defer ctWriter.Close()
	defer plaintextFile.Close()
	defer ciphertext.Close()

}

func TestDec(t *testing.T) {
	ciphertextReader, _ := os.Open("yourFileEncrypted.enc")
	defer ciphertextReader.Close()

	newReader, _ := os.ReadFile("priv.key")

	t.Log(string(newReader))
	ar, err := crypto.NewKeyFromArmored(string(newReader))

	if err != nil {
		t.Log(err)
	}

	keyRingPrivate, _ := crypto.NewKeyRing(ar)

	plaintextReader, _ := keyRingPrivate.DecryptStream(ciphertextReader, nil, 0)
	decryptedData, _ := io.ReadAll(plaintextReader)
	//t.Log(decryptedData)
	decoded, _ := os.Create("decoded.pdf")
	defer decoded.Close()
	decoded.Write(decryptedData)

}