ProtonMail / go-crypto

Fork of go/x/crypto, providing an up-to-date OpenPGP implementation
https://pkg.go.dev/github.com/ProtonMail/go-crypto
BSD 3-Clause "New" or "Revised" License
334 stars 101 forks source link

Add support for signature subpacket type 6: regular-expression #139

Closed arudzitis-stripe closed 1 year ago

arudzitis-stripe commented 1 year ago

Hello, it is me again. You may remember me from pull request such as https://github.com/ProtonMail/go-crypto/pull/138.

I noticed when reviewing the issue with the above pull request (https://github.com/ProtonMail/go-crypto/issues/86), it referenced a slightly different issue in the original Go library: https://github.com/golang/go/issues/20686, which is that we're also missing support for Regular Expression packets (which work hand-in-hand with the trust packets), so I thought I would throw that in as well, if you're interested.

The shape of the change is very similar to https://github.com/ProtonMail/go-crypto/pull/138, but I wanted to call out a few design decisions:

Data used for test case:

echo -n "c2bd0410010800310502886e09001621040f0bfb42b3b08bece556fffcc181c053de849bf20385013c0f862a2e6578616d706c652e636f6d000000620603ff7e405020cdbf82ac30f6ad11f82690d3c2fa2107130f80a66fc48a4b6cc426b90585670d8cb8e258f9c1fa35c62381074fd9b740aaebd96a3265c96d145620d7c24265c8e258a2f9a2229e4edb8076e27d5e229cf676135dde4dad54271e061adea05302e81ff412c55742b15c8b20fe3bee4c6b96cd9dfff44da9cc5df328ab" | xxd -r -p | gpg --list-packets
# off=0 ctb=c2 tag=2 hlen=2 plen=189 new-ctb
:signature packet: algo 1, keyid 0000000000000000
    version 4, created 2288912640, md5len 0, sigclass 0x10
    digest algo 8, begin of digest 62 06
    hashed subpkt 2 len 4 (sig created 2042-07-14)
    hashed subpkt 33 len 21 (issuer fpr v4 0F0BFB42B3B08BECE556FFFCC181C053DE849BF2)
    critical hashed subpkt 5 len 2 (trust signature of depth 1, value 60)
    critical hashed subpkt 6 len 14 (regular expression: "*.example.com\0")
    data: [1023 bits]
twiss commented 1 year ago

Hey :wave: Thanks for the PR and the detailed design considerations!

  • The regular expression on the Signature is a *string. Alternatively, we could go with "" being treated the same as a nil value, but unlike the TrustAmount, there was no other value to lean on for a hint of intention.

Hmm. I think we could go either way with this; on the one hand I would say that since an empty regular expression normally matches anything, it's equivalent to the regex not being there, so we could use the empty string. On the other hand, the RFC says:

A regular expression is zero or more branches, separated by |. It matches anything that matches one of the branches.

Which would seem to imply that the empty regex doesn't match anything. I think this might just be an oversight, but to avoid the confusion we could stick with a pointer, yeah.

  • Signature subpackets can each optionally be critical. It doesn't look like this library has a pattern for preserving the critical flag after parsing it, or allowing the user to indicate whether it is critical. I replicated behavior we had elsewhere and just hard coded this subpacket to critical upon serialization, because that's what I've seen in the wild and also what makes sense to me in this context, but I'm open to looking into a larger change.

Yeah, I think this is reasonable :+1: Since a regex reduces the scope of the signature, it's important that it's understood by the other implementations when using it, so always marking it critical makes sense.

  • The RFC specifies the regex is a null-terminated string, but gpg doesn't appear to expect the string to be null-terminated (the null is shown in the user output, and is not required to parse the outputs). I've followed the RFC, but let me know if you have other thoughts.

Here I'm even more skeptical of the RFC. Coincidentally I also questioned this on the OpenPGP WG mailing list here, but didn't get any response to that particular question. Do you happen to know what GnuPG or other implementations generate when creating a signature with a regex? If they don't generate a trailing \0, I wouldn't do so here either.

arudzitis-stripe commented 1 year ago

If I create a key using GnuPG, it does appear to append a \0. (GnuPG doesn't let you specify a regex; it just asks for a domain and generates the regex.)

Example:

critical hashed subpkt 6 len 25 (regular expression: "<[^>]+[@.]example\x5c.com>$\0")