How to store encrypted data in SoundFlow
From a different thread:
With that said, does Soundflow have an encrypted data store where users can store tokens/secrets/HTTP endpoints? The tricky part would be sync'ing these values across workstations and making sure that these never make it to the Soundflow package directory.
from @ryan
- Christian Scheuer @chrscheuer2019-03-12 14:45:04.839Z
I believe the best way would be to do this via complete end-to-end encryption with the key being derived from a user supplied key phrase or file, which never gets stored in the cloud but only locally on the computer.
This type of end-to-end encryption would make it possible to opaquely store all values in our existing data stores and make it unreadable for anyone who doesn't have the keys.What SF needs to enable is simple access to symmetrical and possibly also asymmetrical encryption callable from Javascript.
Since the encryption/decryption would be running locally, the servers and the world would only ever see the cipher text.Please lmk if you have any preferences for algorithms here.
- RRyan Frias @ryan
I agree with you here. AES-256 would be great!
- In reply tochrscheuer⬆:Christian Scheuer @chrscheuer2019-03-12 15:46:24.805Z
I've made a starting implementation of this.
First you'd generate a secure key, like this:
globalState.key = sf.crypto.aes256.generateKey({}).key;
For this little walkthrough, I'm just storing the key and cipher in the globalState object.
globalState
is available as long as SF is running so is useful for testing across different commands.
You'd normally store the key in a file on disk or on a shared network drive (for example via sf.file.writeText) - and storing the key might be something you'd just do once for the entire org.To encode data, use the
sf.crypto.aes256.encrypt
action, like this:var someText = prompt('Enter plain text'); globalState.cipherText = sf.crypto.aes256.encrypt({ key: globalState.key, plainText: someText }).cipherText;
Again, I'm just storing the cipherText in globalState. This would typically be sent to the cloud etc.
And then to decrypt (fetching both key and cipherText from globalState)
var plainText = sf.crypto.aes256.decrypt({ key: globalState.key, cipherText: globalState.cipherText, }).plainText; alert(plainText);
Christian Scheuer @chrscheuer2019-03-12 15:48:54.668Z
We would probably add methods to our cloud realtime datastore to do this conversion automatically at one point, but since the cloud methods work on entire JSON graphs we would probably start by having the user control that themselves to not make things overly complicated at first.
With the above functionality present, it should be trivial to create for example a key/value datastore with thesf.data
namespace. I'll leave this for a separate discussion though.- In reply tochrscheuer⬆:
Christian Scheuer @chrscheuer2019-03-12 15:51:26.577Z
Note: These methods take care of creating an IV and storing it with the cipherText so it's retrievable for decryption. This approach makes it simple to use the generated key without the need for the user to hang on to the IV. Smaller API surface means less room for user errors which is crucial for cryptography.