secrets
This could be something like a password, or an API key, or an SSH key, etc.
Getting secrets between devices in a lightweight, secure way.
This could be something like a password, or an API key, or an SSH key, etc.
Fortunately, this seemed like a pretty simple thing to build, and the security stakes are low since I don't expect or intend anyone else to use it. I figured building it like someone else would use it would be a decent motivation to get it right (enough), though.
It's amazing how you keep teeing up the exact right questions!
Suppose you want to share your Netflix password with your housemate. You open the tool, paste in the password, and press the submit button. It spits out a big URL that links to itself with a huge fragment. You send that link to your housemate, and they see a different version of the tool that, rather than prompting you to input a secret, offers to copy a secret to your clipboard or display it directly on the page.
At that point, your housemate writes the password on a post-it, sticks in on the fridge, and tells you to stop being a weirdo.
Look, it's an aside!
The sharing works by saving your secret on the server, after symmetrically encrypting it on the client-side with a key that's not shared with the server. This is what allows the server to hold onto your secret without actually knowing what it is.
The key is then encoded into the URL that's generated. That is, that big fragment in the URL is the encryption key. Since fragments are an essential part of the URL but aren't sent to the server, this allows the key to be embedded into the shared link and used by the client-side javascript to decrypt the secret. Since symmetric keys are reasonably small relative to their power, they comfortably fit into the URL, even once they're base64 encoded. This also means you get no information about the secret from the link.
The client also generates a UUID to identify its secret, so that the server knows which one to look up, without me having to generate UUIDs in PHP. The specifics of this ID don't matter much - it could probably have even been sequential for all it matters.
Finally, the server deletes the secret before returning it (or after 24 hours). This means that it's possible, if the request gets interrupted for some reason, for the secret to be lost. However, it also means that if you receive the secret, you know you're the first and only person to receive it (unless you're being man-in-the-middle attacked, I suppose, in which case you probably shouldn't be relying on a one-time-pad secret sharing tool I built for my own low security secrets). This also requires you to believe I'm actually doing that and not storing a copy or logging the encrypted secret somewhere. I'm not, but you have no reason to believe that.
For all the client-side encryption functionality, you can read the javascript the tool runs.
Other than that, the only other thing of interest is the way the tool warns you if you've got javascript disabled. The HTML includes an element stating it's required, which is removed by javascript on load and replaced by the interactable components of the tool. This ensures if you see something interactable, the tool works.
Let me tell you one more time, you shouldn't use this.
The tool you shouldn't use is here. Name shamelessly stolen from an internal tool that a previous employer had for this same purpose, which itself was inspired by the use of nitroglycerine flash paper for one-time pads (permalink) in espionage.
Let me know what you think, what fundamental security errors I've made, flame me about my terrible UI/JS, etc. If you're here you probably know me personally but, if not, you can reach me on mastodon.