{"id":17000159,"url":"https://github.com/mitschabaude/watsign","last_synced_at":"2025-04-16T02:44:31.284Z","repository":{"id":43106696,"uuid":"404641209","full_name":"mitschabaude/watsign","owner":"mitschabaude","description":"Tweetnacl's ed25519 signatures, ported to WebAssembly","archived":false,"fork":false,"pushed_at":"2022-01-04T10:07:52.000Z","size":573,"stargazers_count":13,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-04-06T13:21:28.823Z","etag":null,"topics":["cryptography","ed25519","nacl","signatures","webassembly"],"latest_commit_sha":null,"homepage":"","language":"WebAssembly","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/mitschabaude.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-09T08:17:32.000Z","updated_at":"2023-03-04T20:35:50.000Z","dependencies_parsed_at":"2022-07-09T02:30:32.807Z","dependency_job_id":null,"html_url":"https://github.com/mitschabaude/watsign","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitschabaude%2Fwatsign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitschabaude%2Fwatsign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitschabaude%2Fwatsign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitschabaude%2Fwatsign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mitschabaude","download_url":"https://codeload.github.com/mitschabaude/watsign/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249185929,"owners_count":21226639,"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":["cryptography","ed25519","nacl","signatures","webassembly"],"created_at":"2024-10-14T04:11:14.244Z","updated_at":"2025-04-16T02:44:31.251Z","avatar_url":"https://github.com/mitschabaude.png","language":"WebAssembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"# watsign\n\nThis library is a port of the signing part of [tweetnacl](http://tweetnacl.cr.yp.to/) to WebAssembly + JavaScript. It implements the [ed25519 signature scheme](https://en.wikipedia.org/wiki/EdDSA#Ed25519).\nwatsign works in **all modern browsers** as well as **node** and **deno**!\n\nThe code is based on and tested against [tweetnacl-js](https://github.com/dchest/tweetnacl-js). If you only need signing, we offer the following advantages:\n\n- About 5x faster than tweetnacl-js, see [comparison below](#performance)\n- Size impact is about 70% of tweetnacl-js: 7.4kB vs 10.6kB, minified + gzipped. (But tweetnacl-js contains much more than signing!)\n\nwatsign is even a bit faster than [noble-ed25519](https://github.com/paulmillr/noble-ed25519), which uses built-in JS `BigInt` for field arithmetic. As opposed to `BigInt`, the algorithms here (from tweetnacl) are carefully designed to resist timing attacks and prevent memory access patterns depending on secret data.\n\nThe code is almost entirely written in raw WAT (Webassembly text format) and bundled to JS-friendly Wasm with [watever](https://github.com/mitschabaude/watever), the WAT bundler written also by me. Fun fact: even the entry point of this lib is autogenerated from a WAT file ([./src/sign.wat](https://github.com/mitschabaude/watsign/blob/main/src/sign.wat)). There is no custom JS glue code.\n\n```sh\nnpm i watsign\n```\n\n## Usage\n\n```js\nimport {newKeyPair, sign, verify} from 'watsign';\n\nlet {publicKey, secretKey} = await newKeyPair();\n\nlet message = new TextEncoder().encode('Something I want to sign');\nlet signature = await sign(message, secretKey);\n\nlet ok = await verify(message, signature, publicKey);\nconsole.log('everything ok?', ok);\n```\n\nIn **deno**, you can import from github:\n\n\u003c!-- prettier-ignore --\u003e\n```js\nimport {newKeyPair, sign, verify} from 'https://raw.githubusercontent.com/mitschabaude/watsign/main/mod.js';\n```\n\n## API\n\nThe API is a streamlined version of [nacl.sign from tweetnacl-js](https://github.com/dchest/tweetnacl-js#signatures). The only differences are:\n\n- All exported functions are **async** (this is dictated by WebAssembly, and also enables us to use native browser crypto for SHA-512)\n- We only support detached signatures, so our `sign` is `nacl.sign.detached`\n- There is just a normal named export for each function, no `nacl` object with nested sub-objects\n- There is only the \"high-level\" API, not the redundant \"low-level\" API (`crypto_sign` etc.) and no constants (`nacl.sign.signatureLength` etc.)\n\nLike in tweetnacl-js, all functions operate on `Uint8Array`s.\n\nThe following is the full list of exported functions and their tweetnacl-js equivalents:\n\n- **`sign(message: Uint8Array, secretKey: Uint8Array): Promise\u003cUint8Array\u003e`**  \n  Sign a message with your secret key. Returns a 64 byte signature. Async version of `nacl.sign.detached`.\n\n- **`verify(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): Promise\u003cboolean\u003e`**  \n  Verifies the signature, returns true if and only if it is valid. Async version of `nacl.sign.detached.verify`.\n\n- **`newKeyPair(): Promise\u003c{secretKey: Uint8Array, publicKey: Uint8Array}\u003e`**  \n  Creates a new, random key pair. Async version of `nacl.sign.keyPair`.\n\n- **`keyPairFromSeed(seed: Uint8Array): Promise\u003c{secretKey: Uint8Array, publicKey: Uint8Array}\u003e`**  \n  Deterministically creates a key pair from a 32-byte seed. Async version of `nacl.sign.keyPair.fromSeed`.\n\n- **`keyPairFromSecretKey(secretKey: Uint8Array): Promise\u003c{secretKey: Uint8Array, publicKey: Uint8Array}\u003e`**  \n  Re-creates the full key pair from the 64-byte secret key (which, in fact, has the public key stored in its last 32 bytes). Async version of `nacl.sign.keyPair.fromSecretKey`.\n\n## Performance\n\nPerformance compared to tweetnacl-js and noble-ed25519 on my computer (Intel i7-10700) in Chromium 93 (via puppeteer).\n\nWe are 4-6x faster than tweetnacl-js in the warmed-up regime and up to 33x faster on cold start after page load. Compared to noble-ed25519, we are 1.2-3x faster (warmed up) and up to 17x on cold start.\n\n- **watsign**\n\n```sh\nFirst run after startup (varies between runs!):\nsign (short msg):    2.99 ms\nverify (short msg):  1.81 ms\nsign (long msg):     1.32 ms\nverify (long msg):   1.61 ms\n\nAverage of 50x after warm-up of 50x:\nsign (short msg):    0.67 ± 0.06 ms\nverify (short msg):  1.11 ± 0.03 ms\nsign (long msg):     0.96 ± 0.06 ms\nverify (long msg):   1.28 ± 0.02 ms\n```\n\n- **tweetnacl-js**\n\n```sh\nFirst run after startup (varies between runs!):\nsign (short msg):    15.85 ms\nverify (short msg):  8.45 ms\nsign (long msg):     43.88 ms\nverify (long msg):   12.18 ms\n\nAverage of 50x after warm-up of 50x:\nsign (short msg):    2.86 ± 0.19 ms\nverify (short msg):  5.65 ± 0.22 ms\nsign (long msg):     5.70 ± 0.22 ms\nverify (long msg):   7.21 ± 0.23 ms\n```\n\n- **noble-ed25519**\n\n```sh\nFirst run after startup (varies between runs!):\nsign (short msg):    53.17 ms\nverify (short msg):  3.72 ms\nsign (long msg):     2.11 ms\nverify (long msg):   3.97 ms\n\nAverage of 50x after warm-up of 50x:\nsign (short msg):    1.00 ± 0.06 ms\nverify (short msg):  3.09 ± 0.09 ms\nsign (long msg):     1.27 ± 0.09 ms\nverify (long msg):   3.24 ± 0.09 ms\n```\n\n## Testing\n\n```sh\n# before you do anything else\nnpm install\n\n# build wasm and separate entry-points for node / deno / browser\nnpm run build\n\n# run performance comparison above\nnode test/performance.js\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitschabaude%2Fwatsign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmitschabaude%2Fwatsign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitschabaude%2Fwatsign/lists"}