go-crypto icon indicating copy to clipboard operation
go-crypto copied to clipboard

Is there support encryption with multiple keys?

Open bailantaotao opened this issue 6 years ago • 2 comments

Hi there,

In GPG keychain, I can encrypt a message with multiple recipient public key, and it will return a PGP encrypted message. So that the valid user can decrypt the file.

But I tried in your opengpg package, it can encrypt message, but only one person can decrypt it with GPG keychain.

My step:

  1. Use GPG keychain export multiple users public key.
  2. Use your tool to encrypt a message with above public key and output to base64.
  3. Use GPG keychain CLI to decode the message. But got failed. The corresponding error message:
echo ${ENCRYPTD_BY_OPENGPG_BASE64} | base64 -D | gpg -d`

gpg: encrypted with 4096-bit RSA key, ID 0A00AA00A000AA00, created 2016-02-27
      "foo <[email protected]>"
gpg: decryption failed: No secret key

What's step is wrong?

bailantaotao avatar Sep 05 '18 07:09 bailantaotao

Hello, sorry for late reply.

Can you elaborate on the steps being done to encrypt the message?

go-crypto package supports encryption to multiple recipients, see here: https://github.com/keybase/go-crypto/blob/master/openpgp/write.go#L204-L209

zapu avatar Sep 20 '18 09:09 zapu

Hello, just code from my private project:

// Read PGP keys and create openpgp.EntityList with few keys
func readPublicKeys(keys []string) (openpgp.EntityList, error) {
	var entityLists openpgp.EntityList

	for _, key := range keys {
		entityList, err := openpgp.ReadArmoredKeyRing(strings.NewReader(key))
		if err != nil {
			return entityList, err
		}
		entityLists = append(entityLists, entityList[0])
	}

	return entityLists, nil
}

And you can use it with openpgp.Encrypt

Also my encrypt method wrapper for openpgp.Encrypt:

func encrypt(message string, entityList []*openpgp.Entity) (string, error) {
	buf := new(bytes.Buffer)
	w, err := openpgp.Encrypt(buf, entityList, nil, nil, nil)
	if err != nil {
		return "", err
	}
	_, err = w.Write([]byte(message))
	if err != nil {
		return "", err
	}
	err = w.Close()
	if err != nil {
		return "", err
	}

	output, err := ioutil.ReadAll(buf)
	if err != nil {
		return "", err
	}

	pubKeyBuf := bytes.NewBuffer(nil)
	pubKeyWriter, err := armor.Encode(pubKeyBuf, messageHeader, headers)
	if err != nil {
		return "", err
	}
	_, err = pubKeyWriter.Write(output)
	if err != nil {
		return "", err
	}
	err = pubKeyWriter.Close()
	if err != nil {
		return "", err
	}
	outputString := pubKeyBuf.String()

	return outputString, nil
}

dutchakdev avatar Jan 24 '20 14:01 dutchakdev