What should be reasonable default parameters for the kdf part of crypto?


First: I am going to ask a question about the settings around AES encryption in restic, but I am by no mean an expert in the field, please bear patience if my question is out of focus.

I did have a look at how the internal/crypto package generates keys and uses them to cipher blobs, and I have a remark, and a question, about the crypto.Calibrate() funtion

The context :

  1. this function is called only when a repository is initialized, at its creation
  2. it basically calls sscrypt.Calibrate()
  3. sscrypt.Calibrate() tries to adjust the N,P,R parameters used to generate the AES key by measuring the wallclock time it takes to generate a key (with a known password and salt)
  4. if I read correctly the only sanity check applied at exit (a call to sscrypt.Check on L.308) is that the parameters are 1 or more (and not, for example, above the default values)

The remark :
I had an issue with 3. : if for some reason the machine running the program is slower at some point in time (flooded CPU, swapping, … some people will have more imagination than me here), then the parameters would just be lowered. In a critical case: if an adversary was able to flood the target system for some reason (being able to start as many process as he wants, trigger requests from outside, …) at the moment of calibration, then this could impact the “calibrated” values.

I then realized 1. : this only applies when initializing a repo, which is probably done with an admin conscious of how his system responds – e.g: he should be able to realize whether something is ok or not when he runs his command, and probably runs it in a more controlled environment (more controlled than, say, if a key was generated at each backup). He may not be aware, though, that initializing the repo while some other CPU intensive task happens could have an adverse effect on his generated key.

My question is simply :

  • does it make sense to at least set default values higher than 1 ? (e.g: use sscrypt.Default as a minimum ?)
  • regardless of the system that actually runs restic, what are values which are considered as “good enough” in 2023 ?

You are right - these parameters are only set when a new keyfile is created and added to the repo, not during “normal” operation.

Here is what I did in rustic
I use the parameters recommended by the scrypt crate, see rustic/keyfile.rs at de6c678b11951ed94a1e1f70f9aeb9e4810d3eae · rustic-rs/rustic · GitHub
This results in:
n = 2^15
r = 8
p = 1

I also remember that for me it was important to choose parameters strong enough to guarantee security for any (or, at least almost any) hardware an attacker could have - and of course not parameters depending on the cpu which generates the keyfile…

If anyone is scared about a too low secure keyfile, just generate a new key (using restic on a powerful machine or using rustic) and remove the old key.

And another remark: This is not about AES, it is “only” scrypt which is the algorithm used to encode the actual AES key (called “masterkey”) using the provided password. But as this scrypt-encoded key is saved in the keyfile in the repository, a successful attack to the scrypt algorithm leads to a fully accessible repository.

1 Like

To provide some sample values:

  • Raspberry pi 4: “N”:32768,“r”:8,“p”:1
  • AMD Ryzen 7 PRO 5850U: “N”:32768,“r”:8,“p”:8

That indeed looks like the defaults of “N”:16384,“r”:8,“p”:1 would be suitable as minimum values.