{"_id":"@aguycalled/bls12-381","_rev":"2-5a8359b2adaf12934b70a4c30c6ce070","name":"@aguycalled/bls12-381","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@aguycalled/bls12-381","version":"1.0.0","description":"Fastest JS implementation of BLS12-381. Auditable, secure, 0-dependency aggregated signatures & pairings","main":"index.js","scripts":{"test":"jest test/*.test.ts","build":"tsc -d","build-release":"rollup -c rollup.config.js","bench":"node test/benchmark.js","lint":"prettier --print-width 100 --single-quote --check index.ts"},"author":{"name":"Paul Miller","url":"https://paulmillr.com"},"homepage":"https://github.com/paulmillr/noble-bls12-381","repository":{"type":"git","url":"git+https://github.com/paulmillr/noble-bls12-381.git"},"license":"MIT","browser":{"crypto":false},"devDependencies":{"@rollup/plugin-commonjs":"^19","@rollup/plugin-node-resolve":"^13","@types/jest":"^27","@types/node":"^16.9.2","fast-check":"^2.17","jest":"^27.0.5","micro-bmark":"^0.1.3","prettier":"^2.3.2","rollup":"^2.52.2","ts-jest":"^27","typescript":"^4.4"},"keywords":["bls12-381","bls12","bls","bls signature","threshold signatures","aggregate","aggregated","zk-snark","barreto-lynn-scott","barreto-naehrig","snark","pairing","cryptography","security"],"gitHead":"cc3f1836ee49b68168d657235d67ad5bb819832e","bugs":{"url":"https://github.com/paulmillr/noble-bls12-381/issues"},"_id":"@aguycalled/bls12-381@1.0.0","_nodeVersion":"14.15.5","_npmVersion":"6.14.11","dist":{"integrity":"sha512-u8tN0uRbt0V5nWVcDlgsjiTchEz7AaUjgcShxt9VfdW4NH6RvA/I4awYVMDQpy+X7u3CNINBtipF52CSTc2PzA==","shasum":"fefc7b623ff337fd8acd55f325be4f456d4d7d5f","tarball":"https://registry.npmjs.org/@aguycalled/bls12-381/-/bls12-381-1.0.0.tgz","fileCount":7,"unpackedSize":87240,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwvU+CRA9TVsSAnZWagAASgwP/jcuuY0cdYetBa79S3G7\n30a2ZqB74Hl3RML4H6utMYn9wX6QW2Mp7ryqGAQI51nhjecqyvac4ioc68/0\nNZpaoYBz9z1ie6LFWTMjYkuzgv67vtn1aZkXtohBN0fST3ys/NdouOzsdBqe\nH/w4IyzNwvqjD4wFImYDxI9fJVp/H+NJP0aoc0IArvQumIOrk61H+u0oCew1\ndv/P9bPEpzydSLduyn8Y1po1yjvGnmXTXCfe+HUJ1X2ZSxkPyGlPB49rFj57\nARAcU+8EHGckRKBjFy5dean/S7yqovRkTlX9YPftYQLXw9yJyeArQCvKDK/Q\nMA2I2Qigf/XKcrUeyegdqzrlhp+lJ2Ku6NvL2xtcxgHTZf3VRIUrWXuOUmZY\nq1JVf8x8l5xQW8CFIpNg9VFw27GyzZ+zKgAi7xdkQWvF29z3i2qXHGEcSUov\nSBgqKNjv7kh7p0sstRwRlp+ni5tkUisCriSTk/CkZIHZLl12O3fxed7zmhDJ\n7kk7tTV6p8gOgsopgkcmlTmVH5l0NW73itpDWnhg05ziOdjFi19kv3vYdHdc\nBeX7PVaiOhUwkDWzz0QNDAvQO4D6hy4vdu1usQ8qE9zNjx/7snJzhjQqBUdi\nVUDhWlkgDvVrIpCMK/bUo5v2uOiwm4CewWJDRg+tVgbxgCUJyzMxcwawrdXG\n4CJD\r\n=9IsO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHN0FiMvD1bglWuBiE6UUylCzTPYoVzh/jwWVo8bTIitAiEAgSxM4qpGw1c3D1yfOXECAwMb2/QrMVoBIS98+1oyOnE="}]},"_npmUser":{"name":"aguycalled","email":"alex@nav.community"},"directories":{},"maintainers":[{"name":"aguycalled","email":"alex@nav.community"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/bls12-381_1.0.0_1636648633276_0.5704896584715562"},"_hasShrinkwrap":false}},"time":{"created":"2021-11-11T16:37:13.221Z","1.0.0":"2021-11-11T16:37:13.438Z","modified":"2022-04-04T12:08:57.161Z"},"maintainers":[{"name":"aguycalled","email":"alex@nav.community"}],"description":"Fastest JS implementation of BLS12-381. Auditable, secure, 0-dependency aggregated signatures & pairings","homepage":"https://github.com/paulmillr/noble-bls12-381","keywords":["bls12-381","bls12","bls","bls signature","threshold signatures","aggregate","aggregated","zk-snark","barreto-lynn-scott","barreto-naehrig","snark","pairing","cryptography","security"],"repository":{"type":"git","url":"git+https://github.com/paulmillr/noble-bls12-381.git"},"author":{"name":"Paul Miller","url":"https://paulmillr.com"},"bugs":{"url":"https://github.com/paulmillr/noble-bls12-381/issues"},"license":"MIT","readme":"# noble-bls12-381 ![Node CI](https://github.com/paulmillr/noble-secp256k1/workflows/Node%20CI/badge.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\n**[Fastest](#speed)** implementation of BLS12-381 in a scripting language. The pairing-friendly Barreto-Lynn-Scott elliptic curve construction allows to:\n\n- Construct [zk-SNARKs](https://z.cash/technology/zksnarks/) at the 128-bit security\n- Use [threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716),\n  which allows a user to sign lots of messages with one signature and verify them swiftly in a batch,\n  using Boneh-Lynn-Shacham signature scheme.\n\nCompatible with Algorand, Chia, Dfinity, Ethereum, FIL, Zcash. Matches specs [pairing-curves-10](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-10), [bls-sigs-04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04), [hash-to-curve-12](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12).\n\nTo learn more about internals, check out [BLS12-381 for the rest of us](https://hackmd.io/@benjaminion/bls12-381) & [key concepts of pairings](https://medium.com/@alonmuroch_65570/bls-signatures-part-2-key-concepts-of-pairings-27a8a9533d0c). To try it live, see [the online demo](https://paulmillr.com/ecc) & [threshold sigs demo](https://genthresh.com).\n\n### This library belongs to *noble* crypto\n\n> **noble-crypto** — high-security, easily auditable set of contained cryptographic libraries and tools.\n\n- Just two files\n- No dependencies\n- Easily auditable TypeScript/JS code\n- Supported in all major browsers and stable node.js versions\n- All releases are signed with PGP keys\n- Check out all libraries:\n  [secp256k1](https://github.com/paulmillr/noble-secp256k1),\n  [ed25519](https://github.com/paulmillr/noble-ed25519),\n  [bls12-381](https://github.com/paulmillr/noble-bls12-381),\n  [hashes](https://github.com/paulmillr/noble-hashes)\n\n## Usage\n\nUse NPM in node.js / browser, or include single file from\n[GitHub's releases page](https://github.com/paulmillr/noble-bls12-381/releases):\n\n> npm install @noble/bls12-381\n\n```js\nconst bls = require('@noble/bls12-381');\n// if you're using single file, use global variable nobleBls12381\n\n// You can use Uint8Array, or hex string for readability\nconst privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c';\nconst privateKeys = [\n  '18f020b98eb798752a50ed0563b079c125b0db5dd0b1060d1c1b47d4a193e1e4',\n  'ed69a8c50cf8c9836be3b67c7eeff416612d45ba39a5c099d48fa668bf558c9c',\n  '16ae669f3be7a2121e17d0c68c05a8f3d6bef21ec0f2315f1d7aec12484e4cf5'\n];\nconst message = '64726e3da8';\nconst messages = ['d2', '0d98', '05caf3'];\n\n(async () => {\n  const publicKey = bls.getPublicKey(privateKey);\n  const publicKeys = privateKeys.map(bls.getPublicKey);\n\n  const signature = await bls.sign(message, privateKey);\n  const isCorrect = await bls.verify(signature, message, publicKey);\n  console.log('key', publicKey);\n  console.log('signature', signature);\n  console.log('is correct:', isCorrect);\n\n  // Sign 1 msg with 3 keys\n  const signatures2 = await Promise.all(privateKeys.map(p => bls.sign(message, p)));\n  const aggPubKey2 = bls.aggregatePublicKeys(publicKeys);\n  const aggSignature2 = bls.aggregateSignatures(signatures2);\n  const isCorrect2 = await bls.verify(aggSignature2, message, aggPubKey2);\n  console.log();\n  console.log('signatures are', signatures2);\n  console.log('merged to one signature', aggSignature2);\n  console.log('is correct:', isCorrect2);\n\n  // Sign 3 msgs with 3 keys\n  const signatures3 = await Promise.all(privateKeys.map((p, i) => bls.sign(messages[i], p)));\n  const aggSignature3 = bls.aggregateSignatures(signatures3);\n  const isCorrect3 = await bls.verifyBatch(aggSignature3, messages, publicKeys);\n  console.log();\n  console.log('keys', publicKeys);\n  console.log('signatures', signatures3);\n  console.log('merged to one signature', aggSignature3);\n  console.log('is correct:', isCorrect3);\n})();\n```\n\n## API\n\n- [`getPublicKey(privateKey)`](#getpublickeyprivatekey)\n- [`sign(message, privateKey)`](#signmessage-privatekey)\n- [`verify(signature, message, publicKey)`](#verifysignature-message-publickey)\n- [`aggregatePublicKeys(publicKeys)`](#aggregatepublickeyspublickeys)\n- [`aggregateSignatures(signatures)`](#aggregatesignaturessignatures)\n- [`verifyBatch(signature, messages, publicKeys)`](#verifybatchsignature-messages-publickeys)\n- [`pairing(G1Point, G2Point)`](#pairingg1point-g2point)\n\n##### `getPublicKey(privateKey)`\n```typescript\nfunction getPublicKey(privateKey: Uint8Array | bigint): Uint8Array;\nfunction getPublicKey(privateKey: string): string;\n```\n- `privateKey: Uint8Array | string | bigint` will be used to generate public key.\n  Public key is generated by executing scalar multiplication of a base Point(x, y) by a fixed\n  integer. The result is another `Point(x, y)` which we will by default encode to hex Uint8Array.\n- Returns `Uint8Array`: encoded publicKey for signature verification\n\n**Note:** if you need spec-based `KeyGen`, use [paulmillr/bls12-381-keygen](https://github.com/paulmillr/bls12-381-keygen). It should work properly with ETH2 and FIL keys.\n\n##### `sign(message, privateKey)`\n```typescript\nfunction sign(message: Uint8Array, privateKey: Uint8Array): Promise<Uint8Array>;\nfunction sign(message: string, privateKey: string): Promise<Uint8Array>;\nfunction sign(message: PointG2, privateKey: Uint8Array | string | bigint): Promise<PointG2>;\n```\n- `message: Uint8Array | string` - message which would be hashed & signed\n- `privateKey: Uint8Array | string | bigint` - private key which will sign the hash\n- Returns `Uint8Array | string | PointG2`: encoded signature\n\nCheck out **Internals** section on instructions about domain separation tag (DST).\n\n##### `verify(signature, message, publicKey)`\n```typescript\nfunction verify(\n  signature: Uint8Array | string | PointG2,\n  message: Uint8Array | string | PointG2,\n  publicKey: Uint8Array | string | PointG1\n): Promise<boolean>\n```\n- `signature: Uint8Array | string` - object returned by the `sign` or `aggregateSignatures` function\n- `message: Uint8Array | string` - message hash that needs to be verified\n- `publicKey: Uint8Array | string` - e.g. that was generated from `privateKey` by `getPublicKey`\n- Returns `Promise<boolean>`: `true` / `false` whether the signature matches hash\n\n##### `aggregatePublicKeys(publicKeys)`\n```typescript\nfunction aggregatePublicKeys(publicKeys: Uint8Array[]): Uint8Array;\nfunction aggregatePublicKeys(publicKeys: string[]): string;\nfunction aggregatePublicKeys(publicKeys: PointG1[]): PointG1;\n```\n- `publicKeys: (Uint8Array | string | PointG1)[]` - e.g. that have been generated from `privateKey` by `getPublicKey`\n- Returns `Uint8Array | PointG1`: one aggregated public key which calculated from public keys\n\n##### `aggregateSignatures(signatures)`\n```typescript\nfunction aggregateSignatures(signatures: Uint8Array[]): Uint8Array;\nfunction aggregateSignatures(signatures: string[]): string;\nfunction aggregateSignatures(signatures: PointG2[]): PointG2;\n```\n- `signatures: (Uint8Array | string | PointG2)[]` - e.g. that have been generated by `sign`\n- Returns `Uint8Array | PointG2`: one aggregated signature which calculated from signatures\n\n##### `verifyBatch(signature, messages, publicKeys)`\n```typescript\nfunction verifyBatch(\n  signature: Uint8Array | string | PointG2,\n  messages: (Uint8Array | string | PointG2)[],\n  publicKeys: (Uint8Array | string | PointG1)[]\n): Promise<boolean>\n```\n- `signature: Uint8Array | string | PointG2` - object returned by the `aggregateSignatures` function\n- `messages: (Uint8Array | string | PointG2)[]` - messages hashes that needs to be verified\n- `publicKeys: (Uint8Array | string | PointG1)[]` - e.g. that were generated from `privateKeys` by `getPublicKey`\n- Returns `Promise<boolean>`: `true` / `false` whether the signature matches hashes\n\n##### `pairing(pointG1, pointG2)`\n```typescript\nfunction pairing(\n  pointG1: PointG1,\n  pointG2: PointG2,\n  withFinalExponent: boolean = true\n): Fp12\n```\n- `pointG1: PointG1` - simple point, `x, y` are bigints\n- `pointG2: PointG2` - point over curve with complex numbers (`(x₁, x₂+i), (y₁, y₂+i)`) - pairs of bigints\n- `withFinalExponent: boolean` - should the result be powered by curve order; very slow\n- Returns `Fp12`: paired point over 12-degree extension field.\n\n##### Helpers\n\n```typescript\n// characteristic; z + (z⁴ - z² + 1)(z - 1)²/3\nbls.CURVE.P // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab\n\n// curve order; z⁴ − z² + 1\nbls.CURVE.r // 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001\n\n// cofactor; (z - 1)²/3\nbls.curve.h // 0x396c8c005555e1568c00aaab0000aaab\n\n\n// G1 base point coordinates (x, y)\nbls.CURVE.Gx\n// x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507\nbls.CURVE.Gy\n// y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569\n\n// G2 base point coordinates (x₁, x₂+i), (y₁, y₂+i)\nbls.CURVE.G2x\n// x =\n// 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758,\n// 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160\nbls.CURVE.G2y\n// y =\n// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,\n// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905\n\n// Classes\nbls.Fp      // field over Fp\nbls.Fp2     // field over Fp₂\nbls.Fp12    // finite extension field over irreducible polynominal\nbls.PointG1 // projective point (xyz) at G1\nbls.PointG2 // projective point (xyz) at G2\n```\n\n## Internals\n\nThe library uses G1 for public keys and G2 for signatures. Adding support for G1 signatures is planned.\n\n- BLS Relies on Bilinear Pairing (expensive)\n- Private Keys: 32 bytes\n- Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes.\n- Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays.\n    - The signature is a point on the G2 subgroup, which is defined over a finite field\n    with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the complex numbers).\n- The 12 stands for the Embedding degree.\n\nFormulas:\n\n- `P = pk x G` - public keys\n- `S = pk x H(m)` - signing\n- `e(P, H(m)) == e(G, S)` - verification using pairings\n- `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation\n\nThe BLS parameters for the library are:\n\n- `PK_IN` `G1`\n- `HASH_OR_ENCODE` `true`\n- `DST` `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_` - use `bls.utils.getDSTLabel()` & `bls.utils.setDSTLabel(\"...\")` to read/change the Domain Separation Tag label\n- `RAND_BITS` `64`\n\nFilecoin uses little endian byte arrays for private keys - so ensure to reverse byte order if you'll use it with FIL.\n\n## Speed\n\nTo achieve the best speed out of all JS / Python implementations, the library employs different optimizations:\n\n- cyclotomic exponentation\n- endomorphism for clearing cofactor\n- pairing precomputation\n\nBenchmarks measured with Apple M1:\n\n```\ngetPublicKey x 598 ops/sec @ 1ms/op\nsign x 36 ops/sec @ 27ms/op\nverify x 28 ops/sec @ 35ms/op\npairing x 69 ops/sec @ 14ms/op\naggregatePublicKeys/8 x 84 ops/sec @ 11ms/op\naggregateSignatures/8 x 40 ops/sec @ 24ms/op\n\nwith compression / decompression disabled:\nsign/nc x 54 ops/sec @ 18ms/op\nverify/nc x 47 ops/sec @ 21ms/op\naggregatePublicKeys/32 x 787 ops/sec @ 1ms/op\naggregatePublicKeys/128 x 558 ops/sec @ 1ms/op\naggregatePublicKeys/512 x 256 ops/sec @ 3ms/op\naggregatePublicKeys/2048 x 81 ops/sec @ 12ms/op\naggregateSignatures/32 x 452 ops/sec @ 2ms/op\naggregateSignatures/128 x 240 ops/sec @ 4ms/op\naggregateSignatures/512 x 81 ops/sec @ 12ms/op\naggregateSignatures/2048 x 22 ops/sec @ 43ms/op\n```\n\n## Security\n\nNoble is production-ready.\n\n1. No public audits have been done yet. Our goal is to crowdfund the audit.\n2. It was developed in a similar fashion to\n[noble-secp256k1](https://github.com/paulmillr/noble-secp256k1), which **was** audited by a third-party firm.\n3. It was fuzzed by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz),\nno serious issues have been found. You can run the fuzzer by yourself to check it.\n\nWe're using built-in JS `BigInt`, which is \"unsuitable for use in cryptography\" as [per official spec](https://github.com/tc39/proposal-bigint#cryptography). This means that the lib is potentially vulnerable to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack). But, *JIT-compiler* and *Garbage Collector* make \"constant time\" extremely hard to achieve in a scripting language. Which means *any other JS library doesn't use constant-time bigints*. Including bn.js or anything else. Even statically typed Rust, a language without GC, [makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. Use low-level libraries & languages.\n\nWe however consider infrastructure attacks like rogue NPM modules very important; that's why it's crucial to minimize the amount of 3rd-party dependencies & native bindings. If your app uses 500 dependencies, any dep could get hacked and you'll be downloading rootkits with every `npm install`. Our goal is to minimize this attack vector.\n\n## Contributing\n\n1. Clone the repository.\n2. `npm install` to install build dependencies like TypeScript\n3. `npm run build` to compile TypeScript code\n4. `npm run test` to run jest on `test/index.ts`\n\nSpecial thanks to [Roman Koblov](https://github.com/romankoblov), who have helped to improve pairing speed.\n\n## License\n\nMIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.\n","readmeFilename":"README.md"}