sigstore / rekor

Software Supply Chain Transparency Log
https://sigstore.dev
Apache License 2.0
884 stars 163 forks source link

Unrelated PGP keys are stored together with PGP signature/publickey #1429

Open jas4711 opened 1 year ago

jas4711 commented 1 year ago

Hi. I'm using rekor-cli v1.1.0 and I'm working on transparency for trisquel/ubuntu/debian/etc-style apt archives and noticed the following problem. It seems the rekor server accepts and stores unrelated keys when accepting a PGP signature.

Compare this session:

fika:etiona jas$ pwd
/Users/jas/dists-trisquel/dists/etiona
fika:etiona jas$ gpg < ~/trisquel-archive-signkey.gpg 
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   dsa1024 2007-01-14 [SC]
      E6C27099CA21965B734AEA31B4EFB9F38D8AEBF1
uid           Trisquel GNU/Linux (Trisquel GNU/Linux signing key) <trisquel-devel@trisquel.info>
sub   elg2048 2007-01-14 [E]
pub   rsa4096 2017-01-07 [SC]
      60364C9869F92450421F0C22B138CA450C05112F
uid           Trisquel GNU/Linux <trisquel-devel@trisquel.info>
sub   rsa4096 2017-01-07 [E]
pub   rsa4096 2022-10-19 [SC]
      D24DDAC9226D5BA5E9F3BED3F5DAAAF74AD4C938
uid           Trisquel GNU/Linux Archive Automatic Signing Key (11/aramo) <trisquel-devel@trisquel.info>
fika:etiona jas$ rekor-cli upload --artifact Release --signature Release.gpg --public-key ~/trisquel-archive-signkey.gpg
Created entry at index 17803652, available at: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a29e8599c617e2c05706a959f6a10daa878deed1f1deda0f521dcd83bf8454248

And look at what's stored in the log:

jas@kaka:~$ wget -q -O- https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a29e8599c617e2c05706a959f6a10daa878deed1f1deda0f521dcd83bf8454248 | jq -r '.[] | .body' | base64 -d | jq -r '.spec .signature .publicKey .content'|base64 -d|gpg
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   dsa1024 2007-01-14 [SC]
      E6C27099CA21965B734AEA31B4EFB9F38D8AEBF1
uid           Trisquel GNU/Linux (Trisquel GNU/Linux signing key) <trisquel-devel@trisquel.info>
sub   elg2048 2007-01-14 [E]
pub   rsa4096 2017-01-07 [SC]
      60364C9869F92450421F0C22B138CA450C05112F
uid           Trisquel GNU/Linux <trisquel-devel@trisquel.info>
sub   rsa4096 2017-01-07 [E]
pub   rsa4096 2022-10-19 [SC]
      D24DDAC9226D5BA5E9F3BED3F5DAAAF74AD4C938
uid           Trisquel GNU/Linux Archive Automatic Signing Key (11/aramo) <trisquel-devel@trisquel.info>
jas@kaka:~$ 

The following more minimal upload results in a smaller key:

fika:etiona jas$ cd ../etiona-security/
fika:etiona-security jas$ gpg < ~/112f.txt 
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   rsa4096 2017-01-07 [SC]
      60364C9869F92450421F0C22B138CA450C05112F
uid           Trisquel GNU/Linux <trisquel-devel@trisquel.info>
sub   rsa4096 2017-01-07 [E]
fika:etiona-security jas$ rekor-cli upload --artifact Release --signature Release.gpg --public-key ~/112f.txt
Created entry at index 17803685, available at: https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77aa9e3a4e547b03ab290495bd94178ab83e8601ea57a393e44cf139b19d36ecc5d
fika:etiona-security jas$ 

Compare log output:

jas@kaka:~$ wget -q -O- https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77aa9e3a4e547b03ab290495bd94178ab83e8601ea57a393e44cf139b19d36ecc5d | jq -r '.[] | .body' | base64 -d | jq -r '.spec .signature .publicKey .content'|base64 -d|gpg
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
pub   rsa4096 2017-01-07 [SC]
      60364C9869F92450421F0C22B138CA450C05112F
uid           Trisquel GNU/Linux <trisquel-devel@trisquel.info>
sub   rsa4096 2017-01-07 [E]
jas@kaka:~$ 

Am I missing something, or shouldn't the server strip any non-related keys before adding them to the log?

jas4711 commented 1 year ago

I ran into another problem where rekor refused an upload where the public key sent had a /signature/ from an Ed25519 key.

I believe the solution here should be:

1) Rekor should find out the PGP key IDs used to sign the artifact, from the signature file. 2) These keys should be extracted from the public key sent to rekor. 3) The public keys should be minimized to not contain unrelated information, compare 'gpg --export-options export-minimal --export'. 4) The public keys should be sorted in some canonical order.

Then that should be what goes into the "public key" field and stored in the rekor log.

jas4711 commented 1 year ago

There is a corner-case: what if the artifact was signed by many signers, but the provided public key file did not contain all public keys for those signatures. I think that should be rejected: if several keys signed the artifact, the public keys for ALL those keys should be sent into rekor. An alternative approach is to accept at least ONE key matching the signature, and not care if others are missing. This is the current behaviour, but it feels sub-optimal.