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.