Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Portable Secret – How I store my secrets and communicate privately (mprimi.github.io)
1290 points by mprime1 on Dec 21, 2022 | hide | past | favorite | 376 comments



I'm a security professional and this looks like a great tool for OP's use case, especially with strong passwords and great password hints. I think your secrets are well stored - unless your mother stores the password to these files insecurely, a problem that is not new to this solution.

This also applies to most if not all challenges mentioned by other posters. Take phishing for example, at the moment all methods to exchange information of interest that are at the same time user friendly are relatively easy to phish, be it email, discord or WhatsApp.

I still wouldn't store "top-level secrets" in here and upload this to a cloud drive and forget about it. Someone smarter than me could spot a bug in your code (or the API's code) in a year and that renders your solution vulnerable. A browser's implementation of the API could be flawed in a particular version. Someone adversarial to me could bribe a number of people to get answers to 10 different password hints. There are some other scenarios that are implementation specific, I'm sure.

All in all, great tool. I hope you find more users if you are looking for more! :)


We use a very similar system at work when placing files on removable media. Normally, any files you move from a work PC to a flashdrive are encrypted and cannot be decrypted unless the drive is put into another work PC running the same security software. However there's a feature of the software that still lets you move files to off-network PCs that works just like this. Your files are encrypted like usual but you can use your own password and there's now an html file included that contains all of the necessary crypto libraries. You open the html file on the other PC, type in the password, and it decrypts it for you and can re-encrypt it if you'd like.


Thank you for the insightful comments.

Not looking for users TBH. :-)

re: bug in the vendor implementation of cryptography. Doesn't this apply to everything you encrypt?


I think the parent comment is talking about a defense-in-depth approach: if crypto is your only defense against a worst-level outcome, you don't have any grace if your adversary can exploit a crypto weakness. With perimeter defenses you have a little more leeway in responding to eg leaked keys or other problems. Also presumably you know who might have retrieved the encrypted data, and therefore who might be doing offline attacks against the data.

There are totally use cases where having encrypted data at publicly retrievable, even well-known URIs makes sense, but there are other use cases where you want some level of network security as well.


Anytime.

Re your question: of course. There are some things to consider:

1. These files do seem to have some persistence on either the sender’s, the recipient‘s or a shared machine. With long persistence in several places, the risk of unwanted access is being elevated. (Cloud instances and identity providers get popped, machines get viruses, etc) 2. As mentioned by a sibling comment, the encryption is your only layer of protection. 3. Browser’s are probably one of the top three targets of vulnerability researchers at the moment. They were at the number one spot 2-3 years ago.

When a vulnerability is found in the implementation, the missing controls become a problem. Your quote about 0days is certainly correct. At some point it won’t be an 0day anymore though, and it’s hard to convince people to rummage through their hard drive to delete some files.


> Someone adversarial to me could bribe a number of people to get answers to 10 different password hints.

OP's hints are probably more generous than they need to be. (Indeed, knowing that password is name + flower + name + two-word-thing, plus the fact that there is no limit to the speed you could brute-force this, means that someone could probably make a custom dictionary and break this in a couple days.)

But you can easily have hints and make it harder. In Evernote I store a few passwords to things, and the hints are more opaque ("grey" refers to my old grey cat, for instance) but they're also all prepended with a 15-character master password that changes in subtle ways depending on the service they're used for. This isn't in the hint, it's just in my head.


>knowing that password is name + flower + name + two-word-thing, plus the fact that there is no limit to the speed you could brute-force this, means that someone could probably make a custom dictionary and break this in a couple days

Off topic, but in principle a sufficiently expensive key derivation could guard against this, right? Is there a reason why it isn't done? I wouldn't mind waiting a few minutes for my identity document to decrypt if I hardly ever access it. In that case the usability benefit of a fast key derivation algorithm seems minor.

It wouldn't even be hard to expose this functionality via a user interface -- say when a user is setting up a Portable Secret, let them click to select a security level between "low security" and "high security", where each security level corresponds to an estimated number of minutes it will take the secret to decrypt on a modern PC. Seems like it would make intuitive sense to grandma.

And with regard to the software vulnerabilities topic discussed above, as long as we're waiting a few minutes, we might as well make use of multiple key derivation algorithms in case one or more of them is shown to be weak.


I have things like this in my head too and I wonder if I’ll forget when I get elderly.


or bonked on the head. it's a scary thought.


I've thought of that too, perhaps I write them down in a sealed envelope and tell my spouse or kid, only open in an emergency. I feel it's pretty certain these non-software engineers in my family have less security notions than I do, so I have reserved some passwords that are in my head.

I signed up for the gmail "I died, here is my account" option.


I don't know if I should do that gmail thing or not...afraid it'll mess up or I'll forget about it.

Can the spouse resist opening an envelope? I don't know. Maybe I just hide it in our files and hope she finds it if I die, but not before.


Do you trust Evernote? I think the employee are able to read private notes


Yes, they can. Evernote, the company, really pushes their "everything is encrypted" mantra, but you have to really push them to get them to admit that it's only encrypted in transit. On their server storage, the data is encrypted using their key, so if someone stole a drive or a disk image they wouldn't be able to read it, but any number of people at Evernote would have full access to anyone's data.


That's why my hints are opaque and exclude the long, mutable master password.


If someone did actually find a vulnerability, I would assume they are pretty good at what they do, but wouldn't they just wait for adoption and let this bounty inflate higher before draining it?


Shameless plug: http://hypervault.github.io. Hypervault is a single HTML file (with no external dependencies) which allows you to encrypt files, and it outputs a single html file (with no external dependencies) with a copy of the hypervault decryption software packaged together with your encrypted data. To unlock a hyper vault, all that is needed is the encryption password (entered at creation time).


Very cool, and better UX!

Added you to the project README.

(I got a bunch of compliments for this project today, I hope you are enjoying seeing them too given we had the same idea)


Unsolicited feedback: the contrast is killing me. It doesn't take much html/css to make a web page a bit more user friendly. See screenshot -> https://drive.google.com/file/d/1qNaBhoH2FsGlScvFmeXk9aZXouo...


That's it. I wasn't sure what it was, but something hurt my eyes when I opened it!


The source code mangling (uglification) is really doing a lot more harm than good.


Interesting... on 2022-12-13 the bounty has been claimed! Just a few hours after mprime1 shared the project in a comment on HackerNews, someone managed to drain the BTC.

https://github.com/mprimi/portable-secret/commit/3b22d2b42ba...

I'd love to hear more about this.



Ah, that makes so much more sense. I had thought after looking at the wallet: https://www.blockchain.com/btc/address/bc1qd2jkf8lxp5d3y50gf... that it was "scrambled/tumbled/anonymized" by the attacker.


No, they just changed it themselves? They sent from that old wallet (https://www.blockchain.com/explorer/addresses/btc/bc1qd2jkf8...) to the current wallet (https://www.blockchain.com/explorer/addresses/btc/bc1qpwq8lx...) ?


I don't see any code changes in the commit history after that.

edit: oh, it looks like it wasn't actually drained.


Right I'd love a post-mortem on it!


Postmortem:

- Bitcoin is hard

- Wallets come with sophisticated anonymization built-in

- Don't create the bounty wallet 20 minutes before posting on HN (if that snafu had happened today while this post was on the front page, I would have looked pretty stupid)


Cool project! This stuff is all possible thanks to the SubtleCrypto API (https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...), which became widespread in browsers in the last ~5 years. It's so great we don't have to use weird libraries (some with pretty gnarly side channel leakage) to do cryptography anymore.

It wouldn't be that crazy for the browser to do the encryption part for me, right? Like, what if in the 'save this page' dialog my browser actually did the encryption, and then generated this 'self-decrypting page' for me if I checked a box saying "encrypt with password"? Would be a nice way for regular non-technical people to encrypt things and send them to each other.


What level of confidence is there that all this API will work exactly as it works now after 30 years? I am concerned that they might at the very least deprecate and remove the ciphers used to encrypt my data in portable secret. Worse what if they remove support for the API? Then I am going to have HTML files with data I cannot decrypt anymore, right?


I don't know about 30 years but AES-256-GCM has implementations in multiple programming languages, e.g. it can be decrypted dependency free in Node.js >= 10. If browsers were to drop support (unlikely imo), there should be multiple options for decryption provided one has access to a runtime supporting AES-256-GCM decrypt. An older WASM'd version of PHP or python may even work.

I have no use for this myself but wrote a quick Node.js script which accepts an html file created by this tool and prints messages to stdout or saves a file to decrypted.ext: https://gist.github.com/andrewmackrodt/e6a5a2ea7b22d74102ba7... - it's dependency free (no npm install dependencies) and tested with Node.js 10 and above.

e.g. "docker run --rm -it -v "$PWD:/app" -w /app node:10-alpine portable-secret-decrypt.js example-image.html"

When used with the Bart's drivers license it will create the decrypted file as decrypted.jpeg to the cwd.


You can always implement the decryption yourself, it’s not particularly difficult. But realistically, software doing so will continue to exist for a long time, and there will be extensive transition periods to migrate your secrets to a newer algorithm.


FWIW, symmetric encryption like AES-256 GCM is just astoundingly unlikely to be “broken” in the next ~20 years (or perhaps ever…)

There’s more of a case for public-key stuff changing, but this doesn’t rely on anything public key.


If you’re worried about “30 years from now” you might as well store the decryption software alongside the message


And there are ciphers who have lived much longer than 30 years...

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


Most cryptographic algorithms worth their salt have a pseudo code implementation on Wikipedia too. Just save the article along with the encrypted payload, bam future proofed :)


Web APIs are far more stable and reliable than you're giving them credit for. Do you have reason to believe that this API will break?

No points will be awarded for citing jank that is a direct consequence of depending on proprietary, experimental, or non-standard stuff (like, "well, my Flash site worked in 2002, but now it doesn't").


I suppose that's a different implementation of the same 'hack' demo'd here, with the encryption carried out by an extension.


This is a really cool project!

One thought that I have: would there be an issue sending this file in an unsecure context where MITM is a possibility? Alice sends Bob her HTML file over an unsecured medium, and Jane intercepts this traffic, and gives Bob a modified HTML file that will report the password back to Jane. Jane can set it up so that the browser still displays the local file as it's source, but has an HTTP request in the background phone home back to Jane's server.

My scenario only works if Bob doesn't inspect the page source before entering their password, or if the modifications are sufficiently obfuscated.


> Jane intercepts this traffic, and gives Bob a modified HTML file

I’d expect better from Jane. This is the kind of shit Mallory would pull.


Or Eve. But Jane, I would have never thought.


Yes. This is essentially a binary with the browser acting as the OS. And if it's hosted on a server it's a binary which may change at any moment. There isn't even a mechanism by which to freeze its hash and alert you if it changes - a browser would have to provide that functionality.

To be fair, the exact same problem afflicts something like Protonmail, so calling it a toy may be too harsh.


Maybe it could put a checksum in the url?


100% agree. This is why I’m always a bit dubious of in-browser decryption. At any moment a little extra snippet of JS can be added to stealthily leak my secrets. There’s no great mechanism to ensure the JS I’m running is always the same JS I ran before. Compare this to a desktop app where I always know I’m running the exact same binary I ran last time. (And if I’m not then I’m probably already pwned anyway)

For this persons use case though, assuming they’re not a person of interest to any “threat actors”, I wouldn’t be too worried.


This isn't a 100% solution but you can pin external JavaScript includes in HTML using subresource integrity (https://developer.mozilla.org/en-US/docs/Web/Security/Subres...).

This doesn't help if someone can mess with the HTML though.


It may be too much for moms, but maybe the html document includes the content, but a chrome extension does the work and presents the secret in the extension popup.

- attack surface area drastically reduced. only one MITM matters now, the extension installation - requires great extension UX, to help dads know where to click

less portable than just a document, but perhaps a nice middle ground


> too much for moms

I assume you are referring to the OP's post there but I did a double take because I know some extremely technical moms.


It's important to be precise and clear-thinking when articulating problems, lest we identify the wrong one but believe it's the right one.

Your issue is not with the program being in-browser, but rather it being an online one that gets ~continually re-fetched and immediately trusted without verification.


One counter-measure to this is to run the decryption without internet connection. This is easy enough to explain to a hypothetical non technical mother.


Yea. The html must have signature and Bob has public key of Alice to verify ... and we here again. :)


It looks like the plaintext is being padded so that its length is a multiple of the block size [1]. I can't find any resources that say you need to pad a message before encrypting it with AES-GCM though. The official examples from MDN [2][3] don't pad the message before encrypting. The source code links to a wikipedia article that states that padding isn't necessary for counter mode, which the code is using (GCM is Galois Counter Mode)[4].

[1] https://github.com/mprimi/portable-secret/blob/6efdb4618216f...

[2] https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...

[3] https://github.com/mdn/dom-examples/blob/main/web-crypto/enc...

[4] https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS#5_....


GCM doesn’t require padding (the calculation implicitly pads internally), unless you want to hide the length of the plaintext, as the resulting ciphertext will have the same length.


If anyone is actually going to use this for their top secrets, I can find two things to be aware of.

* When you decrypt then close the tab and open the tab again via the recently closed tab, the password is still there.

* Browser extensions could read the contents of the webpage.

So if anyone is going to use this, they should do it in a "clean" incognito browser without any extensions.


For me the biggest problem with a setup like this is complete loss of access to my secrets. The crypto functions supported by browsers may change in future. A cipher algorithm used to encrypt my secrets may get deprecated and removed by the browser in future. Then I will be left with a bunch of HTML files with data that the browsers cannot decrypt anymore.

GPG or vim -x might be much better choices for secrets that need to be decrypted many years from now.


> For me the biggest problem with a setup like this is complete loss of access to my secrets. The crypto functions supported by browsers may change in future. A cipher algorithm used to encrypt my secrets may get deprecated and removed by the browser in future

These are NIST-recommended algorithms, they'll be around for a while...


Make sure to read this before using vim for anything crypto related!

https://github.com/vim/vim/issues/638

To sum things up, the Vim maintainers are totally ignorant on the topic of cryptography, but what's worse is that they are highly stubborn and refuse to accept their ignorance while ignoring valid criticism from people who do know. This combination of traits does not mix well with cryptography, where doing things correctly is extremely difficult but also extremely important.

I am not totally sure whether this specific issue has been fixed since I last checked this out, but at the time Vim's encryption was totally broken and should not have been used at all.

I am not too familiar with Vim overall, but Emacs file encryption uses GPG to do all of the important stuff, and just provides a nice interface to that. I imagine Vim has something similar available at least as a third party extension. Letting something like GPG or Age handle the important stuff is a much better way of handling this!


I can't for the life of me understand why people haven't just switched to Neovim. Sure fine vim might be what's on your server but for your actual personal development work it's, to me, better in every way.


My main hesitation is that I like being able to drop my vimrc anywhere and have an (almost) identical editor experience, rather than having to maintain one config for vim and one for neovim. Been meaning to try neovim out though!


You can source your .vimrc from neovim if you’re interested. I’ve been separating plugins based on the environment they depend on as well.


All of these crypto functions have many implementations in every popular programming language that return the exact same bits no matter which implementation you use. As long as you have the keys (which is a serious issue) and someone remembers which function was used with which parameters the risk of "will be left with a bunch of HTML files with data that the browsers cannot decrypt anymore." is not even on the same scale as getting hit by lightning but rather on the same scale as getting hit by lightning during clear weather in a deep basement.


I remember a few years ago on Discovery Channel, there was a documentary about people hit by lightning. One was hit by lightning 3 times, all 3 times on forehead, and survived to tell the story on record (you could see his forehead having very clear view of its underlying sanguine vessels as secondary effect).

But one story that particularly stood out was of a woman who was hit by lightning during clear weather, inside the house, through the water pipes - she was cleaning dishes at the time. So your scale might be still too small.


GPG for sure, be very careful with "vim -x" as that's the only implementation of that encryption scheme, not supported in neovim anymore (and I've found security issues in it: https://dgl.cx/2014/10/vim-blowfish, "blowfish2" is just ok, but it's frankly still there to not break people's workflow, I would think very carefully before using it).

Annoyingly this technique uses AES-GCM (which is good!) but OpenSSL's command line tool can't cope with it: https://github.com/openssl/openssl/issues/12220

It would be nice to have a command line tool to extract these files too, then you know the implementation is correct. (Blowing my own trumpet but my very old project https://paste.sh does this.)


The algorithms are well-documented and not difficult to implement (for the purpose of decrypting). The only real risk I would see is for a post-apocalyptic future when that knowledge has somehow become lost or inaccessible. And that’s assuming that any of the secrets would still be relevant then.


Standardized web APIs are very rarely removed. Backwards compatibility is a huge priority for web APIs, and cases where they're broken are rare. It's very hard for me to even think of a web API like this that browsers have ever made incompatible changes to.

The parts of the web that get incompatible changes are generally stuff like nonstandard plugins (Flash being discontinued) and TLS (which isn't relevant if you're keeping some HTML file saved locally). Browsers bend over backwards to keep existing HTML/JS content working.



That page supports my point! Most of the things in that list still work in browsers, and the few things that don't still work look like they're all things that never got standardized to begin with.


A neat feature of this would be to have the source of the html include instructions for decrypting the data outside the browser using command line tools for just this scenario.


Looking at the HTML/JS code does tell you how to implement decryption in a different language.

That's because it only uses NIST recommended encryption, which is baked in or available in most languages.


Yes, but making it really easy by giving the exact openssl (or whatever) commands would be super useful if you needed to do it.


> The crypto functions supported by browsers may change in future.

Legacy versions of Firefox should be available in some archive, nevertheless. For additional security, you may use them on an air gapped system to decrypt our secretes. You need to trust the archive, though (as you need to trust the browser, now).


The web is probably among the best platforms you can bet on. Browsers are super slow to deprecate/remove APIs and it'll be pretty easy to install a browser from today in 20 years.


The crypto functions supported by browsers may change in future.

Could those crypto functions built into the browser be replaced with JavaScript implementations?


Yes, they can. There are libraries already doing that. And while slower than the native implementation in the browser they are still good enough for this tool. So fork the sources of this project and implement in JS those API crypto the browser is using and you're clear to go without relying on them.


You encrypt them again with the newer algorithm?


Just download an older version of the browser?


Ok so in similar manner. Please download Microsoft Silverlight now, only from official MS source. No other source is allowed. Go.

Funny thing, here in EU country, there are government apps which stills require MS Silverlight. Nice right?


To be fair that is not a browser. That's a plugin.


Aside q - can extensions access local storage for a specific domain?


They can when you visit that domain, and they can make you visit the domain, so I guess yes.


This has some desirable security properties, but I would like to see more analysis on the security side (not just: is secure or is not secure).

Passwords:

- Easy to memorize. Pro: Does not rely on a device, can be recovered if devices stolen.

- Easy to phish. Con: Attacker can use a look-a-like page, click-jacking, and pixel extraction (frame stealing) attacks to get password & secret.

- Easy to brute force. Con: Relies on human adherence to password best practices to maintain sufficient entropy. Learning from industry that this does not work in widespread adoption. This will work for certain power users.

Cryptography:

- Uses current state of art algos. Pro: Resistant to access by known methods.

- Will become obsolete. Con: Eventually the secrets will become exposed due to advances in crypt-analysis. Mitigation: Don't store anything to remain secure for decades, shorter lived is okay.

- Secrets are encrypted once. Con: Any issue (there have been many) in WebCrypto implementation at time of encryption can not be fixed by browser upgrade (because of secret caching).

- Secrets can be extracted from page and cracked elsewhere offline. Note: Security features such as timers, throttling, guess limits can not be enforced. They must be implemented e.g. in PBKDF.

Client Side Security:

- Cached objects. Note: For example a web page with browser vulnerability can walk JS objects and get existing secrets. Browser may also cache secrets, passwords, inputs, images to disk where they are not protected.

- Web Browser WebCrypto and Same Origin Bypasses. Pro: Browsers have updates and are constantly being improved to enforce security model. Con: The direction the W3C goes in future (tens of years) is not certain and security model may change. Implementation issues in browser web APIs and Same Origin (common) can put secrets at risk.

- Secret hosting. Con: Hosting content on other servers (e.g. github) may not allow management of access control. For example hosting on one subdomain could now or in future allow JS on sister pages to interact with page and the resources loaded, enabling side-loading attacks in JS. This may not be in control of victim if they uploaded their secret to be hosted by another party.

- Trusted hosting. Con: Any untrusted source of HTML can steal the secrets, e.g. by serving malicious javascript along with the secret. This means the security of the hosting party and trust in the hosting party is required. (Note: this con was added in an edit)


Thank you for the comment and thoughts. Agree with most, disagree with some (easy to brute-force?), but I wanted to comment on this in particular:

> Easy to phish. Con: Attacker can use a look-a-like page, click-jacking, and pixel extraction (frame stealing) attacks to get password & secret

This to me is the most glaring "vulnerability". i.e. I use this to exchange letters with my friend Bob. Now someone impersonates me and sends a fake 'PortableSecret' to Bob that siphons out the actual password.

Clearly this is a valid vector of attack, and one I made no attempts at defending from.

The thing is... this won't happen. If I'm dealing with an attacker so sophisticated to pull this off, it's likely they have 1000 other vectors that are more effective and dangerous.

I have to keep reminding myself this is a real vector, but the fear is irrational.

As they say at DEFCON to people too concerned using their devices: "Nobody is wasting their 0day on you".

I don't think I'm a target valuable enough to attract this kind of attacker.


I agree that each person/organization should look at the security properties of a system and assess their risk against what technology is appropriate. It's entirely reasonable that as a non-targeted person with low value secrets, many of the attacks here don't have ROI for a potential attacker and as a result are neither likely or impactful.

What's important is that other persons and organizations who may be targeted - that they choose what technology to use, knowing what kinds of attacks are possible. For example a human rights activist might very well be targeted by phishing attacks and choose not to store secrets by this method.

I am just trying to enumerate the properties so that persons/organizations can evaluate a match to their use case. I don't believe any system is perfect for all use cases and I don't hold any system to such a standard.


The GP comment about "easy to brute force" must be read in context with the remainder of the comment about "easy to brute force":

"Relies on human adherence to password best practices to maintain sufficient entropy. Learning from industry that this does not work in widespread adoption"

The GP's statement can be boiled down to: "users will choose poor passwords" (as in Password1!) because it has been shown time and again that "users will choose poor passwords" if left to their own devices to do so.

The 'easy to brute force' part then comes in as "for those users who choose poor passwords, this rig linked below will brute force their passwords pretty quickly":

https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a27...

Note that the above performance page is a few years old, updating it for 8x of a newer Nvidia GPU should result in even more impressive performance numbers.

And in all fairness, any cryptography where a user chooses a poor password is then vulnerable to "easy to brute force" by a rig such as the one above. Not because the encryption algorithm is easy to brute force (usually it is not) but because the user picked a poor password, and that poor password itself is easy to brute force.


Right, agree with all of that. I would have characterized as "user can shoot themselves on the foot (i.e. by choosing weak password)", rather than "easy to bruteforce"


It's a perspective difference.

Each individual user perspective: "It is possible I can shoot myself in the foot, and also possible I will not. It is not correct to say I will shoot myself in the foot.".

Outside observer perspective: "Empirically, many users shoot themselves in the foot using this system. It is correct to say this system does not make feet safe".

It might be phrased better in terms of safety than security? The safety of the system is left up to the users, and is - to the best of our knowledge - not safe to use _as is_ by most people.


But users choosing a weak password on a standard rate limited service login is significantly different to choosing a poor password in something that the attacker has unlimited, low latency and undetectable attempts against.


I agree with the point about unlimited and undetectable. I think there's nuance to low latency.

Here the latency the attacker is limited by the amount of parallelism they can bring to bear on e.g. PBKDF. Ultimately this is an economic consideration about the cost to protect a secret vs cost to crack it.


> The thing is... this won't happen. If I'm dealing with an attacker so sophisticated to pull this off, it's likely they have 1000 other vectors that are more effective and dangerous.

Don’t delude yourself. These phishing pages with mirrored login portals happen to podunk organizations all of the time.

If someone manages to get a link to your page and is interesting in the contents, duping it and sending a phishing link to the suspected password holder is a trivial spear phishing attack (with an annoyingly high success rate).


mprime1 feel free to use or alter any of the content you agree with to update the documentation for your project.


> Con: Eventually the secrets will become exposed due to advances in crypt-analysis

You can claim this con for literally any crypto. And I'm not actually sure it's a reasonable assumption.

Block ciphers seem to be pretty unbreakable so far. Even good ol Triple-DES is secure in practice barring some caveats (don't encrypt more than a certain amount of data)

I'd wager if I gave you a real world message encrypted with AES with a strong key it won't be broken in our lifetimes.


That's a good point, I wasn't very specific about this (trying to keep it concise). To be specific here, the con is that there isn't what the industry calls Cryptographic Agility. https://en.wikipedia.org/wiki/Cryptographic_agility.

It is not true this con applies to all cryptography (e.g. look at TLS). It has more to do with how cryptography is configured, parameters are negotiated and keys are managed, than with point-in-time choices about algorithms. The con here is that unlike other deployments of cryptography, this one doesn't have parameter negotiation and key management - and therefore doesn't have cryptographic agility.

Re: "I'd wager that... AES..." is a also a good point. Modern cryptography has shown to be robust for decades and past their deprecation point. However, as you said, it IS a wager. There have been catastrophic failures of cryptographic primitives in the past. The con of this system is you will need to make a wager and tie yourself to the fate - you can't mitigate the risk if the catastrophic event comes or appears to be coming to pass.


Agility does nothing to stop the "ciphertext from the past is broken due to crypto improvements". It's just a means to shorten response time to crypto breaks for _new_ traffic.

This project is plenty agile, upgrading the primitive is very easy as it's not a communication protocol but a data at rest protocol.

> this one doesn't have parameter negotiation and key management

You're thinking in terms of live communication protocols between endpoints. There is no "parameter negotiation" when you are both the sender and receiver of a static ciphertext.

There is no existing remediation for protecting your existing ciphertexts against future cryptanalysis.


I really do hear what you're saying and think you're making a great point.

The part that I think applies is that this is a "data at rest protocol". Communication protocols are assumed (but maybe shouldn't be - a la PRISM disclosures?) ephemeral.

As an attacker, I need to have been in the middle for that specific instance of the communication, and save it for decades, to attack it. Crypto agility shortens the window from a break or weakness to a fix, forcing any adversary who has not already recorded communication traffic to do so in a hurry.

In this setting as a "data at rest" protocol, the work to persist the ciphertext has been done for the attacker. If there's a weakness or break it's up the defender to clean up all copies of the old secret ciphertext that's out there and publish new ones. In cases where the secret has been cached (e.g. Wayback Machine) that may not be possible.

I hope you agree with this nuance that there's something the defender needs to consider. I agree with you that not all defenders will find this consideration will be decisive in their decision to use this method or not.


I just think it's a misleading analysis to say "this system is vulnerable to XYZ" without including the fact that ALL systems in this class are equally vulnerable. Crypto agility is not a thing that can be applied to encryption at rest.

It's similar to criticizing an alcoholic drink by saying "this drink will cause liver damage" as opposed to saying "this drink, like all alcoholic drinks, will cause liver damage"

Without that caveat people will see that criticism as evidence that other alcoholic drinks do not cause liver damage. The absence of words can convey the wrong impression.

*Edited for better clarity.


At this point I can not edit the top comment. I would have edited with something like: "this property is not an implementation bug but a design outcome shared with any deployment of cryptography that persists ciphertext data in public."

Of course in future I will endeavour for more clarity and hope others read into this thread.


Contrary to what Wikipedia says, I don't think agility is considered a desirable property by most cryptographers: you still have the "attacker stored encrypted material" problem, and now you have to worry about downgrade attacks.

Many of the most interesting/effective attacks on SSL/TLS have been downgrade attacks that stem directly from the protocol's (historically) agile design.


I disagree with your speculation as to what most cryptographers think. Are you basing this on any data you can share?

Please also see the other thread about how this secret storage system is different from a communication protocol. Namely, communication protocols have a two step attack: first attacker must MITM and record ciphertext, then they must wait. This secret storage method is different (one step attack): attacker looks for ciphertexts on either targeted or non-targeted basis that use old standard. Persistence, caches and publication of these secrets has been done for them.

It's a good point about downgrade attacks. They have been brutal for TLS to deal with.


> I disagree with your speculation as to what most cryptographers think. Are you basing this on any data you can share?

No, just conversations. I'll admit it's just speculation.

Maybe I should qualify: there's "cryptographic agility" in the protocol sense (a single version of a protocol can accept a wide range of primitives, with the idea being that users can upgrade their primitives as old ones become insecure), and there's "cryptographic agility" in a more abstract design sense: wire formats, etc. should be devolved from the primitives in such a way that the protocol can be switched to secure primitives without requiring unrelated changes, and in a way that doesn't surface any differences to the user.

To my understanding, the first sense of "cryptographic agility" is widely discouraged: we've yet to figure out a really reliable way to provide backwards compatibility without enabling malicious downgrades. The second sense is not something I've heard people use the phrase "cryptographic agility" for, but that's possibly just ignorance on my part. If that is indeed another form of agility, I believe that's widely considered to be good design (and this design is "agile" in that sense, since existing messages do not compromise the security of an upgraded scheme).


>Uses current state of art algos. Pro: Resistant to access by known methods.

AES-GCM is fine sure, but the password hashing function PBKDF2-HMAC-SHA1, i.e. what turns the user's weak password into the AES-key, is the opposite of state-of-the-art in this case.


Please share this silver bullet pake with the rest of the class?


Argon2-HMAC-SHA512 more like it? Or something else?


Argon2 is built on top of BLAKE2 but the hash function isn't what's making it so effective, it's memory hardness, i.e. it fills the RAM when deriving a key from password, which makes massively parallel attacks impractical because GPUs / ASICs don't have petabytes of RAM just lying around.


Cool thank you - thought so, but always good to check :)


> Con: Any issue (there have been many) in WebCrypto implementation at time of encryption can not be fixed by browser upgrade (because of secret caching).

has there ever been an issue that made WebCrypto produce invalid ciphertexts/hashes/PBKDF output?


Great project!

Thinking of using this as the final backup, something to store 2FA backup codes/recovery codes etc, basically a way to end circular-dependency on my password manager, i suppose one would host this using free public hosting, maybe cloudflare pages on a hidden website, basically something reliable and trivial to access.

however relying on localstorage, which can be accessed by extensions worries me, but i couldn't replicate the password showing up in browser history thing(using brave).

seems the best option for my use case so far, maybe a self extracting 7zip archive with file name protection is better?


"long sequence of words that are trivial for me to remember"

I also thought so until I suddenly forgot a master password I have been using for several years. Luckily, I was able to recollect it after several days. Then, I forgot it again.

Age, decease and head trauma can happen.


By "long sequence of words that are trivial for me to remember" I meant concatenation of secret questions, like in the bounty example: https://mprimi.github.io/portable-secret/examples/bounty.htm...

Unless I hit my head really hard, there's zero chance I will forget this passphrase.


Keys should be random. The hints make it too easy. Lets say there exist 100 male names and 100 female names, thats just 100*100 combinations for names part. You could make the key generation intentionally slow though to limit the crack speed.


> You could make the key generation intentionally slow though to limit the crack speed.

Am attacker keen enough to bruteforce can easily copy the ciphertext, IV, and salt to a tool that doesn't have a slowdown. Or, just modify the JS to remove the artificial slowdown.


Presumably they are using some KDF (Key derivation function) that is designed to be algorithmically slow in some way that you can't trivially sidestep.


This is an old problem: how to slow down the hashing. https://en.wikipedia.org/wiki/Bcrypt


> decease

That one makes passwords vanish from ones memory quite effectively.


> Prior art

> I came up with Portable Secret on my own, but I have since found a few projects that do something similar.

> https://github.com/kaushalmeena/digi-cloak

> If you are aware of other similar projects, please let me know and I’ll link them here.

Digi-Cloak appears to be an in-browser steganography tool, but this project looks more like an encrypted pastebin (e.g., PrivateBin [1]).

[1] https://privatebin.info/


I can confirm that the password for the bitcoin wallet is not banana.


Have you tried banana banana?


Using browser crypto to create a document is the right thing to do, but you might want a JavaScript decryption library to improve portability and lifespan. I would check that it’s capable of decrypting the payload when you’re making a document. (Possibly https://github.com/travist/jsencrypt)

The obvious weakness is your hosted document creator: it’s essentially impossible to defend an HTML document against a malicious domain. We can look at your GitHub repo, but there’s no guarantee that’s the exact code that’s running. If you’re an especially valuable target, you can’t even be sure that the files that you think you’re serving haven’t been tampered with.


> might want a JavaScript decryption library to improve portability and lifespan

How does a library improve portability and lifespan? I'm only using NIST-recommended encryption algorithms provided by W3C Crypto APIs.

> The obvious weakness is your hosted document creator: it’s essentially impossible to defend an HTML document against a malicious domain. We can look at your GitHub repo, but there’s no guarantee that’s the exact code that’s running.

I agree. As clearly stated in various places, this is a demo. Take the idea and fork/re-implement it for yourself.


Sorry, I should have started off by saying that this is a great idea! I’m a big fan of encryption and those old, offline things we used to call “files”.

> How does a library improve portability and lifespan? I'm only using NIST-recommended encryption algorithms provided by W3C Crypto APIs.

I’ve been writing software long enough to have been around the block a few times, and the web ecosystem hasn’t been pretty. Things get added, things get taken away, someone discovers some edge case in an API that’s not used very often and instead of being patched it’s just dropped (https://developer.chrome.com/blog/deprecating-web-sql/ or https://chromestatus.com/features#removed). Web apps shouldn’t but often do require significant maintenance.

In that context, it’s likely that something about the API that you’re using will stop working in a few years. Someone who wants to make a new document could bring things up to date and publish a new version. But existing documents? The ones used by friends and family who aren’t as technical, they’ll stop working.

The other side of the web is that the ubiquitous parts, basic HTML and JavaScript, will be supported pretty much forever. People want to see that their browser will render popular old pages, at least ones that don’t use super fancy things. Using a random encryption library to encrypt things could leave your cypher text vulnerable, but using a random decryption library (that’s verified to be able to decrypt) doesn’t have the same risks. It will, however, work pretty much forever (as long as it doesn’t rely on any browser APIs) which is ideally how long our files should last.

Congrats on building a cool thing!


Algorithms are standards recommended by institutes like NIST, so probably not going to change anytime soon.

To your point, the W3C Crypto library APIs might change, and break my secrets. Unlikely but possible.

I don't know that bringing in a library makes this better: it could use features/constructs of the language that get deprecated and break.

There's other factors to consider (convenience, amount of review a given implementation has gotten, etc).

Overall, agree to disagree. Using a library has slightly different tradeoffs and I can see why you are recommending it. But I stick by my choice to depend on browser APIs.


I strongly doubt a crypto API will be taken away. It’s the bread and butter of any language that ships with one. There are very few implementations and their APIs are largely identical too

Web SQL? Now you could survey a room and ask if they think web JavaScript should have a native SQL library and probably half will say ehhh… a native SQL library where there are a thousand ways to implement it was doomed from the start

That said, algorithms may be deprecated and removed. I’ve seen that happen in crypto libraries.


About 10 years ago when I was working with American Express for a Payment Gateway project, all the internal bank too vendor communications were these encrypted emails with a self-contained HTML file that has the content encrypted inside of them, similar like Portable Secret. Sadly I don't recall the proprietary vendor's name or the name of the technology. Pretty sure I've received similar self-embedded HTML from Chase as well.


IKR? I've been receiving such emails for a long time (and still receiving one every month), and this is not a new idea to me. I really wonder what's inherently different here, because I couldn't find one yet it's being hyped up. The use of crypto API is just an implementation detail that might negatively impact the longevity of a document.


They still do this. It sucks.


This is an ingenious idea, one that becomes obvious only in retrospect.

To me this feels like a merger of the ideas in projects like magic-wormhole, Wormhole.app, and the (defunct) Mozilla Send. But then it adds a kind of sharchive twist using the browser as a runtime.

The original paper I saw called it Password Authenticated Key Exchange. https://www.cs.columbia.edu/~smb/papers/neke.pdf

But I think the general form is now called something like this: https://en.wikipedia.org/wiki/Password-authenticated_key_agr...

Anyway I’m posting all this not to show my erudition (I’m really stupid about cryptography) but that there’s lots of precedent for this kind of tool and maybe with a few tweaks can even be made standards-compliant. (RFC 8188 seems to contemplate some ideas like this, but the file isn’t “self-expanding”.)

Some obvious issues: sitting on a thumb drive, the file is vulnerable to unlimited attacks. And since the decryptor is in “plaintext” it could be MITMed in a way, since the decryption code can be tampered with, and a browser environment with localhost access can be tricked into doing lots of things, including sending decrypted contents to the attacker. In a SaaS there’s no MITM given transport security, and you can notice you’re getting attacked, or expire links after a number of tries / some amount of time.

But so what; the whole point here is to provide really good security with a different channel.


Didn't older versions of 1Password allow export to HTML page that contained all the passwords and did decryption by JS embedded in the page itself upon entering the master password? IIRC.


Someone else commented the same, you are not crazy


You could also think of it like an encrypted zip file send from one party to another.



> This is an ingenious idea, one that becomes obvious only in retrospect.

Thank you.


1password used to do this with a thing called 1password anywhere, which was turned down in 2016.

https://1password.community/discussion/63045/moving-beyond-1...

If stores all the passwords in encrypted js files, which the 1password.html would read in and allow for totally offline password access.


This is pretty cool:

> Before we jump in, I wanted to share some history with you. Back in 2009 when we first built 1PasswordAnywhere, it wasn’t possible to use it with Dropbox. We couldn’t use Dropbox at the time because each file request needed to include a revision number and 1PasswordAnywhere had no way to know which revision numbers to use.

> Roustem and I explained this problem to the Dropbox Founder Arash, and he was kind enough to add a workaround to allow us to load files directly. This was state of the art technology in 2009.


I made something similar a few years back when I was learning web dev. It's not nearly as polished, but I'd love to pick apart your code and see what design decisions we did similarly/differently

https://9p4.github.io/hackna/

The big difference is that your project is self-contained in an HTML file, which I think is a much better design


Cool! Added a link to your project


I did the same thing before WebCrypto by including an AES JavaScript library in the page. Nice work.


"Do you think this cannot possibly be secure? Great, prove it.

This secret contains the recovery key for a Bitcoin wallet. Crack it and take my money!"

Love it.


The first few times I shared this with (security professional) colleagues and friends, they'd dismiss it right away "this can't possibly work", but it was because they _assumed_ it didn't work (too simple).

Attaching a challenge made a big difference, they'd spend 5 minutes trying to crack it and, in the process, realize it is actually sound (despite the simplicity).


I think this is very cool, and from a cursory look you've made most of the right design choices (to the extent that the Web Crypto API allows).

That being said, I think most security professionals (myself included!) aren't equipped to outright "crack" this kind of thing in just a few minutes, and most should know better than to think that their inability to do so implies soundness.

With that in mind, here are some things I noticed (none of which represent an immediate break!)

* You're using SHA-1 in your KDF. That's probably fine since PBKDF2 doesn't rely on the properties of SHA-1 that have been broken, but the Web Crypto API gives you better alternatives. You could switch it out for SHA2-256 here without any breakage to the rest of the scheme.

* I'm not a JS expert, but I _think_ your encryption page might allow a confused user to reuse an IV[2]. Normally this wouldn't happen because the user would refresh or reload and trigger the `init` on page load, but it would probably be better to generate the IV on demand rather than having it wait in an HTML attribute.

Again, very cool work! The fact that people can make these kinds of self-containing encrypted applications with Web APIs is a serious testament to how far the standards have progressed.

[1]: https://github.com/mprimi/portable-secret/blob/3b22d2b42baf8...

[2]: https://github.com/mprimi/portable-secret/blob/4de5e958fe6f8...


Thank you.

> most security professionals (myself included!) aren't equipped to outright "crack" this kind of thing in just a few minutes

When I say 'crack' in this context, I mean review the scheme and point out any obvious flaws, like you just did!

> SHA-1 -> SHA2-256

I should do this!

> reuse an IV

Indeed (there is a fine-print in the creator page that says "don't reuse across messages", but I should just regenerate proactively)

Thank you very much for the great comment!


> despite the simplicity

FWIW, it's a simple composition of complex things. Still really cool, thanks for the idea!


Why would they dismiss this?


Because it seems too simple to be secure.

(People are busy, attention is scarce, etc)


Feels like the default human response in a lot of situations...


Notice they have also given clues to what the password words are. So with brute force, maybe spending a good portion of the bounty on cloud resources, you might crack it that way :-)


This is a smart use of crypto too. The verifiable and public parts of crypto here are a benefit and not a con.


If someone tells you:

    This secret image contains a Bitcoin wallet recovery key
    If you can crack the secret, the funds are yours!

    You can check the status of the wallet here: 
    https://www.blockchain.com/explorer/addresses/btc/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Now here's the secret:

    0002146273a3774b3828effff3382000someGarbageSecretThatsActuallyIs{https://youtu.be/eBGIQ7ZuuiU}EnctyptedUsingARandom4096BitStringAsPassword


Which "verifiable and public" part helped?

- Anyone can point to a random link on blockchain.com

- the encrypted secret can contain anything


They didn't do it here, but you can sign a message that includes a checksum of the application with the private key of that address. The signed message can be proved using just the public key that they have linked to.


but you are not guaranteed that the decrypted key is valid.


I hate that I’m saying this because I believe all of cryptocurrency to be a pyramid scheme, but… this is the perfect use case for a smart contract on ethereum…

(Now I gotta go wash my hands after typing this.)


why would a smart contract help though? there needs to be proof that the encrypted key is valid, this would require zero knowledge proof but I'm not sure how you can do it for this use case.


He could post a secret in the decrypted text on the page that, once submitted to the chain, fulfills the contract and transfers the ETH. I know very little about smart contracts but I thought this is what they’re good at… “if a value is posted with a sha512 hash that matches x, the contract is fulfilled”, and put the value on the page, encrypted, and ask hackers to decrypt it.

It doesn’t necessarily prove that the encrypted key is valid, but it proves that the author put some money up on the chain at least. It could always be that the decrypted text doesn’t provide the key that fulfills the contract, but ultimately that isn’t a solvable problem. You can’t prove a claim about some encrypted text without someone having the ability to decrypt it.


But then you don’t need to have a smart contract, simply posting public key of the wallet is enough (to verify the content of the wallet). The contract at most provides an escrow, but even that isn’t really the case since presumably the originator has the key to pull the money (since he knows the secret key).

Proving that an encrypted text has the private key is possible for some encryption schemes through zero knowledge proofs, but I guess not in this case in particular.


Offering a bounty like this has value, but probably only for finding shallow bugs.

Thoroughly evaluating security/cryptography takes deep expertise and a lot of time. You're not going to elicit that without more money, impact/fame, or technical excellence.

- Money: The original bounty was $400. An expert can probably earn $400 an hour just to investigate something, without needing to completely break it.

- Impact/fame: Barely anyone uses this project. There are tons of other tools and services that are more widely used.

- Technical excellence: There's no evidence of anything clever or interesting.

For example, researchers around the world spend tons of effort analyzing the algorithms in the various NIST cryptography competitions. There's significant impact/fame and clear evidence of technical excellence. But if some rando offers a $10k bounty for their encryption algorithm, it's not going to get the required level of scrutiny.

Plus, the bounty is just for the encryption mechanism. With security, it's usually the other moving parts that cause issues, especially in how they interact with human behavior. Phishing works without needing to break TLS, DKIM/SPF, browser sandboxing, etc.

(I read an article ~5-10 years ago by a security/crypto researcher that said basically this, but sadly I can't find it anymore.)

I still think it's great when people build things like this and when they offer any kind of bounty. I just worry that the presence of an unclaimed bounty might mislead people into overestimating the level of security.


FWIW, I (author) agree wholeheartedly with everything you say.

I'm just sharing a little hack I came up with. I hope some people add it to their toolchain (not my specific implementation, the idea in general).

And offering a bounty seemed like a fun things to do, which may also catch some shallow bugs, reward the hunter, and shame me publicly :-)


Very creative and efficient use of $400 on PR/advertising!


$400 or $0?

I don't think of it as PR/Ad. It's a bounty. If you put in time to find a flaw, you deserve at least that much (and I'll give you more if you help me fix it).


Why can't it be both?


What is your comment referring to? I must have missed something...



What happened to the "don't roll your own crypto" that HN loves?


this doesn't, it uses the browser's builtin Web Cryptography API.

if using a crypto algorithm also counts as "rolling your own crypto" then what's left? just don't encrypt anything, ever, because HN says we shouldn't roll our own?


Yes, using a crypto algorithm also counts as rolling your own crypto. You're putting together crypto libs that others wrote. Most crypto vulnerabilities come from glueing together solid crypto implementations. The glueing has to be solid too. Just "using" a crypto algorithm sounds like a recipe for a vulnerability.

I'm not a crypto expert, I'm just telling you what I've been reading on HN for the past few years.


You're not completely wrong in that it's still possible to f up, even when using misuse resistant primitives.

The difference is, you're sort-of allowed to f up if it's an intelligent mistake that teaches the creators of misuse resistant libraries a thing or two about where they went wrong. If OTOH you're clearly just yoloing it, introducing your pseudo-math BS into the mix, or intentionally deviating from best practices or breaking it, then it's on you.


re-using primitives is on a completely different level from creating your own cipher.


[flagged]


Using the output of a language model like mine as a comment reply on a forum like HN could potentially have a negative impact on the discourse in a number of ways.

1. It could undermine the authenticity and integrity of the conversation by introducing responses that are not genuinely from a human.

2. It could create confusion or misunderstanding, as the responses generated by the language model may not be relevant or appropriate for the specific context in which they are used.

3. It could discourage genuine participation and contribution from other members of the community, as it may seem like the conversation is being dominated by automated responses rather than authentic human interaction.

Overall, it is important to consider the impact of your actions on the online community and to strive to contribute to respectful and meaningful discourse. Using the output of a language model as a substitute for genuine human interaction is generally not a good idea, as it can undermine the authenticity and integrity of the conversation.


They didn’t roll their own crypto? They used the web crypto API provided by the web browser.


I can't be the only one who thinks this wallet will be emptied before 2023.

Security by obscurity is real, there's nothing secret about defining the problem space in which your attackers can search.


I'd be happy to see the wallet emptied.

This is what the bounty is for. I just hope whoever cracks it lets me know how they did it and how hard it was.

This is what a bounty is, no?


$400 is nothing, put your life savings into this system if you trust it so much.

It's a cute marketing gimmick, that's about it.


Works on mobile.

It is amazing what all the browser APIs enable as a target platform of its own. And the portability that the (probably-disgusting amount of lines of) code provides.


I wrote a similar software for the same reasons. One goal for mine was that the generated output is small enough to quickly verify that the code sent to the browser is the one you expect. Total code size is under 100 lines.

https://github.com/dividuum/html-vault


Neat! I knew I could not possibly be the only one that had this idea.

Linked your project.


One possible attack is someone changing either the encrypt or decrypt source code, either via Github (if they get access to the OP account) to log keystrokes.

Or if someone has hosted it themselves then hack that hosting provider.

Or they could do something like this: https://www.theverge.com/2018/4/24/17275982/myetherwallet-ha...

Phishing is another potential one. Browser extensions, or supply chain attack on packages they use.


I agree phishing is the most scary vulnerability for this.

In practice, when exchanging emails with my mom, I'm not concerned about it.

A sophisticated attacker has many easier ways to get into my stuff than creating a fake PortableSecret.

(more detail in a different comment: https://news.ycombinator.com/item?id=34084887)


If you get 100,000 people using your site to exchange secrets, the bounty got a lot bigger. For phishing you and your mum might be immune, but one of the 100,000 might get phished. For taking over the account (which is now more juicy, could be some bitcoins there) then everyone would be vulnerable who doesn't check the source code each time they load the page.


In order to have 100'000 potential victims, you need to have an attacker that knows 100'000 users using this and details of how what they do with it in order to convincingly phish them.

That would be a very sophisticated attacker. So back to my original point.

Beside. The README states pretty clearly this is 'demo' tech. Learn the trick and use it on your own. Depending on my GitHub tool for your critical secrets is not a good idea.


So, the next step would be to have this in front of a S3 upload dropzone that generates a public link which self-expires after a few days?

As in, here's a link to a file, you know the password, it'll self-destruct (disappear) in 24 hours.


Sounds cool!

All I wanted to show with this project is the concept of self-contained, self-extracting, super-portable secrets.


I had the exact same idea years ago when I was working on a secrets manager (hobby project)..

Self Destruction, Unique link + password makes it pretty secure.

With the exception of Internal sabotage, I don't see any other issue.


I noticed you are using pbkdf2 to convert password to key. It's recommended to use ARGON2 nowadays.

From some googling, pbkdf2 increases CPU usage to make brute force harder, scrypt increases memory usage to make brute force harder. ARGON2 increases CPU and RAM usage to make brute force harder.

There are other advantages as well, and it is considered the best key derivation function right now.


Fair point, I'd switch to Argon2, but it is not part of the W3C Cryptography APIs so I'd need to bring in a library or hand-roll and implementation.


It would be awesome if this could be code-golfed into a small enough package to fit in a QR code.


Do you mind expanding?

Specifically, what do you mean by de-golfed (I'm only vaguely aware of what 'kids' mean by code-golf these days, and I'm kinda lost on de-golfing).

What would you like to fit into a QR code? A PortableSecret (e.g. html file)?


Like sibling comment elucidates, code-golfing is just using tricks to get the size of a program down without impacting its functionality. This could be as simple as using single-character variable names or something more complicated like including a decompressor that expands some packed code before execution.

If you got the decryption code plus the payload small enough you could theoretically put the whole thing into a data URL (a URL that doesn't link to a remote resource, but contains all the data needed to display a web page). This data url could theoretically then be encoded into QR and accessed entirely locally on anyone's smart device.


> If you got the decryption code plus the payload small enough you could theoretically put the whole thing into a data URL (a URL that doesn't link to a remote resource, but contains all the data needed to display a web page)

This is how the 'secret creator' page works :-)


This used to be called munging


It’s called minification in the JavaScript ecosystem.


Minification may, or may not, involve munging, for example shortening `const foobar = 1;` into `var f = 1;`. This is not always a safe operation, and in some cases you want to disable munging when minifying your code so that you have meaningful component / function names in your stack traces even without sourcemaps.


Code golfing is the act of finding ever and ever smaller, but functionally equivalent, expressions of a specific piece of code. Usually involves a lot of tricks specific to the language the golfing is done in.

So yes, it would contain the PortableSecret minimized to such an extent that the whole thing fits in a QR-code (which has a practical upperlimit of a few KB?)


Gotcha. Thank you.

IDK about including a full HTML into a QR code (how would you even open it? Wouldn't a reader get confused expecting a URL or plain string?)

But...

You can publish portable secrets on your website (just make sure they aren't advertised/linked/crawled) and then create a QR code of the (secret-by-obscurity) URL.


Use a data URL and use base64 variant of the resource


Not just QR code, may be small enough secrets fit in a URL (2KB I think is the limit)!

See also the now defunct sharelock.io by Auth0: https://news.ycombinator.com/item?id=9109924

For creating and later validating magic-links (using Web APIs), I encode the IV, Salt, Cipher all in the URL as a single base64 token: https://github.com/celzero/otp/blob/cddaaa03f12f765fa8da9178...

(Btw, reading through your code makes me wonder if I should pad the plaintext to match blocksize despite https://archive.is/NX7Y2)?


You are saying padding might be superfluous because of AES-GCM, correct?

(I was using AES-CBC before, that's why the padding is there)


Not the original commenter, but if the whole HTML could be included, it would be nice. It is defenitely possible until certain data limits. However, you would need certain app to use it, since by default QR readers probably can’t benefit from it so that it actually increases the usability. File should be extracted and then opened with browser from correct path.


> Send encrypted messages/images/files over insecure channels (email, messaging, …)

I don't understand. Sure you sent these over an insecure channel and they end up... Being opened from a website, in a browser which downloaded JavaScript (JavaScript which may or may not be the same you downloaded yesterday when you used that same site btw)?

And we all know that browsers running unverifiable JavaScript from some Website are a... secure endpoint?

It's not a criticism: I'm probably missing something (is this something I'm supposed to run on my own server or on some computer I take offline after having opened the website from a harddisk-less system booted using a Linux Live CD?)?

How is this not something where you need to trust the website/server?

For all I know upon entering the password the secret is sent to the server over the wire.

Sure, fine, let's disconnect the computer from the Internet before entering the password...

Well then for all I know the JavaScript just downloaded may be saving the data or the secret in a cookie or whatever that is going to be read the next time the site is going to be accessed (so even opening it offline ain't sufficient: it must be done from a system which cannot persist to disk right?).

P.S: as an addition "Do you think this cannot possibly be secure? Great, prove it. This secret contains the recovery key for a Bitcoin wallet. Crack it and take my money!". I'm sorry but that's not how security works. It simply ain't. Once again: I'm probably missing something but reading this thread so far I feel I've been catapulted in an alternate reality, complete with people thinking that this message is somehow a proof that this scheme is secure (which it may or may not be, but that people cannot steal the coins ain't proving jack shit).


"Do you think this cannot possibly be secure? Great, prove it. This secret contains the recovery key for a Bitcoin wallet. Crack it and take my money!". I'm sorry but that's not how security works.

That's not how security works, but that's how a bounty works. If you can do ___, then you get ___. That's it.

If it's any consolation, I sent this project to (security professional) colleagues in the past to get their take on it. This is also not how security works, but to me is better than nothing.

Remember this is not a product. I don't care if you use it. I'm just sharing my hack for carrying secrets around without needing a special device or key.


There is no magic in JS that makes something insecure simply by using JS. Unverifiable? If it's not minified you could literally just right click and read it before typing in your secret.

Similarly, there is no magic dust in a live CD that makes you immune to security issues when running it.


A 'portable secret' is a self-contained HTML file. You can open and decrypt it without an internet connection. This is I think one misunderstanding.

The second one is that you can open the file in an editor and verify what it does before trying to decrypt.

Any modern browser also has protections that prevent a random HTML file from acting like a virus (stealing and uploading files).


The javascript is embedded in the HTML


I've been thinking about something similar, it really should be much easier to send encrypted messages.

I'm not sure if this is a problem, but one thing that is unclear to me is how/if this protects against an adversary that can modify the html file.

If the adversary can modify the HTML file in transit they can just add some code that sends the password to the adversary's server when the real recipient opens the file. (Of course, the recipient can run it in some air gapped browser etc, but that limits the practical use case quite a lot.)

And if you want to use this to send messages over e.g. email this seems like a somewhat important thing to protect against. I guess you could send the portable secret html file separately, and then the user copy-pastes the message in some text-box, but again this makes it more clunky.


Phishing is indeed the most glaring vulnerability of this.

While it's very real in theory, I am not concerned in practice.

If I am the target of a sophisticated attacker, there are easier and more effective ways to pwn me.

A few other comments reference the same, e.g.: https://news.ycombinator.com/item?id=34085245


Fair enough, I guess in many ways I agree that at least for now it is not a real world problem. But if this would become popular it wouldn't be that hard to make a proxy that silently adds some code to the page if you fetch it over the internet.

Maybe it would be good to document this a bit more clearly that this mainly protects against weak adversaries. On the website you make some comparisons to GPG etc, which is a very different level of protection from my understanding, and may give a false sense of security.

I think I would prefer an approach where each person has their own html file, and then they can copy-paste the message into a text box and then decrypt it. Then you could also use public-key cryptography etc, and store a (encrypted) private-key in the html file itself. Like a light-weight GPG client in a single static html page. I guess the main feature that I don't see how to add is how to store and keep track of the public keys for your friends in a nice way.


Age is amazing. I'm using a Yubikey in conjunction with it to encrypt {passwords, docs} and commit them to a private GitHub repo.

See here if interested: https://github.com/mihaigalos/pass


I built a similar tool after Firefox send got killed. It was only for transient messages (e.g. sending secrets to someone else or an other device). I don’t know that I love the idea of these being long-lived, as I’m not sure I trust my password abilities.


I keep putting off the decision on how to store my private keys remotely in case of disaster, and this looks like a good and very pragmatic solution. Thanks for creating this!

My first reaction was "why not a password-protected zip" and you already linked to a relevant stackexchange question. I think it might be helpful to add a "Why not a password-protected zip/rar/7zip/..." on your page when you have time for it.

Or maybe even explicitly make clear which security goals (confidentiality, integrity, etc.) are satisfied by this. The reason being of course that I would like to show this to colleagues/friends and not having to debate this myself :)


> "Why not a password-protected zip/rar/7zip/..." on your page

Great suggestion!

> not having to debate this myself

eh eh.. good luck with that...

I think the problem is that it can be used "good" and can be used "bad". Some people focus/fixate on the ways you can shoot yourself in the foot with this. Other think of the good use cases it enables.


Works pretty well on Android! Unfortunately, today I learned that FireFox doesn't seems to support opening html files. When I download the html file FF isn't one of the options to open it. Only Chrome. Anyone know an way around this?



On what OS? They're all slightly weird about file associations.


On Android. It is a known issue which Mozilla don't seem to intend to fix: https://github.com/mozilla-mobile/fenix/issues/7546


Cyphers, the algorithms used to encrypt the secret file, become obsolete over time.

We still need to solve for obsolescence. You can encrypt a file today using a cypher that will eventually be removed from all browsers, desktops, and phones.


2 sides of obsolescence:

- Too old, no software can decrypt it: not worried about this. These are NIST-standard algorithms, there built-in in most programming languages, they'll be around for a while

- Too old, trivial to crack: this is a bit more concerning to me. It's possible that some entities around the world can already crack this encryption in minutes/hours days

Regarding the second, I'm already working on an Elliptic Curve version of this.


Well, your cipher text could decrypt to a non-published URL that has some cipher text which decrypts to another non-published URL (as many layers of indirection that you need), with the final non-published URL containing the actual cipher text you wanted to decrypt.

You can check server logs to see if those URLs are ever hit.

And if you ever need to, you can abandon the original link after changing what those non-published URLs point to (something "fun", like a rickroll perhaps).

In fact, how about using the Wayback Machine to store a bunch of versions of the static page, each containing different versions of the cipher text. Only you know which date range contains the proper cipher text!


Genius.

As the old adage says 'any problem can be resolved by adding one more layer of indirection'.


I'd argue this isn't a cryptography problem, or at least not a purely cypto problem. Because we have the exact same issues with almost all file formats and storage mediums.

It requires a maintenance toil task to make the occasional conversion from unsupported cyphers to supported cyphers.

Maybe the page needs a second button and JS function - re-encrypt.


I guess this is a downside of the browsers.

If I want to run ancient app (MS-DOS or even ZX Spectrum), there are plenty of well supported modern emulators. But a 5 year browser with feature removed for security reasons like Flash? That's much harder.


The code uses AES. Likely that will remain for longer than most secrets are relevant.


XChaCha20-Poly1305 will probably never go out of fashion.

Argon2 is only making itself in, phasing it out will take decades. OTOH you have a point in that the author's implementation PBKDF2 is being used, and that should already have retired a decade ago.


Can anyone enlighten me on

  Some secrets don’t belong in your password manager. Things like backup private keys, 2FS recovery keys, wallet keys, safe combinations, treasure maps, etc.
I am a 1password user and am aware that I am trusting a 3rd party with most of my life basically (minus the 2FA, my phone), but that's the way I decided for convenience. But why would I keep passwords in there but not PKs, wallet keys etc.? To me they all have the same value. What am I missing?


Honestly that statement sounds like BS to me. Also, this person is trusting his life to a third party as well: the browser vendors’ cryptography implementation.

I think for an average person, the biggest factor is not the strength of the security. You’re already better than 99% of people if you use different passwords per site and store them behind a password. No hacker will spend weeks cracking your passwords if he can get the passwords of those other 99% for free.

So I’d say, pick the solution most convenient for you that is least likely to break over time. And an established name like 1Password sounds great for that.


Author here.

I do use a password manager.

PortableSecret is a complement, not a replacement.

e.g. where do you store the recovery key for your password manager?

I also use this to store tax documents and other mildly secret documents which definitely don't belong in a password manager that copies to who-knows-where-and-in-how-many-copies.


So out of curiosity, what password manager do you use? And as apparently you don’t trust your password manager, why do you use one? And how do you determine what is “useless” enough to be entrusted to that password manager you do not really trust?


I use multiple ones, they're kinda compartmentalized. One for web logins, one for critical operational secrets, one for 'cold storage'. Plus variants of PortableSecret for various other odds and end use cases like emergency recovery USB drives.

I trust everything I use to some degree. Otherwise I wouldn't use it in the first place. But the world is not black and white.

Just because I trust something enough to store secret X in it, doesn't mean I should automatically use it to store secret Y.


Agreed; the only thing I can see the logic for not keeping in there are 2FA codes.


This is really cool!

The "lost thumbdrive" comment makes me wonder if a browser from 20 years (or more) in the future will still have enough legacy functionality to decrypt these payloads.


Even if not, it's affordable to hire a programmer for a few hours to migrate the code to the newer API.


I doubt that would work. You can’t decrypt things encrypted 20 years ago on modern API’s because those algorithms are known to be insecure. You’d have to probably rewrite it from scratch or install an old version of the browser. So it’s probably best to keep a windows version of the browser since that’s currently the only OS that can run software from 20 years ago, so hopefully they’ll still be able to do that 20 years from now.


The cryptography is insecure. The code often is secure – it's just doing an insecure thing. In this example, the encrypted data is (perhaps) insecure, because the cryptography algorithm has known exploits.

Consider a magic unpickable door lock that automatically unlocks itself at midnight. The lock has no security vulnerabilities (it's doing exactly what it's supposed to, and there's no way to subvert it), but your house probably does.


I’m not sure if anything you said makes any sense in the context of my comment, are you sure you’re replying to me?


I assumed you meant something slightly different to what you wrote, because you wrote:

> You can’t decrypt things encrypted 20 years ago on modern API’s because those algorithms are known to be insecure.

Python's standard library, C's standard library, and Win32's CryptoAPI all beg to differ. The specific algorithms used by Crypto.subtle (Rijndael, Rivest–Shamir–Adleman) are over 20 years old, already, so even that's a counterexample.

> So it’s probably best to keep a windows version of the browser since that’s currently the only OS that can run software from 20 years ago, so hopefully they’ll still be able to do that 20 years from now.

Most operating systems can run software from 20 years ago. I'm currently running a 35-year-old piece of software on the latest version of an OS that isn't Windows. (I'm not aware of modern Windows being able to do that, actually; not since NTVDM got removed.)

Does this address your comment better?


> Does this address your comment better?

Much! I'd say that there is always a counter-example. However, even RSA was generally recommended as "insecure" because people can't bother to do any research into the correct values of the parameters. The algorithm itself is secure, but most libraries didn't have sane/secure defaults until like 10ish years ago.

That was the point I was trying to make, you're making a bet that what we know today will still be true 20 years from now. The algorithms you mentioned are symmetric, IIRC, and basically any symmetric algorithm is secure as long as you have a one-time-pad or don't know any of the cleartext. That is, until someone finds a flaw with it.

I remember working on my first 'ciphersaber[1]' when it was discovered it was insecure.

> Most operating systems can run software from 20 years ago.

I was mostly referring to main-stream OS's. Linux and OSX, for example, cannot run software compiled 20 years ago (I'd love to be proven wrong, but my experience hasn't been so great!). On my modern Windows 11 PC, I can still run my first game engine demo, written and compiled in 1998 (I've since lost the source code). Or via WINE on my Linux PC, probably.

I'm sure there are niche cases out there, but the vast majority of people don't have access to those systems and OS's, while anyone can (currently) run a basic version of Windows for free.

[1]: http://ciphersaber.gurus.org/


> Linux and OSX, for example, cannot run software compiled 20 years ago (I'd love to be proven wrong, but my experience hasn't been so great!).

Just get the copy of libc it was compiled for (and any other libraries), and add them to LD_LIBRARY_PATH before running the program. Linux's ABI is stable, so this should work fine. (It's always worked for me – though I haven't tried terribly much software, I'll admit.)

I don't know about macOS; iOS has compatibility problems, but Android basically doesn't.


Please add this: decrypt also on pressing key "Enter". Thank you!


If it's any consolation, it's on the TODO list (not a web/JS developer if it wasn't clear from the crappy CSS)


The value in this may be in tokenizing data for privacy in web applications. An example would be medical test results, where you are the lab and to meet privacy requirements, you don't want to show them to every party involved in processing and billing, but the blob has to be stored and transmitted to the patient and their physician.

The secret/key management part is just an OOB secret, and provided it's in the form of a long passphrase, it should be sufficient, and doesn't rely on patients and regular people doing key management or maintaining keypairs. You just send them the passphrase in the physical mail or some other channel. If they lose it, you just generate another token blob with a new passphrase, etc.

That use case may be declining as privacy rules have been gutted lately, but WebCrypto could facilitate some interesting new protocols for a variety of cases.


Wow, that's a neat idea and a very good execution. If only it didn't had to "...Some Javascript that calls into the browser’s Web Cryptography APIs" and had all the code inside the HTML that would be great. Completely self-sufficient and offline, without dependency to the browser(s).


The HTML is self contained and works offline.


I created something similar to this [1] a few years ago. Before the proliferation of web crypto apis, I just used a WASM’d libsodium. It adds some page weight but whatever…

My use-case was for traveling, it seems like a good idea to have a backup photo of my passport and credit card in case I loose everything. Sure I could put it on Dropbox, but do I really want to log in to my entire Dropbox on someone else’s machine?

Ironically, it has yet to be useful. Just a fun project inspired by the realization that you can base64 just about anything in an HTML document.

1: https://github.com/ccorcos/encrypted-html-vault


Cool!

Main difference I see: you have thousands of lines of JS in your vault. Mine is a lot simpler because it uses the browser Cryptography APIs.

Linked your project from the README.


This seems like a really good proof of concept to let browser vendors know they could create a super useful utility in their browsers.

I mean, it's very cool all on it's own, and great job in building it! I'm just hopeful that someone is taking notes.


Thank you!


I can’t crack your secret but anyone with access to your browser (including the browser provider can).

A post-it note that says “my daughter’s birthday” written on it is secure in the same context. Even if it upload a picture of said post-it note to Dropbox.


So, a self-extracting password-protected archive made portable via web browser APIs?


Yes, that's one way to put it.

p.s. don't use password protected archives: https://security.stackexchange.com/questions/35818/are-passw...


How about you explain the problem with password protected archives and explain how you solved it, instead of linking to something and seeing if it sticks.


I asked myself in the past 'how secure are password-protected zip files?', and the answers I found online all seem to agree on 'not very secure'.

Rather than trying to explain why, I provided a reasonably reputable source with a good summary. Read it if you are curious. Or don't. No need to be bite.


absolutely love it

if it could be 'tweaked' with the following suggestions - even better

- Plausible deniability built in (with one or two passwords)

- if you enter the wrong password you do not get an error message on the unencryption, but just garbage out


> I created Portable Secret to securely exchange documents via email with my mother

Very solid use case here. I installed Signal on my mom's phone, but also her phone is full of scary apps. I feel like .. let it be.


Cool project. Here is a feature suggestion:

One additional feature you can add is a recovery key.

You could use a time-limited master recovery key and encrypt the file's data key and store it within the HTML file as an encrypted header.

It of course increases the attack surface because an attacker can then just focus on the recovery key.

But it would help in the scenarios where the passphrase for the datakey is forgotten and you need a way to recover. By supplying the master recovery passphrase, the file's data key/passphrase can be recovered and the content decrypted.

This is a usability versus security tradeoff.


What does “time limited” mean here?


Time-limited i.e., you rotate master key after a fixed time, say 1 month/1 year etc., depending on the use case.

During that period the content can be recovered by using the masterkey to unwrap the data key and decipher the content. Beyond that period, if you don't remember the master key, you cannot decrypt the content.

The time-period is only a shortcut. So, for personal use, as the OP intended, resetting the masterkey each year would still offer some protection against forgetting the passphrase for the data encryption.


Time is a finicky concept with computers.

Could your time-based scheme be defeated by changing the system clock on the attacker computer?


As I explained above, time is not used in the decryption at all. You use a timer to set expiry for the masterkeyphrase. For eg: If I want to encrypt all personal communication with my family, I could use a single master key phrase for the year 2022 (for all personal correspondence). The UI could prompt me when the new year arrives to reset the master keyphrase. There would still be the file level data encryption key phrase.

In the following [] denotes a byte sequence and | denotes concatenation of two byte sequences and +/-> denotes a transformation.

Encryption

[correspondence] -> [masterkey encrypted datakey|datakey encrypted data]

Normal Decryption

[masterkey encrypted datakey|datakey encrypted data] + [datakey] -> [correspondence]

Key recovery (datakey lost/forgotten)

[masterkey encrypted datakey|datakey encrypted data] + [masterkey] -> [datakey]

Once the datakey is recovered, the encrypted data can be read.

We use keyrecovery as a backup.

We don't need to worry about clock accuracy for this as the timeframe we are talking about is in the order of days or months.

For added security you can use a different keyderivation/encryption method for the masterkey and even a different encryption method. For eg: You could use RSA to encrypt the datakey while you use AES for the data.

I hope this clarifies.


> Crack me if you can

This reminds me of LifeLock CEO's Todd Davis public challenge [1] when he revealed his Social Security number prominently on his site and billboards with overconfidence that his identity cannot be stolen but, unfortunately, he's been a victim of identity theft at least 13 times.

1. https://www.wired.com/2010/05/lifelock-identity-theft/


I'm not that confident in my tool.

That said, I ask myself every day if having my public identity associated to my project, website, etc. Was a good idea.

It certainly helped with jobs in the past, but it's scary to hear stories of devs impersonated by others.


> Portable Secret is not a product and it is barely a project

You are such a humble person as you clearly stated why this thing was built. I am, in no way, claiming that you are too confident in your work, despite it being a cool project that can be used by privacy-aware techies. Your expression Crack me if you can just triggered LifeLock's story from the deepest part of my mind.


Your tool would be safer if you used CBC (with some MAC) rather than GCM as the cipher mode, so that key & IV reuse would not be as dangerous. That said, since you generate a different salt and IV every time, the likelihood of key & IV reuse is very low, and having to implement an AEAD cipher mode by generic construction would be somewhat annoying. So I think the choice of GCM is fine enough.


I started with CBC (without MAC) and upgraded with GCM since it was a more convenient way to provide integrity without adding the MAC step manually.

I should really make sure IV/Salt are regenerated automatically after use. (there is a small print warning in the creator about reuse)


> I should really make sure IV/Salt are regenerated automatically after use.

Good idea.

> I started with CBC (without MAC)

Oof, you really didn't want to do that :) Glad you upgraded to GCM.


He also ended up leaving the company after it was learned he was guilty of a previous felony for identity fraud.


Do you have a reference for this? The internet doesn't seem to know anything about it. I suspect it is false.


https://www.phoenixnewtimes.com/news/lifelock-former-exec-an...

Apparently it was the other cofounder. I confused the two.


This is incredibly cool! Nice demo of a modern browser API I was not aware of, and it's actually useful. I can imagine using this to email confidential PDFs and other small deliverables for clients.


Exactly one of the reasons I came up with this.

One way to see this is "like encrypted PDF, but for any kind of file".


In the same vein of simplifying PGP, I wrote this little app a while ago:

https://prettyeasyprivacy.xyz

Basically a simple GUI on top of PGP. No CLI headache and is completely independent of OS. Encrypted sources follow PGP protocol so are completely backward compatible with CLI tools. Also supports both text and file encryption/decryption.

PGP impl uses proton's openPgp.js


That's a really nicely finished portable tool with great security in mind. I've built something like this a couple of months ago, trying to make it compatible with the OpenSSL lib encryption algo in case my GH account disappears one day. I never got to image encryption part though. It's nice to see that other people struggle with the same security concerns. https://github.com/doomhz/crypter


Great idea. Wanted to point out that a relatively easy solution to the phishing attack brought up several times in the discussion (where an adversary intercepts the file and creates a fake one that exfiltrates the key) is to temporarily disconnect from the internet when decrypting, and to do so in an incognito window and close it right after. So short for a 0-day browser hack, you'd be safe.

Perhaps you can add this as optional instructions to the decryption page.


snazzy.

i think self-extracting archives (like 7z's sfx stubs) edges this out as it's one less dependency. Could you create a self-extracting archive for multiple platforms?


Hi, I don’t know if this question posted because it asked me to make a stupid account. But I do have a really good question. How is this different from “TMWSD”. (This message will self-destruct.)

How are they different? Seriously they seem to have the same features but obviously if someone else created this. The. there has to be a difference, so what is the difference between these two??


I did something similar in the past and called it emergency contacts [1]. Basically a encrypted json that can be decrypted online. I use it to store emergency contact information in case I got stranded without any own device at hand.

[1]: https://github.com/jwillmer/emergency-contacts


Interesting! Never thought of adding important contact info to my emergency stash, but in retrospect it is a great idea.

Linked your project.


Not sure this is exactly prior art but clipperz password manager has an offline mode where it generates a web page with your data encrypted.


Thank you for the pointer

https://clipperz.com


The limitation of just 1 file is technical or just for simplicity? I can think of the use case of ID photos where the same single html file contains both sides of the ID, or multiple parts of a more complex document, etc... Having to input the password repeatedly over a multitude of related html files would get cumbersome pretty soon.


Multiple pictures is doable, but adds some complexity to the generated code so decided to do without. Also, there's a trivial workaround (zip file with multiple pictures).


You can embed the images into an html page as data urls, then save the HTML file.


Just was playing with this more.

Visiting the secret's page from the "recently closed" or "history" views of Brave/Chrome leaves the password in text entry box.

Edge doesn't do it.

Probably there's some easy fix for it, I'd guess, but I'm not really a web dev.


Interesting, thanks for saying something.

I'm also not a web dev, but I think I can manage to clear out the password once the secret is decrypted successfully.


or use <input type="password"> ? But then one can't read the password as one types.


Change it to text on focus, password on blur. It will still be in the history though… clearing it on submit makes the most sense.


changing the type of the input from text to password will help. also the required attribute does nothing in html if the input is not part of a form.


i have my vim extension for the purpose of keeping some private notes: https://github.com/MoserMichael/vimcrypt2

You don't have to re-enter the key during each save, the plugin keeps the key during the vim session in an encrypted form (encrypted with a temp key).

The vim extension is using openssl for aes encryption (using aes-256-ecb - so if a part of the file gets damaged then you won't loose the whole file)

(oh, vim -x seems to be doing something similar, they use blowfish as the default. I am not hashing the text in order to verify its authenticity, probably should add that to my vim extension)


Nice project! It reminds me of tiddlywiki which also has browser encryption: https://tiddlywiki.com/static/Encryption.html .


> Some secrets don’t belong in your password manager. Things like backup private keys, 2FS recovery keys, wallet keys, safe combinations, treasure maps, etc.

Why don't wallet keys, safe combinations and treasure maps belong in a password manager?


I use a password manager for online credentials I regularly need to login across devices.

There's other secrets I'd rather never upload to the cloud, with all the risks that entails. I have various other methods to store and backup those secrets. This tool is part of that toolkit.


> It’s portable because: decrypting these secrets does not require special software! All you need is a browser.

No complex, million+ SLOC codebases to install, except the one browser. I'll stick with gpg signing my pass repo and call it a day.


To be clear: I use gpg too.

But I can't expect my mom or girlfriend to learn how to use it.

With PortableSecret I can communicate privately with them, without installing or learning anything new.


So explain to us the workflow of sharing data to them

Problem: Send a file securely

Solution: Encrypt file using PortableSecret, send file over unencrypted email.

Problem: Send the decryption pasword

Solution: I can't use unencrypted email to send secrets. Let me use end-to-end encrypted Signal for that

---

What problem did you solve, that didn't complicate the process of just sending the file with Signal to begin with?


> Problem: Send the decryption pasword

I can choose a password such as 'The name of uncle Robert's favorite movie' (i.e. something that it's easy for her, but hard for everyone else).

OR

I can call her, and say: 'Just sent you a password-protected file. The password is 'Foobar'

OR

I can include the password in the email itself (doesn't protect from an attacker but protects from mail provider snooping/indexing emails).

It doesn't make my communications NSA proof. It adds a little bit of privacy. For the specific use-case, it's more than enough.


I use LastPass which FYI has a CLI tool that accesses it and even supports YubiKeys.


Hate to be that guy that ruins parties but there's a couple of obvious issues here

Firstly, the repeated Java Script delivery problem

The library that generates random numbers is bundled in your browser. However, the code that calls that library is delivered from network every time, e.g.

let iv = crypto.getRandomValues(new Uint8Array(blockSize));

This code depends on what the server yields for every connection. There is no audit trail to check how the program behaved in the past.

Secondly, passwords. When you're grandma-proofing your product, introducing a low entropy secret from which key is derived creates a weak link for the communications' key. Stretching the key with PBKDF2 doesn't really help because the initial entropy is so low.

Ideally you want very strong key stretching with memory hard hash functions like Argon2, and you'll want to target local encryption of strong random keys with the password, not the communications itself. This is why we want public key authentication for SSH server and no passwords. It's safer that the weak password stays on the user's device.

Lastly, encryption is about converting confidentiality problem into a key management problem. This application doesn't solve the key delivery problem, if exchanging a secret such as the password over e.g. a telephone line is what you need to do, you might as well use that line to exchange the super secret comms.

The author describes this as a hack, when in reality it's just a bad product that doesn't make it easy to automate best practices. I have much more trust in stuff like Signal that generates (and upgrades automatically) strong secrets, uses public key crypto, and allows authenticating key exchanges with values that are safe to say over even an eavesdropped channels.

There's even open source and reproducible builds. That stuff isn't grandma proof, but at least its researcher proof when there at least IS some audit trail.


Crypto is a browser built-in, it’s not being loaded over the network at all. The HTML file is self-contained.

Even if it was loading remote scripts, they could be secured by using an integrity hash (another modern browser feature).


Yeah you can actually just audit the self-extracting code, and create detatched signature for it for every instance.

But yeah my bad, apparently the actual problems with this tools are with usage, password hashing, and non-existent secret sharing mechanisms.


Hate to be that guy that ruins your security researcher dreams. Your Argon2 memory hard function is useful against mass surveillance and belongs in mass market products. Let's leave it there.

Despite your protests, for an average joe who just wants to stash a secret somewhere and not have it in plaintext, this is absolutely ok.


There is no reason not to use Argon2 in place of weaker alternative, especially when there's no UX overhead.

The threat model "for an average Joe who just wants to stash a secret somewhere and not have it in plaintext" should probably be written in red, font size 48.

But take a look what the author is actually saying it can be used for, i.e. to "securely store passwords". The currently available tools like KeepassXC that do just that, also use Argon2.

"Your Argon2 memory hard function is useful against mass surveillance and belongs in mass market products."

Well if this product isn't for mass-market, it's for niche use, and here I thought niche products are usually for the special security cases for people who need extra security, but you're implying average Joes should NOT use mass market grade security but something niche and less secure.


Author here.

Thank you for mentioning Argon2, I didn't know about it. https://en.wikipedia.org/wiki/Argon2

> There is no reason not to use Argon2

In this case, the reason for not using Argon2 is that it's not available: https://www.w3.org/TR/WebCryptoAPI/

> Well if this product isn't for mass-market

This is a demo for self-contained HTML encrypted secrets. Do with it what you want. Definitely not a product in the current format.


In this case, the reason for not using Argon2 is that it's not available

Then it would naturally follow you wouldn't want to implement password-dependent security systems in JS.

I can respect the HTML file that stores an encrypted note. I just struggle in finding the use case given how files are supposed to be shared using secure platforms, and how client-side encrypted cloud and FDE take care of user's personal file confidentiality.

Perhaps you can just send a self-extracting piece and perhaps it's safe enough to deliver the password over the phone, but generally when your adversary sits in the backbone of the internet (i.e. when your default email isn't secure to begin with), you're in a world of problems. Even IF you're avoiding incidental collection, defaulting to any opportunistic E2EE like iMessage, or to any E2EE protocol that isn't authenticated is better UX-wise.


This is password protected, so then an attacker must crack the password. The author exchanges the password over a phone call, which requires the password to be relatively weak, meaning the password is probably crackable. Exchanging the password via a second channel that the other user can copy and paste a more difficult password from to decyrpt the document might be more secure. The password may be more exposed, but an attacker would have to compromise both channels. Basically use two messaging platforms (one of which could be email) ideally where at least one channel is sent encrypted. For example if the other party is using their mobile phone to view the payload they should have a messaging app to copy and paste from that is at least encrypted in transit if not e2e.


This is not meant as a solution. It's a demo of a self-contained, self-extracting, portable encrypted file.

That said, the password strength and the strength of the side-channel to transmit it depend on your use case.

If we were friends for example, I may not need to send you a password at all. I could just add some secret questions we both know in the hint.

Or, at the opposite side of the spectrum, I could send you a secret as email attachment and *include the password in the email itself*. This adds zero security in certain scenarios, but for example it keeps Google bots out of your private correspondence. Which is all I want sometimes.


the author even says that this is more for convenience rather than impenetrable security:

> I created Portable Secret to securely exchange documents via email with my mother, who can’t be expected to learn PGP, age, or similar.


Challenge: make it possible to use something like Diffie Hellman[0] to exchange a key securely even over an unsecure channel but where they resulting key is actually the password to type in and "reads" like https://xkcd.com/936/ i.e. something my grandma could type in. Without reducing the key space too much to be insecure ;)

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


Passwords being transmitted over a voice call does not equate to a weak password. You can very easily communicate 4-6 English words outside the 10,000 most common to produce a password with 49-83 bits of entropy. And most people will have just as easy a time remembering 5 words as 5 alphanumerics, if not easier.


It does not mean the password needs to be weak at all. Make it a full sentence with punctuation, like:

"Don't you hate passwords that need a number and symbol?"

Easy enough to transmit over the phone and definitely more difficult than the ubiquitous "Password1!" that most people I know end up using to meet password "security" requirements.

Also, phone exchange can be preferable for many people who are less tech comfortable


Over the phone I could tell someone: "the password is the first 28 words of Psalm 23 from the King James Version." Would that be a weak password?


Yes because the paraphrase already exists in plain text somewhere public


28 words would be about 200 characters, though, and I don't think simply existing somewhere in plaintext is enough -- what if I said it is the first 28,000 words of the Latin Bible -- would you still consider that a weak password because it exists in plain text somewhere?


Funny enough, the Bible's well enough indexed, and in small enough chunks, that you could just send someone:

Psalms23:2

and have a 14 word passphrase.


"The author exchanges the password over a phone call, which requires the password to be relatively weak" -- where did you get this idea from???


I took a list of "2000 most common English words" used metaphopne to eliminate words that sound similar to other words on the list, and reduced it to a power of 2. I ended up with 512 words that are probably in all fluent English speakers vocabularies so can easily be read over the phone. It's 9 bits per word, so 7 words is 63 bits of entropy which means it's (on average) 2^62 times more computational work to brute-force than it is do decrypt. That's a pretty good margin to have.

If they were using a stupid hash like, say, MD5 the time to brute force that would still be months on a GPU, but they are using PBKDF2/SHA-1 which is significantly more work.


There is nothing requiring the password to be “weak”. It can be a strong password generated with a random number/strong password generator. Sharing a string of characters or a “weak phrase” is no different if reading it to the person.


The author recommends the use of XKCD correct-horse-battery-staple style passwords (aka diceware), which have a high ratio of entropy to ease of transmission effort.

In other words they're relatively easy to exchange over a phone call but still secure.


And you can compose them from "pre shared" secrets.

For example, the password hint for a secret I send to my sister:

- The name of our neighbors cat

- The name of your first boyfriend who scratched dad's car

- Mom's nickname for aunt Ilda

Concatenate those three with a dot. And voila, a pretty secure password without need of a side channel.

(just made this up, I don't have a sister...)


Whatever, now we know your password is "Miffy.Biffy.Boffy"


Or just put it up on the kitchen wall...

"Live well, Laugh Often, Love Much"


There needs to be a new browser standard for sandboxed html files (.htmlsbx files) that only open in a special sandboxed tab with no off-page connectivity allowed.It would be perfect for this.


Got too excited with this, created https://portablesecrets.com/

Extends OP's page to allow saving secrets for later use.


I'm jealous of how in 5 minutes you made it look 10X better. X-)


Awesome because I have a good question. How is this different than the “TMWSD” (this message will self destruct”. Seems very highly similar. But how are they different?


You could apply the same trick to also make a self-decompressing file, basically you could have self decompressing and decrypting archives, all stored in html.

Pretty cool trick


Why not use any of a bunch of other services? Surely you can't think your threat model allows for this but not 1pass?


It's not a service.

It's a simple hack and I use it for 3-4 use cases for which no service exists.

Among other things:

- It works offline

- My mom can use it

- It works on any device (even a borrowed one or a newly formatted one)

- It can save me if *all* my devices get stolen

- It can save me if I'm stranded in a foreign country without any document or trusted devices,

- Etc.


I get that, but why not use a service, instead of this manual process?

1pass literally can solve every single one of these problems.


Not speaking for the poster, I would rather trust a mainstream browser's crypto API than 1pass.


That’s idiotic…


if you've got to communicate the decryption key separately anyway, might as well just use password protected zip files, no?


Indeed, it's functionally similar to password-protected PDF or ZIP for some use cases.

You should probably not treat password-protected zips as secure: https://security.stackexchange.com/questions/35818/are-passw...


The argument your answer makes discusses confidentiality issues with passwords in Zip-files, yet the Portable Secret application doesn't take any major steps or use best practices like Argon2 to solve "brute forcing the password" problem.


neat tool. I would encrypt the payload type and extension tho

>Some browsers disable window.crypto on local files and non-TLS servers

which ones do that?


It is documented [1] as only being available in secure contexts, which is normally https:// but does include file:// urls. Testing now, it works for me in Chrome, Safari, Brave, and Firefox.

If you put:

    <script>
      window.crypto.subtle.generateKey(
        {name: "ECDSA", namedCurve: "P-256"},
        false, ["sign", "verify"])
      .then(function(key){alert(key.publicKey)})
    </script>
in a local HTML file and visit it in your browser, all four browsers alert with "[object CryptoKey]".

[1] https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subt...

[2] https://developer.mozilla.org/en-US/docs/Web/Security/Secure...


Brave and Safari that I know of.

i.e. if you run the creator with a simple HTTP server on localhost:8080 it'll block the fetch to localhost:8080/foo


for local files as well?


Yes.

If that wasn't the case, then "HTML virus" would be a thing: I send you an HTML file and, if you open it, it read files from your hard drive and uploads them to my server.


I should have clarified - I mean I was wondering if any browsers block fetch to remote URLs from local files

I do vaguely recall encountering some problem I didn't expect when I was making a tool contained in a local html file, but I dont remember which browser I was using at the time


The problem with your scenario is the reading the local files without permission, not the use of the crypto API.


You are right, I'm conflating 2 issues.

I'm pretty sure Brave was blocking window.crypto but can't remember if it was on a file or over plain HTTP


Blocking crypto on http:// is to spec (aside from localhost) and all the browsers do that.

Blocking crypto on file:// is not to spec, and testing above (https://news.ycombinator.com/item?id=34084526) none of the browsers do that.


It's been a while and I don't remember the details.

All I remember is that I was developing the secret 'creator' code using Brave (my default unsecured browser) and at some point I had to switch to Safari (which I normally save for trusted websites only).

It's possible it was a red herring, and I switched browser but the problem was something else I did at the same time.


> I keep a copy of my passport encrypted on the internet.

What use is the picture of your passport? It would be easy to fake.


It saves a bit of time for your embassy if you need a new passport urgently in another country.

> Safeguard Your Documents! Make two copies of all your travel documents in case of emergency. Leave one copy with a trusted friend or relative at home and carry the other separately from your original documents. To help prevent theft, do not carry your passport in your back pocket, and keep it separate from your money.

https://travel.state.gov/content/travel/en/international-tra...


Ditto.

And in addition: peace of mind.

Having a copy may not do much from legal perspective, but I'm just less worried if I know it's there.


Hopefully not oversharing. Perfect for communications with my therapist. Thank you!


YES! Better privacy for daily life. This is exactly what I had in mind.

Thank you for sharing!


Hmm, am I missing something here? Because I have been getting HTML files exactly like this for billing from my credit card company, for years and years. It's encrypted, and, when opened, accepts a simple password for decryption. No plugins or whatsoever, just pure HTML+Javascript.


This is also pure HTML+JS without dependencies.


What is the limit on file size? Trying to encrypt a 100MB file made it crash.


Data URLs have a limit, but from what I read online it is browser and platform specific.

But before you hit that limit, your browser may kill the tab because it looks like it's using too many resources. Again hardware/browser/platform specific.

All in all, I'm glad this cannot be used as-is for pirate movies. That would have kept me from releasing it.


Why would I use this? I don't know this guy from Adam. (laughing)


>Some secrets don’t belong in your password manager. Things like backup private keys, 2FS recovery keys, wallet keys, safe combinations, treasure maps, etc.

Uh, I put everything in my Keepass safe, then write the password down in an envelope in a secure location in my house.


Nice idea but it seems not resilient against a rainbow attack.


It looks like it uses a randomly generated unique 128bit salt from crypto.getRandomValues, can you explain what it is doing wrong to be rainbow attack resistant?

https://github.com/mprimi/portable-secret/blob/main/creator/...


There's a ~$400 bounty for anyone who'd like to try.


Hold my beer for a few billion years while I crack it.


The bounty password looks like 2 names, a type of flower, and a two word object. That significantly reduces the search space. Though, it's likely at least one of those words are non-standard or wouldn't be found in any wordlist.


All words appear in some wordlist.

This is the kind of password I use to protect my actual secrets. So if someone is able to crack it, I'd like to know. The bounty is for a 'realistic' use case.


If you want to avoid wordlist vulnerabilities, try this:

Choose a lyric from a favorite song. Concatenate the first letter of each word in the lyric. Example:

“Rock the Casbah Sharif don't like it”

Becomes:

rtcsdli

Add capitalization or numbers/special characters according to your own pref. For example, maybe your decide to alternate lower and upper case and always end with a bang:

rTcSdLi!

Although you have to use the same capitalization rules for all passwords if you have any hope of remembering them.


That is security by obscurity. If somebody knows your method, they can scrape the lyrics for all popular songs, narrow your password down to a few million possible passwords and just try them all.


> to a few million possible passwords

The combinations are easily in the trillions, likely much much more. Read the algorithm.

An algorithm for password generation is not security by obscurity.


10s of thousands of popular songs, dozens of lines per song.

> Although you have to use the same capitalization rules for all passwords if you have any hope of remembering them.

So no additional combinations from that. Your algorithm is simple and common enough that it's possible that an attacker can figure it out from a single leaked password. With one leaked password they've compromised all of your passwords to anything they have the capability of trying a few million passwords on.


You wrote Pooh songs. Not me. There are millions of songs with lyrics. Billions of lines of lyrics. Trillions of combinations that include upper and lower case. Good luck.


If your favorite song is by Pearl Jam you get an extra layer of security:

https://www.youtube.com/watch?v=xLd22ha_-VU


I bet 1000 years will be enough as tech and math progresses.

Or 24h, flight tickets, and a wrench.


Yeah, plus they even give hints to the password complexity, so unless that is a red herring, this should be pretty simple to crack, if not CPU consuming.

Just combine https://github.com/mejdoubi/rainbow-table and their algorithm together. It would probably take me a few hours to put together, but for someone who is very familiar with cryptography, it would be minimal work.


I think the author of that repo misunderstands what a rainbow table is. I only quickly skimmed the code, but it doesn't seem to do anything related to rainbow tables.

On top of that, a rainbow table (if that is what you're looking to use) would not help here. The password is both very long and salted.


The repo was just a quick example of how one would use a rainbow table to crack the password. Yes, the fact that it only generates a simple rainbow table means that it isn't the holy grail to the exercise, but the idea of a rainbow table is that someones out there have already been running and generating a rainbow table for many years.


I'm willing to sweeten the deal.

What amount of money would make you actually try to crack it?


Sounds like a quick $400 for you then. :)


now the ultimate problem: How to share the key (password)


Doesn't require any special software. Just a browser.


The main problem with this is that someone uses it outside of its intended use cases, which even cultured people are missing. Jokes aside, great hack!


Definitely intended for more technical audiences, lots of sharp edges.


Sure, that's clear. Mine was an appreciation comment, but all the comments stating all the potential issues don't get that you're not proposing it to the government.


Any way to make this work with passkeys?


Currently, WebAuthn/Passkeys are only designed for signing; you could re-use a challenge to be signed, but then the signature is as secure as a password (i.e., your Passkey would produce the same signature every time.)

WebAuthn also only works in secure contexts (HTTPS)—you couldn't make it work in a plain .html file.


Nice idea.

password protected zip files are portable too.



This would make a great 2600 article.


Thank you for saying so. I've been noodling with the idea of trying to submit a HOPE talk.


> Choosing a good password

> Choosing a strong-enough password is key (pun intended).

> Eventually I’ll fill in this paragraph. For now all you get is the obligatory XKCD: correct-horse-battery-staple

Might as well have a password generator in the tool itself.




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

Search: