Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using borg with smartcards, crypto sticks, etc. #4549

Open
ThomasWaldmann opened this issue May 10, 2019 · 10 comments
Open

using borg with smartcards, crypto sticks, etc. #4549

ThomasWaldmann opened this issue May 10, 2019 · 10 comments

Comments

@ThomasWaldmann
Copy link
Member

ThomasWaldmann commented May 10, 2019

borg has no special interface / does not use some special api for smartcards or crypto usb sticks.

But there is this:

environment vars for the passphrase

https://borgbackup.readthedocs.io/en/stable/usage/general.html#environment-variables

  • BORG_PASSPHRASE - directly give a passphrase to borg

  • BORG_PASSCOMMAND - execute a shell command which outputs the passphrase

  • BORG_PASSPHRASE_FD - read the passphrase from an open file descriptor

With these, some tool that might come with your hardware and some shell scripting, you can "glue together" the hardware and borg (no internal change in borg is needed for that).

You can use repokey as well as keyfile mode of borg for this, the passphrase that would unlock (decrypt) the key would from / via your special hardware, borg's encrypted key would be stored as usual.

environment vars for the key directory

Alternatively, for usb sticks with encrypted mass storage, the BORG_KEYS_DIR (or BORG_KEY_FILE) environment variable could be used to let borg read the keyfile directly from the storage on the stick (keyfile mode).

The storage needs to be mounted at some place and BORG_KEYS_DIR (or BORG_KEY_FILE) needs to point into there (doing that is also scripting and outside the scope of what borg does internally).

@ThomasWaldmann
Copy link
Member Author

I personally do not use smartcards / crypto sticks (yet?), so I can not help much more than this.

So if anybody already has a setup for this, please add scripts and setup tips below.

@jans23
Copy link

jans23 commented Jun 5, 2019

if you want a free Nitrokey device to develop and test such feature, please drop us an email (see https://www.nitrokey.com/contact ).

@klausenbusk
Copy link

So if anybody already has a setup for this, please add scripts and setup tips below.

Something like this should do it (assuming the key is on a smartcard):

head -c 32 /dev/urandom | base64 | gpg --encrypt -r <key on smartcard ID> > ~/.borg-passphrase.gpg
export BORG_PASSCOMMAND="gpg --decrypt $HOME/.borg-passphrase.gpg"

@ThomasWaldmann
Copy link
Member Author

It would be useful if a nitrokey (yubikey, ...) user could confirm that the solution @klausenbusk was suggesting is actually working.

If you test it, report back whether it is working and give the hardware / key setup you are using.

If it can be made working that simply, guess there is no need for hardware key specific development work (but we could add it to the docs / faq).

@klausenbusk
Copy link

klausenbusk commented Jun 7, 2019

It would be useful if a nitrokey (yubikey, ...) user could confirm that the solution @klausenbusk was suggesting is actually working.

The Quick Start guide already contains a example using pass, pass use GPG under the hood, so I can't see why it shouldn't work.

Nevertheless I did a quick test with my YubiKey 4 and it seems to work:

$ head -c 32 /dev/urandom | base64 | gpg --encrypt -r kristian@klausen.dk > borg-passphrase.gpg
$ export BORG_PASSCOMMAND="gpg --decrypt borg-passphrase.gpg"
$ borg init -e keyfile foo
gpg: encrypted with 4096-bit RSA key, ID 89694FF686B54D0A, created 2019-06-02
      "Kristian Klausen <kristian@klausen.dk>"

By default repositories initialized with this version will produce security
errors if written to with an older version (up to and including Borg 1.0.8).

If you want to use these older versions, you can disable the check by running:
borg upgrade --disable-tam foo

See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability for details about the security implications.

IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
Use "borg key export" to export the key, optionally in printable format.
Write down the passphrase. Store both at safe place(s).

@ThomasWaldmann
Copy link
Member Author

OK, so does anybody feel like making pull requests against master (and after review against 1.1-maint), adding this method to support all gpg supporting hw crypto keys?

@ThomasWaldmann ThomasWaldmann added this to the 1.1.11 milestone Jun 8, 2019
@ThomasWaldmann
Copy link
Member Author

OK, guess what we should do is this:

  • only keep the most simple BORG_PASSPHRASE method in the quickstart script
  • add a note to the script about other options, pointing to a following section
  • add a section below the script about "other options to supply the passphrase"
  • mention BORG_PASSCOMMAND there, give an example with "pass" and one with "gpg"
  • mention that GPG can optionally be used with a hw crypto stick
  • also mention BORG_PASSPHRASE_FD there
  • (optional) give a tested(!) example how to use BORG_PASSPHRASE_FD

@ThomasWaldmann
Copy link
Member Author

Played around with the method suggested by @klausenbusk - it works.

It changes the situation of having a cleartext borg passphrase in some file into having a gpg encrypted borg passphrase in some file. The gpg decryption key would live on your gpg-capable hw key.

The hw key could be configured to require a manual touch for any gpg decryption requested.

But there is a problem with automated backups: maybe one would rather not want to require the manual touch here and also the hw key would be attached to the machine at all times when backups are wanted.

So, any software other than the backup script with borg (e.g. malware) could also decrypt and have the cleartext borg passphrase. Also, humans with local access to the machine could also decrypt.

It would help for cases like somebody accidentally publishing the backup script / gpg encrypted passphrase or some fellow looking over your shoulder - the real passphrase would then not be visible.

@ThomasWaldmann ThomasWaldmann removed this from the 1.1.11 milestone Feb 9, 2023
@ThomasWaldmann
Copy link
Member Author

ThomasWaldmann commented Feb 9, 2023

TODO: Check advantages/disadvantages of https://github.com/Yubico/python-fido2 and hmac-secret method.

@ThomasWaldmann ThomasWaldmann reopened this Feb 9, 2023
@ThomasWaldmann ThomasWaldmann removed their assignment May 11, 2023
@ranenvious
Copy link

TODO: Check advantages/disadvantages of https://github.com/Yubico/python-fido2 and hmac-secret method.

I've been looking into this myself recently for a personal project and there are a few implementations of this idea that I've seen,

Keypassxc (ctrl+f for yubikey) uses the security key (given yubikeys are the most popular I might use the terms interchangably) for encryption with a challenge that is new each time you update your password list. While some would argue this is more secure, I'm not sure it could be made easily compatible with incremental backups without re-encrypting and re-writing the entire backup each time you update it. (which as far as I can tell is exactly what keypassxc does which, while it's feasible for a small password database, almost certainly wouldn't scale) I have a vague idea on how an implementation like that might exist, but I don't have the understanding to confirm it with certainty.

ykfde uses the SHA1 HMAC that I believe is yubikey specific to decrypt luks. (I could be wrong on that, it might exist on other keys but I haven't heard of it if it does) The challenge for this is constant, but ykfde doesn't need to remember it or the secret-key. This makes it more vulnerable to replay attacks but ensures that the host's security can be comprimised (within reason) and still be secure. (ykfde can also use a stored challenge which is the exact same except instead of the user typing in a password that becomes the challenge it's stored. This still means that ykfde doesn't need to remember the secret-key for response authentication however.)

finally there is systemd - cryptenroll which I've been able to find much less info on. (at least info I can understand, while I have spent a good bit of time researching this stuff I don't have any formal education in it and most of the whitepapers read as whitenoise to me) I believe it's much like ykfde but uses the SHA256 HMAC in FIDO2 as opposed to the yubikey's own SHA1 HMAC. It might also have the re-encryption functionality of keypassxc but I can't say for sure. (as opposed to ykfde where the challenge is static) I can't confirm this but given that luks uses your passwords to decrypt it's own independently generated masterpassword, I have a theory that after opening the LUKS masterkey it generates a new challenge/response pair, wipes the old response keyslot, and replaces it with the next expected response. This would mean that it could have a continually changing response without having to re-encrypt the entire drive each time. Again, I haven't been able to confirm this myself but it is the one method in which I could see multi-terabyte key-shifting working and I have a gut feeling that it's being used. If it is, that would be a way to implement replay-resistant encryption with a hardware key. (my issue - aside from the fact that I can't find any confirmation on whether the challenge even is non-static to begin with - is that I can't personally think of a way in which it would be replay-immune since the LUKS volume would have to trust that the newly generated response is valid in some cryptographically secure way, otherwise an attacker could record the next-agreed-upon response to get in at which point they could just continually spoof the next response.)

Someone with a lot more understanding of this on a cryptographic level would have to make the ultimate decision on the exact implementation Borg should use, (if it's implemented at all) but these are the best three examples I personally know of and my high-level understanding of them. (again though, I could be wrong on some details. I don't know enough about cryptography to say with certainty so I'm trying to limit everything to only broad-stroke/high-level generalities)

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

No branches or pull requests

4 participants