{"id":14980082,"url":"https://github.com/nurupo/paper-store","last_synced_at":"2025-07-26T18:07:51.266Z","repository":{"id":69743956,"uuid":"143403644","full_name":"nurupo/paper-store","owner":"nurupo","description":"Cold store small files on paper as QR codes -- PGP keys, Bitcoin keys, Tox keys or any other small files in general.","archived":false,"fork":false,"pushed_at":"2024-04-07T03:59:44.000Z","size":228,"stargazers_count":39,"open_issues_count":1,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-08T23:32:01.594Z","etag":null,"topics":["bitcoin-wallet","cold-storage","gpg","pdf","pgp","printing","qr","qr-code","qrcode","tox"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/nurupo.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},"funding":{"github":"nurupo","custom":["https://github.com/nurupo/donate","https://paypal.com/donate?hosted_button_id=9HJHAH5UDL3GL","https://blockstream.info/address/34qxFsZjs1ZWVBwer11gXiycpv7QHTA8q3"]}},"created_at":"2018-08-03T08:53:39.000Z","updated_at":"2024-12-03T18:58:16.000Z","dependencies_parsed_at":"2024-09-24T04:02:01.881Z","dependency_job_id":null,"html_url":"https://github.com/nurupo/paper-store","commit_stats":{"total_commits":4,"total_committers":1,"mean_commits":4.0,"dds":0.0,"last_synced_commit":"f369e81f8723123d89b8ac527f955e4d4c60b7fd"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nurupo/paper-store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurupo%2Fpaper-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurupo%2Fpaper-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurupo%2Fpaper-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurupo%2Fpaper-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nurupo","download_url":"https://codeload.github.com/nurupo/paper-store/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nurupo%2Fpaper-store/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267205998,"owners_count":24052762,"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","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["bitcoin-wallet","cold-storage","gpg","pdf","pgp","printing","qr","qr-code","qrcode","tox"],"created_at":"2024-09-24T14:01:15.883Z","updated_at":"2025-07-26T18:07:51.219Z","avatar_url":"https://github.com/nurupo.png","language":"Shell","funding_links":["https://github.com/sponsors/nurupo","https://github.com/nurupo/donate","https://paypal.com/donate?hosted_button_id=9HJHAH5UDL3GL","https://blockstream.info/address/34qxFsZjs1ZWVBwer11gXiycpv7QHTA8q3"],"categories":[],"sub_categories":[],"readme":"# Paper Store\n\nA bash script for cold storing small files on paper.\n\nStore your PGP keys, Bitcoin wallet keys, Tox profile keys, etc. on paper.\n\nWorks the best with files below 50KiB, as the resulting page count increases very fast.\n\n## Examples\n\n[Input file](examples/input.txt), [sparse PDF](examples/output_sparse.pdf), [dense PDF](examples/output_dense.pdf).\n\n## How it works\n\nThe script takes a file path as an argument, computes base64 of the file, splits the base64 into 12-line pieces, encodes each piece in a QR code, and generates a printable PDF file with all those QR codes. \nThe PDF is tested by a QR reader to make sure that you can restore the original base64 of the file off the PDF.\n(Each QR code encodes only 12 lines of base64 because QR readers have trouble decoding QR codes that contain more information than that.)\n\nTo restore the file, decode the printed QR codes, concatenate the results in the page order into a single file and decode that file as base64.\n\n## Script variants\n\nThere are two variants of the script: sparse and dense.\n\nSparse version prints just one QR code per page and includes the encoded in the QR code text for the reference of what the QR code should decode to.\n\nDense version prints four QR codes per page and nothing more.\nEach QR code is numbered within the page, so that you know in which order to scan them.\n\nBoth sparse and dense versions result in pages that are foldable in half without QR codes being on the folding line.\nThe sparse version is foldable in half exactly once.\nThe dense version is foldable in half exactly twice.\n\n## Usage\n\nMake sure you have `pdflatex`, `pdfunite`, `qrencode` and `zbarimg` programs installed, along with some common fonts.\n\nOn Debian/Ubuntu systems you can install them with\n\n```bash\napt-get install poppler-utils texlive-fonts-recommended texlive-latex-base qrencode zbar-tools\n```\n\nRun the scripts as\n\n```bash\nbash paper_store_sparse.sh \u003cpath-to-file\u003e\n```\n\nand \n\n```bash\nbash paper_store_dense.sh \u003cpath-to-file\u003e\n```\n\nThe scripts create A4-sized PDFs by default.\nIf you want to change the paper size to something other than A4, set the environment variable `PAPER_STORE_PAPER_SIZE` to any of: a0paper, a1paper, a2paper, a3paper, a4paper, a5paper, a6paper, b0paper, b1paper, b2paper, b3paper, b4paper, b5paper, b6paper, c0paper, c1paper, c2paper, c3paper, c4paper, c5paper, c6paper, b0j, b1j, b2j, b3j, b4j, b5j, b6j, ansiapaper, ansibpaper, ansicpaper, ansidpaper, ansiepaper, letterpaper, executivepaper and legalpaper.\n\nFor example, if you want to set the paper size to Letter, do\n\n```bash\nPAPER_STORE_PAPER_SIZE=letterpaper bash paper_store_dense.sh \u003cpath-to-file\u003e\n```\n\nNote that only A4 and Letter paper sizes were tested, other paper sizes will likely not work.\nFeel free to contribute a LaTeX template that scales well with the paper size, just don't scale up the images above 100% scale, QR readers have trouble scanning large QR codes.\n\n## Troubleshooting\n\nThe script tests if the original file can be restored off the PDF by scanning the QR codes with `zbarimg` and comparing the result against the base64 of the input file.\nSometimes `zbarimg` fails to scan a QR code correctly, which is a false negative, and the script fails thinking that the original file can't be restored off the PDF.\nThere is not much that can be done here to determine if it's indeed a false negative or it's actually a true negative, you can't just run the test several times, there is no non-determinism anywhere, you get the exactly the same result no mater how many times you scan the PDF with `zbarimg`, so the right to make the call is on you.\nIf you think that it is indeed a false negative, just remove the early exit on the error path from the script and don't forget to put it back later.\n\n## Consider encrypting your file\n\nConsider encrypting your file if it's not already encrypted before storing it on paper.\nEven if it's encrypted already, like the passphrase-protected GPG keystore, you might still consider encrypting it once more just to hide any unencrypted metadata, e.g. the public keys and uids are not encrypted in passphrase-protected GPG keystores, only private keys are encrypted, so whoever scans your QR codes would know that it's a GPG keystore for those public keys and the person behind the uid identity, which might not be desirable.\n\nYou can use GPG to password-protect your file like this\n\n```bash\ngpg --symmetric --cipher-algo AES256 --s2k-digest-algo SHA512 \u003cfile-to-encrypt\u003e\n```\n\nThis will encrypt the file with a symmetric AES256 cipher.\nIt will prompt you to come up with a passphrase, which is all you need to remember to decrypt the file in the future.\nMake sure you select a good passphrase.\nIt should be at least 40 characters long and be hard to bruteforce, i.e. avoid using quotes of any kind, like book quotes, song lyrics, dates of birth, phone numbers, etc.\n\nYou could also encrypt it with your existing PGP key and your preferred ciphers with\n\n```bash\ngpg --encrypt \u003cfile-to-encrypt\u003e\n```\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnurupo%2Fpaper-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnurupo%2Fpaper-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnurupo%2Fpaper-store/lists"}