{"_id":"micro-rsa-dsa-dh","_rev":"7-23ba46d1ff52d41004cfffe50bd60662","name":"micro-rsa-dsa-dh","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"micro-rsa-dsa-dh","version":"0.1.0","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.1.0","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"d34db158a792ab4ba9ff94750168a20181cd5d23","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.1.0.tgz","fileCount":68,"integrity":"sha512-SDv/FM9kt/ep1HyzZSCZ1lza7wWFu2dkvijtVSGQBhErUGAp7Pf3zXwIjordB+qKBfnMA76sIAtNPg9137kGlQ==","signatures":[{"sig":"MEUCIQDzsVj7BwsOY9fmzA5U5fBmoUC/98anZy0I3Cq2LtKXngIgYtvWnR5k5k7190FFyPLSYptnCPFc6egZbMasIfC39kE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":388306},"main":"./index.js","types":"./index.d.ts","module":"./esm/index.js","exports":{".":{"import":"./esm/index.js","require":"./index.js"},"./dh.js":{"import":"./esm/dh.js","require":"./dh.js"},"./dsa.js":{"import":"./esm/dsa.js","require":"./dsa.js"},"./rsa.js":{"import":"./esm/rsa.js","require":"./rsa.js"},"./utils.js":{"import":"./esm/utils.js","require":"./utils.js"},"./elgamal.js":{"import":"./esm/elgamal.js","require":"./elgamal.js"},"./primality.js":{"import":"./esm/primality.js","require":"./primality.js"}},"funding":"https://paulmillr.com/funding/","gitHead":"7f0a856e4020a350eaf724ae56bf52bad135375f","scripts":{"lint":"prettier --check src","test":"node test/index.test.mjs","build":"tsc && tsc -p tsconfig.esm.json","format":"prettier --write src"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"10.7.0","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH","directories":{},"_nodeVersion":"22.1.0","dependencies":{"@noble/hashes":"1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.1.1","typescript":"5.5.2","micro-should":"0.4.0","@paulmillr/jsbt":"0.2.1"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.1.0_1720098973414_0.11396104711451427","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"micro-rsa-dsa-dh","version":"0.2.0","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.2.0","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"f076a99c0014a89f795627cb498b228b8114238e","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.2.0.tgz","fileCount":38,"integrity":"sha512-8qC05KUzUB83MUvhFYfiBCt0eAHtaJBWsHMBTk3cFGqGIf16/YLzkKL9xASUbBPgkL0OrH3k2bWbGaDrnNgabg==","signatures":[{"sig":"MEUCIFVVbNnnsoGcoxro09lghIzotWfXOH8X3X3rTIvHFHskAiEAzudlMYyz98nVIrwqNfMYXX7vyr5z1/3pmfbTU48CrrU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228652},"main":"index.js","type":"module","types":"index.d.ts","module":"index.js","gitHead":"943be46d001638bede49fe9529f30dcaf10df3e0","scripts":{"test":"node test/index.ts","build":"tsc","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'","test:bun":"bun test/index.ts","test:deno":"deno --allow-env --allow-read test/index.ts","test:node20":"cd test; npx tsc; node compiled/test/index.js","build:release":"npx --no @paulmillr/jsbt esbuild test/build"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"11.5.1","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"sideEffects":false,"_nodeVersion":"24.6.0","dependencies":{"@noble/hashes":"^2.0.0-beta.5"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","typescript":"5.9.2","@paulmillr/jsbt":"0.4.3"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.2.0_1755711027545_0.42518926391712775","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"micro-rsa-dsa-dh","version":"0.2.1","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.2.1","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"6919a2f42b2868d336411d82840227176b08dadf","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.2.1.tgz","fileCount":38,"integrity":"sha512-bzeli7cWJ13gOK1SmD/zfiPJW9yaE9sFVUhO/LgYmxyDtsE7RYdWVP02SbKhEbYksa0BR13ED+k8WCr9E20KVg==","signatures":[{"sig":"MEUCIQDe+GksQyPR122xZHFaVD2W1wdl41EIQEPWL1qva2smUwIgK3FOt34Nd9HIGvTZxQ7sWE3SEzKt4SCuGXhxXwyhJiU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228652},"main":"index.js","type":"module","types":"index.d.ts","module":"index.js","gitHead":"27fc10394790ca81f6ab506fa882848ed994bb6b","scripts":{"test":"node test/index.ts","build":"tsc","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'","test:bun":"bun test/index.ts","test:deno":"deno --allow-env --allow-read test/index.ts","test:node20":"cd test; npx tsc; node compiled/test/index.js","build:release":"npx --no @paulmillr/jsbt esbuild test/build"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"11.5.1","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"sideEffects":false,"_nodeVersion":"24.6.0","dependencies":{"@noble/hashes":"^2.0.0-beta.5"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","typescript":"5.9.2","@paulmillr/jsbt":"0.4.3"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.2.1_1755711217061_0.7016246813719051","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"micro-rsa-dsa-dh","version":"0.2.2","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.2.2","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"a0315fc7317e65b1a6af1b3c356b1ac669e4a976","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.2.2.tgz","fileCount":38,"integrity":"sha512-SmohiH4quvLZzv2ABhFkWmbvLbcD8+DW3Z1MHK2ZBqipxMhaWZ9cXUxUZ687rzcdgMk7hKQlP/AFJp/MR/zUwA==","signatures":[{"sig":"MEUCIQDc8E2zVJTTdGZqiE1N5JcrIuf3fbf3wKZSVF/wlhD3sQIgS8tVyhhsofSGV7JkLShzEF6HCL3t4onOk+8yUFfJpBU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228645},"main":"index.js","type":"module","types":"index.d.ts","module":"index.js","gitHead":"5aee4f3b20f6e44c8b5f8f308804b106a6fe6027","scripts":{"test":"node test/index.ts","build":"tsc","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'","test:bun":"bun test/index.ts","test:deno":"deno --allow-env --allow-read test/index.ts","test:node20":"cd test; npx tsc; node compiled/test/index.js","build:release":"npx --no @paulmillr/jsbt esbuild test/build"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"11.5.1","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"sideEffects":false,"_nodeVersion":"24.6.0","dependencies":{"@noble/hashes":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","typescript":"5.9.2","@paulmillr/jsbt":"0.4.4"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.2.2_1756140624069_0.4645054883161499","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"micro-rsa-dsa-dh","version":"0.2.3","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.2.3","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"b0704b49c7823af8399b2a543ef1bcc57dfc9644","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.2.3.tgz","fileCount":38,"integrity":"sha512-Mf1lBm4Ho2F3lthxltQQC9ZowpRsU1FSnSLWJC6WbPKZNKw3d7x3FKyxHK9jDaIJCoLL/z9US7m/OPLZM6DBCg==","signatures":[{"sig":"MEQCIADy9c+JP4laz9MUxUFVQzs0LKpqNU8ZWdZVD4KBq9dvAiAj0FALvqyLHI0NJ6XT8RzF7lX01fiYlmsOvqKH58h6gA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":228877},"main":"index.js","type":"module","types":"index.d.ts","module":"index.js","exports":{".":"./index.js","./dh.js":"./dh.js","./dsa.js":"./dsa.js","./rsa.js":"./rsa.js","./utils.js":"./utils.js","./elgamal.js":"./elgamal.js","./primality.js":"./primality.js"},"gitHead":"285084a977d80b4eaaa5c2cb42d6a85161d44a3f","scripts":{"test":"node test/index.ts","build":"tsc","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'","test:bun":"bun test/index.ts","test:deno":"deno --allow-env --allow-read test/index.ts","test:node20":"cd test; npx tsc; node compiled/test/index.js","build:release":"npx --no @paulmillr/jsbt esbuild test/build"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"11.5.1","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"sideEffects":false,"_nodeVersion":"24.6.0","dependencies":{"@noble/hashes":"^2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","typescript":"5.9.2","@paulmillr/jsbt":"0.4.4"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.2.3_1758187916105_0.5762920285002477","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"micro-rsa-dsa-dh","version":"0.3.0","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"micro-rsa-dsa-dh@0.3.0","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"e5654be2113b211289b11b2eb7845fbd865d46c0","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.3.0.tgz","fileCount":38,"integrity":"sha512-s2i37WORwgolfeddVk8U1GUUBx0GLR/J9Vakc1njBL4HPJVMXHfnf51BmnxzUqh+nwnxzYn8n5WCXrMbPD6zWQ==","signatures":[{"sig":"MEUCIQCeHQz2GioRC4UCQxgWOIH/dFusJrs+9shu766WjuK4bAIgeEDp5RerB6dWH43MKMYNn6Lr2nMmBOkBCvOYgljf+rk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":341318},"main":"index.js","type":"module","types":"index.d.ts","module":"index.js","exports":{".":"./index.js","./dh.js":"./dh.js","./dsa.js":"./dsa.js","./rsa.js":"./rsa.js","./utils.js":"./utils.js","./elgamal.js":"./elgamal.js","./primality.js":"./primality.js"},"gitHead":"ccb349b3338334c13804224642b9d0901fb55c63","scripts":{"test":"node test/index.ts","build":"tsc","check":"npx --no @paulmillr/jsbt check package.json","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'","test:bun":"bun test/index.ts","test:deno":"deno --allow-env --allow-read test/index.ts","check:jsdoc":"npx --no @paulmillr/jsbt tsdoc package.json","test:node20":"cd test; npx tsc; node compiled/test/index.js","check:readme":"npx --no @paulmillr/jsbt readme package.json","build:release":"npx --no @paulmillr/jsbt esbuild test/build","check:treeshake":"npx --no @paulmillr/jsbt treeshake package.json test/build/out-treeshake"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:047a8730-ffe8-472a-8260-86108ec551e2"}},"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"11.6.1","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","dependencies":{"@noble/hashes":"^2.2.0"},"_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","typescript":"6.0.2","@paulmillr/jsbt":"0.5.0"},"_npmOperationalInternal":{"tmp":"tmp/micro-rsa-dsa-dh_0.3.0_1777372854782_0.652650451003616","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"_id":"micro-rsa-dsa-dh@0.4.0","bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"dist":{"shasum":"161951e606dcaf853c8eef70bdbb385b59f676fe","tarball":"https://registry.npmjs.org/micro-rsa-dsa-dh/-/micro-rsa-dsa-dh-0.4.0.tgz","integrity":"sha512-zh9zNiN0StmCiUHz7Tp2Cb+7zQP45rvkvdlXknYQd648J9DEiTKO+UphzlECZKXHHt+s1EXaR5urncl7gpu5zw==","fileCount":24,"unpackedSize":323299,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/micro-rsa-dsa-dh@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD5bTL7YRxFWbXdj0HhIgN0l6inrslOkhTMP5PihDfZdQIhANntME9UJ1TE1Qxv83SistvDAWPpNcu7xRaVQ8CZi4hY"}]},"main":"index.js","name":"micro-rsa-dsa-dh","type":"module","types":"index.d.ts","author":{"url":"https://paulmillr.com","name":"Paul Miller"},"module":"index.js","exports":{".":"./index.js","./dh.js":"./dh.js","./dsa.js":"./dsa.js","./rsa.js":"./rsa.js","./utils.js":"./utils.js","./elgamal.js":"./elgamal.js","./primality.js":"./primality.js"},"gitHead":"f17957d30210a9ddd4f32c6dd29fe8b92e1b22bb","license":"MIT","scripts":{"test":"node test/index.ts","build":"tsc","check":"jsbt-check","format":"prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'"},"version":"0.4.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:42cd2eab-3c7b-43af-9363-7141bdfded67"},"approver":{"name":"paulmillr","email":"paul@paulmillr.com"}},"homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"_npmVersion":"12.0.2","description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","directories":{},"maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"sideEffects":false,"_nodeVersion":"24.19.0","dependencies":{"@noble/hashes":"2.4.0","@noble/ciphers":"2.4.0"},"devDependencies":{"bismar":"0.1.8","prettier":"3.9.6","typescript":"6.0.3","@paulmillr/jsbt":"0.7.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/micro-rsa-dsa-dh_0.4.0_1788016968471_0.3255812287386539"},"_hasShrinkwrap":false}},"time":{"created":"2024-07-04T13:16:13.414Z","modified":"2026-08-29T15:22:48.905Z","0.1.0":"2024-07-04T13:16:13.603Z","0.2.0":"2025-08-20T17:30:27.748Z","0.2.1":"2025-08-20T17:33:37.242Z","0.2.2":"2025-08-25T16:50:24.247Z","0.2.3":"2025-09-18T09:31:56.317Z","0.3.0":"2026-04-28T10:40:54.928Z","0.4.0":"2026-08-29T15:22:48.563Z"},"bugs":{"url":"https://github.com/paulmillr/micro-rsa-dsa-dh/issues"},"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","homepage":"https://github.com/paulmillr/micro-rsa-dsa-dh#readme","keywords":["rsa","dsa","dh","elgamal","diffie-hellman","prime","cryptography","noble"],"repository":{"url":"git+https://github.com/paulmillr/micro-rsa-dsa-dh.git","type":"git"},"description":"Minimal implementation of older cryptography algorithms: RSA, DSA, DH, ElGamal","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"readme":"# micro-rsa-dsa-dh\n\nMinimal implementation of older cryptography algorithms: RSA, DSA, DH.\n\n- 🔻 Tree-shakeable: unused code is excluded from your builds\n- 🔑 RSA (Rivest-Shamir-Adleman) public-key cryptosystem, with OAEP, PSS, PKCS1\n- ✍️ DSA (Digital Signature Algorithm) signatures\n- 🤝 DH (Diffie-Hellman) key exchange\n- 📦 ElGamal encryption\n- 5️⃣ Primality tests\n- 🪶 16KB (gzipped)\n\n> [!WARNING]\n> Like in all JS implementations, keep in mind [timing leaks](#security)\n\n## Usage\n\n> `npm install micro-rsa-dsa-dh`\n\n> `deno add jsr:@paulmillr/micro-rsa-dsa-dh`\n\nWe support all major platforms and runtimes.\n\nA standalone file [micro-rsa-dsa-dh.js](https://github.com/paulmillr/micro-rsa-dsa-dh/releases) is also available.\n\n- [All imports](#all-imports)\n- [RSA](#rsa)\n  - [OAEP](#oaep)\n  - [PSS](#pss)\n  - [PKCS1](#pkcs1)\n- [DSA](#dsa)\n- [DH](#dh)\n- [ElGamal](#elgamal)\n- [Primality tests](#primality-tests)\n- [Security](#security)\n\n## All imports\n\n```js\nimport { DH, DHGroups, LegacyDHGroups } from 'micro-rsa-dsa-dh/dh.js';\nimport { DSA } from 'micro-rsa-dsa-dh/dsa.js';\nimport { ElGamal, genElGamalParams } from 'micro-rsa-dsa-dh/elgamal.js';\nimport {\n  millerRabin,\n  jacobi,\n  lucas,\n  bailliePSW,\n  isProbablePrime,\n  isProbablePrimeRSA,\n  isProbablySafePrime,\n} from 'micro-rsa-dsa-dh/primality.js';\nimport {\n  IFCPrimes,\n  keygen,\n  mgf1,\n  OAEP,\n  PSS,\n  PKCS1_KEM,\n  PKCS1_SHA1,\n  PKCS1_SHA224,\n  PKCS1_SHA256,\n  PKCS1_SHA384,\n  PKCS1_SHA512,\n  PKCS1_SHA512_224,\n  PKCS1_SHA512_256,\n  PKCS1_SHA3_224,\n  PKCS1_SHA3_256,\n  PKCS1_SHA3_384,\n  PKCS1_SHA3_512,\n} from 'micro-rsa-dsa-dh/rsa.js';\n```\n\n## RSA\n\nRSA is most common example of integer factorization cryptography (IFC).\n\nKEM version of RSA (encrypt/decrypt) is slow and usually used to exchange AES/ChaCha keys.\n\n> [!WARNING]\n> `keygen()` requires a modulus of at least 2048 bits, but imported `PublicKey` and `PrivateKey`\n> values have no minimum-size check for compatibility. Consequently, encryption, decryption,\n> signing, and verification will accept weak sub-2048-bit imported keys. Applications must require\n> `key.n.toString(2).length >= 2048` before active RSA operations. If old signatures require a weak\n> key, isolate that key to legacy verification and never use it for new signatures or ciphertexts.\n> See [FIPS 186-5](https://csrc.nist.gov/pubs/fips/186-5/final) and\n> [NIST's RSA modulus guidance](https://csrc.nist.gov/projects/cryptographic-module-validation-program/notices).\n\n### OAEP\n\nOAEP is Optimal Asymmetric Encryption Padding.\n\nUse if you need KEM (encrypt/decrypt).\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as rsa from 'micro-rsa-dsa-dh/rsa.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nconst alice = rsa.keygen(2048);\nconst oaep = rsa.OAEP(sha256, rsa.mgf1(sha256));\nconst msg = new Uint8Array([1, 2, 3]);\nconst encrypted = oaep.encrypt(alice.publicKey, msg);\ndeepStrictEqual(oaep.decrypt(alice.privateKey, encrypted), msg);\n```\n\n### PSS\n\nUse if you need signatures (sign/verify).\n\n> [!WARNING]\n> `PSS()` accepts caller-selected hashes and does not reject SHA-1. SHA-1 collision resistance is\n> broken, so do not use it to create signatures; use SHA-256 or stronger. SHA-1 should be retained\n> only where old signatures must be verified. `PKCS1_SHA1` likewise still exposes both `sign()` and\n> `verify()` for compatibility: do not call its `sign()` method. Prefer RSA-PSS with SHA-256 or\n> stronger for new signatures. See [NIST's SHA-1 policy](https://csrc.nist.gov/projects/hash-functions/nist-policy-on-hash-functions).\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as rsa from 'micro-rsa-dsa-dh/rsa.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\nconst alice = rsa.keygen(2048);\nconst pss = rsa.PSS(sha256, rsa.mgf1(sha256));\nconst msg = new Uint8Array([1, 2, 3]);\nconst sig = pss.sign(alice.privateKey, msg);\ndeepStrictEqual(pss.verify(alice.publicKey, msg, sig), true);\n```\n\n### PKCS1\n\nThis is old standard, OAEP/PSS is better.\n\nSignatures:\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as rsa from 'micro-rsa-dsa-dh/rsa.js';\nconst alice = rsa.keygen(2048);\nconst pkcs = rsa.PKCS1_SHA256;\nconst msg = new Uint8Array([1, 2, 3]);\nconst sig = pkcs.sign(alice.privateKey, msg);\ndeepStrictEqual(pkcs.verify(alice.publicKey, msg, sig), true);\n```\n\nKEM (vulnerable [[1]](https://crypto.stackexchange.com/questions/12688/can-you-explain-bleichenbachers-cca-attack-on-pkcs1-v1-5),\n[[2]](https://security.stackexchange.com/questions/183179/what-is-rsa-oaep-rsa-pss-in-simple-terms)\n):\n\n> [!WARNING]\n> `PKCS1_KEM.decrypt()` returns plaintext for valid padding and throws for invalid padding. A service\n> that exposes this distinction is a Bleichenbacher oracle and can allow adaptive plaintext recovery.\n> Use OAEP for new protocols. Legacy online protocols need fixed-length implicit rejection rather\n> than this generic variable-length decryption API.\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as rsa from 'micro-rsa-dsa-dh/rsa.js';\nconst alice = rsa.keygen(2048);\nconst pkcs = rsa.PKCS1_KEM;\nconst msg = new Uint8Array([1, 2, 3]);\nconst encrypted = pkcs.encrypt(alice.publicKey, msg);\ndeepStrictEqual(pkcs.decrypt(alice.privateKey, encrypted), msg);\n```\n\n## DH\n\nSame as ECDH. Use the predefined groups in `DHGroups`, which are all at least 2048 bits. Cons:\n\n- Long keys\n- Harder to protect from timing attacks\n- Using custom non-standard groups can make algorithm weak\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { DH, DHGroups } from 'micro-rsa-dsa-dh/dh.js';\nconst dh = DH('modp18');\nconst alicePriv = dh.randomPrivateKey();\nconst alicePub = dh.getPublicKey(alicePriv);\n\nconst bobPriv = dh.randomPrivateKey();\nconst bobPub = dh.getPublicKey(bobPriv);\n\ndeepStrictEqual(dh.getSharedSecret(alicePriv, bobPub), dh.getSharedSecret(bobPriv, alicePub));\n```\n\nThe obsolete 768-, 1024-, and 1536-bit groups are separated into `LegacyDHGroups`. They are unsafe\nfor new protocols and require an explicit opt-in:\n\n```ts\nimport { DH, LegacyDHGroups } from 'micro-rsa-dsa-dh/dh.js';\n\nconst legacyParams = LegacyDHGroups.modp5;\nconst legacyDH = DH(legacyParams, { allowUnsafeLegacy: true });\n```\n\nSafe custom groups must provide `{ p, q, g }`. Construction validates size bounds, primality,\n`q | p - 1`, and generator order; peer public keys are checked for subgroup membership before\nsecret exponentiation. Private exponents use `[2, q - 2]`. Existing unvalidated `{ p, g }` groups\ncan be opened only for migration with `{ unsafeAllowUnvalidatedGroup: true }`, which restores the\nold `[2, p - 2]` and range-only behavior.\n\n## DSA\n\n> [!NOTE]\n> DSA was deprecated in FIPS186-5. Imported domains are validated for supported sizes, primality,\n> the `q | p - 1` relation, and generator order. The supported 1024/160 pair is retained only for\n> legacy compatibility and provides roughly 80-bit classical security; prefer 2048/224, 2048/256,\n> or 3072/256 when existing DSA interoperability is unavoidable. DSA also accepts caller-selected\n> hashes, including SHA-1, for compatibility. SHA-1 collision resistance is broken: do not use it\n> to generate parameters or new signatures, and retain it only to verify old signatures. Use an\n> approved SHA-2/SHA-3 hash when existing DSA interoperability is unavoidable. See\n> [NIST's SHA-1 policy](https://csrc.nist.gov/projects/hash-functions/nist-policy-on-hash-functions).\n\nSame as ECDSA, but with big numbers. Cons:\n\n- Deprecated\n- No pre-defined groups: need to generate and send params\n- Long keys\n- Harder to protect from timing attacks\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as dsa from 'micro-rsa-dsa-dh/dsa.js';\nimport { sha256 } from '@noble/hashes/sha2.js';\n// 1. Params\n// Carol generates random params\nconst carolParams = dsa.genDSAParams(2048, 256, sha256, 1);\n// Instead of sending primes to Alice and Bob (which can be insecure), she sends seed\n// This ensures that params are not constructed primes, but generated randomly:\n// Alice and Bob can use these params without trusting Carol.\nconst seed = carolParams.domainParameterSeed;\n\nconst aliceParams = dsa.genDSAParams(2048, 256, sha256, 1, seed);\ndeepStrictEqual(aliceParams, carolParams); // Same params as Carol!\n\nconst bobParams = dsa.genDSAParams(2048, 256, sha256, 1, seed);\ndeepStrictEqual(aliceParams, bobParams); // Now Bob has same params too!\n\n// 2. Keys\nconst aliceDSA = dsa.DSA(aliceParams);\nconst alicePrivKey = aliceDSA.randomPrivateKey();\nconst alicePubKey = aliceDSA.getPublicKey(alicePrivKey); // Alice generates public key and sends to Bob\nconst msg = new Uint8Array([1, 2, 3, 4, 5]);\nconst sig = aliceDSA.sign(alicePrivKey, msg); // Alice signs message\n\nconst bobDSA = dsa.DSA(bobParams);\n// Now Bob can verify that message was sent by Alice (and not Carol for example).\ndeepStrictEqual(bobDSA.verify(alicePubKey, msg, sig), true);\n```\n\n## ElGamal\n\nMostly for educational purpose: almost nobody uses it.\n\n> [!WARNING]\n> `genElGamalParams()` is a legacy educational helper, not a safe production key generator. It\n> continues to accept breakable sizes for compatibility and does not force the candidate's high\n> bit, so `bits` is only the random candidate-input width—not a guaranteed modulus size. The small\n> values below are intentionally fast, breakable examples. Generator search is bounded for each\n> candidate safe prime and restarts parameter sampling if none is acceptable. [RFC 9580 §§12.6 and\n> 12.8](https://www.rfc-editor.org/rfc/rfc9580.html#section-12.6) prohibits generating or using\n> ElGamal keys, encryption, and signatures in modern OpenPGP; do not use this API for new protocols.\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { ElGamal, genElGamalParams } from 'micro-rsa-dsa-dh/elgamal.js';\n// NOTE: this is super slow! 512: 1s, 1024: 20s, 2048: 1046s\nconst params = genElGamalParams(512);\nconst elgamal = ElGamal(params, { prehash: sha256 }); // SHA-256 is also the default\n\nconst alicePriv = elgamal.randomPrivateKey();\nconst alicePub = elgamal.getPublicKey(alicePriv);\n// Encryption\nconst msg = new TextEncoder().encode('secret message');\nconst cipherText = elgamal.encrypt(alicePub, msg); // Somebody encrypts message using Alice public key\ndeepStrictEqual(elgamal.decrypt(alicePriv, cipherText), msg); // Alice can decrypt message using private key\n// Sign\nconst signedMsg = new TextEncoder().encode('message');\nconst sig = elgamal.sign(alicePriv, signedMsg); // The helper prehashes this byte message\ndeepStrictEqual(elgamal.verify(alicePub, signedMsg, sig), true); // Other parties can verify it\n```\n\nEncryption uses an order-`q` subgroup KEM, HKDF-SHA-256, and XChaCha20-Poly1305. Its versioned\nciphertext authenticates arbitrary byte messages and does not expose the plaintext's Legendre\nsymbol. Decryption never auto-detects legacy ciphertexts.\n\nDefault construction validates a safe-prime group, a full-order signing generator, imported\nprivate keys in `[2, q)`, public-key ranges, and encryption subgroup elements. It deliberately does\nnot impose a 2048-bit minimum because legacy and educational groups remain supported; size policy\nis the caller's responsibility. The unsafe raw-encryption option also restores permissive legacy\nparameter and key handling.\n\nTextbook ElGamal's raw bigint ciphertext leaks a plaintext predicate and is malleable. The exact\nlegacy API and `{ ct1, ct2 }` format remain available only through\n`ElGamal(params, { unsafeAllowRawEncryption: true })`; use a separately constructed instance to\ndecrypt old data during migration. The raw-bigint signature behavior is forgeable and separately\nrequires `{ unsafeDisablePrehash: true }`. Set both flags only to recreate the complete legacy API.\n\n## Primality tests\n\nA bunch of primality tests.\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport * as primality from 'micro-rsa-dsa-dh/primality.js';\ndeepStrictEqual(primality.millerRabin(7n, 10), true);\ndeepStrictEqual(primality.lucas(7n), true);\ndeepStrictEqual(primality.bailliePSW(7n), true);\ndeepStrictEqual(primality.isProbablePrime(7n, 30), true); // Tests 30 random bases\ndeepStrictEqual(primality.isProbablySafePrime(7n, 10), true);\n```\n\n|                     | Reliable | Deterministic | Approx. 2048-bit prime | Performance and use                                                                                                                                                |\n| ------------------- | -------- | ------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| millerRabin         | No       | No            | 68 ms (10 rounds)      | Cost scales approximately linearly with the requested iteration count. Random bases may expose pseudoprimes; increasing the count reduces that probability.        |\n| lucas               | No       | Yes           | 20 ms                  | One deterministic Lucas pass. Faster here than 10 Miller–Rabin rounds, but known Lucas pseudoprimes exist.                                                         |\n| bailliePSW          | Yes      | Yes           | 27 ms                  | One fixed-base Miller–Rabin pass plus Lucas. No false positives are known.                                                                                          |\n| isProbablePrime     | Yes      | No            | 88 ms (10 rounds)      | Runs the requested random Miller–Rabin rounds followed by Lucas, so its cost is approximately the sum of those tests.                                               |\n| isProbablySafePrime | Yes      | No            | 176 ms (10 rounds)     | Runs `isProbablePrime` for both `p` and `(p - 1) / 2`; a safe-prime candidate therefore costs roughly twice a probable-prime test.                                   |\n\nPerformance values are median wall times from seven warmed runs on Node.js 26.6.0, using the\n2048-bit RFC 3526 MODP group 14 safe prime. They are comparative rather than portable: hardware and\nruntime versions matter, larger inputs become substantially slower, and composite or small values\noften return much earlier through trial division or the first failed round.\n\n- _Reliable:_ no false positives are known\n- _Deterministic:_ it does not rely on randomness\n\n## Security\n\nAll algorithms use JS bigints, which are not constant-time. When timing attacks could be mounted, they will reveal sensitive information.\n\nGenerated RSA private keys include the public exponent `e`, and RSA private operations use it for\nmultiplicative blinding and result verification. Legacy `{ n, d }` private keys remain accepted for\ncompatibility but use the previous unblinded path; imported keys should include their matching `e`.\nBlinding reduces RSA's input-dependent timing exposure, but it does not make JavaScript bigint\narithmetic constant-time. DSA, DH, ElGamal, and legacy RSA private operations retain the timing risk.\n\nThat generally means:\n\n- Document, mail, messaging encryption, like PGP, is probably OK. It's hard for an attacker to measure timings: they don't know how long it took to create a msg\n- Public APIs are NOT safe. Consider something like \"send us document and we will auto-sign it\". These cases can leak private keys\n\nFor comparison, bigint-based elliptic curve implementations will leak much less info. That's because they operate over much smaller numbers: think 2^256, instead of 2^2048.\n\nRSA operations reject moduli wider than 16384 bits and public exponents at or above 2^256 to bound the cost of attacker-controlled bigint arithmetic. This happens after callers construct the bigint values; applications that parse untrusted serialized keys must also limit input and integer lengths before decoding them. See [badrsa](https://github.com/jedisct1/badrsa) for examples of why parsing, key validation, and operation-cost policy are separate checks.\n\n## Links\n\n- [RFC 3447](https://datatracker.ietf.org/doc/html/rfc3447) - old RSA\n- [RFC 8017](https://datatracker.ietf.org/doc/html/rfc8017) - OAEP/PSS/PKCS1\n- [RFC 8702](https://datatracker.ietf.org/doc/html/rfc8702) - RSA-PSS + Shake\n- [FIPS 186-5](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf) - Prime generation\n- [FIPS 186-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf) - DSA\n- [RFC 2631](https://datatracker.ietf.org/doc/html/rfc2631) - DH\n- [RFC 3526](https://datatracker.ietf.org/doc/html/rfc3526) - DH groups\n- [RFC 6979](https://datatracker.ietf.org/doc/html/rfc6979) - DSA\n\n## License\n\nMIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.\n","readmeFilename":"README.md"}