Is ./keys/c1b6b58... a single point of failure for a repo?

Initially, I thought that the password could be reliably used to regenerate a key (that it was a function of the password only). But as I look at the repo structure, and the fact that it is possible to change the password in O(1), it seems that there is an indeed an intermediate key that the password unlocks, and which is stored in ./keys/c1b6b58....

That makes me consider whether this file is a single point of failure for the repository – would a single-bit error in this file render the whole repo unusable? I remember seeing discussions about adding parity bits to repo data, so it seems clear that the underlying model assumes that failure of a single bit or single file is possible.

What I’ve done for my repo is to add a second key with the same password. I’ve confirmed that removing either of the keys is fine, but that if I remove both keys the repository is unusable (to me at least).

  1. Does this seem like a reasonable strategy?

  2. Would it make sense as part of an updated repository format to put backup copies of the key files in other parts of the repository automatically?

1 Like

You’re right, you need at least one key and its password from the keys folder to open the repository. Adding a second key is an option, both keys share the same underlying masterkey. The trick with using the same password for both keys sounds interesting.

I agree, that a new repository format should keep a key backup somewhere.


Kind of an old rant for me, but here goes anyway:

Note: It’s important to start a post like this by acknowledging the many excellent decisions that went into the restic architecture, and the tremendous utility that it provides. Restic is awesome. Having said that, let’s look honestly at areas for improvement:

The fact that the repository uses a single master key is an awful security hole that compromises the security goals expressed in the threat model. Most importantly: once you give someone access to the repository, you can never revoke it. Disabling their password “feels” like revocation, but they’ve already retrieved the master key and will be able to access all of the data in this repository forever.

Past discussions of this topic have prompted suggestions of revoking file-read access (but the threat model explicitly allows untrusted third parties to read files) or to create a new repository with a new key (effective, but simultaneously beyond the application scope and cumbersome to achieve losslessly).

IMHO, the right answer is:

  • The repository should support multiple master encryption keys (a “key list”) which are used on a blob-by-blob basis. Blobs are written using the newest key, but the old blobs can be decrypted with the matching key in the list.
  • User keys should be asymmetric instead of symmetric. Each user’s public key is stored unprotected in the repo, and each user stores their private key externally
  • When a new master encryption key is added to the key list, it is issued to intended users by storing it in each user’s keyfile, encrypted with that user’s public key (allowing them to retrieve it with their private key)
  • Blobs can be migrated from old keys to the newest key

This approach will allow an administrator to revoke a user’s ability to decrypt the repository by issuing a new key to everyone but the revoked user.

  • This will immediately prevent the user from decrypting new content
  • The user will be able to continue decrypting old blobs (which we should assume he already copied while he had access anyway).
  • If the admin desires, he can migrate old blobs to the new key, although this is optional. This will not impact users with access to the current key.

The thread model literally explains that your point is out of scope: “The whole repository is re-encrypted if a key is leaked. With the current key management design, it is impossible to securely revoke a leaked key without re-encrypting the whole repository”. Whilst I’m not against protecting against this vector, there’s no “right answer” in the current implementation because restic is not designed to protect against this, nor is it a severe security flaw.