Cryptographic Key Storage

Two questions:

  1. is there a maximum number of characters one can user to protect ones key
  2. I notice restic stores the key inside of the repo whereas borg stores it on the local machine (if you specify this). While there may be some kind of ‘psychological assurance’ from knowing the key and the data are physically separate, as in the borg model, I believe the reality is the key(s) in a restic repo are well protected using best contemporary practices - and I’ll assume perfectly implemented :slight_smile: Therefore perception aside, the difference in ‘risk’ is negligible. However can I ask, what were the reasons behind deciding to store the key(s) in the repo? I’m a decidely non-crypto guy so if the answer is technical, you’ve definitely got better things to do with your time and therefore feel free to pass on this question. It would be good though if someone could confirm that my assumption that the key management/protection risks are of negligible difference when it comes to restic vs borg.

I don’t know if that’s the original reason, but … if the key isn’t stored in the repository, you’d need to keep a safe backup of it somewhere else. Otherwise you can’t recover any data if the original client is hit by a meteorite or something. And what’s the use of a backup system that can’t recover unless the original data is safe?

2 Likes

@odin you’re right, the reason to do this was that a password (or passphrase) is easy to keep secure non-digitally (e.g. printed out, or shared via Shamir’s secret sharing scheme), whereas a key file is not.

If you need to restore data to a different machine, typing the password (e.g. from a printout) is less complex and much easier than having to transfer a file digitally.

Thank you.

Any idea regarding my first question? My password manager has some ridiculously long passwords (I know GPG allows unlimited length which is one reason) and I’m wondering if I’m going overboard?

// readPassword reads the password from the given reader directly.
func readPassword(in io.Reader) (password string, err error) {
	buf := make([]byte, 1000)
	n, err := io.ReadFull(in, buf)
	buf = buf[:n]

	if err != nil && errors.Cause(err) != io.ErrUnexpectedEOF {
		return "", errors.Wrap(err, "ReadFull")
	}

	return strings.TrimRight(string(buf), "\r\n"), nil
}

I’m not very familiar with Go, but it looks like passwords can have up to 1000 characters (assuming ASCII).

Regarding your first question: @cfbao found a limit of 1000 bytes (which I wasn’t even aware of). Since we’re applying a key-derivation function (scrypt), a much shorter password (20-25 characters if you want to make sure) is plenty. See also here: