Skip to content

x/crypto/openpgp: NewEntity creates malformed PGP key: unexpected EOF #25463

@onetwopunch

Description

@onetwopunch

What I'm trying to do is programmatically generate a PGP keypair, store the private key somewhere only this program has access to write to, such as KMS or something, then use the public key. The problem I'm facing is that it seems my method of creating a key pair is not working such that it can be re-ingested by this same library.

I'm fully aware that I may be doing something wrong here, but on the off chance this is an actual error in the openpgp package I figured I might as well submit an issue.

What version of Go are you using (go version)?

go version go1.10.2 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

Mac OSX

What did you do?

I'm trying to autogenerate a PGP key pair and validate the public key armored using the openpgp package in the following way:

package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"golang.org/x/crypto/openpgp"
	"golang.org/x/crypto/openpgp/armor"
	"golang.org/x/crypto/openpgp/packet"
	"log"
)

func main() {
	buf := createKeyPair()
	fmt.Println(buf)
	encoded, err := readPGP(buf)
	if err != nil {
		log.Fatal(err)
	}
	validate(encoded)
}

func createKeyPair() *bytes.Buffer {
	conf := &packet.Config{
		RSABits: 2048,
	}
	entity, err := openpgp.NewEntity("Rick Sanchez", "Autogenerated GPG Key", "test@example.com", conf)
	// TODO: Store private key somewhere safe
	if err != nil {
		log.Fatal(err)
	}
	serializedEntity := bytes.NewBuffer(nil)
	entity.Serialize(serializedEntity)

	buf := bytes.NewBuffer(nil)
	headers := map[string]string{"Version": "GnuPG v1"}
	w, err := armor.Encode(buf, openpgp.PublicKeyType, headers)
	if err != nil {
		log.Fatal(err)
	}
	_, err = w.Write(serializedEntity.Bytes())
	if err != nil {
		log.Fatalf("error armoring serializedEntity: %s")
	}
	w.Close()

	return buf
}

func validate(keystring string) {
	data, err := base64.StdEncoding.DecodeString(keystring)
	if err != nil {
		log.Fatalf("error decoding given PGP key: %s", err)
	}
	_, err = openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
	if err != nil {
		log.Fatalf("error parsing given PGP key: %s", err)
	}
	fmt.Println("PASSED")
}

func readPGP(armoredKey *bytes.Buffer) (string, error) {
	keyReader := bytes.NewReader(armoredKey.Bytes())
	entityList, err := openpgp.ReadArmoredKeyRing(keyReader)
	if err != nil {
		log.Fatalf("error reading armored key %s", err)
	}
	serializedEntity := bytes.NewBuffer(nil)
	err = entityList[0].Serialize(serializedEntity)
	if err != nil {
		return "", fmt.Errorf("error serializing entity for file %s", err)
	}

	return base64.StdEncoding.EncodeToString(serializedEntity.Bytes()), nil
}

What did you expect to see?

<public key>
PASSED

What did you see instead?

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

xsBNBFr/vScBCADL8q0l5c/H1H5cvIRRvmX0Ulw3CuVodJ8JpMUM288xlkrYRgyE
mJzGyi2puZYXz1MAeutOZQTVjCRz4ReJ0aXOposVZek5wN3Mg/KGh9P8OAZuMFVP
F/KgzWpYxxxVeIglEyka1/5b0k2nv9ypkwsmRlQ1n78hgYzNT+bFi3ElWhVcLV7s
yNV+YHh0YzRLQsR73Ip9Mi5/NbZv4YegdAVJKPAV2ab+oDYiVnatYIxePNuOeGYu
oTGh41M+luqikgryYO61Z8VkQNFf2BuFTUQdMpbH3FIVBqWFDZAJ9kzFD+mNBYeA
fgk9AvnC/fAFCJw732VjcRaeX2D5O6E+I68/ABEBAAHNN1JpY2sgU2FuY2hleiAo
QXV0b2dlbmVyYXRlZCBHUEcgS2V5KSA8dGVzdEBleGFtcGxlLmNvbT4=
=vSR7
-----END PGP PUBLIC KEY BLOCK-----
2018/05/18 22:59:03 error reading armored key unexpected EOF
exit status 1

Also, using this same createKeyPair method but just outputting it to stdout then attempting to import it to gpg (instead of this validation code) also did not work but with a different error:

$ go run gpg_test.go | gpg --import
gpg: key 962282668E9C926F: no valid user IDs
gpg: this may be caused by a missing self-signature
gpg: Total number processed: 1
gpg:           w/o user IDs: 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions