OpenPGP armor.Decode for validating public keys

219 views
Skip to first unread message

dpapathanasiou

unread,
May 14, 2016, 2:44:44 PM5/14/16
to golang-nuts
According to the docs[1], the OpenPGP armor.Decode function should return
an error if it's presented with input that does *not* represent a valid
armored text string:

> Decode reads a PGP armored block from the given Reader. It will ignore
> leading garbage. If it doesn't find a block, it will return nil, io.EOF.

My experience, however, is it will *never* return a non-nil error under
any circumstances (I have been using it to validate armored public
keys versus other types of inputs), and it's only when I try to use the
resulting Block for encoding do I see any errors.

Is this the expected behavior, or is it a bug in the Decode function?

[1] https://godoc.org/golang.org/x/crypto/openpgp/armor#Decode

agl

unread,
May 16, 2016, 7:20:21 PM5/16/16
to golang-nuts
On Saturday, May 14, 2016 at 11:44:44 AM UTC-7, dpapathanasiou wrote:
According to the docs[1], the OpenPGP armor.Decode function should return
an error if it's presented with input that does *not* represent a valid
armored text string:

> Decode reads a PGP armored block from the given Reader. It will ignore
> leading garbage. If it doesn't find a block, it will return nil, io.EOF.

My experience, however, is it will *never* return a non-nil error under
any circumstances (I have been using it to validate armored public
keys versus other types of inputs), and it's only when I try to use the
resulting Block for encoding do I see any errors.

It will return an error if the given io.Reader returns an error.

Since it ignores leading garbage, it'll continue reading data for as long as the io.Reader returns it, unless it finds the header of an armor block. Since OpenPGP armor blocks can be very large, they are processed in a streaming fashion and thus it's not possible to know whether they will be free of errors until you have read it all.


Cheers

AGL 

dpapathanasiou

unread,
May 28, 2016, 11:34:27 AM5/28/16
to golang-nuts
On Monday, May 16, 2016 at 7:20:21 PM UTC-4, agl wrote:
[snip]

It will return an error if the given io.Reader returns an error.

Since it ignores leading garbage, it'll continue reading data for as long as the io.Reader returns it, unless it finds the header of an armor block. Since OpenPGP armor blocks can be very large, they are processed in a streaming fashion and thus it's not possible to know whether they will be free of errors until you have read it all.

Ah, thanks for that clarification: my issue was that accessing the reader
was just fine, it was just that the data it returned did not constitute
a valid key.

I've since changed the implementation to this, which does what I want,
i.e., report an error in either case:

 func DecodeArmoredKey(key string) (*armor.Block, error) {
        block, err := armor.Decode(strings.NewReader(key))
        if nil == block {
                return block, errors.New("Invalid armored text")
        }
        return block, err
}

Reply all
Reply to author
Forward
0 new messages