{"id":27436032,"url":"https://github.com/bitcoinjs/tiny-secp256k1","last_synced_at":"2025-05-15T09:06:15.479Z","repository":{"id":32107809,"uuid":"106483630","full_name":"bitcoinjs/tiny-secp256k1","owner":"bitcoinjs","description":"A tiny secp256k1 native/JS wrapper","archived":false,"fork":false,"pushed_at":"2024-10-20T14:12:29.000Z","size":14833,"stargazers_count":101,"open_issues_count":12,"forks_count":59,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-10T16:31:23.499Z","etag":null,"topics":["node","rust","rust-crate","secp256k1","wasm"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/bitcoinjs.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,"zenodo":null}},"created_at":"2017-10-10T23:51:47.000Z","updated_at":"2025-04-27T00:45:37.000Z","dependencies_parsed_at":"2024-06-18T12:37:41.690Z","dependency_job_id":"25df2a33-adfb-4377-9e7a-e44455ac12bc","html_url":"https://github.com/bitcoinjs/tiny-secp256k1","commit_stats":{"total_commits":258,"total_committers":16,"mean_commits":16.125,"dds":0.5658914728682171,"last_synced_commit":"e8966cd1d9c724c4999ae71c9511b14c6a37648e"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoinjs%2Ftiny-secp256k1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoinjs%2Ftiny-secp256k1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoinjs%2Ftiny-secp256k1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitcoinjs%2Ftiny-secp256k1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitcoinjs","download_url":"https://codeload.github.com/bitcoinjs/tiny-secp256k1/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254310515,"owners_count":22049469,"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":["node","rust","rust-crate","secp256k1","wasm"],"created_at":"2025-04-14T19:18:41.698Z","updated_at":"2025-05-15T09:06:15.458Z","avatar_url":"https://github.com/bitcoinjs.png","language":"JavaScript","funding_links":[],"categories":["🧰 Tech stack"],"sub_categories":["Security \u0026 experience"],"readme":"# tiny-secp256k1\n\n[![NPM](https://img.shields.io/npm/v/tiny-secp256k1.svg)](https://www.npmjs.org/package/tiny-secp256k1)\n\nThis library is under development, and, like the [secp256k1](https://github.com/bitcoin-core/secp256k1) C library (through [secp256k1-sys](https://github.com/rust-bitcoin/rust-secp256k1/) Rust crate) it depends on, this is a research effort to determine an optimal API for end-users of the bitcoinjs ecosystem.\n\n## Installation\n\n### npm\n\n```bash\nnpm install tiny-secp256k1\n```\n\n### yarn\n\n```bash\nyarn add tiny-secp256k1\n```\n\n## WebAssembly and Node.js version\n\nPrevious version of `tiny-secp256k1` implement [C++ addon](https://nodejs.org/api/addons.html) through [NAN (Native Abstractions for Node.js)](https://github.com/nodejs/nan) and [elliptic](https://github.com/indutny/elliptic) as fallback when addon can not be built or in browser-like environement.\n\nCurrent version use Rust crate (which use C library) compiled to [WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly). With Wasm same code executed in any environment. Wasm is faster than `elliptic` but slower than node bindings ([results in PR](https://github.com/bitcoinjs/tiny-secp256k1/pull/53#issuecomment-801844450) or you can run own benchmark in `benches` directory).\n\nTools like webpack, environments like React Native, and a large part of the JavaScript/TypeScript ecosystem has support for WASM based libraries. However, it usually involves special config settings which might be difficult to figure out. We have examples in the examples folder that uses webpack to create a demo website.\n\nHowever, there are also **alternative implementations** of the interface of this library.\n\n## Alternatives\n\n1. [`@bitcoinjs-lib/tiny-secp256k1-asmjs`](https://www.npmjs.com/package/@bitcoin-js/tiny-secp256k1-asmjs) - This library uses wasm2js to convert this library into pure JS. It is about 10x ~ 20x slower than WASM and 3x ~ 10x slower than our old v1 JS implementation.\n2. [`@bitcoinerlab/secp256k1`](https://www.npmjs.com/package/@bitcoinerlab/secp256k1) - This library uses noble/secp256k1, and therefore it uses JS native `BigInt`. If you can support `BigInt` it is much faster than ASM.JS, however, this is not maintained by this library's maintainers, so there's no guarantee that they will keep up with any interface changes in the future. Please check before using. It is about 1.5x ~ 5x slower than WASM.\n\n## Building\n\nFor building locally you need C/C++ toolchain, Rust version \u003e=1.50.0 and `wasm-opt` from [binaryen](https://github.com/WebAssembly/binaryen).\n\n[rustup](https://rustup.rs/) is a recommended way to install `Rust`. You also will need `wasm32-unknown-unknown` target.\n\n```\nrustup toolchain install stable --target wasm32-unknown-unknown --component clippy --component rustfmt\n```\n\nAfter installing development dependencies with `npm` you can build Wasm:\n\n```\nmake build-wasm\n```\n\nor run tests:\n\n```\nmake test\n```\n\nAlternative way is to use [Docker](https://www.docker.com/):\n\n```\n% docker build -t tiny-secp256k1 .\n% docker run -it --rm -v `pwd`:/tiny-secp256k1 -w /tiny-secp256k1 tiny-secp256k1\n# make build\n```\n\n## Examples\n\n`tiny-secp256k1` includes two examples. First is [simple script for Node.js](examples/random-in-node) which generate random data and print arguments and methods results. Second is [React app](examples/react-app).\n\nReact app is builded in GitHub Actions on each commit to master branch and uploaded to [gh-pages](https://github.com/bitcoinjs/tiny-secp256k1/tree/gh-pages) branch, which is always available online: https://bitcoinjs.github.io/tiny-secp256k1/\n\n## Documentation\n\n### isPoint (A)\n\n```haskell\nisPoint :: Buffer -\u003e Bool\n```\n\nReturns `false` if\n\n- `A` is not encoded with a sequence tag of `0x02`, `0x03` or `0x04`\n- `A.x` is not in `[1...p - 1]`\n- `A.y` is not in `[1...p - 1]`\n\n### isPointCompressed (A)\n\n```haskell\nisPointCompressed :: Buffer -\u003e Bool\n```\n\nReturns `false` if the pubkey is **not** compressed.\n\n### isXOnlyPoint (A)\n\n```haskell\nisXOnlyPoint :: Buffer -\u003e Bool\n```\n\nReturns `false` if the pubkey is **not** an xOnlyPubkey.\n\n### isPrivate (d)\n\n```haskell\nisPrivate :: Buffer -\u003e Bool\n```\n\nReturns `false` if\n\n- `d` is not 256-bit, or\n- `d` is not in `[1..order - 1]`\n\n### pointAdd (A, B[, compressed])\n\n```haskell\npointAdd :: Buffer -\u003e Buffer [-\u003e Bool] -\u003e Maybe Buffer\n```\n\nReturns `null` if result is at infinity.\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(A)`\n- `Expected Point` if `!isPoint(B)`\n\n### pointAddScalar (A, tweak[, compressed])\n\n```haskell\npointAddScalar :: Buffer -\u003e Buffer [-\u003e Bool] -\u003e Maybe Buffer\n```\n\nReturns `null` if result is at infinity.\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(A)`\n- `Expected Tweak` if `tweak` is not in `[0...order - 1]`\n\n### pointCompress (A, compressed)\n\n```haskell\npointCompress :: Buffer -\u003e Bool -\u003e Buffer\n```\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(A)`\n\n### pointFromScalar (d[, compressed])\n\n```haskell\npointFromScalar :: Buffer [-\u003e Bool] -\u003e Maybe Buffer\n```\n\nReturns `null` if result is at infinity.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n\n### xOnlyPointFromScalar (d)\n\n```haskell\nxOnlyPointFromScalar :: Buffer -\u003e Buffer\n```\n\nReturns the xOnlyPubkey for a given private key\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n\n### xOnlyPointFromPoint (p)\n\n```haskell\nxOnlyPointFromPoint :: Buffer -\u003e Buffer\n```\n\nReturns the xOnlyPubkey for a given DER public key\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(p)`\n\n### pointMultiply (A, tweak[, compressed])\n\n```haskell\npointMultiply :: Buffer -\u003e Buffer [-\u003e Bool] -\u003e Maybe Buffer\n```\n\nReturns `null` if result is at infinity.\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(A)`\n- `Expected Tweak` if `tweak` is not in `[0...order - 1]`\n\n### privateAdd (d, tweak)\n\n```haskell\nprivateAdd :: Buffer -\u003e Buffer -\u003e Maybe Buffer\n```\n\nReturns `null` if result is equal to `0`.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n- `Expected Tweak` if `tweak` is not in `[0...order - 1]`\n\n### privateSub (d, tweak)\n\n```haskell\nprivateSub :: Buffer -\u003e Buffer -\u003e Maybe Buffer\n```\n\nReturns `null` if result is equal to `0`.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n- `Expected Tweak` if `tweak` is not in `[0...order - 1]`\n\n### privateNegate (d)\n\n```haskell\nprivateNegate :: Buffer -\u003e Buffer\n```\n\nReturns the negation of d on the order n (`n - d`)\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n\n### xOnlyPointAddTweak (p, tweak)\n\n```haskell\nxOnlyPointAddTweak :: Buffer -\u003e Buffer -\u003e { parity: 1 | 0; xOnlyPubkey: Buffer; }\n```\n\nReturns the tweaked xOnlyPubkey along with the parity bit (number type of 1|0)\n\n##### Throws:\n\n- `Expected Point` if `!isXOnlyPoint(p)`\n- `Expected Tweak` if `!isXOnlyPoint(tweak)`\n\n### xOnlyPointAddTweakCheck (p1, p2, tweak[, tweakParity])\n\n```haskell\nxOnlyPointAddTweakCheck :: Buffer -\u003e Buffer -\u003e Buffer [-\u003e 1 | 0] -\u003e Bool\n```\n\nChecks the tweaked pubkey (p2) against the original pubkey (p1) and tweak.\nThis is slightly slower if you include tweakParity, tweakParity will make it\nfaster for aggregation later on.\n\n##### Throws:\n\n- `Expected Point` if `!isXOnlyPoint(p1)`\n- `Expected Point` if `!isXOnlyPoint(p2)`\n- `Expected Tweak` if `!isXOnlyPoint(tweak)`\n- `Expected Parity` if `tweakParity is not 1 or 0`\n\n### sign (h, d[, e])\n\n```haskell\nsign :: Buffer -\u003e Buffer [-\u003e Buffer] -\u003e Buffer\n```\n\nReturns normalized signatures, each of (r, s) values are guaranteed to less than `order / 2`.\nUses RFC6979.\nAdds `e` as Added Entropy to the deterministic k generation.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n- `Expected Scalar` if `h` is not 256-bit\n- `Expected Extra Data (32 bytes)` if `e` is not 256-bit\n\n### signRecoverable (h, d[, e])\n\n```haskell\nsignRecoverable :: Buffer -\u003e Buffer [-\u003e Buffer] -\u003e { recoveryId: 0 | 1 | 2 | 3; signature: Buffer; }\n```\n\nReturns normalized signatures and recovery Id, each of (r, s) values are guaranteed to less than `order / 2`.\nUses RFC6979.\nAdds `e` as Added Entropy to the deterministic k generation.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n- `Expected Scalar` if `h` is not 256-bit\n- `Expected Extra Data (32 bytes)` if `e` is not 256-bit\n\n### signSchnorr (h, d[, e])\n\n```haskell\nsignSchnorr :: Buffer -\u003e Buffer [-\u003e Buffer] -\u003e Buffer\n```\n\nReturns normalized schnorr signature.\nUses BIP340 nonce generation.\nAdds `e` as Added Entropy.\n\n##### Throws:\n\n- `Expected Private` if `!isPrivate(d)`\n- `Expected Scalar` if `h` is not 256-bit\n- `Expected Extra Data (32 bytes)` if `e` is not 256-bit\n\n### verify (h, Q, signature[, strict = false])\n\n```haskell\nverify :: Buffer -\u003e Buffer -\u003e Buffer [-\u003e Bool] -\u003e Bool\n```\n\nReturns `false` if any of (r, s) values are equal to `0`, or if the signature is rejected.\n\nIf `strict` is `true`, valid signatures with any of (r, s) values greater than `order / 2` are rejected.\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(Q)`\n- `Expected Signature` if `signature` has any (r, s) values not in range `[0...order - 1]`\n- `Expected Scalar` if `h` is not 256-bit\n\n### recover (h, signature, recoveryId[, compressed = false])\n\n```haskell\nverify :: Buffer -\u003e Buffer -\u003e Number [-\u003e Bool] -\u003e Maybe Buffer\n```\n\nReturns the ECDSA public key from a signature if it can be recovered, `null` otherwise.\n\n\n##### Throws:\n\n- `Expected Signature` if `signature` has any (r, s) values not in range `(0...order - 1]`\n- `Bad Recovery Id` if `recid \u0026 2 !== 0`  and `signature` has any r value not in range `(0...P - N - 1]`\n- `Expected Hash` if `h` is not 256-bit\n\n\n### verifySchnorr (h, Q, signature)\n\n```haskell\nverifySchnorr :: Buffer -\u003e Buffer -\u003e Buffer -\u003e Bool\n```\n\nReturns `false` if any of (r, s) values are equal to `0`, or if the signature is rejected.\n\n##### Throws:\n\n- `Expected Point` if `!isPoint(Q)`\n- `Expected Signature` if `signature` has any (r, s) values not in range `[0...order - 1]`\n- `Expected Scalar` if `h` is not 256-bit\n\n## Credit\n\nThis library uses the native library [secp256k1](https://github.com/bitcoin-core/secp256k1) by the bitcoin-core developers through Rust crate [secp256k1-sys](https://crates.io/crates/secp256k1-sys), including derivatives of its tests and test vectors.\n\n# LICENSE [MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitcoinjs%2Ftiny-secp256k1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitcoinjs%2Ftiny-secp256k1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitcoinjs%2Ftiny-secp256k1/lists"}