I don't really want my private key file just sitting around in plaintext.
One obvious thing to do is to use age to encrypt that file with a passphrase. I had hoped that if you gave age a passphrase encrypt file in place of a plaintext private key file, it would recognize it and ask for the passphrase, but alas, it does not.
So far, the only way I've found to do this without making a temporary copy of the plaintext private key on disk is to use a FIFO. Given a file, "input", encrypted to my public key, a file, "key.dat" containing my age private key encrypted with a passphrase, this decrypts "input" to the file "output":
$ mkfifo f
$ age -d -i f input > output &
$ age -d key.dat > f
...age prompts for the key.dat passphrase...
Another approach would be to make and mount a RAM disk, decrypt the public key to that, decrypt input, and then unmount and destroy the RAM disk, but that seems more bother, and also less portable. The FIFO trick should work on any modern Unix or Unix-like system.
This is assuming I even want a key file. Age keys are quit small. Here's a private key it just made for me: "AGE-SECRET-KEY-15KMEW7TZY2T02V33ZM0MPH65CTTGHFY34DP2PDQDXFZGT3JU8GQQ5GDAYU"
That's small enough that I'd be happy to store all my private keys in my password manager, and copy/paste from there when I need one. The FIFO trick can work with that:
$ age -d -i f input > output &
$ cat > k
...paste in the key...
That echos the private key to the terminal, though, so maybe something like this?
$ SAVE=$(stty -g)
$ stty -echo
$ age -d -i f input > output &
$ echo "Paste the key, press RETURN, then control-D"
$ cat > k
$ stty $SAVE
I suppose that can be turned into a little shell script, so not having direct support for encrypt private key files is not too annoying--at least on Unix and Unix-like systems.
process substitution might help you avoid an explicit fifo; it should work for this example but in general handling stdin can be tricky when using process substitutions.
age -i <(age -d key.dat) -d input > output
if you're using gnu pass to store private keys, you could do something like
It's NaCl plus Base62 encoding with a fairly simple framing method, that should be fairly rocksolid as far as crypto goes. Internally it's messagepack with binary data for the internal payload, so that's also pretty good and solid.
That shouldn't matter much here, as long as the underlying crypto is fine, baring any very bad exploits in the message pack library, any manipulated message should fail authentication.
They memory safety and type safety of the messagepack library do matter I think: as with PGP, there’s nothing to stop a bad guy from obtaining your public key and sending you encrypted messages. In fact, distribution of public keys is encouraged.
Unlike PGP, this library is interfaced with a FFI interface or you can write your own lib without too much effort. PGP requires understanding it's stdio RPC format. That is the source of some issues related to malicious messages. And of course that PGP doesn't much care where it finds them.
The later very much depends on the email client but the former is less of an issue.
In a worst case using this, you'll be looking at a crash in your client. Code execution is an unlikely issue in Go. The lib doesn't care much about the inside format of the message so that should be a non-issue as well.
I think PGP just gave this sort of messaging format a bad rep because PGP has a bunch of issues related to "being able to cleanly decrypt and encrypt a message".
Shameless plug: https://github.com/gsliepen/packmsg. I tried to create a very fast C implementation (the C implementation of MessagePack is quite slow actually), but also one that is very safe to use, given the constraints of the language.
Can anyone security minded comment on how this tool compares to the Scuttlebutt Secure Handshake[1]?
Notably I've been looking at various modern "safe and easy" crypto tools and found Scuttlebutts handshake interesting. Yet, the entire protocol was a bit difficult to use, and left me with the impression that I'd have to write a lot myself in my preferred language (Rust) to get a batteries included experience. And, for good reason, I'm always hesitant to write anything about crypto hah.
... though, now that I'm looking for a Rust salt pack lib, it doesn't seem to exist in Rust either. Humm.
This is excellent! We need more work like this that is standardized and stable.
From the protocol end, I heard good things about noise [1] but I haven't seen acual apps make use of it(Edit: It literaly says "Noise is currently used by WhatsApp, WireGuard, Lightning, and I2P." On their page). I highly encourage the author of saltpack to keep a reference list of projects that make use of saltpack.
Noise is a bit different in that it's mostly for creating DH protocols with a reduced chance of shooting oneself in the foot. Saltpack seems like it's a wrapper for AEAD encryption w/nacl's secretboxes that also does serialization via messagepack? I'm not sure I see the point of a "crypto messaging format" that pastes nacl and messagepack together and calls it a standard.
I think they're similar in that as you pointer out they reduce the chance of you shooting yourself in the foot. Perhaps a project using noise for data-in-motion and saltpack for data-at-rest(and before transmission) would involve less foot shooting?