Show HN: Send private messages over a public channel
plaintext.worldThe other day I was on github assisting a compiler developer replicate an accidentally-quadratic observed behavior in generated code and was asked if I was willing to privately share my full source code with his company. While that was ultimately unnecessary as it was easy enough to find a simpler example, it did get me wondering about how exactly was I going to do that:
1. github does not (to my knowledge) allow private messages
2. all communication had thus far occurred on the public record (or at least Microsoft's version thereof)
3. my peer did not publish any contact information in his public profile, and out of respect for his privacy I did not look elsewhere
In yet another case of life imitates art imitates life, while I was building this, another developer on this very forum was complaining about not being able to set up a public "dropbox" on the internet in the context of receiving bluesky invite codes which, according to them, were being immediately redeemed by bots. I can't speak to that, but their structure does seem to make them easy to regexp against.
My objectives were to build something that:
1. provides reasonable security against doxxing oneself to other participants
2. runs just about anywhere, even without an internet connection
3. requires no setup beforehand; since this turned out to be impossible, it was later relaxed to "no installation, but might benefit from it"
4. is easy to audit: no external dependencies other than the standard library
What I ended up with was this ~35KiB blob of js + html + css which (I hope) can be broadly summarized as "PGP for people who don't get invited to key signing parties". It is reverse-proxied via Cloudflare (I have a great ISP, but my aging homelab server probably can't handle any significant load) at:
<https://plaintext.world/>.
If, for whatever reason, Cloudflare is a part of your threat model, the shasum -a 256 for the uncompressed file is: 153e8022213bc565b5b914a263162920a6039251dd6da5a77b3a37f35de9b1a3 /var/www/html/plaintext.world/index.html
You'll find most of the relevant technical information on the page itself, though you may have to view-source: in the rather likely event that I've omitted something from the manual.Since this is a technical, VC-backed forum, I'll add a couple more private FAQ entries that may be of interest to some of you, in exchange for the potential of free publicity. Due to HN posts being limited to 4k, you'll find them as a reply by yours truly. I've being building something have similar functionality recently, thus have the underneath tech stacks in mind the moment I saw the title, (webcrypto: ecdhe, kdf, aes/gcm), further glance into the source code seems legit to me. My only nitpick is for service like this, the shared private key shall be short lived one time using, storing into localStorage might potentially be a foot-gun with low ROI tho. Thank you for the impromtpu audit. I agree that localStorage is overkill for the discord use-case, but wanted a bit more leeway for async forum posts. I might tweak the UI to let users explicitly opt into no-storage operation, though now I wonder whether opening it in incognito is the correct UX approach for that behavior? btw, the name of your project reminded me... I've tinkered with similar before, and I always liked the name "planecite" or any pun related to "hiding in plain sight." I'm not gonna do anything with this, so you're welcome to steal it. :) That said, I do like plaintext.world, and I think .world is a great TLD and conveys the same idea (an ideal world where everything is ostensibly in plaintext). funny you should mention that I initially wanted to go with inplainsight dot net cause that felt more fitting, but that's parked and the owner won't let it go for less than the low 4 figures, which was outside my budget for a hobby project I'll send it to you for $300 to my PayPal! jk jk :) it's not mine I swear > Did you learn anything while building this? My main takeaway is that, for all of its footguns, React has solved a lot more problems than it created: Even for this rather simple app, the number of invariants that need to be preserved is large enough that doing jQuery-style UX feels like hand-writing assembly. I know from other projects that React's performance is quite a thorny issue, though I now wonder if that's because we're treating it as a library (as advertised) when instead we should maybe treat it as an optimizing compiler for a far too liberal language (there's only so much you can optimize when some <script> you have no knowledge of can pull the rug). I've also learnt that post-html5 web specs are still annoying, inconsistent or downright missing. I guess that the committee is mostly happy with that outcome but it's almost 2024, can we get TypedArray.to/fromBase64() already? > How do you plan to monetize it? I don't, not really. Pushing ads, even if it could be done without compromising security, might trigger paranoia in some users for example when the interested in private communications data point leads to the user seeing ads for other encryption solutions, some of which may be formulated as they're always watching you!. On a tangential matter, I'm currently looking for contracts. Send me a message if you like what you've read and are willing to retain LLC external contractors (US east coast or EU time zones). My services are not cheap, but (I like to think that) they are top shelf. > How do you plan to keep this running in the future? It's pretty cheap as there's no real infrastructure to speak of. All cryptography is done in the browser and while there is a server, it is only used to deliver the static html page (~12KiB when gzipped). Most of the distribution cost is currently offloaded to the proxy provider and while they are well within their rights to pull the plug at any time, my current choice has a proven track record of doing the opposite for the internet equivalent of public infrastructure: <https://blog.apnic.net/2021/06/17/how-a-small-free-ip-tool-s...>. Other than my time, the only thing I've paid for thus far is the domain name, and I can likely personally afford the renewal fees for the foreseeable future. > You mentioned repudiation. What's that about? Because all secrets are deleted upon (successful) use, both parties can claim to have no knowledge of any secret exchange since there's no hard evidence that can pin them to it. They can argue that either their respective platform accounts or their user agents were compromised and those statements are irrefutable without further evidence. That being said, the exchange itself is part of the public record and may (I am not a lawyer!) constitute reasonable suspicion for an officer of the court to issue a warrant that could lead to the discovery of said evidence. > I want to buy you a coffee, how do I go about doing that? Accepting donations is something that I have considered, but have currently decided against because profiting from this feels unfair to the proxy. While this is subject to change in the future, it will only do so if the projected donations can cover the distribution costs (e.g. via a paid plan or self hosted).