{"id":13610423,"url":"https://github.com/mprimi/portable-secret","last_synced_at":"2025-04-14T22:54:34.747Z","repository":{"id":65023093,"uuid":"536750959","full_name":"mprimi/portable-secret","owner":"mprimi","description":"Better privacy without special software","archived":false,"fork":false,"pushed_at":"2024-07-21T21:15:10.000Z","size":229,"stargazers_count":1727,"open_issues_count":16,"forks_count":117,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-04-14T22:54:21.695Z","etag":null,"topics":["cryptography","encryption","javascript","password-manager","privacy","secrets-management","security","web-cryptography-api"],"latest_commit_sha":null,"homepage":"https://mprimi.github.io/portable-secret/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mprimi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-14T20:35:11.000Z","updated_at":"2025-04-03T15:30:04.000Z","dependencies_parsed_at":"2024-05-30T04:34:06.809Z","dependency_job_id":"962248fd-4e19-4798-9ede-48977c6fbf1a","html_url":"https://github.com/mprimi/portable-secret","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mprimi%2Fportable-secret","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mprimi%2Fportable-secret/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mprimi%2Fportable-secret/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mprimi%2Fportable-secret/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mprimi","download_url":"https://codeload.github.com/mprimi/portable-secret/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248975330,"owners_count":21192208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","encryption","javascript","password-manager","privacy","secrets-management","security","web-cryptography-api"],"created_at":"2024-08-01T19:01:44.579Z","updated_at":"2025-04-14T22:54:34.722Z","avatar_url":"https://github.com/mprimi.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"# 🔐 Portable Secret\n\nBetter privacy, without special software.\n\n## TL;DR;\n\nPortable Secret is a little hack that allows you to:\n\n - Send encrypted messages/images/files over insecure channels (email, messaging, ...)\n - Store sensitive information (passwords, documents) in insecure locations (web, Cloud drives, USB drives)\n\nIt's portable because: **decrypting these secrets does not require special software!**\nAll you need is a browser.\n\nI created Portable Secret **to securely exchange documents via email with my mother**, who can't be expected to learn [PGP](https://en.wikipedia.org/wiki/Pretty_Good_Privacy), [age](https://github.com/FiloSottile/age), or similar.\n\nI also use Portable Secret to store some my most sensitive secrets (private keys, 2FA recovery codes, etc.)\n\nFinally, I use it to store copies of important documents (like a picture of passport). These documents are accessible to me from anywhere, **even if all my trusted devices have been stolen or lost**.\n\nSounds too good to be true? Keep reading. This is for you.\n\n---\n\nPortable Secret is not a product and it is barely a project.\n**It is just a neat trick, a *hack***.\n\nThe [source code](https://github.com/mprimi/portable-secret) and [creator tool](https://mprimi.github.io/portable-secret/creator/) are provided as a demonstration.\n\n**Update January 2023**: [Rocky W.](https://www.rocky.dev/) took this idea and ran with it, creating a beautiful full-fledged product: [PrivacyProtect.dev](https://www.privacyprotect.dev/)\n\n---\n\n## How it works\n\nA 'Portable Secret' is simply an HTML file that also contains:\n - An encrypted payload\n - Some Javascript that calls into the browser's [Web Cryptography APIs](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)\n\nAny (reasonably modern) web browser can open the file, even without an internet connection!\nIf you know the password, you can recover the secret within.\n\n[Here's an example](https://mprimi.github.io/portable-secret/examples/example-message.html) (the password is `banana`)\n\nNotice that the file is self-contained and has no external dependencies!\nIt can be carried on a USB drive and decrypted without an internet connection, on any device that has a web browser.\n\nTo understand how it works, go ahead and [create yourself a secret](https://mprimi.github.io/portable-secret/creator/). Download and inspect the generated Portable Secret.\n\nThe embedded code is straightforward:\n - Take the password and generate a key\n - Use the key to decrypt the payload\n - Display the decrypted secret\n\n---\n\n## How I use Portable Secret\n\n### Private communication\n\nDo you want to communicate privately with people, but you can't expect them to learn how to use PGP?\n\nSend a Portable Secret. For example as email attachment.\n\n \u003e Hey ___, attached to this email is the PDF and data you requested, but it's encrypted. Never double-click on attachments, it's dangerous! Give me a call when you get this, and I'll show you how to read it.\n\nWhenever they call me, I tell them:\n \u003e Right-click on the attachment and 'Open with...' any browser.\n \u003e The password is 'banana_split'.\n \u003e Now you can save the decrypted PDF.\n\n### Store top-level secrets\n\nSome secrets don't belong in your password manager. Things like backup private keys, 2FS recovery keys, wallet keys, safe combinations, treasure maps, etc.\n\nUsing Portable Secret, I can keep copies of these critical keys all over the place (Cloud drives, USB drives, all my devices, etc).\n\nEven if some of these copies end up stolen (e.g. I lose a USB stick), I am not concerned anyone will be able to recover the secrets within.\n\nThe passwords are long sequence of words that are trivial for me to remember (thanks to the hints provided), but impossible for anyone else to guess or crack.\n\n### Emergency documents on the go\n\nHave you ever gotten stranded in a foreign country without any of your devices or documents? It's not fun.\n\nI keep a copy of my passport encrypted on the internet. It's just an HTML file, it's easy to host. If I find myself stranded again, I can use any computer/device to retrieve it.\n\n[Here's an example of ID document safely encrypted in plain sight](https://mprimi.github.io/portable-secret/examples/example-image.html).\n\n---\n\n## Cryptography\n\nThe following is a schematic representation of the encryption scheme implemented by the PortableSecret creator, as well as the decryption happening in the  PortableSecret itself.\n\n![Cryptography](./images/cryptography.png)\n\nThis scheme and its parameters follow best practices and guidelines recommended by [NIST](https://www.nist.gov/cryptography) and [OWASP](https://owasp.org).\n\n### Encryption\n\n[`AES-GCM`](https://en.wikipedia.org/wiki/Galois/Counter_Mode) is used for Symmetric Authenticated Encryption.\n\n - Symmetric because the same key is used to encrypt and decrypt\n - *Authenticated* because it can verify the message **integrity** (if the ciphertext is tampered with, then it will fail to decrypt. As opposed to producing an invalid plaintext)\n\n### Key derivation\n\n[`PBKDF2`](https://en.wikipedia.org/wiki/PBKDF2) is used to turn a text password into an AES key.\nThe purpose of this module is slowing down dictionary-based brute-force attacks.\n\nUnfortunately, the Web Crypto APIs do not support stronger KDFs such as [`scrypt`](https://en.wikipedia.org/wiki/Scrypt), [`bcrypt`](https://en.wikipedia.org/wiki/Bcrypt), or [Argon2](https://en.wikipedia.org/wiki/Argon2).\n\n---\n\n## Bounty: Crack me if you can\n\nDo you think this cannot possibly be secure? Great, prove it.\n\n[This secret](https://mprimi.github.io/portable-secret/examples/bounty.html) contains the recovery key for a Bitcoin wallet. Crack it and take my money!\n\n---\n\n## Miscellaneous\n\n### Choosing a good password\n\nChoosing a strong-enough password is key (pun intended).\n\nEventually I'll fill in this paragraph. For now all you get is the obligatory XKCD: [correct-horse-battery-staple](https://xkcd.com/936/)\n\n### On tools\n\nPortable Secret is a *tool*. As such, it can be used *wrong* (e.g. weak password), or used to do bad things (e.g., exfiltrate intellectual property).\n\nI cannot take responsibility for such misuse any more than a hammer manufacturer can take responsibility for me hammering my thumb, or using the hammer to attack someone.\n\n### Prior art\n\nI came up with Portable Secret on my own, but I have since found a few projects that do something similar.\n\n[StatiCrypt](https://github.com/robinmoisson/staticrypt)\n\n[PolySafe](https://github.com/fmeum/polysafe)\n\n[`hscrypt`](https://smondet.gitlab.io/hscrypt/)\n\n[Hypervault](http://hypervault.github.io)\n\n[Encrypted HTML Vault](https://github.com/ccorcos/encrypted-html-vault)\n\n[UltraCrypt](https://9p4.github.io/hackna/)\n\n[html-vault](https://github.com/dividuum/html-vault)\n\n[Password Protect My File](https://github.com/louissobel/ppmf)\n\n[Emergency Contacts](https://github.com/jwillmer/emergency-contacts)\n\n[Digi-Cloak](https://github.com/kaushalmeena/digi-cloak)\n\n[Pretty Easy Privacy](https://prettyeasyprivacy.xyz/)\n\nIf you are aware of other similar/related projects, please let me know and I'll link them here.\n\n### Feedback\n\nI would love to hear what you think of this project, good, bad, or ugly.\n\nPlease use [GH issue](https://github.com/mprimi/portable-secret/issues) to report a problems and make suggestions. For everything else, start a [GH Discussion](https://github.com/mprimi/portable-secret/discussions).\n\nYou can also find my email on my homepage (linked from my GH profile).\n\nOr discuss on [HackerNews](https://news.ycombinator.com/item?id=34083366)\n\n## References\n\nhttps://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n\nhttps://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html\n\nhttps://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html\n\nhttps://en.wikipedia.org/wiki/Galois/Counter_Mode\n\nhttps://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf\n\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmprimi%2Fportable-secret","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmprimi%2Fportable-secret","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmprimi%2Fportable-secret/lists"}