# Introduction

A version control system like `git` doesn't just track changes, it
also provides a record of who made those changes.  This information
can be used to check that commits are authorized, which can improve
software supply chain security.  In particular, checking a change's
provenance can be used to remove intermediaries like forges, and
package registries from a user's trusted computing base.  But,
[authorship information can easily be
forged](https://dev.to/martiliones/how-i-got-linus-torvalds-in-my-contributors-on-github-3k4g).

![Screenshot of a blog post about impersonating Linus Torvalds](assets/github-impersonation.jpg)

An obvious solution to prevent forgeries is to require commits to be
digitally signed.  But, by itself a digital signature doesn't prevent
forgeries.  Anyone can generate a certificate with any user ID, and
use it to sign commits:

```shell
{{#include ../examples/intro-10-neal-cert.txt}}
{{#include ../examples/intro-20-neal-commit.txt}}
```

When someone like Alice verifies the signature, they see that the
commit is correctly signed, which it is:

```shell
{{#include ../examples/intro-30-git-log.txt}}
```

But as the warning points out, the certificate may not actually belong
to the stated owner.  And, as the prompt suggests, it isn't.

What is needed is not only a list of entities that are allowed to
modify the repository, *but also* the certificates they use to sign
the commits.  In other words, to authenticate a commit we need a
signing policy, which says what certificates are authorized to make
changes.

Creating a policy isn't complicated.  But, for an end user it is time
consuming, and requires diligently tracking the project to identify
when maintainers come and go.  That's too much work.

Instead, a project's maintainers could curate a list of entities that
are allowed to add commits and update the signing policy, and
enumerate the certificates they use to sign them.  The tricky part is
applying the policy.  There are a number of edge cases that need to be
handled like how to merge changes from external contributions, who is
allowed to change the policy, and how to deal with compromised keys.

The [Sequoia git](https://gitlab.com/sequoia-pgp/sequoia-git) project
[specifies a set of
semantics](https://sequoia-pgp.gitlab.io/sequoia-git/), defines a
policy language and file format, and provides a set of tools to manage
a policy file, and authenticate commits.

Using `sq-git` is relatively straightforward.  You start by adding a
policy file, `openpgp-policy.toml`, to your project's repository.  (As
shown in the following chapters, `sq-git` helps you do that.)  The
policy is maintained in-band to allow it to evolve, just like the rest
of the project.  The `openpgp-policy.toml` file is basically a list of
entities, the type of changes they are authorized to make, and their
respective OpenPGP certificates.

Before you merge a pull request, you check that commits are authorized
by the policy.  Locally, this can be done by running `sq-git log` on
the range of commits that you want to check.  If your project uses CI,
you add a job that automatically checks that all new commits are
authorized.

Downstream users can use `sq-git` to check that there is a chain of
trust from an older, known-good version of the software to a new
version.  This helps prevent the use of versions that include
modifications that weren't authorized by the project's maintainers.

`sq-git` has a relatively simple two-step authentication rule.  First,
a commit is considered authorized if one of its parent's policies can
authenticate it.  A commit is considered authorized with respect to a
trust root if there is a path from the trust root to the commit where
every commit is authenticated by the parent commit on the path.

The following shows that there are multiple paths from the first
commit to the last commit:

```shell
{{#include ../examples/frob-140-git-log.txt}}
```

Only one of those paths needs to be authenticated, because when the
parent authenticates the merge commit, it implicitly authenticates the
changes added by the other parents.  In a certain sense, the fact that
the other parents are recorded in the git history is purely
decorative.

`sq-git` distinguishes itself from projects like
[sigstore](https://www.sigstore.dev/) in that all of the information
required to authenticate commits is available locally, and no
third-party authorities are required.
