andrewchambers / bupstash

Easy and efficient encrypted backups.
https://bupstash.io
MIT License
898 stars 31 forks source link

allow new-key to use stdout, and new-sub-key to use stdin and stdout #365

Open smferris opened 1 year ago

smferris commented 1 year ago

The key handling is unnecessarily inflexible right now, because new-key requires -o, and new-sub-key requires -k and -o. This forces people to use files, and makes it difficult to interoperate with keychains, password managers, and other software people might want to use store keys.

I tried using -o /dev/stdout, but then it complains that the file already exists. Using - creates a file named -, so there doesn't seem to be any way to express using stdout.

I'd like the -k and -o arguments to either always be optional, or if you like the error checking, change them to only be required when stdin (for -k) or stdout (for -o) is a tty, but make them optional when stdin/stdout is not a tty. This would allow people to use pipes from and to other software which actually stores the keys, rather than force keys to be files.

For example, to store the primary bupstash key in the macOS keychain but store put and list subkeys in files for easy automated backups:

bupstash new-key | /usr/bin/security add-generic-password -a primary -s bupstash -w
/usr/bin/security find-generic-password -a primary -s bupstash -w | bupstash new-sub-key --put -o put-backups.key
/usr/bin/security find-generic-password -a primary -s bupstash -w | bupstash new-sub-key --list -o list-backups.key

Alternatively, store all the keys in the keychain:

bupstash new-key | /usr/bin/security add-generic-password -a primary -s bupstash -w
/usr/bin/security find-generic-password -a primary -s bupstash -w | bupstash new-sub-key --put | /usr/bin/security add-generic-password -a put -s bupstash -w
/usr/bin/security find-generic-password -a primary -s bupstash -w | bupstash new-sub-key --list | /usr/bin/security add-generic-password -a list -s bupstash -w

Backups can then be automated to use BUPSTASH_KEY_COMMAND to fetch the keys from the keychain.

To encrypt the primary key with age:

bupstash new-key | age -p -o primary.key.age
age -d primary.key.age | bupstash new-sub-key --put -o put-backups.key
age -d primary.key.age | bupstash new-sub-key --list -o list-backups.key

It's a bad idea to ever allow an unencrypted key to be written to disk. Copy-on-write filesystems such as btrfs make programs such as shred (used in the Password Protect Keys guide) useless, because overwriting the existing file data may not be possible if the filesystem CoWs the writes shred does. Best practice is to never allow an unencrypted key to touch storage, which is easiest to arrange if keys can be piped in on stdin and out to stdout.

andrewchambers commented 1 year ago

The original rationale is it was the only way to write the key while and set its permissions so it isn't accidentally world readable. I agree it is too strict at the moment and we can definitely change it to allow to be written so stdout. I also agree with your point about sub keys.

w.r.t. unencrypted keys on disk - I think you are right - I have been using full disk encryption which is probably why I overlooked this issue.