Repository: restic/restic

Issue #3315: Support for non-passphrase authentication (X509/TPM/etc)
Created: 2021-03-01T17:04:34Z
Output of restic version
restic 0.11.0 compiled with go1.15.3 on linux/amd64
What should restic do differently? Which functionality do you think we should add?
Currently, Restic relies on password-authenticated encryption: A root key is encrypted/decrypted through a KDF each time the repository is opened.
Restic should support non-password based authentication, such as X509, TPM, etc. keys.
What are you trying to do? What problem would this solve?
There exists the framework outside of Restic in many cases to use non-password alternatives which significantly improve overall security and allow for secured automated encryption and decryption of the root key without human intervention. For some threat models, this is adequate:

BitLocker considers the TPM adequate for generation and maintenance of asymmetric keys without the need for a user PIN; TPMs can measure boot times and processes to verify that the system has not been tampered with.
An X509 certificate can be controlled, giving automated snapshotting a means to "know" what is going on without its information being available to all through, e.g. SELinux or other forms of MAC.

Additionally, CAC X509 devices are an ideal "sweet spot" for this:

CAC cards are cheap, ubiquitous, and supported in most major platforms (Linux, Windows via pcsc-lite, MacOS via a native interface)
Many laptops ship with CAC card readers in business environments
Consumer equipment is inexpensive for lightweight tokens (sub-$50)
Loss of trust = remove device.
Transport attacks can be mitigated by removal of a USB device or card from a reader
Optional PIN-backed second-factor authentication requires proof of knowledge AND of access.

Challenges
Currently, Restic has a very loose way of handling password authentication:

A passphrase is requested from the user
Attempts to decrypt and MAC the root key are made for each auth key
The first one wins

This means that a few things will need to be addressed:

Selection of keys based on type and presented authentication mechanism
Disambiguation of keys when multiple are present
Structuring and migration of current key management needs to be modified to handle more than just "id, username, hostname, keydata"

Additionally,

Current support for CAC cards in golang is through a yubikey-centric go-piv/piv-go project
If a user deletes all but an X509 certificate backed key and then loses the private key, this effectively creates a no-win situation
TPMs are not always known for being "stable" - Some TPM1.2 devices are known to be unstable and reset for seemingly unknown reasons such as dualboot environments, a particularly slow boot, failing hardware, power fluctuations, etc.

(Yes, I'm willing to help make this happen; I have hardware, and think adding X509 certificate file support first is the simplest path forward)
Did restic help you today? Did it make you happy in any way?
Restic is wonderful. I currently keep over 2TB of photos, videos, personal documents backed up and verified within a Restic backup. I've been using it for quite some time.

Duplicate issue #3849: Add an option to provide a 512-bit key instead of a password and bypass key derivation
Created: 2022-08-03T18:31:25Z
Output of restic version
restic 0.13.1 compiled with go1.18.1 on linux/amd64
If I understand correctly, the way it works currently is:

The master (AES) key is generated randomly
Password is used to generate a helper key to decrypt the master key using scrypt with fixed options
Encrypted master key, along with scrypt options to generate the helper key  is stored in the repo

This setup is a good default but does not offer any control and requires to store the key in the repo (and even if there was an option to not store the key, you have to worry about storing it locally).
Consider this for advanced users:

Restic expects a 256-bit key for AES provided via command-line argument
You can generate the key using any KDF you want, with any config
You can memorize the options easily, along with the password and not store anything in the repo - and be able to recover it just by remembering the password and the options for key generator.

Would that be hard to implement? I may be way off, but on the surface it seems like it's just about adding the new argument to the commands and if statements to bypass the default mechanism to decrypt the master key and use the one provided instead. I understand that the integrity check algorithm also needs a key, in that case, if any extra keys are needed, they could be provided via command line argument too, unless they can be safely derived from the master key.

Closing comment (2022-08-05T16:00:47Z): I mainly wanted this for security purposes and I think I realized that this offers no practical security improvement?. I figure that if I used a 256-bit key as the input password for Restic, being able to specify the key directly as suggested does not improve security, does it. I would guess it would be easier to break master AES key directly or the key that encrypts the master AES key than it would be to break scrypt for a 256-bit input. The encrypted key being in the repo is not an issue either, it's either break the master key to decrypt the data, or break the helper key to unlock the master key - both tasks are equally difficult.
Having the input password being used for encryption of the real master key in order to enable adding / removing keys without re-encrypting data is useful in the long term and I would personally not want to deprive myself from being able to use that option.
I guess that an improvement I ask for is to be able to input the 64 bytes (which is used to decrypt the master key and for Poly)  directly rather than deriving it from the password, while still having the master key encrypted in repo and being able to add / remove passwords / keys. This impacts the behavior of Restic less, and is essentially: "add an option to pass a 512-bit key instead of a password and bypass key derivation" so one could use their own key derivation or their own key, in a cleaner way.
I guess it would be similar to #3315