{"_id":"hashkeys","_rev":"16-801b37cc8736500bdc4b6463d5a4e251","name":"hashkeys","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"hashkeys","version":"0.1.0","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.1.0","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://hashkeys.js.org/","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"aba3c85814e84bc6fbad9c20feade1de185f2648","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.1.0.tgz","fileCount":4,"integrity":"sha512-r4DGRKhU6sjNZetxULsGpqKvyHbRvxi1yPRAeM47WaTg27ZeJWRoYTvrn+HdyIhEepCjNSoL849Ho+ChY/siEQ==","signatures":[{"sig":"MEUCIQD4WIeTMl+0G7gb2iVYNAgg/UBIEsKHguQDGO1KmFiFowIgbUpBD7qeckN6ASMKMOwyVVMjVqn1Sh70QsBcfTNo8ZI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":99755},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"6ea2ebae3ad7fb7f0e70a8b6761c6d979607cfc4","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"11.1.0","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"20.18.2","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.1.0_1756829294095_0.7115994657159053","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"hashkeys","version":"0.1.1","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.1.1","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://github.com/DeFUCC/hashkeys","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"8e16103168b7d41c5760509aaa648b20f217e5c5","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.1.1.tgz","fileCount":4,"integrity":"sha512-4dK4qSgjZa+1qOFBdUE9eXBvh1GbdRci6ao+k0NT3CqkEMg0e6B7TWlo9Y627NSz8FQPkfkMmkt2hWSJ+iQLOQ==","signatures":[{"sig":"MEUCICGcXP7S4QWbOz1HW7b8gIhwX7aVYkROaNgRdeOc7Jp8AiEAkhyG3jCOxhqA3FsbbL6m1XPCdXWKQNU/8/TSLfu0LvQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":112360},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"4c4c497839c531b3d0884c663d49c3c08a3c5a5d","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"10.9.3","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"22.18.0","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.1.1_1756834115394_0.9670429607577933","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"hashkeys","version":"0.1.2","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.1.2","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://github.com/DeFUCC/hashkeys","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"1f1c7d4c9bf0a79fb4a1620e29f1b9d86dcda355","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.1.2.tgz","fileCount":4,"integrity":"sha512-BSvBY9Ua22X/ozPVeAPU+NBXbQ4KE33hdA03JmcNGDUK/0+JM0dtsE/aXdusAZG3uXImDKctj25ghHAZPRz3fQ==","signatures":[{"sig":"MEUCIQDazhxTiLZ+Z2LvY+fNQCEbGscCIa98bQjo43rndh0FSgIgAJ+FLUYuVGJyLoxaW9+J7usawThFBfTq62rYnM6j7HM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":115652},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"b4920d00132e9999d4839e30a998f12b57eb7fb7","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"10.9.3","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"22.19.0","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.1.2_1756836231104_0.1501868324316673","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"hashkeys","version":"0.1.3","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.1.3","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://github.com/DeFUCC/hashkeys","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"1af9321b6d0fd4ea96ac1336b6cceda2cdef4399","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.1.3.tgz","fileCount":4,"integrity":"sha512-YE3WtTHwZ1F+Uf8L+e5lSzfWFmVgHHplo+Yb6hi8MB0RNsqGVjJJ4KxyRGoj2bDxS6ZUlybRuj+Q57Y07TQKhQ==","signatures":[{"sig":"MEYCIQDXimF/VzyBLi8zb2oHifDzkiBkUpGBPf2rGVbWMjmp9AIhAKgF9joAp75+m/kB/cu+Izw7kyIV4YZ145ldqkowiHnY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":114181},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"ac44d0411df73613be6b4032fcbe985a2e3b511f","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"10.9.3","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"22.19.0","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.1.3_1756988671126_0.4524940810775935","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"hashkeys","version":"0.2.0","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.2.0","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://github.com/DeFUCC/hashkeys","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"e24b09f5124bb9931fd887d2486b4b74e3ae485d","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.2.0.tgz","fileCount":4,"integrity":"sha512-FrDmEDo1xAKzaLrw+fyIXnHwsbN6et0gnycX1hRH1JZxyZn7J+EYPseOYAY3rQbBT6A8BKHyQqItyxcnAa1Rhg==","signatures":[{"sig":"MEUCIGedYdmym9bxNo8Uj5r7cfXYXUVJPItXgJ8xlJC+Kj+vAiEAxlinLSKkEhokCdb6qfjKpJ4wVxR1+jz1R6He6nVKraU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":118838},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"7d86f1c94d1bc356c4ef2a639a60930b7e632726","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host","lib.worker":"vite build --config vite.config.lib.worker.js"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"10.9.3","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"22.19.0","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.2.0_1757145484887_0.43407479585865105","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"hashkeys","version":"0.2.1","author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","_id":"hashkeys@0.2.1","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"homepage":"https://hashkeys.js.org","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"dist":{"shasum":"7f9fe0a2b190bbfff32771bf089ebe9a0eb08fd5","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.2.1.tgz","fileCount":4,"integrity":"sha512-W9KvWIH7Z4DwGP14m0qam2TK2z+ssAjCK+slBOv7QWqZUz97PVZGg/JgB35FU9hjd0XOGSJ+GP8g781/ZLnYWQ==","signatures":[{"sig":"MEUCIC1++2op8o9mJNdqCM9udPr1bpJQ0iTYhr+EmXNhyh5UAiEAyC+BYucjCtfUlPUiM3PILu6sVzbImU/liE9I1cY3ewY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":129418},"main":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"type":"module","module":"./lib/index.js","engines":{"node":"22"},"exports":"./lib/index.js","gitHead":"340cd3c2d8249e3c4271d2dcd0abd8cfeeae5d05","scripts":{"dev":"vite --host","lib":"vite build --config vite.config.lib.js --emptyOutDir","build":"vite build --emptyOutDir","preview":"vite preview --host"},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"repository":{"url":"git+https://github.com/DeFUCC/hashkeys.git","type":"git"},"_npmVersion":"10.9.3","description":"Reactive Noble cryptography for p2p identity","directories":{},"_nodeVersion":"22.19.0","dependencies":{"@scure/base":"^2.0.0","@noble/curves":"^2.0.0","@noble/hashes":"^2.0.0","@noble/ciphers":"^2.0.0","shamir-secret-sharing":"^0.0.4"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.15.0","devDependencies":{"pug":"^3.0.3","vue":"3.6.0-alpha.2","vite":"^7.1.3","unocss":"^66.4.2","@vueuse/core":"^13.7.0","@unocss/reset":"^66.4.2","@vue/compiler-sfc":"^3.5.19","@vitejs/plugin-vue":"^6.0.1","@iconify-json/lucide":"^1.2.63","@unocss/extractor-pug":"^66.4.2","vite-plugin-singlefile":"^2.3.0","@vue/language-plugin-pug":"^3.0.6"},"peerDependencies":{"vue":"^3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/hashkeys_0.2.1_1757322705725_0.3301139121723138","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"hashkeys","version":"0.3.0","description":"Reactive Noble cryptography for p2p identity","type":"module","homepage":"https://hashkeys.js.org","repository":{"type":"git","url":"git+https://github.com/DeFUCC/hashkeys.git"},"author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","packageManager":"pnpm@10.26.0","engines":{"node":"22"},"scripts":{"dev":"vite --host","build":"vite build --emptyOutDir","lib":"vite build --config vite.config.lib.js --emptyOutDir","preview":"vite preview --host"},"dependencies":{"@noble/ciphers":"^2.1.1","@noble/curves":"^2.0.1","@noble/hashes":"^2.0.1","@scure/base":"^2.0.0","shamir-secret-sharing":"^0.0.4"},"peerDependencies":{"vue":"^3.5.0"},"devDependencies":{"@iconify-json/lucide":"^1.2.81","@unocss/extractor-pug":"^66.5.10","@unocss/reset":"^66.5.10","@vitejs/plugin-vue":"^6.0.3","@vue/compiler-sfc":"^3.5.25","@vue/language-plugin-pug":"^3.1.8","@vueuse/core":"^14.1.0","pug":"^3.0.3","unocss":"^66.5.10","vite":"^7.3.0","vite-plugin-singlefile":"^2.3.0","vue":"3.6.0-alpha.2"},"main":"./lib/index.js","module":"./lib/index.js","exports":"./lib/index.js","pnpm":{"onlyBuiltDependencies":["bufferutil","esbuild","node-datachannel","utf-8-validate","utp-native"]},"_id":"hashkeys@0.3.0","gitHead":"c011cbf1fee53313d48988620f1dbcb1e79e2c89","bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-J30Y8uskvZKvd8y1ctbE2V/7x8Nz0nW2QCo0akjQ0bLxK5FiLY4jvU8XriSuZevRKSeLerzIfMHRZ0uJfUV65w==","shasum":"22eb6ebed6e1ce960a41aca9d62022e32b838932","tarball":"https://registry.npmjs.org/hashkeys/-/hashkeys-0.3.0.tgz","fileCount":4,"unpackedSize":132656,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/hashkeys@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB6mYs20/9S/KXjfG/Un//lo6PHxdy8YXyubeOuBtf+bAiEAlFP3xpv7kh0a7aAGEj+hcFoUQ6gfcv/QUzP7e8zy7w0="}]},"_npmUser":{"name":"davay","email":"davay@frkt.ru"},"directories":{},"maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hashkeys_0.3.0_1765987336607_0.8841554101063043"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-02T16:08:14.094Z","modified":"2025-12-17T16:02:17.151Z","0.0.1":"2011-09-14T02:11:42.808Z","0.1.0":"2025-09-02T16:08:14.275Z","0.1.1":"2025-09-02T17:28:35.619Z","0.1.2":"2025-09-02T18:03:51.385Z","0.1.3":"2025-09-04T12:24:31.299Z","0.2.0":"2025-09-06T07:58:05.051Z","0.2.1":"2025-09-08T09:11:45.902Z","0.3.0":"2025-12-17T16:02:16.759Z"},"bugs":{"url":"https://github.com/DeFUCC/hashkeys/issues"},"author":{"name":"davay42","email":"davay@defucc.me"},"license":"MIT","homepage":"https://hashkeys.js.org","repository":{"type":"git","url":"git+https://github.com/DeFUCC/hashkeys.git"},"description":"Reactive Noble cryptography for p2p identity","maintainers":[{"name":"davay","email":"davay@frkt.ru"}],"readme":"# HashKeys\n\nReactive Noble cryptography for local‑first apps and p2p identity. `hashkeys` exposes a Vue 3 composable `useAuth()` that returns a reactive object running all cryptography in a Web Worker and provides a simple API for:\n\n- Authentication from a passphrase, a bech32 master key or Shamir shares\n- Identity and public keys\n- Sign/verify\n- Symmetric and end‑to‑end encryption\n- HKDF key derivation\n- PassKeys (WebAuthn) helper flows\n- Session persistence\n\n---\n\n## Install\n\n- Peer dependency: Vue 3\n- Modern bundler (Vite recommended)\n\n```bash\nnpm i hashkeys\n# or\npnpm add hashkeys\n```\n\n---\n\n## Quick start (Vue 3)\n\n```vue\n<script setup>\nimport { useAuth } from 'hashkeys';\n\nconst auth = useAuth();\n\nasync function onLogin() {\n  try {\n    // Pass a strong passphrase OR a bech32 master key (hkmk…)\n    await auth.login('correct horse battery staple');\n    console.log('identity', auth.identity); \n  } catch (e) {\n    console.error(e);\n  }\n}\n\nasync function doSign() {\n  const { signature, publicKey } = await auth.send('sign',{ message: 'hello world' });\n  console.log(signature, publicKey);\n}\n</script>\n\n<template>\n  <div>\n    <button @click=\"onLogin\">Login</button>\n    <p v-if=\"auth.loading\">Loading…</p>\n    <p v-else>Authenticated: {{ auth.authenticated }}</p>\n\n    <button :disabled=\"!auth.authenticated\" @click=\"doSign\">Sign message</button>\n\n    <div v-if=\"auth.error\" class=\"error\">{{ auth.error }}</div>\n  </div>\n</template>\n```\n\n---\n\n## API\n\nThe package exports a composable `useAuth()` (also as the default export) that returns a Vue `reactive` object with state and async methods that proxy to an internal Worker. The worker itself is also provided as `AuthWorker` for direct use.\n\n### Constructing\n\n- `useAuth(prefixOrOptions?)`\n  - `prefixOrOptions` can be:\n    - string: e.g. `'hk'`\n    - Vue Ref('string'): e.g. `ref('hk')`\n    - object: `{ prefix: 'hk' }` or `{ prefix: ref('hk') }`\n  - The prefix must be exactly 2 lowercase letters; invalid inputs fall back to `'hk'`.\n\n### State\n\n- `authenticated: boolean`\n- `loading: boolean`\n- `error: string | null`\n- `publicKey: string | null` — bech32 `hkpk…`\n- `identity: string | null` — bech32 `hkid…` (`SHA256(publicKey)`)\n- `encryptionKey: string | null` — bech32 `hkek…` (X25519 public key for E2E on ed25519)\n- `curve: 'ed25519' | 'secp256k1' | null`\n\n### Methods\n\n#### login(secret)\n\nAuthenticate using a passphrase or a bech32 master key.\n\nParameters:\n\n- `secret` — string. Either a strong passphrase or `hkmk…` bech32 master key.\n\nReturns: object with `authenticated: true` and current keys (`publicKey`, `identity`, optionally `encryptionKey`, `curve`).\n\n#### logout()\n\nEnd the session and clear in-memory state. Also clears the stored master key in session storage.\n\nReturns: object with `authenticated: false`.\n\n#### auth.send('sign',{ message })\n\nCreate a detached signature for the provided data.\n\nParameters:\n\n- `message` — string or Uint8Array. The data to sign.\n\nReturns: `{ signature, publicKey }` (bech32-encoded).\n\nRequires authentication.\n\n#### auth.send('verify',{ message, signature, publicKey })\n\nVerify a detached signature using the provided public key. Does not require authentication.\n\nParameters:\n\n- `message` — string or Uint8Array. The original message that was signed.\n- `signature` — bech32 `hksg…`. The signature to verify.\n- `publicKey` — bech32 `hkpk…`. The public key to verify against.\n\nReturns: `{ valid: boolean }`.\n\n#### auth.send('encrypt',{ data, recipientPublicKey, algorithm })\n\nEncrypt data. If `recipientPublicKey` is omitted, uses a symmetric key derived from your master key. If provided, performs E2E encryption (ed25519/X25519) to the recipient.\n\nParameters:\n\n- `data` — string or Uint8Array. The data to encrypt.\n- `recipientPublicKey` — optional bech32 `hkek…` (recipient's X25519 public key).\n- `algorithm` — optional string. Defaults to `xchacha20poly1305`. With a recipient on ed25519, the algorithm becomes `xchacha20poly1305-x25519`.\n\nReturns: `{ ciphertext, nonce, algorithm }` (nonce/ciphertext bech32-encoded).\n\nRequires authentication.\n\n#### auth.send('decrypt',{ ciphertext, nonce, senderPublicKey, algorithm })\n\nDecrypt data. For symmetric self-encryption, only `ciphertext` and `nonce` are required. For E2E, provide the sender's public key so the worker can derive the shared secret via ECDH (your private key never leaves the worker).\n\nParameters:\n\n- `ciphertext` — bech32 `hkct…`.\n- `nonce` — bech32 `hknc…`.\n- `senderPublicKey` — optional bech32 `hkek…` (sender's X25519 public key). Required for E2E.\n- `algorithm` — optional string. Usually the value returned by `encrypt()`.\n\nReturns: `{ decrypted, decryptedHex }`.\n\nRequires authentication.\n\n#### auth.send('derive-key',{ context, length })\n\nDerive application- or feature-specific key material using HKDF.\n\nParameters:\n\n- `context` — string. A namespace for the derivation (e.g., app or feature name).\n- `length` — number, optional. Bytes of key material to derive (default 32).\n\nReturns: `{ derivedKey, context, length }` (bech32-derived key material).\n\nRequires authentication.\n\n#### auth.send('get-identity')\n\nFetch identity information.\n\nReturns: `{ identity, publicKey, curve }`.\n\nRequires authentication.\n\n#### auth.send('get-public-key')\n\nFetch the current public key and associated metadata.\n\nReturns: `{ publicKey, identity, curve }`.\n\nRequires authentication.\n\n#### auth.send('get-private-key')\n\nExport the current bech32 master key.\n\nReturns: `hkmk…` string.\n\nRequires authentication.\n\n#### auth.send('get-split-key',{ shares, threshold })\n\nSplit the master key into multiple shares using Shamir's Secret Sharing. A subset of these shares (specified by `threshold`) is required to reconstruct the master key.\n\nParameters:\n- `shares` — number. Total number of shares to create.\n- `threshold` — number. Minimum number of shares required to reconstruct the master key.\n\nReturns: `Array<string>` of bech32-encoded shares (prefixed with `hksh1…`).\n\nRequires authentication.\n\n#### auth.send('combine-key',{ shares })\n\nCombine Shamir shares to reconstruct the master key. The number of shares provided must be at least equal to the threshold used when splitting.\n\nParameters:\n- `shares` — Array of bech32-encoded shares (each prefixed with `hksh1…`).\n\nReturns: `hkmk…` string (bech32-encoded master key).\n\nRequires authentication.\n\n#### recall()\n\nAttempt to read a stored bech32 master key from `sessionStorage` and log in automatically.\n\nReturns: `true` if a stored key was found and a login attempt was made, otherwise `false`.\n\n#### clearError()\n\nReset the `error` field to `null`.\n\n#### passKeyAuth(name)\n\nCreate/register a WebAuthn credential (PassKey) for the given user name and log in using the generated credential ID (encoded as `hkwa…`).\n\nParameters:\n\n- `name` — string (user handle).\n\nReturns: boolean indicating whether login was initiated.\n\n#### passKeyLogin()\n\nPrompt for an existing PassKey and log in using its credential ID (encoded as `hkwa…`).\n\nReturns: boolean indicating whether login was initiated.\n\nNotes:\n\n- All methods throw if not authenticated, except `verify`, which operates on provided public inputs.\n- PassKeys helpers encode the WebAuthn `rawId` with Bech32 HRP `hkwa` and use it as the login secret. The worker derives keys from whatever string you pass to `login()`; `hkwa…` is simply a recognizable wrapper for the credential ID.\n\n### Authentication with Shamir Shares\n\nYou can now authenticate using Shamir shares instead of a passphrase or master key. Simply paste one or more shares (one per line) into the login field. The system will automatically detect and combine valid shares.\n\nExample:\n```js\n// Split the master key into 3 shares, requiring 2 to reconstruct\nconst shares = await auth.send('get-split-key',{ shares: 3, threshold: 2 });\n// shares = ['hksh1...', 'hksh1...', 'hksh1...']\n\n// Later, authenticate with at least 2 shares\nawait auth.login('hksh1...\\nhksh1...');\n// or with all 3 shares\nawait auth.login(shares.join('\\n'));\n```\n\n---\n\n## Bech32 prefixes\n\nShort, readable Bech32 encodings are used with app prefix `hk` + tag:\n\n- `nsec1…` private key\n- `npub1…` public/verify key\n- `note1…` identity (`SHA256(publicKey)`)\n- `sig1…` signature\n- `nc1…` nonce\n- `ct1…` ciphertext\n- `npd1…` derived key material\n- `webauthn1…` WebAuthn credential ID (used as a login secret by helpers)\n- `share1…` Shamir share\n\n---\n\n## Session persistence\n\nWhen you authenticate, hashkeys will fetch the bech32 private key (`nsec…`) from the worker and store it in `sessionStorage` under `privateKey`. When you logout or the page is refreshed without recalling, it is cleared. Use `auth.recall()` at startup to restore the session if a key is present.\n\n- Uses `sessionStorage`, so the key persists for the lifetime of the browser tab/window only.\n- The stored value is the bech32-encoded master key, not raw bytes.\n- Calling `auth.logout()` clears the stored key.\n\n---\n\n## Examples\n\n### Password to identity\n\n```js\nimport { useAuth } from 'hashkeys'\nconst auth = useAuth('hk')\nawait auth.login('correct horse battery staple');\nconsole.log(auth.identity); // note1…\n```\n\n### End‑to‑end encrypt to a recipient\n\n```js\nconst { ciphertext, nonce, algorithm } = await auth.send('encrypt',{ \n  data: 'hi', \n  recipientPublicKey: 'hkek1…',\n  algorithm: 'xchacha20poly1305'\n});\n// send {ciphertext, nonce, algorithm} to recipient\n```\n\n### Decrypt from a sender\n\n```js\nconst { decrypted } = await auth.send('decrypt',{ \n  ciphertext: 'hkct1…', \n  nonce: 'hknc1…', \n  senderPublicKey: 'hkek1…', \n  algorithm: 'xchacha20poly1305-x25519' \n});\n```\n\n### Verify someone else’s signature (no login required)\n\n```js\nconst { valid } = await auth.send('verify',{ \n  message: 'msg', \n  signature: 'hksg1…', \n  publicKey: 'hkpk1…' \n});\n```\n\n### PassKeys (WebAuthn)\n\n```js\n// Create/register a new PassKey for a username and login\nawait auth.passKeyAuth('alice@example.com');\nconsole.log(auth.identity); // hkid…\n\n// Use an existing PassKey to login\nawait auth.passKeyLogin();\n```\n\n### Multiple instances (local peer / Alice)\n\n```js\nimport { useAuth } from 'hashkeys'\nconst me = useAuth('hk')\nconst alice = useAuth('hk')\n\nawait me.login('correct horse battery staple')\nawait alice.login('alice-secret')\n\n// You -> Alice\nconst env = await me.send('encrypt',{ \n  data: 'hi Alice', \n  recipientPublicKey: alice.encryptionKey \n})\nconst { decrypted } = await alice.send('decrypt',{ \n  ciphertext: env.ciphertext, \n  nonce: env.nonce, \n  senderPublicKey: me.encryptionKey, \n  algorithm: env.algorithm \n})\n```\n\n### Session persistence (auto-recall)\n\n```vue\n<script setup>\nimport { onMounted } from 'vue'\nimport { useAuth } from 'hashkeys'\n\nconst auth = useAuth('hk')\n\nonMounted(() => {\n  auth.recall()\n})\n</script>\n```\n\n---\n\n## Minimal HTML example\n\nThis mirrors `public/test.html` but targets consumers of the package. Uses Vue's `watch` to react to auth changes.\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <script type=\"importmap\">{ \"imports\": { \"vue\": \"https://esm.sh/vue\", \"hashkeys\": \"https://esm.sh/hashkeys\" } }</script>\n  </head>\n  <body>\n    <div id=\"app\">\n      <input id=\"input\" placeholder=\"passphrase\" />\n      <button id=\"login\" disabled>LOGIN</button>\n      <button id=\"get-key\" disabled>GET KEY</button>\n      <pre id=\"id\"></pre>\n      <pre id=\"master\"></pre>\n    </div>\n    <script type=\"module\">\n      import { watch } from 'vue';\n      import { useAuth } from 'hashkeys';\n\n      const auth = useAuth('ex');\n\n      document.getElementById('get-key').addEventListener('click', async () => {\n        document.getElementById('master').textContent = await auth.send('get-private-key');\n      });\n\n      document.getElementById('input').addEventListener('input', (e) => {\n        document.getElementById('login').disabled = !e.target.value;\n      });\n\n      document.getElementById('login').addEventListener('click', () => {\n        auth.login(document.getElementById('input').value);\n      });\n\n      watch(auth, ({ authenticated, identity }) => {\n        if (authenticated) {\n          document.getElementById('id').textContent = identity;\n          document.getElementById('get-key').disabled = false;\n        }\n      });\n    </script>\n  </body>\n</html>\n```\n\n---\n\n## Environment\n\n- Built and tested with Vite + Vue 3; the Worker is bundled for package consumers.\n- Works in modern browsers with Web Worker support.\n- Avoid persisting raw key bytes; if you must export, prefer the bech32 forms.\n\n---\n\n## License\n\nMIT (c) 2025 davay42\n","readmeFilename":"README.md"}