{"_id":"@dangel34/pqfile","name":"@dangel34/pqfile","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dangel34/pqfile","version":"0.1.0","description":"Quantum-resistant file encryption (ML-KEM, hybrid X25519+ML-KEM-768) - Node.js bindings","license":"MIT","repository":{"type":"git","url":"git+https://github.com/dangel34/PQ-File-Encryption.git"},"main":"index.js","types":"index.d.ts","publishConfig":{"access":"public"},"napi":{"name":"pqfile","triples":{"additional":["aarch64-apple-darwin"]}},"engines":{"node":">= 16"},"scripts":{"build":"napi build --platform --release","build:debug":"napi build --platform","test":"node --test"},"devDependencies":{"@napi-rs/cli":"^2"},"optionalDependencies":{"@dangel34/pqfile-win32-x64-msvc":"0.1.0","@dangel34/pqfile-darwin-x64":"0.1.0","@dangel34/pqfile-linux-x64-gnu":"0.1.0","@dangel34/pqfile-darwin-arm64":"0.1.0"},"gitHead":"91914271282498f530d85699e38ab4d1f6e3d911","_id":"@dangel34/pqfile@0.1.0","bugs":{"url":"https://github.com/dangel34/PQ-File-Encryption/issues"},"homepage":"https://github.com/dangel34/PQ-File-Encryption#readme","_nodeVersion":"24.14.0","_npmVersion":"11.12.0","dist":{"integrity":"sha512-3cEpHr47ZWodLh7NEn06WfTIG6xcJ7IT2aJrbbNaPxM9Q3Y2djLUhtoUmJC94znguLlAGS0/xVACLsZLREAqVA==","shasum":"0b7bcd9d5c58a074c00433f850a38e674dd196af","tarball":"https://registry.npmjs.org/@dangel34/pqfile/-/pqfile-0.1.0.tgz","fileCount":4,"unpackedSize":17228,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCtI4xz5ME9exDseh7WayjUWbuM0GkpS+W4y2lmd7P/wwIhAPLGTjDE4fAr7EVeQfz60dyjlOQM+TRGaq/fmsh4iRUP"}]},"_npmUser":{"name":"dangel34","email":"derek@nappi.work"},"directories":{},"maintainers":[{"name":"dangel34","email":"derek@nappi.work"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pqfile_0.1.0_1784908838503_0.9545265483263099"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-24T16:00:38.384Z","0.1.0":"2026-07-24T16:00:38.657Z","modified":"2026-07-24T16:00:38.807Z"},"maintainers":[{"name":"dangel34","email":"derek@nappi.work"}],"description":"Quantum-resistant file encryption (ML-KEM, hybrid X25519+ML-KEM-768) - Node.js bindings","homepage":"https://github.com/dangel34/PQ-File-Encryption#readme","repository":{"type":"git","url":"git+https://github.com/dangel34/PQ-File-Encryption.git"},"bugs":{"url":"https://github.com/dangel34/PQ-File-Encryption/issues"},"license":"MIT","readme":"# pqfile (Node.js bindings)\n\nNode.js bindings for [`pqfile`](https://github.com/dangel34/PQ-File-Encryption), a\nquantum-resistant file encryption library: ML-KEM (512/768/1024) and hybrid\nX25519+ML-KEM-768 key encapsulation with ChaCha20-Poly1305 authenticated\nencryption. Built with [napi-rs](https://napi.rs); the crypto itself lives\nentirely in the `pqfile` Rust crate, not in this binding layer.\n\nEvery function returns a `Promise` and runs on libuv's worker thread pool\n(napi-rs's `AsyncTask`), not on Node's main thread - Argon2id key derivation\nand ML-KEM operations are CPU-heavy enough that running them inline would\nblock the event loop for the duration.\n\n## Install (from source, until prebuilt binaries are published)\n\n```sh\nnpm install\nnpm run build\n```\n\nPublished on npm as `@dangel34/pqfile` (the unscoped name `pqfile` is blocked -\nnpm treats it as too similar to the existing `vfile` package).\n\n## Quick start\n\n```js\nconst pqfile = require(\"@dangel34/pqfile\");\n\n// Generate a key pair\nconst { publicKey, privateKey } = await pqfile.keygen(); // level defaults to 768; also 512, 1024\n\n// Encrypt / decrypt in memory\nconst ciphertext = await pqfile.encryptBytes(publicKey, Buffer.from(\"hello, post-quantum world\"));\nconst plaintext = await pqfile.decryptBytes(privateKey, ciphertext);\nconsole.log(plaintext.toString()); // \"hello, post-quantum world\"\n\n// Encrypt / decrypt files directly (streams; flat memory use regardless of size)\nawait pqfile.encryptFile(publicKey, \"report.pdf\", \"report.pdf.pqf\");\nawait pqfile.decryptFile(privateKey, \"report.pdf.pqf\", \"report.pdf\");\n```\n\nA passphrase-protected private key:\n\n```js\nconst { publicKey, privateKey } = await pqfile.keygen(undefined, \"correct horse battery staple\");\nconst plaintext = await pqfile.decryptBytes(privateKey, ciphertext, \"correct horse battery staple\");\n```\n\nHybrid X25519 + ML-KEM-768 (defense in depth against a future ML-KEM break):\n\n```js\nconst { publicKey, privateKey } = await pqfile.keygenHybrid();\n```\n\n## Errors\n\nFailures reject the returned `Promise` with an `Error` whose message has the\nstable numeric error code from\n[`docs/ERROR_CODES.md`](../docs/ERROR_CODES.md) appended, e.g.\n`decryption failure: authentication tag mismatch (code 7)`.\n\n## Scope\n\nThis wraps `pqfile::encrypt`/`pqfile::decrypt`'s single-recipient streaming\npath only (`keygen`/`keygenHybrid`/`encryptBytes`/`decryptBytes`/`encryptFile`/`decryptFile`).\nMulti-recipient encryption, signing/`signcrypt`, Shamir sharing, certificates,\nand the other CLI features are not yet exposed here - see\n`docs/ROADMAP.md`, \"Python, Node.js, and mobile bindings\", for status.\n\n## Compatibility\n\nProduces and reads the same `.pqf` v3/v5 wire format as the `pqfile` CLI and\nGUI (see `docs/FORMAT.md`), so files are interchangeable in both directions.\n\n## CI and publishing\n\n`ci.yml`'s `bindings-node` job builds this crate and runs the test suite on\nevery push/PR. `publish-node.yml` is scaffolding for the actual npm release -\nit cross-builds the native addon for Windows/Linux x64 and macOS\n(x86_64 and aarch64), arranges them into napi-rs's standard per-platform\n`optionalDependencies` packages (`napi create-npm-dir`/`napi artifacts`), and\nwould publish all of them plus the main `@dangel34/pqfile` package\n(`napi prepublish`) on a GitHub Release being published. The `artifacts`\nstep's file-matching convention has been verified locally (a fake downloaded\nartifact directory was correctly picked up and copied into place). It\npublishes via npm Trusted Publishing (OIDC) rather than a stored token, which\nneeds npm's Trusted Publisher registered on the `@dangel34/pqfile` package\nfirst (npmjs.com -> package -> Settings -> Trusted Publisher) - GitHub\nActions, owner `dangel34`, repository `PQ-File-Encryption`, workflow\n`publish-node.yml`, environment `release`. Unlike PyPI's \"pending publisher,\"\nnpm's Trusted Publisher is configured from an *existing* package's own\nsettings page, so the very first publish needed to happen some other way: a\nmanual, interactive `npm publish` per package (`napi prepublish`'s automated\nflow can't complete npm's browser-based OTP challenge, since it shells out to\n`npm publish` as a non-interactive subprocess). Two more npm-side blocks\nturned up doing that bootstrap publish, both unrelated to anything in this\nrepo: the unscoped name `pqfile` was rejected as too similar to the existing\n`vfile` package (fixed by scoping to `@dangel34/pqfile`, npm's own suggested\nremedy - `publishConfig.access: \"public\"` was added so a scoped package still\npublishes publicly by default), and the platform-specific package name\n`pqfile-win32-x64-msvc` was separately rejected by npm's spam-detection\nheuristic before the rename (unresolved as of this writing - the scoped\nequivalent, `@dangel34/pqfile-win32-x64-msvc`, has not yet been retried). The\nmacOS/Linux legs of the build matrix have only ever been cross-checked by\nreading napi-rs's own source, not built on this repo's Windows dev machine.\n`aarch64-unknown-linux-gnu` is deliberately left out of `napi.triples` for\nnow - cross-compiling it needs a zig toolchain step (`napi build --zig`) this\nhasn't been wired up for.\n","readmeFilename":"README.md","_rev":"1-3ef12e1e50bf20732d95dd952bde02e9"}