
Nothing to do with Racket, but something tells me I may get some decent ideas here :)
I would like to be able to encrypt a file with utility U on operating system O using a standard algorithm (AES, Blowfish, etc.) A and a passphrase P, so (encrypt passphrase algorithm clear-data)
, and then many years down the road, when I no longer have utility U (and can’t get it for some unknown reason), I would like to be able to decrypt the file with utility U1 on operating system O1 using the same algorithm and passphrase, so (decrypt passphrase algorithm encrypted-data)
i.e. I don’t want anything unique or proprietary in the utilities U and U1. Ideally there would be multiple options for both U and U1 to verify only the 3 parameters (passphrase algorithm data)
are all that’s necessary.

Ryan’s bindings for libcrypto
allow you to encrypt strings with AES and others.
https://docs.racket-lang.org/crypto/intro.html
Try it - and to make sure it decrypts elsewhere, try to decrypt it with, say, Python.
https://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256

You can do this with the crypto
library directly, but beware that it’s not great to use a “password/passphrase” (or its hash) directly as an encryption key, for the same reasons that storing simple password hashes is not a good idea. So it’s better to use some KDF with a salt and work factor to turn the passphrase into a key, but then you need to store or remember that part of the algorithm too. So if you want to do this right, really consider something like age
.

you might be interested in some writing by https://nullprogram.com, e.g., https://nullprogram.com/tags/crypto/. I started trying to find another article of theirs, but what I think I remembered had more to do with RNG. Hm. There was https://nullprogram.com/blog/2018/07/31/ and https://github.com/skeeto/enchive


@ryanc you’re the second person to recommend age
- I guess my requirements/goals are somewhat in conflict with respect to the best way to encrypt a file being somewhat at odds with this “future proof” idea which favors simplicity and easy repeatability. I’m probably overemphasizing this aspect of finding myself in the future with only a file, an algorithm and a passphrase being sufficient :)

Checkout passphrase2pgp; not sure if that will solve your encryption problem, but it is in a similar space of generating keys based on a passphrase.

age
is probably the best pragmatic solution, but I may still try and verify I can encrypt a file with one language/library and decrypt with another language/library. I know the “passphrase only” approach has some weaknesses, but I may be ok with them in some cases. If I go with the latter, then using some secure method of generating a key from a passphrase may be handy, but that’s one more thing to remember 20 years later :)

brew install age
age -e -p -o file.age file.txt
age -d -o file.txt file.age
I’ll go with this for now, and look into my max simplicity “future proof” idea later.

The age
spec is clean and simple enough that I was able to implement encryption-to-passphrase since getting home :slightly_smiling_face:. Decryption will take longer to do, just because of the parsing. Code is on a branch https://github.com/rmculpepper/crypto/blob/b-age/crypto-lib/age.rkt\|here.

Note that rage
, a Rust reimplementation of age
, also exists.

That’s awesome @ryanc! In the case of Racket, I actually don’t mind being “tied” to a single language.

…and if it interoperates with the Go/Rust/etc. versions, so much the better.