Verify sign-build .snap package from snapstore

Hello, I am trying to sign my snap packagein a way where my customers are able to verify that I compiled and authored the package. It seems the way to do this is through a snap-build assertion.

The steps I believe should be taken to create this assertion include:

  1. Run snapcraft to generate the .snap file
  2. Run snapcraft upload <.snap file> to upload the snap file to snapcraft
  3. Run snapcraft create-key to create a key
  4. Run snapcraft register-key to register the key that was created.
  5. Run snapcraft sign-build <.snap file> to sign the uploaded snap file and upload the assert.

Now, this is all fine, except after this, I don’t know how someone is supposed to verify the snap has been signed. When I run snap download lockbook, there is no sign-build file or any sign-build assertion in the .assert file.

Is this sign-build assertion automatically checked when my package is installed or downloaded from the snapstore?

If it isn’t, how is someone expected to assert sign-build?

At present, the snap-build assertions are not used by snapd. It is possible to use the snap command to download and verify those additional assertions.

In the .assert file created by snap download, I can see the snap’s SHA-3 checksum in the snap-revision assertion. Alternatively, I could calculate it from the .snap file and then base-64 encode it to get the same value.

I can then download the snap-build assertion for the lockbook snap with:

snap known --remote snap-build snap-sha3-384=jOxr2SUQ8EY8B2k9poOV_FUbc4pOT0L9KIUVydgsx4l3f2StIuMNr8tFH4Xpia6I > lockbook.snap-build

The snap ack command can be used to load assertions into snapd. Unfortunately we’re not quite done:

$ sudo snap ack lockbook_3.assert
$ sudo snap ack lockbook.snap-build`
error: cannot assert: assert failed: cannot resolve prerequisite assertion: account-key (fqikNXeTHExTwMsksdo78qofrP5HwVISTlZz2dFDsNeNzY_Z6FEki9w9CWqXoDLU)

This is because I’m missing the assertion representing your signing key. I can download that too:

snap known --remote account-key public-key-sha3-384=fqikNXeTHExTwMsksdo78qofrP5HwVISTlZz2dFDsNeNzY_Z6FEki9w9CWqXoDLU > lockbook.account-key

Looking in the assertion, it says it is for account-id EOoIrhxvSFO4NH4RFgdY8ao8KQ3uwoAG. The corresponding account is already in my local assertion database from the previous snap ack call:

$ snap known account account-id=EOoIrhxvSFO4NH4RFgdY8ao8KQ3uwoAG
type: account
authority-id: canonical
account-id: EOoIrhxvSFO4NH4RFgdY8ao8KQ3uwoAG
display-name: Smail Barkouch
timestamp: 2021-11-19T18:30:12.520429Z
username: smailbarkouch
validation: unproven

So I can see that the key belongs to you. I can also load the account-key and snap-build assertions now to prove they’re valid:

sudo snap ack lockbook.account-key
sudo snap ack lockbook.snap-build

This clearly isn’t an end user ready solution, but shows the building blocks that such a “verify snap” type command could be built on.

1 Like

@jamesh thanks for your answer it provided a lot of clarity for our team.

Are snaps installed the way you described auto-updated? If so, does it provide the same verification going forward?

If you install a snap without using the --dangerous flag, then it will be auto-updated by snapd. And to be able to install a snap file without --dangerous, you must have loaded a snap-revision assertion that can be chained back to snapd’s PKI trust root (this is one of the assertions in the lockbook_3.assert file created by snap download).

It won’t cause snapd to download snap-build assertions for new revisions of the snap downloaded from the store though. And I think you might have been overestimating what snapd was doing with the snap-build assertion in my original post.

When I was able to successfully load the snap-build assertion, all that told me is that snapd has verified that the signature on the assertion is valid, and the signing key can be linked back to the trust root through a sequence of signed account-key assertions. It is not checking:

  • that the snap-sha3-384 hash matches the snap file that has been installed.
  • that the owner of the signing key is also the publisher of the snap in question.

Those are both things I was doing manually in the steps above (the first one implicitly by looking up snap-build assertion by hash). Those features would need to be added to usefully verify snaps.

I think part of the reason it hasn’t been done yet is that it’s not clear what the user/developer experience would be. It would be relatively simple to implement a “snap verify $snap_name” command that downloaded and checked the snap-build assertion for the installed revision of a snap, but that’s not particularly useful or secure (since you’d already have installed the snap, and it wouldn’t tell you anything about new revisions that might be installed in an auto update).

A better version would probably be to provide a way for a publisher to say that all revisions of a particular snap (or revisions from a particular channel of the snap) must be signed, and have snapd check for a corresponding snap-build assertion before installing new revisions. There’s also a question of how you’d indicate this status to the user.