Skip to content

Instantly share code, notes, and snippets.

@ericmj
Created April 4, 2016 13:21
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericmj/0ad5d6773c508a5b4a50c870934b39b7 to your computer and use it in GitHub Desktop.
Save ericmj/0ad5d6773c508a5b4a50c870934b39b7 to your computer and use it in GitHub Desktop.

User-signed packages

Few package managers support user-signed packages and with even fewer package managers has it been widely adopted by its community. For signing to be useful it has to be adopted by essentially the whole community, if all your dependencies are signed except one the process is useless because a single attack vector can of course compromise your whole system.

To provide package signing that is useful and can be adopted by the whole community we need to define a set of rules to follow:

  1. No extra applications or dependencies to install on your system.
  2. Easy to sign a package you publish and establish trust that you are the package owner.
  3. Easy and quick to verify a package and verify that the owner is who she says she is - even when working with many packages.
  4. No dependency on a central repository as trusted authority.

One of the hardest parts of public key cryptography is communicating keys and establishing trust for them. There are a few different solutions for this, the most common ones are public key infrastructure (PKIX) [1] and the web of trust [2]. The problem with PKIX is the trust in certificate authorities and hence falls short on rule 4. Web of trust on the other hand, does not rely on central authority but the signing of keys to establish the web of trust is cumbersome and a too big hurdle to get widespread adoption for a package manager and so falls short in rule 2.

The proposal

Users have to prove they own their Hex.pm account, to do this they will associate their Hex.pm account with other online identities and profiles. As an example of this we will use the Phoenix package. I know that Chris McCord is a maintainer for Phoenix, I also know that he has the account https://twitter.com/chris_mccord on Twitter and https://github.com/chrismccord on GitHub. If Chris publishes statements with those accounts saying who he is on Hex.pm and signs those statements with his private key we can use this information as proof of who he is on Hex.pm.

When a user fetches the Phoenix package for the first time their client will ask Hex.pm who published Phoenix. The server will respond with Chris' public key and links to his to the signed statements made with his online profiles. The user should manually verify that the links are to known profiles and the client will automatically verify that the statements were signed with a private key associated with the same public key the server responded with.

The online profile proofs will be signed and included in the users "signature chain". This chain can in the future be expanded to include more than profile proofs, for example device keys. Since it's a user-signed chain the server will not be able parts of the chain.

The server will also a maintain a global merkle tree, signed by the server's public key, that includes the ends of users' signature chains. This adds further protection against the server changing parts of chains without the malicious behaviour being detected.

Trust in the lock

The ownership verification only has to be done when the package is initially fetched for a project. On subsequent fetches the dependency should be stored in the lockfile with the package checksum, if the package checksum matches the verification does not have to be performed again. This also means that for projects with multiple contributors only one of the contributors have to perform the verification.

Even if the package has been stored in the lock users may want to verify ownership again for many reasons, for example after changes have been made to the lock by outside contributions and so clients should make sure to provide a tool for this.

Possible attacks

DDOS

An adversary may DDOS the server to try to prevent users from retrieving data. The server should provide an API that enables mirrors to fully replicate the state of the server. Mirrors can both limit the effect of DDOS attacks and sophisticated mirrors can actively monitor the server for consistency, for example by making sure the global merkle tree is not altered or rolled back in unexpected ways.

Server

The merkle tree limits the server's ability to lie to users, but an advanced attacker may still show users different merkle trees. But the attacker will have to maintain the fork forever or he will be discovered.

For extra security the root of the merkle tree can be published to a third-party, for example it may be routinely included in the bitcoin blockchain by performing bitcoin transaction with the root encoded in the transaction. Clients can then verify that the merkle tree root in the blockchain is consistent with the one the server responds with.

Client

Another attack may be on the package manager client that verifies proofs and signatures. Fortunately we already have three different open source client implementations today so it would be hard for one misbehaving client to go undetected. It's also strongly recommended that releases of the clients are signed by a private key kept offline.

Online private key

Users can optionally chose to store their private key online on the server. The key will be encrypted triplesec [6], a triple paranoid encryption scheme relying on three different cryptos to avoid flaws of a single crypto to affect the security of the encryption.

Storing the key online may seem backwards to some people, which is why it's completely optional. The main goal of this proposal has been to make signing easy while keeping it safe and storing the encrypted private key online makes a good compromise between easy of use and security.

Credit

Much of this proposal is based on ideas from Keybase [4]. Keybase is a service that allows users to easily sign and encrypt messages without relying on public key infrastructure or web trust. I recommend reading their documentation [5] to help get a better understanding of this proposal.

Making user information public

In the past user information on Hex.pm has been private. Hex.pm stores the username and email address of its users, for this feature we will have to make at least one of them public.

Provably append-only registry

Hex.pm will always have the ultimate authority on what is allowed to be published to registry and will have the ability to remove any package. But it's dangerous if Hex.pm can make hidden changes to the registry, users should be able to get the full log of changes of the registry so they can monitor for suspicious activity.

By encoding all changes to the registry in a merkle tree the server will not be able to do changes to registry without the changes being permanently stored in the tree. Users will be able to easily detect inconsistencies and can detect roll backs. Furthermore the root of the merkle tree can again be encoded in the bitcoin blockchain to protect against forking of the tree.

Links

  1. https://en.wikipedia.org/wiki/X.509
  2. https://en.wikipedia.org/wiki/Web_of_trust
  3. https://en.wikipedia.org/wiki/Merkle_tree
  4. https://keybase.io
  5. https://keybase.io/docs
  6. https://keybase.io/triplesec
@aef
Copy link

aef commented Feb 2, 2018

I like the concept and would recommend OpenPGP identity certificates as a foundation because it is an established Internet standard, allows for hierarchical (like X.509 PKI) and graph-based trust delegation and also individual out-of-band management of identity authenticity (e.g. Keybase and your proposal). It is also successfully used to secure other package managers (e.g. APT, Yum) since many years. Also there are lots of tech people with experience in OpenPGP implementations like GnuPG.

Keep in mind that while individual package versions should not be altered after publication, the algorithms used to sign them will grow weak in time. Therefore signatures should expire as well and there should be a way to publish new signatures for an old package release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment