Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Retriever – Securely share secrets over the internet (corgea.io)
193 points by asadeddin 10 months ago | hide | past | favorite | 99 comments
Retriever (https://retriever.corgea.io/), an open-source research project to help users receive secrets and sensitive information without needing a server in the middle. It works by using Public-key cryptography to coordinate the message sharing between the two devices.

Read more on why we built it here: https://retriever.corgea.io/why.html




People keep reinventing Magic Wormhole, and nobody has really done it better; most of them don't even reach parity.

https://github.com/magic-wormhole/magic-wormhole


But you have to have it installed. I could see this solution being useful for dealing with non-technical users.


There is a Web client at https://winden.app (although it uses different servers than the defaults in the Python CLI, the latter can be easily configured to use the same servers).

However, see further discussion in this article about the difficulties of Web / JavaScript security in this context (i.e. you're depending on the people operating the Web server to not serve different JS on each and every visit).


Haven't found anything better than croc, personally.

https://github.com/schollz/croc


Croc is an iteration of the magic wormhole design. Magic wormhole is more popular. Either is fine.


I know github stars isn't a very accurate metric but croc has roughly 8 thousand more github stars than magic wormhole.


That's fascinating.


I meant to imply that croc is more popular than magic wormhole.


How secure is that, though?


Very. Much more secure (respectfully!) than this is.


I'm curious as to why you think that?

I only took a glance at their "why we built this" page, but it seems sound to me. Also, it seems to serve a different purpose to wormhole.

Wormhole allows you to easily ans securely transfer files between two machines, if I understand correctly.

This is a convenient way to generate a public / private key pair and share your public key with someone encoded in a URL. In turn they can conveniently encrypt a short message using your public key which is also encoded in a URL for sending back over an insecure channel.

Being in the browser and having to trust it is not sending anything online, is not ideal. But on paper the concept seems pretty sound to me. I think it's a cool idea and can imagine it could come in useful.


> Being in the browser and having to trust it is not sending anything online, is not ideal. But on paper the concept seems pretty sound to me.

This seems contradictory. If the main thing that's useful is that it uses URLs/browsers, but using URLs/browsers breaks the security of the system, what part of it seems pretty sound?


I mean the concept of generating a private / public key pair and sharing a public key is pretty sound.

If your browser is compromised or can't be trusted then you have bigger problems.

But if we assume this site can be trusted not to send secrets online (which is easy to verify) and they are not rolling their own crypto primitives in javascript, then the idea is pretty sound imo.

Personally I would use gpg or openssl for this, but it's not that easy for non-technical users.


> But if we assume this site can be trusted not to send secrets online (which is easy to verify)

This would require every sender and recipient to read and understand the JavaScript on every page load, because there’s no guarantee that the server is sending every request the same content. It is in fact not easy, especially for non technical users.

If we’re just assuming the site is trustworthy, the public key crypto isn’t necessary. If the site isn’t trustworthy, the public key crypto isn’t secure, because the site is in a position to compromise the private keys.


Sorry, I got confused. I just looked back at old HN discussions, and it was Croc with the security issues, not Magic Wormhole.


I generally just use GPG.

1. I share my public key (if not done previously).

2. They encrypt the secret and send the result back, all using whichever tools they'd like.

3. Only I (and any additional recipients specified during encryption) can view the secret data.


That's definitely a good way to do it, and if it works for you then awesome! We're kind of doing something similar here with this in a workflow where you don't have to share the key and it requires not technical knowledge of doing this. I actually did this with my dad over mobile phones and he doesn't know how to use public-private key encryption.


I'd argue that using GPG as the sharer of a secret has nearly the same level of complexity when using something like pgptool.org, assuming there is no need to _sign_ the data as well.


Doing cryptography in a webapp and saying the server doesn't know the secret doesn't work, as the crypto code comes from the server without any way for the user to check whether it has been tempered with our not.


The crypto in this case doesn't come from the server. Nothing goes to the server for encryption. It's actually the browser that's generating the key pair and encrypting and decrypting. This is what makes all of this unique.

See: https://github.com/Corgea/retriever/blob/main/js/crypto.js


Right, but how do we know that https://retriever.corgea.io faithfully returns the code in that GitHub repo? We still have to trust corgea.io.


Totally valid concern!

Retriever.corgea.io is actually hosted on Github pages (do a CNAME check to see).

https://mxtoolbox.com/SuperTool.aspx?action=cname%3aretrieve...

You can see the canonical name is corgea.github.io which is the domain for GitHub pages. But, to counter my own argument, does this really prove that this domain is actually pointing to the OSS repo? No, other than we're not here to lie to anyone, I'm happy to show that updates made to the OSS repo show up on Retriever.

Otherwise, you can totally run Retriever on your machine and have peace of mind :)


Right, so you might as well just skip the public key cryptography, which isn't doing anything in your design. Instead, just rely on TLS, and give each piece of content a UUID. Then you can just promise not to read it, the same way you're promising not to steal keys.


You can look at the code in your browser's debugger. It's not minified, and is actually quite simple. You can also watch the network inspector to see that it's not sending data back to the server.


Performing a cryptographic penetration test every time you (or, behind your back, your browser) loads a page is a problematic strategy for deploying cryptography on the Internet.

I think the previous comment came across as snark, but it's not snarking; it's a genuine suggestion. The thing they're trying to build can work, and find users, without the performative cryptography.


Agreed on continuous code audit issue! This is the non-resolvable problem with browser-based services.

But I think the cryptography is not entirely performative, and your suggestion of a UUID KVS is not the same model.

In Retriever's model, as I understand it, Alice generates the keypair which Bob will use to send data to Alice. Alice sends the pubkey to Bob (via URL) and Bob encrypts and submits. Bob then sends a new URL to Alice to decrypt and read. (Not sure why this second URL exchange is necessary, unless it contains the encrypted data?).

Only the original receiver (and Retriever/page host) can decrypt the data. Neither of the URLs are secrets, although possession of the first URL would allow an attacker to encrypt arbitrary messages for Bob, and maybe that's why Bob waits for Alice to send the second URL.

That said, it's a fun experiment but too awkward for anything but ad hoc secret sharing between strangers with no better comms channels. Which is not something I do.


I'm not sure I follow. What is the degree of assurance the cryptographic version of this web page can provide that a UUID and a database can't? Remember, the web page can itself surreptitiously decrypt anything Alice or Bob encrypt or decrypt.


Zero, unless you host it yourself.

Agreed, not practical but a bit more involved (both simpler and more complicated) than a UUID KVS.


Right but that works just as well to determine that some js that just uses ordinary network-layer security to send some data doesn't steal anything.


> we’re not here to lie to anyone

A sound foundation for managing my secrets


lol


We use self-hosted yopass at work. Works great and since the link only works once you can simply send the URL with the decryption key to the receiver. If they can open it, the secret is safe to use!

https://yopass.se/


> since the link only works once

Unfortunately this is an anti-feature for almost all large corporations. There is inevitably a security scanner somewhere that consumes the link before the user can.


You're right, but yopass let's you send the link and decryption key separately. The link is only destroyed if the secret is decrypted, not if you just reach the prompt to supply the key.


That is definitely a redeeming feature!


I don't get it: if you have a canal of communication anyway, why not send the secret directly ? We have many options for E2E encrypted communications, some of which are perfect replacements for whatever you use that isn't. I don't see the need for this.


I suppose generic communication channels have a lot of noise for Big Brother monitors. When someone exchanges Retriever links though, monitors will know that some "secret" is being shared and can focus on potential targets more easily, with a noise filter.


My point was assuming proper e2e encryption, so Big Brother can't know it's a retriever link. It also can't know it's an actual secret


People claim E2E yet unless the code is actually open source your believing in faith.

Call me cynical, paranoid but I do not believe the E2E with WhatsApp truly is. It claims to be, yet now owned by the biggest data mining company in existence. How can I trust that?

And don't give me any "three ticks" bullshit. Show me source.


I never talked about WhatsApp. There are other, working solutions that don't have the problem WhatsApp has.


The source for bash was open for years (maybe even 40) before shellshock.


Remember: no matter how big the improvement, it’s not worthwhile unless it achieves absolute perfection.


You can definitely do that. This is just a different mechanism to do so. Your statement could be applied on any secret sharing system that 1password, Bitwarden, Lastpass have. They have a place in the world, and I'm not sure everyone is comfortable with E2E encrypted comms as a way to share secrets.

The whole idea around this was an open-source research project that people can use day-to-day or enhance to share secrets with a zero-knowledge system. What makes this unique is that it's minimal work to do this with a big level of security that you can run on your own.


Password managers serve another purpose, which is remembering, filling and storing passwords, possibly in a collaborative way. Exchanging secrets are, to me, secondary in functionality.

> and I'm not sure everyone is comfortable with E2E encrypted comms as a way to share secrets.

I'd live to know what would make people uncomfortable with this, because your system is, in practice, exactly that :)

> What makes this unique is that it's minimal work to do this with a big level of security that you can run on your own.

I love that this can be used over any channel, secure or not, but I would prefer if we all just switched to proper secure communications everywhere. In 2024 there is no good reason not to anymore.

And if I take your point and consider self hosting this, then it's much easier and better to install proper secure communication with my peers.

Again, I'm not against the idea of allowing secure exchange of secrets in an insecure environment, but as engineers if we really want to solve problems we should look at the real one: why are communications not secure, and how to fix this. This is not a technical problem, it's a societal one, and the solution might be societal. Unfortunately as engineers we tend to suck on the social level so we don't want to see it, but it's height time we take the plunge.


No, I think the question is: if you're passing the URLs via email, WhatsApp, or anything else, then if that system is compromised then you've revealed the secret.

If you trust that system not to be compromised, then you may as well have just sent the secret plain-text.

In what way or in what scenario does this ever grant you MORE secrecy?


As per the documentation the secret is never shared unencrypted an the private key to decypher it is never ever in the url. It stay in the receiver local storage.


This only means the browser, and the javascript code, are part of the chain. Both of them can also be compromised, have bugs, and leak the secret.


I want an ephemeral channel, with an audit trail of accesses. My regular communications channels provide very nearly the opposite -- they're long-lived, and I can't tell how often folk access them. They might also show history on-screen at times that are inconvenient for security, and I don't know what kind of notifications the recipient has set up.

A tool like Bitwarden Send lets me share a link that references a secret, limit the number of times it may be accessed, and validate out of band (using the secure channel you mention) that the single access I saw was indeed the intended recipient. I can -- and do -- confirm receipt and clear the shared value before putting the secret into whatever system it's intended for.

This seems to have similar properties. I still want an E2E channel for passing the links around, but once the exchange has been verified there's no permanent record of the actual value being exchanged in our chat history.


I'm confused. How do you send the request URL, and how do you receive the encrypted secret?

If the answer is "email, chat, text, Whatsapp" or whatever, them why not just send the secret plaintext?

If anyone can get into any of those systems, then they can easily get your secret from the two urls, so why bother with the encryption?


You can send the URL in whatever medium is convenient. However, if someone gets a hold of the URL with the secret, they will not be able to see the secret. For example, here's a URL containing the secret. Can you see the secret?

https://retriever.corgea.io/#eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJ...


If I glean from the landing page correctly, there will be a private key somewhere in the browser e.g. localstorage. This way the sender can encrypt the secret with the public key of the receiver. Mitm attacks are certainly possible, but eavesdropping is not.


You're correct. While a Mitm is possible, it'll be useless because the actor will have to get access to the private key from the requester'ss browser. They would have to be on the requester's machine


I'm loving it! So simple, yet exactly the thing needed to share a secret quickly in a secure manner over a non-secure channel, e. g. email. Still a fresh idea I've never seen elsewhere. Congrats and thank you for providing this!


Generally a good idea, but it’s implementation is not fully thought through.

It’s supposed to be a secure place where secrets are shared, but it comes with Remote Code Executions that are out of the users control. Multiple JavaScript files are loaded from third party hosts to display the page, that would offer a significant attack vectors to your users secrets.

You should both reduce the code dependency on large, external frameworks, as well as verify the necessary files and deliver them from the same host, that already serves the rest of the page (because you‘re going to have to trust that host anyway).


To be fair, except for vue.global.min.js, all the JS files which OP pulls from third-party hosts are integrity-checked. So unless clients use very outdated browsers that don’t support the `integrity` attribute, the respective third parties wouldn’t be able to start inserting malicious code in the future.

That being said, I agree it’s still a cheap security improvement for OP to control the hosting themselves. (Plus to integrity-check the Vue dependency.)


Hmm.

If we pretend that there are no vulnerabilities today, then the mind turns to what will change in the future.

I tolerate js in the Bitwarden extension because it's necessary, funded, supported and necessary. But Retriever sounds to me like a project that would do better to minimise surface area.


Looks really interesting and I love the name! So, to deploy it in my (trusted) infrastructure, all I need is to clone it and put it on my server? I'll discuss it with my team


Thanks! Yea, that's all you need to do really. It's pretty simple to get it up and running :)


Great tool. Secret sharing always felt needlessly complicated and clunky. I love that this lets you securely share secrets with zero barriers to entry in seconds. No need for "what's your email" or "hey make sure you accept the share on lastpass" or any of that. Just a quick one-two secure envelope exchange.


Nothing new here. Sites like privnote.com have been around much longer. PGP, end-to-end encryption is everywhere now.


The end result of sharing the secret is the same. We didn't reinvent secret sharing. What's unique here is there's no server keeping record of a secret, a link or the parties involved. It's the truest form of zero-knowledge because the data doesn't exist in Retriever. With Privnote if you have the link to the secret, then you have the secret. With Retriever, only the requester has it.


> 2) They add their secret and share the URL Retriever generates.

How do you prevent the URL from becoming something which needs to be kept secret?


The private keys are in the requester's browser. So if anyone gets a hold of the URL, they'll see nothing.

For example, here's a secret I just put into Retriever. Are you able to see it? https://retriever.corgea.io/#eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJ...


This is essentially client side TLS, which browsers cut because the ux was bad? Only now you can backdoor/mitm/typosquat a website, rather than attack the major browsers or the os?

And as I understand it, there's no way to verify you're talking to the right person, so sharing a secret via signal is strictly better?


Share the URLs via Signal, then you have a validated identity, and the secret won't pop up in your notifications or be retained in your chat history.


I don't see how privnote.com is the same as this. Privnote seems to use a database and the links themselves should be treated as secrets as anyone with the link can read the note.


This is great! Would it be possible for it to be entirely serverless by letting the repo generate a static HTML page with no CDN's that you could send to others? It would add a bit of friction to the process, but each party could append the hash to the URL after they open the file.


That's pretty much what Retriever.corgea.io is doing right now actually. It's hosted on GitHub pages, and serving a static HTML page. There's no other code running it. I'm not sure if they're using a CDN tho!


Same idea, as a shareable static html page. It never made it to the front page though:

https://news.ycombinator.com/item?id=38365892


That’s a great idea, I think something like this would work very well as a installable PWA even.


It seems key-pair is generated only once. Could be great to get fresh for every request.


Totally! Someone was kind enough to issue a PR to allow you to delete the private key and generate a new one. We're going to fold those changes in.


A default key expiry of 3 days would be helpful here too, as it would mitigate the threat of someone compromising the endpoint and extracting secrets from browser history.


Could also see an implementation where you generate a keypair per secret that saves a hashid (or just an incrementing integer) that you add to the URL fragment. The original sender's browser can then retrieve the private key in localstorage by that hashid. Now secrets can be kept or deleted individually, or given separate expirations.

The only issue is that you can't magically remove the encrypted data in the URL you sent over, so it's really just removing your _own_ access to the data.


Love it. Always wanted to have exactly this for password sharing. Simple yet secure.


Thank you! Glad that you love it, and hope you'll use it :)


Why bother encrypting the fragment of the URL at all? Anyone who has the text of the URL gets the message, whether the fragment is encrypted or not. Encryption is just obfuscation.

An even better way to do this would be to use a data: URL instead. That avoids risks associated with a compromised web server.

   data:,Put your secret message here.
Even better still: just put the message in plain text on a piece of paper. That avoids risks associated with a compromised browser.

Am I missing something?


> Encryption is just obfuscation.

This is what you're missing. Obfuscation is not encryption, and anyone with access to the encrypted data in the URL would not be able to crack it in a reasonable amount of time unless they know something we don't know about public key encryption and SubtleCrypto's implementation of it.

edit: and the problem it's trying to solve are to reach people that you can't just hand a slip of paper of what you want to tell them.


In this case, you crack the encryption by cutting and pasting the URL into your browser's address bar. Navigate to the link, and you get the decrypted message. It is encryption as theatre. Non-functional encryption. Encryption that hides nothing.


No, only if your browser has the right private key.

Let's say User A goes to the Corgea site. Their browser generates an RSA keypair, and appends the _public key_ to the URL, which is supposed to be visible.

When User B accesses that URL, User B's device generates an RSA keypair, and encrypts their message using User A's public key and User B's private key.

User B's generated URL will now contain User B's public key and the aforementioned encrypted message. User A decrypts using User B's public key and User A's private key.

tl;dr: Each browser client generates a keypair, and their private key is never exposed. You only ever encrypt/decrypt with _your_ private key, and someone else's public key.


This presumably uses something like Diffie-Hellman[0]. Getting the URL isn't enough to decrypt the message. Even if you intercept 100% of the data passed between the two users, they still end up with information that you don't.

Now if you intercept and replace the URL, they may be in trouble.

[0] https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exc...


I guess technically they don't have information you don't have, but they have it in a usable form—e.g., they have two prime numbers and you just have the product.


Interesting. I guess the only weakness I can see is that there is no way to know that a request genuinely comes from the person you think is requesting it.

On the one hand, that is down to how you send and receive the URLs. On the other hand, it doesn't make it clear that you should pay attention to that and that it provides no identity authentication.


That's a really interesting perspective. I thought of the anonymity piece as a feature more so than a limitation. For example, you want to share something between two people, but want to "burn after reading". This way no one can associate the message to the two users or get access to the contents. The requester can always clear their local storage of the key. For example, it would be really useful when sharing information between a whistleblower and a journalist. Identity comes from the medium you share really in this case.


Also an interesting perspective. I didn't think of the lack of built in identity authentication as a feature.

I guess my only point is that it should be clear that's how it works so people can take appropriate precautions in either case.


That's a great point. Definitely a human factors improvement that should be implemented.


Would like to give a shout out to LANDrop (not affiliated) if the users are on the local network. I use it. It's very good at saturating the link bandwidth and traffic is guaranteed not to exit the firewall.

https://github.com/LANDrop/LANDrop


great, my browser history is going to be full of secrets now


Your browser history will be full of URLs that only your browser can access. A contributor was kind enough to build a delete function for this to wipe the private key and generate a new one. This would render all those URL's useless. We'll be merging that soon.


Sort of. Malicious browser extensions could look at history and look at local storage before the key is deleted.


A malicious browser extension can steal all sorts of secrets. Is there a unique weakness here in the linked tool? Otherwise, this seems similarly vulnerable to everything else on the web.


How to I know this isn't a honeypot? To build something like this, I'd build it against something people already trust. Since here everything is new, it's difficult to want to paste anything into it.


I totally understand that concern, and I'm pretty security conscious too my self. A few things, you can check the console and network logs while you're interacting with the application. You'll see we Retriever doesn't send anything to a server. If that's not convincing, you can also run your own instance of it and see it doesn't send anything.


Shameless plug: https://bobtoalice.com is a one-file html program to do the same. It can handle files, too.


I will not use this. It loads too many third party domains. It has a tracker. Something like this should not be this leaky IMHO.


Minor nit: retriever is misspelled

> Retreiver lets you request secrets from anyone without any of the data going to a server.


Thanks for sharing that! We got a couple of PR's from very kind folks to fix that. We'll merge them soon.


"Without needing a server" but both parties have to visit a Web ... server ... to do the exchange. So there _is_ in fact "a server in the middle".


this is bad, really bad.

the sender themself cant even read the returned message from a private window. its just another webapp that invades and disrespects privacy.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: