diff --git a/pgp/keysource.go b/pgp/keysource.go index b5f4592d9..dbf2d7f7b 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "fmt" "io/ioutil" + "net/http" "os" "os/user" "path" @@ -81,16 +82,46 @@ func (key *MasterKey) encryptWithGPGBinary(dataKey []byte) error { return nil } -func (key *MasterKey) encryptWithCryptoOpenPGP(dataKey []byte) error { +func getKeyFromKeyServer(keyserver string, fingerprint string) (openpgp.Entity, error) { + url := fmt.Sprintf("https://%s/pks/lookup?op=get&options=mr&search=0x%s", keyserver, fingerprint) + resp, err := http.Get(url) + if err != nil { + return openpgp.Entity{}, fmt.Errorf("error getting key from keyserver: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return openpgp.Entity{}, fmt.Errorf("keyserver returned non-200 status code %d", resp.Status) + } + ents, err := openpgp.ReadArmoredKeyRing(resp.Body) + if err != nil { + return openpgp.Entity{}, fmt.Errorf("could not read entities: %s", err) + } + return *ents[0], nil +} + +func (key *MasterKey) getPubKey() (openpgp.Entity, error) { ring, err := key.pubRing() + if err == nil { + fingerprints := key.fingerprintMap(ring) + entity, ok := fingerprints[key.Fingerprint] + if ok { + return entity, nil + } + } + entity, err := getKeyFromKeyServer("gpg.mozilla.org", key.Fingerprint) + if err != nil { + return openpgp.Entity{}, + fmt.Errorf("key with fingerprint %s is not available "+ + "in keyring and could not be retrieved from keyserver", key.Fingerprint) + } + return entity, nil +} + +func (key *MasterKey) encryptWithCryptoOpenPGP(dataKey []byte) error { + entity, err := key.getPubKey() if err != nil { return err } - fingerprints := key.fingerprintMap(ring) - entity, ok := fingerprints[key.Fingerprint] - if !ok { - return fmt.Errorf("key with fingerprint %s is not available in keyring", key.Fingerprint) - } encbuf := new(bytes.Buffer) armorbuf, err := armor.Encode(encbuf, "PGP MESSAGE", nil) if err != nil { diff --git a/pgp/keysource_test.go b/pgp/keysource_test.go index 6fb048de4..b3723a83b 100644 --- a/pgp/keysource_test.go +++ b/pgp/keysource_test.go @@ -4,6 +4,8 @@ import ( "bytes" "testing" "testing/quick" + + "github.com/stretchr/testify/assert" ) func TestPGP(t *testing.T) { @@ -40,3 +42,9 @@ func TestPGPKeySourceFromString(t *testing.T) { t.Error("Fingerprint does not match") } } + +func TestRetrievePGPKey(t *testing.T) { + fingerprint := "1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A" + _, err := getKeyFromKeyServer("gpg.mozilla.org", fingerprint) + assert.NoError(t, err) +}