Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: 100% offline Shamir's Secret Sharing GUI (simon-frey.com)
180 points by l1am0 on June 16, 2020 | hide | past | favorite | 67 comments



Hate to be this guy, but things trying to be like this should implement a CSP with `connect-src 'none'` (and `form-action: 'none'` and `self` restrictions on everything else). Otherwise I can't be assured that the secrets won't be sent off without disconnecting my network interface.


Love you being this guy as this is a very valid point! I am on the go right now, but will ad this in about 2 hours.


The problem with connect-src 'none' is that is does not allow the webassembly to load than (as this is loaded via js)

`Content Security Policy: The page’s settings blocked the loading of a resource at http://localhost:8080/wasm/wasm.wasm (“connect-src”).`

For now I only added `default-src: 'self'; form-action 'none'` to the index.html


And according to HN that only took you 1 hour and 17 minutes (but I guess "2 hours ago" could be rounded down). Way to under-promise and over-deliver!


https://bs.parity.io/#-BananaSplit-shamir uses different approaches to force offline use.


Why not just embed the wasm directly in the webpage?


Funny I came up with the same idea about 10min ago :D It is now directly embedded via a data uri.

This allows to set `connect-src: 'data'`


CSP = Content Security Policy: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP

"To enable CSP, you need to configure your web server to return the Content-Security-Policy HTTP header (sometimes you will see mentions of the X-Content-Security-Policy header, but that's an older version and you don't need to specify it anymore).

Alternatively, the <meta> element can be used to configure a policy, for example: <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">"


You can't be assured that they will send that CSP header or meta tag with every request, either. If your threat model includes this, might as well save the page locally.


Are you saying JS could modify the CSP policy or meta tag after page load?

Suddenly I'm thinking it would be very cool to be able to right-click on a tab and say 'Take Tab Offline' Imagine if it was like a toggle on the tab itself like muting sound from a tab. It would instruct the browser to isolate the tab/process from the network? I'm not sure how Web Workers play into this.


You have no guarantee that the server won't just "if (ip === companyName) { don't serve CSP + serve infiltrated JS }" in the future.


I mean you could absolutely inspect the source for the page, but these things could be modified at runtime by JS, right?

I'm talking about the meta tags. It would be neat to have a toggle on the tab for isolating the content of the page from the network.


You'd have to restrict localstorage and stuff like that too, else they could save data and then send it when they regain network access.

If you have a use-case, or some ideas, there's Chrome bug page for "offline-only PWAs": https://bugs.chromium.org/p/chromium/issues/detail?id=995236


I think the point is that you go to the site, and save the HTML on your local machine, and then run it from there.

It would be amazing if there was a property you could add to the <html> tag to enforce that the browser would prevent any network access or disk writes.

As it stands I think after you save the files, you would have to look into each .js file downloaded as part of the bundle to check for outgoing network requests?

The code is tiny except for vue_debug.js which is 193KB.


> save the HTML on your local machine, and then run it from there

Yes; there is another js Shamir utility that works like that; it requires you to download the html and refuses to run unless it detects that you are offline. :-)

https://bs.parity.io/#-BananaSplit-shamir


> refuses to run unless it detects that you are offline

They could just display the "please disconnect" error for a while, then sneakily stop checking after some date, collecting data every time you forget to disconnect. You'd need to check the code, or never forget to disconnect - the latter is probably a mistake waiting to happen.

Chrome bug page for "offline-only PWAs" if you want to star it: https://bugs.chromium.org/p/chromium/issues/detail?id=995236


Correct me if I'm wrong, but couldn't they just save your secret data to localStorage and then send it off when you load another page from the same origin (a page without those headers)? Or does the CSP of one page somehow apply to the whole origin? I'm not up to date on this stuff.


How do I verify whether or not this is the case? Do I need to check the headers in the network inspector? (My guess is there's no way to check on mobile?)


While SSSS provides information theoretic security, there are a couple of security gotchas. One example is that it leaks the length of a secret unless padding is used. In practice this isn’t usually an issue, since many applications (like this one) use SSSS for sharing fixed-size symmetric keys.

A more concerning gotcha is that this scheme doesn’t produce verified shares (i.e., shares lack integrity). An adversarial or forgetful share holder can submit a bad share and within this scheme, you’d have no way of being able to prove that they did this. All any of the participants would know is that the resulting secret is wrong, whatever that means for the application (e.g., the AES key doesn’t successfully decrypt a ciphertext).


Can't these problems be solved with another layer like signing with a pubkey where the private is thrown away after issuance? And then maybe some error correcting algorithm to avoid forgetful users?


Signing the shards was the first thing I thought of as well. This will completely thwart bad shards from being mixed into the decryption.


For those interested, there's a whole literature on "verifiable secret sharing", and they generally require some substantial cryptographic heavy lifting and provide computational guarantees

https://en.wikipedia.org/wiki/Verifiable_secret_sharing


If you have any algorithm or source at hand I would be really happy to add this!

Or even better: If you got some time spare, feel free to help out with s4 :D https://github.com/simonfrey/s4


> While SSSS provides information theoretic security, there are a couple of security gotchas. One example is that it leaks the length of a secret unless padding is used. In practice this isn’t usually an issue, since many applications (like this one) use SSSS for sharing fixed-size symmetric keys.

I also believe that also in theory, using SSSS + fixed-size symmetric keys gives you all the same security properties of SSSS and no leaking of the message length, assuming that the symmetric cipher you're using is secure. What exactly do you mean by "this isn't usually an issue" (emphasis is mine).


SSSS isn’t always used with fixed-size symmetric keys, in which case length can leak something important. But in practice it often is, since share size increases with message size and that can get unwieldy. So it isn’t usually an issue.


My point is that there is no reason why you wouldn’t used fixed-size symmetric keys which are more performant, prevent leaking message size, and have all the other security properties that you’d get if you just used SSSS.


If you're secret-sharing a symmetric key then you're dealing with computational security anyway, but you do get some notion of integrity for free. As you said, given a reconstructing set of shares you can tell whether all shares are correct, or whether they aren't (but you are not able to identify the bad share). However, if you have additional good shares (enough good shares to reconstruct), then you will be able to identify the bad shares.

You could also use digital signatures on the shares to get integrity for individual shares.


wouldn't an easy fix for verifiability be that you include a list of hashes of every valid share along with each individual key?


Would love to hear other opinions about that, but that sounds like a good idea in my opinion. But still there would be the problem that you do not know which of the shares is the wrong one, as if there is 4 shares and 2 are right, 2 wrong you don't know which ones are the right ones.

Or am I wrong here?



A fun fact is that this is one of only two algorithms in

https://en.wikipedia.org/wiki/Category:Information-theoretic...

The idea is that there is no amount of computational capacity or mathematical insight that could permit an attacker to break this algorithm, even in principle. That contrasts with other primitives which are often insecure given an efficient P=NP solution (guess the right answer and check that it was correct). With the one-time pad and Shamir's Secret Sharing, the attacker has no meaningful way to check whether the guessed answer was correct or not.

(Both algorithms have a requirement for random input, and the information-theoretic security argument assumes that the attacker could never predict any information about your randomness source, which might not always be true if you're running on real hardware. If you're driving the algorithm with the output of a CSPRNG, the information-theoretic security may reduce to the security of your CSPRNG, which is not information-theoretically secure, for example because an attacker who could somehow guess the CSPRNG seed and offset could potentially confirm that this guess was right.)

Another way of thinking about this is the a brute force attack on a security system requires a way to detect when your current guess is right. This is why, for example, the RSA encryption challenges would always have a plaintext starting with "The unknown message is:". This assumption isn't necessarily that unrealistic if you know that the plaintext of an encrypted message is a particular file format. Apparently a huge amount of military cryptanalysis, once governments started building special-purpose hardware for brute-force-like attacks, consisted in trying to find and refine ways to usefully detect when the attack had succeeded, given relatively great uncertainty about the nature of the plaintext. It also appears that many of those plaintext-recognition ideas are still classified (!).

In an information-theoretically secure algorithm, there is no way to detect a successful break of the algorithm because all plaintexts are equally possible and equally likely given only the evidence of the ciphertext. That means that the ciphertext itself doesn't contribute any new information about the plaintext, so there's in some sense nothing to worry about from sharing the ciphertext with an adversary.


Haha, and I was thinking "Wait, is one-time pad the other one?" before clicking! Too bad, since one-time pad is only theoretically secure. Too many ways to break it in practice.


Well, if used correctly, it is practically secure, and otherwise it's not really a one-time pad.


This is really cool! Very small suggestion, I'd put Minimum required shares ahead of Shares so that it follows the m-of-n order.


Nice UX improvement. Will add it

Edit: Added


Shamir is one of the suggested ways to restore crypto in case of death with more decentralized trust. You select 20 friends and give them each one of the keys, then at your funeral 10 or more of them come together to unlock your wallet and execute your will. But it has a big problem: rot.

It needs to be accompanied by a system that ensures everything is still in tact. The system would ping every key holder every X months and have them prove they are still in possession of their key. If a problem arises the wallet owner is alerted to deal with it. Otherwise she gets an all clear report.

The annoying thing tho is now there is a centralized 3rd-party database of all your key holders. Part of the security is nobody knowing who's in on it. Imagine a wallet with $100M. That database starts becoming valuable. So the service would have to be zero-knowledge or hosted, but now you're hosting stuff, and not just any stuff, the most valuable stuff, requiring top security.


The other problem is that the shares must be combined to recover the secret and doing that safely is hard. It's not a problem if the use case is say, protecting the recovery key for my laptop by giving shares to friends. But in the case of bitcoin, who's going to be allowed to see the resulting secret? Might result in a race to steal the coins. So then there has to be more than 1 group of SSS, with each one getting key for a multisig wallet... or some other carefully executed key ceremony... and the more of such things that are required the more fragile the scheme becomes in practice.


I envisioned the keys coming together at the notary's along with the rest of the estate, with a transaction immediately executed to the final recipient. This is a semi-trusted setup after-all. Also the final recipient would likely be one of the key holders present at the ceremony.


I have usually seen multisig as the recommended way, not Shamir.

One Shamir vs multisig article : https://medium.com/clavestone/bitcoin-multisig-vs-shamirs-se...


[removed]


The only thing I don't like about that is that it is dependent on the network. Some cryptos don't have multi-sig for example. It's a full system, you have to be aware of protocol changes and such - Shamir is straight math and works on any type of key independent of the system. Trade-offs as usual I guess.


Timelocked multi-sig is another alternative in some systems. As time goes on the number of signatures required goes down, this setup can be reset every X blocks as needed.

Provides additional security against key loss or malevolent actors at the cost of having to wait it out when such things occur.


Very cool.

FYI the whole page breaks if you accidentally delete the "shares" value or type 0, requiring a refresh to revive it.


Thanks for that bug report! On the go right now, will fix this in about 3 hours!

Edit: Fixed


Aaarg. The save to local file does not work as of javascript fetch not being able to load local resources. Anyone any ideas how to cirumvent that problem. (The webassembly is loaded via fetch())


Yay, got that fixed with data urls :D Now works also as downloaded file.


> You can find the code on Github and this website works completely offline. Save it to your computer (Ctrl+S) in order to not loose access to the s4 in case this website will be down at any point in the future.

I'm also seeding this on Beaker. hyper://467f73aff5af260ab04a4f064fa8cd7fda6f23fed4ff227bc29514c3381a2087/


I've put it on IPFS too. https://ipfs.io/ipfs/Qmdg6io4ZbdRdW92yUjeL2DHhcdNF3jCF2XWwDs...

IDK what Beaker is exactly, but the nice thing about IPFS is that this hash is guaranteed to correspond to this commit: https://github.com/simonfrey/s4/commit/1d169cb33761b57569e52... - it can't be modified (by me or anyone else) in the future.


This seems to be a good fit for IPFS, since it's a single page with no absolute paths.

While Beaker does let me update the source code at that location - you can also link to the current version permanently by adding the version number (46, in this case) to the end.

hyper://467f73aff5af260ab04a4f064fa8cd7fda6f23fed4ff227bc29514c3381a2087+46/


Would you be so kind and further explain what Beaker is?


Not OP, but here's some info.

Beaker Browser https://beakerbrowser.com/

which uses Hypercore Protocol https://hypercore-protocol.org/


Nice work and extra points for being super responsive to bugs/fixes/recommendations from comments :-)

Reminds me of something similar: https://iancoleman.io/shamir/


Yepp I do know about that one, but it is based on an outdated js library :/ https://github.com/amper5and/secrets.js



Are you pinning it on your server, is that how that works?


This is really neat! I found a minor issue; changing the number of shares on the decode panel (after a successful decode) seems to freeze the output; using a recent firefox on linux.


Thanks for reporting! Fixed :)


Love to be this guy, good way to crash the browser. Set share size to 1000+ and Enjoy!


The GUI starts to look quite shitty around 10 shares already. Something I should work on.

The above mentioned 1000+ share problem could only be solved by a limit, but I would be in favor of not limiting users here.

p.S. On firefox it only chrashes the tab


Interesting. But what about ssss?

Also, I vaguely recall that results may be implementation specific, in that shares must be combined with the same app that produced them. So is this implementation compatible with others?


SSSS is Shamir’s Secret Sharing Scheme.

Sort of. Different apps may use different finite fields. The math should be the same as long as you’re computing everything modulo the same integer. It is also possible that some apps may encode shares differently. For example, I’ve seen some apps base64-encode each share where others keep them as integers.


A very minor nit: Your placeholder text begins "What every message", where I'm pretty sure you meant "Whatever message". Initially confusing until I figured out what you meant.


Damn. This should not have happened. Thanks for that note:) Will change that asap

Edit: Fixed together with other spelling mistakes


I am not able to decrypt when I set the minimum shards to 3 out of 5. Works with 2.


Thanks for that report! Is a problem with the javascript. Should be fix in about 20 min

Edit: Fixed


Hate to be this guy, but it doesn't work with unicode.


Thanks for reporting! The encryption actually works with unicode (as it is go) but apparently vue.js does have a problem with it.

Will check how to solve this :D




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

Search: