From d588a5b7497fddfd4fcb79bb21d006a4219343ed Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 7 Sep 2022 12:38:14 -0700 Subject: [PATCH 1/5] initial commit --- package-lock.json | 35 +++++ package.json | 1 + packages/bls-verify/.eslintignore | 1 + packages/bls-verify/.gitignore | 17 +++ packages/bls-verify/.npmignore | 11 ++ packages/bls-verify/LICENSE | 201 ++++++++++++++++++++++++++ packages/bls-verify/README.md | 30 ++++ packages/bls-verify/jest.config.ts | 17 +++ packages/bls-verify/package.json | 49 +++++++ packages/bls-verify/src/index.ts | 22 +++ packages/bls-verify/src/utils.ts | 57 ++++++++ packages/bls-verify/test-setup.ts | 11 ++ packages/bls-verify/tsconfig-cjs.json | 7 + packages/bls-verify/tsconfig.json | 23 +++ 14 files changed, 482 insertions(+) create mode 100644 packages/bls-verify/.eslintignore create mode 100644 packages/bls-verify/.gitignore create mode 100644 packages/bls-verify/.npmignore create mode 100644 packages/bls-verify/LICENSE create mode 100644 packages/bls-verify/README.md create mode 100644 packages/bls-verify/jest.config.ts create mode 100644 packages/bls-verify/package.json create mode 100644 packages/bls-verify/src/index.ts create mode 100644 packages/bls-verify/src/utils.ts create mode 100644 packages/bls-verify/test-setup.ts create mode 100644 packages/bls-verify/tsconfig-cjs.json create mode 100644 packages/bls-verify/tsconfig.json diff --git a/package-lock.json b/package-lock.json index acc2e2aa2..9d2f1ff6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "packages/principal", "packages/candid", "packages/agent", + "packages/bls-verify", "packages/identity", "packages/identity-ledgerhq", "packages/authentication", @@ -1905,6 +1906,10 @@ "resolved": "packages/authentication", "link": true }, + "node_modules/@dfinity/bls-verify": { + "resolved": "packages/bls-verify", + "link": true + }, "node_modules/@dfinity/candid": { "resolved": "packages/candid", "link": true @@ -3045,6 +3050,17 @@ "win32" ] }, + "node_modules/@noble/bls12-381": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/bls12-381/-/bls12-381-1.3.0.tgz", + "integrity": "sha512-rYQXhQ+Q6fDYLSO/ZUY9RsDE0Adi2Iua9xXxNxLmO8jXiBZGVxecWQsC1116aRlv3XGLvoZTGqyy5vAcBu368g==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -19605,6 +19621,14 @@ "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", "dev": true }, + "packages/bls-verify": { + "name": "@dfinity/bls-verify", + "version": "1.0.0-beta.0", + "license": "Apache-2.0", + "dependencies": { + "@noble/bls12-381": "^1.3.0" + } + }, "packages/candid": { "name": "@dfinity/candid", "version": "1.0.0-beta.0", @@ -21514,6 +21538,12 @@ } } }, + "@dfinity/bls-verify": { + "version": "file:packages/bls-verify", + "requires": { + "@noble/bls12-381": "*" + } + }, "@dfinity/candid": { "version": "file:packages/candid", "requires": { @@ -22710,6 +22740,11 @@ "dev": true, "optional": true }, + "@noble/bls12-381": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/bls12-381/-/bls12-381-1.3.0.tgz", + "integrity": "sha512-rYQXhQ+Q6fDYLSO/ZUY9RsDE0Adi2Iua9xXxNxLmO8jXiBZGVxecWQsC1116aRlv3XGLvoZTGqyy5vAcBu368g==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index d7b3de032..07e14d919 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "packages/principal", "packages/candid", "packages/agent", + "packages/bls-verify", "packages/identity", "packages/identity-ledgerhq", "packages/authentication", diff --git a/packages/bls-verify/.eslintignore b/packages/bls-verify/.eslintignore new file mode 100644 index 000000000..2cb7d2a2e --- /dev/null +++ b/packages/bls-verify/.eslintignore @@ -0,0 +1 @@ +**/*.js diff --git a/packages/bls-verify/.gitignore b/packages/bls-verify/.gitignore new file mode 100644 index 000000000..40ba0014d --- /dev/null +++ b/packages/bls-verify/.gitignore @@ -0,0 +1,17 @@ +build_info.json +node_modules/ +dist/ +**/*.js +**/*.js.map +**/*.d.ts + +# generated docs +/docs/reference + +# Cannot ignore .d.ts files in types/ +!types/**/*.d.ts + +# Cannot ignore setup files for webpack and jest, which are still JavaScript. +!webpack.config.js +!jest.config.js +!test-setup.js diff --git a/packages/bls-verify/.npmignore b/packages/bls-verify/.npmignore new file mode 100644 index 000000000..eb725972f --- /dev/null +++ b/packages/bls-verify/.npmignore @@ -0,0 +1,11 @@ +# We work with a safelist here, so block everything that's not permitted, and add packages +# that are. +** + +!lib/** +!types/**/*.d.ts +!package.json +!README.md + +# The following line further removes all test files (which matches .js and .d.ts). +lib/**/*.test.* diff --git a/packages/bls-verify/LICENSE b/packages/bls-verify/LICENSE new file mode 100644 index 000000000..b27ba1fe8 --- /dev/null +++ b/packages/bls-verify/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 DFINITY LLC. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/bls-verify/README.md b/packages/bls-verify/README.md new file mode 100644 index 000000000..9d601693f --- /dev/null +++ b/packages/bls-verify/README.md @@ -0,0 +1,30 @@ +# @dfinity/bls-verify + +Package wrapping the @noble/bls-12-381 pure JS BLS verification implementation for use in `agent-js`. This is useful in contexts like React Native, where wasm implementations of BLS verification are not supported. + +Visit the [Dfinity Forum](https://forum.dfinity.org/) and [SDK Documentation](https://sdk.dfinity.org/docs/index.html) for more information and support building on the Internet Computer. + +Additional API Documentation can be found [here](https://agent-js.icp.xyz/candid/index.html). + +--- + +## Installation + +Using Principal: + +``` +npm i --save @dfinity/bls-verify +``` + +## To use in your application + +```ts +import { blsVerify } from '@dfinity/bls-verify'; +import { createActor, canisterId } from '../declarations/example'; + +const exampleActor = createActor(canisterId, { + actorOptions: { + blsVerify, + }, +}); +``` diff --git a/packages/bls-verify/jest.config.ts b/packages/bls-verify/jest.config.ts new file mode 100644 index 000000000..128d66015 --- /dev/null +++ b/packages/bls-verify/jest.config.ts @@ -0,0 +1,17 @@ +import baseConfig from '../../jest.config.base'; +const packageName = 'bls-verify'; + +module.exports = { + ...baseConfig, + roots: [`/packages/${packageName}`], + bail: false, + moduleDirectories: ['node_modules'], + modulePaths: [`/packages/${packageName}/src/`], + setupFiles: [`/packages/${packageName}/test-setup.ts`], + transform: { + '^.+\\.ts$': 'ts-jest', + }, + collectCoverageFrom: ['src/**/*.{ts,tsx}'], + displayName: packageName, + rootDir: '../..', +}; diff --git a/packages/bls-verify/package.json b/packages/bls-verify/package.json new file mode 100644 index 000000000..565981a35 --- /dev/null +++ b/packages/bls-verify/package.json @@ -0,0 +1,49 @@ +{ + "name": "@dfinity/bls-verify", + "version": "1.0.0-beta.0", + "author": "DFINITY Stiftung ", + "license": "Apache-2.0", + "description": "bls verification strategy in JavaScript", + "homepage": "https://internetcomputer.org", + "repository": { + "type": "git", + "url": "https://github.com/dfinity/agent-js.git", + "directory": "packages/bls-verify" + }, + "bugs": { + "url": "https://github.com/dfinity/agent-js/issues" + }, + "keywords": [ + "internet computer", + "ic", + "dfinity", + "canister", + "webauthn", + "identity", + "principal", + "dfx", + "candid", + "motoko", + "javascript", + "typescript", + "blockchain", + "crypto", + "distributed", + "api" + ], + "main": "./lib/cjs/index.js", + "module": "./lib/esm/index.js", + "scripts": { + "build": "tsc -b && tsc -p tsconfig-cjs.json", + "bundle": "npm run build", + "ci": "npm run prettier && npm run lint && npm run test", + "lint": "eslint 'src' --ext '.js,.jsx,.ts,.tsx'", + "lint:fix": "npm run lint -- --fix", + "make:docs/reference": "typedoc src/index.ts --out ../../docs/generated/candid --excludeInternal", + "prettier": "prettier --check \"src/**/*.ts\"", + "prettier:write": "npm run prettier -- --write" + }, + "dependencies": { + "@noble/bls12-381": "^1.3.0" + } +} diff --git a/packages/bls-verify/src/index.ts b/packages/bls-verify/src/index.ts new file mode 100644 index 000000000..d3018e0f9 --- /dev/null +++ b/packages/bls-verify/src/index.ts @@ -0,0 +1,22 @@ +import { verify } from '@noble/bls12-381'; +import { toHex } from './utils'; + +type VerifyFunc = (pk: Uint8Array, sig: Uint8Array, msg: Uint8Array) => Promise; + +/** + * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation + * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature + * @param {Uint8Array | string} signature - digital signature + * @param {Uint8Array | string} message - message to verify + * @returns boolean + */ +export const blsVerify: VerifyFunc = async ( + publicKey: Uint8Array | string, + signature: Uint8Array | string, + message: Uint8Array | string, +): Promise => { + const pk = typeof publicKey === 'string' ? publicKey : toHex(publicKey); + const sig = typeof signature === 'string' ? signature : toHex(signature); + const msg = typeof message === 'string' ? message : toHex(message); + return await verify(sig, msg, pk); +}; diff --git a/packages/bls-verify/src/utils.ts b/packages/bls-verify/src/utils.ts new file mode 100644 index 000000000..4db40bdd7 --- /dev/null +++ b/packages/bls-verify/src/utils.ts @@ -0,0 +1,57 @@ +/** + * Concatenate multiple array buffers. + * @param buffers The buffers to concatenate. + */ +export function concat(...buffers: ArrayBuffer[]): ArrayBuffer { + const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); + let index = 0; + for (const b of buffers) { + result.set(new Uint8Array(b), index); + index += b.byteLength; + } + return result.buffer; +} + +/** + * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. + * @param buffer The buffer to return the hexadecimal string of. + */ +export function toHex(buffer: ArrayBuffer): string { + return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); +} + +const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); + +/** + * Transforms a hexadecimal string into an array buffer. + * @param hex The hexadecimal string to use. + */ +export function fromHex(hex: string): ArrayBuffer { + if (!hexRe.test(hex)) { + throw new Error('Invalid hexadecimal string.'); + } + const buffer = [...hex] + .reduce((acc, curr, i) => { + // tslint:disable-next-line:no-bitwise + acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; + return acc; + }, [] as string[]) + .map(x => Number.parseInt(x, 16)); + + return new Uint8Array(buffer).buffer; +} + +export function compare(b1: ArrayBuffer, b2: ArrayBuffer): number { + if (b1.byteLength !== b2.byteLength) { + return b1.byteLength - b2.byteLength; + } + + const u1 = new Uint8Array(b1); + const u2 = new Uint8Array(b2); + for (let i = 0; i < u1.length; i++) { + if (u1[i] !== u2[i]) { + return u1[i] - u2[i]; + } + } + return 0; +} diff --git a/packages/bls-verify/test-setup.ts b/packages/bls-verify/test-setup.ts new file mode 100644 index 000000000..468bc9d51 --- /dev/null +++ b/packages/bls-verify/test-setup.ts @@ -0,0 +1,11 @@ +// This file may be used to polyfill features that aren't available in the test +// environment, i.e. JSDom. +// +// We sometimes need to do this because our target browsers are expected to have +// a feature that JSDom doesn't. +// +// Note that we can use webpack configuration to make some features available to +// Node.js in a similar way. + +global.crypto = require('@trust/webcrypto'); +require('whatwg-fetch'); diff --git a/packages/bls-verify/tsconfig-cjs.json b/packages/bls-verify/tsconfig-cjs.json new file mode 100644 index 000000000..945c51f27 --- /dev/null +++ b/packages/bls-verify/tsconfig-cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS", + "outDir": "./lib/cjs" + } +} diff --git a/packages/bls-verify/tsconfig.json b/packages/bls-verify/tsconfig.json new file mode 100644 index 000000000..f62927784 --- /dev/null +++ b/packages/bls-verify/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "allowJs": true, + "baseUrl": "./", + "composite": true, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "module": "ES2020", + "moduleResolution": "node", + "outDir": "./lib/esm", + "resolveJsonModule": true, + "rootDir": "./src", + "sourceMap": true, + "inlineSources": true, + "strict": true, + "target": "es2017" + }, + "include": ["src/**/*"], + "references": [] +} From f92ffd4975d2d8342778efd0f487b266b2430c52 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 7 Sep 2022 14:26:49 -0700 Subject: [PATCH 2/5] wip --- packages/bls-verify/package.json | 1 + packages/bls-verify/src/bls.ts | 592 +++++++++++++ packages/bls-verify/src/index.test.ts | 103 +++ packages/bls-verify/src/index.ts | 20 +- packages/bls-verify/src/math.ts | 1143 +++++++++++++++++++++++++ packages/bls-verify/src/utils.ts | 57 -- 6 files changed, 1853 insertions(+), 63 deletions(-) create mode 100644 packages/bls-verify/src/bls.ts create mode 100644 packages/bls-verify/src/index.test.ts create mode 100644 packages/bls-verify/src/math.ts delete mode 100644 packages/bls-verify/src/utils.ts diff --git a/packages/bls-verify/package.json b/packages/bls-verify/package.json index 565981a35..2c64e5421 100644 --- a/packages/bls-verify/package.json +++ b/packages/bls-verify/package.json @@ -13,6 +13,7 @@ "bugs": { "url": "https://github.com/dfinity/agent-js/issues" }, + "type": "module", "keywords": [ "internet computer", "ic", diff --git a/packages/bls-verify/src/bls.ts b/packages/bls-verify/src/bls.ts new file mode 100644 index 000000000..782e904b4 --- /dev/null +++ b/packages/bls-verify/src/bls.ts @@ -0,0 +1,592 @@ +/*! noble-bls12-381 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ +import nodeCrypto from 'crypto'; +import { + Fp, + Fr, + Fp2, + Fp12, + CURVE, + ProjectivePoint, + map_to_curve_simple_swu_9mod16, + isogenyMapG2, + millerLoop, + psi, + psi2, + calcPairingPrecomputes, + mod, +} from './math'; +export { Fp, Fr, Fp2, Fp12, CURVE }; +const POW_2_381 = 2n ** 381n; +const POW_2_382 = POW_2_381 * 2n; +const POW_2_383 = POW_2_382 * 2n; +const PUBLIC_KEY_LENGTH = 48; +const SHA256_DIGEST_SIZE = 32; +const htfDefaults = { + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + p: CURVE.P, + m: 2, + k: 128, + expand: true, +}; +function isWithinCurveOrder(num) { + return 0 < num && num < CURVE.r; +} +const crypto = { + node: nodeCrypto, + web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, +}; +export const utils = { + hashToField: hash_to_field, + hashToPrivateKey: hash => { + hash = ensureBytes(hash); + if (hash.length < 40 || hash.length > 1024) + throw new Error('Expected 40-1024 bytes of private key as per FIPS 186'); + const num = mod(bytesToNumberBE(hash), CURVE.r); + if (num === 0n || num === 1n) throw new Error('Invalid private key'); + return numberTo32BytesBE(num); + }, + bytesToHex, + randomBytes: (bytesLength = 32) => { + if (crypto.web) { + return crypto.web.getRandomValues(new Uint8Array(bytesLength)); + } else if (crypto.node) { + const { randomBytes } = crypto.node; + return new Uint8Array(randomBytes(bytesLength).buffer); + } else { + throw new Error("The environment doesn't have randomBytes function"); + } + }, + randomPrivateKey: () => { + return utils.hashToPrivateKey(utils.randomBytes(40)); + }, + sha256: async message => { + if (crypto.web) { + const buffer = await crypto.web.subtle.digest('SHA-256', message.buffer); + return new Uint8Array(buffer); + } else if (crypto.node) { + return Uint8Array.from(crypto.node.createHash('sha256').update(message).digest()); + } else { + throw new Error("The environment doesn't have sha256 function"); + } + }, + mod, + getDSTLabel() { + return htfDefaults.DST; + }, + setDSTLabel(newLabel) { + if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) { + throw new TypeError('Invalid DST'); + } + htfDefaults.DST = newLabel; + }, +}; +function bytesToNumberBE(uint8a) { + if (!(uint8a instanceof Uint8Array)) throw new Error('Expected Uint8Array'); + return BigInt('0x' + bytesToHex(Uint8Array.from(uint8a))); +} +const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); +function bytesToHex(uint8a) { + let hex = ''; + for (let i = 0; i < uint8a.length; i++) { + hex += hexes[uint8a[i]]; + } + return hex; +} +function hexToBytes(hex) { + if (typeof hex !== 'string') { + throw new TypeError('hexToBytes: expected string, got ' + typeof hex); + } + if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex'); + const array = new Uint8Array(hex.length / 2); + for (let i = 0; i < array.length; i++) { + const j = i * 2; + const hexByte = hex.slice(j, j + 2); + if (hexByte.length !== 2) throw new Error('Invalid byte sequence'); + const byte = Number.parseInt(hexByte, 16); + if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence'); + array[i] = byte; + } + return array; +} +function numberTo32BytesBE(num) { + const length = 32; + const hex = num.toString(16).padStart(length * 2, '0'); + return hexToBytes(hex); +} +function toPaddedHex(num, padding) { + if (typeof num !== 'bigint' || num < 0n) throw new Error('Expected valid bigint'); + if (typeof padding !== 'number') throw new TypeError('Expected valid padding'); + return num.toString(16).padStart(padding * 2, '0'); +} +function ensureBytes(hex) { + return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex); +} +function concatBytes(...arrays) { + if (arrays.length === 1) return arrays[0]; + const length = arrays.reduce((a, arr) => a + arr.length, 0); + const result = new Uint8Array(length); + for (let i = 0, pad = 0; i < arrays.length; i++) { + const arr = arrays[i]; + result.set(arr, pad); + pad += arr.length; + } + return result; +} +function stringToBytes(str) { + const bytes = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i); + } + return bytes; +} +function os2ip(bytes) { + let result = 0n; + for (let i = 0; i < bytes.length; i++) { + result <<= 8n; + result += BigInt(bytes[i]); + } + return result; +} +function i2osp(value, length) { + if (value < 0 || value >= 1 << (8 * length)) { + throw new Error(`bad I2OSP call: value=${value} length=${length}`); + } + const res = Array.from({ length }).fill(0); + for (let i = length - 1; i >= 0; i--) { + res[i] = value & 0xff; + value >>>= 8; + } + return new Uint8Array(res); +} +function strxor(a, b) { + const arr = new Uint8Array(a.length); + for (let i = 0; i < a.length; i++) { + arr[i] = a[i] ^ b[i]; + } + return arr; +} +async function expand_message_xmd(msg, DST, lenInBytes) { + const H = utils.sha256; + const b_in_bytes = SHA256_DIGEST_SIZE; + const r_in_bytes = b_in_bytes * 2; + const ell = Math.ceil(lenInBytes / b_in_bytes); + if (ell > 255) throw new Error('Invalid xmd length'); + const DST_prime = concatBytes(DST, i2osp(DST.length, 1)); + const Z_pad = i2osp(0, r_in_bytes); + const l_i_b_str = i2osp(lenInBytes, 2); + const b = new Array(ell); + const b_0 = await H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)); + b[0] = await H(concatBytes(b_0, i2osp(1, 1), DST_prime)); + for (let i = 1; i <= ell; i++) { + const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime]; + b[i] = await H(concatBytes(...args)); + } + const pseudo_random_bytes = concatBytes(...b); + return pseudo_random_bytes.slice(0, lenInBytes); +} +async function hash_to_field(msg, count, options = {}) { + const htfOptions = { ...htfDefaults, ...options }; + const log2p = htfOptions.p.toString(2).length; + const L = Math.ceil((log2p + htfOptions.k) / 8); + const len_in_bytes = count * htfOptions.m * L; + const DST = stringToBytes(htfOptions.DST); + let pseudo_random_bytes = msg; + if (htfOptions.expand) { + pseudo_random_bytes = await expand_message_xmd(msg, DST, len_in_bytes); + } + const u = new Array(count); + for (let i = 0; i < count; i++) { + const e = new Array(htfOptions.m); + for (let j = 0; j < htfOptions.m; j++) { + const elm_offset = L * (j + i * htfOptions.m); + const tv = pseudo_random_bytes.slice(elm_offset, elm_offset + L); + e[j] = mod(os2ip(tv), htfOptions.p); + } + u[i] = e; + } + return u; +} +function normalizePrivKey(key) { + let int; + if (key instanceof Uint8Array && key.length === 32) int = bytesToNumberBE(key); + else if (typeof key === 'string' && key.length === 64) int = BigInt(`0x${key}`); + else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key)) int = BigInt(key); + else if (typeof key === 'bigint' && key > 0n) int = key; + else throw new TypeError('Expected valid private key'); + int = mod(int, CURVE.r); + if (!isWithinCurveOrder(int)) throw new Error('Private key must be 0 < key < CURVE.r'); + return int; +} +function assertType(item, type) { + if (!(item instanceof type)) throw new Error('Expected Fp* argument, not number/bigint'); +} +export class PointG1 extends ProjectivePoint { + constructor(x, y, z = Fp.ONE) { + super(x, y, z, Fp); + assertType(x, Fp); + assertType(y, Fp); + assertType(z, Fp); + } + static fromHex(bytes) { + bytes = ensureBytes(bytes); + let point; + if (bytes.length === 48) { + const { P } = CURVE; + const compressedValue = bytesToNumberBE(bytes); + const bflag = mod(compressedValue, POW_2_383) / POW_2_382; + if (bflag === 1n) { + return this.ZERO; + } + const x = new Fp(mod(compressedValue, POW_2_381)); + const right = x.pow(3n).add(new Fp(CURVE.b)); + let y = right.sqrt(); + if (!y) throw new Error('Invalid compressed G1 point'); + const aflag = mod(compressedValue, POW_2_382) / POW_2_381; + if ((y.value * 2n) / P !== aflag) y = y.negate(); + point = new PointG1(x, y); + } else if (bytes.length === 96) { + if ((bytes[0] & (1 << 6)) !== 0) return PointG1.ZERO; + const x = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); + const y = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH)); + point = new PointG1(new Fp(x), new Fp(y)); + } else { + throw new Error('Invalid point G1, expected 48/96 bytes'); + } + point.assertValidity(); + return point; + } + static fromPrivateKey(privateKey) { + return this.BASE.multiplyPrecomputed(normalizePrivKey(privateKey)); + } + toRawBytes(isCompressed = false) { + return hexToBytes(this.toHex(isCompressed)); + } + toHex(isCompressed = false) { + this.assertValidity(); + if (isCompressed) { + const { P } = CURVE; + let hex; + if (this.isZero()) { + hex = POW_2_383 + POW_2_382; + } else { + const [x, y] = this.toAffine(); + const flag = (y.value * 2n) / P; + hex = x.value + flag * POW_2_381 + POW_2_383; + } + return toPaddedHex(hex, PUBLIC_KEY_LENGTH); + } else { + if (this.isZero()) { + return '4'.padEnd(2 * 2 * PUBLIC_KEY_LENGTH, '0'); + } else { + const [x, y] = this.toAffine(); + return toPaddedHex(x.value, PUBLIC_KEY_LENGTH) + toPaddedHex(y.value, PUBLIC_KEY_LENGTH); + } + } + } + assertValidity() { + if (this.isZero()) return this; + // if (!this.isOnCurve()) throw new Error('Invalid G1 point: not on curve Fp'); + // if (!this.isTorsionFree()) throw new Error('Invalid G1 point: must be of prime-order subgroup'); + return this; + } + [Symbol.for('nodejs.util.inspect.custom')]() { + return this.toString(); + } + millerLoop(P) { + return millerLoop(P.pairingPrecomputes(), this.toAffine()); + } + clearCofactor() { + const t = this.mulCurveMinusX(); + return t.add(this); + } + isOnCurve() { + const b = new Fp(CURVE.b); + const { x, y, z } = this; + const left = y.pow(2n).multiply(z).subtract(x.pow(3n)); + const right = b.multiply(z.pow(3n)); + return left.subtract(right).isZero(); + } + sigma() { + const BETA = + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn; + const [x, y] = this.toAffine(); + return new PointG1(x.multiply(BETA), y); + } + phi() { + const cubicRootOfUnityModP = + 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen; + return new PointG1(this.x.multiply(cubicRootOfUnityModP), this.y, this.z); + } + mulCurveX() { + return this.multiplyUnsafe(CURVE.x).negate(); + } + mulCurveMinusX() { + return this.multiplyUnsafe(CURVE.x); + } + isTorsionFree() { + const xP = this.mulCurveX(); + const u2P = xP.mulCurveMinusX(); + return u2P.equals(this.phi()); + } +} +PointG1.BASE = new PointG1(new Fp(CURVE.Gx), new Fp(CURVE.Gy), Fp.ONE); +PointG1.ZERO = new PointG1(Fp.ONE, Fp.ONE, Fp.ZERO); +export class PointG2 extends ProjectivePoint { + constructor(x, y, z = Fp2.ONE) { + super(x, y, z, Fp2); + assertType(x, Fp2); + assertType(y, Fp2); + assertType(z, Fp2); + } + static async hashToCurve(msg) { + msg = ensureBytes(msg); + const u = await hash_to_field(msg, 2); + const Q0 = new PointG2(...isogenyMapG2(map_to_curve_simple_swu_9mod16(u[0]))); + const Q1 = new PointG2(...isogenyMapG2(map_to_curve_simple_swu_9mod16(u[1]))); + const R = Q0.add(Q1); + const P = R.clearCofactor(); + return P; + } + static fromSignature(hex) { + hex = ensureBytes(hex); + const { P } = CURVE; + const half = hex.length / 2; + if (half !== 48 && half !== 96) + throw new Error('Invalid compressed signature length, must be 96 or 192'); + const z1 = bytesToNumberBE(hex.slice(0, half)); + const z2 = bytesToNumberBE(hex.slice(half)); + const bflag1 = mod(z1, POW_2_383) / POW_2_382; + if (bflag1 === 1n) return this.ZERO; + const x1 = new Fp(z1 % POW_2_381); + const x2 = new Fp(z2); + const x = new Fp2(x2, x1); + const y2 = x.pow(3n).add(Fp2.fromBigTuple(CURVE.b2)); + let y = y2.sqrt(); + if (!y) throw new Error('Failed to find a square root'); + const { re: y0, im: y1 } = y.reim(); + const aflag1 = (z1 % POW_2_382) / POW_2_381; + const isGreater = y1 > 0n && (y1 * 2n) / P !== aflag1; + const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1; + if (isGreater || isZero) y = y.multiply(-1n); + const point = new PointG2(x, y, Fp2.ONE); + point.assertValidity(); + return point; + } + static fromHex(bytes) { + bytes = ensureBytes(bytes); + const m_byte = bytes[0] & 0xe0; + if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) { + throw new Error('Invalid encoding flag: ' + m_byte); + } + const bitC = m_byte & 0x80; + const bitI = m_byte & 0x40; + const bitS = m_byte & 0x20; + let point; + if (bytes.length === 96 && bitC) { + const { P, b2 } = CURVE; + const b = Fp2.fromBigTuple(b2); + bytes[0] = bytes[0] & 0x1f; + if (bitI) { + if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('Invalid compressed G2 point'); + } + return PointG2.ZERO; + } + const x_1 = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); + const x_0 = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH)); + const x = new Fp2(new Fp(x_0), new Fp(x_1)); + const right = x.pow(3n).add(b); + let y = right.sqrt(); + if (!y) throw new Error('Invalid compressed G2 point'); + const Y_bit = y.c1.value === 0n ? (y.c0.value * 2n) / P : (y.c1.value * 2n) / P ? 1n : 0n; + y = bitS > 0 && Y_bit > 0 ? y : y.negate(); + return new PointG2(x, y); + } else if (bytes.length === 192 && !bitC) { + if ((bytes[0] & (1 << 6)) !== 0) { + return PointG2.ZERO; + } + const x1 = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); + const x0 = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH, 2 * PUBLIC_KEY_LENGTH)); + const y1 = bytesToNumberBE(bytes.slice(2 * PUBLIC_KEY_LENGTH, 3 * PUBLIC_KEY_LENGTH)); + const y0 = bytesToNumberBE(bytes.slice(3 * PUBLIC_KEY_LENGTH)); + point = new PointG2(Fp2.fromBigTuple([x0, x1]), Fp2.fromBigTuple([y0, y1])); + } else { + throw new Error('Invalid point G2, expected 96/192 bytes'); + } + point.assertValidity(); + return point; + } + static fromPrivateKey(privateKey) { + return this.BASE.multiplyPrecomputed(normalizePrivKey(privateKey)); + } + toSignature() { + if (this.equals(PointG2.ZERO)) { + const sum = POW_2_383 + POW_2_382; + const h = toPaddedHex(sum, PUBLIC_KEY_LENGTH) + toPaddedHex(0n, PUBLIC_KEY_LENGTH); + return hexToBytes(h); + } + const [{ re: x0, im: x1 }, { re: y0, im: y1 }] = this.toAffine().map(a => a.reim()); + const tmp = y1 > 0n ? y1 * 2n : y0 * 2n; + const aflag1 = tmp / CURVE.P; + const z1 = x1 + aflag1 * POW_2_381 + POW_2_383; + const z2 = x0; + return hexToBytes(toPaddedHex(z1, PUBLIC_KEY_LENGTH) + toPaddedHex(z2, PUBLIC_KEY_LENGTH)); + } + toRawBytes(isCompressed = false) { + return hexToBytes(this.toHex(isCompressed)); + } + toHex(isCompressed = false) { + this.assertValidity(); + if (isCompressed) { + const { P } = CURVE; + let x_1 = 0n; + let x_0 = 0n; + if (this.isZero()) { + x_1 = POW_2_383 + POW_2_382; + } else { + const [x, y] = this.toAffine(); + const flag = y.c1.value === 0n ? (y.c0.value * 2n) / P : (y.c1.value * 2n) / P ? 1n : 0n; + x_1 = x.c1.value + flag * POW_2_381 + POW_2_383; + x_0 = x.c0.value; + } + return toPaddedHex(x_1, PUBLIC_KEY_LENGTH) + toPaddedHex(x_0, PUBLIC_KEY_LENGTH); + } else { + if (this.equals(PointG2.ZERO)) { + return '4'.padEnd(2 * 4 * PUBLIC_KEY_LENGTH, '0'); + } + const [{ re: x0, im: x1 }, { re: y0, im: y1 }] = this.toAffine().map(a => a.reim()); + return ( + toPaddedHex(x1, PUBLIC_KEY_LENGTH) + + toPaddedHex(x0, PUBLIC_KEY_LENGTH) + + toPaddedHex(y1, PUBLIC_KEY_LENGTH) + + toPaddedHex(y0, PUBLIC_KEY_LENGTH) + ); + } + } + assertValidity() { + if (this.isZero()) return this; + if (!this.isOnCurve()) throw new Error('Invalid G2 point: not on curve Fp2'); + if (!this.isTorsionFree()) throw new Error('Invalid G2 point: must be of prime-order subgroup'); + return this; + } + psi() { + return this.fromAffineTuple(psi(...this.toAffine())); + } + psi2() { + return this.fromAffineTuple(psi2(...this.toAffine())); + } + mulCurveX() { + return this.multiplyUnsafe(CURVE.x).negate(); + } + clearCofactor() { + const P = this; + let t1 = P.mulCurveX(); + let t2 = P.psi(); + let t3 = P.double(); + t3 = t3.psi2(); + t3 = t3.subtract(t2); + t2 = t1.add(t2); + t2 = t2.mulCurveX(); + t3 = t3.add(t2); + t3 = t3.subtract(t1); + const Q = t3.subtract(P); + return Q; + } + isOnCurve() { + const b = Fp2.fromBigTuple(CURVE.b2); + const { x, y, z } = this; + const left = y.pow(2n).multiply(z).subtract(x.pow(3n)); + const right = b.multiply(z.pow(3n)); + return left.subtract(right).isZero(); + } + isTorsionFree() { + const P = this; + return P.mulCurveX().equals(P.psi()); + } + [Symbol.for('nodejs.util.inspect.custom')]() { + return this.toString(); + } + clearPairingPrecomputes() { + this._PPRECOMPUTES = undefined; + } + pairingPrecomputes() { + if (this._PPRECOMPUTES) return this._PPRECOMPUTES; + this._PPRECOMPUTES = calcPairingPrecomputes(...this.toAffine()); + return this._PPRECOMPUTES; + } +} +PointG2.BASE = new PointG2(Fp2.fromBigTuple(CURVE.G2x), Fp2.fromBigTuple(CURVE.G2y), Fp2.ONE); +PointG2.ZERO = new PointG2(Fp2.ONE, Fp2.ONE, Fp2.ZERO); +export function pairing(P, Q, withFinalExponent = true) { + if (P.isZero() || Q.isZero()) throw new Error('No pairings at point of Infinity'); + P.assertValidity(); + Q.assertValidity(); + const looped = P.millerLoop(Q); + return withFinalExponent ? looped.finalExponentiate() : looped; +} +function normP1(point) { + return point instanceof PointG1 ? point : PointG1.fromHex(point); +} +function normP2(point) { + return point instanceof PointG2 ? point : PointG2.fromSignature(point); +} +async function normP2Hash(point) { + return point instanceof PointG2 ? point : PointG2.hashToCurve(point); +} +export function getPublicKey(privateKey) { + return PointG1.fromPrivateKey(privateKey).toRawBytes(true); +} +export async function sign(message, privateKey) { + const msgPoint = await normP2Hash(message); + msgPoint.assertValidity(); + const sigPoint = msgPoint.multiply(normalizePrivKey(privateKey)); + if (message instanceof PointG2) return sigPoint; + return sigPoint.toSignature(); +} +export async function verify(signature, message, publicKey) { + const P = normP1(publicKey); + const Hm = await normP2Hash(message); + const G = PointG1.BASE; + const S = normP2(signature); + const ePHm = pairing(P.negate(), Hm, false); + const eGS = pairing(G, S, false); + const exp = eGS.multiply(ePHm).finalExponentiate(); + return exp.equals(Fp12.ONE); +} +export function aggregatePublicKeys(publicKeys) { + if (!publicKeys.length) throw new Error('Expected non-empty array'); + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), PointG1.ZERO); + if (publicKeys[0] instanceof PointG1) return agg.assertValidity(); + return agg.toRawBytes(true); +} +export function aggregateSignatures(signatures) { + if (!signatures.length) throw new Error('Expected non-empty array'); + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), PointG2.ZERO); + if (signatures[0] instanceof PointG2) return agg.assertValidity(); + return agg.toSignature(); +} +export async function verifyBatch(signature, messages, publicKeys) { + if (!messages.length) throw new Error('Expected non-empty messages array'); + if (publicKeys.length !== messages.length) throw new Error('Pubkey count should equal msg count'); + const sig = normP2(signature); + const nMessages = await Promise.all(messages.map(normP2Hash)); + const nPublicKeys = publicKeys.map(normP1); + try { + const paired = []; + for (const message of new Set(nMessages)) { + const groupPublicKey = nMessages.reduce( + (groupPublicKey, subMessage, i) => + subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, + PointG1.ZERO, + ); + paired.push(pairing(groupPublicKey, message, false)); + } + paired.push(pairing(PointG1.BASE.negate(), sig, false)); + const product = paired.reduce((a, b) => a.multiply(b), Fp12.ONE); + const exp = product.finalExponentiate(); + return exp.equals(Fp12.ONE); + } catch { + return false; + } +} +PointG1.BASE.calcMultiplyPrecomputes(4); diff --git a/packages/bls-verify/src/index.test.ts b/packages/bls-verify/src/index.test.ts new file mode 100644 index 000000000..e66746823 --- /dev/null +++ b/packages/bls-verify/src/index.test.ts @@ -0,0 +1,103 @@ +import { blsVerify } from './index'; +import * as Cert from '../../agent/src/certificate'; +import * as cbor from '../../agent/src/cbor'; +import { fromHex, toHex } from '../../agent/src/utils/buffer'; +import { Principal } from '@dfinity/principal'; +function label(str: string): ArrayBuffer { + return new TextEncoder().encode(str); +} + +function pruned(str: string): ArrayBuffer { + return fromHex(str); +} + +// Root public key for the IC main net, encoded as hex +const IC_ROOT_KEY = + '308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c05030201036100814' + + 'c0e6ec71fab583b08bd81373c255c3c371b2e84863c98a4f1e08b74235d14fb5d9c0cd546d968' + + '5f913a0c0b2cc5341583bf4b4392e467db96d65b9bb4cb717112f8472e0d5a4d14505ffd7484' + + 'b01291091c5f87b98883463f98091a0baaae'; + +// The sample certificate for testing delegation is extracted from the response used in agent-rs tests, where they were taken +// from an interaction with the IC mainnet. +const SAMPLE_CERT: string = + 'd9d9f7a364747265658301830182045820250f5e26868d9c1ea7ab29cbe9c15bf1c47c0d7605e803e39e375a7fe09c6ebb830183024e726571756573745f7374617475738301820458204b268227774ec77ff2b37ecb12157329d54cf376694bdd59ded7803efd82386f83025820edad510eaaa08ed2acd4781324e6446269da6753ec17760f206bbe81c465ff528301830183024b72656a6563745f636f64658203410383024e72656a6563745f6d6573736167658203584443616e69737465722069766733372d71696161612d61616161622d61616167612d63616920686173206e6f20757064617465206d6574686f64202772656769737465722783024673746174757382034872656a65637465648204582097232f31f6ab7ca4fe53eb6568fc3e02bc22fe94ab31d010e5fb3c642301f1608301820458203a48d1fc213d49307103104f7d72c2b5930edba8787b90631f343b3aa68a5f0a83024474696d65820349e2dc939091c696eb16697369676e6174757265583089a2be21b5fa8ac9fab1527e041327ce899d7da971436a1f2165393947b4d942365bfe5488710e61a619ba48388a21b16a64656c65676174696f6ea2697375626e65745f6964581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac4026b6365727469666963617465590231d9d9f7a26474726565830182045820ae023f28c3b9d966c8fb09f9ed755c828aadb5152e00aaf700b18c9c067294b483018302467375626e6574830182045820e83bb025f6574c8f31233dc0fe289ff546dfa1e49bd6116dd6e8896d90a4946e830182045820e782619092d69d5bebf0924138bd4116b0156b5a95e25c358ea8cf7e7161a661830183018204582062513fa926c9a9ef803ac284d620f303189588e1d3904349ab63b6470856fc4883018204582060e9a344ced2c9c4a96a0197fd585f2d259dbd193e4eada56239cac26087f9c58302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe82045820996f17bb926be3315745dea7282005a793b58e76afeb5d43d1a28ce29d2d158583024474696d6582034995b8aac0e4eda2ea16697369676e61747572655830ace9fcdd9bc977e05d6328f889dc4e7c99114c737a494653cb27a1f55c06f4555e0f160980af5ead098acc195010b2f7'; + +test('delegation works for canisters within the subnet range', async () => { + // The certificate specifies the range from + // 0x00000000002000000101 + // to + // 0x00000000002FFFFF0101 + const rangeStart = Principal.fromHex('00000000002000000101'); + const rangeInterior = Principal.fromHex('000000000020000C0101'); + const rangeEnd = Principal.fromHex('00000000002FFFFF0101'); + async function verifies(canisterId) { + await expect( + Cert.Certificate.create({ + certificate: fromHex(SAMPLE_CERT), + rootKey: fromHex(IC_ROOT_KEY), + canisterId: canisterId, + blsVerify, + }), + ).resolves.not.toThrow(); + } + await verifies(rangeStart); + await verifies(rangeInterior); + await verifies(rangeEnd); +}); + +test('delegation check fails for canisters outside of the subnet range', async () => { + // Use a different principal than the happy path, which isn't in the delegation ranges. + // The certificate specifies the range from + // 0x00000000002000000101 + // to + // 0x00000000002FFFFF0101 + const beforeRange = Principal.fromHex('00000000000000020101'); + const afterRange = Principal.fromHex('00000000003000020101'); + async function certificateFails(canisterId) { + await expect( + Cert.Certificate.create({ + certificate: fromHex(SAMPLE_CERT), + rootKey: fromHex(IC_ROOT_KEY), + canisterId: canisterId, + blsVerify, + }), + ).rejects.toThrow(/Invalid certificate/); + } + await certificateFails(beforeRange); + await certificateFails(afterRange); +}); + +// The only situation in which one can read state of the IC management canister +// is when the user calls provisional_create_canister_with_cycles. In this case, +// we shouldn't check the delegations. +test('delegation check succeeds for the management canister', async () => { + await expect( + Cert.Certificate.create({ + certificate: fromHex(SAMPLE_CERT), + rootKey: fromHex(IC_ROOT_KEY), + canisterId: Principal.managementCanister(), + blsVerify, + }), + ).resolves.not.toThrow(); +}); + +type FakeCert = { + tree: Cert.HashTree; + signature: ArrayBuffer; + delegation?: { subnet_id: ArrayBuffer; certificate: ArrayBuffer }; +}; + +test('certificate verification fails for an invalid signature', async () => { + let badCert: FakeCert = cbor.decode(fromHex(SAMPLE_CERT)); + badCert.signature = new ArrayBuffer(badCert.signature.byteLength); + const badCertEncoded = cbor.encode(badCert); + await expect( + Cert.Certificate.create({ + certificate: badCertEncoded, + rootKey: fromHex(IC_ROOT_KEY), + canisterId: Principal.fromText('ivg37-qiaaa-aaaab-aaaga-cai'), + blsVerify, + }), + ).rejects.toThrow('Invalid certificate'); +}); diff --git a/packages/bls-verify/src/index.ts b/packages/bls-verify/src/index.ts index d3018e0f9..da6120047 100644 --- a/packages/bls-verify/src/index.ts +++ b/packages/bls-verify/src/index.ts @@ -1,5 +1,5 @@ -import { verify } from '@noble/bls12-381'; -import { toHex } from './utils'; +import { verify } from './bls'; +import * as cbor from '../../agent/src/cbor'; type VerifyFunc = (pk: Uint8Array, sig: Uint8Array, msg: Uint8Array) => Promise; @@ -15,8 +15,16 @@ export const blsVerify: VerifyFunc = async ( signature: Uint8Array | string, message: Uint8Array | string, ): Promise => { - const pk = typeof publicKey === 'string' ? publicKey : toHex(publicKey); - const sig = typeof signature === 'string' ? signature : toHex(signature); - const msg = typeof message === 'string' ? message : toHex(message); - return await verify(sig, msg, pk); + let result = false; + try { + signature.byteLength; //? + result = await verify(signature, message, publicKey).catch(error => { + console.log(error); + return false; //? + }); //? + } catch (error) { + console.error(error); //? + } + + return result; }; diff --git a/packages/bls-verify/src/math.ts b/packages/bls-verify/src/math.ts new file mode 100644 index 000000000..fc314f06f --- /dev/null +++ b/packages/bls-verify/src/math.ts @@ -0,0 +1,1143 @@ +export const CURVE = { + P: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn, + r: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n, + h: 0x396c8c005555e1568c00aaab0000aaabn, + Gx: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbn, + Gy: 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1n, + b: 4n, + P2: + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn ** + 2n - + 1n, + h2: 0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5n, + G2x: [ + 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8n, + 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7en, + ], + G2y: [ + 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801n, + 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79ben, + ], + b2: [4n, 4n], + x: 0xd201000000010000n, + h2Eff: + 0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551n, +}; +const BLS_X_LEN = bitLen(CURVE.x); +export function mod(a, b) { + const res = a % b; + return res >= 0n ? res : b + res; +} +export function powMod(num, power, modulo) { + if (modulo <= 0n || power < 0n) throw new Error('Expected power/modulo > 0'); + if (modulo === 1n) return 0n; + let res = 1n; + while (power > 0n) { + if (power & 1n) res = (res * num) % modulo; + num = (num * num) % modulo; + power >>= 1n; + } + return res; +} +function genInvertBatch(cls, nums) { + const tmp = new Array(nums.length); + const lastMultiplied = nums.reduce((acc, num, i) => { + if (num.isZero()) return acc; + tmp[i] = acc; + return acc.multiply(num); + }, cls.ONE); + const inverted = lastMultiplied.invert(); + nums.reduceRight((acc, num, i) => { + if (num.isZero()) return acc; + tmp[i] = acc.multiply(tmp[i]); + return acc.multiply(num); + }, inverted); + return tmp; +} +function bitLen(n) { + let len; + for (len = 0; n > 0n; n >>= 1n, len += 1); + return len; +} +function bitGet(n, pos) { + return (n >> BigInt(pos)) & 1n; +} +function invert(number, modulo = CURVE.P) { + const _0n = 0n; + const _1n = 1n; + if (number === _0n || modulo <= _0n) { + throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); + } + let a = mod(number, modulo); + let b = modulo; + let x = _0n, + y = _1n, + u = _1n, + v = _0n; + while (a !== _0n) { + const q = b / a; + const r = b % a; + const m = x - u * q; + const n = y - v * q; + (b = a), (a = r), (x = u), (y = v), (u = m), (v = n); + } + const gcd = b; + if (gcd !== _1n) throw new Error('invert: does not exist'); + return mod(x, modulo); +} +export class Fp { + constructor(value) { + this.value = mod(value, Fp.ORDER); + } + isZero() { + return this.value === 0n; + } + equals(rhs) { + return this.value === rhs.value; + } + negate() { + return new Fp(-this.value); + } + invert() { + return new Fp(invert(this.value, Fp.ORDER)); + } + add(rhs) { + return new Fp(this.value + rhs.value); + } + square() { + return new Fp(this.value * this.value); + } + pow(n) { + return new Fp(powMod(this.value, n, Fp.ORDER)); + } + sqrt() { + const root = this.pow((Fp.ORDER + 1n) / 4n); + if (!root.square().equals(this)) return; + return root; + } + subtract(rhs) { + return new Fp(this.value - rhs.value); + } + multiply(rhs) { + if (rhs instanceof Fp) rhs = rhs.value; + return new Fp(this.value * rhs); + } + div(rhs) { + if (typeof rhs === 'bigint') rhs = new Fp(rhs); + return this.multiply(rhs.invert()); + } + toString() { + const str = this.value.toString(16).padStart(96, '0'); + return str.slice(0, 2) + '.' + str.slice(-2); + } +} +Fp.ORDER = CURVE.P; +Fp.MAX_BITS = bitLen(CURVE.P); +Fp.ZERO = new Fp(0n); +Fp.ONE = new Fp(1n); +export class Fr { + constructor(value) { + this.value = mod(value, Fr.ORDER); + } + static isValid(b) { + return b <= Fr.ORDER; + } + isZero() { + return this.value === 0n; + } + equals(rhs) { + return this.value === rhs.value; + } + negate() { + return new Fr(-this.value); + } + invert() { + return new Fr(invert(this.value, Fr.ORDER)); + } + add(rhs) { + return new Fr(this.value + rhs.value); + } + square() { + return new Fr(this.value * this.value); + } + pow(n) { + return new Fr(powMod(this.value, n, Fr.ORDER)); + } + subtract(rhs) { + return new Fr(this.value - rhs.value); + } + multiply(rhs) { + if (rhs instanceof Fr) rhs = rhs.value; + return new Fr(this.value * rhs); + } + div(rhs) { + if (typeof rhs === 'bigint') rhs = new Fr(rhs); + return this.multiply(rhs.invert()); + } + legendre() { + return this.pow((Fr.ORDER - 1n) / 2n); + } + sqrt() { + if (!this.legendre().equals(Fr.ONE)) return; + const P = Fr.ORDER; + let q, s, z; + for (q = P - 1n, s = 0; q % 2n === 0n; q /= 2n, s++); + if (s === 1) return this.pow((P + 1n) / 4n); + for (z = 2n; z < P && new Fr(z).legendre().value !== P - 1n; z++); + let c = powMod(z, q, P); + let r = powMod(this.value, (q + 1n) / 2n, P); + let t = powMod(this.value, q, P); + let t2 = 0n; + while (mod(t - 1n, P) !== 0n) { + t2 = mod(t * t, P); + let i; + for (i = 1; i < s; i++) { + if (mod(t2 - 1n, P) === 0n) break; + t2 = mod(t2 * t2, P); + } + let b = powMod(c, BigInt(1 << (s - i - 1)), P); + r = mod(r * b, P); + c = mod(b * b, P); + t = mod(t * c, P); + s = i; + } + return new Fr(r); + } + toString() { + return '0x' + this.value.toString(16).padStart(64, '0'); + } +} +Fr.ORDER = CURVE.r; +Fr.ZERO = new Fr(0n); +Fr.ONE = new Fr(1n); +function powMod_FQP(fqp, fqpOne, n) { + const elm = fqp; + if (n === 0n) return fqpOne; + if (n === 1n) return elm; + let p = fqpOne; + let d = elm; + while (n > 0n) { + if (n & 1n) p = p.multiply(d); + n >>= 1n; + d = d.square(); + } + return p; +} +export class Fp2 { + constructor(c0, c1) { + this.c0 = c0; + this.c1 = c1; + if (typeof c0 === 'bigint') throw new Error('c0: Expected Fp'); + if (typeof c1 === 'bigint') throw new Error('c1: Expected Fp'); + } + static fromBigTuple(tuple) { + const fps = tuple.map(n => new Fp(n)); + return new Fp2(...fps); + } + one() { + return Fp2.ONE; + } + isZero() { + return this.c0.isZero() && this.c1.isZero(); + } + toString() { + return `Fp2(${this.c0} + ${this.c1}×i)`; + } + reim() { + return { re: this.c0.value, im: this.c1.value }; + } + negate() { + const { c0, c1 } = this; + return new Fp2(c0.negate(), c1.negate()); + } + equals(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return c0.equals(r0) && c1.equals(r1); + } + add(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return new Fp2(c0.add(r0), c1.add(r1)); + } + subtract(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return new Fp2(c0.subtract(r0), c1.subtract(r1)); + } + multiply(rhs) { + const { c0, c1 } = this; + if (typeof rhs === 'bigint') { + return new Fp2(c0.multiply(rhs), c1.multiply(rhs)); + } + const { c0: r0, c1: r1 } = rhs; + let t1 = c0.multiply(r0); + let t2 = c1.multiply(r1); + return new Fp2(t1.subtract(t2), c0.add(c1).multiply(r0.add(r1)).subtract(t1.add(t2))); + } + pow(n) { + return powMod_FQP(this, Fp2.ONE, n); + } + div(rhs) { + const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); + return this.multiply(inv); + } + mulByNonresidue() { + const c0 = this.c0; + const c1 = this.c1; + return new Fp2(c0.subtract(c1), c0.add(c1)); + } + square() { + const c0 = this.c0; + const c1 = this.c1; + const a = c0.add(c1); + const b = c0.subtract(c1); + const c = c0.add(c0); + return new Fp2(a.multiply(b), c.multiply(c1)); + } + sqrt() { + const candidateSqrt = this.pow((Fp2.ORDER + 8n) / 16n); + const check = candidateSqrt.square().div(this); + const R = FP2_ROOTS_OF_UNITY; + const divisor = [R[0], R[2], R[4], R[6]].find(r => r.equals(check)); + if (!divisor) return; + const index = R.indexOf(divisor); + const root = R[index / 2]; + if (!root) throw new Error('Invalid root'); + const x1 = candidateSqrt.div(root); + const x2 = x1.negate(); + const { re: re1, im: im1 } = x1.reim(); + const { re: re2, im: im2 } = x2.reim(); + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1; + return x2; + } + invert() { + const { re: a, im: b } = this.reim(); + const factor = new Fp(a * a + b * b).invert(); + return new Fp2(factor.multiply(new Fp(a)), factor.multiply(new Fp(-b))); + } + frobeniusMap(power) { + return new Fp2(this.c0, this.c1.multiply(FP2_FROBENIUS_COEFFICIENTS[power % 2])); + } + multiplyByB() { + let c0 = this.c0; + let c1 = this.c1; + let t0 = c0.multiply(4n); + let t1 = c1.multiply(4n); + return new Fp2(t0.subtract(t1), t0.add(t1)); + } +} +Fp2.ORDER = CURVE.P2; +Fp2.MAX_BITS = bitLen(CURVE.P2); +Fp2.ZERO = new Fp2(Fp.ZERO, Fp.ZERO); +Fp2.ONE = new Fp2(Fp.ONE, Fp.ZERO); +export class Fp6 { + constructor(c0, c1, c2) { + this.c0 = c0; + this.c1 = c1; + this.c2 = c2; + } + static fromBigSix(t) { + if (!Array.isArray(t) || t.length !== 6) throw new Error('Invalid Fp6 usage'); + const c = [t.slice(0, 2), t.slice(2, 4), t.slice(4, 6)].map(t => Fp2.fromBigTuple(t)); + return new Fp6(...c); + } + fromTriple(triple) { + return new Fp6(...triple); + } + one() { + return Fp6.ONE; + } + isZero() { + return this.c0.isZero() && this.c1.isZero() && this.c2.isZero(); + } + negate() { + const { c0, c1, c2 } = this; + return new Fp6(c0.negate(), c1.negate(), c2.negate()); + } + toString() { + return `Fp6(${this.c0} + ${this.c1} * v, ${this.c2} * v^2)`; + } + equals(rhs) { + const { c0, c1, c2 } = this; + const { c0: r0, c1: r1, c2: r2 } = rhs; + return c0.equals(r0) && c1.equals(r1) && c2.equals(r2); + } + add(rhs) { + const { c0, c1, c2 } = this; + const { c0: r0, c1: r1, c2: r2 } = rhs; + return new Fp6(c0.add(r0), c1.add(r1), c2.add(r2)); + } + subtract(rhs) { + const { c0, c1, c2 } = this; + const { c0: r0, c1: r1, c2: r2 } = rhs; + return new Fp6(c0.subtract(r0), c1.subtract(r1), c2.subtract(r2)); + } + multiply(rhs) { + if (typeof rhs === 'bigint') { + return new Fp6(this.c0.multiply(rhs), this.c1.multiply(rhs), this.c2.multiply(rhs)); + } + let { c0, c1, c2 } = this; + let { c0: r0, c1: r1, c2: r2 } = rhs; + let t0 = c0.multiply(r0); + let t1 = c1.multiply(r1); + let t2 = c2.multiply(r2); + return new Fp6( + t0.add(c1.add(c2).multiply(r1.add(r2)).subtract(t1.add(t2)).mulByNonresidue()), + c0.add(c1).multiply(r0.add(r1)).subtract(t0.add(t1)).add(t2.mulByNonresidue()), + t1.add(c0.add(c2).multiply(r0.add(r2)).subtract(t0.add(t2))), + ); + } + pow(n) { + return powMod_FQP(this, Fp6.ONE, n); + } + div(rhs) { + const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); + return this.multiply(inv); + } + mulByNonresidue() { + return new Fp6(this.c2.mulByNonresidue(), this.c0, this.c1); + } + multiplyBy1(b1) { + return new Fp6( + this.c2.multiply(b1).mulByNonresidue(), + this.c0.multiply(b1), + this.c1.multiply(b1), + ); + } + multiplyBy01(b0, b1) { + let { c0, c1, c2 } = this; + let t0 = c0.multiply(b0); + let t1 = c1.multiply(b1); + return new Fp6( + c1.add(c2).multiply(b1).subtract(t1).mulByNonresidue().add(t0), + b0.add(b1).multiply(c0.add(c1)).subtract(t0).subtract(t1), + c0.add(c2).multiply(b0).subtract(t0).add(t1), + ); + } + multiplyByFp2(rhs) { + let { c0, c1, c2 } = this; + return new Fp6(c0.multiply(rhs), c1.multiply(rhs), c2.multiply(rhs)); + } + square() { + let { c0, c1, c2 } = this; + let t0 = c0.square(); + let t1 = c0.multiply(c1).multiply(2n); + let t3 = c1.multiply(c2).multiply(2n); + let t4 = c2.square(); + return new Fp6( + t3.mulByNonresidue().add(t0), + t4.mulByNonresidue().add(t1), + t1.add(c0.subtract(c1).add(c2).square()).add(t3).subtract(t0).subtract(t4), + ); + } + invert() { + let { c0, c1, c2 } = this; + let t0 = c0.square().subtract(c2.multiply(c1).mulByNonresidue()); + let t1 = c2.square().mulByNonresidue().subtract(c0.multiply(c1)); + let t2 = c1.square().subtract(c0.multiply(c2)); + let t4 = c2.multiply(t1).add(c1.multiply(t2)).mulByNonresidue().add(c0.multiply(t0)).invert(); + return new Fp6(t4.multiply(t0), t4.multiply(t1), t4.multiply(t2)); + } + frobeniusMap(power) { + return new Fp6( + this.c0.frobeniusMap(power), + this.c1.frobeniusMap(power).multiply(FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + this.c2.frobeniusMap(power).multiply(FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + ); + } +} +Fp6.ZERO = new Fp6(Fp2.ZERO, Fp2.ZERO, Fp2.ZERO); +Fp6.ONE = new Fp6(Fp2.ONE, Fp2.ZERO, Fp2.ZERO); +export class Fp12 { + constructor(c0, c1) { + this.c0 = c0; + this.c1 = c1; + } + static fromBigTwelve(t) { + return new Fp12(Fp6.fromBigSix(t.slice(0, 6)), Fp6.fromBigSix(t.slice(6, 12))); + } + fromTuple(c) { + return new Fp12(...c); + } + one() { + return Fp12.ONE; + } + isZero() { + return this.c0.isZero() && this.c1.isZero(); + } + toString() { + return `Fp12(${this.c0} + ${this.c1} * w)`; + } + negate() { + const { c0, c1 } = this; + return new Fp12(c0.negate(), c1.negate()); + } + equals(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return c0.equals(r0) && c1.equals(r1); + } + add(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return new Fp12(c0.add(r0), c1.add(r1)); + } + subtract(rhs) { + const { c0, c1 } = this; + const { c0: r0, c1: r1 } = rhs; + return new Fp12(c0.subtract(r0), c1.subtract(r1)); + } + multiply(rhs) { + if (typeof rhs === 'bigint') return new Fp12(this.c0.multiply(rhs), this.c1.multiply(rhs)); + let { c0, c1 } = this; + let { c0: r0, c1: r1 } = rhs; + let t1 = c0.multiply(r0); + let t2 = c1.multiply(r1); + return new Fp12( + t1.add(t2.mulByNonresidue()), + c0.add(c1).multiply(r0.add(r1)).subtract(t1.add(t2)), + ); + } + pow(n) { + return powMod_FQP(this, Fp12.ONE, n); + } + div(rhs) { + const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); + return this.multiply(inv); + } + multiplyBy014(o0, o1, o4) { + let { c0, c1 } = this; + let t0 = c0.multiplyBy01(o0, o1); + let t1 = c1.multiplyBy1(o4); + return new Fp12( + t1.mulByNonresidue().add(t0), + c1.add(c0).multiplyBy01(o0, o1.add(o4)).subtract(t0).subtract(t1), + ); + } + multiplyByFp2(rhs) { + return new Fp12(this.c0.multiplyByFp2(rhs), this.c1.multiplyByFp2(rhs)); + } + square() { + let { c0, c1 } = this; + let ab = c0.multiply(c1); + return new Fp12( + c1.mulByNonresidue().add(c0).multiply(c0.add(c1)).subtract(ab).subtract(ab.mulByNonresidue()), + ab.add(ab), + ); + } + invert() { + let { c0, c1 } = this; + let t = c0.square().subtract(c1.square().mulByNonresidue()).invert(); + return new Fp12(c0.multiply(t), c1.multiply(t).negate()); + } + conjugate() { + return new Fp12(this.c0, this.c1.negate()); + } + frobeniusMap(power) { + const r0 = this.c0.frobeniusMap(power); + const { c0, c1, c2 } = this.c1.frobeniusMap(power); + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12]; + return new Fp12(r0, new Fp6(c0.multiply(coeff), c1.multiply(coeff), c2.multiply(coeff))); + } + Fp4Square(a, b) { + const a2 = a.square(); + const b2 = b.square(); + return { + first: b2.mulByNonresidue().add(a2), + second: a.add(b).square().subtract(a2).subtract(b2), + }; + } + cyclotomicSquare() { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = this.c0; + const { c0: c1c0, c1: c1c1, c2: c1c2 } = this.c1; + const { first: t3, second: t4 } = this.Fp4Square(c0c0, c1c1); + const { first: t5, second: t6 } = this.Fp4Square(c1c0, c0c2); + const { first: t7, second: t8 } = this.Fp4Square(c0c1, c1c2); + let t9 = t8.mulByNonresidue(); + return new Fp12( + new Fp6( + t3.subtract(c0c0).multiply(2n).add(t3), + t5.subtract(c0c1).multiply(2n).add(t5), + t7.subtract(c0c2).multiply(2n).add(t7), + ), + new Fp6( + t9.add(c1c0).multiply(2n).add(t9), + t4.add(c1c1).multiply(2n).add(t4), + t6.add(c1c2).multiply(2n).add(t6), + ), + ); + } + cyclotomicExp(n) { + let z = Fp12.ONE; + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = z.cyclotomicSquare(); + if (bitGet(n, i)) z = z.multiply(this); + } + return z; + } + finalExponentiate() { + const { x } = CURVE; + const t0 = this.frobeniusMap(6).div(this); + const t1 = t0.frobeniusMap(2).multiply(t0); + const t2 = t1.cyclotomicExp(x).conjugate(); + const t3 = t1.cyclotomicSquare().conjugate().multiply(t2); + const t4 = t3.cyclotomicExp(x).conjugate(); + const t5 = t4.cyclotomicExp(x).conjugate(); + const t6 = t5.cyclotomicExp(x).conjugate().multiply(t2.cyclotomicSquare()); + const t7 = t6.cyclotomicExp(x).conjugate(); + const t2_t5_pow_q2 = t2.multiply(t5).frobeniusMap(2); + const t4_t1_pow_q3 = t4.multiply(t1).frobeniusMap(3); + const t6_t1c_pow_q1 = t6.multiply(t1.conjugate()).frobeniusMap(1); + const t7_t3c_t1 = t7.multiply(t3.conjugate()).multiply(t1); + return t2_t5_pow_q2.multiply(t4_t1_pow_q3).multiply(t6_t1c_pow_q1).multiply(t7_t3c_t1); + } +} +Fp12.ZERO = new Fp12(Fp6.ZERO, Fp6.ZERO); +Fp12.ONE = new Fp12(Fp6.ONE, Fp6.ZERO); +export class ProjectivePoint { + constructor(x, y, z, C) { + this.x = x; + this.y = y; + this.z = z; + this.C = C; + } + isZero() { + return this.z.isZero(); + } + createPoint(x, y, z) { + return new this.constructor(x, y, z); + } + getZero() { + return this.createPoint(this.C.ONE, this.C.ONE, this.C.ZERO); + } + equals(rhs) { + if (this.constructor !== rhs.constructor) + throw new Error( + `ProjectivePoint#equals: this is ${this.constructor}, but rhs is ${rhs.constructor}`, + ); + const a = this; + const b = rhs; + const xe = a.x.multiply(b.z).equals(b.x.multiply(a.z)); + const ye = a.y.multiply(b.z).equals(b.y.multiply(a.z)); + return xe && ye; + } + negate() { + return this.createPoint(this.x, this.y.negate(), this.z); + } + toString(isAffine = true) { + if (this.isZero()) { + return `Point`; + } + if (!isAffine) { + return `Point`; + } + const [x, y] = this.toAffine(); + return `Point`; + } + fromAffineTuple(xy) { + return this.createPoint(xy[0], xy[1], this.C.ONE); + } + toAffine(invZ = this.z.invert()) { + if (invZ.isZero()) throw new Error('Invalid inverted z'); + return [this.x.multiply(invZ), this.y.multiply(invZ)]; + } + toAffineBatch(points) { + const toInv = genInvertBatch( + this.C, + points.map(p => p.z), + ); + return points.map((p, i) => p.toAffine(toInv[i])); + } + normalizeZ(points) { + return this.toAffineBatch(points).map(t => this.fromAffineTuple(t)); + } + double() { + const { x, y, z } = this; + const W = x.multiply(x).multiply(3n); + const S = y.multiply(z); + const SS = S.multiply(S); + const SSS = SS.multiply(S); + const B = x.multiply(y).multiply(S); + const H = W.multiply(W).subtract(B.multiply(8n)); + const X3 = H.multiply(S).multiply(2n); + const Y3 = W.multiply(B.multiply(4n).subtract(H)).subtract( + y.multiply(y).multiply(8n).multiply(SS), + ); + const Z3 = SSS.multiply(8n); + return this.createPoint(X3, Y3, Z3); + } + add(rhs) { + if (this.constructor !== rhs.constructor) + throw new Error( + `ProjectivePoint#add: this is ${this.constructor}, but rhs is ${rhs.constructor}`, + ); + const p1 = this; + const p2 = rhs; + if (p1.isZero()) return p2; + if (p2.isZero()) return p1; + const X1 = p1.x; + const Y1 = p1.y; + const Z1 = p1.z; + const X2 = p2.x; + const Y2 = p2.y; + const Z2 = p2.z; + const U1 = Y2.multiply(Z1); + const U2 = Y1.multiply(Z2); + const V1 = X2.multiply(Z1); + const V2 = X1.multiply(Z2); + if (V1.equals(V2) && U1.equals(U2)) return this.double(); + if (V1.equals(V2)) return this.getZero(); + const U = U1.subtract(U2); + const V = V1.subtract(V2); + const VV = V.multiply(V); + const VVV = VV.multiply(V); + const V2VV = V2.multiply(VV); + const W = Z1.multiply(Z2); + const A = U.multiply(U).multiply(W).subtract(VVV).subtract(V2VV.multiply(2n)); + const X3 = V.multiply(A); + const Y3 = U.multiply(V2VV.subtract(A)).subtract(VVV.multiply(U2)); + const Z3 = VVV.multiply(W); + return this.createPoint(X3, Y3, Z3); + } + subtract(rhs) { + if (this.constructor !== rhs.constructor) + throw new Error( + `ProjectivePoint#subtract: this is ${this.constructor}, but rhs is ${rhs.constructor}`, + ); + return this.add(rhs.negate()); + } + validateScalar(n) { + if (typeof n === 'number') n = BigInt(n); + if (typeof n !== 'bigint' || n <= 0 || n > CURVE.r) { + throw new Error( + `Point#multiply: invalid scalar, expected positive integer < CURVE.r. Got: ${n}`, + ); + } + return n; + } + multiplyUnsafe(scalar) { + let n = this.validateScalar(scalar); + let point = this.getZero(); + let d = this; + while (n > 0n) { + if (n & 1n) point = point.add(d); + d = d.double(); + n >>= 1n; + } + return point; + } + multiply(scalar) { + let n = this.validateScalar(scalar); + let point = this.getZero(); + let fake = this.getZero(); + let d = this; + let bits = Fp.ORDER; + while (bits > 0n) { + if (n & 1n) { + point = point.add(d); + } else { + fake = fake.add(d); + } + d = d.double(); + n >>= 1n; + bits >>= 1n; + } + return point; + } + maxBits() { + return this.C.MAX_BITS; + } + precomputeWindow(W) { + const windows = Math.ceil(this.maxBits() / W); + const windowSize = 2 ** (W - 1); + let points = []; + let p = this; + let base = p; + for (let window = 0; window < windows; window++) { + base = p; + points.push(base); + for (let i = 1; i < windowSize; i++) { + base = base.add(p); + points.push(base); + } + p = base.double(); + } + return points; + } + calcMultiplyPrecomputes(W) { + if (this._MPRECOMPUTES) throw new Error('This point already has precomputes'); + this._MPRECOMPUTES = [W, this.normalizeZ(this.precomputeWindow(W))]; + } + clearMultiplyPrecomputes() { + this._MPRECOMPUTES = undefined; + } + wNAF(n) { + let W, precomputes; + if (this._MPRECOMPUTES) { + [W, precomputes] = this._MPRECOMPUTES; + } else { + W = 1; + precomputes = this.precomputeWindow(W); + } + let p = this.getZero(); + let f = this.getZero(); + const windows = Math.ceil(this.maxBits() / W); + const windowSize = 2 ** (W - 1); + const mask = BigInt(2 ** W - 1); + const maxNumber = 2 ** W; + const shiftBy = BigInt(W); + for (let window = 0; window < windows; window++) { + const offset = window * windowSize; + let wbits = Number(n & mask); + n >>= shiftBy; + if (wbits > windowSize) { + wbits -= maxNumber; + n += 1n; + } + if (wbits === 0) { + f = f.add(window % 2 ? precomputes[offset].negate() : precomputes[offset]); + } else { + const cached = precomputes[offset + Math.abs(wbits) - 1]; + p = p.add(wbits < 0 ? cached.negate() : cached); + } + } + return [p, f]; + } + multiplyPrecomputed(scalar) { + return this.wNAF(this.validateScalar(scalar))[0]; + } +} +function sgn0(x) { + const { re: x0, im: x1 } = x.reim(); + const sign_0 = x0 % 2n; + const zero_0 = x0 === 0n; + const sign_1 = x1 % 2n; + return BigInt(sign_0 || (zero_0 && sign_1)); +} +const P_MINUS_9_DIV_16 = (CURVE.P ** 2n - 9n) / 16n; +function sqrt_div_fp2(u, v) { + const v7 = v.pow(7n); + const uv7 = u.multiply(v7); + const uv15 = uv7.multiply(v7.multiply(v)); + const gamma = uv15.pow(P_MINUS_9_DIV_16).multiply(uv7); + let success = false; + let result = gamma; + const positiveRootsOfUnity = FP2_ROOTS_OF_UNITY.slice(0, 4); + positiveRootsOfUnity.forEach(root => { + const candidate = root.multiply(gamma); + if (candidate.pow(2n).multiply(v).subtract(u).isZero() && !success) { + success = true; + result = candidate; + } + }); + return { success, sqrtCandidateOrGamma: result }; +} +export function map_to_curve_simple_swu_9mod16(t) { + const iso_3_a = new Fp2(new Fp(0n), new Fp(240n)); + const iso_3_b = new Fp2(new Fp(1012n), new Fp(1012n)); + const iso_3_z = new Fp2(new Fp(-2n), new Fp(-1n)); + if (Array.isArray(t)) t = Fp2.fromBigTuple(t); + const t2 = t.pow(2n); + const iso_3_z_t2 = iso_3_z.multiply(t2); + const ztzt = iso_3_z_t2.add(iso_3_z_t2.pow(2n)); + let denominator = iso_3_a.multiply(ztzt).negate(); + let numerator = iso_3_b.multiply(ztzt.add(Fp2.ONE)); + if (denominator.isZero()) denominator = iso_3_z.multiply(iso_3_a); + let v = denominator.pow(3n); + let u = numerator + .pow(3n) + .add(iso_3_a.multiply(numerator).multiply(denominator.pow(2n))) + .add(iso_3_b.multiply(v)); + const { success, sqrtCandidateOrGamma } = sqrt_div_fp2(u, v); + let y; + if (success) y = sqrtCandidateOrGamma; + const sqrtCandidateX1 = sqrtCandidateOrGamma.multiply(t.pow(3n)); + u = iso_3_z_t2.pow(3n).multiply(u); + let success2 = false; + FP2_ETAs.forEach(eta => { + const etaSqrtCandidate = eta.multiply(sqrtCandidateX1); + const temp = etaSqrtCandidate.pow(2n).multiply(v).subtract(u); + if (temp.isZero() && !success && !success2) { + y = etaSqrtCandidate; + success2 = true; + } + }); + if (!success && !success2) throw new Error('Hash to Curve - Optimized SWU failure'); + if (success2) numerator = numerator.multiply(iso_3_z_t2); + y = y; + if (sgn0(t) !== sgn0(y)) y = y.negate(); + y = y.multiply(denominator); + return [numerator, y, denominator]; +} +export function isogenyMapG2(xyz) { + const x = xyz[0], + y = xyz[1], + z = xyz[2]; + const zz = z.multiply(z); + const zzz = zz.multiply(z); + const zPowers = [z, zz, zzz]; + const mapped = [Fp2.ZERO, Fp2.ZERO, Fp2.ZERO, Fp2.ZERO]; + for (let i = 0; i < ISOGENY_COEFFICIENTS.length; i++) { + const k_i = ISOGENY_COEFFICIENTS[i]; + mapped[i] = k_i.slice(-1)[0]; + const arr = k_i.slice(0, -1).reverse(); + for (let j = 0; j < arr.length; j++) { + const k_i_j = arr[j]; + mapped[i] = mapped[i].multiply(x).add(zPowers[j].multiply(k_i_j)); + } + } + mapped[2] = mapped[2].multiply(y); + mapped[3] = mapped[3].multiply(z); + const z2 = mapped[1].multiply(mapped[3]); + const x2 = mapped[0].multiply(mapped[3]); + const y2 = mapped[1].multiply(mapped[2]); + return [x2, y2, z2]; +} +export function calcPairingPrecomputes(x, y) { + const Qx = x, + Qy = y, + Qz = Fp2.ONE; + let Rx = Qx, + Ry = Qy, + Rz = Qz; + let ell_coeff = []; + for (let i = BLS_X_LEN - 2; i >= 0; i--) { + let t0 = Ry.square(); + let t1 = Rz.square(); + let t2 = t1.multiply(3n).multiplyByB(); + let t3 = t2.multiply(3n); + let t4 = Ry.add(Rz).square().subtract(t1).subtract(t0); + ell_coeff.push([t2.subtract(t0), Rx.square().multiply(3n), t4.negate()]); + Rx = t0.subtract(t3).multiply(Rx).multiply(Ry).div(2n); + Ry = t0.add(t3).div(2n).square().subtract(t2.square().multiply(3n)); + Rz = t0.multiply(t4); + if (bitGet(CURVE.x, i)) { + let t0 = Ry.subtract(Qy.multiply(Rz)); + let t1 = Rx.subtract(Qx.multiply(Rz)); + ell_coeff.push([t0.multiply(Qx).subtract(t1.multiply(Qy)), t0.negate(), t1]); + let t2 = t1.square(); + let t3 = t2.multiply(t1); + let t4 = t2.multiply(Rx); + let t5 = t3.subtract(t4.multiply(2n)).add(t0.square().multiply(Rz)); + Rx = t1.multiply(t5); + Ry = t4.subtract(t5).multiply(t0).subtract(t3.multiply(Ry)); + Rz = Rz.multiply(t3); + } + } + return ell_coeff; +} +export function millerLoop(ell, g1) { + const Px = g1[0].value; + const Py = g1[1].value; + let f12 = Fp12.ONE; + for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) { + const E = ell[j]; + f12 = f12.multiplyBy014(E[0], E[1].multiply(Px), E[2].multiply(Py)); + if (bitGet(CURVE.x, i)) { + j += 1; + const F = ell[j]; + f12 = f12.multiplyBy014(F[0], F[1].multiply(Px), F[2].multiply(Py)); + } + if (i !== 0) f12 = f12.square(); + } + return f12.conjugate(); +} +const ut_root = new Fp6(Fp2.ZERO, Fp2.ONE, Fp2.ZERO); +const wsq = new Fp12(ut_root, Fp6.ZERO); +const wcu = new Fp12(Fp6.ZERO, ut_root); +const [wsq_inv, wcu_inv] = genInvertBatch(Fp12, [wsq, wcu]); +export function psi(x, y) { + const x2 = wsq_inv.multiplyByFp2(x).frobeniusMap(1).multiply(wsq).c0.c0; + const y2 = wcu_inv.multiplyByFp2(y).frobeniusMap(1).multiply(wcu).c0.c0; + return [x2, y2]; +} +export function psi2(x, y) { + return [x.multiply(PSI2_C1), y.negate()]; +} +const PSI2_C1 = + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn; +const rv1 = + 0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n; +const ev1 = + 0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90n; +const ev2 = + 0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5n; +const ev3 = + 0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17n; +const ev4 = + 0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1n; +const FP2_FROBENIUS_COEFFICIENTS = [ + 0x1n, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, +].map(item => new Fp(item)); +const FP2_ROOTS_OF_UNITY = [ + [1n, 0n], + [rv1, -rv1], + [0n, 1n], + [rv1, rv1], + [-1n, 0n], + [-rv1, rv1], + [0n, -1n], + [-rv1, -rv1], +].map(pair => Fp2.fromBigTuple(pair)); +const FP2_ETAs = [ + [ev1, ev2], + [-ev2, ev1], + [ev3, ev4], + [-ev4, ev3], +].map(pair => Fp2.fromBigTuple(pair)); +const FP6_FROBENIUS_COEFFICIENTS_1 = [ + [0x1n, 0x0n], + [ + 0x0n, + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, + ], + [ + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, + 0x0n, + ], + [0x0n, 0x1n], + [ + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, + 0x0n, + ], + [ + 0x0n, + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, + ], +].map(pair => Fp2.fromBigTuple(pair)); +const FP6_FROBENIUS_COEFFICIENTS_2 = [ + [0x1n, 0x0n], + [ + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn, + 0x0n, + ], + [ + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, + 0x0n, + ], + [ + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, + 0x0n, + ], + [ + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, + 0x0n, + ], + [ + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn, + 0x0n, + ], +].map(pair => Fp2.fromBigTuple(pair)); +const FP12_FROBENIUS_COEFFICIENTS = [ + [0x1n, 0x0n], + [ + 0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n, + 0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n, + ], + [ + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn, + 0x0n, + ], + [ + 0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n, + 0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n, + ], + [ + 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, + 0x0n, + ], + [ + 0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n, + 0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n, + ], + [ + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, + 0x0n, + ], + [ + 0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n, + 0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n, + ], + [ + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, + 0x0n, + ], + [ + 0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n, + 0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n, + ], + [ + 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn, + 0x0n, + ], + [ + 0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n, + 0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n, + ], +].map(n => Fp2.fromBigTuple(n)); +const xnum = [ + [ + 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6n, + 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6n, + ], + [ + 0x0n, + 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71an, + ], + [ + 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71en, + 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38dn, + ], + [ + 0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1n, + 0x0n, + ], +].map(pair => Fp2.fromBigTuple(pair)); +const xden = [ + [ + 0x0n, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63n, + ], + [ + 0xcn, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9fn, + ], + [0x1n, 0x0n], + [0x0n, 0x0n], +].map(pair => Fp2.fromBigTuple(pair)); +const ynum = [ + [ + 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706n, + 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706n, + ], + [ + 0x0n, + 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97ben, + ], + [ + 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71cn, + 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38fn, + ], + [ + 0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10n, + 0x0n, + ], +].map(pair => Fp2.fromBigTuple(pair)); +const yden = [ + [ + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fbn, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fbn, + ], + [ + 0x0n, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3n, + ], + [ + 0x12n, + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99n, + ], + [0x1n, 0x0n], +].map(pair => Fp2.fromBigTuple(pair)); +const ISOGENY_COEFFICIENTS = [xnum, xden, ynum, yden]; diff --git a/packages/bls-verify/src/utils.ts b/packages/bls-verify/src/utils.ts deleted file mode 100644 index 4db40bdd7..000000000 --- a/packages/bls-verify/src/utils.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Concatenate multiple array buffers. - * @param buffers The buffers to concatenate. - */ -export function concat(...buffers: ArrayBuffer[]): ArrayBuffer { - const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); - let index = 0; - for (const b of buffers) { - result.set(new Uint8Array(b), index); - index += b.byteLength; - } - return result.buffer; -} - -/** - * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. - * @param buffer The buffer to return the hexadecimal string of. - */ -export function toHex(buffer: ArrayBuffer): string { - return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); -} - -const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); - -/** - * Transforms a hexadecimal string into an array buffer. - * @param hex The hexadecimal string to use. - */ -export function fromHex(hex: string): ArrayBuffer { - if (!hexRe.test(hex)) { - throw new Error('Invalid hexadecimal string.'); - } - const buffer = [...hex] - .reduce((acc, curr, i) => { - // tslint:disable-next-line:no-bitwise - acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; - return acc; - }, [] as string[]) - .map(x => Number.parseInt(x, 16)); - - return new Uint8Array(buffer).buffer; -} - -export function compare(b1: ArrayBuffer, b2: ArrayBuffer): number { - if (b1.byteLength !== b2.byteLength) { - return b1.byteLength - b2.byteLength; - } - - const u1 = new Uint8Array(b1); - const u2 = new Uint8Array(b2); - for (let i = 0; i < u1.length; i++) { - if (u1[i] !== u2[i]) { - return u1[i] - u2[i]; - } - } - return 0; -} From a225f8affe48f048a97b92dddcd37059b511904c Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 7 Sep 2022 16:46:19 -0700 Subject: [PATCH 3/5] tests passing - very slow --- package-lock.json | 100 +- packages/bls-verify/.gitignore | 2 +- packages/bls-verify/lib/cjs/index.js | 20 + packages/bls-verify/lib/cjs/utils.js | 59 + packages/bls-verify/lib/esm/index.js | 16 + packages/bls-verify/lib/esm/utils.js | 52 + packages/bls-verify/package.json | 2 +- packages/bls-verify/src/bls.ts | 592 ---- packages/bls-verify/src/index.test.ts | 26 +- packages/bls-verify/src/index.ts | 40 +- packages/bls-verify/src/math.ts | 1143 ------- packages/bls-verify/src/utils.ts | 28 + .../bls-verify/src/vendor/amcl-js/index.js | 1 + .../src/vendor/amcl-js/package.json | 15 + .../bls-verify/src/vendor/amcl-js/readme.md | 62 + .../bls-verify/src/vendor/amcl-js/src/aes.js | 882 ++++++ .../bls-verify/src/vendor/amcl-js/src/big.js | 1505 +++++++++ .../bls-verify/src/vendor/amcl-js/src/bls.js | 184 ++ .../src/vendor/amcl-js/src/bls192.js | 183 ++ .../src/vendor/amcl-js/src/bls256.js | 188 ++ .../bls-verify/src/vendor/amcl-js/src/ctx.js | 1203 ++++++++ .../bls-verify/src/vendor/amcl-js/src/ecdh.js | 447 +++ .../bls-verify/src/vendor/amcl-js/src/ecp.js | 1966 ++++++++++++ .../bls-verify/src/vendor/amcl-js/src/ecp2.js | 1094 +++++++ .../bls-verify/src/vendor/amcl-js/src/ecp4.js | 970 ++++++ .../bls-verify/src/vendor/amcl-js/src/ecp8.js | 1172 +++++++ .../bls-verify/src/vendor/amcl-js/src/ff.js | 1024 +++++++ .../bls-verify/src/vendor/amcl-js/src/fp.js | 833 +++++ .../bls-verify/src/vendor/amcl-js/src/fp12.js | 1069 +++++++ .../bls-verify/src/vendor/amcl-js/src/fp16.js | 594 ++++ .../bls-verify/src/vendor/amcl-js/src/fp2.js | 483 +++ .../bls-verify/src/vendor/amcl-js/src/fp24.js | 1131 +++++++ .../bls-verify/src/vendor/amcl-js/src/fp4.js | 722 +++++ .../bls-verify/src/vendor/amcl-js/src/fp48.js | 1225 ++++++++ .../bls-verify/src/vendor/amcl-js/src/fp8.js | 737 +++++ .../bls-verify/src/vendor/amcl-js/src/gcm.js | 471 +++ .../src/vendor/amcl-js/src/hash256.js | 235 ++ .../src/vendor/amcl-js/src/hash384.js | 361 +++ .../src/vendor/amcl-js/src/hash512.js | 364 +++ .../bls-verify/src/vendor/amcl-js/src/hmac.js | 764 +++++ .../bls-verify/src/vendor/amcl-js/src/hpke.js | 297 ++ .../bls-verify/src/vendor/amcl-js/src/mpin.js | 274 ++ .../src/vendor/amcl-js/src/mpin192.js | 275 ++ .../src/vendor/amcl-js/src/mpin256.js | 276 ++ .../bls-verify/src/vendor/amcl-js/src/nhs.js | 766 +++++ .../bls-verify/src/vendor/amcl-js/src/pair.js | 1076 +++++++ .../src/vendor/amcl-js/src/pair4.js | 819 +++++ .../src/vendor/amcl-js/src/pair8.js | 918 ++++++ .../bls-verify/src/vendor/amcl-js/src/rand.js | 197 ++ .../src/vendor/amcl-js/src/rom_curve.js | 2705 +++++++++++++++++ .../src/vendor/amcl-js/src/rom_field.js | 1101 +++++++ .../bls-verify/src/vendor/amcl-js/src/rsa.js | 290 ++ .../bls-verify/src/vendor/amcl-js/src/sha3.js | 392 +++ .../src/vendor/amcl-js/src/share.js | 152 + .../src/vendor/amcl-js/src/uint64.js | 67 + 55 files changed, 29743 insertions(+), 1827 deletions(-) create mode 100644 packages/bls-verify/lib/cjs/index.js create mode 100644 packages/bls-verify/lib/cjs/utils.js create mode 100644 packages/bls-verify/lib/esm/index.js create mode 100644 packages/bls-verify/lib/esm/utils.js delete mode 100644 packages/bls-verify/src/bls.ts delete mode 100644 packages/bls-verify/src/math.ts create mode 100644 packages/bls-verify/src/utils.ts create mode 100644 packages/bls-verify/src/vendor/amcl-js/index.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/package.json create mode 100644 packages/bls-verify/src/vendor/amcl-js/readme.md create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/aes.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/big.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/bls.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/bls192.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/bls256.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ctx.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ecdh.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ecp.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ecp2.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ecp4.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ecp8.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/ff.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp12.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp16.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp2.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp24.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp4.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp48.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/fp8.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/gcm.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/hash256.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/hash384.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/hash512.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/hmac.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/hpke.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/mpin.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/mpin192.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/mpin256.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/nhs.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/pair.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/pair4.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/pair8.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/rand.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/rom_curve.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/rom_field.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/rsa.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/sha3.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/share.js create mode 100644 packages/bls-verify/src/vendor/amcl-js/src/uint64.js diff --git a/package-lock.json b/package-lock.json index 9d2f1ff6c..9f40b9176 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1794,7 +1794,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, "engines": { "node": ">=0.1.90" } @@ -3050,17 +3049,6 @@ "win32" ] }, - "node_modules/@noble/bls12-381": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/bls12-381/-/bls12-381-1.3.0.tgz", - "integrity": "sha512-rYQXhQ+Q6fDYLSO/ZUY9RsDE0Adi2Iua9xXxNxLmO8jXiBZGVxecWQsC1116aRlv3XGLvoZTGqyy5vAcBu368g==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6292,6 +6280,10 @@ "ajv": "^6.9.1" } }, + "node_modules/amcl-js": { + "resolved": "packages/bls-verify/src/vendor/amcl-js", + "link": true + }, "node_modules/amp": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", @@ -6520,8 +6512,7 @@ "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "node_modules/async-listener": { "version": "0.6.10", @@ -7610,7 +7601,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true, "engines": { "node": ">=0.1.90" } @@ -8059,7 +8049,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -10136,7 +10125,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "dev": true, "engines": { "node": "> 0.1.90" } @@ -11826,8 +11814,7 @@ "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -14373,8 +14360,7 @@ "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "node_modules/nan": { "version": "2.16.0", @@ -15930,7 +15916,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dev": true, "dependencies": { "@colors/colors": "1.5.0", "async": "3.2.3", @@ -15945,8 +15930,7 @@ "node_modules/prompt/node_modules/async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "node_modules/promptly": { "version": "2.2.0", @@ -16216,7 +16200,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, "dependencies": { "mute-stream": "~0.0.4" }, @@ -16584,7 +16567,6 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -17222,7 +17204,6 @@ "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true, "engines": { "node": "*" } @@ -19060,7 +19041,6 @@ "version": "2.4.6", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", - "dev": true, "dependencies": { "async": "^3.2.3", "colors": "1.0.x", @@ -19626,7 +19606,23 @@ "version": "1.0.0-beta.0", "license": "Apache-2.0", "dependencies": { - "@noble/bls12-381": "^1.3.0" + "amcl-js": "file:src/vendor/amcl-js" + } + }, + "packages/bls-verify/src/vendor/amcl-js": { + "version": "3.0.0", + "license": "Apache License 2.0", + "dependencies": { + "prompt": "^1.0.0" + } + }, + "packages/bls-verify/vendor/miracl": { + "name": "amcl-js", + "version": "3.0.0", + "extraneous": true, + "license": "Apache License 2.0", + "dependencies": { + "prompt": "^1.0.0" } }, "packages/candid": { @@ -21191,8 +21187,7 @@ "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" }, "@cspotcode/source-map-support": { "version": "0.8.1", @@ -21541,7 +21536,7 @@ "@dfinity/bls-verify": { "version": "file:packages/bls-verify", "requires": { - "@noble/bls12-381": "*" + "amcl-js": "file:src/vendor/amcl-js" } }, "@dfinity/candid": { @@ -22740,11 +22735,6 @@ "dev": true, "optional": true }, - "@noble/bls12-381": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/bls12-381/-/bls12-381-1.3.0.tgz", - "integrity": "sha512-rYQXhQ+Q6fDYLSO/ZUY9RsDE0Adi2Iua9xXxNxLmO8jXiBZGVxecWQsC1116aRlv3XGLvoZTGqyy5vAcBu368g==" - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -25133,6 +25123,12 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "requires": {} }, + "amcl-js": { + "version": "file:packages/bls-verify/src/vendor/amcl-js", + "requires": { + "prompt": "^1.0.0" + } + }, "amp": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", @@ -25299,8 +25295,7 @@ "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "async-listener": { "version": "0.6.10", @@ -26109,8 +26104,7 @@ "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==" }, "combined-stream": { "version": "1.0.8", @@ -26456,8 +26450,7 @@ "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "dev": true + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==" }, "cypress": { "version": "10.7.0", @@ -27905,8 +27898,7 @@ "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "dev": true + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==" }, "fake-indexeddb": { "version": "4.0.0", @@ -29141,8 +29133,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -31043,8 +31034,7 @@ "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "nan": { "version": "2.16.0", @@ -32191,7 +32181,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dev": true, "requires": { "@colors/colors": "1.5.0", "async": "3.2.3", @@ -32203,8 +32192,7 @@ "async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" } } }, @@ -32424,7 +32412,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, "requires": { "mute-stream": "~0.0.4" } @@ -32713,8 +32700,7 @@ "revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", - "dev": true + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==" }, "rfdc": { "version": "1.3.0", @@ -33225,8 +33211,7 @@ "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" }, "stack-utils": { "version": "2.0.5", @@ -34498,7 +34483,6 @@ "version": "2.4.6", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", - "dev": true, "requires": { "async": "^3.2.3", "colors": "1.0.x", diff --git a/packages/bls-verify/.gitignore b/packages/bls-verify/.gitignore index 40ba0014d..ebb03fc9f 100644 --- a/packages/bls-verify/.gitignore +++ b/packages/bls-verify/.gitignore @@ -1,7 +1,7 @@ build_info.json node_modules/ dist/ -**/*.js + **/*.js.map **/*.d.ts diff --git a/packages/bls-verify/lib/cjs/index.js b/packages/bls-verify/lib/cjs/index.js new file mode 100644 index 000000000..dffc55576 --- /dev/null +++ b/packages/bls-verify/lib/cjs/index.js @@ -0,0 +1,20 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.blsVerify = void 0; +const bls12_381_1 = require('@noble/bls12-381'); +const utils_1 = require('./utils'); +/** + * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation + * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature + * @param {Uint8Array | string} signature - digital signature + * @param {Uint8Array | string} message - message to verify + * @returns boolean + */ +const blsVerify = async (publicKey, signature, message) => { + const pk = typeof publicKey === 'string' ? publicKey : (0, utils_1.toHex)(publicKey); + const sig = typeof signature === 'string' ? signature : (0, utils_1.toHex)(signature); + const msg = typeof message === 'string' ? message : (0, utils_1.toHex)(message); + return await (0, bls12_381_1.verify)(sig, msg, pk); +}; +exports.blsVerify = blsVerify; +//# sourceMappingURL=index.js.map diff --git a/packages/bls-verify/lib/cjs/utils.js b/packages/bls-verify/lib/cjs/utils.js new file mode 100644 index 000000000..a9e3de4d9 --- /dev/null +++ b/packages/bls-verify/lib/cjs/utils.js @@ -0,0 +1,59 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.compare = exports.fromHex = exports.toHex = exports.concat = void 0; +/** + * Concatenate multiple array buffers. + * @param buffers The buffers to concatenate. + */ +function concat(...buffers) { + const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); + let index = 0; + for (const b of buffers) { + result.set(new Uint8Array(b), index); + index += b.byteLength; + } + return result.buffer; +} +exports.concat = concat; +/** + * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. + * @param buffer The buffer to return the hexadecimal string of. + */ +function toHex(buffer) { + return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); +} +exports.toHex = toHex; +const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); +/** + * Transforms a hexadecimal string into an array buffer. + * @param hex The hexadecimal string to use. + */ +function fromHex(hex) { + if (!hexRe.test(hex)) { + throw new Error('Invalid hexadecimal string.'); + } + const buffer = [...hex] + .reduce((acc, curr, i) => { + // tslint:disable-next-line:no-bitwise + acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; + return acc; + }, []) + .map(x => Number.parseInt(x, 16)); + return new Uint8Array(buffer).buffer; +} +exports.fromHex = fromHex; +function compare(b1, b2) { + if (b1.byteLength !== b2.byteLength) { + return b1.byteLength - b2.byteLength; + } + const u1 = new Uint8Array(b1); + const u2 = new Uint8Array(b2); + for (let i = 0; i < u1.length; i++) { + if (u1[i] !== u2[i]) { + return u1[i] - u2[i]; + } + } + return 0; +} +exports.compare = compare; +//# sourceMappingURL=utils.js.map diff --git a/packages/bls-verify/lib/esm/index.js b/packages/bls-verify/lib/esm/index.js new file mode 100644 index 000000000..4c18c62cf --- /dev/null +++ b/packages/bls-verify/lib/esm/index.js @@ -0,0 +1,16 @@ +import { verify } from '@noble/bls12-381'; +import { toHex } from './utils'; +/** + * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation + * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature + * @param {Uint8Array | string} signature - digital signature + * @param {Uint8Array | string} message - message to verify + * @returns boolean + */ +export const blsVerify = async (publicKey, signature, message) => { + const pk = typeof publicKey === 'string' ? publicKey : toHex(publicKey); + const sig = typeof signature === 'string' ? signature : toHex(signature); + const msg = typeof message === 'string' ? message : toHex(message); + return await verify(sig, msg, pk); +}; +//# sourceMappingURL=index.js.map diff --git a/packages/bls-verify/lib/esm/utils.js b/packages/bls-verify/lib/esm/utils.js new file mode 100644 index 000000000..27e0702dd --- /dev/null +++ b/packages/bls-verify/lib/esm/utils.js @@ -0,0 +1,52 @@ +/** + * Concatenate multiple array buffers. + * @param buffers The buffers to concatenate. + */ +export function concat(...buffers) { + const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); + let index = 0; + for (const b of buffers) { + result.set(new Uint8Array(b), index); + index += b.byteLength; + } + return result.buffer; +} +/** + * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. + * @param buffer The buffer to return the hexadecimal string of. + */ +export function toHex(buffer) { + return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); +} +const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); +/** + * Transforms a hexadecimal string into an array buffer. + * @param hex The hexadecimal string to use. + */ +export function fromHex(hex) { + if (!hexRe.test(hex)) { + throw new Error('Invalid hexadecimal string.'); + } + const buffer = [...hex] + .reduce((acc, curr, i) => { + // tslint:disable-next-line:no-bitwise + acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; + return acc; + }, []) + .map(x => Number.parseInt(x, 16)); + return new Uint8Array(buffer).buffer; +} +export function compare(b1, b2) { + if (b1.byteLength !== b2.byteLength) { + return b1.byteLength - b2.byteLength; + } + const u1 = new Uint8Array(b1); + const u2 = new Uint8Array(b2); + for (let i = 0; i < u1.length; i++) { + if (u1[i] !== u2[i]) { + return u1[i] - u2[i]; + } + } + return 0; +} +//# sourceMappingURL=utils.js.map diff --git a/packages/bls-verify/package.json b/packages/bls-verify/package.json index 2c64e5421..ae43159ef 100644 --- a/packages/bls-verify/package.json +++ b/packages/bls-verify/package.json @@ -45,6 +45,6 @@ "prettier:write": "npm run prettier -- --write" }, "dependencies": { - "@noble/bls12-381": "^1.3.0" + "amcl-js": "file:src/vendor/amcl-js" } } diff --git a/packages/bls-verify/src/bls.ts b/packages/bls-verify/src/bls.ts deleted file mode 100644 index 782e904b4..000000000 --- a/packages/bls-verify/src/bls.ts +++ /dev/null @@ -1,592 +0,0 @@ -/*! noble-bls12-381 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ -import nodeCrypto from 'crypto'; -import { - Fp, - Fr, - Fp2, - Fp12, - CURVE, - ProjectivePoint, - map_to_curve_simple_swu_9mod16, - isogenyMapG2, - millerLoop, - psi, - psi2, - calcPairingPrecomputes, - mod, -} from './math'; -export { Fp, Fr, Fp2, Fp12, CURVE }; -const POW_2_381 = 2n ** 381n; -const POW_2_382 = POW_2_381 * 2n; -const POW_2_383 = POW_2_382 * 2n; -const PUBLIC_KEY_LENGTH = 48; -const SHA256_DIGEST_SIZE = 32; -const htfDefaults = { - DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - p: CURVE.P, - m: 2, - k: 128, - expand: true, -}; -function isWithinCurveOrder(num) { - return 0 < num && num < CURVE.r; -} -const crypto = { - node: nodeCrypto, - web: typeof self === 'object' && 'crypto' in self ? self.crypto : undefined, -}; -export const utils = { - hashToField: hash_to_field, - hashToPrivateKey: hash => { - hash = ensureBytes(hash); - if (hash.length < 40 || hash.length > 1024) - throw new Error('Expected 40-1024 bytes of private key as per FIPS 186'); - const num = mod(bytesToNumberBE(hash), CURVE.r); - if (num === 0n || num === 1n) throw new Error('Invalid private key'); - return numberTo32BytesBE(num); - }, - bytesToHex, - randomBytes: (bytesLength = 32) => { - if (crypto.web) { - return crypto.web.getRandomValues(new Uint8Array(bytesLength)); - } else if (crypto.node) { - const { randomBytes } = crypto.node; - return new Uint8Array(randomBytes(bytesLength).buffer); - } else { - throw new Error("The environment doesn't have randomBytes function"); - } - }, - randomPrivateKey: () => { - return utils.hashToPrivateKey(utils.randomBytes(40)); - }, - sha256: async message => { - if (crypto.web) { - const buffer = await crypto.web.subtle.digest('SHA-256', message.buffer); - return new Uint8Array(buffer); - } else if (crypto.node) { - return Uint8Array.from(crypto.node.createHash('sha256').update(message).digest()); - } else { - throw new Error("The environment doesn't have sha256 function"); - } - }, - mod, - getDSTLabel() { - return htfDefaults.DST; - }, - setDSTLabel(newLabel) { - if (typeof newLabel !== 'string' || newLabel.length > 2048 || newLabel.length === 0) { - throw new TypeError('Invalid DST'); - } - htfDefaults.DST = newLabel; - }, -}; -function bytesToNumberBE(uint8a) { - if (!(uint8a instanceof Uint8Array)) throw new Error('Expected Uint8Array'); - return BigInt('0x' + bytesToHex(Uint8Array.from(uint8a))); -} -const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); -function bytesToHex(uint8a) { - let hex = ''; - for (let i = 0; i < uint8a.length; i++) { - hex += hexes[uint8a[i]]; - } - return hex; -} -function hexToBytes(hex) { - if (typeof hex !== 'string') { - throw new TypeError('hexToBytes: expected string, got ' + typeof hex); - } - if (hex.length % 2) throw new Error('hexToBytes: received invalid unpadded hex'); - const array = new Uint8Array(hex.length / 2); - for (let i = 0; i < array.length; i++) { - const j = i * 2; - const hexByte = hex.slice(j, j + 2); - if (hexByte.length !== 2) throw new Error('Invalid byte sequence'); - const byte = Number.parseInt(hexByte, 16); - if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence'); - array[i] = byte; - } - return array; -} -function numberTo32BytesBE(num) { - const length = 32; - const hex = num.toString(16).padStart(length * 2, '0'); - return hexToBytes(hex); -} -function toPaddedHex(num, padding) { - if (typeof num !== 'bigint' || num < 0n) throw new Error('Expected valid bigint'); - if (typeof padding !== 'number') throw new TypeError('Expected valid padding'); - return num.toString(16).padStart(padding * 2, '0'); -} -function ensureBytes(hex) { - return hex instanceof Uint8Array ? Uint8Array.from(hex) : hexToBytes(hex); -} -function concatBytes(...arrays) { - if (arrays.length === 1) return arrays[0]; - const length = arrays.reduce((a, arr) => a + arr.length, 0); - const result = new Uint8Array(length); - for (let i = 0, pad = 0; i < arrays.length; i++) { - const arr = arrays[i]; - result.set(arr, pad); - pad += arr.length; - } - return result; -} -function stringToBytes(str) { - const bytes = new Uint8Array(str.length); - for (let i = 0; i < str.length; i++) { - bytes[i] = str.charCodeAt(i); - } - return bytes; -} -function os2ip(bytes) { - let result = 0n; - for (let i = 0; i < bytes.length; i++) { - result <<= 8n; - result += BigInt(bytes[i]); - } - return result; -} -function i2osp(value, length) { - if (value < 0 || value >= 1 << (8 * length)) { - throw new Error(`bad I2OSP call: value=${value} length=${length}`); - } - const res = Array.from({ length }).fill(0); - for (let i = length - 1; i >= 0; i--) { - res[i] = value & 0xff; - value >>>= 8; - } - return new Uint8Array(res); -} -function strxor(a, b) { - const arr = new Uint8Array(a.length); - for (let i = 0; i < a.length; i++) { - arr[i] = a[i] ^ b[i]; - } - return arr; -} -async function expand_message_xmd(msg, DST, lenInBytes) { - const H = utils.sha256; - const b_in_bytes = SHA256_DIGEST_SIZE; - const r_in_bytes = b_in_bytes * 2; - const ell = Math.ceil(lenInBytes / b_in_bytes); - if (ell > 255) throw new Error('Invalid xmd length'); - const DST_prime = concatBytes(DST, i2osp(DST.length, 1)); - const Z_pad = i2osp(0, r_in_bytes); - const l_i_b_str = i2osp(lenInBytes, 2); - const b = new Array(ell); - const b_0 = await H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)); - b[0] = await H(concatBytes(b_0, i2osp(1, 1), DST_prime)); - for (let i = 1; i <= ell; i++) { - const args = [strxor(b_0, b[i - 1]), i2osp(i + 1, 1), DST_prime]; - b[i] = await H(concatBytes(...args)); - } - const pseudo_random_bytes = concatBytes(...b); - return pseudo_random_bytes.slice(0, lenInBytes); -} -async function hash_to_field(msg, count, options = {}) { - const htfOptions = { ...htfDefaults, ...options }; - const log2p = htfOptions.p.toString(2).length; - const L = Math.ceil((log2p + htfOptions.k) / 8); - const len_in_bytes = count * htfOptions.m * L; - const DST = stringToBytes(htfOptions.DST); - let pseudo_random_bytes = msg; - if (htfOptions.expand) { - pseudo_random_bytes = await expand_message_xmd(msg, DST, len_in_bytes); - } - const u = new Array(count); - for (let i = 0; i < count; i++) { - const e = new Array(htfOptions.m); - for (let j = 0; j < htfOptions.m; j++) { - const elm_offset = L * (j + i * htfOptions.m); - const tv = pseudo_random_bytes.slice(elm_offset, elm_offset + L); - e[j] = mod(os2ip(tv), htfOptions.p); - } - u[i] = e; - } - return u; -} -function normalizePrivKey(key) { - let int; - if (key instanceof Uint8Array && key.length === 32) int = bytesToNumberBE(key); - else if (typeof key === 'string' && key.length === 64) int = BigInt(`0x${key}`); - else if (typeof key === 'number' && key > 0 && Number.isSafeInteger(key)) int = BigInt(key); - else if (typeof key === 'bigint' && key > 0n) int = key; - else throw new TypeError('Expected valid private key'); - int = mod(int, CURVE.r); - if (!isWithinCurveOrder(int)) throw new Error('Private key must be 0 < key < CURVE.r'); - return int; -} -function assertType(item, type) { - if (!(item instanceof type)) throw new Error('Expected Fp* argument, not number/bigint'); -} -export class PointG1 extends ProjectivePoint { - constructor(x, y, z = Fp.ONE) { - super(x, y, z, Fp); - assertType(x, Fp); - assertType(y, Fp); - assertType(z, Fp); - } - static fromHex(bytes) { - bytes = ensureBytes(bytes); - let point; - if (bytes.length === 48) { - const { P } = CURVE; - const compressedValue = bytesToNumberBE(bytes); - const bflag = mod(compressedValue, POW_2_383) / POW_2_382; - if (bflag === 1n) { - return this.ZERO; - } - const x = new Fp(mod(compressedValue, POW_2_381)); - const right = x.pow(3n).add(new Fp(CURVE.b)); - let y = right.sqrt(); - if (!y) throw new Error('Invalid compressed G1 point'); - const aflag = mod(compressedValue, POW_2_382) / POW_2_381; - if ((y.value * 2n) / P !== aflag) y = y.negate(); - point = new PointG1(x, y); - } else if (bytes.length === 96) { - if ((bytes[0] & (1 << 6)) !== 0) return PointG1.ZERO; - const x = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); - const y = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH)); - point = new PointG1(new Fp(x), new Fp(y)); - } else { - throw new Error('Invalid point G1, expected 48/96 bytes'); - } - point.assertValidity(); - return point; - } - static fromPrivateKey(privateKey) { - return this.BASE.multiplyPrecomputed(normalizePrivKey(privateKey)); - } - toRawBytes(isCompressed = false) { - return hexToBytes(this.toHex(isCompressed)); - } - toHex(isCompressed = false) { - this.assertValidity(); - if (isCompressed) { - const { P } = CURVE; - let hex; - if (this.isZero()) { - hex = POW_2_383 + POW_2_382; - } else { - const [x, y] = this.toAffine(); - const flag = (y.value * 2n) / P; - hex = x.value + flag * POW_2_381 + POW_2_383; - } - return toPaddedHex(hex, PUBLIC_KEY_LENGTH); - } else { - if (this.isZero()) { - return '4'.padEnd(2 * 2 * PUBLIC_KEY_LENGTH, '0'); - } else { - const [x, y] = this.toAffine(); - return toPaddedHex(x.value, PUBLIC_KEY_LENGTH) + toPaddedHex(y.value, PUBLIC_KEY_LENGTH); - } - } - } - assertValidity() { - if (this.isZero()) return this; - // if (!this.isOnCurve()) throw new Error('Invalid G1 point: not on curve Fp'); - // if (!this.isTorsionFree()) throw new Error('Invalid G1 point: must be of prime-order subgroup'); - return this; - } - [Symbol.for('nodejs.util.inspect.custom')]() { - return this.toString(); - } - millerLoop(P) { - return millerLoop(P.pairingPrecomputes(), this.toAffine()); - } - clearCofactor() { - const t = this.mulCurveMinusX(); - return t.add(this); - } - isOnCurve() { - const b = new Fp(CURVE.b); - const { x, y, z } = this; - const left = y.pow(2n).multiply(z).subtract(x.pow(3n)); - const right = b.multiply(z.pow(3n)); - return left.subtract(right).isZero(); - } - sigma() { - const BETA = - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn; - const [x, y] = this.toAffine(); - return new PointG1(x.multiply(BETA), y); - } - phi() { - const cubicRootOfUnityModP = - 0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen; - return new PointG1(this.x.multiply(cubicRootOfUnityModP), this.y, this.z); - } - mulCurveX() { - return this.multiplyUnsafe(CURVE.x).negate(); - } - mulCurveMinusX() { - return this.multiplyUnsafe(CURVE.x); - } - isTorsionFree() { - const xP = this.mulCurveX(); - const u2P = xP.mulCurveMinusX(); - return u2P.equals(this.phi()); - } -} -PointG1.BASE = new PointG1(new Fp(CURVE.Gx), new Fp(CURVE.Gy), Fp.ONE); -PointG1.ZERO = new PointG1(Fp.ONE, Fp.ONE, Fp.ZERO); -export class PointG2 extends ProjectivePoint { - constructor(x, y, z = Fp2.ONE) { - super(x, y, z, Fp2); - assertType(x, Fp2); - assertType(y, Fp2); - assertType(z, Fp2); - } - static async hashToCurve(msg) { - msg = ensureBytes(msg); - const u = await hash_to_field(msg, 2); - const Q0 = new PointG2(...isogenyMapG2(map_to_curve_simple_swu_9mod16(u[0]))); - const Q1 = new PointG2(...isogenyMapG2(map_to_curve_simple_swu_9mod16(u[1]))); - const R = Q0.add(Q1); - const P = R.clearCofactor(); - return P; - } - static fromSignature(hex) { - hex = ensureBytes(hex); - const { P } = CURVE; - const half = hex.length / 2; - if (half !== 48 && half !== 96) - throw new Error('Invalid compressed signature length, must be 96 or 192'); - const z1 = bytesToNumberBE(hex.slice(0, half)); - const z2 = bytesToNumberBE(hex.slice(half)); - const bflag1 = mod(z1, POW_2_383) / POW_2_382; - if (bflag1 === 1n) return this.ZERO; - const x1 = new Fp(z1 % POW_2_381); - const x2 = new Fp(z2); - const x = new Fp2(x2, x1); - const y2 = x.pow(3n).add(Fp2.fromBigTuple(CURVE.b2)); - let y = y2.sqrt(); - if (!y) throw new Error('Failed to find a square root'); - const { re: y0, im: y1 } = y.reim(); - const aflag1 = (z1 % POW_2_382) / POW_2_381; - const isGreater = y1 > 0n && (y1 * 2n) / P !== aflag1; - const isZero = y1 === 0n && (y0 * 2n) / P !== aflag1; - if (isGreater || isZero) y = y.multiply(-1n); - const point = new PointG2(x, y, Fp2.ONE); - point.assertValidity(); - return point; - } - static fromHex(bytes) { - bytes = ensureBytes(bytes); - const m_byte = bytes[0] & 0xe0; - if (m_byte === 0x20 || m_byte === 0x60 || m_byte === 0xe0) { - throw new Error('Invalid encoding flag: ' + m_byte); - } - const bitC = m_byte & 0x80; - const bitI = m_byte & 0x40; - const bitS = m_byte & 0x20; - let point; - if (bytes.length === 96 && bitC) { - const { P, b2 } = CURVE; - const b = Fp2.fromBigTuple(b2); - bytes[0] = bytes[0] & 0x1f; - if (bitI) { - if (bytes.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('Invalid compressed G2 point'); - } - return PointG2.ZERO; - } - const x_1 = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); - const x_0 = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH)); - const x = new Fp2(new Fp(x_0), new Fp(x_1)); - const right = x.pow(3n).add(b); - let y = right.sqrt(); - if (!y) throw new Error('Invalid compressed G2 point'); - const Y_bit = y.c1.value === 0n ? (y.c0.value * 2n) / P : (y.c1.value * 2n) / P ? 1n : 0n; - y = bitS > 0 && Y_bit > 0 ? y : y.negate(); - return new PointG2(x, y); - } else if (bytes.length === 192 && !bitC) { - if ((bytes[0] & (1 << 6)) !== 0) { - return PointG2.ZERO; - } - const x1 = bytesToNumberBE(bytes.slice(0, PUBLIC_KEY_LENGTH)); - const x0 = bytesToNumberBE(bytes.slice(PUBLIC_KEY_LENGTH, 2 * PUBLIC_KEY_LENGTH)); - const y1 = bytesToNumberBE(bytes.slice(2 * PUBLIC_KEY_LENGTH, 3 * PUBLIC_KEY_LENGTH)); - const y0 = bytesToNumberBE(bytes.slice(3 * PUBLIC_KEY_LENGTH)); - point = new PointG2(Fp2.fromBigTuple([x0, x1]), Fp2.fromBigTuple([y0, y1])); - } else { - throw new Error('Invalid point G2, expected 96/192 bytes'); - } - point.assertValidity(); - return point; - } - static fromPrivateKey(privateKey) { - return this.BASE.multiplyPrecomputed(normalizePrivKey(privateKey)); - } - toSignature() { - if (this.equals(PointG2.ZERO)) { - const sum = POW_2_383 + POW_2_382; - const h = toPaddedHex(sum, PUBLIC_KEY_LENGTH) + toPaddedHex(0n, PUBLIC_KEY_LENGTH); - return hexToBytes(h); - } - const [{ re: x0, im: x1 }, { re: y0, im: y1 }] = this.toAffine().map(a => a.reim()); - const tmp = y1 > 0n ? y1 * 2n : y0 * 2n; - const aflag1 = tmp / CURVE.P; - const z1 = x1 + aflag1 * POW_2_381 + POW_2_383; - const z2 = x0; - return hexToBytes(toPaddedHex(z1, PUBLIC_KEY_LENGTH) + toPaddedHex(z2, PUBLIC_KEY_LENGTH)); - } - toRawBytes(isCompressed = false) { - return hexToBytes(this.toHex(isCompressed)); - } - toHex(isCompressed = false) { - this.assertValidity(); - if (isCompressed) { - const { P } = CURVE; - let x_1 = 0n; - let x_0 = 0n; - if (this.isZero()) { - x_1 = POW_2_383 + POW_2_382; - } else { - const [x, y] = this.toAffine(); - const flag = y.c1.value === 0n ? (y.c0.value * 2n) / P : (y.c1.value * 2n) / P ? 1n : 0n; - x_1 = x.c1.value + flag * POW_2_381 + POW_2_383; - x_0 = x.c0.value; - } - return toPaddedHex(x_1, PUBLIC_KEY_LENGTH) + toPaddedHex(x_0, PUBLIC_KEY_LENGTH); - } else { - if (this.equals(PointG2.ZERO)) { - return '4'.padEnd(2 * 4 * PUBLIC_KEY_LENGTH, '0'); - } - const [{ re: x0, im: x1 }, { re: y0, im: y1 }] = this.toAffine().map(a => a.reim()); - return ( - toPaddedHex(x1, PUBLIC_KEY_LENGTH) + - toPaddedHex(x0, PUBLIC_KEY_LENGTH) + - toPaddedHex(y1, PUBLIC_KEY_LENGTH) + - toPaddedHex(y0, PUBLIC_KEY_LENGTH) - ); - } - } - assertValidity() { - if (this.isZero()) return this; - if (!this.isOnCurve()) throw new Error('Invalid G2 point: not on curve Fp2'); - if (!this.isTorsionFree()) throw new Error('Invalid G2 point: must be of prime-order subgroup'); - return this; - } - psi() { - return this.fromAffineTuple(psi(...this.toAffine())); - } - psi2() { - return this.fromAffineTuple(psi2(...this.toAffine())); - } - mulCurveX() { - return this.multiplyUnsafe(CURVE.x).negate(); - } - clearCofactor() { - const P = this; - let t1 = P.mulCurveX(); - let t2 = P.psi(); - let t3 = P.double(); - t3 = t3.psi2(); - t3 = t3.subtract(t2); - t2 = t1.add(t2); - t2 = t2.mulCurveX(); - t3 = t3.add(t2); - t3 = t3.subtract(t1); - const Q = t3.subtract(P); - return Q; - } - isOnCurve() { - const b = Fp2.fromBigTuple(CURVE.b2); - const { x, y, z } = this; - const left = y.pow(2n).multiply(z).subtract(x.pow(3n)); - const right = b.multiply(z.pow(3n)); - return left.subtract(right).isZero(); - } - isTorsionFree() { - const P = this; - return P.mulCurveX().equals(P.psi()); - } - [Symbol.for('nodejs.util.inspect.custom')]() { - return this.toString(); - } - clearPairingPrecomputes() { - this._PPRECOMPUTES = undefined; - } - pairingPrecomputes() { - if (this._PPRECOMPUTES) return this._PPRECOMPUTES; - this._PPRECOMPUTES = calcPairingPrecomputes(...this.toAffine()); - return this._PPRECOMPUTES; - } -} -PointG2.BASE = new PointG2(Fp2.fromBigTuple(CURVE.G2x), Fp2.fromBigTuple(CURVE.G2y), Fp2.ONE); -PointG2.ZERO = new PointG2(Fp2.ONE, Fp2.ONE, Fp2.ZERO); -export function pairing(P, Q, withFinalExponent = true) { - if (P.isZero() || Q.isZero()) throw new Error('No pairings at point of Infinity'); - P.assertValidity(); - Q.assertValidity(); - const looped = P.millerLoop(Q); - return withFinalExponent ? looped.finalExponentiate() : looped; -} -function normP1(point) { - return point instanceof PointG1 ? point : PointG1.fromHex(point); -} -function normP2(point) { - return point instanceof PointG2 ? point : PointG2.fromSignature(point); -} -async function normP2Hash(point) { - return point instanceof PointG2 ? point : PointG2.hashToCurve(point); -} -export function getPublicKey(privateKey) { - return PointG1.fromPrivateKey(privateKey).toRawBytes(true); -} -export async function sign(message, privateKey) { - const msgPoint = await normP2Hash(message); - msgPoint.assertValidity(); - const sigPoint = msgPoint.multiply(normalizePrivKey(privateKey)); - if (message instanceof PointG2) return sigPoint; - return sigPoint.toSignature(); -} -export async function verify(signature, message, publicKey) { - const P = normP1(publicKey); - const Hm = await normP2Hash(message); - const G = PointG1.BASE; - const S = normP2(signature); - const ePHm = pairing(P.negate(), Hm, false); - const eGS = pairing(G, S, false); - const exp = eGS.multiply(ePHm).finalExponentiate(); - return exp.equals(Fp12.ONE); -} -export function aggregatePublicKeys(publicKeys) { - if (!publicKeys.length) throw new Error('Expected non-empty array'); - const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), PointG1.ZERO); - if (publicKeys[0] instanceof PointG1) return agg.assertValidity(); - return agg.toRawBytes(true); -} -export function aggregateSignatures(signatures) { - if (!signatures.length) throw new Error('Expected non-empty array'); - const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), PointG2.ZERO); - if (signatures[0] instanceof PointG2) return agg.assertValidity(); - return agg.toSignature(); -} -export async function verifyBatch(signature, messages, publicKeys) { - if (!messages.length) throw new Error('Expected non-empty messages array'); - if (publicKeys.length !== messages.length) throw new Error('Pubkey count should equal msg count'); - const sig = normP2(signature); - const nMessages = await Promise.all(messages.map(normP2Hash)); - const nPublicKeys = publicKeys.map(normP1); - try { - const paired = []; - for (const message of new Set(nMessages)) { - const groupPublicKey = nMessages.reduce( - (groupPublicKey, subMessage, i) => - subMessage === message ? groupPublicKey.add(nPublicKeys[i]) : groupPublicKey, - PointG1.ZERO, - ); - paired.push(pairing(groupPublicKey, message, false)); - } - paired.push(pairing(PointG1.BASE.negate(), sig, false)); - const product = paired.reduce((a, b) => a.multiply(b), Fp12.ONE); - const exp = product.finalExponentiate(); - return exp.equals(Fp12.ONE); - } catch { - return false; - } -} -PointG1.BASE.calcMultiplyPrecomputes(4); diff --git a/packages/bls-verify/src/index.test.ts b/packages/bls-verify/src/index.test.ts index e66746823..f394c2fe7 100644 --- a/packages/bls-verify/src/index.test.ts +++ b/packages/bls-verify/src/index.test.ts @@ -3,13 +3,6 @@ import * as Cert from '../../agent/src/certificate'; import * as cbor from '../../agent/src/cbor'; import { fromHex, toHex } from '../../agent/src/utils/buffer'; import { Principal } from '@dfinity/principal'; -function label(str: string): ArrayBuffer { - return new TextEncoder().encode(str); -} - -function pruned(str: string): ArrayBuffer { - return fromHex(str); -} // Root public key for the IC main net, encoded as hex const IC_ROOT_KEY = @@ -20,9 +13,12 @@ const IC_ROOT_KEY = // The sample certificate for testing delegation is extracted from the response used in agent-rs tests, where they were taken // from an interaction with the IC mainnet. -const SAMPLE_CERT: string = +const SAMPLE_CERT = 'd9d9f7a364747265658301830182045820250f5e26868d9c1ea7ab29cbe9c15bf1c47c0d7605e803e39e375a7fe09c6ebb830183024e726571756573745f7374617475738301820458204b268227774ec77ff2b37ecb12157329d54cf376694bdd59ded7803efd82386f83025820edad510eaaa08ed2acd4781324e6446269da6753ec17760f206bbe81c465ff528301830183024b72656a6563745f636f64658203410383024e72656a6563745f6d6573736167658203584443616e69737465722069766733372d71696161612d61616161622d61616167612d63616920686173206e6f20757064617465206d6574686f64202772656769737465722783024673746174757382034872656a65637465648204582097232f31f6ab7ca4fe53eb6568fc3e02bc22fe94ab31d010e5fb3c642301f1608301820458203a48d1fc213d49307103104f7d72c2b5930edba8787b90631f343b3aa68a5f0a83024474696d65820349e2dc939091c696eb16697369676e6174757265583089a2be21b5fa8ac9fab1527e041327ce899d7da971436a1f2165393947b4d942365bfe5488710e61a619ba48388a21b16a64656c65676174696f6ea2697375626e65745f6964581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac4026b6365727469666963617465590231d9d9f7a26474726565830182045820ae023f28c3b9d966c8fb09f9ed755c828aadb5152e00aaf700b18c9c067294b483018302467375626e6574830182045820e83bb025f6574c8f31233dc0fe289ff546dfa1e49bd6116dd6e8896d90a4946e830182045820e782619092d69d5bebf0924138bd4116b0156b5a95e25c358ea8cf7e7161a661830183018204582062513fa926c9a9ef803ac284d620f303189588e1d3904349ab63b6470856fc4883018204582060e9a344ced2c9c4a96a0197fd585f2d259dbd193e4eada56239cac26087f9c58302581dd77b2a2f7199b9a8aec93fe6fb588661358cf12223e9a3af7b4ebac402830183024f63616e69737465725f72616e6765738203581bd9d9f781824a000000000020000001014a00000000002fffff010183024a7075626c69635f6b657982035885308182301d060d2b0601040182dc7c0503010201060c2b0601040182dc7c050302010361009933e1f89e8a3c4d7fdcccdbd518089e2bd4d8180a261f18d9c247a52768ebce98dc7328a39814a8f911086a1dd50cbe015e2a53b7bf78b55288893daa15c346640e8831d72a12bdedd979d28470c34823b8d1c3f4795d9c3984a247132e94fe82045820996f17bb926be3315745dea7282005a793b58e76afeb5d43d1a28ce29d2d158583024474696d6582034995b8aac0e4eda2ea16697369676e61747572655830ace9fcdd9bc977e05d6328f889dc4e7c99114c737a494653cb27a1f55c06f4555e0f160980af5ead098acc195010b2f7'; +beforeEach(() => { + jest.setTimeout(10_000); +}); test('delegation works for canisters within the subnet range', async () => { // The certificate specifies the range from // 0x00000000002000000101 @@ -89,7 +85,7 @@ type FakeCert = { }; test('certificate verification fails for an invalid signature', async () => { - let badCert: FakeCert = cbor.decode(fromHex(SAMPLE_CERT)); + const badCert: FakeCert = cbor.decode(fromHex(SAMPLE_CERT)); badCert.signature = new ArrayBuffer(badCert.signature.byteLength); const badCertEncoded = cbor.encode(badCert); await expect( @@ -101,3 +97,15 @@ test('certificate verification fails for an invalid signature', async () => { }), ).rejects.toThrow('Invalid certificate'); }); + +test('verify', async () => { + const pk = + 'a7623a93cdb56c4d23d99c14216afaab3dfd6d4f9eb3db23d038280b6d5cb2caaee2a19dd92c9df7001d' + + 'ede23bf036bc0f33982dfb41e8fa9b8e96b5dc3e83d55ca4dd146c7eb2e8b6859cb5a5db815db86810b8' + + 'd12cee1588b5dbf34a4dc9a5'; + const sig = + 'b89e13a212c830586eaa9ad53946cd968718ebecc27eda849d9232673dcd4f440e8b5df39bf14a88048c15e16cbcaabe'; + const msg = Buffer.from('hello').toString('hex'); + expect(await blsVerify(pk, sig, msg)).toBe(true); + expect(await blsVerify(pk, sig, Buffer.from('hallo').toString('hex'))).toBe(false); +}, 10000); // Default timer is flaky with WASM. diff --git a/packages/bls-verify/src/index.ts b/packages/bls-verify/src/index.ts index da6120047..e31c0f725 100644 --- a/packages/bls-verify/src/index.ts +++ b/packages/bls-verify/src/index.ts @@ -1,30 +1,24 @@ -import { verify } from './bls'; -import * as cbor from '../../agent/src/cbor'; +import { CTX } from 'amcl-js'; +import { toHex } from './utils'; -type VerifyFunc = (pk: Uint8Array, sig: Uint8Array, msg: Uint8Array) => Promise; - -/** - * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation - * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature - * @param {Uint8Array | string} signature - digital signature - * @param {Uint8Array | string} message - message to verify - * @returns boolean - */ -export const blsVerify: VerifyFunc = async ( - publicKey: Uint8Array | string, +export const blsVerify = async ( + primaryKey: Uint8Array | string, signature: Uint8Array | string, message: Uint8Array | string, ): Promise => { - let result = false; - try { - signature.byteLength; //? - result = await verify(signature, message, publicKey).catch(error => { - console.log(error); - return false; //? - }); //? - } catch (error) { - console.error(error); //? + const pk = typeof primaryKey === 'string' ? primaryKey : toHex(primaryKey); + const sig = typeof signature === 'string' ? signature : toHex(signature); + const msg = typeof message === 'string' ? message : toHex(message); + const ctx = new CTX('BLS12381'); + if (((ctx as any).BLS as any).init() !== 0) { + throw new Error('Cannot initialize BLS'); } - return result; + return ( + ((ctx as any).BLS as any).core_verify( + ((ctx as any).BLS as any).stringtobytes(sig), + ((ctx as any).BLS as any).stringtobytes(msg), + ((ctx as any).BLS as any).stringtobytes(pk), + ) == 0 + ); }; diff --git a/packages/bls-verify/src/math.ts b/packages/bls-verify/src/math.ts deleted file mode 100644 index fc314f06f..000000000 --- a/packages/bls-verify/src/math.ts +++ /dev/null @@ -1,1143 +0,0 @@ -export const CURVE = { - P: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn, - r: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n, - h: 0x396c8c005555e1568c00aaab0000aaabn, - Gx: 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bbn, - Gy: 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1n, - b: 4n, - P2: - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn ** - 2n - - 1n, - h2: 0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5n, - G2x: [ - 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8n, - 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7en, - ], - G2y: [ - 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801n, - 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79ben, - ], - b2: [4n, 4n], - x: 0xd201000000010000n, - h2Eff: - 0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551n, -}; -const BLS_X_LEN = bitLen(CURVE.x); -export function mod(a, b) { - const res = a % b; - return res >= 0n ? res : b + res; -} -export function powMod(num, power, modulo) { - if (modulo <= 0n || power < 0n) throw new Error('Expected power/modulo > 0'); - if (modulo === 1n) return 0n; - let res = 1n; - while (power > 0n) { - if (power & 1n) res = (res * num) % modulo; - num = (num * num) % modulo; - power >>= 1n; - } - return res; -} -function genInvertBatch(cls, nums) { - const tmp = new Array(nums.length); - const lastMultiplied = nums.reduce((acc, num, i) => { - if (num.isZero()) return acc; - tmp[i] = acc; - return acc.multiply(num); - }, cls.ONE); - const inverted = lastMultiplied.invert(); - nums.reduceRight((acc, num, i) => { - if (num.isZero()) return acc; - tmp[i] = acc.multiply(tmp[i]); - return acc.multiply(num); - }, inverted); - return tmp; -} -function bitLen(n) { - let len; - for (len = 0; n > 0n; n >>= 1n, len += 1); - return len; -} -function bitGet(n, pos) { - return (n >> BigInt(pos)) & 1n; -} -function invert(number, modulo = CURVE.P) { - const _0n = 0n; - const _1n = 1n; - if (number === _0n || modulo <= _0n) { - throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`); - } - let a = mod(number, modulo); - let b = modulo; - let x = _0n, - y = _1n, - u = _1n, - v = _0n; - while (a !== _0n) { - const q = b / a; - const r = b % a; - const m = x - u * q; - const n = y - v * q; - (b = a), (a = r), (x = u), (y = v), (u = m), (v = n); - } - const gcd = b; - if (gcd !== _1n) throw new Error('invert: does not exist'); - return mod(x, modulo); -} -export class Fp { - constructor(value) { - this.value = mod(value, Fp.ORDER); - } - isZero() { - return this.value === 0n; - } - equals(rhs) { - return this.value === rhs.value; - } - negate() { - return new Fp(-this.value); - } - invert() { - return new Fp(invert(this.value, Fp.ORDER)); - } - add(rhs) { - return new Fp(this.value + rhs.value); - } - square() { - return new Fp(this.value * this.value); - } - pow(n) { - return new Fp(powMod(this.value, n, Fp.ORDER)); - } - sqrt() { - const root = this.pow((Fp.ORDER + 1n) / 4n); - if (!root.square().equals(this)) return; - return root; - } - subtract(rhs) { - return new Fp(this.value - rhs.value); - } - multiply(rhs) { - if (rhs instanceof Fp) rhs = rhs.value; - return new Fp(this.value * rhs); - } - div(rhs) { - if (typeof rhs === 'bigint') rhs = new Fp(rhs); - return this.multiply(rhs.invert()); - } - toString() { - const str = this.value.toString(16).padStart(96, '0'); - return str.slice(0, 2) + '.' + str.slice(-2); - } -} -Fp.ORDER = CURVE.P; -Fp.MAX_BITS = bitLen(CURVE.P); -Fp.ZERO = new Fp(0n); -Fp.ONE = new Fp(1n); -export class Fr { - constructor(value) { - this.value = mod(value, Fr.ORDER); - } - static isValid(b) { - return b <= Fr.ORDER; - } - isZero() { - return this.value === 0n; - } - equals(rhs) { - return this.value === rhs.value; - } - negate() { - return new Fr(-this.value); - } - invert() { - return new Fr(invert(this.value, Fr.ORDER)); - } - add(rhs) { - return new Fr(this.value + rhs.value); - } - square() { - return new Fr(this.value * this.value); - } - pow(n) { - return new Fr(powMod(this.value, n, Fr.ORDER)); - } - subtract(rhs) { - return new Fr(this.value - rhs.value); - } - multiply(rhs) { - if (rhs instanceof Fr) rhs = rhs.value; - return new Fr(this.value * rhs); - } - div(rhs) { - if (typeof rhs === 'bigint') rhs = new Fr(rhs); - return this.multiply(rhs.invert()); - } - legendre() { - return this.pow((Fr.ORDER - 1n) / 2n); - } - sqrt() { - if (!this.legendre().equals(Fr.ONE)) return; - const P = Fr.ORDER; - let q, s, z; - for (q = P - 1n, s = 0; q % 2n === 0n; q /= 2n, s++); - if (s === 1) return this.pow((P + 1n) / 4n); - for (z = 2n; z < P && new Fr(z).legendre().value !== P - 1n; z++); - let c = powMod(z, q, P); - let r = powMod(this.value, (q + 1n) / 2n, P); - let t = powMod(this.value, q, P); - let t2 = 0n; - while (mod(t - 1n, P) !== 0n) { - t2 = mod(t * t, P); - let i; - for (i = 1; i < s; i++) { - if (mod(t2 - 1n, P) === 0n) break; - t2 = mod(t2 * t2, P); - } - let b = powMod(c, BigInt(1 << (s - i - 1)), P); - r = mod(r * b, P); - c = mod(b * b, P); - t = mod(t * c, P); - s = i; - } - return new Fr(r); - } - toString() { - return '0x' + this.value.toString(16).padStart(64, '0'); - } -} -Fr.ORDER = CURVE.r; -Fr.ZERO = new Fr(0n); -Fr.ONE = new Fr(1n); -function powMod_FQP(fqp, fqpOne, n) { - const elm = fqp; - if (n === 0n) return fqpOne; - if (n === 1n) return elm; - let p = fqpOne; - let d = elm; - while (n > 0n) { - if (n & 1n) p = p.multiply(d); - n >>= 1n; - d = d.square(); - } - return p; -} -export class Fp2 { - constructor(c0, c1) { - this.c0 = c0; - this.c1 = c1; - if (typeof c0 === 'bigint') throw new Error('c0: Expected Fp'); - if (typeof c1 === 'bigint') throw new Error('c1: Expected Fp'); - } - static fromBigTuple(tuple) { - const fps = tuple.map(n => new Fp(n)); - return new Fp2(...fps); - } - one() { - return Fp2.ONE; - } - isZero() { - return this.c0.isZero() && this.c1.isZero(); - } - toString() { - return `Fp2(${this.c0} + ${this.c1}×i)`; - } - reim() { - return { re: this.c0.value, im: this.c1.value }; - } - negate() { - const { c0, c1 } = this; - return new Fp2(c0.negate(), c1.negate()); - } - equals(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return c0.equals(r0) && c1.equals(r1); - } - add(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return new Fp2(c0.add(r0), c1.add(r1)); - } - subtract(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return new Fp2(c0.subtract(r0), c1.subtract(r1)); - } - multiply(rhs) { - const { c0, c1 } = this; - if (typeof rhs === 'bigint') { - return new Fp2(c0.multiply(rhs), c1.multiply(rhs)); - } - const { c0: r0, c1: r1 } = rhs; - let t1 = c0.multiply(r0); - let t2 = c1.multiply(r1); - return new Fp2(t1.subtract(t2), c0.add(c1).multiply(r0.add(r1)).subtract(t1.add(t2))); - } - pow(n) { - return powMod_FQP(this, Fp2.ONE, n); - } - div(rhs) { - const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); - return this.multiply(inv); - } - mulByNonresidue() { - const c0 = this.c0; - const c1 = this.c1; - return new Fp2(c0.subtract(c1), c0.add(c1)); - } - square() { - const c0 = this.c0; - const c1 = this.c1; - const a = c0.add(c1); - const b = c0.subtract(c1); - const c = c0.add(c0); - return new Fp2(a.multiply(b), c.multiply(c1)); - } - sqrt() { - const candidateSqrt = this.pow((Fp2.ORDER + 8n) / 16n); - const check = candidateSqrt.square().div(this); - const R = FP2_ROOTS_OF_UNITY; - const divisor = [R[0], R[2], R[4], R[6]].find(r => r.equals(check)); - if (!divisor) return; - const index = R.indexOf(divisor); - const root = R[index / 2]; - if (!root) throw new Error('Invalid root'); - const x1 = candidateSqrt.div(root); - const x2 = x1.negate(); - const { re: re1, im: im1 } = x1.reim(); - const { re: re2, im: im2 } = x2.reim(); - if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1; - return x2; - } - invert() { - const { re: a, im: b } = this.reim(); - const factor = new Fp(a * a + b * b).invert(); - return new Fp2(factor.multiply(new Fp(a)), factor.multiply(new Fp(-b))); - } - frobeniusMap(power) { - return new Fp2(this.c0, this.c1.multiply(FP2_FROBENIUS_COEFFICIENTS[power % 2])); - } - multiplyByB() { - let c0 = this.c0; - let c1 = this.c1; - let t0 = c0.multiply(4n); - let t1 = c1.multiply(4n); - return new Fp2(t0.subtract(t1), t0.add(t1)); - } -} -Fp2.ORDER = CURVE.P2; -Fp2.MAX_BITS = bitLen(CURVE.P2); -Fp2.ZERO = new Fp2(Fp.ZERO, Fp.ZERO); -Fp2.ONE = new Fp2(Fp.ONE, Fp.ZERO); -export class Fp6 { - constructor(c0, c1, c2) { - this.c0 = c0; - this.c1 = c1; - this.c2 = c2; - } - static fromBigSix(t) { - if (!Array.isArray(t) || t.length !== 6) throw new Error('Invalid Fp6 usage'); - const c = [t.slice(0, 2), t.slice(2, 4), t.slice(4, 6)].map(t => Fp2.fromBigTuple(t)); - return new Fp6(...c); - } - fromTriple(triple) { - return new Fp6(...triple); - } - one() { - return Fp6.ONE; - } - isZero() { - return this.c0.isZero() && this.c1.isZero() && this.c2.isZero(); - } - negate() { - const { c0, c1, c2 } = this; - return new Fp6(c0.negate(), c1.negate(), c2.negate()); - } - toString() { - return `Fp6(${this.c0} + ${this.c1} * v, ${this.c2} * v^2)`; - } - equals(rhs) { - const { c0, c1, c2 } = this; - const { c0: r0, c1: r1, c2: r2 } = rhs; - return c0.equals(r0) && c1.equals(r1) && c2.equals(r2); - } - add(rhs) { - const { c0, c1, c2 } = this; - const { c0: r0, c1: r1, c2: r2 } = rhs; - return new Fp6(c0.add(r0), c1.add(r1), c2.add(r2)); - } - subtract(rhs) { - const { c0, c1, c2 } = this; - const { c0: r0, c1: r1, c2: r2 } = rhs; - return new Fp6(c0.subtract(r0), c1.subtract(r1), c2.subtract(r2)); - } - multiply(rhs) { - if (typeof rhs === 'bigint') { - return new Fp6(this.c0.multiply(rhs), this.c1.multiply(rhs), this.c2.multiply(rhs)); - } - let { c0, c1, c2 } = this; - let { c0: r0, c1: r1, c2: r2 } = rhs; - let t0 = c0.multiply(r0); - let t1 = c1.multiply(r1); - let t2 = c2.multiply(r2); - return new Fp6( - t0.add(c1.add(c2).multiply(r1.add(r2)).subtract(t1.add(t2)).mulByNonresidue()), - c0.add(c1).multiply(r0.add(r1)).subtract(t0.add(t1)).add(t2.mulByNonresidue()), - t1.add(c0.add(c2).multiply(r0.add(r2)).subtract(t0.add(t2))), - ); - } - pow(n) { - return powMod_FQP(this, Fp6.ONE, n); - } - div(rhs) { - const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); - return this.multiply(inv); - } - mulByNonresidue() { - return new Fp6(this.c2.mulByNonresidue(), this.c0, this.c1); - } - multiplyBy1(b1) { - return new Fp6( - this.c2.multiply(b1).mulByNonresidue(), - this.c0.multiply(b1), - this.c1.multiply(b1), - ); - } - multiplyBy01(b0, b1) { - let { c0, c1, c2 } = this; - let t0 = c0.multiply(b0); - let t1 = c1.multiply(b1); - return new Fp6( - c1.add(c2).multiply(b1).subtract(t1).mulByNonresidue().add(t0), - b0.add(b1).multiply(c0.add(c1)).subtract(t0).subtract(t1), - c0.add(c2).multiply(b0).subtract(t0).add(t1), - ); - } - multiplyByFp2(rhs) { - let { c0, c1, c2 } = this; - return new Fp6(c0.multiply(rhs), c1.multiply(rhs), c2.multiply(rhs)); - } - square() { - let { c0, c1, c2 } = this; - let t0 = c0.square(); - let t1 = c0.multiply(c1).multiply(2n); - let t3 = c1.multiply(c2).multiply(2n); - let t4 = c2.square(); - return new Fp6( - t3.mulByNonresidue().add(t0), - t4.mulByNonresidue().add(t1), - t1.add(c0.subtract(c1).add(c2).square()).add(t3).subtract(t0).subtract(t4), - ); - } - invert() { - let { c0, c1, c2 } = this; - let t0 = c0.square().subtract(c2.multiply(c1).mulByNonresidue()); - let t1 = c2.square().mulByNonresidue().subtract(c0.multiply(c1)); - let t2 = c1.square().subtract(c0.multiply(c2)); - let t4 = c2.multiply(t1).add(c1.multiply(t2)).mulByNonresidue().add(c0.multiply(t0)).invert(); - return new Fp6(t4.multiply(t0), t4.multiply(t1), t4.multiply(t2)); - } - frobeniusMap(power) { - return new Fp6( - this.c0.frobeniusMap(power), - this.c1.frobeniusMap(power).multiply(FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), - this.c2.frobeniusMap(power).multiply(FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), - ); - } -} -Fp6.ZERO = new Fp6(Fp2.ZERO, Fp2.ZERO, Fp2.ZERO); -Fp6.ONE = new Fp6(Fp2.ONE, Fp2.ZERO, Fp2.ZERO); -export class Fp12 { - constructor(c0, c1) { - this.c0 = c0; - this.c1 = c1; - } - static fromBigTwelve(t) { - return new Fp12(Fp6.fromBigSix(t.slice(0, 6)), Fp6.fromBigSix(t.slice(6, 12))); - } - fromTuple(c) { - return new Fp12(...c); - } - one() { - return Fp12.ONE; - } - isZero() { - return this.c0.isZero() && this.c1.isZero(); - } - toString() { - return `Fp12(${this.c0} + ${this.c1} * w)`; - } - negate() { - const { c0, c1 } = this; - return new Fp12(c0.negate(), c1.negate()); - } - equals(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return c0.equals(r0) && c1.equals(r1); - } - add(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return new Fp12(c0.add(r0), c1.add(r1)); - } - subtract(rhs) { - const { c0, c1 } = this; - const { c0: r0, c1: r1 } = rhs; - return new Fp12(c0.subtract(r0), c1.subtract(r1)); - } - multiply(rhs) { - if (typeof rhs === 'bigint') return new Fp12(this.c0.multiply(rhs), this.c1.multiply(rhs)); - let { c0, c1 } = this; - let { c0: r0, c1: r1 } = rhs; - let t1 = c0.multiply(r0); - let t2 = c1.multiply(r1); - return new Fp12( - t1.add(t2.mulByNonresidue()), - c0.add(c1).multiply(r0.add(r1)).subtract(t1.add(t2)), - ); - } - pow(n) { - return powMod_FQP(this, Fp12.ONE, n); - } - div(rhs) { - const inv = typeof rhs === 'bigint' ? new Fp(rhs).invert().value : rhs.invert(); - return this.multiply(inv); - } - multiplyBy014(o0, o1, o4) { - let { c0, c1 } = this; - let t0 = c0.multiplyBy01(o0, o1); - let t1 = c1.multiplyBy1(o4); - return new Fp12( - t1.mulByNonresidue().add(t0), - c1.add(c0).multiplyBy01(o0, o1.add(o4)).subtract(t0).subtract(t1), - ); - } - multiplyByFp2(rhs) { - return new Fp12(this.c0.multiplyByFp2(rhs), this.c1.multiplyByFp2(rhs)); - } - square() { - let { c0, c1 } = this; - let ab = c0.multiply(c1); - return new Fp12( - c1.mulByNonresidue().add(c0).multiply(c0.add(c1)).subtract(ab).subtract(ab.mulByNonresidue()), - ab.add(ab), - ); - } - invert() { - let { c0, c1 } = this; - let t = c0.square().subtract(c1.square().mulByNonresidue()).invert(); - return new Fp12(c0.multiply(t), c1.multiply(t).negate()); - } - conjugate() { - return new Fp12(this.c0, this.c1.negate()); - } - frobeniusMap(power) { - const r0 = this.c0.frobeniusMap(power); - const { c0, c1, c2 } = this.c1.frobeniusMap(power); - const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12]; - return new Fp12(r0, new Fp6(c0.multiply(coeff), c1.multiply(coeff), c2.multiply(coeff))); - } - Fp4Square(a, b) { - const a2 = a.square(); - const b2 = b.square(); - return { - first: b2.mulByNonresidue().add(a2), - second: a.add(b).square().subtract(a2).subtract(b2), - }; - } - cyclotomicSquare() { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = this.c0; - const { c0: c1c0, c1: c1c1, c2: c1c2 } = this.c1; - const { first: t3, second: t4 } = this.Fp4Square(c0c0, c1c1); - const { first: t5, second: t6 } = this.Fp4Square(c1c0, c0c2); - const { first: t7, second: t8 } = this.Fp4Square(c0c1, c1c2); - let t9 = t8.mulByNonresidue(); - return new Fp12( - new Fp6( - t3.subtract(c0c0).multiply(2n).add(t3), - t5.subtract(c0c1).multiply(2n).add(t5), - t7.subtract(c0c2).multiply(2n).add(t7), - ), - new Fp6( - t9.add(c1c0).multiply(2n).add(t9), - t4.add(c1c1).multiply(2n).add(t4), - t6.add(c1c2).multiply(2n).add(t6), - ), - ); - } - cyclotomicExp(n) { - let z = Fp12.ONE; - for (let i = BLS_X_LEN - 1; i >= 0; i--) { - z = z.cyclotomicSquare(); - if (bitGet(n, i)) z = z.multiply(this); - } - return z; - } - finalExponentiate() { - const { x } = CURVE; - const t0 = this.frobeniusMap(6).div(this); - const t1 = t0.frobeniusMap(2).multiply(t0); - const t2 = t1.cyclotomicExp(x).conjugate(); - const t3 = t1.cyclotomicSquare().conjugate().multiply(t2); - const t4 = t3.cyclotomicExp(x).conjugate(); - const t5 = t4.cyclotomicExp(x).conjugate(); - const t6 = t5.cyclotomicExp(x).conjugate().multiply(t2.cyclotomicSquare()); - const t7 = t6.cyclotomicExp(x).conjugate(); - const t2_t5_pow_q2 = t2.multiply(t5).frobeniusMap(2); - const t4_t1_pow_q3 = t4.multiply(t1).frobeniusMap(3); - const t6_t1c_pow_q1 = t6.multiply(t1.conjugate()).frobeniusMap(1); - const t7_t3c_t1 = t7.multiply(t3.conjugate()).multiply(t1); - return t2_t5_pow_q2.multiply(t4_t1_pow_q3).multiply(t6_t1c_pow_q1).multiply(t7_t3c_t1); - } -} -Fp12.ZERO = new Fp12(Fp6.ZERO, Fp6.ZERO); -Fp12.ONE = new Fp12(Fp6.ONE, Fp6.ZERO); -export class ProjectivePoint { - constructor(x, y, z, C) { - this.x = x; - this.y = y; - this.z = z; - this.C = C; - } - isZero() { - return this.z.isZero(); - } - createPoint(x, y, z) { - return new this.constructor(x, y, z); - } - getZero() { - return this.createPoint(this.C.ONE, this.C.ONE, this.C.ZERO); - } - equals(rhs) { - if (this.constructor !== rhs.constructor) - throw new Error( - `ProjectivePoint#equals: this is ${this.constructor}, but rhs is ${rhs.constructor}`, - ); - const a = this; - const b = rhs; - const xe = a.x.multiply(b.z).equals(b.x.multiply(a.z)); - const ye = a.y.multiply(b.z).equals(b.y.multiply(a.z)); - return xe && ye; - } - negate() { - return this.createPoint(this.x, this.y.negate(), this.z); - } - toString(isAffine = true) { - if (this.isZero()) { - return `Point`; - } - if (!isAffine) { - return `Point`; - } - const [x, y] = this.toAffine(); - return `Point`; - } - fromAffineTuple(xy) { - return this.createPoint(xy[0], xy[1], this.C.ONE); - } - toAffine(invZ = this.z.invert()) { - if (invZ.isZero()) throw new Error('Invalid inverted z'); - return [this.x.multiply(invZ), this.y.multiply(invZ)]; - } - toAffineBatch(points) { - const toInv = genInvertBatch( - this.C, - points.map(p => p.z), - ); - return points.map((p, i) => p.toAffine(toInv[i])); - } - normalizeZ(points) { - return this.toAffineBatch(points).map(t => this.fromAffineTuple(t)); - } - double() { - const { x, y, z } = this; - const W = x.multiply(x).multiply(3n); - const S = y.multiply(z); - const SS = S.multiply(S); - const SSS = SS.multiply(S); - const B = x.multiply(y).multiply(S); - const H = W.multiply(W).subtract(B.multiply(8n)); - const X3 = H.multiply(S).multiply(2n); - const Y3 = W.multiply(B.multiply(4n).subtract(H)).subtract( - y.multiply(y).multiply(8n).multiply(SS), - ); - const Z3 = SSS.multiply(8n); - return this.createPoint(X3, Y3, Z3); - } - add(rhs) { - if (this.constructor !== rhs.constructor) - throw new Error( - `ProjectivePoint#add: this is ${this.constructor}, but rhs is ${rhs.constructor}`, - ); - const p1 = this; - const p2 = rhs; - if (p1.isZero()) return p2; - if (p2.isZero()) return p1; - const X1 = p1.x; - const Y1 = p1.y; - const Z1 = p1.z; - const X2 = p2.x; - const Y2 = p2.y; - const Z2 = p2.z; - const U1 = Y2.multiply(Z1); - const U2 = Y1.multiply(Z2); - const V1 = X2.multiply(Z1); - const V2 = X1.multiply(Z2); - if (V1.equals(V2) && U1.equals(U2)) return this.double(); - if (V1.equals(V2)) return this.getZero(); - const U = U1.subtract(U2); - const V = V1.subtract(V2); - const VV = V.multiply(V); - const VVV = VV.multiply(V); - const V2VV = V2.multiply(VV); - const W = Z1.multiply(Z2); - const A = U.multiply(U).multiply(W).subtract(VVV).subtract(V2VV.multiply(2n)); - const X3 = V.multiply(A); - const Y3 = U.multiply(V2VV.subtract(A)).subtract(VVV.multiply(U2)); - const Z3 = VVV.multiply(W); - return this.createPoint(X3, Y3, Z3); - } - subtract(rhs) { - if (this.constructor !== rhs.constructor) - throw new Error( - `ProjectivePoint#subtract: this is ${this.constructor}, but rhs is ${rhs.constructor}`, - ); - return this.add(rhs.negate()); - } - validateScalar(n) { - if (typeof n === 'number') n = BigInt(n); - if (typeof n !== 'bigint' || n <= 0 || n > CURVE.r) { - throw new Error( - `Point#multiply: invalid scalar, expected positive integer < CURVE.r. Got: ${n}`, - ); - } - return n; - } - multiplyUnsafe(scalar) { - let n = this.validateScalar(scalar); - let point = this.getZero(); - let d = this; - while (n > 0n) { - if (n & 1n) point = point.add(d); - d = d.double(); - n >>= 1n; - } - return point; - } - multiply(scalar) { - let n = this.validateScalar(scalar); - let point = this.getZero(); - let fake = this.getZero(); - let d = this; - let bits = Fp.ORDER; - while (bits > 0n) { - if (n & 1n) { - point = point.add(d); - } else { - fake = fake.add(d); - } - d = d.double(); - n >>= 1n; - bits >>= 1n; - } - return point; - } - maxBits() { - return this.C.MAX_BITS; - } - precomputeWindow(W) { - const windows = Math.ceil(this.maxBits() / W); - const windowSize = 2 ** (W - 1); - let points = []; - let p = this; - let base = p; - for (let window = 0; window < windows; window++) { - base = p; - points.push(base); - for (let i = 1; i < windowSize; i++) { - base = base.add(p); - points.push(base); - } - p = base.double(); - } - return points; - } - calcMultiplyPrecomputes(W) { - if (this._MPRECOMPUTES) throw new Error('This point already has precomputes'); - this._MPRECOMPUTES = [W, this.normalizeZ(this.precomputeWindow(W))]; - } - clearMultiplyPrecomputes() { - this._MPRECOMPUTES = undefined; - } - wNAF(n) { - let W, precomputes; - if (this._MPRECOMPUTES) { - [W, precomputes] = this._MPRECOMPUTES; - } else { - W = 1; - precomputes = this.precomputeWindow(W); - } - let p = this.getZero(); - let f = this.getZero(); - const windows = Math.ceil(this.maxBits() / W); - const windowSize = 2 ** (W - 1); - const mask = BigInt(2 ** W - 1); - const maxNumber = 2 ** W; - const shiftBy = BigInt(W); - for (let window = 0; window < windows; window++) { - const offset = window * windowSize; - let wbits = Number(n & mask); - n >>= shiftBy; - if (wbits > windowSize) { - wbits -= maxNumber; - n += 1n; - } - if (wbits === 0) { - f = f.add(window % 2 ? precomputes[offset].negate() : precomputes[offset]); - } else { - const cached = precomputes[offset + Math.abs(wbits) - 1]; - p = p.add(wbits < 0 ? cached.negate() : cached); - } - } - return [p, f]; - } - multiplyPrecomputed(scalar) { - return this.wNAF(this.validateScalar(scalar))[0]; - } -} -function sgn0(x) { - const { re: x0, im: x1 } = x.reim(); - const sign_0 = x0 % 2n; - const zero_0 = x0 === 0n; - const sign_1 = x1 % 2n; - return BigInt(sign_0 || (zero_0 && sign_1)); -} -const P_MINUS_9_DIV_16 = (CURVE.P ** 2n - 9n) / 16n; -function sqrt_div_fp2(u, v) { - const v7 = v.pow(7n); - const uv7 = u.multiply(v7); - const uv15 = uv7.multiply(v7.multiply(v)); - const gamma = uv15.pow(P_MINUS_9_DIV_16).multiply(uv7); - let success = false; - let result = gamma; - const positiveRootsOfUnity = FP2_ROOTS_OF_UNITY.slice(0, 4); - positiveRootsOfUnity.forEach(root => { - const candidate = root.multiply(gamma); - if (candidate.pow(2n).multiply(v).subtract(u).isZero() && !success) { - success = true; - result = candidate; - } - }); - return { success, sqrtCandidateOrGamma: result }; -} -export function map_to_curve_simple_swu_9mod16(t) { - const iso_3_a = new Fp2(new Fp(0n), new Fp(240n)); - const iso_3_b = new Fp2(new Fp(1012n), new Fp(1012n)); - const iso_3_z = new Fp2(new Fp(-2n), new Fp(-1n)); - if (Array.isArray(t)) t = Fp2.fromBigTuple(t); - const t2 = t.pow(2n); - const iso_3_z_t2 = iso_3_z.multiply(t2); - const ztzt = iso_3_z_t2.add(iso_3_z_t2.pow(2n)); - let denominator = iso_3_a.multiply(ztzt).negate(); - let numerator = iso_3_b.multiply(ztzt.add(Fp2.ONE)); - if (denominator.isZero()) denominator = iso_3_z.multiply(iso_3_a); - let v = denominator.pow(3n); - let u = numerator - .pow(3n) - .add(iso_3_a.multiply(numerator).multiply(denominator.pow(2n))) - .add(iso_3_b.multiply(v)); - const { success, sqrtCandidateOrGamma } = sqrt_div_fp2(u, v); - let y; - if (success) y = sqrtCandidateOrGamma; - const sqrtCandidateX1 = sqrtCandidateOrGamma.multiply(t.pow(3n)); - u = iso_3_z_t2.pow(3n).multiply(u); - let success2 = false; - FP2_ETAs.forEach(eta => { - const etaSqrtCandidate = eta.multiply(sqrtCandidateX1); - const temp = etaSqrtCandidate.pow(2n).multiply(v).subtract(u); - if (temp.isZero() && !success && !success2) { - y = etaSqrtCandidate; - success2 = true; - } - }); - if (!success && !success2) throw new Error('Hash to Curve - Optimized SWU failure'); - if (success2) numerator = numerator.multiply(iso_3_z_t2); - y = y; - if (sgn0(t) !== sgn0(y)) y = y.negate(); - y = y.multiply(denominator); - return [numerator, y, denominator]; -} -export function isogenyMapG2(xyz) { - const x = xyz[0], - y = xyz[1], - z = xyz[2]; - const zz = z.multiply(z); - const zzz = zz.multiply(z); - const zPowers = [z, zz, zzz]; - const mapped = [Fp2.ZERO, Fp2.ZERO, Fp2.ZERO, Fp2.ZERO]; - for (let i = 0; i < ISOGENY_COEFFICIENTS.length; i++) { - const k_i = ISOGENY_COEFFICIENTS[i]; - mapped[i] = k_i.slice(-1)[0]; - const arr = k_i.slice(0, -1).reverse(); - for (let j = 0; j < arr.length; j++) { - const k_i_j = arr[j]; - mapped[i] = mapped[i].multiply(x).add(zPowers[j].multiply(k_i_j)); - } - } - mapped[2] = mapped[2].multiply(y); - mapped[3] = mapped[3].multiply(z); - const z2 = mapped[1].multiply(mapped[3]); - const x2 = mapped[0].multiply(mapped[3]); - const y2 = mapped[1].multiply(mapped[2]); - return [x2, y2, z2]; -} -export function calcPairingPrecomputes(x, y) { - const Qx = x, - Qy = y, - Qz = Fp2.ONE; - let Rx = Qx, - Ry = Qy, - Rz = Qz; - let ell_coeff = []; - for (let i = BLS_X_LEN - 2; i >= 0; i--) { - let t0 = Ry.square(); - let t1 = Rz.square(); - let t2 = t1.multiply(3n).multiplyByB(); - let t3 = t2.multiply(3n); - let t4 = Ry.add(Rz).square().subtract(t1).subtract(t0); - ell_coeff.push([t2.subtract(t0), Rx.square().multiply(3n), t4.negate()]); - Rx = t0.subtract(t3).multiply(Rx).multiply(Ry).div(2n); - Ry = t0.add(t3).div(2n).square().subtract(t2.square().multiply(3n)); - Rz = t0.multiply(t4); - if (bitGet(CURVE.x, i)) { - let t0 = Ry.subtract(Qy.multiply(Rz)); - let t1 = Rx.subtract(Qx.multiply(Rz)); - ell_coeff.push([t0.multiply(Qx).subtract(t1.multiply(Qy)), t0.negate(), t1]); - let t2 = t1.square(); - let t3 = t2.multiply(t1); - let t4 = t2.multiply(Rx); - let t5 = t3.subtract(t4.multiply(2n)).add(t0.square().multiply(Rz)); - Rx = t1.multiply(t5); - Ry = t4.subtract(t5).multiply(t0).subtract(t3.multiply(Ry)); - Rz = Rz.multiply(t3); - } - } - return ell_coeff; -} -export function millerLoop(ell, g1) { - const Px = g1[0].value; - const Py = g1[1].value; - let f12 = Fp12.ONE; - for (let j = 0, i = BLS_X_LEN - 2; i >= 0; i--, j++) { - const E = ell[j]; - f12 = f12.multiplyBy014(E[0], E[1].multiply(Px), E[2].multiply(Py)); - if (bitGet(CURVE.x, i)) { - j += 1; - const F = ell[j]; - f12 = f12.multiplyBy014(F[0], F[1].multiply(Px), F[2].multiply(Py)); - } - if (i !== 0) f12 = f12.square(); - } - return f12.conjugate(); -} -const ut_root = new Fp6(Fp2.ZERO, Fp2.ONE, Fp2.ZERO); -const wsq = new Fp12(ut_root, Fp6.ZERO); -const wcu = new Fp12(Fp6.ZERO, ut_root); -const [wsq_inv, wcu_inv] = genInvertBatch(Fp12, [wsq, wcu]); -export function psi(x, y) { - const x2 = wsq_inv.multiplyByFp2(x).frobeniusMap(1).multiply(wsq).c0.c0; - const y2 = wcu_inv.multiplyByFp2(y).frobeniusMap(1).multiply(wcu).c0.c0; - return [x2, y2]; -} -export function psi2(x, y) { - return [x.multiply(PSI2_C1), y.negate()]; -} -const PSI2_C1 = - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn; -const rv1 = - 0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n; -const ev1 = - 0x699be3b8c6870965e5bf892ad5d2cc7b0e85a117402dfd83b7f4a947e02d978498255a2aaec0ac627b5afbdf1bf1c90n; -const ev2 = - 0x8157cd83046453f5dd0972b6e3949e4288020b5b8a9cc99ca07e27089a2ce2436d965026adad3ef7baba37f2183e9b5n; -const ev3 = - 0xab1c2ffdd6c253ca155231eb3e71ba044fd562f6f72bc5bad5ec46a0b7a3b0247cf08ce6c6317f40edbc653a72dee17n; -const ev4 = - 0xaa404866706722864480885d68ad0ccac1967c7544b447873cc37e0181271e006df72162a3d3e0287bf597fbf7f8fc1n; -const FP2_FROBENIUS_COEFFICIENTS = [ - 0x1n, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, -].map(item => new Fp(item)); -const FP2_ROOTS_OF_UNITY = [ - [1n, 0n], - [rv1, -rv1], - [0n, 1n], - [rv1, rv1], - [-1n, 0n], - [-rv1, rv1], - [0n, -1n], - [-rv1, -rv1], -].map(pair => Fp2.fromBigTuple(pair)); -const FP2_ETAs = [ - [ev1, ev2], - [-ev2, ev1], - [ev3, ev4], - [-ev4, ev3], -].map(pair => Fp2.fromBigTuple(pair)); -const FP6_FROBENIUS_COEFFICIENTS_1 = [ - [0x1n, 0x0n], - [ - 0x0n, - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, - ], - [ - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, - 0x0n, - ], - [0x0n, 0x1n], - [ - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, - 0x0n, - ], - [ - 0x0n, - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, - ], -].map(pair => Fp2.fromBigTuple(pair)); -const FP6_FROBENIUS_COEFFICIENTS_2 = [ - [0x1n, 0x0n], - [ - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn, - 0x0n, - ], - [ - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, - 0x0n, - ], - [ - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, - 0x0n, - ], - [ - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, - 0x0n, - ], - [ - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn, - 0x0n, - ], -].map(pair => Fp2.fromBigTuple(pair)); -const FP12_FROBENIUS_COEFFICIENTS = [ - [0x1n, 0x0n], - [ - 0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n, - 0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n, - ], - [ - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffeffffn, - 0x0n, - ], - [ - 0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n, - 0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n, - ], - [ - 0x00000000000000005f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffen, - 0x0n, - ], - [ - 0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n, - 0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n, - ], - [ - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaan, - 0x0n, - ], - [ - 0x00fc3e2b36c4e03288e9e902231f9fb854a14787b6c7b36fec0c8ec971f63c5f282d5ac14d6c7ec22cf78a126ddc4af3n, - 0x1904d3bf02bb0667c231beb4202c0d1f0fd603fd3cbd5f4f7b2443d784bab9c4f67ea53d63e7813d8d0775ed92235fb8n, - ], - [ - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaacn, - 0x0n, - ], - [ - 0x06af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09n, - 0x135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2n, - ], - [ - 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaadn, - 0x0n, - ], - [ - 0x05b2cfd9013a5fd8df47fa6b48b1e045f39816240c0b8fee8beadf4d8e9c0566c63a3e6e257f87329b18fae980078116n, - 0x144e4211384586c16bd3ad4afa99cc9170df3560e77982d0db45f3536814f0bd5871c1908bd478cd1ee605167ff82995n, - ], -].map(n => Fp2.fromBigTuple(n)); -const xnum = [ - [ - 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6n, - 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6n, - ], - [ - 0x0n, - 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71an, - ], - [ - 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71en, - 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38dn, - ], - [ - 0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1n, - 0x0n, - ], -].map(pair => Fp2.fromBigTuple(pair)); -const xden = [ - [ - 0x0n, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63n, - ], - [ - 0xcn, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9fn, - ], - [0x1n, 0x0n], - [0x0n, 0x0n], -].map(pair => Fp2.fromBigTuple(pair)); -const ynum = [ - [ - 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706n, - 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706n, - ], - [ - 0x0n, - 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97ben, - ], - [ - 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71cn, - 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38fn, - ], - [ - 0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10n, - 0x0n, - ], -].map(pair => Fp2.fromBigTuple(pair)); -const yden = [ - [ - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fbn, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fbn, - ], - [ - 0x0n, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3n, - ], - [ - 0x12n, - 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99n, - ], - [0x1n, 0x0n], -].map(pair => Fp2.fromBigTuple(pair)); -const ISOGENY_COEFFICIENTS = [xnum, xden, ynum, yden]; diff --git a/packages/bls-verify/src/utils.ts b/packages/bls-verify/src/utils.ts new file mode 100644 index 000000000..83faceaae --- /dev/null +++ b/packages/bls-verify/src/utils.ts @@ -0,0 +1,28 @@ +/** + * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. + * @param buffer The buffer to return the hexadecimal string of. + */ +export function toHex(buffer: ArrayBuffer): string { + return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); +} + +const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); + +/** + * Transforms a hexadecimal string into an array buffer. + * @param hex The hexadecimal string to use. + */ +export function fromHex(hex: string): ArrayBuffer { + if (!hexRe.test(hex)) { + throw new Error('Invalid hexadecimal string.'); + } + const buffer = [...hex] + .reduce((acc, curr, i) => { + // tslint:disable-next-line:no-bitwise + acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; + return acc; + }, [] as string[]) + .map(x => Number.parseInt(x, 16)); + + return new Uint8Array(buffer).buffer; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/index.js b/packages/bls-verify/src/vendor/amcl-js/index.js new file mode 100644 index 000000000..b8e38afff --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/index.js @@ -0,0 +1 @@ +module.exports.CTX = require('./src/ctx'); diff --git a/packages/bls-verify/src/vendor/amcl-js/package.json b/packages/bls-verify/src/vendor/amcl-js/package.json new file mode 100644 index 000000000..43addfb1e --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/package.json @@ -0,0 +1,15 @@ +{ + "name": "amcl-js", + "version": "3.0.0", + "description": "AMCL Library", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Michael Scott, Alessandro Budroni, Kealan McCusker, Samuele Andreoli", + "license": "Apache License 2.0", + "dependencies": { + "prompt": "^1.0.0" + } +} diff --git a/packages/bls-verify/src/vendor/amcl-js/readme.md b/packages/bls-verify/src/vendor/amcl-js/readme.md new file mode 100644 index 000000000..ce1ac3802 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/readme.md @@ -0,0 +1,62 @@ +# Installation and Testing + +Suppose you want to implement ECDH with NIST256 elliptic curve. First you need to initialize the context: + + var ctx = new CTX("NIST256"); + +then you can call the functions as follows: + + ctx.ECDH.KEY_PAIR_GENERATE(...); + ctx.ECDH.ECPSVDP_DH(...); + +If you need to use more than one elliptic curve in the same program you only need to initialize two different contexts, for example + + var ctx1 = new CTX("NIST256"); + var ctx2 = new CTX("C25519"); + +The following is the list of all elliptic curves supported by MIRACL Core JS + + ['ED25519', 'C25519', 'C41417', 'GOLDILOCKS', 'X448', 'NIST256', 'SECP160R1', 'C1174', 'C1665', 'MDC', 'NIST384','NIST521', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'JUBJUB', 'NUMS256W', 'SECP256K1','NUMS256E', 'NUMS384W', 'NUMS384E', 'NUMS512W', 'NUMS512E', 'TWEEDLEDUM', 'TWEEDLEDEE', 'BN254', 'BN254CX', 'BLS12383', 'BLS12381', 'FP256BN', 'FP512BN', 'BLS12461', 'BN462', 'BLS24479', 'BLS48556', 'BLS48581', 'BLS48286']; + +This library supports also RSA encryption/decryption and RSA signature. The following is a quick example on how to use RSA. First initialize the context + + var ctx = new CTX("RSA2048"); + +then you can call the RSA functions as follows: + + ctx.RSA.ENCRYPT(...); + ctx.RSA.DECRYPT(...); + +The following is the list of all the RSA security level supported by _MIRACL Core JS_ + + ['RSA2048','RSA3072','RSA4096']; + +MIRACL Core JS supports also SHA256, SHA384, SHA512, SHA3, AES-GCM encryption and a secure random number generator. Those functions are contained in every context initialized with RSA or with an elliptic curve. +If you want to create a context supporting only those general functions then initialize it with no parameter as follows: + + var ctx = new CTX(); + +To use this library in Node.js import it as follows: + +```javascript +var CTX = require('./index.js'); +``` + +It is also possible to use it as a npm package. Install it locally into your project with: + + npm install --save + +As an example in React it is possible to install the library with npm and import it with + +```javascript +const ctx = require('amcl-js').CTX; +``` + +After the import the library is used as described above. + +--- + +To see some running examples, load TestECC.html or TestMPIN.html or TestHPKE.html or TestHTP.html or TestBLS.html or TestNHS.html or BenchtestALL.html into your favourite browser. +You might have to wait a few seconds for the benchmarking scripts to complete. + +For TestMPIN.html the correct PIN number is 1234. diff --git a/packages/bls-verify/src/vendor/amcl-js/src/aes.js b/packages/bls-verify/src/vendor/amcl-js/src/aes.js new file mode 100644 index 000000000..0ce8d189a --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/aes.js @@ -0,0 +1,882 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var AES = function () { + 'use strict'; + + var AES = function () { + this.Nk = 0; + this.Nr = 0; + this.mode = 0; + this.fkey = []; + this.rkey = []; + this.f = []; + }; + + // AES constants + AES.ECB = 0; + AES.CBC = 1; + AES.CFB1 = 2; + AES.CFB2 = 3; + AES.CFB4 = 5; + AES.OFB1 = 14; + AES.OFB2 = 15; + AES.OFB4 = 17; + AES.OFB8 = 21; + AES.OFB16 = 29; + AES.CTR1 = 30; + AES.CTR2 = 31; + AES.CTR4 = 33; + AES.CTR8 = 37; + AES.CTR16 = 45; + + AES.prototype = { + /* reset cipher */ + reset: function (m, iv) { + /* reset mode, or reset iv */ + var i; + + this.mode = m; + + for (i = 0; i < 16; i++) { + this.f[i] = 0; + } + + if (this.mode != AES.ECB && iv !== null) { + for (i = 0; i < 16; i++) { + this.f[i] = iv[i]; + } + } + }, + + getreg: function () { + var ir = [], + i; + + for (i = 0; i < 16; i++) { + ir[i] = this.f[i]; + } + + return ir; + }, + + increment: function () { + var i; + + for (i = 0; i < 16; i++) { + this.f[i]++; + + if ((this.f[i] & 0xff) != 0) { + break; + } + } + }, + + /* Initialise cipher */ + init: function (m, nk, key, iv) { + /* Key=16 bytes */ + /* Key Scheduler. Create expanded encryption key */ + var CipherKey = [], + b = [], + i, + j, + k, + N, + nr; + + nk /= 4; + + if (nk != 4 && nk != 6 && nk != 8) { + return false; + } + + nr = 6 + nk; + + this.Nk = nk; + this.Nr = nr; + + this.reset(m, iv); + N = 4 * (nr + 1); + + for (i = j = 0; i < nk; i++, j += 4) { + for (k = 0; k < 4; k++) { + b[k] = key[j + k]; + } + CipherKey[i] = AES.pack(b); + } + + for (i = 0; i < nk; i++) { + this.fkey[i] = CipherKey[i]; + } + + for (j = nk, k = 0; j < N; j += nk, k++) { + this.fkey[j] = + this.fkey[j - nk] ^ AES.SubByte(AES.ROTL24(this.fkey[j - 1])) ^ (AES.rco[k] & 0xff); + + if (nk <= 6) { + for (i = 1; i < nk && i + j < N; i++) { + this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1]; + } + } else { + for (i = 1; i < 4 && i + j < N; i++) { + this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1]; + } + if (j + 4 < N) { + this.fkey[j + 4] = this.fkey[j + 4 - nk] ^ AES.SubByte(this.fkey[j + 3]); + } + for (i = 5; i < nk && i + j < N; i++) { + this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1]; + } + } + } + + /* now for the expanded decrypt key in reverse order */ + + for (j = 0; j < 4; j++) { + this.rkey[j + N - 4] = this.fkey[j]; + } + + for (i = 4; i < N - 4; i += 4) { + k = N - 4 - i; + for (j = 0; j < 4; j++) { + this.rkey[k + j] = AES.InvMixCol(this.fkey[i + j]); + } + } + + for (j = N - 4; j < N; j++) { + this.rkey[j - N + 4] = this.fkey[j]; + } + }, + + /* Encrypt a single block */ + ecb_encrypt: function (buff) { + var b = [], + p = [], + q = [], + t, + i, + j, + k; + + for (i = j = 0; i < 4; i++, j += 4) { + for (k = 0; k < 4; k++) { + b[k] = buff[j + k]; + } + p[i] = AES.pack(b); + p[i] ^= this.fkey[i]; + } + + k = 4; + + /* State alternates between p and q */ + for (i = 1; i < this.Nr; i++) { + q[0] = + this.fkey[k] ^ + AES.ftable[p[0] & 0xff] ^ + AES.ROTL8(AES.ftable[(p[1] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.ftable[(p[2] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.ftable[(p[3] >>> 24) & 0xff]); + q[1] = + this.fkey[k + 1] ^ + AES.ftable[p[1] & 0xff] ^ + AES.ROTL8(AES.ftable[(p[2] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.ftable[(p[3] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.ftable[(p[0] >>> 24) & 0xff]); + q[2] = + this.fkey[k + 2] ^ + AES.ftable[p[2] & 0xff] ^ + AES.ROTL8(AES.ftable[(p[3] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.ftable[(p[0] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.ftable[(p[1] >>> 24) & 0xff]); + q[3] = + this.fkey[k + 3] ^ + AES.ftable[p[3] & 0xff] ^ + AES.ROTL8(AES.ftable[(p[0] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.ftable[(p[1] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.ftable[(p[2] >>> 24) & 0xff]); + + k += 4; + for (j = 0; j < 4; j++) { + t = p[j]; + p[j] = q[j]; + q[j] = t; + } + } + + /* Last Round */ + + q[0] = + this.fkey[k] ^ + (AES.fbsub[p[0] & 0xff] & 0xff) ^ + AES.ROTL8(AES.fbsub[(p[1] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.fbsub[(p[2] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.fbsub[(p[3] >>> 24) & 0xff] & 0xff); + + q[1] = + this.fkey[k + 1] ^ + (AES.fbsub[p[1] & 0xff] & 0xff) ^ + AES.ROTL8(AES.fbsub[(p[2] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.fbsub[(p[3] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.fbsub[(p[0] >>> 24) & 0xff] & 0xff); + + q[2] = + this.fkey[k + 2] ^ + (AES.fbsub[p[2] & 0xff] & 0xff) ^ + AES.ROTL8(AES.fbsub[(p[3] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.fbsub[(p[0] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.fbsub[(p[1] >>> 24) & 0xff] & 0xff); + + q[3] = + this.fkey[k + 3] ^ + (AES.fbsub[p[3] & 0xff] & 0xff) ^ + AES.ROTL8(AES.fbsub[(p[0] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.fbsub[(p[1] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.fbsub[(p[2] >>> 24) & 0xff] & 0xff); + + for (i = j = 0; i < 4; i++, j += 4) { + b = AES.unpack(q[i]); + for (k = 0; k < 4; k++) { + buff[j + k] = b[k]; + } + } + }, + + /* Decrypt a single block */ + ecb_decrypt: function (buff) { + var b = [], + p = [], + q = [], + t, + i, + j, + k; + + for (i = j = 0; i < 4; i++, j += 4) { + for (k = 0; k < 4; k++) { + b[k] = buff[j + k]; + } + p[i] = AES.pack(b); + p[i] ^= this.rkey[i]; + } + + k = 4; + + /* State alternates between p and q */ + for (i = 1; i < this.Nr; i++) { + q[0] = + this.rkey[k] ^ + AES.rtable[p[0] & 0xff] ^ + AES.ROTL8(AES.rtable[(p[3] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.rtable[(p[2] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.rtable[(p[1] >>> 24) & 0xff]); + q[1] = + this.rkey[k + 1] ^ + AES.rtable[p[1] & 0xff] ^ + AES.ROTL8(AES.rtable[(p[0] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.rtable[(p[3] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.rtable[(p[2] >>> 24) & 0xff]); + q[2] = + this.rkey[k + 2] ^ + AES.rtable[p[2] & 0xff] ^ + AES.ROTL8(AES.rtable[(p[1] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.rtable[(p[0] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.rtable[(p[3] >>> 24) & 0xff]); + q[3] = + this.rkey[k + 3] ^ + AES.rtable[p[3] & 0xff] ^ + AES.ROTL8(AES.rtable[(p[2] >>> 8) & 0xff]) ^ + AES.ROTL16(AES.rtable[(p[1] >>> 16) & 0xff]) ^ + AES.ROTL24(AES.rtable[(p[0] >>> 24) & 0xff]); + + k += 4; + + for (j = 0; j < 4; j++) { + t = p[j]; + p[j] = q[j]; + q[j] = t; + } + } + + /* Last Round */ + + q[0] = + this.rkey[k] ^ + (AES.rbsub[p[0] & 0xff] & 0xff) ^ + AES.ROTL8(AES.rbsub[(p[3] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.rbsub[(p[2] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.rbsub[(p[1] >>> 24) & 0xff] & 0xff); + q[1] = + this.rkey[k + 1] ^ + (AES.rbsub[p[1] & 0xff] & 0xff) ^ + AES.ROTL8(AES.rbsub[(p[0] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.rbsub[(p[3] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.rbsub[(p[2] >>> 24) & 0xff] & 0xff); + q[2] = + this.rkey[k + 2] ^ + (AES.rbsub[p[2] & 0xff] & 0xff) ^ + AES.ROTL8(AES.rbsub[(p[1] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.rbsub[(p[0] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.rbsub[(p[3] >>> 24) & 0xff] & 0xff); + q[3] = + this.rkey[k + 3] ^ + (AES.rbsub[p[3] & 0xff] & 0xff) ^ + AES.ROTL8(AES.rbsub[(p[2] >>> 8) & 0xff] & 0xff) ^ + AES.ROTL16(AES.rbsub[(p[1] >>> 16) & 0xff] & 0xff) ^ + AES.ROTL24(AES.rbsub[(p[0] >>> 24) & 0xff] & 0xff); + + for (i = j = 0; i < 4; i++, j += 4) { + b = AES.unpack(q[i]); + for (k = 0; k < 4; k++) { + buff[j + k] = b[k]; + } + } + }, + + /* Encrypt using selected mode of operation */ + encrypt: function (buff) { + var st = [], + bytes, + fell_off, + j; + + // Supported Modes of Operation + + fell_off = 0; + + switch (this.mode) { + case AES.ECB: + this.ecb_encrypt(buff); + return 0; + + case AES.CBC: + for (j = 0; j < 16; j++) { + buff[j] ^= this.f[j]; + } + this.ecb_encrypt(buff); + for (j = 0; j < 16; j++) { + this.f[j] = buff[j]; + } + return 0; + + case AES.CFB1: + case AES.CFB2: + case AES.CFB4: + bytes = this.mode - AES.CFB1 + 1; + for (j = 0; j < bytes; j++) { + fell_off = (fell_off << 8) | this.f[j]; + } + for (j = 0; j < 16; j++) { + st[j] = this.f[j]; + } + for (j = bytes; j < 16; j++) { + this.f[j - bytes] = this.f[j]; + } + this.ecb_encrypt(st); + for (j = 0; j < bytes; j++) { + buff[j] ^= st[j]; + this.f[16 - bytes + j] = buff[j]; + } + return fell_off; + + case AES.OFB1: + case AES.OFB2: + case AES.OFB4: + case AES.OFB8: + case AES.OFB16: + bytes = this.mode - AES.OFB1 + 1; + this.ecb_encrypt(this.f); + for (j = 0; j < bytes; j++) { + buff[j] ^= this.f[j]; + } + return 0; + + case AES.CTR1: + case AES.CTR2: + case AES.CTR4: + case AES.CTR8: + case AES.CTR16: + bytes = this.mode - AES.CTR1 + 1; + for (j = 0; j < 16; j++) { + st[j] = this.f[j]; + } + this.ecb_encrypt(st); + for (j = 0; j < bytes; j++) { + buff[j] ^= st[j]; + } + this.increment(); + return 0; + + default: + return 0; + } + }, + + /* Decrypt using selected mode of operation */ + decrypt: function (buff) { + var st = [], + bytes, + fell_off, + j; + + // Supported modes of operation + fell_off = 0; + switch (this.mode) { + case AES.ECB: + this.ecb_decrypt(buff); + return 0; + + case AES.CBC: + for (j = 0; j < 16; j++) { + st[j] = this.f[j]; + this.f[j] = buff[j]; + } + this.ecb_decrypt(buff); + for (j = 0; j < 16; j++) { + buff[j] ^= st[j]; + st[j] = 0; + } + return 0; + + case AES.CFB1: + case AES.CFB2: + case AES.CFB4: + bytes = this.mode - AES.CFB1 + 1; + for (j = 0; j < bytes; j++) { + fell_off = (fell_off << 8) | this.f[j]; + } + for (j = 0; j < 16; j++) { + st[j] = this.f[j]; + } + for (j = bytes; j < 16; j++) { + this.f[j - bytes] = this.f[j]; + } + this.ecb_encrypt(st); + for (j = 0; j < bytes; j++) { + this.f[16 - bytes + j] = buff[j]; + buff[j] ^= st[j]; + } + return fell_off; + + case AES.OFB1: + case AES.OFB2: + case AES.OFB4: + case AES.OFB8: + case AES.OFB16: + bytes = this.mode - AES.OFB1 + 1; + this.ecb_encrypt(this.f); + for (j = 0; j < bytes; j++) { + buff[j] ^= this.f[j]; + } + return 0; + + case AES.CTR1: + case AES.CTR2: + case AES.CTR4: + case AES.CTR8: + case AES.CTR16: + bytes = this.mode - AES.CTR1 + 1; + for (j = 0; j < 16; j++) { + st[j] = this.f[j]; + } + this.ecb_encrypt(st); + for (j = 0; j < bytes; j++) { + buff[j] ^= st[j]; + } + this.increment(); + return 0; + + default: + return 0; + } + }, + + /* Clean up and delete left-overs */ + end: function () { + // clean up + var i; + + for (i = 0; i < 4 * (this.Nr + 1); i++) { + this.fkey[i] = this.rkey[i] = 0; + } + + for (i = 0; i < 16; i++) { + this.f[i] = 0; + } + }, + }; + + /* static functions */ + + AES.ROTL8 = function (x) { + return (x << 8) | (x >>> 24); + }; + + AES.ROTL16 = function (x) { + return (x << 16) | (x >>> 16); + }; + + AES.ROTL24 = function (x) { + return (x << 24) | (x >>> 8); + }; + + AES.pack = function (b) { + /* pack 4 bytes into a 32-bit Word */ + return ((b[3] & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff); + }; + + AES.unpack = function (a) { + /* unpack bytes from a word */ + var b = []; + b[0] = a & 0xff; + b[1] = (a >>> 8) & 0xff; + b[2] = (a >>> 16) & 0xff; + b[3] = (a >>> 24) & 0xff; + return b; + }; + + AES.bmul = function (x, y) { + /* x.y= AntiLog(Log(x) + Log(y)) */ + var ix = x & 0xff, + iy = y & 0xff, + lx = AES.ltab[ix] & 0xff, + ly = AES.ltab[iy] & 0xff; + + if (x !== 0 && y !== 0) { + return AES.ptab[(lx + ly) % 255]; + } else { + return 0; + } + }; + + // if (x && y) + + AES.SubByte = function (a) { + var b = AES.unpack(a); + b[0] = AES.fbsub[b[0] & 0xff]; + b[1] = AES.fbsub[b[1] & 0xff]; + b[2] = AES.fbsub[b[2] & 0xff]; + b[3] = AES.fbsub[b[3] & 0xff]; + return AES.pack(b); + }; + + AES.product = function (x, y) { + /* dot product of two 4-byte arrays */ + var xb = AES.unpack(x), + yb = AES.unpack(y); + + return ( + (AES.bmul(xb[0], yb[0]) ^ + AES.bmul(xb[1], yb[1]) ^ + AES.bmul(xb[2], yb[2]) ^ + AES.bmul(xb[3], yb[3])) & + 0xff + ); + }; + + AES.InvMixCol = function (x) { + /* matrix Multiplication */ + var b = [], + y, + m; + + m = AES.pack(AES.InCo); + b[3] = AES.product(m, x); + m = AES.ROTL24(m); + b[2] = AES.product(m, x); + m = AES.ROTL24(m); + b[1] = AES.product(m, x); + m = AES.ROTL24(m); + b[0] = AES.product(m, x); + y = AES.pack(b); + + return y; + }; + + AES.CBC_IV0_ENCRYPT = function (K, M) { + /* ctx.AES CBC encryption, with Null IV and key K */ + /* Input is from an octet string M, output is to an octet string C */ + /* Input is padded as necessary to make up a full final block */ + var a = new AES(), + buff = [], + C = [], + fin, + padlen, + i, + j, + ipt, + opt; + + a.init(AES.CBC, K.length, K, null); + + ipt = opt = 0; + fin = false; + + for (;;) { + for (i = 0; i < 16; i++) { + if (ipt < M.length) { + buff[i] = M[ipt++]; + } else { + fin = true; + break; + } + } + + if (fin) { + break; + } + + a.encrypt(buff); + + for (i = 0; i < 16; i++) { + C[opt++] = buff[i]; + } + } + + /* last block, filled up to i-th index */ + + padlen = 16 - i; + for (j = i; j < 16; j++) { + buff[j] = padlen; + } + a.encrypt(buff); + for (i = 0; i < 16; i++) { + C[opt++] = buff[i]; + } + a.end(); + + return C; + }; + + AES.CBC_IV0_DECRYPT = function (K, C) { + /* padding is removed */ + var a = new AES(), + buff = [], + MM = [], + ipt = 0, + opt = 0, + M, + ch, + fin, + bad, + padlen, + i; + + a.init(AES.CBC, K.length, K, null); + + if (C.length === 0) { + return []; + } + ch = C[ipt++]; + + fin = false; + + for (;;) { + for (i = 0; i < 16; i++) { + buff[i] = ch; + if (ipt >= C.length) { + fin = true; + break; + } else { + ch = C[ipt++]; + } + } + a.decrypt(buff); + if (fin) { + break; + } + + for (i = 0; i < 16; i++) { + MM[opt++] = buff[i]; + } + } + + a.end(); + bad = false; + padlen = buff[15]; + + if (i != 15 || padlen < 1 || padlen > 16) { + bad = true; + } + + if (padlen >= 2 && padlen <= 16) { + for (i = 16 - padlen; i < 16; i++) { + if (buff[i] != padlen) { + bad = true; + } + } + } + + if (!bad) { + for (i = 0; i < 16 - padlen; i++) { + MM[opt++] = buff[i]; + } + } + + M = []; + if (bad) { + return M; + } + + for (i = 0; i < opt; i++) { + M[i] = MM[i]; + } + + return M; + }; + + AES.InCo = [0xb, 0xd, 0x9, 0xe]; /* Inverse Coefficients */ + AES.rco = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47]; + + AES.ptab = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, + 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11, + 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, + 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, 94, + 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, + 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, + 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, + 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, + 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162, 253, + 28, 36, 108, 180, 199, 82, 246, 1, + ]; + AES.ltab = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, + 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, + 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, 48, + 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, + 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, + 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, 215, + 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, + 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, + 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, + 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, + 140, 128, 192, 247, 112, 7, + ]; + AES.fbsub = [ + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, + 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, + 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, + 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, + 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, + 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, + 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, + 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, + 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, + 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, + 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, + 176, 84, 187, 22, + ]; + AES.rbsub = [ + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, + 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, + 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, + 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, + 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, + 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, + 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, + 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, + 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, + 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, + 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, + 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, + 99, 85, 33, 12, 125, + ]; + AES.ftable = [ + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, + 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, + ]; + AES.rtable = [ + 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, + 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, + 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, + 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, + 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, + 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, + 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, + 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, + 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, + 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, + 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, + 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, + 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, + 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, + 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, + 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, + 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, + 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, + 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, + 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, + 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, + 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, + 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, + 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, + 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, + 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, + 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, + 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, + ]; + + return AES; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + AES: AES, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/big.js b/packages/bls-verify/src/vendor/amcl-js/src/big.js new file mode 100644 index 000000000..bd318cf77 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/big.js @@ -0,0 +1,1505 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE BIG number class */ +var BIG, DBIG; + +BIG = function (ctx) { + 'use strict'; + + /* General purpose Constructor */ + var BIG = function (x) { + this.w = new Array(BIG.NLEN); + + switch (typeof x) { + case 'object': + this.copy(x); + break; + + case 'number': + this.zero(); + this.w[0] = x; + break; + + default: + this.zero(); + } + }; + + BIG.CHUNK = 32; + BIG.MODBYTES = ctx.config['@NB']; + BIG.BASEBITS = ctx.config['@BASE']; + BIG.NLEN = 1 + Math.floor((8 * BIG.MODBYTES - 1) / BIG.BASEBITS); + BIG.DNLEN = 2 * BIG.NLEN; + BIG.BMASK = (1 << BIG.BASEBITS) - 1; + BIG.BIGBITS = 8 * BIG.MODBYTES; + BIG.NEXCESS = 1 << (BIG.CHUNK - BIG.BASEBITS - 1); + BIG.MODINV = Math.pow(2, -BIG.BASEBITS); + + BIG.prototype = { + /* set to zero */ + zero: function () { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] = 0; + } + + return this; + }, + + /* set to one */ + one: function () { + var i; + + this.w[0] = 1; + for (i = 1; i < BIG.NLEN; i++) { + this.w[i] = 0; + } + + return this; + }, + + get: function (i) { + return this.w[i]; + }, + + set: function (i, x) { + this.w[i] = x; + }, + + /* test for zero */ + iszilch: function () { + var i; + var d = 0; + for (i = 0; i < BIG.NLEN; i++) { + d |= this.w[i]; + } + return (1 & ((d - 1) >> BIG.BASEBITS)) != 0; + }, + + /* test for unity */ + isunity: function () { + var i; + var d = 0; + + for (i = 1; i < BIG.NLEN; i++) { + d |= this.w[i]; + } + + return (1 & ((d - 1) >> BIG.BASEBITS) & (((this.w[0] ^ 1) - 1) >> BIG.BASEBITS)) != 0; + }, + + /* Conditional swap of two BIGs depending on d using XOR - no branches */ + cswap: function (b, d) { + var c = d, + t, + i; + + c = ~(c - 1); + + for (i = 0; i < BIG.NLEN; i++) { + t = c & (this.w[i] ^ b.w[i]); + this.w[i] ^= t; + b.w[i] ^= t; + } + }, + + /* Conditional move of BIG depending on d using XOR - no branches */ + cmove: function (b, d) { + var c = d, + i; + + c = ~(c - 1); + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] ^= (this.w[i] ^ b.w[i]) & c; + } + }, + + /* copy from another BIG */ + copy: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] = y.w[i]; + } + + return this; + }, + + /* copy from bottom half of ctx.DBIG */ + hcopy: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] = y.w[i]; + } + + return this; + }, + + /* copy from ROM */ + rcopy: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] = y[i]; + } + + return this; + }, + + xortop: function (x) { + this.w[BIG.NLEN - 1] ^= x; + }, + + ortop: function (x) { + this.w[BIG.NLEN - 1] |= x; + }, + + /* normalise BIG - force all digits < 2^BASEBITS */ + norm: function () { + var carry = 0, + d, + i; + + for (i = 0; i < BIG.NLEN - 1; i++) { + d = this.w[i] + carry; + this.w[i] = d & BIG.BMASK; + carry = d >> BIG.BASEBITS; + } + + this.w[BIG.NLEN - 1] = this.w[BIG.NLEN - 1] + carry; + + return this.w[BIG.NLEN - 1] >> (8 * BIG.MODBYTES) % BIG.BASEBITS; + }, + + /* quick shift right by less than a word */ + fshr: function (k) { + var r, i; + + r = this.w[0] & ((1 << k) - 1); /* shifted out part */ + + for (i = 0; i < BIG.NLEN - 1; i++) { + this.w[i] = (this.w[i] >> k) | ((this.w[i + 1] << (BIG.BASEBITS - k)) & BIG.BMASK); + } + + this.w[BIG.NLEN - 1] = this.w[BIG.NLEN - 1] >> k; + + return r; + }, + + /* General shift right by k bits */ + shr: function (k) { + var n = k % BIG.BASEBITS, + m = Math.floor(k / BIG.BASEBITS), + i; + + for (i = 0; i < BIG.NLEN - m - 1; i++) { + this.w[i] = (this.w[m + i] >> n) | ((this.w[m + i + 1] << (BIG.BASEBITS - n)) & BIG.BMASK); + } + + this.w[BIG.NLEN - m - 1] = this.w[BIG.NLEN - 1] >> n; + + for (i = BIG.NLEN - m; i < BIG.NLEN; i++) { + this.w[i] = 0; + } + + return this; + }, + + /* quick shift left by less than a word */ + fshl: function (k) { + var i; + + this.w[BIG.NLEN - 1] = + (this.w[BIG.NLEN - 1] << k) | (this.w[BIG.NLEN - 2] >> (BIG.BASEBITS - k)); + + for (i = BIG.NLEN - 2; i > 0; i--) { + this.w[i] = ((this.w[i] << k) & BIG.BMASK) | (this.w[i - 1] >> (BIG.BASEBITS - k)); + } + + this.w[0] = (this.w[0] << k) & BIG.BMASK; + + return ( + this.w[BIG.NLEN - 1] >> (8 * BIG.MODBYTES) % BIG.BASEBITS + ); /* return excess - only used in FF.java */ + }, + + /* General shift left by k bits */ + shl: function (k) { + var n = k % BIG.BASEBITS, + m = Math.floor(k / BIG.BASEBITS), + i; + + this.w[BIG.NLEN - 1] = this.w[BIG.NLEN - 1 - m] << n; + + if (BIG.NLEN > m + 2) { + this.w[BIG.NLEN - 1] |= this.w[BIG.NLEN - m - 2] >> (BIG.BASEBITS - n); + } + + for (i = BIG.NLEN - 2; i > m; i--) { + this.w[i] = ((this.w[i - m] << n) & BIG.BMASK) | (this.w[i - m - 1] >> (BIG.BASEBITS - n)); + } + + this.w[m] = (this.w[0] << n) & BIG.BMASK; + + for (i = 0; i < m; i++) { + this.w[i] = 0; + } + + return this; + }, + + /* return length in bits */ + nbits: function () { + var k = BIG.NLEN - 1, + bts, + c; + + var t = new BIG(0); + t.copy(this); + t.norm(); + + while (k >= 0 && t.w[k] === 0) { + k--; + } + + if (k < 0) { + return 0; + } + + bts = BIG.BASEBITS * k; + c = t.w[k]; + + while (c !== 0) { + c = Math.floor(c / 2); + bts++; + } + + return bts; + }, + + /* convert this to string */ + toString: function () { + var s = '', + len = this.nbits(), + b, + i; + + if (len % 4 === 0) { + len = Math.floor(len / 4); + } else { + len = Math.floor(len / 4); + len++; + } + + if (len < BIG.MODBYTES * 2) { + len = BIG.MODBYTES * 2; + } + + for (i = len - 1; i >= 0; i--) { + b = new BIG(0); + b.copy(this); + b.shr(i * 4); + s += (b.w[0] & 15).toString(16); + } + + return s; + }, + + /* this+=y */ + add: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] += y.w[i]; + } + + return this; + }, + + /* this|=y */ + or: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] |= y.w[i]; + } + + return this; + }, + + /* return this+x */ + plus: function (x) { + var s = new BIG(0), + i; + + for (i = 0; i < BIG.NLEN; i++) { + s.w[i] = this.w[i] + x.w[i]; + } + + return s; + }, + + /* this+=i, where i is int */ + inc: function (i) { + this.norm(); + this.w[0] += i; + return this; + }, + + /* this-=y */ + sub: function (y) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] -= y.w[i]; + } + + return this; + }, + + /* reverse subtract this=x-this */ + rsub: function (x) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] = x.w[i] - this.w[i]; + } + + return this; + }, + + /* this-=i, where i is int */ + dec: function (i) { + this.norm(); + this.w[0] -= i; + return this; + }, + + /* return this-x */ + minus: function (x) { + var d = new BIG(0), + i; + + for (i = 0; i < BIG.NLEN; i++) { + d.w[i] = this.w[i] - x.w[i]; + } + + return d; + }, + + /* multiply by small integer */ + imul: function (c) { + var i; + + for (i = 0; i < BIG.NLEN; i++) { + this.w[i] *= c; + } + + return this; + }, + + /* convert this BIG to byte array */ + tobytearray: function (b, n) { + var c = new BIG(0), + i; + + c.copy(this); + c.norm(); + + for (i = BIG.MODBYTES - 1; i >= 0; i--) { + b[i + n] = c.w[0] & 0xff; + c.fshr(8); + } + + return this; + }, + + /* convert this to byte array */ + toBytes: function (b) { + this.tobytearray(b, 0); + }, + + /* set this[i]+=x*y+c, and return high part */ + muladd: function (x, y, c, i) { + var prod = x * y + c + this.w[i]; + this.w[i] = prod & BIG.BMASK; + return (prod - this.w[i]) * BIG.MODINV; + }, + + /* multiply by larger int */ + pmul: function (c) { + var carry = 0, + ak, + i; + + for (i = 0; i < BIG.NLEN; i++) { + ak = this.w[i]; + this.w[i] = 0; + carry = this.muladd(ak, c, carry, i); + } + + return carry; + }, + + /* multiply by still larger int - results requires a ctx.DBIG */ + pxmul: function (c) { + var m = new ctx.DBIG(0), + carry = 0, + j; + + for (j = 0; j < BIG.NLEN; j++) { + carry = m.muladd(this.w[j], c, carry, j); + } + + m.w[BIG.NLEN] = carry; + + return m; + }, + + /* divide by 3 */ + div3: function () { + var carry = 0, + ak, + base, + i; + + this.norm(); + base = 1 << BIG.BASEBITS; + + for (i = BIG.NLEN - 1; i >= 0; i--) { + ak = carry * base + this.w[i]; + this.w[i] = Math.floor(ak / 3); + carry = ak % 3; + } + return carry; + }, + + /* set x = x mod 2^m */ + mod2m: function (m) { + var i, wd, bt, msk; + + wd = Math.floor(m / BIG.BASEBITS); + bt = m % BIG.BASEBITS; + msk = (1 << bt) - 1; + this.w[wd] &= msk; + + for (i = wd + 1; i < BIG.NLEN; i++) { + this.w[i] = 0; + } + }, + + /* a=1/a mod 2^256. This is very fast! */ + invmod2m: function () { + var U = new BIG(0), + b = new BIG(0), + c = new BIG(0), + i, + t1, + t2; + + U.inc(BIG.invmod256(this.lastbits(8))); + + for (i = 8; i < BIG.BIGBITS; i <<= 1) { + U.norm(); + b.copy(this); + b.mod2m(i); + t1 = BIG.smul(U, b); + t1.shr(i); + c.copy(this); + c.shr(i); + c.mod2m(i); + + t2 = BIG.smul(U, c); + t2.mod2m(i); + t1.add(t2); + t1.norm(); + b = BIG.smul(t1, U); + t1.copy(b); + t1.mod2m(i); + + t2.one(); + t2.shl(i); + t1.rsub(t2); + t1.norm(); + t1.shl(i); + U.add(t1); + } + + U.mod2m(BIG.BIGBITS); + this.copy(U); + this.norm(); + }, + + /* reduce this mod m */ + mod: function (m1) { + var k = 0, + r = new BIG(0); + var m = new BIG(0); + m.copy(m1); + + this.norm(); + + if (BIG.comp(this, m) < 0) { + return; + } + + do { + m.fshl(1); + k++; + } while (BIG.comp(this, m) >= 0); + + while (k > 0) { + m.fshr(1); + + r.copy(this); + r.sub(m); + r.norm(); + this.cmove(r, 1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1)); + + k--; + } + }, + /* this/=m */ + div: function (m1) { + var k = 0, + d = 0, + e = new BIG(1), + b = new BIG(0), + r = new BIG(0); + var m = new BIG(0); + m.copy(m1); + + this.norm(); + b.copy(this); + this.zero(); + + while (BIG.comp(b, m) >= 0) { + e.fshl(1); + m.fshl(1); + k++; + } + + while (k > 0) { + m.fshr(1); + e.fshr(1); + + r.copy(b); + r.sub(m); + r.norm(); + d = 1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1); + b.cmove(r, d); + r.copy(this); + r.add(e); + r.norm(); + this.cmove(r, d); + + k--; + } + }, + /* return parity of this */ + parity: function () { + return this.w[0] % 2; + }, + + /* return n-th bit of this */ + bit: function (n) { + if ((this.w[Math.floor(n / BIG.BASEBITS)] & (1 << n % BIG.BASEBITS)) > 0) { + return 1; + } else { + return 0; + } + }, + + /* return last n bits of this */ + lastbits: function (n) { + var msk = (1 << n) - 1; + this.norm(); + return this.w[0] & msk; + }, + + isok: function () { + var ok = true, + i; + + for (i = 0; i < BIG.NLEN; i++) { + if (this.w[i] >> BIG.BASEBITS != 0) { + ok = false; + } + } + + return ok; + }, + + /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ + jacobi: function (p) { + var m = 0, + t = new BIG(0), + x = new BIG(0), + n = new BIG(0), + zilch = new BIG(0), + one = new BIG(1), + n8, + k; + + if (p.parity() === 0 || BIG.comp(this, zilch) === 0 || BIG.comp(p, one) <= 0) { + return 0; + } + + this.norm(); + x.copy(this); + n.copy(p); + x.mod(p); + + while (BIG.comp(n, one) > 0) { + if (BIG.comp(x, zilch) === 0) { + return 0; + } + + n8 = n.lastbits(3); + k = 0; + + while (x.parity() === 0) { + k++; + x.shr(1); + } + + if (k % 2 == 1) { + m += (n8 * n8 - 1) / 8; + } + + m += ((n8 - 1) * (x.lastbits(2) - 1)) / 4; + t.copy(n); + t.mod(x); + n.copy(x); + x.copy(t); + m %= 2; + } + + if (m === 0) { + return 1; + } else { + return -1; + } + }, + + /* this=1/this mod p. Binary method */ + invmodp: function (p) { + if (this.iszilch()) { + return; + } + var u = new BIG(0), + v = new BIG(0), + x1 = new BIG(1), + x2 = new BIG(0), + t = new BIG(0), + one = new BIG(1); + + this.mod(p); + u.copy(this); + v.copy(p); + + while (BIG.comp(u, one) !== 0 && BIG.comp(v, one) !== 0) { + while (u.parity() === 0) { + u.fshr(1); + t.copy(x1); + t.add(p); + x1.cmove(t, x1.parity()); + x1.norm(); + x1.fshr(1); + } + while (v.parity() === 0) { + v.fshr(1); + t.copy(x2); + t.add(p); + x2.cmove(t, x2.parity()); + x2.norm(); + x2.fshr(1); + } + if (BIG.comp(u, v) >= 0) { + u.sub(v); + u.norm(); + t.copy(x1); + t.add(p); + x1.cmove(t, (BIG.comp(x1, x2) >> 1) & 1); + x1.sub(x2); + x1.norm(); + } else { + v.sub(u); + v.norm(); + t.copy(x2); + t.add(p); + x2.cmove(t, (BIG.comp(x2, x1) >> 1) & 1); + x2.sub(x1); + x2.norm(); + } + } + + this.copy(x1); + this.cmove(x2, BIG.comp(u, one) & 1); + }, + + /* return this^e mod m */ + powmod: function (e1, m) { + var a = new BIG(1), + z = new BIG(0), + s = new BIG(0), + bt; + + var e = new BIG(0); + e.copy(e1); + this.norm(); + e.norm(); + z.copy(e); + s.copy(this); + + for (;;) { + bt = z.parity(); + z.fshr(1); + if (bt == 1) { + a = BIG.modmul(a, s, m); + } + + if (z.iszilch()) { + break; + } + + s = BIG.modsqr(s, m); + } + + return a; + }, + }; + + BIG.ssn = function (r, a, m) { + var n = BIG.NLEN - 1; + m.w[0] = (m.w[0] >> 1) | ((m.w[1] << (BIG.BASEBITS - 1)) & BIG.BMASK); + r.w[0] = a.w[0] - m.w[0]; + var carry = r.w[0] >> BIG.BASEBITS; + r.w[0] &= BIG.BMASK; + for (var i = 1; i < n; i++) { + m.w[i] = (m.w[i] >> 1) | ((m.w[i + 1] << (BIG.BASEBITS - 1)) & BIG.BMASK); + r.w[i] = a.w[i] - m.w[i] + carry; + carry = r.w[i] >> BIG.BASEBITS; + r.w[i] &= BIG.BMASK; + } + m.w[n] >>= 1; + r.w[n] = a.w[n] - m.w[n] + carry; + return (r.w[n] >> (BIG.CHUNK - 1)) & 1; + }; + + /* convert from byte array to BIG */ + BIG.frombytearray = function (b, n) { + var m = new BIG(0), + i; + + for (i = 0; i < BIG.MODBYTES; i++) { + m.fshl(8); + m.w[0] += b[i + n] & 0xff; + } + + return m; + }; + + BIG.fromBytes = function (b) { + return BIG.frombytearray(b, 0); + }; + + /* return a*b where product fits a BIG */ + BIG.smul = function (a, b) { + var c = new BIG(0), + carry, + i, + j; + + for (i = 0; i < BIG.NLEN; i++) { + carry = 0; + + for (j = 0; j < BIG.NLEN; j++) { + if (i + j < BIG.NLEN) { + carry = c.muladd(a.w[i], b.w[j], carry, i + j); + } + } + } + + return c; + }; + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + BIG.comp = function (a, b) { + var i; + var gt = 0; + var eq = 1; + + for (i = BIG.NLEN - 1; i >= 0; i--) { + gt |= ((b.w[i] - a.w[i]) >> BIG.BASEBITS) & eq; + eq &= ((b.w[i] ^ a.w[i]) - 1) >> BIG.BASEBITS; + } + + return gt + gt + eq - 1; + }; + + /* get 8*MODBYTES size random number */ + BIG.random = function (rng) { + var m = new BIG(0), + j = 0, + r = 0, + i, + b; + + /* generate random BIG */ + for (i = 0; i < 8 * BIG.MODBYTES; i++) { + if (j === 0) { + r = rng.getByte(); + } else { + r >>= 1; + } + + b = r & 1; + m.shl(1); + m.w[0] += b; // m.inc(b); + j++; + j &= 7; + } + return m; + }; + + /* Create random BIG in portable way, one bit at a time */ + BIG.randomnum = function (q, rng) { + var d = new ctx.DBIG(0), + j = 0, + r = 0, + i, + b, + m; + + for (i = 0; i < 2 * q.nbits(); i++) { + if (j === 0) { + r = rng.getByte(); + } else { + r >>= 1; + } + + b = r & 1; + d.shl(1); + d.w[0] += b; + j++; + j &= 7; + } + + m = d.mod(q); + + return m; + }; + + BIG.randtrunc = function (q, trunc, rng) { + var m = BIG.randomnum(q, rng); + if (q.nbits() > trunc) m.mod2m(trunc); + return m; + }; + + /* return a*b as ctx.DBIG */ + BIG.mul = function (a, b) { + var c = new ctx.DBIG(0), + d = new Array(BIG.NLEN), //[], + n, + s, + t, + i, + k, + co; + + for (i = 0; i < BIG.NLEN; i++) { + d[i] = a.w[i] * b.w[i]; + } + + s = d[0]; + t = s; + c.w[0] = t; + + for (k = 1; k < BIG.NLEN; k++) { + s += d[k]; + t = s; + for (i = k; i >= 1 + Math.floor(k / 2); i--) { + t += (a.w[i] - a.w[k - i]) * (b.w[k - i] - b.w[i]); + } + c.w[k] = t; + } + for (k = BIG.NLEN; k < 2 * BIG.NLEN - 1; k++) { + s -= d[k - BIG.NLEN]; + t = s; + for (i = BIG.NLEN - 1; i >= 1 + Math.floor(k / 2); i--) { + t += (a.w[i] - a.w[k - i]) * (b.w[k - i] - b.w[i]); + } + c.w[k] = t; + } + + co = 0; + for (i = 0; i < BIG.DNLEN - 1; i++) { + n = c.w[i] + co; + c.w[i] = n & BIG.BMASK; + co = (n - c.w[i]) * BIG.MODINV; + } + c.w[BIG.DNLEN - 1] = co; + + return c; + }; + + /* return a^2 as ctx.DBIG */ + BIG.sqr = function (a) { + var c = new ctx.DBIG(0), + n, + t, + j, + i, + co; + + c.w[0] = a.w[0] * a.w[0]; + + for (j = 1; j < BIG.NLEN - 1; ) { + t = a.w[j] * a.w[0]; + for (i = 1; i < (j + 1) >> 1; i++) { + t += a.w[j - i] * a.w[i]; + } + t += t; + c.w[j] = t; + j++; + t = a.w[j] * a.w[0]; + for (i = 1; i < (j + 1) >> 1; i++) { + t += a.w[j - i] * a.w[i]; + } + t += t; + t += a.w[j >> 1] * a.w[j >> 1]; + c.w[j] = t; + j++; + } + + for (j = BIG.NLEN - 1 + (BIG.NLEN % 2); j < BIG.DNLEN - 3; ) { + t = a.w[BIG.NLEN - 1] * a.w[j - BIG.NLEN + 1]; + for (i = j - BIG.NLEN + 2; i < (j + 1) >> 1; i++) { + t += a.w[j - i] * a.w[i]; + } + t += t; + c.w[j] = t; + j++; + t = a.w[BIG.NLEN - 1] * a.w[j - BIG.NLEN + 1]; + for (i = j - BIG.NLEN + 2; i < (j + 1) >> 1; i++) { + t += a.w[j - i] * a.w[i]; + } + t += t; + t += a.w[j >> 1] * a.w[j >> 1]; + c.w[j] = t; + j++; + } + + t = a.w[BIG.NLEN - 2] * a.w[BIG.NLEN - 1]; + t += t; + c.w[BIG.DNLEN - 3] = t; + + t = a.w[BIG.NLEN - 1] * a.w[BIG.NLEN - 1]; + c.w[BIG.DNLEN - 2] = t; + + co = 0; + for (i = 0; i < BIG.DNLEN - 1; i++) { + n = c.w[i] + co; + c.w[i] = n & BIG.BMASK; + co = (n - c.w[i]) * BIG.MODINV; + } + c.w[BIG.DNLEN - 1] = co; + + return c; + }; + + BIG.monty = function (m, nd, d) { + var b = new BIG(0), + v = new Array(BIG.NLEN), + dd = new Array(BIG.NLEN), + s, + c, + t, + i, + k; + + t = d.w[0]; + v[0] = ((t & BIG.BMASK) * nd) & BIG.BMASK; + t += v[0] * m.w[0]; + c = d.w[1] + t * BIG.MODINV; + s = 0; + + for (k = 1; k < BIG.NLEN; k++) { + t = c + s + v[0] * m.w[k]; + for (i = k - 1; i > Math.floor(k / 2); i--) { + t += (v[k - i] - v[i]) * (m.w[i] - m.w[k - i]); + } + v[k] = ((t & BIG.BMASK) * nd) & BIG.BMASK; + t += v[k] * m.w[0]; + c = t * BIG.MODINV + d.w[k + 1]; + + dd[k] = v[k] * m.w[k]; + s += dd[k]; + } + + for (k = BIG.NLEN; k < 2 * BIG.NLEN - 1; k++) { + t = c + s; + for (i = BIG.NLEN - 1; i >= 1 + Math.floor(k / 2); i--) { + t += (v[k - i] - v[i]) * (m.w[i] - m.w[k - i]); + } + b.w[k - BIG.NLEN] = t & BIG.BMASK; + c = (t - b.w[k - BIG.NLEN]) * BIG.MODINV + d.w[k + 1]; + + s -= dd[k - BIG.NLEN + 1]; + } + + b.w[BIG.NLEN - 1] = c & BIG.BMASK; + + return b; + }; + + /* return a*b mod m */ + BIG.modmul = function (a1, b1, m) { + var d; + var a = new BIG(0); + a.copy(a1); + var b = new BIG(0); + b.copy(b1); + a.mod(m); + b.mod(m); + d = BIG.mul(a, b); + + return d.mod(m); + }; + + /* return a^2 mod m */ + BIG.modsqr = function (a1, m) { + var d; + var a = new BIG(0); + a.copy(a1); + a.mod(m); + d = BIG.sqr(a); + + return d.mod(m); + }; + + /* return -a mod m */ + BIG.modneg = function (a1, m) { + var a = new BIG(0); + a.copy(a1); + a.mod(m); + a.rsub(m); + a.mod(m); + return a; + }; + + /* return a+b mod m */ + BIG.modadd = function (a1, b1, m) { + var a = new BIG(0); + a.copy(a1); + var b = new BIG(0); + b.copy(b1); + a.mod(m); + b.mod(m); + a.add(b); + a.norm(); + a.mod(m); + return a; + }; + + /* Arazi and Qi inversion mod 256 */ + BIG.invmod256 = function (a) { + var U, t1, t2, b, c; + + t1 = 0; + c = (a >> 1) & 1; + t1 += c; + t1 &= 1; + t1 = 2 - t1; + t1 <<= 1; + U = t1 + 1; + + // i=2 + b = a & 3; + t1 = U * b; + t1 >>= 2; + c = (a >> 2) & 3; + t2 = (U * c) & 3; + t1 += t2; + t1 *= U; + t1 &= 3; + t1 = 4 - t1; + t1 <<= 2; + U += t1; + + // i=4 + b = a & 15; + t1 = U * b; + t1 >>= 4; + c = (a >> 4) & 15; + t2 = (U * c) & 15; + t1 += t2; + t1 *= U; + t1 &= 15; + t1 = 16 - t1; + t1 <<= 4; + U += t1; + + return U; + }; + return BIG; +}; + +/* CORE double length DBIG number class */ +DBIG = function (ctx) { + 'use strict'; + + /* constructor */ + var DBIG = function (x) { + this.w = new Array(BIG.DNLEN); + this.zero(); + this.w[0] = x; + }; + + DBIG.prototype = { + /* set this=0 */ + zero: function () { + for (var i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] = 0; + } + return this; + }, + + /* set this=b */ + copy: function (b) { + for (var i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] = b.w[i]; + } + return this; + }, + + /* copy from ctx.BIG */ + hcopy: function (b) { + var i; + + for (i = 0; i < ctx.BIG.NLEN; i++) { + this.w[i] = b.w[i]; + } + + for (i = ctx.BIG.NLEN; i < ctx.BIG.DNLEN; i++) { + this.w[i] = 0; + } + + return this; + }, + + ucopy: function (b) { + var i; + + for (i = 0; i < ctx.BIG.NLEN; i++) { + this.w[i] = 0; + } + + for (i = ctx.BIG.NLEN; i < ctx.BIG.DNLEN; i++) { + this.w[i] = b.w[i - ctx.BIG.NLEN]; + } + + return this; + }, + + /* normalise this */ + norm: function () { + var carry = 0, + d, + i; + + for (i = 0; i < ctx.BIG.DNLEN - 1; i++) { + d = this.w[i] + carry; + this.w[i] = d & ctx.BIG.BMASK; + carry = d >> ctx.BIG.BASEBITS; + } + this.w[ctx.BIG.DNLEN - 1] = this.w[ctx.BIG.DNLEN - 1] + carry; + + return this; + }, + + /* set this[i]+=x*y+c, and return high part */ + muladd: function (x, y, c, i) { + var prod = x * y + c + this.w[i]; + this.w[i] = prod & ctx.BIG.BMASK; + return (prod - this.w[i]) * ctx.BIG.MODINV; + }, + + /* shift this right by k bits */ + shr: function (k) { + var n = k % ctx.BIG.BASEBITS, + m = Math.floor(k / ctx.BIG.BASEBITS), + i; + + for (i = 0; i < ctx.BIG.DNLEN - m - 1; i++) { + this.w[i] = + (this.w[m + i] >> n) | ((this.w[m + i + 1] << (ctx.BIG.BASEBITS - n)) & ctx.BIG.BMASK); + } + + this.w[ctx.BIG.DNLEN - m - 1] = this.w[ctx.BIG.DNLEN - 1] >> n; + + for (i = ctx.BIG.DNLEN - m; i < ctx.BIG.DNLEN; i++) { + this.w[i] = 0; + } + + return this; + }, + + /* shift this left by k bits */ + shl: function (k) { + var n = k % ctx.BIG.BASEBITS, + m = Math.floor(k / ctx.BIG.BASEBITS), + i; + + this.w[ctx.BIG.DNLEN - 1] = + (this.w[ctx.BIG.DNLEN - 1 - m] << n) | + (this.w[ctx.BIG.DNLEN - m - 2] >> (ctx.BIG.BASEBITS - n)); + + for (i = ctx.BIG.DNLEN - 2; i > m; i--) { + this.w[i] = + ((this.w[i - m] << n) & ctx.BIG.BMASK) | (this.w[i - m - 1] >> (ctx.BIG.BASEBITS - n)); + } + + this.w[m] = (this.w[0] << n) & ctx.BIG.BMASK; + + for (i = 0; i < m; i++) { + this.w[i] = 0; + } + + return this; + }, + + /* Conditional move of ctx.BIG depending on d using XOR - no branches */ + cmove: function (b, d) { + var c = d, + i; + + c = ~(c - 1); + + for (i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] ^= (this.w[i] ^ b.w[i]) & c; + } + }, + + /* this+=x */ + add: function (x) { + for (var i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] += x.w[i]; + } + }, + + /* this-=x */ + sub: function (x) { + for (var i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] -= x.w[i]; + } + }, + + rsub: function (x) { + for (var i = 0; i < ctx.BIG.DNLEN; i++) { + this.w[i] = x.w[i] - this.w[i]; + } + }, + + /* return number of bits in this */ + nbits: function () { + var k = ctx.BIG.DNLEN - 1, + bts, + c; + + var t = new DBIG(0); + t.copy(this); + t.norm(); + + while (k >= 0 && t.w[k] === 0) { + k--; + } + + if (k < 0) { + return 0; + } + + bts = ctx.BIG.BASEBITS * k; + c = t.w[k]; + + while (c !== 0) { + c = Math.floor(c / 2); + bts++; + } + + return bts; + }, + + /* convert this to string */ + toString: function () { + var s = '', + len = this.nbits(), + b, + i; + + if (len % 4 === 0) { + len = Math.floor(len / 4); + } else { + len = Math.floor(len / 4); + len++; + } + + for (i = len - 1; i >= 0; i--) { + b = new DBIG(0); + b.copy(this); + b.shr(i * 4); + s += (b.w[0] & 15).toString(16); + } + + return s; + }, + + /* reduces this DBIG mod a ctx.BIG, and returns the ctx.BIG */ + mod: function (c) { + var k = 0, + m = new DBIG(0), + dr = new DBIG(0), + r = new ctx.BIG(0); + + this.norm(); + m.hcopy(c); + r.hcopy(this); + + if (DBIG.comp(this, m) < 0) { + return r; + } + + do { + m.shl(1); + k++; + } while (DBIG.comp(this, m) >= 0); + + while (k > 0) { + m.shr(1); + + dr.copy(this); + dr.sub(m); + dr.norm(); + this.cmove(dr, 1 - ((dr.w[ctx.BIG.DNLEN - 1] >> (ctx.BIG.CHUNK - 1)) & 1)); + k--; + } + + r.hcopy(this); + + return r; + }, + + /* this/=c */ + div: function (c) { + var d = 0, + k = 0, + m = new DBIG(0), + dr = new DBIG(0), + r = new ctx.BIG(0), + a = new ctx.BIG(0), + e = new ctx.BIG(1); + + m.hcopy(c); + this.norm(); + + while (DBIG.comp(this, m) >= 0) { + e.fshl(1); + m.shl(1); + k++; + } + + while (k > 0) { + m.shr(1); + e.shr(1); + + dr.copy(this); + dr.sub(m); + dr.norm(); + d = 1 - ((dr.w[ctx.BIG.DNLEN - 1] >> (ctx.BIG.CHUNK - 1)) & 1); + this.cmove(dr, d); + r.copy(a); + r.add(e); + r.norm(); + a.cmove(r, d); + + k--; + } + return a; + }, + + /* split this DBIG at position n, return higher half, keep lower half */ + split: function (n) { + var t = new ctx.BIG(0), + m = n % ctx.BIG.BASEBITS, + carry = this.w[ctx.BIG.DNLEN - 1] << (ctx.BIG.BASEBITS - m), + nw, + i; + + for (i = ctx.BIG.DNLEN - 2; i >= ctx.BIG.NLEN - 1; i--) { + nw = (this.w[i] >> m) | carry; + carry = (this.w[i] << (ctx.BIG.BASEBITS - m)) & ctx.BIG.BMASK; + t.w[i - ctx.BIG.NLEN + 1] = nw; + } + + this.w[ctx.BIG.NLEN - 1] &= (1 << m) - 1; + + return t; + }, + }; + + /* Compare a and b, return 0 if a==b, -1 if ab. Inputs must be normalised */ + DBIG.comp = function (a, b) { + var i; + var gt = 0; + var eq = 1; + for (i = ctx.BIG.DNLEN - 1; i >= 0; i--) { + gt |= ((b.w[i] - a.w[i]) >> ctx.BIG.BASEBITS) & eq; + eq &= ((b.w[i] ^ a.w[i]) - 1) >> ctx.BIG.BASEBITS; + } + + return gt + gt + eq - 1; + }; + + /* convert from byte array to DBIG */ + DBIG.fromBytes = function (b) { + var m = new DBIG(0), + i; + + for (i = 0; i < b.length; i++) { + m.shl(8); + m.w[0] += b[i] & 0xff; + } + + return m; + }; + + return DBIG; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + BIG: BIG, + DBIG: DBIG, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/bls.js b/packages/bls-verify/src/vendor/amcl-js/src/bls.js new file mode 100644 index 000000000..1af3affb8 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/bls.js @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Boneh-Lynn-Shacham signature 128-bit API Functions */ + +var BLS = function (ctx) { + 'use strict'; + + var BLS = { + BLS_OK: 0, + BLS_FAIL: -1, + + BFS: ctx.BIG.MODBYTES, + BGS: ctx.BIG.MODBYTES, + G2_TAB: [], + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + return b; + }, + + init: function () { + var G = ctx.ECP2.generator(); + if (G.is_infinity()) return this.BLS_FAIL; + this.G2_TAB = ctx.PAIR.precomp(G); + return this.BLS_OK; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + /* output u \in F_p */ + hash_to_field: function (hash, hlen, DST, M, ctr) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var L = this.ceil(q.nbits() + ctx.ECP.AESKEY * 8, 8); + var u = []; + var fd = []; + var OKM = ctx.HMAC.XMD_Expand(hash, hlen, L * ctr, DST, M); + + for (var i = 0; i < ctr; i++) { + for (var j = 0; j < L; j++) fd[j] = OKM[i * L + j]; + u[i] = new ctx.FP(ctx.DBIG.fromBytes(fd).mod(q)); + } + return u; + }, + + /* hash a message to an ECP point, using SHA2 */ + bls_hash_to_point: function (M) { + var dst = 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_'; + var u = this.hash_to_field(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, this.asciitobytes(dst), M, 2); + + var P = ctx.ECP.map2point(u[0]); + var P1 = ctx.ECP.map2point(u[1]); + P.add(P1); + P.cfp(); + P.affine(); + return P; + }, + + /* generate key pair, private key S, public key W */ + KeyPairGenerate: function (IKM, S, W) { + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var L = this.ceil(3 * this.ceil(r.nbits(), 8), 2); + var G = ctx.ECP2.generator(); + var LEN = ctx.HMAC.inttobytes(L, 2); + var AIKM = []; + for (var i = 0; i < IKM.length; i++) AIKM[i] = IKM[i]; + AIKM[IKM.length] = 0; + + var salt = 'BLS-SIG-KEYGEN-SALT-'; + var PRK = ctx.HMAC.HKDF_Extract( + ctx.HMAC.MC_SHA2, + ctx.ECP.HASH_TYPE, + this.asciitobytes(salt), + AIKM, + ); + var OKM = ctx.HMAC.HKDF_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, PRK, LEN); + + var dx = ctx.DBIG.fromBytes(OKM); + var s = dx.mod(r); + s.toBytes(S); + // SkToPk + G = ctx.PAIR.G2mul(G, s); + G.toBytes(W, true); + return this.BLS_OK; + }, + + /* Sign message m using private key S to produce signature SIG */ + + core_sign: function (SIG, M, S) { + var D = this.bls_hash_to_point(M); + var s = ctx.BIG.fromBytes(S); + D = ctx.PAIR.G1mul(D, s); + D.toBytes(SIG, true); + return this.BLS_OK; + }, + + /* Verify signature given message m, the signature SIG, and the public key W */ + + core_verify: function (SIG, M, W) { + var HM = this.bls_hash_to_point(M); + + var D = ctx.ECP.fromBytes(SIG); + if (!ctx.PAIR.G1member(D)) return this.BLS_FAIL; + D.neg(); + + var PK = ctx.ECP2.fromBytes(W); + if (!ctx.PAIR.G2member(PK)) return this.BLS_FAIL; + + // Use new multi-pairing mechanism + //var r = ctx.PAIR.initmp(); + //ctx.PAIR.another_pc(r, this.G2_TAB, D); + // ctx.PAIR.another(r,G,D); + //ctx.PAIR.another(r, PK, HM); + //var v = ctx.PAIR.miller(r); + + //.. or alternatively + var G = ctx.ECP2.generator(); + var v = ctx.PAIR.ate2(G, D, PK, HM); + + v = ctx.PAIR.fexp(v); + if (v.isunity()) return this.BLS_OK; + return this.BLS_FAIL; + }, + }; + + return BLS; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + BLS: BLS, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/bls192.js b/packages/bls-verify/src/vendor/amcl-js/src/bls192.js new file mode 100644 index 000000000..61b26ca57 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/bls192.js @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Boneh-Lynn-Shacham signature 192-bit API Functions */ + +var BLS192 = function (ctx) { + 'use strict'; + + var BLS192 = { + BLS_OK: 0, + BLS_FAIL: -1, + + BFS: ctx.BIG.MODBYTES, + BGS: ctx.BIG.MODBYTES, + G2_TAB: [], + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + init: function () { + var G = ctx.ECP4.generator(); + if (G.is_infinity()) return this.BLS_FAIL; + this.G2_TAB = ctx.PAIR4.precomp(G); + return this.BLS_OK; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + /* output u \in F_p */ + hash_to_field: function (hash, hlen, DST, M, ctr) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var L = this.ceil(q.nbits() + ctx.ECP.AESKEY * 8, 8); + var u = []; + var fd = []; + var OKM = ctx.HMAC.XMD_Expand(hash, hlen, L * ctr, DST, M); + + for (var i = 0; i < ctr; i++) { + for (var j = 0; j < L; j++) fd[j] = OKM[i * L + j]; + u[i] = new ctx.FP(ctx.DBIG.fromBytes(fd).mod(q)); + } + return u; + }, + + /* hash a message to an ECP point, using SHA2 */ + bls_hash_to_point: function (M) { + var dst = 'BLS_SIG_ZZZG1_XMD:SHA-384_SVDW_RO_NUL_'; + var u = this.hash_to_field(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, this.asciitobytes(dst), M, 2); + + var P = ctx.ECP.map2point(u[0]); + var P1 = ctx.ECP.map2point(u[1]); + P.add(P1); + P.cfp(); + P.affine(); + return P; + }, + + /* generate key pair, private key S, public key W */ + KeyPairGenerate: function (IKM, S, W) { + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var L = this.ceil(3 * this.ceil(r.nbits(), 8), 2); + var G = ctx.ECP4.generator(); + var LEN = ctx.HMAC.inttobytes(L, 2); + var AIKM = []; + for (var i = 0; i < IKM.length; i++) AIKM[i] = IKM[i]; + AIKM[IKM.length] = 0; + + var salt = 'BLS-SIG-KEYGEN-SALT-'; + var PRK = ctx.HMAC.HKDF_Extract( + ctx.HMAC.MC_SHA2, + ctx.ECP.HASH_TYPE, + this.asciitobytes(salt), + AIKM, + ); + var OKM = ctx.HMAC.HKDF_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, PRK, LEN); + + var dx = ctx.DBIG.fromBytes(OKM); + var s = dx.mod(r); + s.toBytes(S); + // SkToPk + G = ctx.PAIR4.G2mul(G, s); + G.toBytes(W, true); + return this.BLS_OK; + }, + + /* Sign message m using private key S to produce signature SIG */ + + core_sign: function (SIG, M, S) { + var D = this.bls_hash_to_point(M); + var s = ctx.BIG.fromBytes(S); + D = ctx.PAIR4.G1mul(D, s); + D.toBytes(SIG, true); + return this.BLS_OK; + }, + + /* Verify signature given message m, the signature SIG, and the public key W */ + + core_verify: function (SIG, M, W) { + var HM = this.bls_hash_to_point(M); + + var D = ctx.ECP.fromBytes(SIG); + if (!ctx.PAIR4.G1member(D)) return this.BLS_FAIL; + D.neg(); + + var PK = ctx.ECP4.fromBytes(W); + if (!ctx.PAIR4.G2member(PK)) return this.BLS_FAIL; + + // Use new multi-pairing mechanism + var r = ctx.PAIR4.initmp(); + // ctx.PAIR4.another(r,G,D); + ctx.PAIR4.another_pc(r, this.G2_TAB, D); + ctx.PAIR4.another(r, PK, HM); + var v = ctx.PAIR4.miller(r); + + //.. or alternatively + // var v=ctx.PAIR4.ate2(G,D,PK,HM); + v = ctx.PAIR4.fexp(v); + if (v.isunity()) return this.BLS_OK; + return this.BLS_FAIL; + }, + }; + + return BLS192; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + BLS192: BLS192, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/bls256.js b/packages/bls-verify/src/vendor/amcl-js/src/bls256.js new file mode 100644 index 000000000..dd4077eba --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/bls256.js @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Boneh-Lynn-Shacham signature 256-bit API Functions */ + +var BLS256 = function (ctx) { + 'use strict'; + + var BLS256 = { + BLS_OK: 0, + BLS_FAIL: -1, + + BFS: ctx.BIG.MODBYTES, + BGS: ctx.BIG.MODBYTES, + G2_TAB: [], + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + init: function () { + var G = ctx.ECP8.generator(); + if (G.is_infinity()) return this.BLS_FAIL; + this.G2_TAB = ctx.PAIR8.precomp(G); + return this.BLS_OK; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + /* output u \in F_p */ + hash_to_field: function (hash, hlen, DST, M, ctr) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var L = this.ceil(q.nbits() + ctx.ECP.AESKEY * 8, 8); + var u = []; + var fd = []; + var OKM = ctx.HMAC.XMD_Expand(hash, hlen, L * ctr, DST, M); + + for (var i = 0; i < ctr; i++) { + for (var j = 0; j < L; j++) fd[j] = OKM[i * L + j]; + u[i] = new ctx.FP(ctx.DBIG.fromBytes(fd).mod(q)); + } + return u; + }, + + /* hash a message to an ECP point, using SHA2 */ + bls_hash_to_point: function (M) { + var dst = 'BLS_SIG_ZZZG1_XMD:SHA-512_SVDW_RO_NUL_'; + var u = this.hash_to_field(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, this.asciitobytes(dst), M, 2); + + var P = ctx.ECP.map2point(u[0]); + var P1 = ctx.ECP.map2point(u[1]); + P.add(P1); + P.cfp(); + P.affine(); + return P; + }, + + /* generate key pair, private key S, public key W */ + KeyPairGenerate: function (IKM, S, W) { + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var L = this.ceil(3 * this.ceil(r.nbits(), 8), 2); + var G = ctx.ECP8.generator(); + var LEN = ctx.HMAC.inttobytes(L, 2); + var AIKM = []; + for (var i = 0; i < IKM.length; i++) AIKM[i] = IKM[i]; + AIKM[IKM.length] = 0; + + var salt = 'BLS-SIG-KEYGEN-SALT-'; + var PRK = ctx.HMAC.HKDF_Extract( + ctx.HMAC.MC_SHA2, + ctx.ECP.HASH_TYPE, + this.asciitobytes(salt), + AIKM, + ); + var OKM = ctx.HMAC.HKDF_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, PRK, LEN); + + var dx = ctx.DBIG.fromBytes(OKM); + var s = dx.mod(r); + s.toBytes(S); + // SkToPk + G = ctx.PAIR8.G2mul(G, s); + G.toBytes(W, true); + return this.BLS_OK; + }, + + /* Sign message m using private key S to produce signature SIG */ + + core_sign: function (SIG, M, S) { + var D = this.bls_hash_to_point(M); + var s = ctx.BIG.fromBytes(S); + D = ctx.PAIR8.G1mul(D, s); + D.toBytes(SIG, true); + return this.BLS_OK; + }, + + /* Verify signature given message m, the signature SIG, and the public key W */ + + core_verify: function (SIG, M, W) { + var HM = this.bls_hash_to_point(M); + + var D = ctx.ECP.fromBytes(SIG); + if (!ctx.PAIR8.G1member(D)) return this.BLS_FAIL; + D.neg(); + + var PK = ctx.ECP8.fromBytes(W); + if (!ctx.PAIR8.G2member(PK)) return this.BLS_FAIL; + + //if (!ctx.PAIR8.G2member(PK)) alert("Not a member"); + //alert("PK= "+PK.toString()); + + // Use new multi-pairing mechanism + var r = ctx.PAIR8.initmp(); + // ctx.PAIR8.another(r,G,D); + ctx.PAIR8.another_pc(r, this.G2_TAB, D); + ctx.PAIR8.another(r, PK, HM); + var v = ctx.PAIR8.miller(r); + + //.. or alternatively + //var G = ctx.ECP8.generator(); + //var v=ctx.PAIR8.ate2(G,D,PK,HM); + + v = ctx.PAIR8.fexp(v); + if (v.isunity()) return this.BLS_OK; + return this.BLS_FAIL; + }, + }; + + return BLS256; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + BLS256: BLS256, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ctx.js b/packages/bls-verify/src/vendor/amcl-js/src/ctx.js new file mode 100644 index 000000000..5a2a51636 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ctx.js @@ -0,0 +1,1203 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var CTX = function (input_parameter) { + 'use strict'; + + var ctx = this, + CTXLIST, + prepareModule; + + CTXLIST = { + ED25519: { + 'BITS': '256', + 'FIELD': '25519', + 'CURVE': 'ED25519', + '@NB': 32 /* Number of bytes in Modulus */, + '@BASE': 24 /* Number base as power of 2 */, + '@NBT': 255 /* Number of bits in modulus */, + '@M8': 2 /* Modulus mod 8 */, + '@RZ': 1 /* Hash-to-point Z value */, + '@RZ2A': 0 /* Hash-to-point G2 Z value */, + '@RZ2B': 0 /* Hash-to-point G2 Z value */, + '@HC': 0 /* Isogeny degree G1 */, + '@HC2': 0 /* Isogeny degree G2 */, + '@MT': 1 /* Modulus Type (pseudo-mersenne,...) */, + '@QI': 0 /* Fp2 QNR */, + '@TW': 0 /* Tower type */, + '@CT': 1 /* Curve Type (Weierstrass,...) */, + '@CA': -1 /* Curve A parameter */, + '@PF': 0 /* Pairing Friendly */, + '@ST': 0 /* Sextic Twist Type */, + '@SX': 0 /* Sign of x parameter */, + '@AB': 0 /* ATE parameter size */, + '@HT': 32 /* Hash output size */, + '@SH': 9 /* Maximum field excess */, + '@AK': 16 /* AES key size */, + }, + + MDC: { + 'BITS': '256', + 'FIELD': 'MDC', + 'CURVE': 'MDC', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + X448: { + 'BITS': '448', + 'FIELD': 'GOLDILOCKS', + 'CURVE': 'X448', + '@NB': 56, + '@BASE': 23, + '@NBT': 448, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 2, + '@QI': 0, + '@TW': 0, + '@CT': 2, + '@CA': 156326, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + SECP160R1: { + 'BITS': '160', + 'FIELD': 'SECP160R1', + 'CURVE': 'SECP160R1', + '@NB': 20, + '@BASE': 24, + '@NBT': 160, + '@M8': 1, + '@RZ': 3, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + C25519: { + 'BITS': '256', + 'FIELD': '25519', + 'CURVE': 'C25519', + '@NB': 32, + '@BASE': 24, + '@NBT': 255, + '@M8': 2, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 2, + '@CA': 486662, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 9, + '@AK': 16, + }, + + C13318: { + 'BITS': '256', + 'FIELD': '25519', + 'CURVE': 'C13318', + '@NB': 32, + '@BASE': 24, + '@NBT': 255, + '@M8': 2, + '@RZ': 2, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 9, + '@AK': 16, + }, + + JUBJUB: { + 'BITS': '256', + 'FIELD': 'JUBJUB', + 'CURVE': 'JUBJUB', + '@NB': 32, + '@BASE': 24, + '@NBT': 255, + '@M8': 32, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 5, + '@TW': 0, + '@CT': 1, + '@CA': -1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 9, + '@AK': 16, + }, + + SECP256K1: { + 'BITS': '256', + 'FIELD': 'SECP256K1', + 'CURVE': 'SECP256K1', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': -11, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 3, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + NIST256: { + 'BITS': '256', + 'FIELD': 'NIST256', + 'CURVE': 'NIST256', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': -10, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + SM2: { + 'BITS': '256', + 'FIELD': 'SM2', + 'CURVE': 'SM2', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': -9, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + NIST384: { + 'BITS': '384', + 'FIELD': 'NIST384', + 'CURVE': 'NIST384', + '@NB': 48, + '@BASE': 23, + '@NBT': 384, + '@M8': 1, + '@RZ': -12, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 48, + '@SH': 7, + '@AK': 24, + }, + + BRAINPOOL: { + 'BITS': '256', + 'FIELD': 'BRAINPOOL', + 'CURVE': 'BRAINPOOL', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': -3, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + ANSSI: { + 'BITS': '256', + 'FIELD': 'ANSSI', + 'CURVE': 'ANSSI', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': -5, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + HIFIVE: { + 'BITS': '336', + 'FIELD': 'HIFIVE', + 'CURVE': 'HIFIVE', + '@NB': 42, + '@BASE': 23, + '@NBT': 336, + '@M8': 2, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 48, + '@SH': 9, + '@AK': 24, + }, + + GOLDILOCKS: { + 'BITS': '448', + 'FIELD': 'GOLDILOCKS', + 'CURVE': 'GOLDILOCKS', + '@NB': 56, + '@BASE': 23, + '@NBT': 448, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 2, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + C41417: { + 'BITS': '416', + 'FIELD': 'C41417', + 'CURVE': 'C41417', + '@NB': 52, + '@BASE': 22, + '@NBT': 414, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 4, + '@AK': 32, + }, + + C1174: { + 'BITS': '256', + 'FIELD': 'C1174', + 'CURVE': 'C1174', + '@NB': 32, + '@BASE': 24, + '@NBT': 251, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + C1665: { + 'BITS': '168', + 'FIELD': 'C1665', + 'CURVE': 'C1665', + '@NB': 21, + '@BASE': 23, + '@NBT': 166, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + NIST521: { + 'BITS': '528', + 'FIELD': 'NIST521', + 'CURVE': 'NIST521', + '@NB': 66, + '@BASE': 23, + '@NBT': 521, + '@M8': 1, + '@RZ': -4, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 8, + '@AK': 32, + }, + + NUMS256W: { + 'BITS': '256', + 'FIELD': '256PM', + 'CURVE': 'NUMS256W', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': 7, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + NUMS256E: { + 'BITS': '256', + 'FIELD': '256PM', + 'CURVE': 'NUMS256E', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + NUMS384W: { + 'BITS': '384', + 'FIELD': '384PM', + 'CURVE': 'NUMS384W', + '@NB': 48, + '@BASE': 23, + '@NBT': 384, + '@M8': 1, + '@RZ': -4, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 48, + '@SH': 7, + '@AK': 24, + }, + + NUMS384E: { + 'BITS': '384', + 'FIELD': '384PM', + 'CURVE': 'NUMS384E', + '@NB': 48, + '@BASE': 23, + '@NBT': 384, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 48, + '@SH': 7, + '@AK': 24, + }, + + NUMS512W: { + 'BITS': '512', + 'FIELD': '512PM', + 'CURVE': 'NUMS512W', + '@NB': 64, + '@BASE': 23, + '@NBT': 512, + '@M8': 1, + '@RZ': -4, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': -3, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + NUMS512E: { + 'BITS': '512', + 'FIELD': '512PM', + 'CURVE': 'NUMS512E', + '@NB': 64, + '@BASE': 23, + '@NBT': 512, + '@M8': 1, + '@RZ': 0, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 1, + '@QI': 0, + '@TW': 0, + '@CT': 1, + '@CA': 1, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + TWEEDLEDUM: { + 'BITS': '255', + 'FIELD': 'TWEEDLEDUM', + 'CURVE': 'TWEEDLEDUM', + '@NB': 32, + '@BASE': 24, + '@NBT': 255, + '@M8': 33, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 5, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 9, + '@AK': 16, + }, + + TWEEDLEDEE: { + 'BITS': '255', + 'FIELD': 'TWEEDLEDEE', + 'CURVE': 'TWEEDLEDEE', + '@NB': 32, + '@BASE': 24, + '@NBT': 255, + '@M8': 34, + '@RZ': 1, + '@RZ2A': 0, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 5, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 0, + '@ST': 0, + '@SX': 0, + '@AB': 0, + '@HT': 32, + '@SH': 9, + '@AK': 16, + }, + + FP256BN: { + 'BITS': '256', + 'FIELD': 'FP256BN', + 'CURVE': 'FP256BN', + '@NB': 32, + '@BASE': 24, + '@NBT': 256, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 1, + '@ST': 1, + '@SX': 1, + '@AB': 66, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + FP512BN: { + 'BITS': '512', + 'FIELD': 'FP512BN', + 'CURVE': 'FP512BN', + '@NB': 64, + '@BASE': 23, + '@NBT': 512, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 1, + '@ST': 1, + '@SX': 0, + '@AB': 130, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + BN254: { + 'BITS': '256', + 'FIELD': 'BN254', + 'CURVE': 'BN254', + '@NB': 32, + '@BASE': 24, + '@NBT': 254, + '@M8': 1, + '@RZ': -1, + '@RZ2A': -1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 1, + '@ST': 0, + '@SX': 1, + '@AB': 66, + '@HT': 32, + '@SH': 10, + '@AK': 16, + }, + + BN254CX: { + 'BITS': '256', + 'FIELD': 'BN254CX', + 'CURVE': 'BN254CX', + '@NB': 32, + '@BASE': 24, + '@NBT': 254, + '@M8': 1, + '@RZ': -1, + '@RZ2A': -1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 1, + '@ST': 0, + '@SX': 1, + '@AB': 66, + '@HT': 32, + '@SH': 10, + '@AK': 16, + }, + + BN462: { + 'BITS': '464', + 'FIELD': 'BN462', + 'CURVE': 'BN462', + '@NB': 58, + '@BASE': 23, + '@NBT': 462, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 1, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 1, + '@ST': 0, + '@SX': 0, + '@AB': 118, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + BLS12383: { + 'BITS': '384', + 'FIELD': 'BLS12383', + 'CURVE': 'BLS12383', + '@NB': 48, + '@BASE': 23, + '@NBT': 383, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 2, + '@ST': 1, + '@SX': 0, + '@AB': 65, + '@HT': 32, + '@SH': 8, + '@AK': 16, + }, + + BLS24479: { + 'BITS': '480', + 'FIELD': 'BLS24479', + 'CURVE': 'BLS24479', + '@NB': 60, + '@BASE': 23, + '@NBT': 479, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 4, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 3, + '@ST': 1, + '@SX': 0, + '@AB': 49, + '@HT': 48, + '@SH': 4, + '@AK': 24, + }, + + BLS48556: { + 'BITS': '560', + 'FIELD': 'BLS48556', + 'CURVE': 'BLS48556', + '@NB': 70, + '@BASE': 23, + '@NBT': 556, + '@M8': 1, + '@RZ': -1, + '@RZ2A': 2, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 4, + '@ST': 1, + '@SX': 0, + '@AB': 32, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + BLS48286: { + 'BITS': '288', + 'FIELD': 'BLS48286', + 'CURVE': 'BLS48286', + '@NB': 36, + '@BASE': 23, + '@NBT': 286, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 1, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 4, + '@ST': 1, + '@SX': 0, + '@AB': 17, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + BLS48581: { + 'BITS': '584', + 'FIELD': 'BLS48581', + 'CURVE': 'BLS48581', + '@NB': 73, + '@BASE': 23, + '@NBT': 581, + '@M8': 1, + '@RZ': 2, + '@RZ2A': 2, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 1, + '@CT': 0, + '@CA': 0, + '@PF': 4, + '@ST': 0, + '@SX': 1, + '@AB': 33, + '@HT': 64, + '@SH': 11, + '@AK': 32, + }, + + BLS12381: { + 'BITS': '381', + 'FIELD': 'BLS12381', + 'CURVE': 'BLS12381', + '@NB': 48, + '@BASE': 23, + '@NBT': 381, + '@M8': 1, + '@RZ': 11, + '@RZ2A': -2, + '@RZ2B': -1, + '@HC': 11, + '@HC2': 3, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 2, + '@ST': 1, + '@SX': 1, + '@AB': 65, + '@HT': 32, + '@SH': 10, + '@AK': 16, + }, + + BLS12461: { + 'BITS': '464', + 'FIELD': 'BLS12461', + 'CURVE': 'BLS12461', + '@NB': 58, + '@BASE': 23, + '@NBT': 461, + '@M8': 1, + '@RZ': 1, + '@RZ2A': 4, + '@RZ2B': 0, + '@HC': 0, + '@HC2': 0, + '@MT': 0, + '@QI': 0, + '@TW': 0, + '@CT': 0, + '@CA': 0, + '@PF': 2, + '@ST': 1, + '@SX': 1, + '@AB': 78, + '@HT': 32, + '@SH': 11, + '@AK': 16, + }, + + RSA2048: { + 'BITS': '1024', + 'TFF': '2048', + '@NB': 128, + '@BASE': 22, + '@ML': 2, + }, + + RSA3072: { + 'BITS': '384', + 'TFF': '3072', + '@NB': 48, + '@BASE': 23, + '@ML': 8, + }, + + RSA4096: { + 'BITS': '512', + 'TFF': '4096', + '@NB': 64, + '@BASE': 23, + '@ML': 8, + }, + }; + + prepareModule = function (moduleName, fileName, propertyName) { + if (!propertyName) { + propertyName = moduleName; + } + + if (typeof require !== 'undefined') { + if (!fileName) { + fileName = moduleName.toLowerCase(); + } + + ctx[propertyName] = require('./' + fileName)[moduleName](ctx); + } else { + ctx[propertyName] = window[moduleName](ctx); + } + }; + + prepareModule('AES'); + prepareModule('GCM'); + prepareModule('UInt64'); + prepareModule('HMAC'); + prepareModule('HASH256'); + prepareModule('HASH384'); + prepareModule('HASH512'); + prepareModule('SHA3'); + prepareModule('RAND'); + prepareModule('SHARE'); + prepareModule('NHS'); + + if (typeof input_parameter === 'undefined') { + return; + } + + ctx.config = CTXLIST[input_parameter]; + + // Set BIG parameters + prepareModule('BIG'); + prepareModule('DBIG', 'big'); + + // Set RSA parameters + if (typeof ctx.config['TFF'] !== 'undefined') { + prepareModule('FF'); + prepareModule('RSA'); + prepareModule('rsa_public_key', 'rsa'); + prepareModule('rsa_private_key', 'rsa'); + return; + } + + // Set Elliptic Curve parameters + if (typeof ctx.config['CURVE'] !== 'undefined') { + prepareModule('ROM_CURVE_' + ctx.config['CURVE'], 'rom_curve', 'ROM_CURVE'); + + prepareModule('ROM_FIELD_' + ctx.config['FIELD'], 'rom_field', 'ROM_FIELD'); + + prepareModule('FP'); + prepareModule('ECP'); + prepareModule('ECDH'); + prepareModule('HPKE'); + + if (ctx.config['@PF'] == 1 || ctx.config['@PF'] == 2) { + prepareModule('FP2'); + prepareModule('FP4'); + prepareModule('FP12'); + prepareModule('ECP2'); + prepareModule('PAIR'); + prepareModule('MPIN'); + prepareModule('BLS'); + } + + if (ctx.config['@PF'] == 3) { + prepareModule('FP2'); + prepareModule('FP4'); + prepareModule('FP8'); + prepareModule('FP24'); + prepareModule('ECP4'); + prepareModule('PAIR4'); + prepareModule('MPIN192'); + prepareModule('BLS192'); + } + + if (ctx.config['@PF'] == 4) { + prepareModule('FP2'); + prepareModule('FP4'); + prepareModule('FP8'); + prepareModule('FP16'); + prepareModule('FP48'); + prepareModule('ECP8'); + prepareModule('PAIR8'); + prepareModule('MPIN256'); + prepareModule('BLS256'); + } + + return; + } +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = CTX; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ecdh.js b/packages/bls-verify/src/vendor/amcl-js/src/ecdh.js new file mode 100644 index 000000000..f00493340 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ecdh.js @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ECDH/ECIES/ECDSA API Functions */ + +var ECDH = function (ctx) { + 'use strict'; + + var ECDH = { + INVALID_PUBLIC_KEY: -2, + ERROR: -3, + //INVALID: -4, + EFS: ctx.BIG.MODBYTES, + EGS: ctx.BIG.MODBYTES, + SHA256: 32, + SHA384: 48, + SHA512: 64, + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + /* ctx.AES encryption/decryption */ + + IN_RANGE: function (S) { + var r, s; + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + s = ctx.BIG.fromBytes(S); + if (s.iszilch()) return false; + if (ctx.BIG.comp(s, r) >= 0) return false; + return true; + }, + + KEY_PAIR_GENERATE: function (RNG, S, W) { + var res = 0, + r, + s, + G, + WP; + // var T=[]; + + G = ctx.ECP.generator(); + + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + if (RNG === null) { + s = ctx.BIG.fromBytes(S); + s.mod(r); + } else { + s = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, RNG); + } + + s.toBytes(S); + + WP = G.mul(s); + WP.toBytes(W, false); // To use point compression on public keys, change to true + + return res; + }, + + PUBLIC_KEY_VALIDATE: function (W) { + var WP = ctx.ECP.fromBytes(W), + res = 0, + r, + q, + nb, + k; + + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + if (WP.is_infinity()) { + res = this.INVALID_PUBLIC_KEY; + } + + if (res === 0) { + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + nb = q.nbits(); + k = new ctx.BIG(1); + k.shl(Math.floor((nb + 4) / 2)); + k.add(q); + k.div(r); + + while (k.parity() == 0) { + k.shr(1); + WP.dbl(); + } + + if (!k.isunity()) { + WP = WP.mul(k); + } + + if (WP.is_infinity()) { + res = this.INVALID_PUBLIC_KEY; + } + } + + return res; + }, + + ECPSVDP_DH: function (S, WD, Z, type) { + var res = 0, + r, + s, + i, + W; + + s = ctx.BIG.fromBytes(S); + + W = ctx.ECP.fromBytes(WD); + if (W.is_infinity()) { + res = this.ERROR; + } + + if (res === 0) { + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + s.mod(r); + W = W.mul(s); + + if (W.is_infinity()) { + res = this.ERROR; + } else { + if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) { + if (type > 0) { + if (type == 1) W.toBytes(Z, true); + else W.toBytes(Z, false); + } else { + W.getX().toBytes(Z); + } + return res; + } else { + W.getX().toBytes(Z); + } + } + } + return res; + }, + + ECPSP_DSA: function (sha, RNG, S, F, C, D) { + var T = [], + i, + r, + s, + f, + c, + d, + u, + vx, + w, + G, + V, + B; + + B = ctx.HMAC.GPhashit(ctx.HMAC.MC_SHA2, sha, ctx.BIG.MODBYTES, 0, F, -1, null); + + G = ctx.ECP.generator(); + + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + s = ctx.BIG.fromBytes(S); + f = ctx.BIG.fromBytes(B); + + c = new ctx.BIG(0); + d = new ctx.BIG(0); + V = new ctx.ECP(); + + do { + u = ctx.BIG.randomnum(r, RNG); + w = ctx.BIG.randomnum(r, RNG); /* side channel masking */ + V.copy(G); + V = V.mul(u); + vx = V.getX(); + c.copy(vx); + c.mod(r); + if (c.iszilch()) { + continue; + } + u = ctx.BIG.modmul(u, w, r); + u.invmodp(r); + d = ctx.BIG.modmul(s, c, r); + d.add(f); + d = ctx.BIG.modmul(d, w, r); + d = ctx.BIG.modmul(u, d, r); + } while (d.iszilch()); + + c.toBytes(T); + for (i = 0; i < this.EFS; i++) { + C[i] = T[i]; + } + d.toBytes(T); + for (i = 0; i < this.EFS; i++) { + D[i] = T[i]; + } + + return 0; + }, + + ECPVP_DSA: function (sha, W, F, C, D) { + var B = [], + res = 0, + r, + f, + c, + d, + h2, + G, + WP, + P; + + B = ctx.HMAC.GPhashit(ctx.HMAC.MC_SHA2, sha, ctx.BIG.MODBYTES, 0, F, -1, null); + + G = ctx.ECP.generator(); + + r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + c = ctx.BIG.fromBytes(C); + d = ctx.BIG.fromBytes(D); + f = ctx.BIG.fromBytes(B); + + if (c.iszilch() || ctx.BIG.comp(c, r) >= 0 || d.iszilch() || ctx.BIG.comp(d, r) >= 0) { + res = this.ERROR; + } + + if (res === 0) { + d.invmodp(r); + f = ctx.BIG.modmul(f, d, r); + h2 = ctx.BIG.modmul(c, d, r); + + WP = ctx.ECP.fromBytes(W); + if (WP.is_infinity()) { + res = this.ERROR; + } else { + P = new ctx.ECP(); + /* + var X=[]; X[0]=new ctx.ECP(); X[1]=new ctx.ECP(); + var e=[]; e[0]=new ctx.BIG(); e[1]=new ctx.BIG(); + X[0].copy(WP); X[1].copy(G); + e[0].copy(h2); e[1].copy(f); + P=ctx.ECP.muln(2,X,e); +*/ + + P.copy(WP); + P = P.mul2(h2, G, f); + + if (P.is_infinity()) { + res = this.ERROR; + } else { + d = P.getX(); + d.mod(r); + if (ctx.BIG.comp(d, c) !== 0) { + res = this.ERROR; + } + } + } + } + + return res; + }, + + ECIES_ENCRYPT: function (sha, P1, P2, RNG, W, M, V, T) { + var Z = [], + VZ = [], + K1 = [], + K2 = [], + U = [], + C = [], + K, + L2, + AC, + i; + + if (this.KEY_PAIR_GENERATE(RNG, U, V) !== 0) { + return C; + } + + if (this.ECPSVDP_DH(U, W, Z, 0) !== 0) { + return C; + } + + for (i = 0; i < 2 * this.EFS + 1; i++) { + VZ[i] = V[i]; + } + + for (i = 0; i < this.EFS; i++) { + VZ[2 * this.EFS + 1 + i] = Z[i]; + } + + K = ctx.HMAC.KDF2(ctx.HMAC.MC_SHA2, sha, VZ, P1, 2 * ctx.ECP.AESKEY); + + for (i = 0; i < ctx.ECP.AESKEY; i++) { + K1[i] = K[i]; + K2[i] = K[ctx.ECP.AESKEY + i]; + } + + C = ctx.AES.CBC_IV0_ENCRYPT(K1, M); + + L2 = ctx.HMAC.inttobytes(P2.length, 8); + + AC = []; + for (i = 0; i < C.length; i++) { + AC[i] = C[i]; + } + for (i = 0; i < P2.length; i++) { + AC[C.length + i] = P2[i]; + } + for (i = 0; i < 8; i++) { + AC[C.length + P2.length + i] = L2[i]; + } + + ctx.HMAC.HMAC1(ctx.HMAC.MC_SHA2, sha, T, T.length, K2, AC); + + return C; + }, + + ncomp: function (T1, T2, n) { + var res = 0; + for (var i = 0; i < n; i++) { + res |= T1[i] ^ T2[i]; + } + if (res == 0) return true; + return false; + }, + + ECIES_DECRYPT: function (sha, P1, P2, V, C, T, U) { + var Z = [], + VZ = [], + K1 = [], + K2 = [], + TAG = new Array(T.length), + M = [], + K, + L2, + AC, + i; + + if (this.ECPSVDP_DH(U, V, Z, 0) !== 0) { + return M; + } + + for (i = 0; i < 2 * this.EFS + 1; i++) { + VZ[i] = V[i]; + } + + for (i = 0; i < this.EFS; i++) { + VZ[2 * this.EFS + 1 + i] = Z[i]; + } + + K = ctx.HMAC.KDF2(ctx.HMAC.MC_SHA2, sha, VZ, P1, 2 * ctx.ECP.AESKEY); + + for (i = 0; i < ctx.ECP.AESKEY; i++) { + K1[i] = K[i]; + K2[i] = K[ctx.ECP.AESKEY + i]; + } + + M = ctx.AES.CBC_IV0_DECRYPT(K1, C); + + if (M.length === 0) { + return M; + } + + L2 = ctx.HMAC.inttobytes(P2.length, 8); + + AC = []; + + for (i = 0; i < C.length; i++) { + AC[i] = C[i]; + } + for (i = 0; i < P2.length; i++) { + AC[C.length + i] = P2[i]; + } + for (i = 0; i < 8; i++) { + AC[C.length + P2.length + i] = L2[i]; + } + + ctx.HMAC.HMAC1(ctx.HMAC.MC_SHA2, sha, TAG, TAG.length, K2, AC); + + if (!this.ncomp(T, TAG, T.length)) { + return []; + } + + return M; + }, + }; + + return ECDH; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + ECDH: ECDH, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ecp.js b/packages/bls-verify/src/vendor/amcl-js/src/ecp.js new file mode 100644 index 000000000..28dbb0aae --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ecp.js @@ -0,0 +1,1966 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Elliptic Curve Point class */ + +var ECP = function (ctx) { + 'use strict'; + + /* Constructor */ + var ECP = function () { + this.x = new ctx.FP(0); + this.y = new ctx.FP(1); + if (ECP.CURVETYPE != ECP.EDWARDS) { + this.z = new ctx.FP(0); + } else { + this.z = new ctx.FP(1); + } + }; + + ECP.WEIERSTRASS = 0; + ECP.EDWARDS = 1; + ECP.MONTGOMERY = 2; + ECP.NOT = 0; + ECP.BN = 1; + ECP.BLS12 = 2; + ECP.BLS24 = 3; + ECP.BLS48 = 4; + ECP.D_TYPE = 0; + ECP.M_TYPE = 1; + ECP.POSITIVEX = 0; + ECP.NEGATIVEX = 1; + + ECP.CURVETYPE = ctx.config['@CT']; + ECP.CURVE_A = ctx.config['@CA']; + ECP.CURVE_PAIRING_TYPE = ctx.config['@PF']; + ECP.SEXTIC_TWIST = ctx.config['@ST']; + ECP.SIGN_OF_X = ctx.config['@SX']; + ECP.ATE_BITS = ctx.config['@AB']; + ECP.HTC_ISO = ctx.config['@HC']; + ECP.HTC_ISO_G2 = ctx.config['@HC2']; + + ECP.HASH_TYPE = ctx.config['@HT']; + ECP.AESKEY = ctx.config['@AK']; + ECP.ALLOW_ALT_COMPRESS = true; + + ECP.prototype = { + /* test this=O point-at-infinity */ + is_infinity: function () { + if (ECP.CURVETYPE == ECP.EDWARDS) { + return this.x.iszilch() && this.y.equals(this.z); + } else if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + return this.x.iszilch() && this.z.iszilch(); + } else if (ECP.CURVETYPE == ECP.MONTGOMERY) { + return this.z.iszilch(); + } + + return true; + }, + + /* conditional swap of this and Q dependant on d */ + cswap: function (Q, d) { + this.x.cswap(Q.x, d); + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + this.y.cswap(Q.y, d); + } + this.z.cswap(Q.z, d); + }, + + /* conditional move of Q to P dependant on d */ + cmove: function (Q, d) { + this.x.cmove(Q.x, d); + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + this.y.cmove(Q.y, d); + } + this.z.cmove(Q.z, d); + }, + + /* Constant time select from pre-computed table */ + select: function (W, b) { + var MP = new ECP(), + m = b >> 31, + babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + this.cmove(W[0], ECP.teq(babs, 0)); // conditional move + this.cmove(W[1], ECP.teq(babs, 1)); + this.cmove(W[2], ECP.teq(babs, 2)); + this.cmove(W[3], ECP.teq(babs, 3)); + this.cmove(W[4], ECP.teq(babs, 4)); + this.cmove(W[5], ECP.teq(babs, 5)); + this.cmove(W[6], ECP.teq(babs, 6)); + this.cmove(W[7], ECP.teq(babs, 7)); + + MP.copy(this); + MP.neg(); + this.cmove(MP, m & 1); + }, + + /* Test P == Q */ + + equals: function (Q) { + var a, b; + + a = new ctx.FP(0); + b = new ctx.FP(0); + a.copy(this.x); + a.mul(Q.z); + a.reduce(); + b.copy(Q.x); + b.mul(this.z); + b.reduce(); + + if (!a.equals(b)) { + return false; + } + + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + a.copy(this.y); + a.mul(Q.z); + a.reduce(); + b.copy(Q.y); + b.mul(this.z); + b.reduce(); + if (!a.equals(b)) { + return false; + } + } + + return true; + }, + + /* copy this=P */ + copy: function (P) { + this.x.copy(P.x); + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + this.y.copy(P.y); + } + this.z.copy(P.z); + }, + + /* this=-this */ + neg: function () { + if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + this.y.neg(); + this.y.norm(); + } else if (ECP.CURVETYPE == ECP.EDWARDS) { + this.x.neg(); + this.x.norm(); + } + + return; + }, + + /* set this=O */ + inf: function () { + this.x.zero(); + + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + this.y.one(); + } + + if (ECP.CURVETYPE != ECP.EDWARDS) { + this.z.zero(); + } else { + this.z.one(); + } + }, + + /* set this=(x,y) where x and y are BIGs */ + setxy: function (ix, iy) { + var rhs, y2; + + this.x = new ctx.FP(0); + this.x.bcopy(ix); + + this.y = new ctx.FP(0); + this.y.bcopy(iy); + this.z = new ctx.FP(1); + this.x.norm(); + rhs = ECP.RHS(this.x); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + if (rhs.qr(null) != 1) { + this.inf(); + } + } else { + y2 = new ctx.FP(0); + y2.copy(this.y); + y2.sqr(); + + if (!y2.equals(rhs)) { + this.inf(); + } + } + }, + + /* set this=x, where x is ctx.BIG, y is derived from sign s */ + setxi: function (ix, s) { + var rhs, ny; + + this.x = new ctx.FP(0); + this.x.bcopy(ix); + this.x.norm(); + rhs = ECP.RHS(this.x); + this.z = new ctx.FP(1); + var hint = new ctx.FP(0); + if (rhs.qr(hint) == 1) { + ny = rhs.sqrt(hint); + if (ny.sign() != s) { + ny.neg(); + ny.norm(); + } + this.y = ny; + } else { + this.inf(); + } + }, + + /* set this=x, y calculated from curve equation */ + setx: function (ix) { + var rhs; + + this.x = new ctx.FP(0); + this.x.bcopy(ix); + this.x.norm(); + rhs = ECP.RHS(this.x); + this.z = new ctx.FP(1); + var hint = new ctx.FP(0); + + if (rhs.qr(hint) == 1) { + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + this.y = rhs.sqrt(hint); + } + } else { + this.inf(); + } + }, + + /* set this to affine - from (x,y,z) to (x,y) */ + affine: function () { + var one; + + if (this.is_infinity()) { + return; + } + + one = new ctx.FP(1); + + if (this.z.equals(one)) { + return; + } + + this.z.inverse(null); + + if (ECP.CURVETYPE == ECP.EDWARDS || ECP.CURVETYPE == ECP.WEIERSTRASS) { + this.x.mul(this.z); + this.x.reduce(); + this.y.mul(this.z); + this.y.reduce(); + this.z = one; + } + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + this.x.mul(this.z); + this.x.reduce(); + this.z = one; + } + }, + + /* extract x as ctx.BIG */ + getX: function () { + var W = new ECP(); + W.copy(this); + W.affine(); + return W.x.redc(); + }, + + /* extract y as ctx.BIG */ + getY: function () { + var W = new ECP(); + W.copy(this); + W.affine(); + return W.y.redc(); + }, + + /* get sign of Y */ + getS: function () { + var W = new ECP(); + W.copy(this); + W.affine(); + return W.y.sign(); + }, + + /* extract x as ctx.FP */ + getx: function () { + return this.x; + }, + + /* extract y as ctx.FP */ + gety: function () { + return this.y; + }, + + /* extract z as ctx.FP */ + getz: function () { + return this.z; + }, + + /* convert to byte array */ + toBytes: function (b, compress) { + var t = []; + var alt = false; + var W = new ECP(); + W.copy(this); + W.affine(); + W.x.redc().toBytes(t); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + for (i = 0; i < ctx.BIG.MODBYTES; i++) { + b[i] = t[i]; + } + return; + } + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < ctx.BIG.MODBYTES; i++) b[i] = t[i]; + if (compress) { + b[0] |= 0x80; + if (W.y.islarger() == 1) b[0] |= 0x20; + } else { + W.y.redc().toBytes(t); + for (var i = 0; i < ctx.BIG.MODBYTES; i++) b[i + ctx.BIG.MODBYTES] = t[i]; + } + } else { + for (var i = 0; i < ctx.BIG.MODBYTES; i++) b[i + 1] = t[i]; + if (compress) { + b[0] = 0x02; + if (W.y.sign() == 1) b[0] = 0x03; + return; + } + b[0] = 0x04; + W.y.redc().toBytes(t); + for (var i = 0; i < ctx.BIG.MODBYTES; i++) b[i + ctx.BIG.MODBYTES + 1] = t[i]; + } + }, + /* convert to hex string */ + toString: function () { + var W = new ECP(); + W.copy(this); + if (W.is_infinity()) { + return 'infinity'; + } + + W.affine(); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + return '(' + W.x.redc().toString() + ')'; + } else { + return '(' + W.x.redc().toString() + ',' + W.y.redc().toString() + ')'; + } + }, + + /* this+=this */ + dbl: function () { + var t0, t1, t2, t3, x3, y3, z3, b, C, D, H, J, A, B, AA, BB; + + if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + if (ECP.CURVE_A == 0) { + t0 = new ctx.FP(0); + t0.copy(this.y); + t0.sqr(); + t1 = new ctx.FP(0); + t1.copy(this.y); + t1.mul(this.z); + t2 = new ctx.FP(0); + t2.copy(this.z); + t2.sqr(); + + this.z.copy(t0); + this.z.add(t0); + this.z.norm(); + this.z.add(this.z); + this.z.add(this.z); + this.z.norm(); + + t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I); + + x3 = new ctx.FP(0); + x3.copy(t2); + x3.mul(this.z); + y3 = new ctx.FP(0); + y3.copy(t0); + y3.add(t2); + y3.norm(); + this.z.mul(t1); + t1.copy(t2); + t1.add(t2); + t2.add(t1); + t0.sub(t2); + t0.norm(); + y3.mul(t0); + y3.add(x3); + t1.copy(this.x); + t1.mul(this.y); + this.x.copy(t0); + this.x.norm(); + this.x.mul(t1); + this.x.add(this.x); + + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + } else { + t0 = new ctx.FP(0); + t0.copy(this.x); + t1 = new ctx.FP(0); + t1.copy(this.y); + t2 = new ctx.FP(0); + t2.copy(this.z); + t3 = new ctx.FP(0); + t3.copy(this.x); + z3 = new ctx.FP(0); + z3.copy(this.z); + y3 = new ctx.FP(0); + x3 = new ctx.FP(0); + b = new ctx.FP(0); + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + b.rcopy(ctx.ROM_CURVE.CURVE_B); + } + + t0.sqr(); //1 x^2 + t1.sqr(); //2 y^2 + t2.sqr(); //3 + + t3.mul(this.y); //4 + t3.add(t3); + t3.norm(); //5 + z3.mul(this.x); //6 + z3.add(z3); + z3.norm(); //7 + y3.copy(t2); + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + y3.mul(b); //8 + } else { + y3.imul(ctx.ROM_CURVE.CURVE_B_I); + } + + y3.sub(z3); //9 *** + x3.copy(y3); + x3.add(y3); + x3.norm(); //10 + + y3.add(x3); //11 + x3.copy(t1); + x3.sub(y3); + x3.norm(); //12 + y3.add(t1); + y3.norm(); //13 + y3.mul(x3); //14 + x3.mul(t3); //15 + t3.copy(t2); + t3.add(t2); //16 + t2.add(t3); //17 + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + z3.mul(b); //18 + } else { + z3.imul(ctx.ROM_CURVE.CURVE_B_I); + } + + z3.sub(t2); //19 + z3.sub(t0); + z3.norm(); //20 *** + t3.copy(z3); + t3.add(z3); //21 + + z3.add(t3); + z3.norm(); //22 + t3.copy(t0); + t3.add(t0); //23 + t0.add(t3); //24 + t0.sub(t2); + t0.norm(); //25 + + t0.mul(z3); //26 + y3.add(t0); //27 + t0.copy(this.y); + t0.mul(this.z); //28 + t0.add(t0); + t0.norm(); //29 + z3.mul(t0); //30 + x3.sub(z3); //31 + t0.add(t0); + t0.norm(); //32 + t1.add(t1); + t1.norm(); //33 + z3.copy(t0); + z3.mul(t1); //34 + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + } + } + + if (ECP.CURVETYPE == ECP.EDWARDS) { + C = new ctx.FP(0); + C.copy(this.x); + D = new ctx.FP(0); + D.copy(this.y); + H = new ctx.FP(0); + H.copy(this.z); + J = new ctx.FP(0); + + this.x.mul(this.y); + this.x.add(this.x); + this.x.norm(); + C.sqr(); + D.sqr(); + if (ECP.CURVE_A == -1) { + C.neg(); + } + + this.y.copy(C); + this.y.add(D); + this.y.norm(); + H.sqr(); + H.add(H); + + this.z.copy(this.y); + J.copy(this.y); + + J.sub(H); + J.norm(); + + this.x.mul(J); + C.sub(D); + C.norm(); + this.y.mul(C); + this.z.mul(J); + } + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + A = new ctx.FP(0); + A.copy(this.x); + B = new ctx.FP(0); + B.copy(this.x); + AA = new ctx.FP(0); + BB = new ctx.FP(0); + C = new ctx.FP(0); + + A.add(this.z); + A.norm(); + AA.copy(A); + AA.sqr(); + B.sub(this.z); + B.norm(); + BB.copy(B); + BB.sqr(); + C.copy(AA); + C.sub(BB); + C.norm(); + this.x.copy(AA); + this.x.mul(BB); + + A.copy(C); + A.imul((ECP.CURVE_A + 2) >> 2); + + BB.add(A); + BB.norm(); + this.z.copy(BB); + this.z.mul(C); + } + + return; + }, + + /* this+=Q */ + add: function (Q) { + var b, t0, t1, t2, t3, t4, x3, y3, z3, A, B, C, D, E, F, G; + + if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + if (ECP.CURVE_A == 0) { + b = 3 * ctx.ROM_CURVE.CURVE_B_I; + t0 = new ctx.FP(0); + t0.copy(this.x); + t0.mul(Q.x); + t1 = new ctx.FP(0); + t1.copy(this.y); + t1.mul(Q.y); + t2 = new ctx.FP(0); + t2.copy(this.z); + t2.mul(Q.z); + t3 = new ctx.FP(0); + t3.copy(this.x); + t3.add(this.y); + t3.norm(); + t4 = new ctx.FP(0); + t4.copy(Q.x); + t4.add(Q.y); + t4.norm(); + t3.mul(t4); + t4.copy(t0); + t4.add(t1); + + t3.sub(t4); + t3.norm(); + t4.copy(this.y); + t4.add(this.z); + t4.norm(); + x3 = new ctx.FP(0); + x3.copy(Q.y); + x3.add(Q.z); + x3.norm(); + + t4.mul(x3); + x3.copy(t1); + x3.add(t2); + + t4.sub(x3); + t4.norm(); + x3.copy(this.x); + x3.add(this.z); + x3.norm(); + y3 = new ctx.FP(0); + y3.copy(Q.x); + y3.add(Q.z); + y3.norm(); + x3.mul(y3); + y3.copy(t0); + y3.add(t2); + y3.rsub(x3); + y3.norm(); + x3.copy(t0); + x3.add(t0); + t0.add(x3); + t0.norm(); + t2.imul(b); + + z3 = new ctx.FP(0); + z3.copy(t1); + z3.add(t2); + z3.norm(); + t1.sub(t2); + t1.norm(); + y3.imul(b); + + x3.copy(y3); + x3.mul(t4); + t2.copy(t3); + t2.mul(t1); + x3.rsub(t2); + y3.mul(t0); + t1.mul(z3); + y3.add(t1); + t0.mul(t3); + z3.mul(t4); + z3.add(t0); + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + } else { + t0 = new ctx.FP(0); + t0.copy(this.x); + t1 = new ctx.FP(0); + t1.copy(this.y); + t2 = new ctx.FP(0); + t2.copy(this.z); + t3 = new ctx.FP(0); + t3.copy(this.x); + t4 = new ctx.FP(0); + t4.copy(Q.x); + z3 = new ctx.FP(0); + y3 = new ctx.FP(0); + y3.copy(Q.x); + x3 = new ctx.FP(0); + x3.copy(Q.y); + b = new ctx.FP(0); + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + b.rcopy(ctx.ROM_CURVE.CURVE_B); + } + t0.mul(Q.x); //1 + t1.mul(Q.y); //2 + t2.mul(Q.z); //3 + + t3.add(this.y); + t3.norm(); //4 + t4.add(Q.y); + t4.norm(); //5 + t3.mul(t4); //6 + t4.copy(t0); + t4.add(t1); //7 + t3.sub(t4); + t3.norm(); //8 + t4.copy(this.y); + t4.add(this.z); + t4.norm(); //9 + x3.add(Q.z); + x3.norm(); //10 + t4.mul(x3); //11 + x3.copy(t1); + x3.add(t2); //12 + + t4.sub(x3); + t4.norm(); //13 + x3.copy(this.x); + x3.add(this.z); + x3.norm(); //14 + y3.add(Q.z); + y3.norm(); //15 + + x3.mul(y3); //16 + y3.copy(t0); + y3.add(t2); //17 + + y3.rsub(x3); + y3.norm(); //18 + z3.copy(t2); + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + z3.mul(b); //18 + } else { + z3.imul(ctx.ROM_CURVE.CURVE_B_I); + } + + x3.copy(y3); + x3.sub(z3); + x3.norm(); //20 + z3.copy(x3); + z3.add(x3); //21 + + x3.add(z3); //22 + z3.copy(t1); + z3.sub(x3); + z3.norm(); //23 + x3.add(t1); + x3.norm(); //24 + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + y3.mul(b); //18 + } else { + y3.imul(ctx.ROM_CURVE.CURVE_B_I); + } + + t1.copy(t2); + t1.add(t2); //26 + t2.add(t1); //27 + + y3.sub(t2); //28 + + y3.sub(t0); + y3.norm(); //29 + t1.copy(y3); + t1.add(y3); //30 + y3.add(t1); + y3.norm(); //31 + + t1.copy(t0); + t1.add(t0); //32 + t0.add(t1); //33 + t0.sub(t2); + t0.norm(); //34 + t1.copy(t4); + t1.mul(y3); //35 + t2.copy(t0); + t2.mul(y3); //36 + y3.copy(x3); + y3.mul(z3); //37 + y3.add(t2); //38 + x3.mul(t3); //39 + x3.sub(t1); //40 + z3.mul(t4); //41 + t1.copy(t3); + t1.mul(t0); //42 + z3.add(t1); + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + } + } + + if (ECP.CURVETYPE == ECP.EDWARDS) { + A = new ctx.FP(0); + A.copy(this.z); + B = new ctx.FP(0); + C = new ctx.FP(0); + C.copy(this.x); + D = new ctx.FP(0); + D.copy(this.y); + E = new ctx.FP(0); + F = new ctx.FP(0); + G = new ctx.FP(0); + + A.mul(Q.z); //A=2 + B.copy(A); + B.sqr(); //B=2 + C.mul(Q.x); //C=2 + D.mul(Q.y); //D=2 + + E.copy(C); + E.mul(D); //E=2 + + if (ctx.ROM_CURVE.CURVE_B_I == 0) { + b = new ctx.FP(0); + b.rcopy(ctx.ROM_CURVE.CURVE_B); + E.mul(b); + } else { + E.imul(ctx.ROM_CURVE.CURVE_B_I); //E=22222 + } + + F.copy(B); + F.sub(E); //F=22224 + G.copy(B); + G.add(E); //G=22224 + + if (ECP.CURVE_A == 1) { + E.copy(D); + E.sub(C); //E=4 + } + C.add(D); //C=4 + + B.copy(this.x); + B.add(this.y); //B=4 + D.copy(Q.x); + D.add(Q.y); + B.norm(); + D.norm(); //D=4 + B.mul(D); //B=2 + B.sub(C); + B.norm(); + F.norm(); // B=6 + B.mul(F); //B=2 + this.x.copy(A); + this.x.mul(B); + G.norm(); // x=2 + + if (ECP.CURVE_A == 1) { + E.norm(); + C.copy(E); + C.mul(G); //C=2 + } + + if (ECP.CURVE_A == -1) { + C.norm(); + C.mul(G); + } + + this.y.copy(A); + this.y.mul(C); //y=2 + this.z.copy(F); + this.z.mul(G); + } + + return; + }, + + /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ + dadd: function (Q, W) { + var A, B, C, D, DA, CB; + + A = new ctx.FP(0); + A.copy(this.x); + B = new ctx.FP(0); + B.copy(this.x); + C = new ctx.FP(0); + C.copy(Q.x); + D = new ctx.FP(0); + D.copy(Q.x); + DA = new ctx.FP(0); + CB = new ctx.FP(0); + + A.add(this.z); + B.sub(this.z); + + C.add(Q.z); + D.sub(Q.z); + + D.norm(); + A.norm(); + DA.copy(D); + DA.mul(A); + C.norm(); + B.norm(); + CB.copy(C); + CB.mul(B); + + A.copy(DA); + A.add(CB); + A.norm(); + A.sqr(); + B.copy(DA); + B.sub(CB); + B.norm(); + B.sqr(); + + this.x.copy(A); + this.z.copy(W.x); + this.z.mul(B); + + // this.x.norm(); + }, + + /* this-=Q */ + sub: function (Q) { + var NQ = new ECP(); + NQ.copy(Q); + NQ.neg(); + this.add(NQ); + }, + + /* constant time multiply by small integer of length bts - use ladder */ + pinmul: function (e, bts) { + var i, b, P, R0, R1; + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + return this.mul(new ctx.BIG(e)); + } else { + P = new ECP(); + R0 = new ECP(); + R1 = new ECP(); + R1.copy(this); + + for (i = bts - 1; i >= 0; i--) { + b = (e >> i) & 1; + P.copy(R1); + P.add(R0); + R0.cswap(R1, b); + R1.copy(P); + R0.dbl(); + R0.cswap(R1, b); + } + + P.copy(R0); + + return P; + } + }, + + // multiply this by the curves cofactor + cfp: function () { + var cf = ctx.ROM_CURVE.CURVE_Cof_I, + c = new ctx.BIG(0); + + if (cf == 1) { + return; + } + if (cf == 4) { + this.dbl(); + this.dbl(); + return; + } + if (cf == 8) { + this.dbl(); + this.dbl(); + this.dbl(); + return; + } + c.rcopy(ctx.ROM_CURVE.CURVE_Cof); + this.copy(this.mul(c)); + }, + + /* return e.this - SPA immune, using Ladder */ + mul: function (e) { + var P, D, R0, R1, mt, t, Q, C, W, w, i, b, nb, s, ns; + + if (e.iszilch() || this.is_infinity()) { + return new ECP(); + } + + P = new ECP(); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + /* use ladder */ + D = new ECP(); + R0 = new ECP(); + R0.copy(this); + R1 = new ECP(); + R1.copy(this); + R1.dbl(); + D.copy(this); + D.affine(); + nb = e.nbits(); + for (i = nb - 2; i >= 0; i--) { + b = e.bit(i); + P.copy(R1); + P.dadd(R0, D); + + R0.cswap(R1, b); + R1.copy(P); + R0.dbl(); + R0.cswap(R1, b); + } + P.copy(R0); + } else { + // fixed size windows + mt = new ctx.BIG(); + t = new ctx.BIG(); + Q = new ECP(); + C = new ECP(); + W = []; + w = []; + + // precompute table + Q.copy(this); + Q.dbl(); + W[0] = new ECP(); + W[0].copy(this); + + for (i = 1; i < 8; i++) { + W[i] = new ECP(); + W[i].copy(W[i - 1]); + W[i].add(Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(e); + s = t.parity(); + t.inc(1); + t.norm(); + ns = t.parity(); + mt.copy(t); + mt.inc(1); + mt.norm(); + t.cmove(mt, s); + Q.cmove(this, ns); + C.copy(Q); + + nb = 1 + Math.floor((t.nbits() + 3) / 4); + + // convert exponent to signed 4-bit window + for (i = 0; i < nb; i++) { + w[i] = t.lastbits(5) - 16; + t.dec(w[i]); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5); + + P.copy(W[Math.floor((w[nb] - 1) / 2)]); + for (i = nb - 1; i >= 0; i--) { + Q.select(W, w[i]); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(Q); + } + P.sub(C); + } + + return P; + }, + + /* Return e.this+f.Q */ + + mul2: function (e, Q, f) { + var te = new ctx.BIG(), + tf = new ctx.BIG(), + mt = new ctx.BIG(), + S = new ECP(), + T = new ECP(), + C = new ECP(), + W = [], + w = [], + i, + s, + ns, + nb, + a, + b; + + te.copy(e); + tf.copy(f); + + // precompute table + W[1] = new ECP(); + W[1].copy(this); + W[1].sub(Q); + W[2] = new ECP(); + W[2].copy(this); + W[2].add(Q); + S.copy(Q); + S.dbl(); + W[0] = new ECP(); + W[0].copy(W[1]); + W[0].sub(S); + W[3] = new ECP(); + W[3].copy(W[2]); + W[3].add(S); + T.copy(this); + T.dbl(); + W[5] = new ECP(); + W[5].copy(W[1]); + W[5].add(T); + W[6] = new ECP(); + W[6].copy(W[2]); + W[6].add(T); + W[4] = new ECP(); + W[4].copy(W[5]); + W[4].sub(S); + W[7] = new ECP(); + W[7].copy(W[6]); + W[7].add(S); + + // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction + + s = te.parity(); + te.inc(1); + te.norm(); + ns = te.parity(); + mt.copy(te); + mt.inc(1); + mt.norm(); + te.cmove(mt, s); + T.cmove(this, ns); + C.copy(T); + + s = tf.parity(); + tf.inc(1); + tf.norm(); + ns = tf.parity(); + mt.copy(tf); + mt.inc(1); + mt.norm(); + tf.cmove(mt, s); + S.cmove(Q, ns); + C.add(S); + + mt.copy(te); + mt.add(tf); + mt.norm(); + nb = 1 + Math.floor((mt.nbits() + 1) / 2); + + // convert exponent to signed 2-bit window + for (i = 0; i < nb; i++) { + a = te.lastbits(3) - 4; + te.dec(a); + te.norm(); + te.fshr(2); + b = tf.lastbits(3) - 4; + tf.dec(b); + tf.norm(); + tf.fshr(2); + w[i] = 4 * a + b; + } + w[nb] = 4 * te.lastbits(3) + tf.lastbits(3); + S.copy(W[Math.floor((w[nb] - 1) / 2)]); + + for (i = nb - 1; i >= 0; i--) { + T.select(W, w[i]); + S.dbl(); + S.dbl(); + S.add(T); + } + S.sub(C); /* apply correction */ + + return S; + }, + }; + + // set to group generator + ECP.generator = function () { + var G = new ECP(), + gx = new ctx.BIG(0), + gy = new ctx.BIG(0); + + gx.rcopy(ctx.ROM_CURVE.CURVE_Gx); + + if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) { + gy.rcopy(ctx.ROM_CURVE.CURVE_Gy); + G.setxy(gx, gy); + } else { + G.setx(gx); + } + return G; + }; + + /* return 1 if b==c, no branching */ + ECP.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* convert from byte array to ECP */ + ECP.fromBytes = function (b) { + var t = [], + P = new ECP(), + p = new ctx.BIG(0), + px, + py, + i; + var alt = false; + + p.rcopy(ctx.ROM_FIELD.Modulus); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + for (i = 0; i < ctx.BIG.MODBYTES; i++) { + t[i] = b[i]; + } + px = ctx.BIG.fromBytes(t); + if (ctx.BIG.comp(px, p) >= 0) { + return P; + } + P.setx(px); + return P; + } + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (i = 0; i < ctx.BIG.MODBYTES; i++) t[i] = b[i]; + t[0] &= 0x1f; + px = ctx.BIG.fromBytes(t); + if ((b[0] & 0x80) == 0) { + for (i = 0; i < ctx.BIG.MODBYTES; i++) t[i] = b[i + ctx.BIG.MODBYTES]; + py = ctx.BIG.fromBytes(t); + P.setxy(px, py); + return P; + } else { + var sgn = (b[0] & 0x20) >> 5; + P.setxi(px, 0); + var cmp = P.y.islarger(); + if ((sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1)) P.neg(); + return P; + } + } else { + for (i = 0; i < ctx.BIG.MODBYTES; i++) { + t[i] = b[i + 1]; + } + px = ctx.BIG.fromBytes(t); + if (ctx.BIG.comp(px, p) >= 0) { + return P; + } + + if (b[0] == 0x04) { + for (i = 0; i < ctx.BIG.MODBYTES; i++) { + t[i] = b[i + ctx.BIG.MODBYTES + 1]; + } + + py = ctx.BIG.fromBytes(t); + + if (ctx.BIG.comp(py, p) >= 0) { + return P; + } + + P.setxy(px, py); + + return P; + } + + if (b[0] == 0x02 || b[0] == 0x03) { + P.setxi(px, b[0] & 1); + return P; + } + } + + return P; + }; + + /* Calculate RHS of curve equation */ + ECP.RHS = function (x) { + var r = new ctx.FP(0), + b, + cx, + one, + x3; + + //x.norm(); + r.copy(x); + r.sqr(); + + if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + // x^3+Ax+B + b = new ctx.FP(0); + b.rcopy(ctx.ROM_CURVE.CURVE_B); + r.mul(x); + if (ECP.CURVE_A == -3) { + cx = new ctx.FP(0); + cx.copy(x); + cx.imul(3); + cx.neg(); + cx.norm(); + r.add(cx); + } + r.add(b); + } else if (ECP.CURVETYPE == ECP.EDWARDS) { + // (Ax^2-1)/(Bx^2-1) + b = new ctx.FP(0); + b.rcopy(ctx.ROM_CURVE.CURVE_B); + + one = new ctx.FP(1); + b.mul(r); + b.sub(one); + b.norm(); + if (ECP.CURVE_A == -1) { + r.neg(); + } + r.sub(one); + r.norm(); + b.inverse(null); + + r.mul(b); + } else if (ECP.CURVETYPE == ECP.MONTGOMERY) { + // x^3+Ax^2+x + x3 = new ctx.FP(0); + x3.copy(r); + x3.mul(x); + r.imul(ECP.CURVE_A); + r.add(x3); + r.add(x); + } + + r.reduce(); + + return r; + }; + + // Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i + ECP.muln = function (n, X, e) { + var B = []; + var P = new ECP(); + var R = new ECP(); + var S = new ECP(); + var t = new ctx.BIG(); + var mr = new ctx.BIG(); + + for (var i = 0; i < 16; i++) { + B[i] = new ECP(); + } + var mt = new ctx.BIG(); + mt.copy(e[0]); + mt.norm(); + for (var i = 1; i < n; i++) { + // find biggest + t.copy(e[i]); + t.norm(); + var k = ctx.BIG.comp(t, mt); + mt.cmove(t, (k + 1) >> 1); + } + var nb = (mt.nbits() + 3) >> 2; + for (var i = nb - 1; i >= 0; i--) { + for (var j = 0; j < 16; j++) { + B[j].inf(); + } + for (var j = 0; j < n; j++) { + mt.copy(e[j]); + mt.norm(); + mt.shr(4 * i); + var k = mt.lastbits(4); + B[k].add(X[j]); + } + R.inf(); + S.inf(); + for (var j = 15; j >= 1; j--) { + R.add(B[j]); + S.add(R); + } + for (var j = 0; j < 4; j++) { + P.dbl(); + } + P.add(S); + } + return P; + }; + + /* Hunt and Peck a BIG to a curve point + ECP.hap2point = function(h) { + var P = new ECP(); + var x=new ctx.BIG(h); + for (;;) { + if (ECP.CURVETYPE != ECP.MONTGOMERY) { + P.setxi(x, 0); + } else { + P.setx(x); + } + x.inc(1); + x.norm(); + if (!P.is_infinity()) break; + } + return P; + }; */ + + /* Constant time Map to Point */ + ECP.map2point = function (h) { + var P = new ECP(); + + if (ECP.CURVETYPE == ECP.MONTGOMERY) { + var X1 = new ctx.FP(0); + var X2 = new ctx.FP(0); + var t = new ctx.FP(h); + var w = new ctx.FP(0); + var one = new ctx.FP(1); + var N = new ctx.FP(0); + var D = new ctx.FP(0); + var hint = new ctx.FP(0); + var A = new ctx.FP(ECP.CURVE_A); + t.sqr(); + + if (ctx.FP.PM1D2 == 2) { + t.add(t); + } + if (ctx.FP.PM1D2 == 1) { + t.neg(); + } + if (ctx.FP.PM1D2 > 2) { + t.imul(ctx.FP.PM1D2); + } + t.norm(); + D.copy(t); + D.add(one); + D.norm(); + + X1.copy(A); + X1.neg(); + X1.norm(); + X2.copy(X1); + X2.mul(t); + + w.copy(X1); + w.sqr(); + N.copy(w); + N.mul(X1); + w.mul(A); + w.mul(D); + N.add(w); + t.copy(D); + t.sqr(); + t.mul(X1); + N.add(t); + N.norm(); + + t.copy(N); + t.mul(D); + var qres = t.qr(hint); + w.copy(t); + w.inverse(hint); + D.copy(w); + D.mul(N); + X1.mul(D); + X2.mul(D); + X1.cmove(X2, 1 - qres); + + var a = X1.redc(); + P.setx(a); + } + if (ECP.CURVETYPE == ECP.EDWARDS) { + // Elligator 2 - map to Montgomery, place point, map back + var X1 = new ctx.FP(0); + var X2 = new ctx.FP(0); + var t = new ctx.FP(h); + var w = new ctx.FP(0); + var one = new ctx.FP(1); + var A = new ctx.FP(0); + var w1 = new ctx.FP(0); + var w2 = new ctx.FP(0); + var B = new ctx.FP(0); + B.rcopy(ctx.ROM_CURVE.CURVE_B); + var Y = new ctx.FP(0); + var K = new ctx.FP(0); + var D = new ctx.FP(0); + var hint = new ctx.FP(0); + //var Y3 = new ctx.FP(0); + + var qres, + qnr, + rfc = 0; + + if (ctx.FP.MODTYPE != ctx.FP.GENERALISED_MERSENNE) { + A.copy(B); + if (ECP.CURVE_A == 1) { + A.add(one); + B.sub(one); + } else { + A.sub(one); + B.add(one); + } + A.norm(); + B.norm(); + + A.div2(); + B.div2(); + B.div2(); + + K.copy(B); + K.neg(); + K.norm(); + //K.inverse(null); + K.invsqrt(K, w1); + + rfc = ctx.FP.RIADZ; + if (rfc == 1) { + // RFC7748 + A.mul(K); + K.mul(w1); + //K=K.sqrt(null); + } else { + B.sqr(); + } + } else { + A.copy(new ctx.FP(156326)); + rfc = 1; + } + + t.sqr(); + if (ctx.FP.PM1D2 == 2) { + t.add(t); + qnr = 2; + } + if (ctx.FP.PM1D2 == 1) { + t.neg(); + qnr = -1; + } + if (ctx.FP.PM1D2 > 2) { + t.imul(ctx.FP.PM1D2); + qnr = ctx.FP.PM1D2; + } + t.norm(); + D.copy(t); + D.add(one); + D.norm(); + X1.copy(A); + X1.neg(); + X1.norm(); + X2.copy(X1); + X2.mul(t); + + // Figure out RHS of Montgomery curve in rational form gx1/d^3 + + w.copy(X1); + w.sqr(); + w1.copy(w); + w1.mul(X1); + w.mul(A); + w.mul(D); + w1.add(w); + w2.copy(D); + w2.sqr(); + + if (rfc == 0) { + w.copy(X1); + w.mul(B); + w2.mul(w); + w1.add(w2); + } else { + w2.mul(X1); + w1.add(w2); + } + w1.norm(); + + B.copy(w1); + B.mul(D); + qres = B.qr(hint); + w.copy(B); + w.inverse(hint); + D.copy(w); + D.mul(w1); + X1.mul(D); + X2.mul(D); + D.sqr(); + + w1.copy(B); + w1.imul(qnr); + w.rcopy(ctx.ROM_CURVE.CURVE_HTPC); + w.mul(hint); + w2.copy(D); + w2.mul(h); + + X1.cmove(X2, 1 - qres); + B.cmove(w1, 1 - qres); + hint.cmove(w, 1 - qres); + D.cmove(w2, 1 - qres); + + Y.copy(B.sqrt(hint)); + Y.mul(D); + + /* + Y.copy(B.sqrt(hint)); + Y.mul(D); + + B.imul(qnr); + w.rcopy(ctx.ROM_CURVE.CURVE_HTPC); + hint.mul(w); + + Y3.copy(B.sqrt(hint)); + D.mul(h); + Y3.mul(D); + + X1.cmove(X2,1-qres); + Y.cmove(Y3,1-qres); +*/ + w.copy(Y); + w.neg(); + w.norm(); + Y.cmove(w, qres ^ Y.sign()); + + if (rfc == 0) { + X1.mul(K); + Y.mul(K); + } + + if (ctx.FP.MODTYPE == ctx.FP.GENERALISED_MERSENNE) { + // GOLDILOCKS isogeny + t.copy(X1); + t.sqr(); + w.copy(t); + w.add(one); + w.norm(); + t.sub(one); + t.norm(); + w1.copy(t); + w1.mul(Y); + w1.add(w1); + X2.copy(w1); + X2.add(w1); + X2.norm(); + t.sqr(); + Y.sqr(); + Y.add(Y); + Y.add(Y); + Y.norm(); + B.copy(t); + B.add(Y); + B.norm(); + + w2.copy(Y); + w2.sub(t); + w2.norm(); + w2.mul(X1); + t.mul(X1); + Y.div2(); + w1.copy(Y); + w1.mul(w); + w1.rsub(t); + w1.norm(); + + t.copy(X2); + t.mul(w1); + P = new ECP(); + P.x.copy(t); + t.copy(w2); + t.mul(B); + P.y.copy(t); + t.copy(w1); + t.mul(B); + P.z.copy(t); + + return P; + } else { + w1.copy(X1); + w1.add(one); + w1.norm(); + w2.copy(X1); + w2.sub(one); + w2.norm(); + t.copy(w1); + t.mul(Y); + X1.mul(w1); + + if (rfc == 1) X1.mul(K); + + Y.mul(w2); + P = new ECP(); + P.x.copy(X1); + P.y.copy(Y); + P.z.copy(t); + + return P; + } + } + if (ECP.CURVETYPE == ECP.WEIERSTRASS) { + // swu method + var A = new ctx.FP(0); + var B = new ctx.FP(0); + var X1 = new ctx.FP(0); + var X2 = new ctx.FP(0); + var X3 = new ctx.FP(0); + var one = new ctx.FP(1); + var Y = new ctx.FP(0); + var D = new ctx.FP(0); + var t = new ctx.FP(h); + var w = new ctx.FP(0); + var D2 = new ctx.FP(0); + var hint = new ctx.FP(0); + var GX1 = new ctx.FP(0); + //var Y3=new ctx.FP(0); + var sgn = t.sign(); + + if (ECP.CURVE_A != 0 || ECP.HTC_ISO != 0) { + if (ECP.HTC_ISO != 0) { + A.rcopy(ctx.ROM_CURVE.CURVE_Ad); + B.rcopy(ctx.ROM_CURVE.CURVE_Bd); + } else { + A.copy(new ctx.FP(ECP.CURVE_A)); + B.rcopy(ctx.ROM_CURVE.CURVE_B); + } + // SSWU Method + t.sqr(); + t.imul(ctx.FP.RIADZ); + w.copy(t); + w.add(one); + w.norm(); + + w.mul(t); + D.copy(A); + D.mul(w); + + w.add(one); + w.norm(); + w.mul(B); + w.neg(); + w.norm(); + + X2.copy(w); + X3.copy(t); + X3.mul(X2); + + // x^3+Ad^2x+Bd^3 + GX1.copy(X2); + GX1.sqr(); + D2.copy(D); + D2.sqr(); + w.copy(A); + w.mul(D2); + GX1.add(w); + GX1.norm(); + GX1.mul(X2); + D2.mul(D); + w.copy(B); + w.mul(D2); + GX1.add(w); + GX1.norm(); + + w.copy(GX1); + w.mul(D); + var qr = w.qr(hint); + D.copy(w); + D.inverse(hint); + D.mul(GX1); + X2.mul(D); + X3.mul(D); + t.mul(h); + D2.copy(D); + D2.sqr(); + + D.copy(D2); + D.mul(t); + t.copy(w); + t.imul(ctx.FP.RIADZ); + X1.rcopy(ctx.ROM_CURVE.CURVE_HTPC); + X1.mul(hint); + + X2.cmove(X3, 1 - qr); + D2.cmove(D, 1 - qr); + w.cmove(t, 1 - qr); + hint.cmove(X1, 1 - qr); + + Y.copy(w.sqrt(hint)); + Y.mul(D2); + + /* + Y.copy(w.sqrt(hint)); + Y.mul(D2); + + D2.mul(t); + w.imul(ctx.FP.RIADZ); + + X1.rcopy(ctx.ROM_CURVE.CURVE_HTPC); + hint.mul(X1); + + Y3.copy(w.sqrt(hint)); + Y3.mul(D2); + + X2.cmove(X3,1-qr); + Y.cmove(Y3,1-qr); +*/ + var ne = Y.sign() ^ sgn; + w.copy(Y); + w.neg(); + w.norm(); + Y.cmove(w, ne); + + if (ECP.HTC_ISO != 0) { + var k = 0; + var isox = ECP.HTC_ISO; + var isoy = (3 * (isox - 1)) / 2; + // xnum + var xnum = new ctx.FP(0); + xnum.rcopy(ctx.ROM_CURVE.PC[k++]); + for (var i = 0; i < isox; i++) { + xnum.mul(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + xnum.add(w); + xnum.norm(); + } + // xden + var xden = new ctx.FP(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + xden.add(w); + xden.norm(); + for (var i = 0; i < isox - 2; i++) { + xden.mul(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + xden.add(w); + xden.norm(); + } + // ynum + var ynum = new ctx.FP(0); + ynum.rcopy(ctx.ROM_CURVE.PC[k++]); + for (var i = 0; i < isoy; i++) { + ynum.mul(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + ynum.add(w); + ynum.norm(); + } + // yden + var yden = new ctx.FP(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + yden.add(w); + yden.norm(); + for (var i = 0; i < isoy - 1; i++) { + yden.mul(X2); + w.rcopy(ctx.ROM_CURVE.PC[k++]); + yden.add(w); + yden.norm(); + } + ynum.mul(Y); + w.copy(xnum); + w.mul(yden); + P.x.copy(w); + w.copy(ynum); + w.mul(xden); + P.y.copy(w); + w.copy(xden); + w.mul(yden); + P.z.copy(w); + return P; + } else { + var x = X2.redc(); + var y = Y.redc(); + P.setxy(x, y); + return P; + } + } else { + // Shallue and van de Woestijne + var Z = ctx.FP.RIADZ; + X1.copy(new ctx.FP(Z)); + X3.copy(X1); + var A = ECP.RHS(X1); + B.rcopy(ctx.ROM_FIELD.SQRTm3); + B.imul(Z); + + t.sqr(); + Y.copy(A); + Y.mul(t); + t.copy(one); + t.add(Y); + t.norm(); + Y.rsub(one); + Y.norm(); + D.copy(t); + D.mul(Y); + D.mul(B); + + var w = new ctx.FP(A); + ctx.FP.tpo(D, w); + + w.mul(B); + if (w.sign() == 1) { + w.neg(); + w.norm(); + } + w.mul(B); + w.mul(h); + w.mul(Y); + w.mul(D); + + X1.neg(); + X1.norm(); + X1.div2(); + X2.copy(X1); + X1.sub(w); + X1.norm(); + X2.add(w); + X2.norm(); + A.add(A); + A.add(A); + A.norm(); + t.sqr(); + t.mul(D); + t.sqr(); + A.mul(t); + X3.add(A); + X3.norm(); + + var rhs = ECP.RHS(X2); + X3.cmove(X2, rhs.qr(null)); + rhs.copy(ECP.RHS(X1)); + X3.cmove(X1, rhs.qr(null)); + rhs.copy(ECP.RHS(X3)); + Y.copy(rhs.sqrt(null)); + + var ne = Y.sign() ^ sgn; + w.copy(Y); + w.neg(); + w.norm(); + Y.cmove(w, ne); + + var x = X3.redc(); + var y = Y.redc(); + P.setxy(x, y); + return P; + } + } + return P; + }; + + /* + ECP.mapit = function(h) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var dx = ctx.DBIG.fromBytes(h); + var x=dx.mod(q); + var P=ctx.ECP.hap2point(x); + P.cfp(); + return P; + }; +*/ + return ECP; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.ECP = ECP; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ecp2.js b/packages/bls-verify/src/vendor/amcl-js/src/ecp2.js new file mode 100644 index 000000000..544ca7601 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ecp2.js @@ -0,0 +1,1094 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Weierstrass elliptic curve functions over ctx.FP2 */ + +var ECP2 = function (ctx) { + 'use strict'; + + /* Constructor, set this=O */ + var ECP2 = function () { + this.x = new ctx.FP2(0); + this.y = new ctx.FP2(1); + this.z = new ctx.FP2(0); + }; + + ECP2.prototype = { + /* Test this=O? */ + is_infinity: function () { + return this.x.iszilch() && this.z.iszilch(); + }, + + /* copy this=P */ + copy: function (P) { + this.x.copy(P.x); + this.y.copy(P.y); + this.z.copy(P.z); + }, + + /* set this=O */ + inf: function () { + this.x.zero(); + this.y.one(); + this.z.zero(); + }, + + /* conditional move of Q to P dependant on d */ + cmove: function (Q, d) { + this.x.cmove(Q.x, d); + this.y.cmove(Q.y, d); + this.z.cmove(Q.z, d); + }, + + /* Constant time select from pre-computed table */ + select: function (W, b) { + var MP = new ECP2(), + m, + babs; + + (m = b >> 31), (babs = (b ^ m) - m); + babs = (babs - 1) / 2; + + this.cmove(W[0], ECP2.teq(babs, 0)); // conditional move + this.cmove(W[1], ECP2.teq(babs, 1)); + this.cmove(W[2], ECP2.teq(babs, 2)); + this.cmove(W[3], ECP2.teq(babs, 3)); + this.cmove(W[4], ECP2.teq(babs, 4)); + this.cmove(W[5], ECP2.teq(babs, 5)); + this.cmove(W[6], ECP2.teq(babs, 6)); + this.cmove(W[7], ECP2.teq(babs, 7)); + + MP.copy(this); + MP.neg(); + this.cmove(MP, m & 1); + }, + + /* Test P == Q */ + equals: function (Q) { + var a, b; + + a = new ctx.FP2(0); + a.copy(this.x); + b = new ctx.FP2(0); + b.copy(Q.x); + + a.copy(this.x); + a.mul(Q.z); + a.reduce(); + b.copy(Q.x); + b.mul(this.z); + b.reduce(); + if (!a.equals(b)) { + return false; + } + + a.copy(this.y); + a.mul(Q.z); + a.reduce(); + b.copy(Q.y); + b.mul(this.z); + b.reduce(); + if (!a.equals(b)) { + return false; + } + + return true; + }, + + /* set this=-this */ + neg: function () { + this.y.norm(); + this.y.neg(); + this.y.norm(); + return; + }, + + /* convert this to affine, from (x,y,z) to (x,y) */ + affine: function () { + var one; + + if (this.is_infinity()) { + return; + } + + one = new ctx.FP2(1); + + if (this.z.equals(one)) { + this.x.reduce(); + this.y.reduce(); + return; + } + + this.z.inverse(null); + + this.x.mul(this.z); + this.x.reduce(); + this.y.mul(this.z); + this.y.reduce(); + this.z.copy(one); + }, + + /* extract affine x as ctx.FP2 */ + getX: function () { + var W = new ECP2(); + W.copy(this); + W.affine(); + return W.x; + }, + + /* extract affine y as ctx.FP2 */ + getY: function () { + var W = new ECP2(); + W.copy(this); + W.affine(); + return W.y; + }, + + /* extract projective x */ + getx: function () { + return this.x; + }, + + /* extract projective y */ + gety: function () { + return this.y; + }, + + /* extract projective z */ + getz: function () { + return this.z; + }, + + /* convert this to byte array */ + toBytes: function (b, compress) { + var t = []; + var alt = false; + var W = new ECP2(); + W.copy(this); + W.affine(); + W.x.toBytes(t); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ctx.ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) b[i] = t[i]; + if (!compress) { + W.y.toBytes(t); + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) b[i + 2 * ctx.BIG.MODBYTES] = t[i]; + } else { + b[0] |= 0x80; + if (W.y.islarger() == 1) b[0] |= 0x20; + } + } else { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) b[i + 1] = t[i]; + if (!compress) { + b[0] = 0x04; + W.y.toBytes(t); + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) b[i + 2 * ctx.BIG.MODBYTES + 1] = t[i]; + } else { + b[0] = 0x02; + if (W.y.sign() == 1) b[0] = 0x03; + } + } + }, + + /* convert this to hex string */ + toString: function () { + var W = new ECP2(); + W.copy(this); + if (W.is_infinity()) { + return 'infinity'; + } + W.affine(); + return '(' + W.x.toString() + ',' + W.y.toString() + ')'; + }, + + /* set this=(x,y) */ + setxy: function (ix, iy) { + var rhs, y2; + + this.x.copy(ix); + this.y.copy(iy); + this.z.one(); + this.x.norm(); + + rhs = ECP2.RHS(this.x); + + y2 = new ctx.FP2(this.y); + y2.sqr(); + + if (!y2.equals(rhs)) { + this.inf(); + } + }, + + /* set this=(x,.) */ + setx: function (ix, s) { + var rhs, h; + + this.x.copy(ix); + this.z.one(); + this.x.norm(); + + rhs = ECP2.RHS(this.x); + //alert("Into setx= rhs= "+rhs.toString()); + if (rhs.qr(h) == 1) { + rhs.sqrt(h); + if (rhs.sign() != s) rhs.neg(); + rhs.reduce(); + this.y.copy(rhs); + } else { + this.inf(); + } + }, + + /* set this*=q, where q is Modulus, using Frobenius */ + frob: function (X) { + var X2; + + X2 = new ctx.FP2(X); //X2.copy(X); + X2.sqr(); + this.x.conj(); + this.y.conj(); + this.z.conj(); + this.z.reduce(); + this.x.mul(X2); + this.y.mul(X2); + this.y.mul(X); + }, + + /* this+=this */ + dbl: function () { + var iy, t0, t1, t2, x3, y3; + + iy = new ctx.FP2(0); + iy.copy(this.y); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + iy.mul_ip(); + iy.norm(); + } + + t0 = new ctx.FP2(0); + t0.copy(this.y); + t0.sqr(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.mul_ip(); + } + t1 = new ctx.FP2(0); + t1.copy(iy); + t1.mul(this.z); + t2 = new ctx.FP2(0); + t2.copy(this.z); + t2.sqr(); + + this.z.copy(t0); + this.z.add(t0); + this.z.norm(); + this.z.add(this.z); + this.z.add(this.z); + this.z.norm(); + + t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.mul_ip(); + t2.norm(); + } + + x3 = new ctx.FP2(0); + x3.copy(t2); + x3.mul(this.z); + + y3 = new ctx.FP2(0); + y3.copy(t0); + + y3.add(t2); + y3.norm(); + this.z.mul(t1); + t1.copy(t2); + t1.add(t2); + t2.add(t1); + t2.norm(); + t0.sub(t2); + t0.norm(); //y^2-9bz^2 + y3.mul(t0); + y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 + t1.copy(this.x); + t1.mul(iy); // + this.x.copy(t0); + this.x.norm(); + this.x.mul(t1); + this.x.add(this.x); //(y^2-9bz^2)xy2 + + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + + return 1; + }, + + /* this+=Q - return 0 for add, 1 for double, -1 for O */ + /* this+=Q */ + add: function (Q) { + var b, t0, t1, t2, t3, t4, x3, y3, z3; + + b = 3 * ctx.ROM_CURVE.CURVE_B_I; + t0 = new ctx.FP2(0); + t0.copy(this.x); + t0.mul(Q.x); // x.Q.x + t1 = new ctx.FP2(0); + t1.copy(this.y); + t1.mul(Q.y); // y.Q.y + + t2 = new ctx.FP2(0); + t2.copy(this.z); + t2.mul(Q.z); + t3 = new ctx.FP2(0); + t3.copy(this.x); + t3.add(this.y); + t3.norm(); //t3=X1+Y1 + t4 = new ctx.FP2(0); + t4.copy(Q.x); + t4.add(Q.y); + t4.norm(); //t4=X2+Y2 + t3.mul(t4); //t3=(X1+Y1)(X2+Y2) + t4.copy(t0); + t4.add(t1); //t4=X1.X2+Y1.Y2 + + t3.sub(t4); + t3.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t3.mul_ip(); + t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 + } + + t4.copy(this.y); + t4.add(this.z); + t4.norm(); //t4=Y1+Z1 + x3 = new ctx.FP2(0); + x3.copy(Q.y); + x3.add(Q.z); + x3.norm(); //x3=Y2+Z2 + + t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2) + x3.copy(t1); // + x3.add(t2); //X3=Y1.Y2+Z1.Z2 + + t4.sub(x3); + t4.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t4.mul_ip(); + t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 + } + + x3.copy(this.x); + x3.add(this.z); + x3.norm(); // x3=X1+Z1 + y3 = new ctx.FP2(0); + y3.copy(Q.x); + y3.add(Q.z); + y3.norm(); // y3=X2+Z2 + x3.mul(y3); // x3=(X1+Z1)(X2+Z2) + y3.copy(t0); + y3.add(t2); // y3=X1.X2+Z1+Z2 + y3.rsub(x3); + y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.mul_ip(); + t0.norm(); // x.Q.x + t1.mul_ip(); + t1.norm(); // y.Q.y + } + + x3.copy(t0); + x3.add(t0); + t0.add(x3); + t0.norm(); + t2.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.mul_ip(); + t2.norm(); + } + + z3 = new ctx.FP2(0); + z3.copy(t1); + z3.add(t2); + z3.norm(); + t1.sub(t2); + t1.norm(); + y3.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + y3.mul_ip(); + y3.norm(); + } + + x3.copy(y3); + x3.mul(t4); + t2.copy(t3); + t2.mul(t1); + x3.rsub(t2); + y3.mul(t0); + t1.mul(z3); + y3.add(t1); + t0.mul(t3); + z3.mul(t4); + z3.add(t0); + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + + return 0; + }, + + /* this-=Q */ + sub: function (Q) { + var D; + var NQ = new ECP2(); + NQ.copy(Q); + NQ.neg(); + D = this.add(NQ); + return D; + }, + + /* P*=e */ + mul: function (e) { + /* fixed size windows */ + var mt = new ctx.BIG(), + t = new ctx.BIG(), + C = new ECP2(), + P = new ECP2(), + Q = new ECP2(), + W = [], + w = [], + i, + nb, + s, + ns; + + if (this.is_infinity()) { + return new ECP2(); + } + + // precompute table + Q.copy(this); + Q.dbl(); + W[0] = new ECP2(); + W[0].copy(this); + + for (i = 1; i < 8; i++) { + W[i] = new ECP2(); + W[i].copy(W[i - 1]); + W[i].add(Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(e); + s = t.parity(); + t.inc(1); + t.norm(); + ns = t.parity(); + mt.copy(t); + mt.inc(1); + mt.norm(); + t.cmove(mt, s); + Q.cmove(this, ns); + C.copy(Q); + + nb = 1 + Math.floor((t.nbits() + 3) / 4); + + // convert exponent to signed 4-bit window + for (i = 0; i < nb; i++) { + w[i] = t.lastbits(5) - 16; + t.dec(w[i]); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5); + + P.copy(W[Math.floor((w[nb] - 1) / 2)]); + for (i = nb - 1; i >= 0; i--) { + Q.select(W, w[i]); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(Q); + } + P.sub(C); + + return P; + }, + + // clear cofactor + cfp: function () { + var fa = new ctx.BIG(0), + fb = new ctx.BIG(0), + x, + T, + K, + X, + xQ, + x2Q; + + // Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez + fa.rcopy(ctx.ROM_FIELD.Fra); + fb.rcopy(ctx.ROM_FIELD.Frb); + X = new ctx.FP2(fa, fb); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + X.inverse(null); + X.norm(); + } + + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + T = new ECP2(); + T.copy(this); + T = T.mul(x); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + T.neg(); + } + K = new ECP2(); + K.copy(T); + K.dbl(); + K.add(T); //K.affine(); + + K.frob(X); + this.frob(X); + this.frob(X); + this.frob(X); + this.add(T); + this.add(K); + T.frob(X); + T.frob(X); + this.add(T); + } + + if (ctx.ECP.CURVE_PAIRING_TYPE > ctx.ECP.BN) { + xQ = this.mul(x); + x2Q = xQ.mul(x); + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + xQ.neg(); + } + + x2Q.sub(xQ); + x2Q.sub(this); + + xQ.sub(this); + xQ.frob(X); + + this.dbl(); + this.frob(X); + this.frob(X); + + this.add(x2Q); + this.add(xQ); + } + }, + }; + + // set to group generator + ECP2.generator = function () { + var G = new ECP2(), + A = new ctx.BIG(0), + B = new ctx.BIG(0), + QX, + QY; + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxb); + QX = new ctx.FP2(0); + QX.bset(A, B); + A.rcopy(ctx.ROM_CURVE.CURVE_Pya); + B.rcopy(ctx.ROM_CURVE.CURVE_Pyb); + QY = new ctx.FP2(0); + QY.bset(A, B); + G.setxy(QX, QY); + return G; + }; + + /* convert from byte array to point */ + ECP2.fromBytes = function (b) { + var t = []; + var alt = false; + var typ = b[0]; + var P = new ECP2(); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ctx.ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = b[i]; + t[0] &= 0x1f; + var rx = ctx.FP2.fromBytes(t); + if ((b[0] & 0x80) == 0) { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 2 * ctx.BIG.MODBYTES]; + var ry = ctx.FP2.fromBytes(t); + P.setxy(rx, ry); + } else { + var sgn = (b[0] & 0x20) >> 5; + P.setx(rx, 0); + var cmp = P.y.islarger(); + if ((sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1)) P.neg(); + } + } else { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 1]; + var rx = ctx.FP2.fromBytes(t); + if (typ == 0x04) { + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 2 * ctx.BIG.MODBYTES + 1]; + var ry = ctx.FP2.fromBytes(t); + P.setxy(rx, ry); + } else { + P.setx(rx, typ & 1); + } + } + return P; + }; + + /* Calculate RHS of curve equation x^3+B */ + ECP2.RHS = function (x) { + var r, c, b; + + //x.norm(); + r = new ctx.FP2(x); //r.copy(x); + r.sqr(); + + c = new ctx.BIG(0); + c.rcopy(ctx.ROM_CURVE.CURVE_B); + b = new ctx.FP2(c); //b.bseta(c); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b.div_ip(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b.norm(); + b.mul_ip(); + b.norm(); + } + + r.mul(x); + r.add(b); + + r.reduce(); + + return r; + }; + + /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + ECP2.mul4 = function (Q, u) { + var W = new ECP2(), + P = new ECP2(), + T = [], + mt = new ctx.BIG(), + t = [], + w = [], + s = [], + i, + j, + k, + nb, + bt, + pb; + + for (i = 0; i < 4; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + //Q[i].affine(); + } + + T[0] = new ECP2(); + T[0].copy(Q[0]); // Q[0] + T[1] = new ECP2(); + T[1].copy(T[0]); + T[1].add(Q[1]); // Q[0]+Q[1] + T[2] = new ECP2(); + T[2].copy(T[0]); + T[2].add(Q[2]); // Q[0]+Q[2] + T[3] = new ECP2(); + T[3].copy(T[1]); + T[3].add(Q[2]); // Q[0]+Q[1]+Q[2] + T[4] = new ECP2(); + T[4].copy(T[0]); + T[4].add(Q[3]); // Q[0]+Q[3] + T[5] = new ECP2(); + T[5].copy(T[1]); + T[5].add(Q[3]); // Q[0]+Q[1]+Q[3] + T[6] = new ECP2(); + T[6].copy(T[2]); + T[6].add(Q[3]); // Q[0]+Q[2]+Q[3] + T[7] = new ECP2(); + T[7].copy(T[3]); + T[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] + + // Make it odd + pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 4; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s[i] = 2 * t[0].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w[i] += bt * k; + k *= 2; + } + } + + // Main loop + P.select(T, 2 * w[nb - 1] + 1); + for (i = nb - 2; i >= 0; i--) { + P.dbl(); + W.select(T, 2 * w[i] + s[i]); + P.add(W); + } + + // apply correction + W.copy(P); + W.sub(Q[0]); + P.cmove(W, pb); + return P; + }; + + /* return 1 if b==c, no branching */ + ECP2.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* Hunt and Peck a BIG to a curve point + ECP2.hap2point = function(h) + { + var one=new ctx.BIG(1); + var x=new ctx.BIG(h); + var Q,X2; + for (;;) { + X2 = new ctx.FP2(one, x); + Q = new ECP2(); + Q.setx(X2,0); + if (!Q.is_infinity()) break; + x.inc(1); + x.norm(); + } + return Q; + }; */ + + /* Constant time Map to Point */ + ECP2.map2point = function (H) { + // Shallue and van de Woestijne method. + var sgn, ne; + var NY = new ctx.FP2(1); + var T = new ctx.FP2(H); + sgn = T.sign(); + if (ctx.ECP.HTC_ISO_G2 == 0) { + var Z = new ctx.FP(ctx.FP.RIADZG2A); + var X1 = new ctx.FP2(Z); + var A = ECP2.RHS(X1); + var W = new ctx.FP2(A); + if ( + ctx.FP.RIADZG2A == -1 && + ctx.FP.RIADZG2B == 0 && + ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE && + ctx.ROM_CURVE.CURVE_B_I == 4 + ) { + // special case for BLS12381 + W.copy(new ctx.FP2(2, 1)); + } else { + W.sqrt(null); + } + var s = new ctx.FP(0); + s.rcopy(ctx.ROM_FIELD.SQRTm3); + Z.mul(s); + + T.sqr(); + var Y = new ctx.FP2(A); + Y.mul(T); + T.copy(NY); + T.add(Y); + T.norm(); + Y.rsub(NY); + Y.norm(); + NY.copy(T); + NY.mul(Y); + + NY.pmul(Z); + NY.inverse(null); + + W.pmul(Z); + if (W.sign() == 1) { + W.neg(); + W.norm(); + } + W.pmul(Z); + W.mul(H); + W.mul(Y); + W.mul(NY); + + var X3 = new ctx.FP2(X1); + X1.neg(); + X1.norm(); + X1.div2(); + var X2 = new ctx.FP2(X1); + X1.sub(W); + X1.norm(); + X2.add(W); + X2.norm(); + A.add(A); + A.add(A); + A.norm(); + T.sqr(); + T.mul(NY); + T.sqr(); + A.mul(T); + X3.add(A); + X3.norm(); + + Y.copy(ECP2.RHS(X2)); + X3.cmove(X2, Y.qr(null)); + Y.copy(ECP2.RHS(X1)); + X3.cmove(X1, Y.qr(null)); + Y.copy(ECP2.RHS(X3)); + Y.sqrt(null); + + ne = Y.sign() ^ sgn; + W.copy(Y); + W.neg(); + W.norm(); + Y.cmove(W, ne); + + var P = new ECP2(); + P.setxy(X3, Y); + return P; + } else { + var Q = new ctx.ECP2(); + var ra = new ctx.FP(0); + var rb = new ctx.FP(0); + ra.rcopy(ctx.ROM_CURVE.CURVE_Adr); + rb.rcopy(ctx.ROM_CURVE.CURVE_Adi); + var Ad = new ctx.FP2(ra, rb); + ra.rcopy(ctx.ROM_CURVE.CURVE_Bdr); + rb.rcopy(ctx.ROM_CURVE.CURVE_Bdi); + var Bd = new ctx.FP2(ra, rb); + var ZZ = new ctx.FP2(ctx.FP.RIADZG2A, ctx.FP.RIADZG2B); + var hint = new ctx.FP(0); + + T.sqr(); + T.mul(ZZ); + var W = new ctx.FP2(T); + W.add(NY); + W.norm(); + + W.mul(T); + var D = new ctx.FP2(Ad); + D.mul(W); + + W.add(NY); + W.norm(); + W.mul(Bd); + W.neg(); + W.norm(); + + var X2 = new ctx.FP2(W); + var X3 = new ctx.FP2(T); + X3.mul(X2); + + var GX1 = new ctx.FP2(X2); + GX1.sqr(); + var D2 = new ctx.FP2(D); + D2.sqr(); + W.copy(Ad); + W.mul(D2); + GX1.add(W); + GX1.norm(); + GX1.mul(X2); + D2.mul(D); + W.copy(Bd); + W.mul(D2); + GX1.add(W); + GX1.norm(); // x^3+Ax+b + + W.copy(GX1); + W.mul(D); + var qr = W.qr(hint); + D.copy(W); + D.inverse(hint); + D.mul(GX1); + X2.mul(D); + X3.mul(D); + T.mul(H); + D2.copy(D); + D2.sqr(); + + D.copy(D2); + D.mul(T); + T.copy(W); + T.mul(ZZ); + + var s = new ctx.FP(0); + s.rcopy(ctx.ROM_CURVE.CURVE_HTPC2); + s.mul(hint); + + X2.cmove(X3, 1 - qr); + W.cmove(T, 1 - qr); + D2.cmove(D, 1 - qr); + hint.cmove(s, 1 - qr); + + var Y = new ctx.FP2(W); + Y.sqrt(hint); + Y.mul(D2); + + ne = Y.sign() ^ sgn; + W.copy(Y); + W.neg(); + W.norm(); + Y.cmove(W, ne); + + var k = 0; + var isox = ctx.ECP.HTC_ISO_G2; + var isoy = (3 * (isox - 1)) / 2; + + // xnum + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + var xnum = new ctx.FP2(ra, rb); + k++; + for (var i = 0; i < isox; i++) { + xnum.mul(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + xnum.add(W); + xnum.norm(); + } + + //xden + var xden = new ctx.FP2(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + xden.add(W); + xden.norm(); + for (var i = 0; i < isox - 2; i++) { + xden.mul(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + xden.add(W); + xden.norm(); + } + + //ynum + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + var ynum = new ctx.FP2(ra, rb); + k++; + for (var i = 0; i < isoy; i++) { + ynum.mul(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + ynum.add(W); + ynum.norm(); + } + + //yden + var yden = new ctx.FP2(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + yden.add(W); + yden.norm(); + for (var i = 0; i < isoy - 1; i++) { + yden.mul(X2); + ra.rcopy(ctx.ROM_CURVE.PCR[k]); + rb.rcopy(ctx.ROM_CURVE.PCI[k]); + W.copy(new ctx.FP2(ra, rb)); + k++; + yden.add(W); + yden.norm(); + } + + ynum.mul(Y); + + T.copy(xnum); + T.mul(yden); + Q.x.copy(T); + T.copy(ynum); + T.mul(xden); + Q.y.copy(T); + T.copy(xden); + T.mul(yden); + Q.z.copy(T); + + return Q; + } + }; + + /* Map octet string to curve point + ECP2.mapit = function(h) + { + var q=new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var dx=ctx.DBIG.fromBytes(h); + var x=dx.mod(q); + + var Q=ECP2.hap2point(x); + Q.cfp(); + return Q; + };*/ + + return ECP2; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.ECP2 = ECP2; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ecp4.js b/packages/bls-verify/src/vendor/amcl-js/src/ecp4.js new file mode 100644 index 000000000..a1cb9407b --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ecp4.js @@ -0,0 +1,970 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Weierstrass elliptic curve functions over ctx.FP4 */ + +var ECP4 = function (ctx) { + 'use strict'; + + /* Constructor, set this=O */ + var ECP4 = function () { + this.x = new ctx.FP4(0); + this.y = new ctx.FP4(1); + this.z = new ctx.FP4(0); + }; + + ECP4.prototype = { + /* Test this=O? */ + is_infinity: function () { + return this.x.iszilch() && this.z.iszilch(); + }, + + /* copy this=P */ + copy: function (P) { + this.x.copy(P.x); + this.y.copy(P.y); + this.z.copy(P.z); + }, + + /* set this=O */ + inf: function () { + this.x.zero(); + this.y.one(); + this.z.zero(); + }, + + /* conditional move of Q to P dependant on d */ + cmove: function (Q, d) { + this.x.cmove(Q.x, d); + this.y.cmove(Q.y, d); + this.z.cmove(Q.z, d); + }, + + /* Constant time select from pre-computed table */ + select: function (W, b) { + var MP = new ECP4(), + m = b >> 31, + babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + this.cmove(W[0], ECP4.teq(babs, 0)); // conditional move + this.cmove(W[1], ECP4.teq(babs, 1)); + this.cmove(W[2], ECP4.teq(babs, 2)); + this.cmove(W[3], ECP4.teq(babs, 3)); + this.cmove(W[4], ECP4.teq(babs, 4)); + this.cmove(W[5], ECP4.teq(babs, 5)); + this.cmove(W[6], ECP4.teq(babs, 6)); + this.cmove(W[7], ECP4.teq(babs, 7)); + + MP.copy(this); + MP.neg(); + this.cmove(MP, m & 1); + }, + + /* Test P == Q */ + equals: function (Q) { + var a, b; + + a = new ctx.FP4(this.x); + b = new ctx.FP4(Q.x); + + a.mul(Q.z); + b.mul(this.z); + if (!a.equals(b)) { + return false; + } + + a.copy(this.y); + a.mul(Q.z); + b.copy(Q.y); + b.mul(this.z); + if (!a.equals(b)) { + return false; + } + + return true; + }, + + /* set this=-this */ + neg: function () { + this.y.norm(); + this.y.neg(); + this.y.norm(); + return; + }, + + /* convert this to affine, from (x,y,z) to (x,y) */ + affine: function () { + var one; + + if (this.is_infinity()) { + return; + } + + one = new ctx.FP4(1); + + if (this.z.equals(one)) { + this.x.reduce(); + this.y.reduce(); + return; + } + + this.z.inverse(null); + + this.x.mul(this.z); + this.x.reduce(); + this.y.mul(this.z); + this.y.reduce(); + this.z.copy(one); + }, + + /* extract affine x as ctx.FP4 */ + getX: function () { + var W = new ECP4(); + W.copy(this); + W.affine(); + return W.x; + }, + + /* extract affine y as ctx.FP4 */ + getY: function () { + var W = new ECP4(); + W.copy(this); + W.affine(); + return W.y; + }, + + /* extract projective x */ + getx: function () { + return this.x; + }, + + /* extract projective y */ + gety: function () { + return this.y; + }, + + /* extract projective z */ + getz: function () { + return this.z; + }, + + /* convert this to byte array */ + toBytes: function (b, compress) { + var t = []; + var alt = false; + var W = new ECP4(); + W.copy(this); + W.affine(); + W.x.toBytes(t); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) b[i] = t[i]; + if (!compress) { + W.y.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) b[i + 4 * ctx.BIG.MODBYTES] = t[i]; + } else { + b[0] |= 0x80; + if (W.y.islarger() == 1) b[0] |= 0x20; + } + } else { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) b[i + 1] = t[i]; + if (!compress) { + b[0] = 0x04; + W.y.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) b[i + 4 * ctx.BIG.MODBYTES + 1] = t[i]; + } else { + b[0] = 0x02; + if (W.y.sign() == 1) b[0] = 0x03; + } + } + }, + + /* convert this to hex string */ + toString: function () { + var W = new ECP4(); + W.copy(this); + if (W.is_infinity()) { + return 'infinity'; + } + W.affine(); + return '(' + W.x.toString() + ',' + W.y.toString() + ')'; + }, + + /* set this=(x,y) */ + setxy: function (ix, iy) { + var rhs, y2; + + this.x.copy(ix); + this.y.copy(iy); + this.z.one(); + this.x.norm(); + + rhs = ECP4.RHS(this.x); + + y2 = new ctx.FP4(this.y); //y2.copy(this.y); + y2.sqr(); + + if (!y2.equals(rhs)) { + this.inf(); + } + }, + + /* set this=(x,.) */ + setx: function (ix, s) { + var rhs, h; + + this.x.copy(ix); + this.z.one(); + this.x.norm(); + rhs = ECP4.RHS(this.x); + + if (rhs.qr(h) == 1) { + rhs.sqrt(h); + if (rhs.sign() != s) rhs.neg(); + rhs.reduce(); + this.y.copy(rhs); + } else { + this.inf(); + } + }, + + /* set this*=q, where q is Modulus, using Frobenius */ + frob: function (F, n) { + for (var i = 0; i < n; i++) { + this.x.frob(F[2]); + this.x.pmul(F[0]); + + this.y.frob(F[2]); + this.y.pmul(F[1]); + this.y.times_i(); + + this.z.frob(F[2]); + } + }, + + /* this+=this */ + dbl: function () { + var iy, t0, t1, t2, x3, y3; + + iy = new ctx.FP4(this.y); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + iy.times_i(); + iy.norm(); + } + + t0 = new ctx.FP4(this.y); + t0.sqr(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.times_i(); + } + t1 = new ctx.FP4(iy); + t1.mul(this.z); + t2 = new ctx.FP4(this.z); + t2.sqr(); + + this.z.copy(t0); + this.z.add(t0); + this.z.norm(); + this.z.add(this.z); + this.z.add(this.z); + this.z.norm(); + + t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.times_i(); + } + + x3 = new ctx.FP4(t2); + x3.mul(this.z); + + y3 = new ctx.FP4(t0); + + y3.add(t2); + y3.norm(); + this.z.mul(t1); + t1.copy(t2); + t1.add(t2); + t2.add(t1); + t2.norm(); + t0.sub(t2); + t0.norm(); //y^2-9bz^2 + y3.mul(t0); + y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 + t1.copy(this.x); + t1.mul(iy); // + this.x.copy(t0); + this.x.norm(); + this.x.mul(t1); + this.x.add(this.x); //(y^2-9bz^2)xy2 + + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + + return 1; + }, + + /* this+=Q */ + add: function (Q) { + var b, t0, t1, t2, t3, t4, x3, y3, z3; + + b = 3 * ctx.ROM_CURVE.CURVE_B_I; + t0 = new ctx.FP4(this.x); + t0.mul(Q.x); // x.Q.x + t1 = new ctx.FP4(this.y); + t1.mul(Q.y); // y.Q.y + + t2 = new ctx.FP4(this.z); + t2.mul(Q.z); + t3 = new ctx.FP4(this.x); + t3.add(this.y); + t3.norm(); //t3=X1+Y1 + t4 = new ctx.FP4(Q.x); + t4.add(Q.y); + t4.norm(); //t4=X2+Y2 + t3.mul(t4); //t3=(X1+Y1)(X2+Y2) + t4.copy(t0); + t4.add(t1); //t4=X1.X2+Y1.Y2 + + t3.sub(t4); + t3.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t3.times_i(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 + } + + t4.copy(this.y); + t4.add(this.z); + t4.norm(); //t4=Y1+Z1 + x3 = new ctx.FP4(Q.y); + x3.add(Q.z); + x3.norm(); //x3=Y2+Z2 + + t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2) + x3.copy(t1); // + x3.add(t2); //X3=Y1.Y2+Z1.Z2 + + t4.sub(x3); + t4.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t4.times_i(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 + } + + x3.copy(this.x); + x3.add(this.z); + x3.norm(); // x3=X1+Z1 + y3 = new ctx.FP4(Q.x); + y3.add(Q.z); + y3.norm(); // y3=X2+Z2 + x3.mul(y3); // x3=(X1+Z1)(X2+Z2) + y3.copy(t0); + y3.add(t2); // y3=X1.X2+Z1+Z2 + y3.rsub(x3); + y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.times_i(); + t1.times_i(); + } + + x3.copy(t0); + x3.add(t0); + t0.add(x3); + t0.norm(); + t2.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.times_i(); + } + + z3 = new ctx.FP4(t1); + z3.add(t2); + z3.norm(); + t1.sub(t2); + t1.norm(); + y3.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + y3.times_i(); + } + + x3.copy(y3); + x3.mul(t4); + t2.copy(t3); + t2.mul(t1); + x3.rsub(t2); + y3.mul(t0); + t1.mul(z3); + y3.add(t1); + t0.mul(t3); + z3.mul(t4); + z3.add(t0); + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + + return 0; + }, + + /* this-=Q */ + sub: function (Q) { + var D; + var NQ = new ECP4(); + NQ.copy(Q); + NQ.neg(); + D = this.add(NQ); + return D; + }, + + /* P*=e */ + mul: function (e) { + /* fixed size windows */ + var mt = new ctx.BIG(), + t = new ctx.BIG(), + C = new ECP4(), + P = new ECP4(), + Q = new ECP4(), + W = [], + w = [], + i, + nb, + s, + ns; + + if (this.is_infinity()) { + return new ECP4(); + } + + // precompute table + Q.copy(this); + Q.dbl(); + W[0] = new ECP4(); + W[0].copy(this); + + for (i = 1; i < 8; i++) { + W[i] = new ECP4(); + W[i].copy(W[i - 1]); + W[i].add(Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(e); + s = t.parity(); + t.inc(1); + t.norm(); + ns = t.parity(); + mt.copy(t); + mt.inc(1); + mt.norm(); + t.cmove(mt, s); + Q.cmove(this, ns); + C.copy(Q); + + nb = 1 + Math.floor((t.nbits() + 3) / 4); + + // convert exponent to signed 4-bit window + for (i = 0; i < nb; i++) { + w[i] = t.lastbits(5) - 16; + t.dec(w[i]); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5); + + P.copy(W[Math.floor((w[nb] - 1) / 2)]); + for (i = nb - 1; i >= 0; i--) { + Q.select(W, w[i]); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(Q); + } + P.sub(C); + P.affine(); + + return P; + }, + + cfp: function () { + var F = ECP4.frob_constants(), + x, + xQ, + x2Q, + x3Q, + x4Q; + + /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + xQ = this.mul(x); + x2Q = xQ.mul(x); + x3Q = x2Q.mul(x); + x4Q = x3Q.mul(x); + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + xQ.neg(); + x3Q.neg(); + } + + x4Q.sub(x3Q); + x4Q.sub(this); + + x3Q.sub(x2Q); + x3Q.frob(F, 1); + + x2Q.sub(xQ); + x2Q.frob(F, 2); + + xQ.sub(this); + xQ.frob(F, 3); + + this.dbl(); + this.frob(F, 4); + + this.add(x4Q); + this.add(x3Q); + this.add(x2Q); + this.add(xQ); + + this.affine(); + }, + }; + + // set to group generator + ECP4.generator = function () { + var G = new ECP4(), + A = new ctx.BIG(0), + B = new ctx.BIG(0), + XA, + XB, + X, + YA, + YB, + Y; + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxab); + XA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxbb); + + XB = new ctx.FP2(A, B); + X = new ctx.FP4(XA, XB); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pyaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pyab); + YA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pyba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pybb); + + YB = new ctx.FP2(A, B); + Y = new ctx.FP4(YA, YB); + + G.setxy(X, Y); + + return G; + }; + + /* convert from byte array to point */ + ECP4.fromBytes = function (b) { + var t = []; + var alt = false; + var typ = b[0]; + var P = new ECP4(); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = b[i]; + t[0] &= 0x1f; + var rx = ctx.FP4.fromBytes(t); + if ((b[0] & 0x80) == 0) { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 4 * ctx.BIG.MODBYTES]; + var ry = ctx.FP4.fromBytes(t); + P.setxy(rx, ry); + } else { + var sgn = (b[0] & 0x20) >> 5; + P.setx(rx, 0); + var cmp = P.y.islarger(); + if ((sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1)) P.neg(); + } + } else { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 1]; + var rx = ctx.FP4.fromBytes(t); + if (typ == 0x04) { + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 4 * ctx.BIG.MODBYTES + 1]; + var ry = ctx.FP4.fromBytes(t); + P.setxy(rx, ry); + } else { + P.setx(rx, typ & 1); + } + } + return P; + }; + + /* Calculate RHS of curve equation x^3+B */ + ECP4.RHS = function (x) { + var r, c, b; + + //x.norm(); + r = new ctx.FP4(x); //r.copy(x); + r.sqr(); + + c = new ctx.BIG(0); + c.rcopy(ctx.ROM_CURVE.CURVE_B); + b = new ctx.FP4(c); //b.bseta(c); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b.div_i(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b.times_i(); + } + + r.mul(x); + r.add(b); + + r.reduce(); + return r; + }; + + /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + ECP4.mul8 = function (Q, u) { + var W = new ECP4(), + P = new ECP4(), + T1 = [], + T2 = [], + mt = new ctx.BIG(), + t = [], + w1 = [], + s1 = [], + w2 = [], + s2 = [], + i, + j, + k, + nb, + bt, + pb1, + pb2; + + for (i = 0; i < 8; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + //Q[i].affine(); + } + + T1[0] = new ECP4(); + T1[0].copy(Q[0]); // Q[0] + T1[1] = new ECP4(); + T1[1].copy(T1[0]); + T1[1].add(Q[1]); // Q[0]+Q[1] + T1[2] = new ECP4(); + T1[2].copy(T1[0]); + T1[2].add(Q[2]); // Q[0]+Q[2] + T1[3] = new ECP4(); + T1[3].copy(T1[1]); + T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2] + T1[4] = new ECP4(); + T1[4].copy(T1[0]); + T1[4].add(Q[3]); // Q[0]+Q[3] + T1[5] = new ECP4(); + T1[5].copy(T1[1]); + T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3] + T1[6] = new ECP4(); + T1[6].copy(T1[2]); + T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3] + T1[7] = new ECP4(); + T1[7].copy(T1[3]); + T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] + + T2[0] = new ECP4(); + T2[0].copy(Q[4]); // Q[0] + T2[1] = new ECP4(); + T2[1].copy(T2[0]); + T2[1].add(Q[5]); // Q[0]+Q[1] + T2[2] = new ECP4(); + T2[2].copy(T2[0]); + T2[2].add(Q[6]); // Q[0]+Q[2] + T2[3] = new ECP4(); + T2[3].copy(T2[1]); + T2[3].add(Q[6]); // Q[0]+Q[1]+Q[2] + T2[4] = new ECP4(); + T2[4].copy(T2[0]); + T2[4].add(Q[7]); // Q[0]+Q[3] + T2[5] = new ECP4(); + T2[5].copy(T2[1]); + T2[5].add(Q[7]); // Q[0]+Q[1]+Q[3] + T2[6] = new ECP4(); + T2[6].copy(T2[2]); + T2[6].add(Q[7]); // Q[0]+Q[2]+Q[3] + T2[7] = new ECP4(); + T2[7].copy(T2[3]); + T2[7].add(Q[7]); // Q[0]+Q[1]+Q[2]+Q[3] + + // Make it odd + pb1 = 1 - t[0].parity(); + t[0].inc(pb1); + t[0].norm(); + + pb2 = 1 - t[4].parity(); + t[4].inc(pb2); + t[4].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 8; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s1[nb - 1] = 1; + s2[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s1[i] = 2 * t[0].parity() - 1; + t[4].fshr(1); + s2[i] = 2 * t[4].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w1[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s1[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w1[i] += bt * k; + k *= 2; + } + w2[i] = 0; + k = 1; + for (j = 5; j < 8; j++) { + bt = s2[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w2[i] += bt * k; + k *= 2; + } + } + + // Main loop + P.select(T1, 2 * w1[nb - 1] + 1); + W.select(T2, 2 * w2[nb - 1] + 1); + P.add(W); + for (i = nb - 2; i >= 0; i--) { + P.dbl(); + W.select(T1, 2 * w1[i] + s1[i]); + P.add(W); + W.select(T2, 2 * w2[i] + s2[i]); + P.add(W); + } + + // apply correction + W.copy(P); + W.sub(Q[0]); + P.cmove(W, pb1); + + W.copy(P); + W.sub(Q[4]); + P.cmove(W, pb2); + + P.affine(); + return P; + }; + + /* return 1 if b==c, no branching */ + ECP4.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* Hunt and Peck a BIG to a curve point + ECP4.hap2point = function(h) + { + var one=new ctx.BIG(1); + var x=new ctx.BIG(h); + var Q,X2,X4; + for (;;) { + X2 = new ctx.FP2(one, x); + X4 = new ctx.FP4(X2); + Q = new ECP4(); + Q.setx(X4,0); + if (!Q.is_infinity()) break; + x.inc(1); + x.norm(); + } + return Q; + }; */ + + /* Constant time Map to Point */ + ECP4.map2point = function (H) { + // Shallue and van de Woestijne method. + var sgn, ne; + var NY = new ctx.FP4(1); + var T = new ctx.FP4(H); + sgn = T.sign(); + + var Z = new ctx.FP(ctx.FP.RIADZG2A); + var X1 = new ctx.FP4(Z); + var A = ECP4.RHS(X1); + var W = new ctx.FP4(A); + + W.sqrt(null); + + var s = new ctx.FP(0); + s.rcopy(ctx.ROM_FIELD.SQRTm3); + Z.mul(s); + + T.sqr(); + var Y = new ctx.FP4(A); + Y.mul(T); + T.copy(NY); + T.add(Y); + T.norm(); + Y.rsub(NY); + Y.norm(); + NY.copy(T); + NY.mul(Y); + + NY.qmul(Z); + NY.inverse(null); + + W.qmul(Z); + if (W.sign() == 1) { + W.neg(); + W.norm(); + } + W.qmul(Z); + W.mul(H); + W.mul(Y); + W.mul(NY); + + var X3 = new ctx.FP4(X1); + X1.neg(); + X1.norm(); + X1.div2(); + var X2 = new ctx.FP4(X1); + X1.sub(W); + X1.norm(); + X2.add(W); + X2.norm(); + A.add(A); + A.add(A); + A.norm(); + T.sqr(); + T.mul(NY); + T.sqr(); + A.mul(T); + X3.add(A); + X3.norm(); + + Y.copy(ECP4.RHS(X2)); + X3.cmove(X2, Y.qr(null)); + Y.copy(ECP4.RHS(X1)); + X3.cmove(X1, Y.qr(null)); + Y.copy(ECP4.RHS(X3)); + Y.sqrt(null); + + ne = Y.sign() ^ sgn; + W.copy(Y); + W.neg(); + W.norm(); + Y.cmove(W, ne); + + var P = new ECP4(); + P.setxy(X3, Y); + return P; + }; + + /* Map octet string to curve point + ECP4.mapit = function(h) + { + var q=new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var dx=ctx.DBIG.fromBytes(h); + var x=dx.mod(q); + + var Q=ECP4.hap2point(x); + Q.cfp(); + return Q; + }; */ + + ECP4.frob_constants = function () { + var fa = new ctx.BIG(0), + fb = new ctx.BIG(0), + F = [], + X, + F0, + F1, + F2; + + fa.rcopy(ctx.ROM_FIELD.Fra); + fb.rcopy(ctx.ROM_FIELD.Frb); + X = new ctx.FP2(fa, fb); + + F0 = new ctx.FP2(X); + F0.sqr(); + F2 = new ctx.FP2(F0); + F2.mul_ip(); + F2.norm(); + F1 = new ctx.FP2(F2); + F1.sqr(); + F2.mul(F1); + F1.copy(X); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + F1.mul_ip(); + F1.inverse(null); + F0.copy(F1); + F0.sqr(); + } + F0.mul_ip(); + F0.norm(); + F1.mul(F0); + + F[0] = new ctx.FP2(F0); + F[1] = new ctx.FP2(F1); + F[2] = new ctx.FP2(F2); + return F; + }; + + return ECP4; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.ECP4 = ECP4; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ecp8.js b/packages/bls-verify/src/vendor/amcl-js/src/ecp8.js new file mode 100644 index 000000000..7edfaba54 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ecp8.js @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Weierstrass elliptic curve functions over ctx.FP8 */ + +var ECP8 = function (ctx) { + 'use strict'; + + /* Constructor, set this=O */ + var ECP8 = function () { + this.x = new ctx.FP8(0); + this.y = new ctx.FP8(1); + this.z = new ctx.FP8(0); + }; + + ECP8.prototype = { + /* Test this=O? */ + is_infinity: function () { + return this.x.iszilch() && this.z.iszilch(); + }, + + /* copy this=P */ + copy: function (P) { + this.x.copy(P.x); + this.y.copy(P.y); + this.z.copy(P.z); + }, + + /* set this=O */ + inf: function () { + this.x.zero(); + this.y.one(); + this.z.zero(); + }, + + /* conditional move of Q to P dependant on d */ + cmove: function (Q, d) { + this.x.cmove(Q.x, d); + this.y.cmove(Q.y, d); + this.z.cmove(Q.z, d); + }, + + /* Constant time select from pre-computed table */ + select: function (W, b) { + var MP = new ECP8(), + m = b >> 31, + babs = (b ^ m) - m; + + babs = (babs - 1) / 2; + + this.cmove(W[0], ECP8.teq(babs, 0)); // conditional move + this.cmove(W[1], ECP8.teq(babs, 1)); + this.cmove(W[2], ECP8.teq(babs, 2)); + this.cmove(W[3], ECP8.teq(babs, 3)); + this.cmove(W[4], ECP8.teq(babs, 4)); + this.cmove(W[5], ECP8.teq(babs, 5)); + this.cmove(W[6], ECP8.teq(babs, 6)); + this.cmove(W[7], ECP8.teq(babs, 7)); + + MP.copy(this); + MP.neg(); + this.cmove(MP, m & 1); + }, + + /* Test P == Q */ + equals: function (Q) { + var a, b; + + a = new ctx.FP8(this.x); + b = new ctx.FP8(Q.x); + + a.mul(Q.z); + b.mul(this.z); + if (!a.equals(b)) { + return false; + } + + a.copy(this.y); + a.mul(Q.z); + b.copy(Q.y); + b.mul(this.z); + if (!a.equals(b)) { + return false; + } + + return true; + }, + + /* set this=-this */ + neg: function () { + this.y.norm(); + this.y.neg(); + this.y.norm(); + return; + }, + + /* convert this to affine, from (x,y,z) to (x,y) */ + affine: function () { + var one; + + if (this.is_infinity()) { + return; + } + + one = new ctx.FP8(1); + + if (this.z.equals(one)) { + this.x.reduce(); + this.y.reduce(); + return; + } + + this.z.inverse(null); + this.x.mul(this.z); + this.x.reduce(); + this.y.mul(this.z); + this.y.reduce(); + this.z.copy(one); + }, + + /* extract affine x as ctx.FP8 */ + getX: function () { + var W = new ECP8(); + W.copy(this); + W.affine(); + return W.x; + }, + + /* extract affine y as ctx.FP8 */ + getY: function () { + var W = new ECP8(); + W.copy(this); + W.affine(); + return W.y; + }, + + /* extract projective x */ + getx: function () { + return this.x; + }, + + /* extract projective y */ + gety: function () { + return this.y; + }, + + /* extract projective z */ + getz: function () { + return this.z; + }, + + /* convert this to byte array */ + toBytes: function (b, compress) { + var t = []; + var alt = false; + var W = new ECP8(); + W.copy(this); + W.affine(); + W.x.toBytes(t); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) b[i] = t[i]; + if (!compress) { + W.y.toBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) b[i + 8 * ctx.BIG.MODBYTES] = t[i]; + } else { + b[0] |= 0x80; + if (W.y.islarger() == 1) b[0] |= 0x20; + } + } else { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) b[i + 1] = t[i]; + if (!compress) { + b[0] = 0x04; + W.y.toBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) b[i + 8 * ctx.BIG.MODBYTES + 1] = t[i]; + } else { + b[0] = 0x02; + if (W.y.sign() == 1) b[0] = 0x03; + } + } + }, + + /* convert this to hex string */ + toString: function () { + var W = new ECP8(); + W.copy(this); + if (W.is_infinity()) { + return 'infinity'; + } + W.affine(); + return '(' + W.x.toString() + ',' + W.y.toString() + ')'; + }, + + /* set this=(x,y) */ + setxy: function (ix, iy) { + var rhs, y2; + + this.x.copy(ix); + this.y.copy(iy); + this.z.one(); + this.x.norm(); + + rhs = ECP8.RHS(this.x); + + y2 = new ctx.FP8(this.y); //y2.copy(this.y); + y2.sqr(); + + if (!y2.equals(rhs)) { + this.inf(); + } + }, + + /* set this=(x,.) */ + setx: function (ix, s) { + var rhs, h; + + this.x.copy(ix); + this.z.one(); + this.x.norm(); + rhs = ECP8.RHS(this.x); + + //alert("0. rhs= "+rhs.toString()); + if (rhs.qr(h) == 1) { + rhs.sqrt(h); + //alert("1. rhs= "+rhs.toString()); + if (rhs.sign() != s) rhs.neg(); + rhs.reduce(); + this.y.copy(rhs); + } else { + this.inf(); + } + }, + + /* set this*=q, where q is Modulus, using Frobenius */ + frob: function (F, n) { + for (var i = 0; i < n; i++) { + this.x.frob(F[2]); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + this.x.qmul(F[0]); + this.x.times_i2(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + this.x.qmul(F[0]); + this.x.times_i2(); + } + + this.y.frob(F[2]); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + this.y.qmul(F[1]); + this.y.times_i2(); + this.y.times_i(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + this.y.qmul(F[1]); + this.y.times_i(); + } + + this.z.frob(F[2]); + } + }, + + /* this+=this */ + dbl: function () { + var iy, t0, t1, t2, x3, y3; + + iy = new ctx.FP8(this.y); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + iy.times_i(); + iy.norm(); + } + + t0 = new ctx.FP8(this.y); + t0.sqr(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.times_i(); + } + t1 = new ctx.FP8(iy); + t1.mul(this.z); + t2 = new ctx.FP8(this.z); + t2.sqr(); + + this.z.copy(t0); + this.z.add(t0); + this.z.norm(); + this.z.add(this.z); + this.z.add(this.z); + this.z.norm(); + + t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.times_i(); + } + + x3 = new ctx.FP8(t2); + x3.mul(this.z); + + y3 = new ctx.FP8(t0); + + y3.add(t2); + y3.norm(); + this.z.mul(t1); + t1.copy(t2); + t1.add(t2); + t2.add(t1); + t2.norm(); + t0.sub(t2); + t0.norm(); //y^2-9bz^2 + y3.mul(t0); + y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2 + t1.copy(this.x); + t1.mul(iy); // + this.x.copy(t0); + this.x.norm(); + this.x.mul(t1); + this.x.add(this.x); //(y^2-9bz^2)xy2 + + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + + return 1; + }, + + /* this+=Q */ + add: function (Q) { + var b, t0, t1, t2, t3, t4, x3, y3, z3; + + b = 3 * ctx.ROM_CURVE.CURVE_B_I; + t0 = new ctx.FP8(this.x); + t0.mul(Q.x); // x.Q.x + t1 = new ctx.FP8(this.y); + t1.mul(Q.y); // y.Q.y + + t2 = new ctx.FP8(this.z); + t2.mul(Q.z); + t3 = new ctx.FP8(this.x); + t3.add(this.y); + t3.norm(); //t3=X1+Y1 + t4 = new ctx.FP8(Q.x); + t4.add(Q.y); + t4.norm(); //t4=X2+Y2 + t3.mul(t4); //t3=(X1+Y1)(X2+Y2) + t4.copy(t0); + t4.add(t1); //t4=X1.X2+Y1.Y2 + + t3.sub(t4); + t3.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t3.times_i(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1 + } + + t4.copy(this.y); + t4.add(this.z); + t4.norm(); //t4=Y1+Z1 + x3 = new ctx.FP8(Q.y); + x3.add(Q.z); + x3.norm(); //x3=Y2+Z2 + + t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2) + x3.copy(t1); // + x3.add(t2); //X3=Y1.Y2+Z1.Z2 + + t4.sub(x3); + t4.norm(); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t4.times_i(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1 + } + + x3.copy(this.x); + x3.add(this.z); + x3.norm(); // x3=X1+Z1 + y3 = new ctx.FP8(Q.x); + y3.add(Q.z); + y3.norm(); // y3=X2+Z2 + x3.mul(y3); // x3=(X1+Z1)(X2+Z2) + y3.copy(t0); + y3.add(t2); // y3=X1.X2+Z1+Z2 + y3.rsub(x3); + y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + t0.times_i(); + t1.times_i(); + } + + x3.copy(t0); + x3.add(t0); + t0.add(x3); + t0.norm(); + t2.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + t2.times_i(); + } + + z3 = new ctx.FP8(t1); + z3.add(t2); + z3.norm(); + t1.sub(t2); + t1.norm(); + y3.imul(b); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + y3.times_i(); + } + + x3.copy(y3); + x3.mul(t4); + t2.copy(t3); + t2.mul(t1); + x3.rsub(t2); + y3.mul(t0); + t1.mul(z3); + y3.add(t1); + t0.mul(t3); + z3.mul(t4); + z3.add(t0); + + this.x.copy(x3); + this.x.norm(); + this.y.copy(y3); + this.y.norm(); + this.z.copy(z3); + this.z.norm(); + + return 0; + }, + + /* this-=Q */ + sub: function (Q) { + var D; + var NQ = new ECP8(); + NQ.copy(Q); + NQ.neg(); + D = this.add(NQ); + return D; + }, + + /* P*=e */ + mul: function (e) { + /* fixed size windows */ + var mt = new ctx.BIG(), + t = new ctx.BIG(), + C = new ECP8(), + P = new ECP8(), + Q = new ECP8(), + W = [], + w = [], + i, + nb, + s, + ns; + + if (this.is_infinity()) { + return new ECP8(); + } + + // precompute table + Q.copy(this); + Q.dbl(); + W[0] = new ECP8(); + W[0].copy(this); + + for (i = 1; i < 8; i++) { + W[i] = new ECP8(); + W[i].copy(W[i - 1]); + W[i].add(Q); + } + + // make exponent odd - add 2P if even, P if odd + t.copy(e); + s = t.parity(); + t.inc(1); + t.norm(); + ns = t.parity(); + mt.copy(t); + mt.inc(1); + mt.norm(); + t.cmove(mt, s); + Q.cmove(this, ns); + C.copy(Q); + + nb = 1 + Math.floor((t.nbits() + 3) / 4); + + // convert exponent to signed 4-bit window + for (i = 0; i < nb; i++) { + w[i] = t.lastbits(5) - 16; + t.dec(w[i]); + t.norm(); + t.fshr(4); + } + w[nb] = t.lastbits(5); + + P.copy(W[Math.floor((w[nb] - 1) / 2)]); + for (i = nb - 1; i >= 0; i--) { + Q.select(W, w[i]); + P.dbl(); + P.dbl(); + P.dbl(); + P.dbl(); + P.add(Q); + } + P.sub(C); + P.affine(); + + return P; + }, + /* clear cofactor */ + cfp: function (h) { + var F = ECP8.frob_constants(), + x, + xQ, + x2Q, + x3Q, + x4Q, + x5Q, + x6Q, + x7Q, + x8Q; + + /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + xQ = this.mul(x); + x2Q = xQ.mul(x); + x3Q = x2Q.mul(x); + x4Q = x3Q.mul(x); + x5Q = x4Q.mul(x); + x6Q = x5Q.mul(x); + x7Q = x6Q.mul(x); + x8Q = x7Q.mul(x); + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + xQ.neg(); + x3Q.neg(); + x5Q.neg(); + x7Q.neg(); + } + + x8Q.sub(x7Q); + x8Q.sub(this); + + x7Q.sub(x6Q); + x7Q.frob(F, 1); + + x6Q.sub(x5Q); + x6Q.frob(F, 2); + + x5Q.sub(x4Q); + x5Q.frob(F, 3); + + x4Q.sub(x3Q); + x4Q.frob(F, 4); + + x3Q.sub(x2Q); + x3Q.frob(F, 5); + + x2Q.sub(xQ); + x2Q.frob(F, 6); + + xQ.sub(this); + xQ.frob(F, 7); + + this.dbl(); + this.frob(F, 8); + + this.add(x8Q); + this.add(x7Q); + this.add(x6Q); + this.add(x5Q); + + this.add(x4Q); + this.add(x3Q); + this.add(x2Q); + this.add(xQ); + + this.affine(); + }, + }; + + // set to group generator + ECP8.generator = function () { + var G = new ECP8(), + A = new ctx.BIG(0), + B = new ctx.BIG(0), + XAA, + XAB, + XA, + XBA, + XBB, + XB, + X, + YAA, + YAB, + YA, + YBA, + YBB, + YB, + Y; + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxaaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxaab); + XAA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxaba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxabb); + + XAB = new ctx.FP2(A, B); + XA = new ctx.FP4(XAA, XAB); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxbaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxbab); + XBA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pxbba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pxbbb); + + XBB = new ctx.FP2(A, B); + XB = new ctx.FP4(XBA, XBB); + + X = new ctx.FP8(XA, XB); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pyaaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pyaab); + YAA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pyaba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pyabb); + + YAB = new ctx.FP2(A, B); + YA = new ctx.FP4(YAA, YAB); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pybaa); + B.rcopy(ctx.ROM_CURVE.CURVE_Pybab); + YBA = new ctx.FP2(A, B); + + A.rcopy(ctx.ROM_CURVE.CURVE_Pybba); + B.rcopy(ctx.ROM_CURVE.CURVE_Pybbb); + + YBB = new ctx.FP2(A, B); + YB = new ctx.FP4(YBA, YBB); + + Y = new ctx.FP8(YA, YB); + + G.setxy(X, Y); + + return G; + }; + + /* convert from byte array to point */ + ECP8.fromBytes = function (b) { + var t = []; + var alt = false; + var typ = b[0]; + var P = new ECP8(); + + if ((ctx.FP.MODBITS - 1) % 8 <= 4 && ECP.ALLOW_ALT_COMPRESS) alt = true; + + if (alt) { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = b[i]; + t[0] &= 0x1f; + var rx = ctx.FP8.fromBytes(t); + if ((b[0] & 0x80) == 0) { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 8 * ctx.BIG.MODBYTES]; + var ry = ctx.FP8.fromBytes(t); + P.setxy(rx, ry); + } else { + var sgn = (b[0] & 0x20) >> 5; + P.setx(rx, 0); + var cmp = P.y.islarger(); + if ((sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1)) P.neg(); + } + } else { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 1]; + var rx = ctx.FP8.fromBytes(t); + if (typ == 0x04) { + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = b[i + 8 * ctx.BIG.MODBYTES + 1]; + var ry = ctx.FP8.fromBytes(t); + P.setxy(rx, ry); + } else { + P.setx(rx, typ & 1); + } + } + return P; + }; + + /* Calculate RHS of curve equation x^3+B */ + ECP8.RHS = function (x) { + var r, c, b; + + //x.norm(); + r = new ctx.FP8(x); //r.copy(x); + r.sqr(); + + c = new ctx.BIG(0); + c.rcopy(ctx.ROM_CURVE.CURVE_B); + b = new ctx.FP8(c); //b.bseta(c); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b.div_i(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b.times_i(); + } + + r.mul(x); + r.add(b); + + r.reduce(); + return r; + }; + + /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + ECP8.mul16 = function (Q, u) { + var W = new ECP8(), + P = new ECP8(), + T1 = [], + T2 = [], + T3 = [], + T4 = [], + mt = new ctx.BIG(), + t = [], + w1 = [], + s1 = [], + w2 = [], + s2 = [], + w3 = [], + s3 = [], + w4 = [], + s4 = [], + i, + j, + k, + nb, + bt, + pb1, + pb2, + pb3, + pb4; + + for (i = 0; i < 16; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + //Q[i].affine(); + } + + T1[0] = new ECP8(); + T1[0].copy(Q[0]); // Q[0] + T1[1] = new ECP8(); + T1[1].copy(T1[0]); + T1[1].add(Q[1]); // Q[0]+Q[1] + T1[2] = new ECP8(); + T1[2].copy(T1[0]); + T1[2].add(Q[2]); // Q[0]+Q[2] + T1[3] = new ECP8(); + T1[3].copy(T1[1]); + T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2] + T1[4] = new ECP8(); + T1[4].copy(T1[0]); + T1[4].add(Q[3]); // Q[0]+Q[3] + T1[5] = new ECP8(); + T1[5].copy(T1[1]); + T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3] + T1[6] = new ECP8(); + T1[6].copy(T1[2]); + T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3] + T1[7] = new ECP8(); + T1[7].copy(T1[3]); + T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3] + + T2[0] = new ECP8(); + T2[0].copy(Q[4]); // Q[0] + T2[1] = new ECP8(); + T2[1].copy(T2[0]); + T2[1].add(Q[5]); // Q[0]+Q[1] + T2[2] = new ECP8(); + T2[2].copy(T2[0]); + T2[2].add(Q[6]); // Q[0]+Q[2] + T2[3] = new ECP8(); + T2[3].copy(T2[1]); + T2[3].add(Q[6]); // Q[0]+Q[1]+Q[2] + T2[4] = new ECP8(); + T2[4].copy(T2[0]); + T2[4].add(Q[7]); // Q[0]+Q[3] + T2[5] = new ECP8(); + T2[5].copy(T2[1]); + T2[5].add(Q[7]); // Q[0]+Q[1]+Q[3] + T2[6] = new ECP8(); + T2[6].copy(T2[2]); + T2[6].add(Q[7]); // Q[0]+Q[2]+Q[3] + T2[7] = new ECP8(); + T2[7].copy(T2[3]); + T2[7].add(Q[7]); // Q[0]+Q[1]+Q[2]+Q[3] + + T3[0] = new ECP8(); + T3[0].copy(Q[8]); // Q[0] + T3[1] = new ECP8(); + T3[1].copy(T3[0]); + T3[1].add(Q[9]); // Q[0]+Q[1] + T3[2] = new ECP8(); + T3[2].copy(T3[0]); + T3[2].add(Q[10]); // Q[0]+Q[2] + T3[3] = new ECP8(); + T3[3].copy(T3[1]); + T3[3].add(Q[10]); // Q[0]+Q[1]+Q[2] + T3[4] = new ECP8(); + T3[4].copy(T3[0]); + T3[4].add(Q[11]); // Q[0]+Q[3] + T3[5] = new ECP8(); + T3[5].copy(T3[1]); + T3[5].add(Q[11]); // Q[0]+Q[1]+Q[3] + T3[6] = new ECP8(); + T3[6].copy(T3[2]); + T3[6].add(Q[11]); // Q[0]+Q[2]+Q[3] + T3[7] = new ECP8(); + T3[7].copy(T3[3]); + T3[7].add(Q[11]); // Q[0]+Q[1]+Q[2]+Q[3] + + T4[0] = new ECP8(); + T4[0].copy(Q[12]); // Q[0] + T4[1] = new ECP8(); + T4[1].copy(T4[0]); + T4[1].add(Q[13]); // Q[0]+Q[1] + T4[2] = new ECP8(); + T4[2].copy(T4[0]); + T4[2].add(Q[14]); // Q[0]+Q[2] + T4[3] = new ECP8(); + T4[3].copy(T4[1]); + T4[3].add(Q[14]); // Q[0]+Q[1]+Q[2] + T4[4] = new ECP8(); + T4[4].copy(T4[0]); + T4[4].add(Q[15]); // Q[0]+Q[3] + T4[5] = new ECP8(); + T4[5].copy(T4[1]); + T4[5].add(Q[15]); // Q[0]+Q[1]+Q[3] + T4[6] = new ECP8(); + T4[6].copy(T4[2]); + T4[6].add(Q[15]); // Q[0]+Q[2]+Q[3] + T4[7] = new ECP8(); + T4[7].copy(T4[3]); + T4[7].add(Q[15]); // Q[0]+Q[1]+Q[2]+Q[3] + + // Make it odd + pb1 = 1 - t[0].parity(); + t[0].inc(pb1); + t[0].norm(); + + pb2 = 1 - t[4].parity(); + t[4].inc(pb2); + t[4].norm(); + + pb3 = 1 - t[8].parity(); + t[8].inc(pb3); + t[8].norm(); + + pb4 = 1 - t[12].parity(); + t[12].inc(pb4); + t[12].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 16; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s1[nb - 1] = 1; + s2[nb - 1] = 1; + s3[nb - 1] = 1; + s4[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s1[i] = 2 * t[0].parity() - 1; + t[4].fshr(1); + s2[i] = 2 * t[4].parity() - 1; + + t[8].fshr(1); + s3[i] = 2 * t[8].parity() - 1; + t[12].fshr(1); + s4[i] = 2 * t[12].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w1[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s1[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w1[i] += bt * k; + k *= 2; + } + w2[i] = 0; + k = 1; + for (j = 5; j < 8; j++) { + bt = s2[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w2[i] += bt * k; + k *= 2; + } + + w3[i] = 0; + k = 1; + for (j = 9; j < 12; j++) { + bt = s3[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w3[i] += bt * k; + k *= 2; + } + w4[i] = 0; + k = 1; + for (j = 13; j < 16; j++) { + bt = s4[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w4[i] += bt * k; + k *= 2; + } + } + + // Main loop + P.select(T1, 2 * w1[nb - 1] + 1); + W.select(T2, 2 * w2[nb - 1] + 1); + P.add(W); + W.select(T3, 2 * w3[nb - 1] + 1); + P.add(W); + W.select(T4, 2 * w4[nb - 1] + 1); + P.add(W); + for (i = nb - 2; i >= 0; i--) { + P.dbl(); + W.select(T1, 2 * w1[i] + s1[i]); + P.add(W); + W.select(T2, 2 * w2[i] + s2[i]); + P.add(W); + W.select(T3, 2 * w3[i] + s3[i]); + P.add(W); + W.select(T4, 2 * w4[i] + s4[i]); + P.add(W); + } + + // apply correction + W.copy(P); + W.sub(Q[0]); + P.cmove(W, pb1); + + W.copy(P); + W.sub(Q[4]); + P.cmove(W, pb2); + + W.copy(P); + W.sub(Q[8]); + P.cmove(W, pb3); + + W.copy(P); + W.sub(Q[12]); + P.cmove(W, pb4); + + P.affine(); + return P; + }; + + /* return 1 if b==c, no branching */ + ECP8.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* Hunt and Peck a BIG to a curve point + ECP8.hap2point = function(h) + { + var one=new ctx.BIG(1); + var x=new ctx.BIG(h); + var Q,X2,X4,X4; + for (;;) { + X2 = new ctx.FP2(one, x); + X4 = new ctx.FP4(X2); + X8 = new ctx.FP8(X4); + Q = new ECP8(); + Q.setx(X8,0); + if (!Q.is_infinity()) break; + x.inc(1); + x.norm(); + } + return Q; + }; */ + + /* Constant time Map to Point */ + ECP8.map2point = function (H) { + // Shallue and van de Woestijne method. + var sgn, ne; + var NY = new ctx.FP8(1); + var T = new ctx.FP8(H); + sgn = T.sign(); + + var Z = new ctx.FP(ctx.FP.RIADZG2A); + var X1 = new ctx.FP8(Z); + var A = ECP8.RHS(X1); + var W = new ctx.FP8(A); + + W.sqrt(null); + + var s = new ctx.FP(0); + s.rcopy(ctx.ROM_FIELD.SQRTm3); + Z.mul(s); + + T.sqr(); + var Y = new ctx.FP8(A); + Y.mul(T); + T.copy(NY); + T.add(Y); + T.norm(); + Y.rsub(NY); + Y.norm(); + NY.copy(T); + NY.mul(Y); + + NY.tmul(Z); + NY.inverse(null); + + W.tmul(Z); + if (W.sign() == 1) { + W.neg(); + W.norm(); + } + W.tmul(Z); + W.mul(H); + W.mul(Y); + W.mul(NY); + + var X3 = new ctx.FP8(X1); + X1.neg(); + X1.norm(); + X1.div2(); + var X2 = new ctx.FP8(X1); + X1.sub(W); + X1.norm(); + X2.add(W); + X2.norm(); + A.add(A); + A.add(A); + A.norm(); + T.sqr(); + T.mul(NY); + T.sqr(); + A.mul(T); + X3.add(A); + X3.norm(); + + Y.copy(ECP8.RHS(X2)); + X3.cmove(X2, Y.qr(null)); + Y.copy(ECP8.RHS(X1)); + X3.cmove(X1, Y.qr(null)); + Y.copy(ECP8.RHS(X3)); + Y.sqrt(null); + + ne = Y.sign() ^ sgn; + W.copy(Y); + W.neg(); + W.norm(); + Y.cmove(W, ne); + + var P = new ECP8(); + P.setxy(X3, Y); + return P; + }; + + /* Map octet string to curve point + ECP8.mapit = function(h) + { + var q=new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var dx=ctx.DBIG.fromBytes(h); + var x=dx.mod(q); + + var Q=ECP8.hap2point(x); + Q.cfp(); + return Q; + }; */ + + ECP8.frob_constants = function () { + var fa = new ctx.BIG(0), + fb = new ctx.BIG(0), + F = [], + X, + F0, + F1, + F2; + + fa.rcopy(ctx.ROM_FIELD.Fra); + fb.rcopy(ctx.ROM_FIELD.Frb); + X = new ctx.FP2(fa, fb); + + F0 = new ctx.FP2(X); + F0.sqr(); + F2 = new ctx.FP2(F0); + F2.mul_ip(); + F2.norm(); + F1 = new ctx.FP2(F2); + F1.sqr(); + F2.mul(F1); + + F2.mul_ip(); + F2.norm(); + + F1.copy(X); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + F1.mul_ip(); + F1.norm(); + F1.inverse(null); + F0.copy(F1); + F0.sqr(); + + F1.mul(F0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + F0.copy(F1); + F0.sqr(); + F1.mul(F0); + F0.mul_ip(); + F0.norm(); + F1.mul_ip(); + F1.norm(); + F1.mul_ip(); + F1.norm(); + } + /* + } + F0.mul_ip(); F0.norm(); + F1.mul(F0); */ + + F[0] = new ctx.FP2(F0); + F[1] = new ctx.FP2(F1); + F[2] = new ctx.FP2(F2); + return F; + }; + + return ECP8; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.ECP8 = ECP8; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/ff.js b/packages/bls-verify/src/vendor/amcl-js/src/ff.js new file mode 100644 index 000000000..772c36c7e --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/ff.js @@ -0,0 +1,1024 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE FF number class */ + +var FF = function (ctx) { + 'use strict'; + + /* General purpose Constructor */ + var FF = function (n) { + this.v = new Array(n); + this.length = n; + for (var i = 0; i < n; i++) { + this.v[i] = new ctx.BIG(0); + } + }; + + FF.FFLEN = ctx.config['@ML']; + FF.P_MBITS = ctx.BIG.MODBYTES * 8; + FF.P_OMASK = -1 << FF.P_MBITS % ctx.BIG.BASEBITS; + FF.P_FEXCESS = 1 << (ctx.BIG.BASEBITS * ctx.BIG.NLEN - FF.P_MBITS - 1); + FF.P_TBITS = FF.P_MBITS % ctx.BIG.BASEBITS; + FF.FF_BITS = ctx.BIG.BIGBITS * FF.FFLEN; + FF.HFLEN = FF.FFLEN / 2; /* Useful for half-size RSA private key operations */ + + FF.prototype = { + /* set to zero */ + + P_EXCESS: function () { + return ((this.v[this.length - 1].get(ctx.BIG.NLEN - 1) & FF.P_OMASK) >> FF.P_TBITS) + 1; + }, + + zero: function () { + for (var i = 0; i < this.length; i++) { + this.v[i].zero(); + } + + return this; + }, + + getlen: function () { + return this.length; + }, + + /* set to integer */ + set: function (m) { + this.zero(); + this.v[0].set(0, m & ctx.BIG.BMASK); + this.v[0].set(1, m >> ctx.BIG.BASEBITS); + }, + /* copy from FF b */ + copy: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].copy(b.v[i]); + } + }, + /* copy from FF b */ + rcopy: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].rcopy(b[i]); + } + }, + /* x=y<>n */ + sducopy: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].copy(b.v[this.length + i]); + } + }, + one: function () { + this.v[0].one(); + for (var i = 1; i < this.length; i++) { + this.v[i].zero(); + } + }, + /* test equals 0 */ + iszilch: function () { + for (var i = 0; i < this.length; i++) { + if (!this.v[i].iszilch()) { + return false; + } + } + + return true; + }, + /* shift right by BIGBITS-bit words */ + shrw: function (n) { + for (var i = 0; i < n; i++) { + this.v[i].copy(this.v[i + n]); + this.v[i + n].zero(); + } + }, + + /* shift left by BIGBITS-bit words */ + shlw: function (n) { + for (var i = 0; i < n; i++) { + this.v[n + i].copy(this.v[i]); + this.v[i].zero(); + } + }, + /* extract last bit */ + parity: function () { + return this.v[0].parity(); + }, + + lastbits: function (m) { + return this.v[0].lastbits(m); + }, + + /* recursive add */ + radd: function (vp, x, xp, y, yp, n) { + for (var i = 0; i < n; i++) { + this.v[vp + i].copy(x.v[xp + i]); + this.v[vp + i].add(y.v[yp + i]); + } + }, + + /* recursive inc */ + rinc: function (vp, y, yp, n) { + for (var i = 0; i < n; i++) { + this.v[vp + i].add(y.v[yp + i]); + } + }, + + /* recursive sub */ + rsub: function (vp, x, xp, y, yp, n) { + for (var i = 0; i < n; i++) { + this.v[vp + i].copy(x.v[xp + i]); + this.v[vp + i].sub(y.v[yp + i]); + } + }, + + /* recursive dec */ + rdec: function (vp, y, yp, n) { + for (var i = 0; i < n; i++) { + this.v[vp + i].sub(y.v[yp + i]); + } + }, + + /* simple add */ + add: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].add(b.v[i]); + } + }, + + /* simple sub */ + sub: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].sub(b.v[i]); + } + }, + + /* reverse sub */ + revsub: function (b) { + for (var i = 0; i < this.length; i++) { + this.v[i].rsub(b.v[i]); + } + }, + + /* increment/decrement by a small integer */ + inc: function (m) { + this.v[0].inc(m); + this.norm(); + }, + + dec: function (m) { + this.v[0].dec(m); + this.norm(); + }, + + /* normalise - but hold any overflow in top part unless n<0 */ + rnorm: function (vp, n) { + var trunc = false, + i, + carry; + + if (n < 0) { + /* -v n signals to do truncation */ + n = -n; + trunc = true; + } + + for (i = 0; i < n - 1; i++) { + carry = this.v[vp + i].norm(); + this.v[vp + i].xortop(carry << FF.P_TBITS); + this.v[vp + i + 1].inc(carry); + } + carry = this.v[vp + n - 1].norm(); + + if (trunc) { + this.v[vp + n - 1].xortop(carry << FF.P_TBITS); + } + + return this; + }, + + norm: function () { + this.rnorm(0, this.length); + }, + + /* shift left by one bit */ + shl: function () { + var delay_carry = 0, + i, + carry; + + for (i = 0; i < this.length - 1; i++) { + carry = this.v[i].fshl(1); + this.v[i].inc(delay_carry); + this.v[i].xortop(carry << FF.P_TBITS); + delay_carry = carry; + } + + this.v[this.length - 1].fshl(1); + this.v[this.length - 1].inc(delay_carry); + }, + + /* shift right by one bit */ + shr: function () { + var i, carry; + + for (i = this.length - 1; i > 0; i--) { + carry = this.v[i].fshr(1); + this.v[i - 1].ortop(carry << FF.P_TBITS); + } + + this.v[0].fshr(1); + }, + + /* Convert to Hex String */ + toString: function () { + var s = '', + i; + + this.norm(); + + for (i = this.length - 1; i >= 0; i--) { + s += this.v[i].toString(); + } + + return s; + }, + /* Convert FFs to/from byte arrays */ + toBytes: function (b) { + var i; + + for (i = 0; i < this.length; i++) { + this.v[i].tobytearray(b, (this.length - i - 1) * ctx.BIG.MODBYTES); + } + }, + + /* z=x*y, t is workspace */ + karmul: function (vp, x, xp, y, yp, t, tp, n) { + var nd2, d; + + if (n === 1) { + x.v[xp].norm(); + y.v[yp].norm(); + d = ctx.BIG.mul(x.v[xp], y.v[yp]); + this.v[vp + 1] = d.split(8 * ctx.BIG.MODBYTES); + this.v[vp].copy(d); + + return; + } + + nd2 = n / 2; + this.radd(vp, x, xp, x, xp + nd2, nd2); + this.rnorm(vp, nd2); /* Important - required for 32-bit build */ + this.radd(vp + nd2, y, yp, y, yp + nd2, nd2); + this.rnorm(vp + nd2, nd2); /* Important - required for 32-bit build */ + t.karmul(tp, this, vp, this, vp + nd2, t, tp + n, nd2); + this.karmul(vp, x, xp, y, yp, t, tp + n, nd2); + this.karmul(vp + n, x, xp + nd2, y, yp + nd2, t, tp + n, nd2); + t.rdec(tp, this, vp, n); + t.rdec(tp, this, vp + n, n); + this.rinc(vp + nd2, t, tp, n); + this.rnorm(vp, 2 * n); + }, + + karsqr: function (vp, x, xp, t, tp, n) { + var nd2, d; + + if (n === 1) { + x.v[xp].norm(); + d = ctx.BIG.sqr(x.v[xp]); + this.v[vp + 1].copy(d.split(8 * ctx.BIG.MODBYTES)); + this.v[vp].copy(d); + + return; + } + + nd2 = n / 2; + this.karsqr(vp, x, xp, t, tp + n, nd2); + this.karsqr(vp + n, x, xp + nd2, t, tp + n, nd2); + t.karmul(tp, x, xp, x, xp + nd2, t, tp + n, nd2); + this.rinc(vp + nd2, t, tp, n); + this.rinc(vp + nd2, t, tp, n); + this.rnorm(vp + nd2, n); + }, + + karmul_lower: function (vp, x, xp, y, yp, t, tp, n) { + /* Calculates Least Significant bottom half of x*y */ + var nd2; + + if (n === 1) { + /* only calculate bottom half of product */ + this.v[vp].copy(ctx.BIG.smul(x.v[xp], y.v[yp])); + + return; + } + + nd2 = n / 2; + + this.karmul(vp, x, xp, y, yp, t, tp + n, nd2); + t.karmul_lower(tp, x, xp + nd2, y, yp, t, tp + n, nd2); + this.rinc(vp + nd2, t, tp, nd2); + t.karmul_lower(tp, x, xp, y, yp + nd2, t, tp + n, nd2); + + this.rinc(vp + nd2, t, tp, nd2); + this.rnorm(vp + nd2, -nd2); /* truncate it */ + }, + + karmul_upper: function (x, y, t, n) { + /* Calculates Most Significant upper half of x*y, given lower part */ + var nd2; + + nd2 = n / 2; + this.radd(n, x, 0, x, nd2, nd2); + this.radd(n + nd2, y, 0, y, nd2, nd2); + this.rnorm(n, nd2); + this.rnorm(n + nd2, nd2); + + t.karmul(0, this, n + nd2, this, n, t, n, nd2); /* t = (a0+a1)(b0+b1) */ + this.karmul(n, x, nd2, y, nd2, t, n, nd2); /* z[n]= a1*b1 */ + /* z[0-nd2]=l(a0b0) z[nd2-n]= h(a0b0)+l(t)-l(a0b0)-l(a1b1) */ + t.rdec(0, this, n, n); /* t=t-a1b1 */ + this.rinc(nd2, this, 0, nd2); /* z[nd2-n]+=l(a0b0) = h(a0b0)+l(t)-l(a1b1) */ + this.rdec(nd2, t, 0, nd2); /* z[nd2-n]=h(a0b0)+l(t)-l(a1b1)-l(t-a1b1)=h(a0b0) */ + this.rnorm(0, -n); /* a0b0 now in z - truncate it */ + t.rdec(0, this, 0, n); /* (a0+a1)(b0+b1) - a0b0 */ + this.rinc(nd2, t, 0, n); + + this.rnorm(nd2, n); + }, + + /* return low part of product this*y */ + lmul: function (y) { + var n = this.length, + t = new FF(2 * n), + x = new FF(n); + + x.copy(this); + this.karmul_lower(0, x, 0, y, 0, t, 0, n); + }, + + /* Set b=b mod c */ + mod: function (c) { + var k = 0; + + this.norm(); + if (FF.comp(this, c) < 0) { + return; + } + + do { + c.shl(); + k++; + } while (FF.comp(this, c) >= 0); + + while (k > 0) { + c.shr(); + + if (FF.comp(this, c) >= 0) { + this.sub(c); + this.norm(); + } + + k--; + } + }, + + /* return This mod modulus, N is modulus, ND is Montgomery Constant */ + reduce: function (N, ND) { + /* fast karatsuba Montgomery reduction */ + var n = N.length, + t = new FF(2 * n), + r = new FF(n), + m = new FF(n); + + r.sducopy(this); + m.karmul_lower(0, this, 0, ND, 0, t, 0, n); + this.karmul_upper(N, m, t, n); + m.sducopy(this); + + r.add(N); + r.sub(m); + r.norm(); + + return r; + }, + + /* Set r=this mod b */ + /* this is of length - 2*n */ + /* r,b is of length - n */ + dmod: function (b) { + var n = b.length, + m = new FF(2 * n), + x = new FF(2 * n), + r = new FF(n), + k; + + x.copy(this); + x.norm(); + m.dsucopy(b); + k = ctx.BIG.BIGBITS * n; + + while (FF.comp(x, m) >= 0) { + x.sub(m); + x.norm(); + } + + while (k > 0) { + m.shr(); + + if (FF.comp(x, m) >= 0) { + x.sub(m); + x.norm(); + } + + k--; + } + + r.copy(x); + r.mod(b); + + return r; + }, + + /* Set return=1/this mod p. Binary method - a

= 0) { + u.sub(v); + u.norm(); + + if (FF.comp(x1, x2) >= 0) { + x1.sub(x2); + } else { + t.copy(p); + t.sub(x2); + x1.add(t); + } + + x1.norm(); + } else { + v.sub(u); + v.norm(); + + if (FF.comp(x2, x1) >= 0) { + x2.sub(x1); + } else { + t.copy(p); + t.sub(x1); + x2.add(t); + } + + x2.norm(); + } + } + + if (FF.comp(u, one) === 0) { + this.copy(x1); + } else { + this.copy(x2); + } + }, + + /* nresidue mod m */ + nres: function (m) { + var n = m.length, + d; + + if (n === 1) { + d = new ctx.DBIG(0); + d.hcopy(this.v[0]); + d.shl(ctx.BIG.NLEN * ctx.BIG.BASEBITS); + this.v[0].copy(d.mod(m.v[0])); + } else { + d = new FF(2 * n); + d.dsucopy(this); + this.copy(d.dmod(m)); + } + }, + + redc: function (m, ND) { + var n = m.length, + d; + + if (n === 1) { + d = new ctx.DBIG(0); + d.hcopy(this.v[0]); + this.v[0].copy(ctx.BIG.monty(m.v[0], (1 << ctx.BIG.BASEBITS) - ND.v[0].w[0], d)); + } else { + d = new FF(2 * n); + this.mod(m); + d.dscopy(this); + this.copy(d.reduce(m, ND)); + this.mod(m); + } + }, + + mod2m: function (m) { + for (var i = m; i < this.length; i++) { + this.v[i].zero(); + } + }, + + /* U=1/a mod 2^m - Arazi & Qi */ + invmod2m: function () { + var n = this.length, + b = new FF(n), + c = new FF(n), + U = new FF(n), + t, + i; + + U.zero(); + U.v[0].copy(this.v[0]); + U.v[0].invmod2m(); + + for (i = 1; i < n; i <<= 1) { + b.copy(this); + b.mod2m(i); + t = FF.mul(U, b); + t.shrw(i); + b.copy(t); + c.copy(this); + c.shrw(i); + c.mod2m(i); + c.lmul(U); + c.mod2m(i); + + b.add(c); + b.norm(); + b.lmul(U); + b.mod2m(i); + + c.one(); + c.shlw(i); + b.revsub(c); + b.norm(); + b.shlw(i); + U.add(b); + } + U.norm(); + + return U; + }, + + random: function (rng) { + var n = this.length, + i; + + for (i = 0; i < n; i++) { + this.v[i].copy(ctx.BIG.random(rng)); + } + + /* make sure top bit is 1 */ + while (this.v[n - 1].nbits() < ctx.BIG.MODBYTES * 8) { + this.v[n - 1].copy(ctx.BIG.random(rng)); + } + }, + + /* generate random x */ + randomnum: function (p, rng) { + var n = this.length, + d = new FF(2 * n), + i; + + for (i = 0; i < 2 * n; i++) { + d.v[i].copy(ctx.BIG.random(rng)); + } + + this.copy(d.dmod(p)); + }, + + /* this*=y mod p */ + modmul: function (y, p, nd) { + var ex = this.P_EXCESS(), + ey = y.P_EXCESS(), + n = p.length, + d; + + if (ex + 1 >= Math.floor((FF.P_FEXCESS - 1) / (ey + 1))) { + this.mod(p); + } + + if (n === 1) { + d = ctx.BIG.mul(this.v[0], y.v[0]); + this.v[0].copy(ctx.BIG.monty(p.v[0], (1 << ctx.BIG.BASEBITS) - nd.v[0].w[0], d)); + } else { + d = FF.mul(this, y); + this.copy(d.reduce(p, nd)); + } + }, + + /* this*=y mod p */ + modsqr: function (p, nd) { + var ex = this.P_EXCESS(), + n, + d; + + if (ex + 1 >= Math.floor((FF.P_FEXCESS - 1) / (ex + 1))) { + this.mod(p); + } + n = p.length; + + if (n === 1) { + d = ctx.BIG.sqr(this.v[0]); + this.v[0].copy(ctx.BIG.monty(p.v[0], (1 << ctx.BIG.BASEBITS) - nd.v[0].w[0], d)); + } else { + d = FF.sqr(this); + this.copy(d.reduce(p, nd)); + } + }, + + /* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */ + skpow: function (e, p) { + var n = p.length, + R0 = new FF(n), + R1 = new FF(n), + ND = p.invmod2m(), + i, + b; + + this.mod(p); + R0.one(); + R1.copy(this); + R0.nres(p); + R1.nres(p); + + for (i = 8 * ctx.BIG.MODBYTES * n - 1; i >= 0; i--) { + b = e.v[Math.floor(i / ctx.BIG.BIGBITS)].bit(i % ctx.BIG.BIGBITS); + + this.copy(R0); + this.modmul(R1, p, ND); + + FF.cswap(R0, R1, b); + R0.modsqr(p, ND); + + R1.copy(this); + FF.cswap(R0, R1, b); + } + + this.copy(R0); + this.redc(p, ND); + }, + + /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */ + skspow: function (e, p) { + var n = p.length, + R0 = new FF(n), + R1 = new FF(n), + ND = p.invmod2m(), + i, + b; + + this.mod(p); + R0.one(); + R1.copy(this); + R0.nres(p); + R1.nres(p); + + for (i = 8 * ctx.BIG.MODBYTES - 1; i >= 0; i--) { + b = e.bit(i); + this.copy(R0); + this.modmul(R1, p, ND); + + FF.cswap(R0, R1, b); + R0.modsqr(p, ND); + + R1.copy(this); + FF.cswap(R0, R1, b); + } + this.copy(R0); + this.redc(p, ND); + }, + + /* raise to an integer power - right-to-left method */ + power: function (e, p) { + var n = p.length, + f = true, + w = new FF(n), + ND = p.invmod2m(); + + w.copy(this); + w.nres(p); + + if (e == 2) { + this.copy(w); + this.modsqr(p, ND); + } else { + for (;;) { + if (e % 2 == 1) { + if (f) { + this.copy(w); + } else { + this.modmul(w, p, ND); + } + f = false; + } + e >>= 1; + if (e === 0) { + break; + } + w.modsqr(p, ND); + } + } + + this.redc(p, ND); + }, + + /* this=this^e mod p, faster but not side channel resistant */ + pow: function (e, p) { + var n = p.length, + w = new FF(n), + ND = p.invmod2m(), + i, + b; + + w.copy(this); + this.one(); + this.nres(p); + w.nres(p); + + for (i = 8 * ctx.BIG.MODBYTES * n - 1; i >= 0; i--) { + this.modsqr(p, ND); + b = e.v[Math.floor(i / ctx.BIG.BIGBITS)].bit(i % ctx.BIG.BIGBITS); + if (b === 1) { + this.modmul(w, p, ND); + } + } + + this.redc(p, ND); + }, + + /* double exponentiation r=x^e.y^f mod p */ + pow2: function (e, y, f, p) { + var n = p.length, + xn = new FF(n), + yn = new FF(n), + xy = new FF(n), + ND = p.invmod2m(), + i, + eb, + fb; + + xn.copy(this); + yn.copy(y); + xn.nres(p); + yn.nres(p); + xy.copy(xn); + xy.modmul(yn, p, ND); + this.one(); + this.nres(p); + + for (i = 8 * ctx.BIG.MODBYTES - 1; i >= 0; i--) { + eb = e.bit(i); + fb = f.bit(i); + this.modsqr(p, ND); + + if (eb == 1) { + if (fb == 1) { + this.modmul(xy, p, ND); + } else { + this.modmul(xn, p, ND); + } + } else { + if (fb == 1) { + this.modmul(yn, p, ND); + } + } + } + this.redc(p, ND); + }, + + /* quick and dirty check for common factor with n */ + cfactor: function (s) { + var n = this.length, + x = new FF(n), + y = new FF(n), + r, + g; + + y.set(s); + + x.copy(this); + x.norm(); + + do { + x.sub(y); + x.norm(); + while (!x.iszilch() && x.parity() === 0) { + x.shr(); + } + } while (FF.comp(x, y) > 0); + + g = x.v[0].get(0); + r = FF.igcd(s, g); + if (r > 1) { + return true; + } + + return false; + }, + }; + + /* compare x and y - must be normalised, and of same length */ + FF.comp = function (a, b) { + var i, j; + + for (i = a.length - 1; i >= 0; i--) { + j = ctx.BIG.comp(a.v[i], b.v[i]); + if (j !== 0) { + return j; + } + } + + return 0; + }; + + FF.fromBytes = function (x, b) { + var i; + + for (i = 0; i < x.length; i++) { + x.v[i] = ctx.BIG.frombytearray(b, (x.length - i - 1) * ctx.BIG.MODBYTES); + } + }; + + /* in-place swapping using xor - side channel resistant - lengths must be the same */ + FF.cswap = function (a, b, d) { + var i; + + for (i = 0; i < a.length; i++) { + a.v[i].cswap(b.v[i], d); + } + }; + + /* z=x*y. Assumes x and y are of same length. */ + FF.mul = function (x, y) { + var n = x.length, + z = new FF(2 * n), + t = new FF(2 * n); + + z.karmul(0, x, 0, y, 0, t, 0, n); + + return z; + }; + + /* z=x^2 */ + FF.sqr = function (x) { + var n = x.length, + z = new FF(2 * n), + t = new FF(2 * n); + + z.karsqr(0, x, 0, t, 0, n); + + return z; + }; + + FF.igcd = function (x, y) { + /* integer GCD, returns GCD of x and y */ + var r; + + if (y === 0) { + return x; + } + + while ((r = x % y) !== 0) { + x = y; + y = r; + } + + return y; + }; + + /* Miller-Rabin test for primality. Slow. */ + FF.prime = function (p, rng) { + var n = p.length, + s = 0, + loop, + d = new FF(n), + x = new FF(n), + unity = new FF(n), + nm1 = new FF(n), + sf = 4849845 /* 3*5*.. *19 */, + i, + j; + + p.norm(); + + if (p.cfactor(sf)) { + return false; + } + + unity.one(); + nm1.copy(p); + nm1.sub(unity); + nm1.norm(); + d.copy(nm1); + + while (d.parity() === 0) { + d.shr(); + s++; + } + + if (s === 0) { + return false; + } + + for (i = 0; i < 10; i++) { + x.randomnum(p, rng); + x.pow(d, p); + + if (FF.comp(x, unity) === 0 || FF.comp(x, nm1) === 0) { + continue; + } + + loop = false; + + for (j = 1; j < s; j++) { + x.power(2, p); + + if (FF.comp(x, unity) === 0) { + return false; + } + + if (FF.comp(x, nm1) === 0) { + loop = true; + break; + } + } + if (loop) { + continue; + } + + return false; + } + + return true; + }; + + return FF; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FF: FF, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp.js b/packages/bls-verify/src/vendor/amcl-js/src/fp.js new file mode 100644 index 000000000..2dee274e0 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp.js @@ -0,0 +1,833 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Finite Field arithmetic */ +/* CORE mod p functions */ + +var FP = function (ctx) { + 'use strict'; + + /* General purpose Constructor */ + var FP = function (x) { + if (x instanceof FP) { + this.f = new ctx.BIG(x.f); + this.XES = x.XES; + } else { + if (x instanceof ctx.BIG) { + this.f = new ctx.BIG(x); + } else { + if (x < 0) { + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + m.inc(x); + m.norm(); + this.f = new ctx.BIG(m); + } else { + this.f = new ctx.BIG(x); + } + } + this.XES = 1; + //if (x!=0) + if (!this.f.iszilch()) this.nres(); + } + }; + + FP.NOT_SPECIAL = 0; + FP.PSEUDO_MERSENNE = 1; + FP.GENERALISED_MERSENNE = 2; + FP.MONTGOMERY_FRIENDLY = 3; + + FP.ZERO = 0; + FP.ONE = 1; + FP.SPARSEST = 2; + FP.SPARSER = 3; + FP.SPARSE = 4; + FP.DENSE = 5; + + FP.NEGATOWER = 0; + FP.POSITOWER = 1; + + FP.MODBITS = ctx.config['@NBT']; + FP.PM1D2 = ctx.config['@M8']; + FP.RIADZ = ctx.config['@RZ']; + FP.RIADZG2A = ctx.config['@RZ2A']; + FP.RIADZG2B = ctx.config['@RZ2B']; + FP.MODTYPE = ctx.config['@MT']; + FP.QNRI = ctx.config['@QI']; + FP.TOWER = ctx.config['@TW']; + + FP.FEXCESS = (1 << ctx.config['@SH']) - 1; // 2^(BASEBITS*NLEN-MODBITS)-1 + FP.OMASK = -1 << FP.TBITS; + FP.TBITS = FP.MODBITS % ctx.BIG.BASEBITS; + FP.TMASK = (1 << FP.TBITS) - 1; + + FP.BIG_ENDIAN_SIGN = false; + + FP.prototype = { + /* set this=0 */ + zero: function () { + this.XES = 1; + this.f.zero(); + }, + + /* copy from a ctx.BIG in ROM */ + rcopy: function (y) { + this.f.rcopy(y); + this.nres(); + }, + + /* copy from another ctx.BIG */ + bcopy: function (y) { + this.f.copy(y); + this.nres(); + }, + + /* copy from another FP */ + copy: function (y) { + this.XES = y.XES; + this.f.copy(y.f); + }, + + /* conditional swap of a and b depending on d */ + cswap: function (b, d) { + this.f.cswap(b.f, d); + var t, + c = d; + c = ~(c - 1); + t = c & (this.XES ^ b.XES); + this.XES ^= t; + b.XES ^= t; + }, + + /* conditional copy of b to a depending on d */ + cmove: function (b, d) { + var c = d; + + c = ~(c - 1); + + this.f.cmove(b.f, d); + this.XES ^= (this.XES ^ b.XES) & c; + }, + + /* convert to Montgomery n-residue form */ + nres: function () { + var r, d; + + if (FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE) { + r = new ctx.BIG(); + r.rcopy(ctx.ROM_FIELD.R2modp); + + d = ctx.BIG.mul(this.f, r); + this.f.copy(FP.mod(d)); + this.XES = 2; + } else { + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + this.f.mod(m); + this.XES = 1; + } + + return this; + }, + + /* convert back to regular form */ + redc: function () { + var r = new ctx.BIG(0), + d, + w; + + r.copy(this.f); + + if (FP.MODTYPE != FP.PSEUDO_MERSENNE && FP.MODTYPE != FP.GENERALISED_MERSENNE) { + d = new ctx.DBIG(0); + d.hcopy(this.f); + w = FP.mod(d); + r.copy(w); + } + + return r; + }, + + /* convert this to string */ + toString: function () { + var s = this.redc().toString(); + return s; + }, + + /* test this=0 */ + iszilch: function () { + var c = new FP(0); + c.copy(this); + c.reduce(); + return c.f.iszilch(); + }, + + islarger: function () { + if (this.iszilch()) return; + var sx = new ctx.BIG(0); + sx.rcopy(ctx.ROM_FIELD.Modulus); + var fx = this.redc(); + sx.sub(fx); + sx.norm(); + return ctx.BIG.comp(fx, sx); + }, + + toBytes: function (b) { + this.redc().toBytes(b); + }, + + /* test this=1 */ + isunity: function () { + var c = new FP(0); + c.copy(this); + c.reduce(); + return c.redc().isunity(); + }, + + sign: function () { + if (FP.BIG_ENDIAN_SIGN) { + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + m.dec(1); + m.fshr(1); + var n = new FP(0); + n.copy(this); + n.reduce(); + var w = n.redc(); + var cp = ctx.BIG.comp(w, m); + return ((cp + 1) & 2) >> 1; + } else { + var c = new FP(0); + c.copy(this); + c.reduce(); + return c.redc().parity(); + } + }, + + /* reduce this mod Modulus */ + reduce: function () { + var q, + carry, + sr, + sb, + m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_FIELD.Modulus); + this.f.norm(); + + if (this.XES > 16) { + q = FP.quo(this.f, m); + carry = r.pmul(q); + r.w[ctx.BIG.NLEN - 1] += carry << ctx.BIG.BASEBITS; // correction - put any carry out back in again + this.f.sub(r); + this.f.norm(); + sb = 2; + } else { + sb = FP.logb2(this.XES - 1); + } + m.fshl(sb); + + while (sb > 0) { + // constant time... + sr = ctx.BIG.ssn(r, this.f, m); // optimized combined shift, subtract and norm + this.f.cmove(r, 1 - sr); + sb--; + } + + this.XES = 1; + }, + + /* set this=1 */ + one: function () { + this.f.one(); + this.nres(); + }, + + /* normalise this */ + norm: function () { + return this.f.norm(); + }, + + /* this*=b mod Modulus */ + mul: function (b) { + var d; + + if (this.XES * b.XES > FP.FEXCESS) { + this.reduce(); + } + + d = ctx.BIG.mul(this.f, b.f); + this.f.copy(FP.mod(d)); + this.XES = 2; + + return this; + }, + + /* this*=c mod Modulus where c is an int */ + imul: function (c) { + var s = false, + d, + n; + + if (c < 0) { + c = -c; + s = true; + } + + if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE) { + d = this.f.pxmul(c); + this.f.copy(FP.mod(d)); + this.XES = 2; + } else { + if (this.XES * c <= FP.FEXCESS) { + this.f.pmul(c); + this.XES *= c; + } else { + n = new FP(c); + this.mul(n); + } + } + + if (s) { + this.neg(); + this.norm(); + } + return this; + }, + + /* this*=this mod Modulus */ + sqr: function () { + var d, t; + + if (this.XES * this.XES > FP.FEXCESS) { + this.reduce(); + } + + d = ctx.BIG.sqr(this.f); + t = FP.mod(d); + this.f.copy(t); + this.XES = 2; + + return this; + }, + + /* this+=b */ + add: function (b) { + this.f.add(b.f); + this.XES += b.XES; + + if (this.XES > FP.FEXCESS) { + this.reduce(); + } + + return this; + }, + /* this=-this mod Modulus */ + neg: function () { + var m = new ctx.BIG(0), + sb; + + m.rcopy(ctx.ROM_FIELD.Modulus); + + sb = FP.logb2(this.XES - 1); + + m.fshl(sb); + this.XES = (1 << sb) + 1; + this.f.rsub(m); + + if (this.XES > FP.FEXCESS) { + this.reduce(); + } + + return this; + }, + + /* this-=b */ + sub: function (b) { + var n = new FP(0); + + n.copy(b); + n.neg(); + this.add(n); + + return this; + }, + + rsub: function (b) { + var n = new FP(0); + + n.copy(this); + n.neg(); + this.copy(b); + this.add(n); + }, + + /* this/=2 mod Modulus */ + div2: function () { + var p; + p = new ctx.BIG(0); + p.rcopy(ctx.ROM_FIELD.Modulus); + var pr = this.f.parity(); + var w = new ctx.BIG(0); + w.copy(this.f); + this.f.fshr(1); + w.add(p); + w.norm(); + w.fshr(1); + this.f.cmove(w, pr); + return this; + }, + + /* return jacobi symbol (this/Modulus) */ + jacobi: function () { + var p = new ctx.BIG(0), + w = this.redc(); + + p.rcopy(ctx.ROM_FIELD.Modulus); + + return w.jacobi(p); + }, + + /* return TRUE if this==a */ + equals: function (a) { + var ft = new FP(0); + ft.copy(this); + var sd = new FP(0); + sd.copy(a); + ft.reduce(); + sd.reduce(); + + if (ctx.BIG.comp(ft.f, sd.f) === 0) { + return true; + } + + return false; + }, + + /* return this^e mod Modulus */ + pow: function (e) { + var i, + w = [], + tb = [], + t = new ctx.BIG(e), + nb, + lsbs, + r; + this.norm(); + t.norm(); + nb = 1 + Math.floor((t.nbits() + 3) / 4); + + for (i = 0; i < nb; i++) { + lsbs = t.lastbits(4); + t.dec(lsbs); + t.norm(); + w[i] = lsbs; + t.fshr(4); + } + tb[0] = new FP(1); + tb[1] = new FP(this); + for (i = 2; i < 16; i++) { + tb[i] = new FP(tb[i - 1]); + tb[i].mul(this); + } + r = new FP(tb[w[nb - 1]]); + for (i = nb - 2; i >= 0; i--) { + r.sqr(); + r.sqr(); + r.sqr(); + r.sqr(); + r.mul(tb[w[i]]); + } + r.reduce(); + return r; + }, + + // return this^(p-3)/4 or this^(p-5)/8 + // See https://eprint.iacr.org/2018/1038 + fpow: function () { + var i, j, k, bw, w, c, nw, lo, m, n, nd, e; + var xp = []; + var ac = [1, 2, 3, 6, 12, 15, 30, 60, 120, 240, 255]; + // phase 1 + + xp[0] = new FP(this); // 1 + xp[1] = new FP(this); + xp[1].sqr(); // 2 + xp[2] = new FP(xp[1]); + xp[2].mul(this); //3 + xp[3] = new FP(xp[2]); + xp[3].sqr(); // 6 + xp[4] = new FP(xp[3]); + xp[4].sqr(); // 12 + xp[5] = new FP(xp[4]); + xp[5].mul(xp[2]); // 15 + xp[6] = new FP(xp[5]); + xp[6].sqr(); // 30 + xp[7] = new FP(xp[6]); + xp[7].sqr(); // 60 + xp[8] = new FP(xp[7]); + xp[8].sqr(); // 120 + xp[9] = new FP(xp[8]); + xp[9].sqr(); // 240 + xp[10] = new FP(xp[9]); + xp[10].mul(xp[5]); // 255 + + n = FP.MODBITS; + if (FP.MODTYPE == FP.GENERALISED_MERSENNE) + // Goldilocks ONLY + n /= 2; + + e = FP.PM1D2; + + n -= e + 1; + c = (ctx.ROM_FIELD.MConst + (1 << e) + 1) / (1 << (e + 1)); + + nd = 0; + while (c % 2 == 0) { + c /= 2; + n -= 1; + nd++; + } + + bw = 0; + w = 1; + while (w < c) { + w *= 2; + bw += 1; + } + k = w - c; + + i = 10; + var key = new FP(0); + if (k != 0) { + while (ac[i] > k) i--; + key.copy(xp[i]); + k -= ac[i]; + } + while (k != 0) { + i--; + if (ac[i] > k) continue; + key.mul(xp[i]); + k -= ac[i]; + } + + // phase 2 + xp[1].copy(xp[2]); + xp[2].copy(xp[5]); + xp[3].copy(xp[10]); + + j = 3; + m = 8; + nw = n - bw; + var t = new FP(0); + while (2 * m < nw) { + t.copy(xp[j++]); + for (i = 0; i < m; i++) t.sqr(); + xp[j].copy(xp[j - 1]); + xp[j].mul(t); + m *= 2; + } + lo = nw - m; + var r = new FP(xp[j]); + + while (lo != 0) { + m /= 2; + j--; + if (lo < m) continue; + lo -= m; + t.copy(r); + for (i = 0; i < m; i++) t.sqr(); + r.copy(t); + r.mul(xp[j]); + } + + // phase 3 + if (bw != 0) { + for (i = 0; i < bw; i++) r.sqr(); + r.mul(key); + } + + if (FP.MODTYPE == FP.GENERALISED_MERSENNE) { + // Goldilocks ONLY + key.copy(r); + r.sqr(); + r.mul(this); + for (i = 0; i < n + 1; i++) r.sqr(); + r.mul(key); + } + + for (i = 0; i < nd; i++) r.sqr(); + + return r; + }, + + // calculates r=x^(p-1-2^e)/2^{e+1) where 2^e|p-1 + progen: function () { + if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE) { + this.copy(this.fpow()); + return; + } + var e = FP.PM1D2; + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + m.dec(1); + m.shr(e); + m.dec(1); + m.fshr(1); + + this.copy(this.pow(m)); + }, + + /* this=1/this mod Modulus */ + inverse: function (h) { + var e = FP.PM1D2; + this.norm(); + var s = new FP(this); + for (var i = 0; i < e - 1; i++) { + s.sqr(); + s.mul(this); + } + if (h == null) this.progen(); + else this.copy(h); + + for (var i = 0; i <= e; i++) this.sqr(); + this.mul(s); + this.reduce(); + return this; + }, + + // Calculate both inverse and square root of x, return QR + invsqrt: function (i, s) { + var h = new FP(0); + var qr = this.qr(h); + s.copy(this.sqrt(h)); + i.copy(this); + i.inverse(h); + return qr; + }, + + /* test for Quadratic residue */ + qr: function (h) { + var r = new FP(this); + var e = FP.PM1D2; + r.progen(); + if (h != null) h.copy(r); + + r.sqr(); + r.mul(this); + for (var i = 0; i < e - 1; i++) r.sqr(); + + return r.isunity() ? 1 : 0; + }, + + /* return sqrt(this) mod Modulus */ + sqrt: function (h) { + var e = FP.PM1D2; + var g = new FP(this); + if (h == null) g.progen(); + else g.copy(h); + + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.ROI); + + var v = new FP(m); + + var t = new FP(g); + t.sqr(); + t.mul(this); + + var r = new FP(this); + r.mul(g); + var b = new FP(t); + + for (var k = e; k > 1; k--) { + for (var j = 1; j < k - 1; j++) b.sqr(); + var u = b.isunity() ? 0 : 1; + g.copy(r); + g.mul(v); + r.cmove(g, u); + v.sqr(); + g.copy(t); + g.mul(v); + t.cmove(g, u); + b.copy(t); + } + var sgn = r.sign(); + var nr = new FP(r); + nr.neg(); + nr.norm(); + r.cmove(nr, sgn); + return r; + }, + }; + + // Two for the price of One - See Hamburg https://eprint.iacr.org/2012/309.pdf + // Calculate inverse of i and square root of s, return QR + FP.tpo = function (i, s) { + var w = new FP(s); + var t = new FP(i); + w.mul(i); + t.mul(w); + var qr = t.invsqrt(i, s); + i.mul(w); + s.mul(i); + return qr; + }; + + FP.fromBytes = function (b) { + var t = ctx.BIG.fromBytes(b); + return new FP(t); + }; + + FP.rand = function (rng) { + var m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + var w = ctx.BIG.randomnum(m, rng); + return new FP(w); + }; + + FP.logb2 = function (v) { + var r; + + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + r = (((v + (v >>> 4)) & 0xf0f0f0f) * 0x1010101) >>> 24; + + return r; + }; + + FP.quo = function (n, m) { + var num, + den, + hb = ctx.BIG.CHUNK >> 1; + if (FP.TBITS < hb) { + var sh = hb - FP.TBITS; + num = (n.w[ctx.BIG.NLEN - 1] << sh) | (n.w[ctx.BIG.NLEN - 2] >> (ctx.BIG.BASEBITS - sh)); + den = (m.w[ctx.BIG.NLEN - 1] << sh) | (m.w[ctx.BIG.NLEN - 2] >> (ctx.BIG.BASEBITS - sh)); + } else { + num = n.w[ctx.BIG.NLEN - 1]; + den = m.w[ctx.BIG.NLEN - 1]; + } + return Math.floor(num / (den + 1)); + }; + + /* reduce a ctx.DBIG to a ctx.BIG using a "special" modulus */ + FP.mod = function (d) { + var b = new ctx.BIG(0), + i, + t, + v, + tw, + tt, + lo, + carry, + m, + dd; + + if (FP.MODTYPE == FP.PSEUDO_MERSENNE) { + t = d.split(FP.MODBITS); + b.hcopy(d); + + if (ctx.ROM_FIELD.MConst != 1) { + v = t.pmul(ctx.ROM_FIELD.MConst); + } else { + v = 0; + } + + t.add(b); + t.norm(); + + tw = t.w[ctx.BIG.NLEN - 1]; + t.w[ctx.BIG.NLEN - 1] &= FP.TMASK; + t.inc(ctx.ROM_FIELD.MConst * ((tw >> FP.TBITS) + (v << (ctx.BIG.BASEBITS - FP.TBITS)))); + // b.add(t); + t.norm(); + + return t; + } + + if (FP.MODTYPE == FP.MONTGOMERY_FRIENDLY) { + for (i = 0; i < ctx.BIG.NLEN; i++) { + d.w[ctx.BIG.NLEN + i] += d.muladd( + d.w[i], + ctx.ROM_FIELD.MConst - 1, + d.w[i], + ctx.BIG.NLEN + i - 1, + ); + } + + for (i = 0; i < ctx.BIG.NLEN; i++) { + b.w[i] = d.w[ctx.BIG.NLEN + i]; + } + + b.norm(); + } + + if (FP.MODTYPE == FP.GENERALISED_MERSENNE) { + // GoldiLocks Only + t = d.split(FP.MODBITS); + b.hcopy(d); + b.add(t); + dd = new ctx.DBIG(0); + dd.hcopy(t); + dd.shl(FP.MODBITS / 2); + + tt = dd.split(FP.MODBITS); + lo = new ctx.BIG(); + lo.hcopy(dd); + + b.add(tt); + b.add(lo); + //b.norm(); + tt.shl(FP.MODBITS / 2); + b.add(tt); + + carry = b.w[ctx.BIG.NLEN - 1] >> FP.TBITS; + b.w[ctx.BIG.NLEN - 1] &= FP.TMASK; + b.w[0] += carry; + + b.w[Math.floor(224 / ctx.BIG.BASEBITS)] += carry << 224 % ctx.BIG.BASEBITS; + b.norm(); + } + + if (FP.MODTYPE == FP.NOT_SPECIAL) { + m = new ctx.BIG(0); + m.rcopy(ctx.ROM_FIELD.Modulus); + + b.copy(ctx.BIG.monty(m, ctx.ROM_FIELD.MConst, d)); + } + + return b; + }; + + return FP; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP: FP, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp12.js b/packages/bls-verify/src/vendor/amcl-js/src/fp12.js new file mode 100644 index 000000000..3c1c3f016 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp12.js @@ -0,0 +1,1069 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Fp^12 functions */ + +/* FP12 elements are of the form a+i.b+i^2.c */ + +var FP12 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP12 = function (d, e, f) { + /* + if (!isNaN(d)) + { + this.a = new ctx.FP4(d); + this.b = new ctx.FP4(0); + this.c = new ctx.FP4(0); + if (d==1) this.stype=ctx.FP.ONE; + else this.stype=ctx.FP.SPARSEST; + } + else + { + if (d instanceof FP12) { + this.a = new ctx.FP4(d.a); + this.b = new ctx.FP4(d.b); + this.c = new ctx.FP4(d.c); + } else { + this.a = new ctx.FP4(d); + this.b = new ctx.FP4(e); + this.c = new ctx.FP4(f); + } + this.stype=ctx.FP.DENSE; + } +*/ + if (d instanceof FP12) { + // ignore e, d, which are assumed be undefined in this case + this.a = new ctx.FP4(d.a); + this.b = new ctx.FP4(d.b); + this.c = new ctx.FP4(d.c); + this.stype = ctx.FP.DENSE; + } else if (typeof d !== 'undefined' && typeof e !== 'undefined' && typeof f !== 'undefined') { + // all 3 components set to (can be anything that the FP4 constructor supports) + this.a = new ctx.FP4(d); + this.b = new ctx.FP4(e); + this.c = new ctx.FP4(f); + this.stype = ctx.FP.DENSE; + } else if (typeof d === 'number') { + // first component is number + this.a = new ctx.FP4(d); + this.b = new ctx.FP4(0); + this.c = new ctx.FP4(0); + if (d == 1) this.stype = ctx.FP.ONE; + else this.stype = ctx.FP.SPARSER; + } else { + // other cases, including `new ctx.FP12()` fall back to zero + this.a = new ctx.FP4(0); + this.b = new ctx.FP4(0); + this.c = new ctx.FP4(0); + this.stype = ctx.FP.ZERO; + } + }; + + FP12.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + this.c.reduce(); + }, + + /* normalize all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + this.c.norm(); + }, + + /* test x==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch() && this.c.iszilch(); + }, + + /* test x==1 ? */ + isunity: function () { + var one = new ctx.FP4(1); + return this.a.equals(one) && this.b.iszilch() && this.c.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + this.c.cmove(g.c, d); + d = ~(d - 1); + this.stype ^= (this.stype ^ g.stype) & d; + }, + + /* Constant time select from pre-computed table */ + select: function (g, b) { + var invf = new FP12(0), + m, + babs; + + m = b >> 31; + babs = (b ^ m) - m; + babs = (babs - 1) / 2; + + this.cmove(g[0], FP12.teq(babs, 0)); // conditional move + this.cmove(g[1], FP12.teq(babs, 1)); + this.cmove(g[2], FP12.teq(babs, 2)); + this.cmove(g[3], FP12.teq(babs, 3)); + this.cmove(g[4], FP12.teq(babs, 4)); + this.cmove(g[5], FP12.teq(babs, 5)); + this.cmove(g[6], FP12.teq(babs, 6)); + this.cmove(g[7], FP12.teq(babs, 7)); + + invf.copy(this); + invf.conj(); + this.cmove(invf, m & 1); + }, + + settype: function (w) { + this.stype = w; + }, + + gettype: function () { + return this.stype; + }, + + /* extract a from this */ + geta: function () { + return this.a; + }, + + /* extract b */ + getb: function () { + return this.b; + }, + + /* extract c */ + getc: function () { + return this.c; + }, + + /* return 1 if x==y, else 0 */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + this.c.copy(x.c); + this.stype = x.stype; + }, + + /* set this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ONE; + }, + + /* set this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ZERO; + }, + + /* this=conj(this) */ + conj: function () { + this.a.conj(); + this.b.nconj(); + this.c.conj(); + }, + + /* set this from 3 FP4s */ + set: function (d, e, f) { + this.a.copy(d); + this.b.copy(e); + this.c.copy(f); + this.stype = ctx.FP.DENSE; + }, + + /* set this from one ctx.FP4 */ + seta: function (d) { + this.a.copy(d); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.SPARSEST; + }, + + /* Granger-Scott Unitary Squaring */ + usqr: function () { + var A = new ctx.FP4(this.a), + B = new ctx.FP4(this.c), + C = new ctx.FP4(this.b), + D = new ctx.FP4(0); + + this.a.sqr(); + D.copy(this.a); + D.add(this.a); + this.a.add(D); + + A.nconj(); + + A.add(A); + this.a.add(A); + B.sqr(); + B.times_i(); + + D.copy(B); + D.add(B); + B.add(D); + + C.sqr(); + D.copy(C); + D.add(C); + C.add(D); + + this.b.conj(); + this.b.add(this.b); + this.c.nconj(); + + this.c.add(this.c); + this.b.add(B); + this.c.add(C); + this.stype = ctx.FP.DENSE; + this.reduce(); + }, + + /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ + sqr: function () { + if (this.stype == ctx.FP.ONE) return; + + var A = new ctx.FP4(this.a), + B = new ctx.FP4(this.b), + C = new ctx.FP4(this.c), + D = new ctx.FP4(this.a); + + A.sqr(); + B.mul(this.c); + B.add(B); + C.sqr(); + D.mul(this.b); + D.add(D); + + this.c.add(this.a); + this.c.add(this.b); + this.c.norm(); + this.c.sqr(); + + this.a.copy(A); + + A.add(B); + A.add(C); + A.add(D); + A.neg(); + B.times_i(); + C.times_i(); + + this.a.add(B); + this.b.copy(C); + this.b.add(D); + this.c.add(A); + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) this.stype = ctx.FP.SPARSE; + else this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP12 full multiplication this=this*y */ + mul: function (y) { + var z0 = new ctx.FP4(this.a), + z1 = new ctx.FP4(0), + z2 = new ctx.FP4(this.b), + z3 = new ctx.FP4(0), + t0 = new ctx.FP4(this.a), + t1 = new ctx.FP4(y.a); + + z0.mul(y.a); + z2.mul(y.b); + + t0.add(this.b); + t1.add(y.b); + + t0.norm(); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + + t1.copy(y.b); + t1.add(y.c); + + t0.norm(); + t1.norm(); + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t1.copy(y.a); + t1.add(y.c); + + t0.norm(); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + t0.copy(this.c); + t0.mul(y.c); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP12 multiplication w=w*y */ + /* catering for special case that arises from special form of ATE pairing line function */ + /* w and y are both sparser line functions - cost = 6m */ + smul: function (y) { + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + var w1 = new ctx.FP2(this.a.geta()); + var w2 = new ctx.FP2(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.b.geta().geta()); + t.mul(y.b.geta().geta()); + w3 = new ctx.FP2(t); + } else { + if (y.stype != ctx.FP.SPARSEST) { + w3 = new ctx.FP2(y.b.geta()); + w3.pmul(this.b.geta().geta()); + } else { + w3 = new ctx.FP2(this.b.geta()); + w3.pmul(y.b.geta().geta()); + } + } + } else { + w3 = new ctx.FP2(this.b.geta()); + w3.mul(y.b.geta()); + } + + var ta = new ctx.FP2(this.a.geta()); + var tb = new ctx.FP2(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP2(ta); + tc.mul(tb); + var t = new ctx.FP2(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.b.geta()); + tb.norm(); + var td = new ctx.FP2(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.b.geta()); + tb.norm(); + var te = new ctx.FP2(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.mul_ip(); + w1.add(w2); + + this.a.geta().copy(w1); + this.a.getb().copy(tc); + this.b.geta().copy(td); + this.b.getb().copy(te); + this.c.geta().copy(w3); + this.c.getb().zero(); + + this.a.norm(); + this.b.norm(); + } else { + var w1 = new ctx.FP2(this.a.geta()); + var w2 = new ctx.FP2(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.c.getb().geta()); + t.mul(y.c.getb().geta()); + w3 = new ctx.FP2(t); + } else { + if (y.type != ctx.FP.SPARSEST) { + w3 = new ctx.FP2(y.c.getb()); + w3.pmul(this.c.getb().geta()); + } else { + w3 = new ctx.FP2(this.c.getb()); + w3.pmul(y.c.getb().geta()); + } + } + } else { + w3 = new ctx.FP2(this.c.getb()); + w3.mul(y.c.getb()); + } + + var ta = new ctx.FP2(this.a.geta()); + var tb = new ctx.FP2(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP2(ta); + tc.mul(tb); + var t = new ctx.FP2(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.c.getb()); + tb.norm(); + var td = new ctx.FP2(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.c.getb()); + tb.norm(); + var te = new ctx.FP2(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.mul_ip(); + w1.add(w2); + this.a.geta().copy(w1); + this.a.getb().copy(tc); + + w3.mul_ip(); + w3.norm(); + this.b.geta().zero(); + this.b.getb().copy(w3); + + te.norm(); + te.mul_ip(); + this.c.geta().copy(te); + this.c.getb().copy(td); + + this.a.norm(); + this.c.norm(); + } + this.stype = ctx.FP.SPARSE; + }, + + /* FP12 full multiplication w=w*y */ + /* Supports sparse multiplicands */ + /* Usually w is denser than y */ + ssmul: function (y) { + if (this.stype == ctx.FP.ONE) { + this.copy(y); + return; + } + if (y.stype == ctx.FP.ONE) return; + + if (y.stype >= ctx.FP.SPARSE) { + var z0 = new ctx.FP4(this.a); + var z1 = new ctx.FP4(0); + var z2 = new ctx.FP4(0); + var z3 = new ctx.FP4(0); + z0.mul(y.a); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + z2.getb().copy(this.b.getb()); + z2.getb().mul(y.b.getb()); + z2.geta().zero(); + if (y.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.getb()); + z2.geta().mul(y.b.geta()); + } + if (this.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.geta()); + z2.geta().mul(y.b.getb()); + } + z2.times_i(); + } else { + z2.copy(this.b); + z2.mul(y.b); + } + } else { + z2.copy(this.b); + z2.mul(y.b); + } + var t0 = new ctx.FP4(this.a); + var t1 = new ctx.FP4(y.a); + t0.add(this.b); + t0.norm(); + t1.add(y.b); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + t1.copy(y.b); + t1.add(y.c); + t1.norm(); + + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + t0.geta().copy(this.c.geta()); + t0.geta().mul(y.c.geta()); + t0.getb().zero(); + if (y.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.geta()); + t0.getb().mul(y.c.getb()); + } + if (this.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.getb()); + t0.getb().mul(y.c.geta()); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } else { + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) { + this.smul(y); + return; + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + // dense by sparser - 13m + var z0 = new ctx.FP4(this.a); + var z2 = new ctx.FP4(this.b); + var z3 = new ctx.FP4(this.b); + var t0 = new ctx.FP4(0); + var t1 = new ctx.FP4(y.a); + z0.mul(y.a); + + if (y.stype == ctx.FP.SPARSEST) z2.qmul(y.b.geta().geta()); + else z2.pmul(y.b.geta()); + + this.b.add(this.a); + t1.real().add(y.b.geta()); + + t1.norm(); + this.b.norm(); + this.b.mul(t1); + z3.add(this.c); + z3.norm(); + if (y.stype == ctx.FP.SPARSEST) z3.qmul(y.b.geta().geta()); + else z3.pmul(y.b.geta()); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + this.b.add(t0); + + this.b.add(t1); + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + z3.norm(); + t0.mul(y.a); + this.c.copy(z2); + this.c.add(t0); + + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + var z0 = new ctx.FP4(this.a); + var z1 = new ctx.FP4(0); + var z2 = new ctx.FP4(0); + var z3 = new ctx.FP4(0); + var t0 = new ctx.FP4(this.a); + var t1 = new ctx.FP4(0); + + z0.mul(y.a); + t0.add(this.b); + t0.norm(); + + z1.copy(t0); + z1.mul(y.a); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + + z3.copy(t0); + + if (y.stype == ctx.FP.SPARSEST) z3.qmul(y.c.getb().geta()); + else z3.pmul(y.c.getb()); + z3.times_i(); + + t0.copy(z0); + t0.neg(); + z1.add(t0); + this.b.copy(z1); + z2.copy(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + t0.copy(this.c); + + if (y.stype == ctx.FP.SPARSEST) t0.qmul(y.c.getb().geta()); + else t0.pmul(y.c.getb()); + t0.times_i(); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + } + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* this=1/this */ + inverse: function () { + var f0 = new ctx.FP4(this.a), + f1 = new ctx.FP4(this.b), + f2 = new ctx.FP4(this.a), + f3 = new ctx.FP4(0); + + f0.sqr(); + f1.mul(this.c); + f1.times_i(); + f0.sub(f1); + f0.norm(); + + f1.copy(this.c); + f1.sqr(); + f1.times_i(); + f2.mul(this.b); + f1.sub(f2); + f1.norm(); + + f2.copy(this.b); + f2.sqr(); + f3.copy(this.a); + f3.mul(this.c); + f2.sub(f3); + f2.norm(); + + f3.copy(this.b); + f3.mul(f2); + f3.times_i(); + this.a.mul(f0); + f3.add(this.a); + this.c.mul(f1); + this.c.times_i(); + + f3.add(this.c); + f3.norm(); + f3.inverse(null); + this.a.copy(f0); + this.a.mul(f3); + this.b.copy(f1); + this.b.mul(f3); + this.c.copy(f2); + this.c.mul(f3); + this.stype = ctx.FP.DENSE; + }, + + /* this=this^p, where p=Modulus, using Frobenius */ + frob: function (f) { + var f2 = new ctx.FP2(f), + f3 = new ctx.FP2(f); + + f2.sqr(); + f3.mul(f2); + + this.a.frob(f3); + this.b.frob(f3); + this.c.frob(f3); + + this.b.pmul(f); + this.c.pmul(f2); + this.stype = ctx.FP.DENSE; + }, + + /* trace function */ + trace: function () { + var t = new ctx.FP4(0); + + t.copy(this.a); + t.imul(3); + t.reduce(); + + return t; + }, + + /* convert this to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ',' + this.c.toString() + ']'; + }, + + /* convert this to byte array */ + toBytes: function (w) { + var t = []; + this.c.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i] = t[i]; + this.b.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 4 * ctx.BIG.MODBYTES] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 8 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* set this=this^e */ + pow: function (e) { + var e1, e3, w, nb, i, bt, sf; + e1 = new ctx.BIG(e); + e1.norm(); + e3 = new ctx.BIG(e1); + e3.pmul(3); + e3.norm(); + + sf = new FP12(this); + sf.norm(); + w = new FP12(sf); + if (e3.iszilch()) { + w.one(); + return w; + } + nb = e3.nbits(); + + for (i = nb - 2; i >= 1; i--) { + w.usqr(); + bt = e3.bit(i) - e1.bit(i); + + if (bt == 1) { + w.mul(sf); + } + if (bt == -1) { + sf.conj(); + w.mul(sf); + sf.conj(); + } + } + w.reduce(); + + return w; + }, + + /* constant time powering by small integer of max length bts */ + pinpow: function (e, bts) { + var R = [], + i, + b; + + R[0] = new FP12(1); + R[1] = new FP12(this); + + for (i = bts - 1; i >= 0; i--) { + b = (e >> i) & 1; + R[1 - b].mul(R[b]); + R[b].usqr(); + } + + this.copy(R[0]); + }, + + /* Faster compressed powering for unitary elements */ + compow: function (e, r) { + var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + + m = new ctx.BIG(q); + m.mod(r); + + a = new ctx.BIG(e); + a.mod(m); + + b = new ctx.BIG(e); + b.div(m); + + g1 = new FP12(0); + g2 = new FP12(0); + g1.copy(this); + + c = g1.trace(); + + if (b.iszilch()) { + c = c.xtr_pow(e); + return c; + } + + g2.copy(g1); + g2.frob(f); + cp = g2.trace(); + g1.conj(); + g2.mul(g1); + cpm1 = g2.trace(); + g2.mul(g1); + cpm2 = g2.trace(); + + c = c.xtr_pow2(cp, cpm1, cpm2, a, b); + return c; + }, + }; + + /* convert from byte array to FP12 */ + FP12.fromBytes = function (w) { + var a, b, c; + var t = []; + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = w[i]; + c = ctx.FP4.fromBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 4 * ctx.BIG.MODBYTES]; + b = ctx.FP4.fromBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 8 * ctx.BIG.MODBYTES]; + a = ctx.FP4.fromBytes(t); + return new FP12(a, b, c); + }; + + /* return 1 if b==c, no branching */ + FP12.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* p=q0^u0.q1^u1.q2^u2.q3^u3 */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + FP12.pow4 = function (q, u) { + var g = [], + r = new FP12(0), + p = new FP12(0), + t = [], + mt = new ctx.BIG(0), + w = [], + s = [], + i, + j, + k, + nb, + bt, + pb; + + for (i = 0; i < 4; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + } + + g[0] = new FP12(q[0]); // q[0] + g[1] = new FP12(g[0]); + g[1].mul(q[1]); // q[0].q[1] + g[2] = new FP12(g[0]); + g[2].mul(q[2]); // q[0].q[2] + g[3] = new FP12(g[1]); + g[3].mul(q[2]); // q[0].q[1].q[2] + g[4] = new FP12(q[0]); + g[4].mul(q[3]); // q[0].q[3] + g[5] = new FP12(g[1]); + g[5].mul(q[3]); // q[0].q[1].q[3] + g[6] = new FP12(g[2]); + g[6].mul(q[3]); // q[0].q[2].q[3] + g[7] = new FP12(g[3]); + g[7].mul(q[3]); // q[0].q[1].q[2].q[3] + + // Make it odd + pb = 1 - t[0].parity(); + t[0].inc(pb); + t[0].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 4; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s[i] = 2 * t[0].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w[i] += bt * k; + k *= 2; + } + } + + // Main loop + p.select(g, 2 * w[nb - 1] + 1); + for (i = nb - 2; i >= 0; i--) { + p.usqr(); + r.select(g, 2 * w[i] + s[i]); + p.mul(r); + } + + // apply correction + r.copy(q[0]); + r.conj(); + r.mul(p); + p.cmove(r, pb); + + p.reduce(); + return p; + }; + + return FP12; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP12: FP12, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp16.js b/packages/bls-verify/src/vendor/amcl-js/src/fp16.js new file mode 100644 index 000000000..8ce7919e0 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp16.js @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Finite Field arithmetic Fp^16 functions */ + +/* FP16 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */ + +var FP16 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP16 = function (c, d) { + if (c instanceof FP16) { + this.a = new ctx.FP8(c.a); + this.b = new ctx.FP8(c.b); + } else { + this.a = new ctx.FP8(c); + this.b = new ctx.FP8(d); + } + }; + + FP16.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + }, + + /* normalise all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + }, + + /* test this==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch(); + }, + + toBytes: function (bf) { + var t = []; + this.b.toBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) bf[i] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) bf[i + 2 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* test this==1 ? */ + isunity: function () { + var one = new ctx.FP8(1); + return this.a.equals(one) && this.b.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + }, + + /* test is w real? That is in a+ib test b is zero */ + isreal: function () { + return this.b.iszilch(); + }, + + /* extract real part a */ + real: function () { + return this.a; + }, + + geta: function () { + return this.a; + }, + + /* extract imaginary part b */ + getb: function () { + return this.b; + }, + + /* test this=x? */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + }, + + /* this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + }, + + /* this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + }, + + /* set from two FP8s */ + set: function (c, d) { + this.a.copy(c); + this.b.copy(d); + }, + + /* set a */ + seta: function (c) { + this.a.copy(c); + this.b.zero(); + }, + + /* this=-this */ + neg: function () { + var m = new ctx.FP8(this.a), + t = new ctx.FP8(0); + + this.norm(); + m.add(this.b); + m.neg(); + + t.copy(m); + t.add(this.b); + this.b.copy(m); + this.b.add(this.a); + this.a.copy(t); + this.norm(); + }, + + /* this=conjugate(this) */ + conj: function () { + this.b.neg(); + this.norm(); + }, + + /* this=-conjugate(this) */ + nconj: function () { + this.a.neg(); + this.norm(); + }, + + /* this+=x */ + add: function (x) { + this.a.add(x.a); + this.b.add(x.b); + }, + + /* this-=x */ + sub: function (x) { + var m = new FP16(x); + m.neg(); + this.add(m); + }, + + /* this*=s where s is FP8 */ + pmul: function (s) { + this.a.mul(s); + this.b.mul(s); + }, + + /* this*=s where s is FP2 */ + qmul: function (s) { + this.a.qmul(s); + this.b.qmul(s); + }, + + /* this*=c where s is int */ + imul: function (c) { + this.a.imul(c); + this.b.imul(c); + }, + + /* this*=this */ + sqr: function () { + var t1 = new ctx.FP8(this.a), + t2 = new ctx.FP8(this.b), + t3 = new ctx.FP8(this.a); + + t3.mul(this.b); + t1.add(this.b); + t1.norm(); + t2.times_i(); + + t2.add(this.a); + t2.norm(); + this.a.copy(t1); + + this.a.mul(t2); + + t2.copy(t3); + t2.times_i(); + t2.add(t3); + + t2.neg(); + + this.a.add(t2); + + this.b.copy(t3); + this.b.add(t3); + + this.norm(); + }, + + /* this*=y */ + mul: function (y) { + var t1 = new ctx.FP8(this.a), + t2 = new ctx.FP8(this.b), + t3 = new ctx.FP8(0), + t4 = new ctx.FP8(this.b); + + t1.mul(y.a); + t2.mul(y.b); + t3.copy(y.b); + t3.add(y.a); + t4.add(this.a); + + t3.norm(); + t4.norm(); + + t4.mul(t3); + + t3.copy(t1); + t3.neg(); + t4.add(t3); + + t3.copy(t2); + t3.neg(); + this.b.copy(t4); + this.b.add(t3); + + t2.times_i(); + this.a.copy(t2); + this.a.add(t1); + + this.norm(); + }, + + /* convert to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ']'; + }, + + /* this=1/this */ + inverse: function () { + //this.norm(); + + var t1 = new ctx.FP8(this.a), + t2 = new ctx.FP8(this.b); + + t1.sqr(); + t2.sqr(); + t2.times_i(); + t2.norm(); // ?? + t1.sub(t2); + t1.inverse(null); + this.a.mul(t1); + t1.neg(); + t1.norm(); + this.b.mul(t1); + }, + + /* this*=i where i = sqrt(-1+sqrt(-1)) */ + times_i: function () { + var s = new ctx.FP8(this.b), + t = new ctx.FP8(this.a); + + s.times_i(); + this.b.copy(t); + + this.a.copy(s); + this.norm(); + }, + + times_i2: function () { + this.a.times_i(); + this.b.times_i(); + }, + + times_i4: function () { + this.a.times_i2(); + this.b.times_i2(); + }, + + /* this=this^q using Frobenius, where q is Modulus */ + frob: function (f) { + var ff = new ctx.FP2(f); + ff.sqr(); + ff.norm(); + this.a.frob(ff); + this.b.frob(ff); + this.b.qmul(f); + this.b.times_i(); + }, + + /* this=this^e */ + pow: function (e) { + var w = new FP16(this), + z = new ctx.BIG(e), + r = new FP16(1), + bt; + w.norm(); + z.norm(); + for (;;) { + bt = z.parity(); + z.fshr(1); + + if (bt === 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + + w.sqr(); + } + r.reduce(); + + return r; + }, + + /* XTR xtr_a function */ + /* + xtr_A: function(w, y, z) { + var r = new FP16(w), + t = new FP16(w); + + r.sub(y); + r.norm(); + r.pmul(this.a); + t.add(y); + t.norm(); + t.pmul(this.b); + t.times_i(); + + this.copy(r); + this.add(t); + this.add(z); + + this.reduce(); + }, +*/ + /* XTR xtr_d function */ + /* + xtr_D: function() { + var w = new FP16(this); + this.sqr(); + w.conj(); + w.add(w); + this.sub(w); + this.reduce(); + }, +*/ + /* r=x^n using XTR method on traces of FP48s */ + /* + xtr_pow: function(n) { + var sf = new FP16(this); + sf.norm(); + var a = new FP16(3), + b = new FP16(sf), + c = new FP16(b), + t = new FP16(0), + r = new FP16(0), + par, v, nb, i; + + c.xtr_D(); + + + par = n.parity(); + v = new ctx.BIG(n); + v.norm(); + v.fshr(1); + + if (par === 0) { + v.dec(1); + v.norm(); + } + + nb = v.nbits(); + for (i = nb - 1; i >= 0; i--) { + if (v.bit(i) != 1) { + t.copy(b); + sf.conj(); + c.conj(); + b.xtr_A(a, sf, c); + sf.conj(); + c.copy(t); + c.xtr_D(); + a.xtr_D(); + } else { + t.copy(a); + t.conj(); + a.copy(b); + a.xtr_D(); + b.xtr_A(c, sf, t); + c.xtr_D(); + } + } + + if (par === 0) { + r.copy(c); + } else { + r.copy(b); + } + r.reduce(); + + return r; + }, +*/ + /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP48s. See Stam thesis. */ + /* + xtr_pow2: function(ck, ckml, ckm2l, a, b) { + + var e = new ctx.BIG(a), + d = new ctx.BIG(b), + w = new ctx.BIG(0), + cu = new FP16(ck), + cv = new FP16(this), + cumv = new FP16(ckml), + cum2v = new FP16(ckm2l), + r = new FP16(0), + t = new FP16(0), + f2 = 0, + i; + + d.norm(); + e.norm(); + + while (d.parity() === 0 && e.parity() === 0) { + d.fshr(1); + e.fshr(1); + f2++; + } + + while (ctx.BIG.comp(d, e) !== 0) { + if (ctx.BIG.comp(d, e) > 0) { + w.copy(e); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(d, w) <= 0) { + w.copy(d); + d.copy(e); + e.rsub(w); + e.norm(); + + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cum2v.conj(); + cumv.copy(cv); + cv.copy(cu); + cu.copy(t); + + } else if (d.parity() === 0) { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } else if (e.parity() == 1) { + d.sub(e); + d.norm(); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cu.xtr_D(); + cum2v.copy(cv); + cum2v.xtr_D(); + cum2v.conj(); + cv.copy(t); + } else { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } + } + if (ctx.BIG.comp(d, e) < 0) { + w.copy(d); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(e, w) <= 0) { + e.sub(d); + e.norm(); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cumv.copy(cu); + cu.copy(t); + } else if (e.parity() === 0) { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } else if (d.parity() == 1) { + w.copy(e); + e.copy(d); + w.sub(d); + w.norm(); + d.copy(w); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cumv.conj(); + cum2v.copy(cu); + cum2v.xtr_D(); + cum2v.conj(); + cu.copy(cv); + cu.xtr_D(); + cv.copy(t); + } else { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } + } + } + r.copy(cv); + r.xtr_A(cu, cumv, cum2v); + for (i = 0; i < f2; i++) { + r.xtr_D(); + } + r = r.xtr_pow(d); + return r; + } +*/ + }; + + FP16.fromBytes = function (bf) { + var t = []; + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = bf[i]; + var tb = ctx.FP8.fromBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = bf[i + 8 * ctx.BIG.MODBYTES]; + var ta = ctx.FP8.fromBytes(t); + return new FP16(ta, tb); + }; + + return FP16; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP16: FP16, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp2.js b/packages/bls-verify/src/vendor/amcl-js/src/fp2.js new file mode 100644 index 000000000..baf3edf14 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp2.js @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Finite Field arithmetic Fp^2 functions */ + +/* FP2 elements are of the form a+ib, where i is sqrt(-1) */ + +var FP2 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP2 = function (c, d) { + if (c instanceof FP2) { + this.a = new ctx.FP(c.a); + this.b = new ctx.FP(c.b); + } else { + this.a = new ctx.FP(c); + this.b = new ctx.FP(d); + } + }; + + FP2.prototype = { + /* reduce components mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + }, + + /* normalise components of w */ + norm: function () { + this.a.norm(); + this.b.norm(); + }, + + /* test this=0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch(); + }, + + islarger: function () { + if (this.iszilch()) return 0; + var cmp = this.b.islarger(); + if (cmp != 0) return cmp; + return this.a.islarger(); + }, + + toBytes: function (bf) { + var t = []; + this.b.toBytes(t); + for (var i = 0; i < ctx.BIG.MODBYTES; i++) bf[i] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < ctx.BIG.MODBYTES; i++) bf[i + ctx.BIG.MODBYTES] = t[i]; + }, + + /* test this=1 ? */ + isunity: function () { + var one = new ctx.FP(1); + return this.a.equals(one) && this.b.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + }, + + /* test this=x */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b); + }, + + /* extract a */ + + geta: function () { + return this.a; + }, + + getA: function () { + return this.a.redc(); + }, + + /* extract b */ + getb: function () { + return this.b; + }, + + getB: function () { + return this.b.redc(); + }, + + /* set from pair of FPs */ + set: function (c, d) { + this.a.copy(c); + this.b.copy(d); + }, + + /* set a */ + seta: function (c) { + this.a.copy(c); + this.b.zero(); + }, + + /* set from two BIGs */ + bset: function (c, d) { + this.a.bcopy(c); + this.b.bcopy(d); + }, + + /* set from one ctx.BIG */ + bseta: function (c) { + this.a.bcopy(c); + this.b.zero(); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + }, + + /* set this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + }, + + /* set this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + }, + + sign: function () { + var p1 = this.a.sign(); + var p2 = this.b.sign(); + if (ctx.FP.BIG_ENDIAN_SIGN) { + var u = this.b.iszilch() ? 1 : 0; + p2 ^= (p1 ^ p2) & u; + return p2; + } else { + var u = this.a.iszilch() ? 1 : 0; + p1 ^= (p1 ^ p2) & u; + return p1; + } + }, + + /* negate this */ + neg: function () { + var m = new ctx.FP(this.a), + t = new ctx.FP(0); + + m.add(this.b); + m.neg(); + t.copy(m); + t.add(this.b); + this.b.copy(m); + this.b.add(this.a); + this.a.copy(t); + }, + + /* conjugate this */ + conj: function () { + this.b.neg(); + this.b.norm(); + }, + + /* this+=a */ + add: function (x) { + this.a.add(x.a); + this.b.add(x.b); + }, + + /* this-=x */ + sub: function (x) { + var m = new FP2(x); + m.neg(); + this.add(m); + }, + + rsub: function (x) { + this.neg(); + this.add(x); + }, + + /* this*=s, where s is FP */ + pmul: function (s) { + this.a.mul(s); + this.b.mul(s); + }, + + /* this*=c, where s is int */ + imul: function (c) { + this.a.imul(c); + this.b.imul(c); + }, + + /* this*=this */ + sqr: function () { + var w1 = new ctx.FP(this.a), + w3 = new ctx.FP(this.a), + mb = new ctx.FP(this.b); + + w1.add(this.b); + w3.add(this.a); + w3.norm(); + this.b.mul(w3); + + mb.neg(); + this.a.add(mb); + + this.a.norm(); + w1.norm(); + + this.a.mul(w1); + }, + + /* this*=y */ + /* Now using Lazy reduction - inputs must be normed */ + mul: function (y) { + var p = new ctx.BIG(0), + pR = new ctx.DBIG(0), + A, + B, + C, + D, + E, + F; + + p.rcopy(ctx.ROM_FIELD.Modulus); + pR.ucopy(p); + + if ((this.a.XES + this.b.XES) * (y.a.XES + y.b.XES) > ctx.FP.FEXCESS) { + if (this.a.XES > 1) { + this.a.reduce(); + } + + if (this.b.XES > 1) { + this.b.reduce(); + } + } + + A = ctx.BIG.mul(this.a.f, y.a.f); + B = ctx.BIG.mul(this.b.f, y.b.f); + + C = new ctx.BIG(this.a.f); + D = new ctx.BIG(y.a.f); + + C.add(this.b.f); + C.norm(); + D.add(y.b.f); + D.norm(); + + E = ctx.BIG.mul(C, D); + F = new ctx.DBIG(0); + F.copy(A); + F.add(B); + B.rsub(pR); + + A.add(B); + A.norm(); + E.sub(F); + E.norm(); + + this.a.f.copy(ctx.FP.mod(A)); + this.a.XES = 3; + this.b.f.copy(ctx.FP.mod(E)); + this.b.XES = 2; + }, + + /* this^e */ + /* + pow: function(e) { + var r = new FP2(1), + w = new FP2(this), + z = new ctx.BIG(e), + bt; + + for (;;) { + bt = z.parity(); + z.fshr(1); + if (bt == 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + w.sqr(); + } + + r.reduce(); + this.copy(r); + }, */ + + qr: function (h) { + var c = new FP2(this); + c.conj(); + c.mul(this); + + return c.geta().qr(h); + }, + + /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */ + sqrt: function (h) { + var w1, w2, w3, w4, hint; + + if (this.iszilch()) { + return; + } + + w1 = new ctx.FP(this.b); + w2 = new ctx.FP(this.a); + w3 = new ctx.FP(this.a); + w4 = new ctx.FP(this.a); + hint = new ctx.FP(this.a); + + w1.sqr(); + w2.sqr(); + w1.add(w2); + w1.norm(); + + w1 = w1.sqrt(h); + + w2.copy(this.a); + w2.add(w1); + w2.norm(); + w2.div2(); + + w1.copy(this.b); + w1.div2(); + var qr = w2.qr(hint); + + // tweak hint + w3.copy(hint); + w3.neg(); + w3.norm(); + w4.copy(w2); + w4.neg(); + w4.norm(); + + w2.cmove(w4, 1 - qr); + hint.cmove(w3, 1 - qr); + + this.a.copy(w2.sqrt(hint)); + w3.copy(w2); + w3.inverse(hint); + w3.mul(this.a); + this.b.copy(w3); + this.b.mul(w1); + w4.copy(this.a); + + this.a.cmove(this.b, 1 - qr); + this.b.cmove(w4, 1 - qr); + + /* + this.a.copy(w2.sqrt(hint)); + w3.copy(w2); w3.inverse(hint); + w3.mul(this.a); + this.b.copy(w3); this.b.mul(w1); + + hint.neg(); hint.norm(); + w2.neg(); w2.norm(); + + w4.copy(w2.sqrt(hint)); + w3.copy(w2); w3.inverse(hint); + w3.mul(w4); + w3.mul(w1); + + this.a.cmove(w3,1-qr); + this.b.cmove(w4,1-qr); +*/ + var sgn = this.sign(); + var nr = new FP2(this); + nr.neg(); + nr.norm(); + this.cmove(nr, sgn); + }, + + /* convert this to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ']'; + }, + + /* this=1/this */ + inverse: function (h) { + var w1, w2; + + this.norm(); + + w1 = new ctx.FP(this.a); + w2 = new ctx.FP(this.b); + + w1.sqr(); + w2.sqr(); + w1.add(w2); + w1.inverse(h); + this.a.mul(w1); + w1.neg(); + w1.norm(); + this.b.mul(w1); + }, + + /* this/=2 */ + div2: function () { + this.a.div2(); + this.b.div2(); + }, + + /* this*=sqrt(-1) */ + times_i: function () { + var z = new ctx.FP(this.a); //z.copy(this.a); + this.a.copy(this.b); + this.a.neg(); + this.b.copy(z); + }, + + /* w*=(1+sqrt(-1)) */ + /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */ + mul_ip: function () { + var t = new FP2(this); + var i = ctx.FP.QNRI; + this.times_i(); + while (i > 0) { + t.add(t); + t.norm(); + i--; + } + this.add(t); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.norm(); + this.neg(); + } + }, + + /* w/=(1+sqrt(-1)) */ + div_ip: function () { + var z = new FP2(1 << ctx.FP.QNRI, 1); + z.inverse(null); + this.mul(z); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.neg(); + this.norm(); + } + }, + }; + + FP2.rand = function (rng) { + return new FP2(ctx.FP.rand(rng), ctx.FP.rand(rng)); + }; + + FP2.fromBytes = function (bf) { + var t = []; + for (var i = 0; i < ctx.BIG.MODBYTES; i++) t[i] = bf[i]; + var tb = ctx.FP.fromBytes(t); + for (var i = 0; i < ctx.BIG.MODBYTES; i++) t[i] = bf[i + ctx.BIG.MODBYTES]; + var ta = ctx.FP.fromBytes(t); + return new FP2(ta, tb); + }; + + return FP2; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP2: FP2, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp24.js b/packages/bls-verify/src/vendor/amcl-js/src/fp24.js new file mode 100644 index 000000000..768bf1cd4 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp24.js @@ -0,0 +1,1131 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Fp^24 functions */ + +/* FP24 elements are of the form a+i.b+i^2.c */ + +var FP24 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP24 = function (d, e, f) { + /* + if (!isNaN(d)) + { + this.a = new ctx.FP8(d); + this.b = new ctx.FP8(0); + this.c = new ctx.FP8(0); + if (d==1) this.stype=ctx.FP.ONE; + else this.stype=ctx.FP.SPARSEST; + } + else + { + if (d instanceof FP24) { + this.a = new ctx.FP8(d.a); + this.b = new ctx.FP8(d.b); + this.c = new ctx.FP8(d.c); + } else { + this.a = new ctx.FP8(d); + this.b = new ctx.FP8(e); + this.c = new ctx.FP8(f); + } + this.stype=ctx.FP.DENSE; + } +*/ + + if (d instanceof FP24) { + // ignore e, d, which are assumed be undefined in this case + this.a = new ctx.FP8(d.a); + this.b = new ctx.FP8(d.b); + this.c = new ctx.FP8(d.c); + this.stype = ctx.FP.DENSE; + } else if (typeof d !== 'undefined' && typeof e !== 'undefined' && typeof f !== 'undefined') { + // all 3 components set to (can be anything that the FP8 constructor supports) + this.a = new ctx.FP8(d); + this.b = new ctx.FP8(e); + this.c = new ctx.FP8(f); + this.stype = ctx.FP.DENSE; + } else if (typeof d === 'number') { + // first component is number + this.a = new ctx.FP8(d); + this.b = new ctx.FP8(0); + this.c = new ctx.FP8(0); + if (d == 1) this.stype = ctx.FP.ONE; + else this.stype = ctx.FP.SPARSER; + } else { + // other cases, including `new ctx.FP24()` fall back to zero + this.a = new ctx.FP8(0); + this.b = new ctx.FP8(0); + this.c = new ctx.FP8(0); + this.stype = ctx.FP.ZERO; + } + }; + + FP24.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + this.c.reduce(); + }, + + /* normalize all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + this.c.norm(); + }, + + /* test x==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch() && this.c.iszilch(); + }, + + /* test x==1 ? */ + isunity: function () { + var one = new ctx.FP8(1); + return this.a.equals(one) && this.b.iszilch() && this.c.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + this.c.cmove(g.c, d); + d = ~(d - 1); + this.stype ^= (this.stype ^ g.stype) & d; + }, + + /* Constant time select from pre-computed table */ + select: function (g, b) { + var invf = new FP24(0), + m, + babs; + + m = b >> 31; + babs = (b ^ m) - m; + babs = (babs - 1) / 2; + + this.cmove(g[0], FP24.teq(babs, 0)); // conditional move + this.cmove(g[1], FP24.teq(babs, 1)); + this.cmove(g[2], FP24.teq(babs, 2)); + this.cmove(g[3], FP24.teq(babs, 3)); + this.cmove(g[4], FP24.teq(babs, 4)); + this.cmove(g[5], FP24.teq(babs, 5)); + this.cmove(g[6], FP24.teq(babs, 6)); + this.cmove(g[7], FP24.teq(babs, 7)); + + invf.copy(this); + invf.conj(); + this.cmove(invf, m & 1); + }, + + settype: function (w) { + this.stype = w; + }, + + gettype: function () { + return this.stype; + }, + /* extract a from this */ + geta: function () { + return this.a; + }, + + /* extract b */ + getb: function () { + return this.b; + }, + + /* extract c */ + getc: function () { + return this.c; + }, + + /* return 1 if x==y, else 0 */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + this.c.copy(x.c); + this.stype = x.stype; + }, + + /* set this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ONE; + }, + + /* set this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ZERO; + }, + + /* this=conj(this) */ + conj: function () { + this.a.conj(); + this.b.nconj(); + this.c.conj(); + }, + + /* set this from 3 FP8s */ + set: function (d, e, f) { + this.a.copy(d); + this.b.copy(e); + this.c.copy(f); + this.stype = ctx.FP.DENSE; + }, + + /* set this from one ctx.FP8 */ + seta: function (d) { + this.a.copy(d); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.SPARSEST; + }, + + /* Granger-Scott Unitary Squaring */ + usqr: function () { + var A = new ctx.FP8(this.a), + B = new ctx.FP8(this.c), + C = new ctx.FP8(this.b), + D = new ctx.FP8(0); + + this.a.sqr(); + D.copy(this.a); + D.add(this.a); + this.a.add(D); + + A.nconj(); + + A.add(A); + this.a.add(A); + B.sqr(); + B.times_i(); + + D.copy(B); + D.add(B); + B.add(D); + + C.sqr(); + D.copy(C); + D.add(C); + C.add(D); + + this.b.conj(); + this.b.add(this.b); + this.c.nconj(); + + this.c.add(this.c); + this.b.add(B); + this.c.add(C); + this.stype = ctx.FP.DENSE; + this.reduce(); + }, + + /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ + sqr: function () { + if (this.stype == ctx.FP.ONE) return; + + var A = new ctx.FP8(this.a), + B = new ctx.FP8(this.b), + C = new ctx.FP8(this.c), + D = new ctx.FP8(this.a); + + A.sqr(); + B.mul(this.c); + B.add(B); + C.sqr(); + D.mul(this.b); + D.add(D); + + this.c.add(this.a); + this.c.add(this.b); + this.c.norm(); + this.c.sqr(); + + this.a.copy(A); + + A.add(B); + A.add(C); + A.add(D); + A.neg(); + B.times_i(); + C.times_i(); + + this.a.add(B); + this.b.copy(C); + this.b.add(D); + this.c.add(A); + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) this.stype = ctx.FP.SPARSE; + else this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP24 full multiplication this=this*y */ + mul: function (y) { + var z0 = new ctx.FP8(this.a), + z1 = new ctx.FP8(0), + z2 = new ctx.FP8(this.b), + z3 = new ctx.FP8(0), + t0 = new ctx.FP8(this.a), + t1 = new ctx.FP8(y.a); + + z0.mul(y.a); + z2.mul(y.b); + + t0.add(this.b); + t1.add(y.b); + + t0.norm(); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + + t1.copy(y.b); + t1.add(y.c); + + t0.norm(); + t1.norm(); + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t1.copy(y.a); + t1.add(y.c); + + t0.norm(); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + t0.copy(this.c); + t0.mul(y.c); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + // z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP24 multiplication w=w*y */ + /* catering for special case that arises from special form of ATE pairing line function */ + /* w and y are both sparser line functions - cost = 6m */ + smul: function (y) { + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + var w1 = new ctx.FP4(this.a.geta()); + var w2 = new ctx.FP4(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.b.geta().geta().geta()); + t.mul(y.b.geta().geta().geta()); + w3 = new ctx.FP4(t); + } else { + if (y.stype != ctx.FP.SPARSEST) { + w3 = new ctx.FP4(y.b.geta()); + w3.qmul(this.b.geta().geta().geta()); + } else { + w3 = new ctx.FP4(this.b.geta()); + w3.qmul(y.b.geta().geta().geta()); + } + } + } else { + w3 = new ctx.FP4(this.b.geta()); + w3.mul(y.b.geta()); + } + + var ta = new ctx.FP4(this.a.geta()); + var tb = new ctx.FP4(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP4(ta); + tc.mul(tb); + var t = new ctx.FP4(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.b.geta()); + tb.norm(); + var td = new ctx.FP4(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.b.geta()); + tb.norm(); + var te = new ctx.FP4(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.times_i(); + w1.add(w2); + + this.a.geta().copy(w1); + this.a.getb().copy(tc); + this.b.geta().copy(td); + this.b.getb().copy(te); + this.c.geta().copy(w3); + this.c.getb().zero(); + + this.a.norm(); + this.b.norm(); + } else { + var w1 = new ctx.FP4(this.a.geta()); + var w2 = new ctx.FP4(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.c.getb().geta().geta()); + t.mul(y.c.getb().geta().geta()); + w3 = new ctx.FP4(t); + } else { + if (y.type != ctx.FP.SPARSEST) { + w3 = new ctx.FP4(y.c.getb()); + w3.qmul(this.c.getb().geta().geta()); + } else { + w3 = new ctx.FP4(this.c.getb()); + w3.qmul(y.c.getb().geta().geta()); + } + } + } else { + w3 = new ctx.FP4(this.c.getb()); + w3.mul(y.c.getb()); + } + + var ta = new ctx.FP4(this.a.geta()); + var tb = new ctx.FP4(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP4(ta); + tc.mul(tb); + var t = new ctx.FP4(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.c.getb()); + tb.norm(); + var td = new ctx.FP4(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.c.getb()); + tb.norm(); + var te = new ctx.FP4(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.times_i(); + w1.add(w2); + this.a.geta().copy(w1); + this.a.getb().copy(tc); + + w3.times_i(); + w3.norm(); + this.b.geta().zero(); + this.b.getb().copy(w3); + + te.norm(); + te.times_i(); + this.c.geta().copy(te); + this.c.getb().copy(td); + + this.a.norm(); + this.c.norm(); + } + this.stype = ctx.FP.SPARSE; + }, + + /* FP24 full multiplication w=w*y */ + /* Supports sparse multiplicands */ + /* Usually w is denser than y */ + ssmul: function (y) { + if (this.stype == ctx.FP.ONE) { + this.copy(y); + return; + } + if (y.stype == ctx.FP.ONE) return; + + if (y.stype >= ctx.FP.SPARSE) { + var z0 = new ctx.FP8(this.a); + var z1 = new ctx.FP8(0); + var z2 = new ctx.FP8(0); + var z3 = new ctx.FP8(0); + z0.mul(y.a); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + z2.getb().copy(this.b.getb()); + z2.getb().mul(y.b.getb()); + z2.geta().zero(); + if (y.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.getb()); + z2.geta().mul(y.b.geta()); + } + if (this.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.geta()); + z2.geta().mul(y.b.getb()); + } + z2.times_i(); + } else { + z2.copy(this.b); + z2.mul(y.b); + } + } else { + z2.copy(this.b); + z2.mul(y.b); + } + var t0 = new ctx.FP8(this.a); + var t1 = new ctx.FP8(y.a); + t0.add(this.b); + t0.norm(); + t1.add(y.b); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + t1.copy(y.b); + t1.add(y.c); + t1.norm(); + + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + t0.geta().copy(this.c.geta()); + t0.geta().mul(y.c.geta()); + t0.getb().zero(); + if (y.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.geta()); + t0.getb().mul(y.c.getb()); + } + if (this.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.getb()); + t0.getb().mul(y.c.geta()); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } else { + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) { + this.smul(y); + return; + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + // dense by sparser - 13m + var z0 = new ctx.FP8(this.a); + var z2 = new ctx.FP8(this.b); + var z3 = new ctx.FP8(this.b); + var t0 = new ctx.FP8(0); + var t1 = new ctx.FP8(y.a); + z0.mul(y.a); + + if (y.stype == ctx.FP.SPARSEST) z2.tmul(y.b.geta().geta().geta()); + else z2.pmul(y.b.geta()); + + this.b.add(this.a); + t1.geta().add(y.b.geta()); + + t1.norm(); + this.b.norm(); + this.b.mul(t1); + z3.add(this.c); + z3.norm(); + + if (y.stype == ctx.FP.SPARSEST) z3.tmul(y.b.geta().geta().geta()); + else z3.pmul(y.b.geta()); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + this.b.add(t0); + + this.b.add(t1); + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + z3.norm(); + t0.mul(y.a); + this.c.copy(z2); + this.c.add(t0); + + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + var z0 = new ctx.FP8(this.a); + var z1 = new ctx.FP8(0); + var z2 = new ctx.FP8(0); + var z3 = new ctx.FP8(0); + var t0 = new ctx.FP8(this.a); + var t1 = new ctx.FP8(0); + + z0.mul(y.a); + t0.add(this.b); + t0.norm(); + + z1.copy(t0); + z1.mul(y.a); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + + z3.copy(t0); + + if (y.stype == ctx.FP.SPARSEST) z3.tmul(y.c.getb().geta().geta()); + else z3.pmul(y.c.getb()); + + z3.times_i(); + + t0.copy(z0); + t0.neg(); + z1.add(t0); + this.b.copy(z1); + z2.copy(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + t0.copy(this.c); + + if (y.stype == ctx.FP.SPARSEST) t0.tmul(y.c.getb().geta().geta()); + else t0.pmul(y.c.getb()); + + t0.times_i(); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + } + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* this=1/this */ + inverse: function () { + var f0 = new ctx.FP8(this.a), + f1 = new ctx.FP8(this.b), + f2 = new ctx.FP8(this.a), + f3 = new ctx.FP8(0); + + f0.sqr(); + f1.mul(this.c); + f1.times_i(); + f0.sub(f1); + f0.norm(); + + f1.copy(this.c); + f1.sqr(); + f1.times_i(); + f2.mul(this.b); + f1.sub(f2); + f1.norm(); + + f2.copy(this.b); + f2.sqr(); + f3.copy(this.a); + f3.mul(this.c); + f2.sub(f3); + f2.norm(); + + f3.copy(this.b); + f3.mul(f2); + f3.times_i(); + this.a.mul(f0); + f3.add(this.a); + this.c.mul(f1); + this.c.times_i(); + + f3.add(this.c); + f3.norm(); + f3.inverse(null); + this.a.copy(f0); + this.a.mul(f3); + this.b.copy(f1); + this.b.mul(f3); + this.c.copy(f2); + this.c.mul(f3); + this.stype = ctx.FP.DENSE; + }, + + /* this=this^p, where p=Modulus, using Frobenius */ + frob: function (f, n) { + var f2 = new ctx.FP2(f), + f3 = new ctx.FP2(f), + i; + + f2.sqr(); + f3.mul(f2); + + f3.mul_ip(); + f3.norm(); + + for (i = 0; i < n; i++) { + this.a.frob(f3); + this.b.frob(f3); + this.c.frob(f3); + + this.b.qmul(f); + this.b.times_i2(); + this.c.qmul(f2); + this.c.times_i2(); + this.c.times_i2(); + } + this.stype = ctx.FP.DENSE; + }, + + /* trace function */ + trace: function () { + var t = new ctx.FP8(0); + + t.copy(this.a); + t.imul(3); + t.reduce(); + + return t; + }, + + /* convert this to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ',' + this.c.toString() + ']'; + }, + + /* convert this to byte array */ + toBytes: function (w) { + var t = []; + this.c.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i] = t[i]; + this.b.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 8 * ctx.BIG.MODBYTES] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 16 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* set this=this^e */ + pow: function (e) { + var e1, e3, w, nb, i, bt, sf; + + sf = new FP24(this); + sf.norm(); + e1 = new ctx.BIG(e); + e1.norm(); + + e3 = new ctx.BIG(e1); + e3.pmul(3); + e3.norm(); + + w = new FP24(sf); + if (e3.iszilch()) { + w.one(); + return w; + } + nb = e3.nbits(); + + for (i = nb - 2; i >= 1; i--) { + w.usqr(); + bt = e3.bit(i) - e1.bit(i); + + if (bt == 1) { + w.mul(sf); + } + if (bt == -1) { + sf.conj(); + w.mul(sf); + sf.conj(); + } + } + w.reduce(); + + return w; + }, + + /* constant time powering by small integer of max length bts */ + pinpow: function (e, bts) { + var R = [], + i, + b; + + R[0] = new FP24(1); + R[1] = new FP24(this); + + for (i = bts - 1; i >= 0; i--) { + b = (e >> i) & 1; + R[1 - b].mul(R[b]); + R[b].usqr(); + } + + this.copy(R[0]); + }, + + /* Faster compressed powering for unitary elements */ + /* + compow: function(e, r) { + var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + + m = new ctx.BIG(q); + m.mod(r); + + a = new ctx.BIG(e); + a.mod(m); + + b = new ctx.BIG(e); + b.div(m); + + g1 = new FP24(0); + g2 = new FP24(0); + g1.copy(this); + + c = g1.trace(); + + if (b.iszilch()) { + c=c.xtr_pow(e); + return c; + } + + g2.copy(g1); + g2.frob(f,1); + cp = g2.trace(); + g1.conj(); + g2.mul(g1); + cpm1 = g2.trace(); + g2.mul(g1); + cpm2 = g2.trace(); + + c = c.xtr_pow2(cp, cpm1, cpm2, a, b); + return c; + } +*/ + }; + + /* convert from byte array to FP12 */ + FP24.fromBytes = function (w) { + var a, b, c; + var t = []; + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = w[i]; + c = ctx.FP8.fromBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 8 * ctx.BIG.MODBYTES]; + b = ctx.FP8.fromBytes(t); + for (var i = 0; i < 8 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 16 * ctx.BIG.MODBYTES]; + a = ctx.FP8.fromBytes(t); + return new FP24(a, b, c); + }; + + /* return 1 if b==c, no branching */ + FP24.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* p=q0^u0.q1^u1.q2^u2.q3^u3... */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + FP24.pow8 = function (q, u) { + var g1 = [], + g2 = [], + r = new FP24(0), + p = new FP24(0), + t = [], + mt = new ctx.BIG(0), + w1 = [], + s1 = [], + w2 = [], + s2 = [], + i, + j, + k, + nb, + bt, + pb1, + pb2; + + for (i = 0; i < 8; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + } + + g1[0] = new FP24(q[0]); // q[0] + g1[1] = new FP24(g1[0]); + g1[1].mul(q[1]); // q[0].q[1] + g1[2] = new FP24(g1[0]); + g1[2].mul(q[2]); // q[0].q[2] + g1[3] = new FP24(g1[1]); + g1[3].mul(q[2]); // q[0].q[1].q[2] + g1[4] = new FP24(q[0]); + g1[4].mul(q[3]); // q[0].q[3] + g1[5] = new FP24(g1[1]); + g1[5].mul(q[3]); // q[0].q[1].q[3] + g1[6] = new FP24(g1[2]); + g1[6].mul(q[3]); // q[0].q[2].q[3] + g1[7] = new FP24(g1[3]); + g1[7].mul(q[3]); // q[0].q[1].q[2].q[3] + + g2[0] = new FP24(q[4]); // q[0] + g2[1] = new FP24(g2[0]); + g2[1].mul(q[5]); // q[0].q[1] + g2[2] = new FP24(g2[0]); + g2[2].mul(q[6]); // q[0].q[2] + g2[3] = new FP24(g2[1]); + g2[3].mul(q[6]); // q[0].q[1].q[2] + g2[4] = new FP24(q[4]); + g2[4].mul(q[7]); // q[0].q[3] + g2[5] = new FP24(g2[1]); + g2[5].mul(q[7]); // q[0].q[1].q[3] + g2[6] = new FP24(g2[2]); + g2[6].mul(q[7]); // q[0].q[2].q[3] + g2[7] = new FP24(g2[3]); + g2[7].mul(q[7]); // q[0].q[1].q[2].q[3] + + // Make it odd + pb1 = 1 - t[0].parity(); + t[0].inc(pb1); + t[0].norm(); + + pb2 = 1 - t[4].parity(); + t[4].inc(pb2); + t[4].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 8; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s1[nb - 1] = 1; + s2[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s1[i] = 2 * t[0].parity() - 1; + t[4].fshr(1); + s2[i] = 2 * t[4].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w1[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s1[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w1[i] += bt * k; + k *= 2; + } + w2[i] = 0; + k = 1; + for (j = 5; j < 8; j++) { + bt = s2[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w2[i] += bt * k; + k *= 2; + } + } + + // Main loop + p.select(g1, 2 * w1[nb - 1] + 1); + r.select(g2, 2 * w2[nb - 1] + 1); + p.mul(r); + for (i = nb - 2; i >= 0; i--) { + p.usqr(); + r.select(g1, 2 * w1[i] + s1[i]); + p.mul(r); + r.select(g2, 2 * w2[i] + s2[i]); + p.mul(r); + } + + // apply correction + r.copy(q[0]); + r.conj(); + r.mul(p); + p.cmove(r, pb1); + + r.copy(q[4]); + r.conj(); + r.mul(p); + p.cmove(r, pb2); + + p.reduce(); + return p; + }; + + return FP24; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP24: FP24, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp4.js b/packages/bls-verify/src/vendor/amcl-js/src/fp4.js new file mode 100644 index 000000000..7ad95fa59 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp4.js @@ -0,0 +1,722 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Finite Field arithmetic Fp^4 functions */ + +/* FP4 elements are of the form a+ib, where i is sqrt(-1+sqrt(-1)) */ + +var FP4 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP4 = function (c, d) { + if (c instanceof FP4) { + this.a = new ctx.FP2(c.a); + this.b = new ctx.FP2(c.b); + } else { + this.a = new ctx.FP2(c); + this.b = new ctx.FP2(d); + } + }; + + FP4.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + }, + + /* normalise all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + }, + + /* test this==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch(); + }, + + islarger: function () { + if (this.iszilch()) return 0; + var cmp = this.b.larger(); + if (cmp != 0) return cmp; + return this.a.larger(); + }, + + toBytes: function (bf) { + var t = []; + this.b.toBytes(t); + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) bf[i] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) bf[i + 2 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* test this==1 ? */ + isunity: function () { + var one = new ctx.FP2(1); + return this.a.equals(one) && this.b.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + }, + + /* test is w real? That is in a+ib test b is zero */ + isreal: function () { + return this.b.iszilch(); + }, + + /* extract real part a */ + real: function () { + return this.a; + }, + + geta: function () { + return this.a; + }, + + /* extract imaginary part b */ + getb: function () { + return this.b; + }, + + /* test this=x? */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + }, + + /* this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + }, + + /* this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + }, + + /* set from two FP2s */ + set: function (c, d) { + this.a.copy(c); + this.b.copy(d); + }, + + /* set a */ + seta: function (c) { + this.a.copy(c); + this.b.zero(); + }, + + sign: function () { + var p1 = this.a.sign(); + var p2 = this.b.sign(); + if (ctx.FP.BIG_ENDIAN_SIGN) { + var u = this.b.iszilch() ? 1 : 0; + p2 ^= (p1 ^ p2) & u; + return p2; + } else { + var u = this.a.iszilch() ? 1 : 0; + p1 ^= (p1 ^ p2) & u; + return p1; + } + }, + + /* this=-this */ + neg: function () { + this.norm(); + var m = new ctx.FP2(this.a), + t = new ctx.FP2(0); + + m.add(this.b); + m.neg(); + t.copy(m); + t.add(this.b); + this.b.copy(m); + this.b.add(this.a); + this.a.copy(t); + this.norm(); + }, + + /* this=conjugate(this) */ + conj: function () { + this.b.neg(); + this.norm(); + }, + + /* this=-conjugate(this) */ + nconj: function () { + this.a.neg(); + this.norm(); + }, + + /* this+=x */ + add: function (x) { + this.a.add(x.a); + this.b.add(x.b); + }, + + /* this-=x */ + sub: function (x) { + var m = new FP4(x); + m.neg(); + this.add(m); + }, + + rsub: function (x) { + this.neg(); + this.add(x); + }, + + /* this*=s where s is FP2 */ + pmul: function (s) { + this.a.mul(s); + this.b.mul(s); + }, + + /* this*=c where s is int */ + imul: function (c) { + this.a.imul(c); + this.b.imul(c); + }, + + /* this*=this */ + sqr: function () { + // this.norm(); + + var t1 = new ctx.FP2(this.a), + t2 = new ctx.FP2(this.b), + t3 = new ctx.FP2(this.a); + + t3.mul(this.b); + t1.add(this.b); + t1.norm(); + t2.mul_ip(); + + t2.add(this.a); + t2.norm(); + this.a.copy(t1); + + this.a.mul(t2); + + t2.copy(t3); + t2.mul_ip(); + t2.add(t3); + t2.norm(); // ?? + + t2.neg(); + + this.a.add(t2); + + this.b.copy(t3); + this.b.add(t3); + + this.norm(); + }, + + /* this*=y */ + mul: function (y) { + // this.norm(); + + var t1 = new ctx.FP2(this.a), + t2 = new ctx.FP2(this.b), + t3 = new ctx.FP2(0), + t4 = new ctx.FP2(this.b); + + t1.mul(y.a); + t2.mul(y.b); + t3.copy(y.b); + t3.add(y.a); + t4.add(this.a); + + t3.norm(); + t4.norm(); + + t4.mul(t3); + + t3.copy(t1); + t3.neg(); + t4.add(t3); + + t3.copy(t2); + t3.neg(); + this.b.copy(t4); + this.b.add(t3); + + t2.mul_ip(); + this.a.copy(t2); + this.a.add(t1); + + this.norm(); + }, + + /* convert to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ']'; + }, + + /* this=1/this */ + inverse: function (h) { + this.norm(); + + var t1 = new ctx.FP2(this.a), + t2 = new ctx.FP2(this.b); + + t1.sqr(); + t2.sqr(); + t2.mul_ip(); + t2.norm(); // ?? + t1.sub(t2); + t1.inverse(h); + this.a.mul(t1); + t1.neg(); + t1.norm(); + this.b.mul(t1); + }, + + /* this*=i where i = sqrt(-1+sqrt(-1)) */ + times_i: function () { + var t = new ctx.FP2(this.b); + this.b.copy(this.a); + t.mul_ip(); + this.a.copy(t); + this.norm(); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.neg(); + this.norm(); + } + }, + + /* this=this^q using Frobenius, where q is Modulus */ + frob: function (f) { + this.a.conj(); + this.b.conj(); + this.b.mul(f); + }, + + /* this=this^e */ + /* + pow: function(e) { + var w = new FP4(this), + z = new ctx.BIG(e), + r = new FP4(1), + bt; + w.norm(); + z.norm(); + for (;;) { + bt = z.parity(); + z.fshr(1); + + if (bt === 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + + w.sqr(); + } + r.reduce(); + + return r; + }, */ + + /* XTR xtr_a function */ + xtr_A: function (w, y, z) { + var r = new FP4(w), + t = new FP4(w); + + //y.norm(); // ?? + r.sub(y); + r.norm(); + r.pmul(this.a); + t.add(y); + t.norm(); + t.pmul(this.b); + t.times_i(); + + this.copy(r); + this.add(t); + this.add(z); + + this.reduce(); + }, + + /* XTR xtr_d function */ + xtr_D: function () { + var w = new FP4(this); + this.sqr(); + w.conj(); + w.add(w); + this.sub(w); + this.reduce(); + }, + + /* r=x^n using XTR method on traces of FP12s */ + xtr_pow: function (n) { + var sf = new FP4(this); + sf.norm(); + var a = new FP4(3), + b = new FP4(sf), + c = new FP4(b), + t = new FP4(0), + r = new FP4(0), + par, + v, + nb, + i; + + c.xtr_D(); + + //n.norm(); + par = n.parity(); + v = new ctx.BIG(n); + v.norm(); + v.fshr(1); + + if (par === 0) { + v.dec(1); + v.norm(); + } + + nb = v.nbits(); + for (i = nb - 1; i >= 0; i--) { + if (v.bit(i) != 1) { + t.copy(b); + sf.conj(); + c.conj(); + b.xtr_A(a, sf, c); + sf.conj(); + c.copy(t); + c.xtr_D(); + a.xtr_D(); + } else { + t.copy(a); + t.conj(); + a.copy(b); + a.xtr_D(); + b.xtr_A(c, sf, t); + c.xtr_D(); + } + } + + if (par === 0) { + r.copy(c); + } else { + r.copy(b); + } + r.reduce(); + + return r; + }, + + /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */ + xtr_pow2: function (ck, ckml, ckm2l, a, b) { + var e = new ctx.BIG(a), + d = new ctx.BIG(b), + w = new ctx.BIG(0), + cu = new FP4(ck), + cv = new FP4(this), + cumv = new FP4(ckml), + cum2v = new FP4(ckm2l), + r = new FP4(0), + t = new FP4(0), + f2 = 0, + i; + + e.norm(); + d.norm(); + + while (d.parity() === 0 && e.parity() === 0) { + d.fshr(1); + e.fshr(1); + f2++; + } + + while (ctx.BIG.comp(d, e) !== 0) { + if (ctx.BIG.comp(d, e) > 0) { + w.copy(e); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(d, w) <= 0) { + w.copy(d); + d.copy(e); + e.rsub(w); + e.norm(); + + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cum2v.conj(); + cumv.copy(cv); + cv.copy(cu); + cu.copy(t); + } else if (d.parity() === 0) { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } else if (e.parity() == 1) { + d.sub(e); + d.norm(); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cu.xtr_D(); + cum2v.copy(cv); + cum2v.xtr_D(); + cum2v.conj(); + cv.copy(t); + } else { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } + } + if (ctx.BIG.comp(d, e) < 0) { + w.copy(d); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(e, w) <= 0) { + e.sub(d); + e.norm(); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cumv.copy(cu); + cu.copy(t); + } else if (e.parity() === 0) { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } else if (d.parity() == 1) { + w.copy(e); + e.copy(d); + w.sub(d); + w.norm(); + d.copy(w); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cumv.conj(); + cum2v.copy(cu); + cum2v.xtr_D(); + cum2v.conj(); + cu.copy(cv); + cu.xtr_D(); + cv.copy(t); + } else { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } + } + } + r.copy(cv); + r.xtr_A(cu, cumv, cum2v); + for (i = 0; i < f2; i++) { + r.xtr_D(); + } + r = r.xtr_pow(d); + return r; + }, + + /* New stuff for ecp4.js */ + + div2: function () { + this.a.div2(); + this.b.div2(); + }, + + div_i: function () { + var u = new ctx.FP2(this.a), + v = new ctx.FP2(this.b); + u.div_ip(); + this.a.copy(v); + this.b.copy(u); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.neg(); + this.norm(); + } + }, + + qmul: function (s) { + this.a.pmul(s); + this.b.pmul(s); + }, + + /* this^e */ + /* + pow: function(e) { + var r = new FP4(1), + w = new FP4(this), + z = new ctx.BIG(e), + bt; + + for (;;) { + bt = z.parity(); + z.fshr(1); + if (bt == 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + w.sqr(); + } + + r.reduce(); + this.copy(r); + },*/ + + qr: function (h) { + var c = new FP4(this); + c.conj(); + c.mul(this); + return c.geta().qr(h); + }, + + sqrt: function (h) { + if (this.iszilch()) { + return; + } + var wa = new ctx.FP2(this.a), + wb = new ctx.FP2(this.a), + ws = new ctx.FP2(this.b), + wt = new ctx.FP2(this.a); + var hint = new ctx.FP(0); + + ws.sqr(); + wa.sqr(); + ws.mul_ip(); + ws.norm(); + wa.sub(ws); + + ws.copy(wa); + ws.norm(); + ws.sqrt(h); + + wa.copy(wt); + wa.add(ws); + wa.norm(); + wa.div2(); + + wb.copy(this.b); + wb.div2(); + var qr = wa.qr(hint); + + // tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial + ws.copy(wa); + var twk = new ctx.FP(0); + twk.rcopy(ctx.ROM_FIELD.TWK); + twk.mul(hint); + ws.div_ip(); + ws.norm(); + + wa.cmove(ws, 1 - qr); + hint.cmove(twk, 1 - qr); + + this.a.copy(wa); + this.a.sqrt(hint); + ws.copy(wa); + ws.inverse(hint); + ws.mul(this.a); + this.b.copy(ws); + this.b.mul(wb); + wt.copy(this.a); + + this.a.cmove(this.b, 1 - qr); + this.b.cmove(wt, 1 - qr); + + var sgn = this.sign(); + var nr = new FP4(this); + nr.neg(); + nr.norm(); + this.cmove(nr, sgn); + }, + }; + + FP4.rand = function (rng) { + return new FP4(ctx.FP2.rand(rng), ctx.FP2.rand(rng)); + }; + + FP4.fromBytes = function (bf) { + var t = []; + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = bf[i]; + var tb = ctx.FP2.fromBytes(t); + for (var i = 0; i < 2 * ctx.BIG.MODBYTES; i++) t[i] = bf[i + 2 * ctx.BIG.MODBYTES]; + var ta = ctx.FP2.fromBytes(t); + return new FP4(ta, tb); + }; + + return FP4; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP4: FP4, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp48.js b/packages/bls-verify/src/vendor/amcl-js/src/fp48.js new file mode 100644 index 000000000..3e4ebb85f --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp48.js @@ -0,0 +1,1225 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* CORE Fp^48 functions */ + +/* FP48 elements are of the form a+i.b+i^2.c */ + +var FP48 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP48 = function (d, e, f) { + /* + if (!isNaN(d)) + { + this.a = new ctx.FP16(d); + this.b = new ctx.FP16(0); + this.c = new ctx.FP16(0); + if (d==1) this.stype=ctx.FP.ONE; + else this.stype=ctx.FP.SPARSEST; + } + else + { + if (d instanceof FP48) { + this.a = new ctx.FP16(d.a); + this.b = new ctx.FP16(d.b); + this.c = new ctx.FP16(d.c); + } else { + this.a = new ctx.FP16(d); + this.b = new ctx.FP16(e); + this.c = new ctx.FP16(f); + } + this.stype=ctx.FP.DENSE; + } +*/ + + if (d instanceof FP48) { + // ignore e, d, which are assumed be undefined in this case + this.a = new ctx.FP16(d.a); + this.b = new ctx.FP16(d.b); + this.c = new ctx.FP16(d.c); + this.stype = ctx.FP.DENSE; + } else if (typeof d !== 'undefined' && typeof e !== 'undefined' && typeof f !== 'undefined') { + // all 3 components set to (can be anything that the FP16 constructor supports) + this.a = new ctx.FP16(d); + this.b = new ctx.FP16(e); + this.c = new ctx.FP16(f); + this.stype = ctx.FP.DENSE; + } else if (typeof d === 'number') { + // first component is number + this.a = new ctx.FP16(d); + this.b = new ctx.FP16(0); + this.c = new ctx.FP16(0); + if (d == 1) this.stype = ctx.FP.ONE; + else this.stype = ctx.FP.SPARSER; + } else { + // other cases, including `new ctx.FP48()` fall back to zero + this.a = new ctx.FP16(0); + this.b = new ctx.FP16(0); + this.c = new ctx.FP16(0); + this.stype = ctx.FP.ZERO; + } + }; + + FP48.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + this.c.reduce(); + }, + + /* normalize all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + this.c.norm(); + }, + + /* test x==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch() && this.c.iszilch(); + }, + + /* test x==1 ? */ + isunity: function () { + var one = new ctx.FP16(1); + return this.a.equals(one) && this.b.iszilch() && this.c.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + this.c.cmove(g.c, d); + d = ~(d - 1); + this.stype ^= (this.stype ^ g.stype) & d; + }, + + /* Constant time select from pre-computed table */ + select: function (g, b) { + var invf = new FP48(0), + m, + babs; + + m = b >> 31; + babs = (b ^ m) - m; + babs = (babs - 1) / 2; + + this.cmove(g[0], FP48.teq(babs, 0)); // conditional move + this.cmove(g[1], FP48.teq(babs, 1)); + this.cmove(g[2], FP48.teq(babs, 2)); + this.cmove(g[3], FP48.teq(babs, 3)); + this.cmove(g[4], FP48.teq(babs, 4)); + this.cmove(g[5], FP48.teq(babs, 5)); + this.cmove(g[6], FP48.teq(babs, 6)); + this.cmove(g[7], FP48.teq(babs, 7)); + + invf.copy(this); + invf.conj(); + this.cmove(invf, m & 1); + }, + + settype: function (w) { + this.stype = w; + }, + + gettype: function () { + return this.stype; + }, + + /* extract a from this */ + geta: function () { + return this.a; + }, + + /* extract b */ + getb: function () { + return this.b; + }, + + /* extract c */ + getc: function () { + return this.c; + }, + + /* return 1 if x==y, else 0 */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + this.c.copy(x.c); + this.stype = x.stype; + }, + + /* set this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ONE; + }, + + /* set this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.ZERO; + }, + + /* this=conj(this) */ + conj: function () { + this.a.conj(); + this.b.nconj(); + this.c.conj(); + }, + + /* set this from 3 FP16s */ + set: function (d, e, f) { + this.a.copy(d); + this.b.copy(e); + this.c.copy(f); + this.stype = ctx.FP.DENSE; + }, + + /* set this from one ctx.FP16 */ + seta: function (d) { + this.a.copy(d); + this.b.zero(); + this.c.zero(); + this.stype = ctx.FP.SPARSEST; + }, + + /* Granger-Scott Unitary Squaring */ + usqr: function () { + var A = new ctx.FP16(this.a), + B = new ctx.FP16(this.c), + C = new ctx.FP16(this.b), + D = new ctx.FP16(0); + + this.a.sqr(); + D.copy(this.a); + D.add(this.a); + this.a.add(D); + + A.nconj(); + + A.add(A); + this.a.add(A); + B.sqr(); + B.times_i(); + + D.copy(B); + D.add(B); + B.add(D); + + C.sqr(); + D.copy(C); + D.add(C); + C.add(D); + + this.b.conj(); + this.b.add(this.b); + this.c.nconj(); + + this.c.add(this.c); + this.b.add(B); + this.c.add(C); + this.stype = ctx.FP.DENSE; + this.reduce(); + }, + + /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */ + sqr: function () { + if (this.stype == ctx.FP.ONE) return; + + var A = new ctx.FP16(this.a), + B = new ctx.FP16(this.b), + C = new ctx.FP16(this.c), + D = new ctx.FP16(this.a); + + A.sqr(); + B.mul(this.c); + B.add(B); + C.sqr(); + D.mul(this.b); + D.add(D); + + this.c.add(this.a); + this.c.add(this.b); + this.c.norm(); + this.c.sqr(); + + this.a.copy(A); + + A.add(B); + A.add(C); + A.add(D); + A.neg(); + B.times_i(); + C.times_i(); + + this.a.add(B); + this.b.copy(C); + this.b.add(D); + this.c.add(A); + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) this.stype = ctx.FP.SPARSE; + else this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP48 full multiplication this=this*y */ + mul: function (y) { + var z0 = new ctx.FP16(this.a), + z1 = new ctx.FP16(0), + z2 = new ctx.FP16(this.b), + z3 = new ctx.FP16(0), + t0 = new ctx.FP16(this.a), + t1 = new ctx.FP16(y.a); + + z0.mul(y.a); + z2.mul(y.b); + + t0.add(this.b); + t1.add(y.b); + + t0.norm(); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + + t1.copy(y.b); + t1.add(y.c); + + t0.norm(); + t1.norm(); + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t1.copy(y.a); + t1.add(y.c); + + t0.norm(); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + t0.copy(this.c); + t0.mul(y.c); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* FP48 multiplication w=w*y */ + /* catering for special case that arises from special form of ATE pairing line function */ + /* w and y are both sparser line functions - cost = 6m */ + smul: function (y) { + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + var w1 = new ctx.FP8(this.a.geta()); + var w2 = new ctx.FP8(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.b.geta().geta().geta().geta()); + t.mul(y.b.geta().geta().geta().geta()); + w3 = new ctx.FP8(t); + } else { + if (y.stype != ctx.FP.SPARSEST) { + w3 = new ctx.FP8(y.b.geta()); + w3.tmul(this.b.geta().geta().geta().geta()); + } else { + w3 = new ctx.FP8(this.b.geta()); + w3.tmul(y.b.geta().geta().geta().geta()); + } + } + } else { + w3 = new ctx.FP8(this.b.geta()); + w3.mul(y.b.geta()); + } + + var ta = new ctx.FP8(this.a.geta()); + var tb = new ctx.FP8(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP8(ta); + tc.mul(tb); + var t = new ctx.FP8(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.b.geta()); + tb.norm(); + var td = new ctx.FP8(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.b.geta()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.b.geta()); + tb.norm(); + var te = new ctx.FP8(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.times_i(); + w1.add(w2); + + this.a.geta().copy(w1); + this.a.getb().copy(tc); + this.b.geta().copy(td); + this.b.getb().copy(te); + this.c.geta().copy(w3); + this.c.getb().zero(); + + this.a.norm(); + this.b.norm(); + } else { + var w1 = new ctx.FP8(this.a.geta()); + var w2 = new ctx.FP8(this.a.getb()); + var w3; + + w1.mul(y.a.geta()); + w2.mul(y.a.getb()); + if (y.stype == ctx.FP.SPARSEST || this.stype == ctx.FP.SPARSEST) { + if (y.stype == ctx.FP.SPARSEST && this.stype == ctx.FP.SPARSEST) { + var t = new ctx.FP(this.c.getb().geta().geta().geta()); + t.mul(y.c.getb().geta().geta().geta()); + w3 = new ctx.FP8(t); + } else { + if (y.type != ctx.FP.SPARSEST) { + w3 = new ctx.FP8(y.c.getb()); + w3.tmul(this.c.getb().geta().geta().geta()); + } else { + w3 = new ctx.FP8(this.c.getb()); + w3.tmul(y.c.getb().geta().geta().geta()); + } + } + } else { + w3 = new ctx.FP8(this.c.getb()); + w3.mul(y.c.getb()); + } + var ta = new ctx.FP8(this.a.geta()); + var tb = new ctx.FP8(y.a.geta()); + ta.add(this.a.getb()); + ta.norm(); + tb.add(y.a.getb()); + tb.norm(); + var tc = new ctx.FP8(ta); + tc.mul(tb); + var t = new ctx.FP8(w1); + t.add(w2); + t.neg(); + tc.add(t); + + ta.copy(this.a.geta()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.geta()); + tb.add(y.c.getb()); + tb.norm(); + var td = new ctx.FP8(ta); + td.mul(tb); + t.copy(w1); + t.add(w3); + t.neg(); + td.add(t); + + ta.copy(this.a.getb()); + ta.add(this.c.getb()); + ta.norm(); + tb.copy(y.a.getb()); + tb.add(y.c.getb()); + tb.norm(); + var te = new ctx.FP8(ta); + te.mul(tb); + t.copy(w2); + t.add(w3); + t.neg(); + te.add(t); + + w2.times_i(); + w1.add(w2); + this.a.geta().copy(w1); + this.a.getb().copy(tc); + + w3.times_i(); + w3.norm(); + this.b.geta().zero(); + this.b.getb().copy(w3); + + te.norm(); + te.times_i(); + this.c.geta().copy(te); + this.c.getb().copy(td); + + this.a.norm(); + this.c.norm(); + } + this.stype = ctx.FP.SPARSE; + }, + + /* FP48 full multiplication w=w*y */ + /* Supports sparse multiplicands */ + /* Usually w is denser than y */ + ssmul: function (y) { + if (this.stype == ctx.FP.ONE) { + this.copy(y); + return; + } + if (y.stype == ctx.FP.ONE) return; + + if (y.stype >= ctx.FP.SPARSE) { + var z0 = new ctx.FP16(this.a); + var z1 = new ctx.FP16(0); + var z2 = new ctx.FP16(0); + var z3 = new ctx.FP16(0); + z0.mul(y.a); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + z2.getb().copy(this.b.getb()); + z2.getb().mul(y.b.getb()); + z2.geta().zero(); + if (y.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.getb()); + z2.geta().mul(y.b.geta()); + } + if (this.stype != ctx.FP.SPARSE) { + z2.geta().copy(this.b.geta()); + z2.geta().mul(y.b.getb()); + } + z2.times_i(); + } else { + z2.copy(this.b); + z2.mul(y.b); + } + } else { + z2.copy(this.b); + z2.mul(y.b); + } + var t0 = new ctx.FP16(this.a); + var t1 = new ctx.FP16(y.a); + t0.add(this.b); + t0.norm(); + t1.add(y.b); + t1.norm(); + + z1.copy(t0); + z1.mul(t1); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + t1.copy(y.b); + t1.add(y.c); + t1.norm(); + + z3.copy(t0); + z3.mul(t1); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + z1.add(t0); + this.b.copy(z1); + this.b.add(t1); + + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + if (y.stype == ctx.FP.SPARSE || this.stype == ctx.FP.SPARSE) { + t0.geta().copy(this.c.geta()); + t0.geta().mul(y.c.geta()); + t0.getb().zero(); + if (y.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.geta()); + t0.getb().mul(y.c.getb()); + } + if (this.stype != ctx.FP.SPARSE) { + t0.getb().copy(this.c.getb()); + t0.getb().mul(y.c.geta()); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + } else { + t0.copy(this.c); + t0.mul(y.c); + } + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } else { + if (this.stype == ctx.FP.SPARSER || this.stype == ctx.FP.SPARSEST) { + this.smul(y); + return; + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + // dense by sparser - 13m + var z0 = new ctx.FP16(this.a); + var z2 = new ctx.FP16(this.b); + var z3 = new ctx.FP16(this.b); + var t0 = new ctx.FP16(0); + var t1 = new ctx.FP16(y.a); + z0.mul(y.a); + + if (y.stype == ctx.FP.SPARSEST) z2.tmul(y.b.geta().geta().geta().geta()); + else z2.pmul(y.b.geta()); + + this.b.add(this.a); + t1.geta().add(y.b.geta()); + + t1.norm(); + this.b.norm(); + this.b.mul(t1); + z3.add(this.c); + z3.norm(); + + if (y.stype == ctx.FP.SPARSEST) z3.tmul(y.b.geta().geta().geta().geta()); + else z3.pmul(y.b.real()); + + t0.copy(z0); + t0.neg(); + t1.copy(z2); + t1.neg(); + + this.b.add(t0); + + this.b.add(t1); + z3.add(t1); + z2.add(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + z3.norm(); + t0.mul(y.a); + this.c.copy(z2); + this.c.add(t0); + + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + var z0 = new ctx.FP16(this.a); + var z1 = new ctx.FP16(0); + var z2 = new ctx.FP16(0); + var z3 = new ctx.FP16(0); + var t0 = new ctx.FP16(this.a); + var t1 = new ctx.FP16(0); + + z0.mul(y.a); + t0.add(this.b); + t0.norm(); + + z1.copy(t0); + z1.mul(y.a); + t0.copy(this.b); + t0.add(this.c); + t0.norm(); + + z3.copy(t0); + + if (y.stype == ctx.FP.SPARSEST) z3.tmul(y.c.getb().geta().geta().geta()); + else z3.pmul(y.c.getb()); + z3.times_i(); + + t0.copy(z0); + t0.neg(); + z1.add(t0); + this.b.copy(z1); + z2.copy(t0); + + t0.copy(this.a); + t0.add(this.c); + t0.norm(); + t1.copy(y.a); + t1.add(y.c); + t1.norm(); + + t0.mul(t1); + z2.add(t0); + t0.copy(this.c); + + if (y.stype == ctx.FP.SPARSEST) t0.tmul(y.c.getb().geta().geta().geta()); + else t0.pmul(y.c.getb()); + t0.times_i(); + t1.copy(t0); + t1.neg(); + + this.c.copy(z2); + this.c.add(t1); + z3.add(t1); + t0.times_i(); + this.b.add(t0); + z3.norm(); + z3.times_i(); + this.a.copy(z0); + this.a.add(z3); + } + } + this.stype = ctx.FP.DENSE; + this.norm(); + }, + + /* this=1/this */ + inverse: function () { + var f0 = new ctx.FP16(this.a), + f1 = new ctx.FP16(this.b), + f2 = new ctx.FP16(this.a), + f3 = new ctx.FP16(0); + + f0.sqr(); + f1.mul(this.c); + f1.times_i(); + f0.sub(f1); + f0.norm(); + + f1.copy(this.c); + f1.sqr(); + f1.times_i(); + f2.mul(this.b); + f1.sub(f2); + f1.norm(); + + f2.copy(this.b); + f2.sqr(); + f3.copy(this.a); + f3.mul(this.c); + f2.sub(f3); + f2.norm(); + + f3.copy(this.b); + f3.mul(f2); + f3.times_i(); + this.a.mul(f0); + f3.add(this.a); + this.c.mul(f1); + this.c.times_i(); + + f3.add(this.c); + f3.norm(); + f3.inverse(); + this.a.copy(f0); + this.a.mul(f3); + this.b.copy(f1); + this.b.mul(f3); + this.c.copy(f2); + this.c.mul(f3); + this.stype = ctx.FP.DENSE; + }, + + /* this=this^p, where p=Modulus, using Frobenius */ + frob: function (f, n) { + var f2 = new ctx.FP2(f), + f3 = new ctx.FP2(f), + i; + + f2.sqr(); + f3.mul(f2); + + f3.mul_ip(); + f3.norm(); + f3.mul_ip(); + f3.norm(); + + for (i = 0; i < n; i++) { + this.a.frob(f3); + this.b.frob(f3); + this.c.frob(f3); + + this.b.qmul(f); + this.b.times_i4(); + this.b.times_i2(); + this.c.qmul(f2); + this.c.times_i4(); + this.c.times_i4(); + this.c.times_i4(); + } + this.stype = ctx.FP.DENSE; + }, + + /* trace function */ + trace: function () { + var t = new ctx.FP16(0); + + t.copy(this.a); + t.imul(3); + t.reduce(); + + return t; + }, + + /* convert this to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ',' + this.c.toString() + ']'; + }, + + /* convert this to byte array */ + toBytes: function (w) { + var t = []; + this.c.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i] = t[i]; + this.b.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 16 * ctx.BIG.MODBYTES] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) w[i + 32 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* set this=this^e */ + pow: function (e) { + var e1, e3, w, nb, i, bt, sf; + + sf = new FP48(this); + sf.norm(); + e1 = new ctx.BIG(e); + e1.norm(); + + e3 = new ctx.BIG(e1); + e3.pmul(3); + e3.norm(); + + w = new FP48(sf); //w.copy(this); + + if (e3.iszilch()) { + w.one(); + return w; + } + nb = e3.nbits(); + + for (i = nb - 2; i >= 1; i--) { + w.usqr(); + bt = e3.bit(i) - e1.bit(i); + + if (bt == 1) { + w.mul(sf); + } + if (bt == -1) { + sf.conj(); + w.mul(sf); + sf.conj(); + } + } + w.reduce(); + + return w; + }, + + /* constant time powering by small integer of max length bts */ + pinpow: function (e, bts) { + var R = [], + i, + b; + + R[0] = new FP48(1); + R[1] = new FP48(this); + + for (i = bts - 1; i >= 0; i--) { + b = (e >> i) & 1; + R[1 - b].mul(R[b]); + R[b].usqr(); + } + + this.copy(R[0]); + }, + + /* Faster compressed powering for unitary elements */ + /* + compow: function(e, r) { + var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + + m = new ctx.BIG(q); + m.mod(r); + + a = new ctx.BIG(e); + a.mod(m); + + b = new ctx.BIG(e); + b.div(m); + + g1 = new FP48(0); + g2 = new FP48(0); + g1.copy(this); + + c = g1.trace(); + + if (b.iszilch()) { + c=c.xtr_pow(e); + return c; + } + + g2.copy(g1); + g2.frob(f,1); + cp = g2.trace(); + g1.conj(); + g2.mul(g1); + cpm1 = g2.trace(); + g2.mul(g1); + cpm2 = g2.trace(); + + c = c.xtr_pow2(cp, cpm1, cpm2, a, b); + return c; + } +*/ + }; + + /* convert from byte array to FP12 */ + FP48.fromBytes = function (w) { + var a, b, c; + var t = []; + for (var i = 0; i < 16 * ctx.BIG.MODBYTES; i++) t[i] = w[i]; + c = ctx.FP16.fromBytes(t); + for (var i = 0; i < 16 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 16 * ctx.BIG.MODBYTES]; + b = ctx.FP16.fromBytes(t); + for (var i = 0; i < 16 * ctx.BIG.MODBYTES; i++) t[i] = w[i + 32 * ctx.BIG.MODBYTES]; + a = ctx.FP16.fromBytes(t); + return new FP48(a, b, c); + }; + + /* return 1 if b==c, no branching */ + FP48.teq = function (b, c) { + var x = b ^ c; + x -= 1; // if x=0, x now -1 + return (x >> 31) & 1; + }; + + /* p=q0^u0.q1^u1.q2^u2.q3^u3... */ + // Bos & Costello https://eprint.iacr.org/2013/458.pdf + // Faz-Hernandez & Longa & Sanchez https://eprint.iacr.org/2013/158.pdf + // Side channel attack secure + FP48.pow16 = function (q, u) { + var g1 = [], + g2 = [], + g3 = [], + g4 = [], + r = new FP48(0), + p = new FP48(0), + t = [], + mt = new ctx.BIG(0), + w1 = [], + s1 = [], + w2 = [], + s2 = [], + w3 = [], + s3 = [], + w4 = [], + s4 = [], + i, + j, + k, + nb, + bt, + pb1, + pb2, + pb3, + pb4; + + for (i = 0; i < 16; i++) { + t[i] = new ctx.BIG(u[i]); + t[i].norm(); + } + + g1[0] = new FP48(q[0]); // q[0] + g1[1] = new FP48(g1[0]); + g1[1].mul(q[1]); // q[0].q[1] + g1[2] = new FP48(g1[0]); + g1[2].mul(q[2]); // q[0].q[2] + g1[3] = new FP48(g1[1]); + g1[3].mul(q[2]); // q[0].q[1].q[2] + g1[4] = new FP48(q[0]); + g1[4].mul(q[3]); // q[0].q[3] + g1[5] = new FP48(g1[1]); + g1[5].mul(q[3]); // q[0].q[1].q[3] + g1[6] = new FP48(g1[2]); + g1[6].mul(q[3]); // q[0].q[2].q[3] + g1[7] = new FP48(g1[3]); + g1[7].mul(q[3]); // q[0].q[1].q[2].q[3] + + g2[0] = new FP48(q[4]); // q[0] + g2[1] = new FP48(g2[0]); + g2[1].mul(q[5]); // q[0].q[1] + g2[2] = new FP48(g2[0]); + g2[2].mul(q[6]); // q[0].q[2] + g2[3] = new FP48(g2[1]); + g2[3].mul(q[6]); // q[0].q[1].q[2] + g2[4] = new FP48(q[4]); + g2[4].mul(q[7]); // q[0].q[3] + g2[5] = new FP48(g2[1]); + g2[5].mul(q[7]); // q[0].q[1].q[3] + g2[6] = new FP48(g2[2]); + g2[6].mul(q[7]); // q[0].q[2].q[3] + g2[7] = new FP48(g2[3]); + g2[7].mul(q[7]); // q[0].q[1].q[2].q[3] + + g3[0] = new FP48(q[8]); // q[0] + g3[1] = new FP48(g3[0]); + g3[1].mul(q[9]); // q[0].q[1] + g3[2] = new FP48(g3[0]); + g3[2].mul(q[10]); // q[0].q[2] + g3[3] = new FP48(g3[1]); + g3[3].mul(q[10]); // q[0].q[1].q[2] + g3[4] = new FP48(q[8]); + g3[4].mul(q[11]); // q[0].q[3] + g3[5] = new FP48(g3[1]); + g3[5].mul(q[11]); // q[0].q[1].q[3] + g3[6] = new FP48(g3[2]); + g3[6].mul(q[11]); // q[0].q[2].q[3] + g3[7] = new FP48(g3[3]); + g3[7].mul(q[11]); // q[0].q[1].q[2].q[3] + + g4[0] = new FP48(q[12]); // q[0] + g4[1] = new FP48(g4[0]); + g4[1].mul(q[13]); // q[0].q[1] + g4[2] = new FP48(g4[0]); + g4[2].mul(q[14]); // q[0].q[2] + g4[3] = new FP48(g4[1]); + g4[3].mul(q[14]); // q[0].q[1].q[2] + g4[4] = new FP48(q[12]); + g4[4].mul(q[15]); // q[0].q[3] + g4[5] = new FP48(g4[1]); + g4[5].mul(q[15]); // q[0].q[1].q[3] + g4[6] = new FP48(g4[2]); + g4[6].mul(q[15]); // q[0].q[2].q[3] + g4[7] = new FP48(g4[3]); + g4[7].mul(q[15]); // q[0].q[1].q[2].q[3] + + // Make it odd + pb1 = 1 - t[0].parity(); + t[0].inc(pb1); + t[0].norm(); + + pb2 = 1 - t[4].parity(); + t[4].inc(pb2); + t[4].norm(); + + pb3 = 1 - t[8].parity(); + t[8].inc(pb3); + t[8].norm(); + + pb4 = 1 - t[12].parity(); + t[12].inc(pb4); + t[12].norm(); + + // Number of bits + mt.zero(); + for (i = 0; i < 16; i++) { + mt.or(t[i]); + } + + nb = 1 + mt.nbits(); + + // Sign pivot + s1[nb - 1] = 1; + s2[nb - 1] = 1; + s3[nb - 1] = 1; + s4[nb - 1] = 1; + for (i = 0; i < nb - 1; i++) { + t[0].fshr(1); + s1[i] = 2 * t[0].parity() - 1; + t[4].fshr(1); + s2[i] = 2 * t[4].parity() - 1; + t[8].fshr(1); + s3[i] = 2 * t[8].parity() - 1; + t[12].fshr(1); + s4[i] = 2 * t[12].parity() - 1; + } + + // Recoded exponent + for (i = 0; i < nb; i++) { + w1[i] = 0; + k = 1; + for (j = 1; j < 4; j++) { + bt = s1[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w1[i] += bt * k; + k *= 2; + } + w2[i] = 0; + k = 1; + for (j = 5; j < 8; j++) { + bt = s2[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w2[i] += bt * k; + k *= 2; + } + w3[i] = 0; + k = 1; + for (j = 9; j < 12; j++) { + bt = s3[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w3[i] += bt * k; + k *= 2; + } + w4[i] = 0; + k = 1; + for (j = 13; j < 16; j++) { + bt = s4[i] * t[j].parity(); + t[j].fshr(1); + t[j].dec(bt >> 1); + t[j].norm(); + w4[i] += bt * k; + k *= 2; + } + } + + // Main loop + p.select(g1, 2 * w1[nb - 1] + 1); + r.select(g2, 2 * w2[nb - 1] + 1); + p.mul(r); + r.select(g3, 2 * w3[nb - 1] + 1); + p.mul(r); + r.select(g4, 2 * w4[nb - 1] + 1); + p.mul(r); + for (i = nb - 2; i >= 0; i--) { + p.usqr(); + r.select(g1, 2 * w1[i] + s1[i]); + p.mul(r); + r.select(g2, 2 * w2[i] + s2[i]); + p.mul(r); + r.select(g3, 2 * w3[i] + s3[i]); + p.mul(r); + r.select(g4, 2 * w4[i] + s4[i]); + p.mul(r); + } + + // apply correction + r.copy(q[0]); + r.conj(); + r.mul(p); + p.cmove(r, pb1); + + r.copy(q[4]); + r.conj(); + r.mul(p); + p.cmove(r, pb2); + + r.copy(q[8]); + r.conj(); + r.mul(p); + p.cmove(r, pb3); + + r.copy(q[12]); + r.conj(); + r.mul(p); + p.cmove(r, pb4); + + p.reduce(); + return p; + }; + + return FP48; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP48: FP48, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/fp8.js b/packages/bls-verify/src/vendor/amcl-js/src/fp8.js new file mode 100644 index 000000000..0be8b39d0 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/fp8.js @@ -0,0 +1,737 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Finite Field arithmetic Fp^8 functions */ + +/* FP8 elements are of the form a+ib, where i is sqrt(sqrt(-1+sqrt(-1))) */ + +var FP8 = function (ctx) { + 'use strict'; + + /* general purpose constructor */ + var FP8 = function (c, d) { + if (c instanceof FP8) { + this.a = new ctx.FP4(c.a); + this.b = new ctx.FP4(c.b); + } else { + this.a = new ctx.FP4(c); + this.b = new ctx.FP4(d); + } + }; + + FP8.prototype = { + /* reduce all components of this mod Modulus */ + reduce: function () { + this.a.reduce(); + this.b.reduce(); + }, + + /* normalise all components of this mod Modulus */ + norm: function () { + this.a.norm(); + this.b.norm(); + }, + + /* test this==0 ? */ + iszilch: function () { + return this.a.iszilch() && this.b.iszilch(); + }, + + islarger: function () { + if (this.iszilch()) return 0; + var cmp = this.b.larger(); + if (cmp != 0) return cmp; + return this.a.larger(); + }, + + toBytes: function (bf) { + var t = []; + this.b.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) bf[i] = t[i]; + this.a.toBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) bf[i + 4 * ctx.BIG.MODBYTES] = t[i]; + }, + + /* test this==1 ? */ + isunity: function () { + var one = new ctx.FP4(1); + return this.a.equals(one) && this.b.iszilch(); + }, + + /* conditional copy of g to this depending on d */ + cmove: function (g, d) { + this.a.cmove(g.a, d); + this.b.cmove(g.b, d); + }, + + /* test is w real? That is in a+ib test b is zero */ + isreal: function () { + return this.b.iszilch(); + }, + + /* extract real part a */ + real: function () { + return this.a; + }, + + geta: function () { + return this.a; + }, + + /* extract imaginary part b */ + getb: function () { + return this.b; + }, + + /* test this=x? */ + equals: function (x) { + return this.a.equals(x.a) && this.b.equals(x.b); + }, + + /* copy this=x */ + copy: function (x) { + this.a.copy(x.a); + this.b.copy(x.b); + }, + + /* this=0 */ + zero: function () { + this.a.zero(); + this.b.zero(); + }, + + /* this=1 */ + one: function () { + this.a.one(); + this.b.zero(); + }, + + /* set from two FP4s */ + set: function (c, d) { + this.a.copy(c); + this.b.copy(d); + }, + + /* set a */ + seta: function (c) { + this.a.copy(c); + this.b.zero(); + }, + + sign: function () { + var p1 = this.a.sign(); + var p2 = this.b.sign(); + if (ctx.FP.BIG_ENDIAN_SIGN) { + var u = this.b.iszilch() ? 1 : 0; + p2 ^= (p1 ^ p2) & u; + return p2; + } else { + var u = this.a.iszilch() ? 1 : 0; + p1 ^= (p1 ^ p2) & u; + return p1; + } + }, + + /* this=-this */ + neg: function () { + this.norm(); + var m = new ctx.FP4(this.a), + t = new ctx.FP4(0); + + m.add(this.b); + m.neg(); + t.copy(m); + t.add(this.b); + this.b.copy(m); + this.b.add(this.a); + this.a.copy(t); + this.norm(); + }, + + /* this=conjugate(this) */ + conj: function () { + this.b.neg(); + this.norm(); + }, + + /* this=-conjugate(this) */ + nconj: function () { + this.a.neg(); + this.norm(); + }, + + /* this+=x */ + add: function (x) { + this.a.add(x.a); + this.b.add(x.b); + }, + + /* this-=x */ + sub: function (x) { + var m = new FP8(x); + m.neg(); + this.add(m); + }, + + rsub: function (x) { + this.neg(); + this.add(x); + }, + + /* this*=s where s is FP4 */ + pmul: function (s) { + this.a.mul(s); + this.b.mul(s); + }, + + /* this*=c where s is int */ + imul: function (c) { + this.a.imul(c); + this.b.imul(c); + }, + + /* this*=this */ + sqr: function () { + var t1 = new ctx.FP4(this.a), + t2 = new ctx.FP4(this.b), + t3 = new ctx.FP4(this.a); + + t3.mul(this.b); + t1.add(this.b); + t1.norm(); + t2.times_i(); + + t2.add(this.a); + t2.norm(); + this.a.copy(t1); + + this.a.mul(t2); + + t2.copy(t3); + t2.times_i(); + t2.add(t3); + + t2.neg(); + + this.a.add(t2); + + this.b.copy(t3); + this.b.add(t3); + + this.norm(); + }, + + /* this*=y */ + mul: function (y) { + var t1 = new ctx.FP4(this.a), + t2 = new ctx.FP4(this.b), + t3 = new ctx.FP4(0), + t4 = new ctx.FP4(this.b); + + t1.mul(y.a); + t2.mul(y.b); + t3.copy(y.b); + t3.add(y.a); + t4.add(this.a); + + t3.norm(); + t4.norm(); + + t4.mul(t3); + + t3.copy(t1); + t3.neg(); + t4.add(t3); + + t3.copy(t2); + t3.neg(); + this.b.copy(t4); + this.b.add(t3); + + t2.times_i(); + this.a.copy(t2); + this.a.add(t1); + + this.norm(); + }, + + /* convert to hex string */ + toString: function () { + return '[' + this.a.toString() + ',' + this.b.toString() + ']'; + }, + + /* this=1/this */ + inverse: function (h) { + this.norm(); + + var t1 = new ctx.FP4(this.a), + t2 = new ctx.FP4(this.b); + + t1.sqr(); + t2.sqr(); + t2.times_i(); + t2.norm(); // ?? + t1.sub(t2); + t1.inverse(h); + this.a.mul(t1); + t1.neg(); + t1.norm(); + this.b.mul(t1); + }, + + /* this*=i where i = sqrt(-1+sqrt(-1)) */ + times_i: function () { + var s = new ctx.FP4(this.b), + t = new ctx.FP4(this.a); + + s.times_i(); + this.b.copy(t); + + this.a.copy(s); + this.norm(); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.neg(); + this.norm(); + } + }, + + times_i2: function () { + this.a.times_i(); + this.b.times_i(); + }, + + /* this=this^q using Frobenius, where q is Modulus */ + frob: function (f) { + var ff = new ctx.FP2(f); + ff.sqr(); + ff.mul_ip(); + ff.norm(); + this.a.frob(ff); + this.b.frob(ff); + this.b.pmul(f); + this.b.times_i(); + }, + + /* this=this^e */ + /* + pow: function(e) { + var w = new FP8(this), + z = new ctx.BIG(e), + r = new FP8(1), + bt; + w.norm(); + z.norm(); + for (;;) { + bt = z.parity(); + z.fshr(1); + + if (bt === 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + + w.sqr(); + } + r.reduce(); + + return r; + }, */ + + /* XTR xtr_a function */ + /* + xtr_A: function(w, y, z) { + var r = new FP8(w), + t = new FP8(w); + + r.sub(y); + r.norm(); + r.pmul(this.a); + t.add(y); + t.norm(); + t.pmul(this.b); + t.times_i(); + + this.copy(r); + this.add(t); + this.add(z); + + this.reduce(); + }, +*/ + /* XTR xtr_d function */ + /* + xtr_D: function() { + var w = new FP8(this); //w.copy(this); + this.sqr(); + w.conj(); + w.add(w); + this.sub(w); + this.reduce(); + }, +*/ + /* r=x^n using XTR method on traces of FP24s */ + /* + xtr_pow: function(n) { + var sf = new FP8(this); + sf.norm(); + var a = new FP8(3), + b = new FP8(sf), + c = new FP8(b), + t = new FP8(0), + r = new FP8(0), + par, v, nb, i; + + c.xtr_D(); + + + par = n.parity(); + v = new ctx.BIG(n); + v.norm(); + v.fshr(1); + + if (par === 0) { + v.dec(1); + v.norm(); + } + + nb = v.nbits(); + for (i = nb - 1; i >= 0; i--) { + if (v.bit(i) != 1) { + t.copy(b); + sf.conj(); + c.conj(); + b.xtr_A(a, sf, c); + sf.conj(); + c.copy(t); + c.xtr_D(); + a.xtr_D(); + } else { + t.copy(a); + t.conj(); + a.copy(b); + a.xtr_D(); + b.xtr_A(c, sf, t); + c.xtr_D(); + } + } + + if (par === 0) { + r.copy(c); + } else { + r.copy(b); + } + r.reduce(); + + return r; + }, +*/ + /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP24s. See Stam thesis. */ + /* + xtr_pow2: function(ck, ckml, ckm2l, a, b) { + + var e = new ctx.BIG(a), + d = new ctx.BIG(b), + w = new ctx.BIG(0), + cu = new FP8(ck), + cv = new FP8(this), + cumv = new FP8(ckml), + cum2v = new FP8(ckm2l), + r = new FP8(0), + t = new FP8(0), + f2 = 0, + i; + + e.norm(); + d.norm(); + + while (d.parity() === 0 && e.parity() === 0) { + d.fshr(1); + e.fshr(1); + f2++; + } + + while (ctx.BIG.comp(d, e) !== 0) { + if (ctx.BIG.comp(d, e) > 0) { + w.copy(e); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(d, w) <= 0) { + w.copy(d); + d.copy(e); + e.rsub(w); + e.norm(); + + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cum2v.conj(); + cumv.copy(cv); + cv.copy(cu); + cu.copy(t); + + } else if (d.parity() === 0) { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } else if (e.parity() == 1) { + d.sub(e); + d.norm(); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cu.xtr_D(); + cum2v.copy(cv); + cum2v.xtr_D(); + cum2v.conj(); + cv.copy(t); + } else { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } + } + if (ctx.BIG.comp(d, e) < 0) { + w.copy(d); + w.imul(4); + w.norm(); + + if (ctx.BIG.comp(e, w) <= 0) { + e.sub(d); + e.norm(); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cum2v.copy(cumv); + cumv.copy(cu); + cu.copy(t); + } else if (e.parity() === 0) { + w.copy(d); + d.copy(e); + d.fshr(1); + e.copy(w); + t.copy(cumv); + t.xtr_D(); + cumv.copy(cum2v); + cumv.conj(); + cum2v.copy(t); + cum2v.conj(); + t.copy(cv); + t.xtr_D(); + cv.copy(cu); + cu.copy(t); + } else if (d.parity() == 1) { + w.copy(e); + e.copy(d); + w.sub(d); + w.norm(); + d.copy(w); + d.fshr(1); + t.copy(cv); + t.xtr_A(cu, cumv, cum2v); + cumv.conj(); + cum2v.copy(cu); + cum2v.xtr_D(); + cum2v.conj(); + cu.copy(cv); + cu.xtr_D(); + cv.copy(t); + } else { + d.fshr(1); + r.copy(cum2v); + r.conj(); + t.copy(cumv); + t.xtr_A(cu, cv, r); + cum2v.copy(cumv); + cum2v.xtr_D(); + cumv.copy(t); + cu.xtr_D(); + } + } + } + r.copy(cv); + r.xtr_A(cu, cumv, cum2v); + for (i = 0; i < f2; i++) { + r.xtr_D(); + } + r = r.xtr_pow(d); + return r; + }, +*/ + /* New stuff for ecp4.js */ + + div2: function () { + this.a.div2(); + this.b.div2(); + }, + + div_i: function () { + var u = new ctx.FP4(this.a), + v = new ctx.FP4(this.b); + u.div_i(); + this.a.copy(v); + this.b.copy(u); + if (ctx.FP.TOWER == ctx.FP.POSITOWER) { + this.neg(); + this.norm(); + } + }, + + qmul: function (s) { + this.a.pmul(s); + this.b.pmul(s); + }, + + tmul: function (s) { + this.a.qmul(s); + this.b.qmul(s); + }, + + /* this^e */ + /* + pow: function(e) { + var r = new FP8(1), + w = new FP8(this), + z = new ctx.BIG(e), + bt; + + for (;;) { + bt = z.parity(); + z.fshr(1); + if (bt == 1) { + r.mul(w); + } + + if (z.iszilch()) { + break; + } + w.sqr(); + } + + r.reduce(); + this.copy(r); + },*/ + + qr: function (h) { + var c = new FP8(this); + c.conj(); + c.mul(this); + return c.geta().qr(h); + }, + + sqrt: function (h) { + if (this.iszilch()) { + return; + } + var wa = new ctx.FP4(this.a), + wb = new ctx.FP4(this.a), + ws = new ctx.FP4(this.b), + wt = new ctx.FP4(this.a); + var hint = new ctx.FP(0); + + ws.sqr(); + wa.sqr(); + ws.times_i(); + ws.norm(); + wa.sub(ws); + + ws.copy(wa); + ws.norm(); + ws.sqrt(h); + + wa.copy(wt); + wa.add(ws); + wa.norm(); + wa.div2(); + + wb.copy(this.b); + wb.div2(); + var qr = wa.qr(hint); + + // tweak hint - multiply old hint by Norm(1/Beta)^e where Beta is irreducible polynomial + ws.copy(wa); + var twk = new ctx.FP(0); + twk.rcopy(ctx.ROM_FIELD.TWK); + twk.mul(hint); + ws.div_i(); + ws.norm(); + + wa.cmove(ws, 1 - qr); + hint.cmove(twk, 1 - qr); + + this.a.copy(wa); + this.a.sqrt(hint); + ws.copy(wa); + ws.inverse(hint); + ws.mul(this.a); + this.b.copy(ws); + this.b.mul(wb); + wt.copy(this.a); + + this.a.cmove(this.b, 1 - qr); + this.b.cmove(wt, 1 - qr); + + var sgn = this.sign(); + var nr = new FP8(this); + nr.neg(); + nr.norm(); + this.cmove(nr, sgn); + }, + }; + + FP8.rand = function (rng) { + return new FP8(ctx.FP4.rand(rng), ctx.FP4.rand(rng)); + }; + + FP8.fromBytes = function (bf) { + var t = []; + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = bf[i]; + var tb = ctx.FP4.fromBytes(t); + for (var i = 0; i < 4 * ctx.BIG.MODBYTES; i++) t[i] = bf[i + 4 * ctx.BIG.MODBYTES]; + var ta = ctx.FP4.fromBytes(t); + return new FP8(ta, tb); + }; + + return FP8; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + FP8: FP8, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/gcm.js b/packages/bls-verify/src/vendor/amcl-js/src/gcm.js new file mode 100644 index 000000000..a66c0b39a --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/gcm.js @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Implementation of the ctx.AES-GCM Encryption/Authentication + * + * Some restrictions.. + * 1. Only for use with ctx.AES + * 2. Returned tag is always 128-bits. Truncate at your own risk. + * 3. The order of function calls must follow some rules + * + * Typical sequence of calls.. + * 1. call GCM_init + * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size) + * 3. call GCM_add_header one last time with any length of header + * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes + * 5. call GCM_add_cipher one last time with any length of cipher/plaintext + * 6. call GCM_finish to extract the tag. + * + * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf + */ + +var GCM = function (ctx) { + 'use strict'; + + var GCM = function () { + this.table = new Array(128); + for (var i = 0; i < 128; i++) { + this.table[i] = new Array(4); /* 2k bytes */ + } + this.stateX = []; + this.Y_0 = []; + this.counter = 0; + this.lenA = []; + this.lenC = []; + this.status = 0; + this.a = new ctx.AES(); + }; + + // GCM constants + + GCM.ACCEPTING_HEADER = 0; + GCM.ACCEPTING_CIPHER = 1; + GCM.NOT_ACCEPTING_MORE = 2; + GCM.FINISHED = 3; + GCM.ENCRYPTING = 0; + GCM.DECRYPTING = 1; + + GCM.prototype = { + precompute: function (H) { + var b = [], + i, + j, + c; + + for (i = j = 0; i < 4; i++, j += 4) { + b[0] = H[j]; + b[1] = H[j + 1]; + b[2] = H[j + 2]; + b[3] = H[j + 3]; + this.table[0][i] = GCM.pack(b); + } + for (i = 1; i < 128; i++) { + c = 0; + for (j = 0; j < 4; j++) { + this.table[i][j] = c | (this.table[i - 1][j] >>> 1); + c = this.table[i - 1][j] << 31; + } + + if (c !== 0) { + this.table[i][0] ^= 0xe1000000; /* irreducible polynomial */ + } + } + }, + + gf2mul: function () { + /* gf2m mul - Z=H*X mod 2^128 */ + var P = [], + b = [], + i, + j, + m, + k, + c; + + P[0] = P[1] = P[2] = P[3] = 0; + j = 8; + m = 0; + + for (i = 0; i < 128; i++) { + c = (this.stateX[m] >>> --j) & 1; + c = ~c + 1; + for (k = 0; k < 4; k++) { + P[k] ^= this.table[i][k] & c; + } + + if (j === 0) { + j = 8; + m++; + if (m == 16) { + break; + } + } + } + + for (i = j = 0; i < 4; i++, j += 4) { + b = GCM.unpack(P[i]); + this.stateX[j] = b[0]; + this.stateX[j + 1] = b[1]; + this.stateX[j + 2] = b[2]; + this.stateX[j + 3] = b[3]; + } + }, + + wrap: function () { + /* Finish off GHASH */ + var F = [], + L = [], + b = [], + i, + j; + + /* convert lengths from bytes to bits */ + F[0] = (this.lenA[0] << 3) | ((this.lenA[1] & 0xe0000000) >>> 29); + F[1] = this.lenA[1] << 3; + F[2] = (this.lenC[0] << 3) | ((this.lenC[1] & 0xe0000000) >>> 29); + F[3] = this.lenC[1] << 3; + + for (i = j = 0; i < 4; i++, j += 4) { + b = GCM.unpack(F[i]); + L[j] = b[0]; + L[j + 1] = b[1]; + L[j + 2] = b[2]; + L[j + 3] = b[3]; + } + + for (i = 0; i < 16; i++) { + this.stateX[i] ^= L[i]; + } + + this.gf2mul(); + }, + + /* Initialize GCM mode */ + init: function (nk, key, niv, iv) { + /* iv size niv is usually 12 bytes (96 bits). ctx.AES key size nk can be 16,24 or 32 bytes */ + var H = [], + b = [], + i; + + for (i = 0; i < 16; i++) { + H[i] = 0; + this.stateX[i] = 0; + } + + this.a.init(ctx.AES.ECB, nk, key, iv); + this.a.ecb_encrypt(H); /* E(K,0) */ + this.precompute(H); + + this.lenA[0] = this.lenC[0] = this.lenA[1] = this.lenC[1] = 0; + + if (niv == 12) { + for (i = 0; i < 12; i++) { + this.a.f[i] = iv[i]; + } + + b = GCM.unpack(1); + this.a.f[12] = b[0]; + this.a.f[13] = b[1]; + this.a.f[14] = b[2]; + this.a.f[15] = b[3]; /* initialise IV */ + + for (i = 0; i < 16; i++) { + this.Y_0[i] = this.a.f[i]; + } + } else { + this.status = GCM.ACCEPTING_CIPHER; + this.ghash(iv, niv); /* GHASH(H,0,IV) */ + this.wrap(); + + for (i = 0; i < 16; i++) { + this.a.f[i] = this.stateX[i]; + this.Y_0[i] = this.a.f[i]; + this.stateX[i] = 0; + } + + this.lenA[0] = this.lenC[0] = this.lenA[1] = this.lenC[1] = 0; + } + + this.status = GCM.ACCEPTING_HEADER; + }, + + /* Add Header data - included but not encrypted */ + add_header: function (header, len) { + /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ + var i, + j = 0; + + if (this.status != GCM.ACCEPTING_HEADER) { + return false; + } + + while (j < len) { + for (i = 0; i < 16 && j < len; i++) { + this.stateX[i] ^= header[j++]; + this.lenA[1]++; + this.lenA[1] |= 0; + + if (this.lenA[1] === 0) { + this.lenA[0]++; + } + } + + this.gf2mul(); + } + + if (len % 16 !== 0) { + this.status = GCM.ACCEPTING_CIPHER; + } + + return true; + }, + + ghash: function (plain, len) { + var i, + j = 0; + + if (this.status == GCM.ACCEPTING_HEADER) { + this.status = GCM.ACCEPTING_CIPHER; + } + + if (this.status != GCM.ACCEPTING_CIPHER) { + return false; + } + + while (j < len) { + for (i = 0; i < 16 && j < len; i++) { + this.stateX[i] ^= plain[j++]; + this.lenC[1]++; + this.lenC[1] |= 0; + + if (this.lenC[1] === 0) { + this.lenC[0]++; + } + } + this.gf2mul(); + } + + if (len % 16 !== 0) { + this.status = GCM.NOT_ACCEPTING_MORE; + } + + return true; + }, + + /* Add Plaintext - included and encrypted */ + add_plain: function (plain, len) { + var B = [], + b = [], + cipher = [], + i, + j = 0; + + if (this.status == GCM.ACCEPTING_HEADER) { + this.status = GCM.ACCEPTING_CIPHER; + } + + if (this.status != GCM.ACCEPTING_CIPHER) { + return cipher; + } + + while (j < len) { + b[0] = this.a.f[12]; + b[1] = this.a.f[13]; + b[2] = this.a.f[14]; + b[3] = this.a.f[15]; + this.counter = GCM.pack(b); + this.counter++; + b = GCM.unpack(this.counter); + this.a.f[12] = b[0]; + this.a.f[13] = b[1]; + this.a.f[14] = b[2]; + this.a.f[15] = b[3]; /* increment counter */ + + for (i = 0; i < 16; i++) { + B[i] = this.a.f[i]; + } + + this.a.ecb_encrypt(B); /* encrypt it */ + + for (i = 0; i < 16 && j < len; i++) { + cipher[j] = plain[j] ^ B[i]; + this.stateX[i] ^= cipher[j++]; + this.lenC[1]++; + this.lenC[1] |= 0; + + if (this.lenC[1] === 0) { + this.lenC[0]++; + } + } + + this.gf2mul(); + } + + if (len % 16 !== 0) { + this.status = GCM.NOT_ACCEPTING_MORE; + } + + return cipher; + }, + + /* Add Ciphertext - decrypts to plaintext */ + add_cipher: function (cipher, len) { + var B = [], + b = [], + plain = [], + j = 0, + i, + oc; + + if (this.status == GCM.ACCEPTING_HEADER) { + this.status = GCM.ACCEPTING_CIPHER; + } + + if (this.status != GCM.ACCEPTING_CIPHER) { + return plain; + } + + while (j < len) { + b[0] = this.a.f[12]; + b[1] = this.a.f[13]; + b[2] = this.a.f[14]; + b[3] = this.a.f[15]; + this.counter = GCM.pack(b); + this.counter++; + b = GCM.unpack(this.counter); + this.a.f[12] = b[0]; + this.a.f[13] = b[1]; + this.a.f[14] = b[2]; + this.a.f[15] = b[3]; /* increment counter */ + + for (i = 0; i < 16; i++) { + B[i] = this.a.f[i]; + } + + this.a.ecb_encrypt(B); /* encrypt it */ + + for (i = 0; i < 16 && j < len; i++) { + oc = cipher[j]; + plain[j] = cipher[j] ^ B[i]; + this.stateX[i] ^= oc; + j++; + this.lenC[1]++; + this.lenC[1] |= 0; + + if (this.lenC[1] === 0) { + this.lenC[0]++; + } + } + + this.gf2mul(); + } + + if (len % 16 !== 0) { + this.status = GCM.NOT_ACCEPTING_MORE; + } + + return plain; + }, + + /* Finish and extract Tag */ + finish: function (extract) { + /* Finish off GHASH and extract tag (MAC) */ + var tag = [], + i; + + this.wrap(); + /* extract tag */ + if (extract) { + this.a.ecb_encrypt(this.Y_0); /* E(K,Y0) */ + + for (i = 0; i < 16; i++) { + this.Y_0[i] ^= this.stateX[i]; + } + + for (i = 0; i < 16; i++) { + tag[i] = this.Y_0[i]; + this.Y_0[i] = this.stateX[i] = 0; + } + } + + this.status = GCM.FINISHED; + this.a.end(); + + return tag; + }, + }; + + GCM.pack = function (b) { + /* pack 4 bytes into a 32-bit Word */ + return ((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff); + }; + + GCM.unpack = function (a) { + /* unpack bytes from a word */ + var b = []; + + b[3] = a & 0xff; + b[2] = (a >>> 8) & 0xff; + b[1] = (a >>> 16) & 0xff; + b[0] = (a >>> 24) & 0xff; + + return b; + }; + + GCM.hex2bytes = function (s) { + var len = s.length, + data = [], + i; + + for (i = 0; i < len; i += 2) { + data[i / 2] = parseInt(s.substr(i, 2), 16); + } + + return data; + }; + + GCM.encrypt = function (C, T, K, IV, H, P) { + var g = new GCM(); + g.init(K.length, K, IV.length, IV); + g.add_header(H, H.length); + var b = g.add_plain(P, P.length); + for (var i = 0; i < b.length; i++) C[i] = b[i]; + b = g.finish(true); + for (var i = 0; i < b.length; i++) T[i] = b[i]; + }; + + GCM.decrypt = function (P, T, K, IV, H, C) { + var g = new GCM(); + g.init(K.length, K, IV.length, IV); + g.add_header(H, H.length); + var b = g.add_cipher(C, C.length); + for (var i = 0; i < b.length; i++) P[i] = b[i]; + b = g.finish(true); + for (var i = 0; i < b.length; i++) T[i] = b[i]; + }; + + return GCM; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + GCM: GCM, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/hash256.js b/packages/bls-verify/src/vendor/amcl-js/src/hash256.js new file mode 100644 index 000000000..7a629e5d1 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/hash256.js @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var HASH256 = function () { + 'use strict'; + + var HASH256 = function () { + this.length = []; + this.h = []; + this.w = []; + this.init(); + }; + + HASH256.prototype = { + transform: function () { + /* basic transformation step */ + var a, b, c, d, e, f, g, hh, t1, t2, j; + + for (j = 16; j < 64; j++) { + this.w[j] = + (HASH256.theta1(this.w[j - 2]) + + this.w[j - 7] + + HASH256.theta0(this.w[j - 15]) + + this.w[j - 16]) | + 0; + } + + a = this.h[0]; + b = this.h[1]; + c = this.h[2]; + d = this.h[3]; + e = this.h[4]; + f = this.h[5]; + g = this.h[6]; + hh = this.h[7]; + + for (j = 0; j < 64; j++) { + /* 64 times - mush it up */ + t1 = (hh + HASH256.Sig1(e) + HASH256.Ch(e, f, g) + HASH256.HK[j] + this.w[j]) | 0; + t2 = (HASH256.Sig0(a) + HASH256.Maj(a, b, c)) | 0; + hh = g; + g = f; + f = e; + e = (d + t1) | 0; // Need to knock these back down to prevent 52-bit overflow + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + this.h[0] += a; + this.h[1] += b; + this.h[2] += c; + this.h[3] += d; + this.h[4] += e; + this.h[5] += f; + this.h[6] += g; + this.h[7] += hh; + }, + + /* Initialise Hash function */ + init: function () { + /* initialise */ + var i; + + for (i = 0; i < 64; i++) { + this.w[i] = 0; + } + this.length[0] = this.length[1] = 0; + this.h[0] = HASH256.H[0]; + this.h[1] = HASH256.H[1]; + this.h[2] = HASH256.H[2]; + this.h[3] = HASH256.H[3]; + this.h[4] = HASH256.H[4]; + this.h[5] = HASH256.H[5]; + this.h[6] = HASH256.H[6]; + this.h[7] = HASH256.H[7]; + }, + + copy: function (b) { + for (var i = 0; i < 64; i++) { + this.w[i] = b.w[i]; + } + this.length[0] = b.length[0]; + this.length[1] = b.length[1]; + for (var i = 0; i < 8; i++) { + this.h[i] = b.h[i]; + } + }, + + /* process a single byte */ + process: function (byt) { + /* process the next message byte */ + var cnt; + + cnt = (this.length[0] >>> 5) % 16; + this.w[cnt] <<= 8; + this.w[cnt] |= byt & 0xff; + this.length[0] += 8; + + if ((this.length[0] & 0xffffffff) === 0) { + this.length[1]++; + this.length[0] = 0; + } + + if (this.length[0] % 512 === 0) { + this.transform(); + } + }, + + /* process an array of bytes */ + process_array: function (b) { + for (var i = 0; i < b.length; i++) { + this.process(b[i]); + } + }, + + /* process a 32-bit integer */ + process_num: function (n) { + this.process((n >> 24) & 0xff); + this.process((n >> 16) & 0xff); + this.process((n >> 8) & 0xff); + this.process(n & 0xff); + }, + + hash: function () { + /* pad message and finish - supply digest */ + var digest = [], + len0, + len1, + i; + + len0 = this.length[0]; + len1 = this.length[1]; + this.process(0x80); + + while (this.length[0] % 512 != 448) { + this.process(0); + } + + this.w[14] = len1; + this.w[15] = len0; + this.transform(); + + for (i = 0; i < HASH256.len; i++) { + /* convert to bytes */ + digest[i] = (this.h[i >>> 2] >> (8 * (3 - (i % 4)))) & 0xff; + } + this.init(); + + return digest; + }, + + continuing_hash() { + var sh = new HASH256(); + sh.copy(this); + return sh.hash(); + }, + }; + + /* static functions */ + + HASH256.S = function (n, x) { + return (x >>> n) | (x << (32 - n)); + }; + + HASH256.R = function (n, x) { + return x >>> n; + }; + + HASH256.Ch = function (x, y, z) { + return (x & y) ^ (~x & z); + }; + + HASH256.Maj = function (x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + }; + + HASH256.Sig0 = function (x) { + return HASH256.S(2, x) ^ HASH256.S(13, x) ^ HASH256.S(22, x); + }; + + HASH256.Sig1 = function (x) { + return HASH256.S(6, x) ^ HASH256.S(11, x) ^ HASH256.S(25, x); + }; + + HASH256.theta0 = function (x) { + return HASH256.S(7, x) ^ HASH256.S(18, x) ^ HASH256.R(3, x); + }; + + HASH256.theta1 = function (x) { + return HASH256.S(17, x) ^ HASH256.S(19, x) ^ HASH256.R(10, x); + }; + + /* constants */ + HASH256.len = 32; + + HASH256.H = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, + ]; + + HASH256.HK = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, + ]; + + return HASH256; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + HASH256: HASH256, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/hash384.js b/packages/bls-verify/src/vendor/amcl-js/src/hash384.js new file mode 100644 index 000000000..d27028ae3 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/hash384.js @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var HASH384 = function (ctx) { + 'use strict'; + + var HASH384 = function () { + this.length = []; + this.h = []; + this.w = []; + this.init(); + }; + + HASH384.prototype = { + transform: function () { + /* basic transformation step */ + var a, b, c, d, e, f, g, hh, t1, t2, j; + + for (j = 16; j < 80; j++) { + this.w[j] = HASH384.theta1(this.w[j - 2]) + .add(this.w[j - 7]) + .add(HASH384.theta0(this.w[j - 15])) + .add(this.w[j - 16]); + } + + a = this.h[0].copy(); + b = this.h[1].copy(); + c = this.h[2].copy(); + d = this.h[3].copy(); + e = this.h[4].copy(); + f = this.h[5].copy(); + g = this.h[6].copy(); + hh = this.h[7].copy(); + + for (j = 0; j < 80; j++) { + /* 80 times - mush it up */ + t1 = hh.copy(); + t1.add(HASH384.Sig1(e)).add(HASH384.Ch(e, f, g)).add(HASH384.HK[j]).add(this.w[j]); + + t2 = HASH384.Sig0(a); + t2.add(HASH384.Maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.copy(); + e.add(t1); + + d = c; + c = b; + b = a; + a = t1.copy(); + a.add(t2); + } + + this.h[0].add(a); + this.h[1].add(b); + this.h[2].add(c); + this.h[3].add(d); + this.h[4].add(e); + this.h[5].add(f); + this.h[6].add(g); + this.h[7].add(hh); + }, + + copy: function (b) { + for (var i = 0; i < 80; i++) { + this.w[i] = b.w[i].copy(); + } + this.length[0] = b.length[0].copy(); + this.length[1] = b.length[1].copy(); + for (var i = 0; i < 8; i++) { + this.h[i] = b.h[i].copy(); + } + }, + + /* Initialise Hash function */ + init: function () { + /* initialise */ + var i; + + for (i = 0; i < 80; i++) { + this.w[i] = new ctx.UInt64(0, 0); + } + this.length[0] = new ctx.UInt64(0, 0); + this.length[1] = new ctx.UInt64(0, 0); + this.h[0] = HASH384.H[0].copy(); + this.h[1] = HASH384.H[1].copy(); + this.h[2] = HASH384.H[2].copy(); + this.h[3] = HASH384.H[3].copy(); + this.h[4] = HASH384.H[4].copy(); + this.h[5] = HASH384.H[5].copy(); + this.h[6] = HASH384.H[6].copy(); + this.h[7] = HASH384.H[7].copy(); + }, + + /* process a single byte */ + process: function (byt) { + /* process the next message byte */ + var cnt, e; + + cnt = (this.length[0].bot >>> 6) % 16; + this.w[cnt].shlb(); + this.w[cnt].bot |= byt & 0xff; + + e = new ctx.UInt64(0, 8); + this.length[0].add(e); + + if (this.length[0].top === 0 && this.length[0].bot == 0) { + e = new ctx.UInt64(0, 1); + this.length[1].add(e); + } + + if (this.length[0].bot % 1024 === 0) { + this.transform(); + } + }, + + /* process an array of bytes */ + process_array: function (b) { + for (var i = 0; i < b.length; i++) { + this.process(b[i]); + } + }, + + /* process a 32-bit integer */ + process_num: function (n) { + this.process((n >> 24) & 0xff); + this.process((n >> 16) & 0xff); + this.process((n >> 8) & 0xff); + this.process(n & 0xff); + }, + + hash: function () { + /* pad message and finish - supply digest */ + var digest = [], + len0, + len1, + i; + + len0 = this.length[0].copy(); + len1 = this.length[1].copy(); + this.process(0x80); + while (this.length[0].bot % 1024 != 896) { + this.process(0); + } + + this.w[14] = len1; + this.w[15] = len0; + this.transform(); + + for (i = 0; i < HASH384.len; i++) { + /* convert to bytes */ + digest[i] = HASH384.R(8 * (7 - (i % 8)), this.h[i >>> 3]).bot & 0xff; + } + + this.init(); + + return digest; + }, + + continuing_hash() { + var sh = new HASH384(); + sh.copy(this); + return sh.hash(); + }, + }; + + /* static functions */ + HASH384.S = function (n, x) { + if (n == 0) { + return x; + } + + if (n < 32) { + return new ctx.UInt64( + (x.top >>> n) | (x.bot << (32 - n)), + (x.bot >>> n) | (x.top << (32 - n)), + ); + } else { + return new ctx.UInt64( + (x.bot >>> (n - 32)) | (x.top << (64 - n)), + (x.top >>> (n - 32)) | (x.bot << (64 - n)), + ); + } + }; + + HASH384.R = function (n, x) { + if (n == 0) { + return x; + } + + if (n < 32) { + return new ctx.UInt64(x.top >>> n, (x.bot >>> n) | (x.top << (32 - n))); + } else { + return new ctx.UInt64(0, x.top >>> (n - 32)); + } + }; + + HASH384.Ch = function (x, y, z) { + return new ctx.UInt64((x.top & y.top) ^ (~x.top & z.top), (x.bot & y.bot) ^ (~x.bot & z.bot)); + }; + + HASH384.Maj = function (x, y, z) { + return new ctx.UInt64( + (x.top & y.top) ^ (x.top & z.top) ^ (y.top & z.top), + (x.bot & y.bot) ^ (x.bot & z.bot) ^ (y.bot & z.bot), + ); + }; + + HASH384.Sig0 = function (x) { + var r1 = HASH384.S(28, x), + r2 = HASH384.S(34, x), + r3 = HASH384.S(39, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH384.Sig1 = function (x) { + var r1 = HASH384.S(14, x), + r2 = HASH384.S(18, x), + r3 = HASH384.S(41, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH384.theta0 = function (x) { + var r1 = HASH384.S(1, x), + r2 = HASH384.S(8, x), + r3 = HASH384.R(7, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH384.theta1 = function (x) { + var r1 = HASH384.S(19, x), + r2 = HASH384.S(61, x), + r3 = HASH384.R(6, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH384.len = 48; + + HASH384.H = [ + new ctx.UInt64(0xcbbb9d5d, 0xc1059ed8), + new ctx.UInt64(0x629a292a, 0x367cd507), + new ctx.UInt64(0x9159015a, 0x3070dd17), + new ctx.UInt64(0x152fecd8, 0xf70e5939), + new ctx.UInt64(0x67332667, 0xffc00b31), + new ctx.UInt64(0x8eb44a87, 0x68581511), + new ctx.UInt64(0xdb0c2e0d, 0x64f98fa7), + new ctx.UInt64(0x47b5481d, 0xbefa4fa4), + ]; + + HASH384.HK = [ + new ctx.UInt64(0x428a2f98, 0xd728ae22), + new ctx.UInt64(0x71374491, 0x23ef65cd), + new ctx.UInt64(0xb5c0fbcf, 0xec4d3b2f), + new ctx.UInt64(0xe9b5dba5, 0x8189dbbc), + new ctx.UInt64(0x3956c25b, 0xf348b538), + new ctx.UInt64(0x59f111f1, 0xb605d019), + new ctx.UInt64(0x923f82a4, 0xaf194f9b), + new ctx.UInt64(0xab1c5ed5, 0xda6d8118), + new ctx.UInt64(0xd807aa98, 0xa3030242), + new ctx.UInt64(0x12835b01, 0x45706fbe), + new ctx.UInt64(0x243185be, 0x4ee4b28c), + new ctx.UInt64(0x550c7dc3, 0xd5ffb4e2), + new ctx.UInt64(0x72be5d74, 0xf27b896f), + new ctx.UInt64(0x80deb1fe, 0x3b1696b1), + new ctx.UInt64(0x9bdc06a7, 0x25c71235), + new ctx.UInt64(0xc19bf174, 0xcf692694), + new ctx.UInt64(0xe49b69c1, 0x9ef14ad2), + new ctx.UInt64(0xefbe4786, 0x384f25e3), + new ctx.UInt64(0x0fc19dc6, 0x8b8cd5b5), + new ctx.UInt64(0x240ca1cc, 0x77ac9c65), + new ctx.UInt64(0x2de92c6f, 0x592b0275), + new ctx.UInt64(0x4a7484aa, 0x6ea6e483), + new ctx.UInt64(0x5cb0a9dc, 0xbd41fbd4), + new ctx.UInt64(0x76f988da, 0x831153b5), + new ctx.UInt64(0x983e5152, 0xee66dfab), + new ctx.UInt64(0xa831c66d, 0x2db43210), + new ctx.UInt64(0xb00327c8, 0x98fb213f), + new ctx.UInt64(0xbf597fc7, 0xbeef0ee4), + new ctx.UInt64(0xc6e00bf3, 0x3da88fc2), + new ctx.UInt64(0xd5a79147, 0x930aa725), + new ctx.UInt64(0x06ca6351, 0xe003826f), + new ctx.UInt64(0x14292967, 0x0a0e6e70), + new ctx.UInt64(0x27b70a85, 0x46d22ffc), + new ctx.UInt64(0x2e1b2138, 0x5c26c926), + new ctx.UInt64(0x4d2c6dfc, 0x5ac42aed), + new ctx.UInt64(0x53380d13, 0x9d95b3df), + new ctx.UInt64(0x650a7354, 0x8baf63de), + new ctx.UInt64(0x766a0abb, 0x3c77b2a8), + new ctx.UInt64(0x81c2c92e, 0x47edaee6), + new ctx.UInt64(0x92722c85, 0x1482353b), + new ctx.UInt64(0xa2bfe8a1, 0x4cf10364), + new ctx.UInt64(0xa81a664b, 0xbc423001), + new ctx.UInt64(0xc24b8b70, 0xd0f89791), + new ctx.UInt64(0xc76c51a3, 0x0654be30), + new ctx.UInt64(0xd192e819, 0xd6ef5218), + new ctx.UInt64(0xd6990624, 0x5565a910), + new ctx.UInt64(0xf40e3585, 0x5771202a), + new ctx.UInt64(0x106aa070, 0x32bbd1b8), + new ctx.UInt64(0x19a4c116, 0xb8d2d0c8), + new ctx.UInt64(0x1e376c08, 0x5141ab53), + new ctx.UInt64(0x2748774c, 0xdf8eeb99), + new ctx.UInt64(0x34b0bcb5, 0xe19b48a8), + new ctx.UInt64(0x391c0cb3, 0xc5c95a63), + new ctx.UInt64(0x4ed8aa4a, 0xe3418acb), + new ctx.UInt64(0x5b9cca4f, 0x7763e373), + new ctx.UInt64(0x682e6ff3, 0xd6b2b8a3), + new ctx.UInt64(0x748f82ee, 0x5defb2fc), + new ctx.UInt64(0x78a5636f, 0x43172f60), + new ctx.UInt64(0x84c87814, 0xa1f0ab72), + new ctx.UInt64(0x8cc70208, 0x1a6439ec), + new ctx.UInt64(0x90befffa, 0x23631e28), + new ctx.UInt64(0xa4506ceb, 0xde82bde9), + new ctx.UInt64(0xbef9a3f7, 0xb2c67915), + new ctx.UInt64(0xc67178f2, 0xe372532b), + new ctx.UInt64(0xca273ece, 0xea26619c), + new ctx.UInt64(0xd186b8c7, 0x21c0c207), + new ctx.UInt64(0xeada7dd6, 0xcde0eb1e), + new ctx.UInt64(0xf57d4f7f, 0xee6ed178), + new ctx.UInt64(0x06f067aa, 0x72176fba), + new ctx.UInt64(0x0a637dc5, 0xa2c898a6), + new ctx.UInt64(0x113f9804, 0xbef90dae), + new ctx.UInt64(0x1b710b35, 0x131c471b), + new ctx.UInt64(0x28db77f5, 0x23047d84), + new ctx.UInt64(0x32caab7b, 0x40c72493), + new ctx.UInt64(0x3c9ebe0a, 0x15c9bebc), + new ctx.UInt64(0x431d67c4, 0x9c100d4c), + new ctx.UInt64(0x4cc5d4be, 0xcb3e42b6), + new ctx.UInt64(0x597f299c, 0xfc657e2a), + new ctx.UInt64(0x5fcb6fab, 0x3ad6faec), + new ctx.UInt64(0x6c44198c, 0x4a475817), + ]; + + return HASH384; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + HASH384: HASH384, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/hash512.js b/packages/bls-verify/src/vendor/amcl-js/src/hash512.js new file mode 100644 index 000000000..6a2797177 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/hash512.js @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var HASH512 = function (ctx) { + 'use strict'; + + var HASH512 = function () { + this.length = []; + this.h = []; + this.w = []; + this.init(); + }; + + HASH512.prototype = { + transform: function () { + /* basic transformation step */ + var a, b, c, d, e, f, g, hh, t1, t2, j; + + for (j = 16; j < 80; j++) { + this.w[j] = HASH512.theta1(this.w[j - 2]) + .add(this.w[j - 7]) + .add(HASH512.theta0(this.w[j - 15])) + .add(this.w[j - 16]); + } + + a = this.h[0].copy(); + b = this.h[1].copy(); + c = this.h[2].copy(); + d = this.h[3].copy(); + e = this.h[4].copy(); + f = this.h[5].copy(); + g = this.h[6].copy(); + hh = this.h[7].copy(); + + for (j = 0; j < 80; j++) { + /* 80 times - mush it up */ + t1 = hh.copy(); + t1.add(HASH512.Sig1(e)).add(HASH512.Ch(e, f, g)).add(HASH512.HK[j]).add(this.w[j]); + + t2 = HASH512.Sig0(a); + t2.add(HASH512.Maj(a, b, c)); + hh = g; + g = f; + f = e; + e = d.copy(); + e.add(t1); + + d = c; + c = b; + b = a; + a = t1.copy(); + a.add(t2); + } + + this.h[0].add(a); + this.h[1].add(b); + this.h[2].add(c); + this.h[3].add(d); + this.h[4].add(e); + this.h[5].add(f); + this.h[6].add(g); + this.h[7].add(hh); + }, + + copy: function (b) { + for (var i = 0; i < 80; i++) { + this.w[i] = b.w[i].copy(); + } + this.length[0] = b.length[0].copy(); + this.length[1] = b.length[1].copy(); + for (var i = 0; i < 8; i++) { + this.h[i] = b.h[i].copy(); + } + }, + + /* Initialise Hash function */ + init: function () { + /* initialise */ + var i; + + for (i = 0; i < 80; i++) { + this.w[i] = new ctx.UInt64(0, 0); + } + + this.length[0] = new ctx.UInt64(0, 0); + this.length[1] = new ctx.UInt64(0, 0); + this.h[0] = HASH512.H[0].copy(); + this.h[1] = HASH512.H[1].copy(); + this.h[2] = HASH512.H[2].copy(); + this.h[3] = HASH512.H[3].copy(); + this.h[4] = HASH512.H[4].copy(); + this.h[5] = HASH512.H[5].copy(); + this.h[6] = HASH512.H[6].copy(); + this.h[7] = HASH512.H[7].copy(); + }, + + /* process a single byte */ + process: function (byt) { + /* process the next message byte */ + var cnt, e; + + cnt = (this.length[0].bot >>> 6) % 16; + this.w[cnt].shlb(); + this.w[cnt].bot |= byt & 0xff; + + e = new ctx.UInt64(0, 8); + this.length[0].add(e); + + if (this.length[0].top === 0 && this.length[0].bot == 0) { + e = new ctx.UInt64(0, 1); + this.length[1].add(e); + } + + if (this.length[0].bot % 1024 === 0) { + this.transform(); + } + }, + + /* process an array of bytes */ + process_array: function (b) { + for (var i = 0; i < b.length; i++) { + this.process(b[i]); + } + }, + + /* process a 32-bit integer */ + process_num: function (n) { + this.process((n >> 24) & 0xff); + this.process((n >> 16) & 0xff); + this.process((n >> 8) & 0xff); + this.process(n & 0xff); + }, + + hash: function () { + /* pad message and finish - supply digest */ + var digest = [], + len0, + len1, + i; + + len0 = this.length[0].copy(); + len1 = this.length[1].copy(); + this.process(0x80); + + while (this.length[0].bot % 1024 != 896) { + this.process(0); + } + + this.w[14] = len1; + this.w[15] = len0; + this.transform(); + + for (i = 0; i < HASH512.len; i++) { + /* convert to bytes */ + digest[i] = HASH512.R(8 * (7 - (i % 8)), this.h[i >>> 3]).bot & 0xff; + } + + this.init(); + + return digest; + }, + + continuing_hash() { + var sh = new HASH256(); + sh.copy(this); + return sh.hash(); + }, + }; + + /* static functions */ + HASH512.S = function (n, x) { + if (n == 0) { + return x; + } + + if (n < 32) { + return new ctx.UInt64( + (x.top >>> n) | (x.bot << (32 - n)), + (x.bot >>> n) | (x.top << (32 - n)), + ); + } else { + return new ctx.UInt64( + (x.bot >>> (n - 32)) | (x.top << (64 - n)), + (x.top >>> (n - 32)) | (x.bot << (64 - n)), + ); + } + }; + + HASH512.R = function (n, x) { + if (n == 0) { + return x; + } + + if (n < 32) { + return new ctx.UInt64(x.top >>> n, (x.bot >>> n) | (x.top << (32 - n))); + } else { + return new ctx.UInt64(0, x.top >>> (n - 32)); + } + }; + + HASH512.Ch = function (x, y, z) { + return new ctx.UInt64((x.top & y.top) ^ (~x.top & z.top), (x.bot & y.bot) ^ (~x.bot & z.bot)); + }; + + HASH512.Maj = function (x, y, z) { + return new ctx.UInt64( + (x.top & y.top) ^ (x.top & z.top) ^ (y.top & z.top), + (x.bot & y.bot) ^ (x.bot & z.bot) ^ (y.bot & z.bot), + ); + }; + + HASH512.Sig0 = function (x) { + var r1 = HASH512.S(28, x), + r2 = HASH512.S(34, x), + r3 = HASH512.S(39, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH512.Sig1 = function (x) { + var r1 = HASH512.S(14, x), + r2 = HASH512.S(18, x), + r3 = HASH512.S(41, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH512.theta0 = function (x) { + var r1 = HASH512.S(1, x), + r2 = HASH512.S(8, x), + r3 = HASH512.R(7, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + HASH512.theta1 = function (x) { + var r1 = HASH512.S(19, x), + r2 = HASH512.S(61, x), + r3 = HASH512.R(6, x); + + return new ctx.UInt64(r1.top ^ r2.top ^ r3.top, r1.bot ^ r2.bot ^ r3.bot); + }; + + /* constants */ + HASH512.len = 64; + + HASH512.H = [ + new ctx.UInt64(0x6a09e667, 0xf3bcc908), + new ctx.UInt64(0xbb67ae85, 0x84caa73b), + new ctx.UInt64(0x3c6ef372, 0xfe94f82b), + new ctx.UInt64(0xa54ff53a, 0x5f1d36f1), + new ctx.UInt64(0x510e527f, 0xade682d1), + new ctx.UInt64(0x9b05688c, 0x2b3e6c1f), + new ctx.UInt64(0x1f83d9ab, 0xfb41bd6b), + new ctx.UInt64(0x5be0cd19, 0x137e2179), + ]; + + HASH512.HK = [ + new ctx.UInt64(0x428a2f98, 0xd728ae22), + new ctx.UInt64(0x71374491, 0x23ef65cd), + new ctx.UInt64(0xb5c0fbcf, 0xec4d3b2f), + new ctx.UInt64(0xe9b5dba5, 0x8189dbbc), + new ctx.UInt64(0x3956c25b, 0xf348b538), + new ctx.UInt64(0x59f111f1, 0xb605d019), + new ctx.UInt64(0x923f82a4, 0xaf194f9b), + new ctx.UInt64(0xab1c5ed5, 0xda6d8118), + new ctx.UInt64(0xd807aa98, 0xa3030242), + new ctx.UInt64(0x12835b01, 0x45706fbe), + new ctx.UInt64(0x243185be, 0x4ee4b28c), + new ctx.UInt64(0x550c7dc3, 0xd5ffb4e2), + new ctx.UInt64(0x72be5d74, 0xf27b896f), + new ctx.UInt64(0x80deb1fe, 0x3b1696b1), + new ctx.UInt64(0x9bdc06a7, 0x25c71235), + new ctx.UInt64(0xc19bf174, 0xcf692694), + new ctx.UInt64(0xe49b69c1, 0x9ef14ad2), + new ctx.UInt64(0xefbe4786, 0x384f25e3), + new ctx.UInt64(0x0fc19dc6, 0x8b8cd5b5), + new ctx.UInt64(0x240ca1cc, 0x77ac9c65), + new ctx.UInt64(0x2de92c6f, 0x592b0275), + new ctx.UInt64(0x4a7484aa, 0x6ea6e483), + new ctx.UInt64(0x5cb0a9dc, 0xbd41fbd4), + new ctx.UInt64(0x76f988da, 0x831153b5), + new ctx.UInt64(0x983e5152, 0xee66dfab), + new ctx.UInt64(0xa831c66d, 0x2db43210), + new ctx.UInt64(0xb00327c8, 0x98fb213f), + new ctx.UInt64(0xbf597fc7, 0xbeef0ee4), + new ctx.UInt64(0xc6e00bf3, 0x3da88fc2), + new ctx.UInt64(0xd5a79147, 0x930aa725), + new ctx.UInt64(0x06ca6351, 0xe003826f), + new ctx.UInt64(0x14292967, 0x0a0e6e70), + new ctx.UInt64(0x27b70a85, 0x46d22ffc), + new ctx.UInt64(0x2e1b2138, 0x5c26c926), + new ctx.UInt64(0x4d2c6dfc, 0x5ac42aed), + new ctx.UInt64(0x53380d13, 0x9d95b3df), + new ctx.UInt64(0x650a7354, 0x8baf63de), + new ctx.UInt64(0x766a0abb, 0x3c77b2a8), + new ctx.UInt64(0x81c2c92e, 0x47edaee6), + new ctx.UInt64(0x92722c85, 0x1482353b), + new ctx.UInt64(0xa2bfe8a1, 0x4cf10364), + new ctx.UInt64(0xa81a664b, 0xbc423001), + new ctx.UInt64(0xc24b8b70, 0xd0f89791), + new ctx.UInt64(0xc76c51a3, 0x0654be30), + new ctx.UInt64(0xd192e819, 0xd6ef5218), + new ctx.UInt64(0xd6990624, 0x5565a910), + new ctx.UInt64(0xf40e3585, 0x5771202a), + new ctx.UInt64(0x106aa070, 0x32bbd1b8), + new ctx.UInt64(0x19a4c116, 0xb8d2d0c8), + new ctx.UInt64(0x1e376c08, 0x5141ab53), + new ctx.UInt64(0x2748774c, 0xdf8eeb99), + new ctx.UInt64(0x34b0bcb5, 0xe19b48a8), + new ctx.UInt64(0x391c0cb3, 0xc5c95a63), + new ctx.UInt64(0x4ed8aa4a, 0xe3418acb), + new ctx.UInt64(0x5b9cca4f, 0x7763e373), + new ctx.UInt64(0x682e6ff3, 0xd6b2b8a3), + new ctx.UInt64(0x748f82ee, 0x5defb2fc), + new ctx.UInt64(0x78a5636f, 0x43172f60), + new ctx.UInt64(0x84c87814, 0xa1f0ab72), + new ctx.UInt64(0x8cc70208, 0x1a6439ec), + new ctx.UInt64(0x90befffa, 0x23631e28), + new ctx.UInt64(0xa4506ceb, 0xde82bde9), + new ctx.UInt64(0xbef9a3f7, 0xb2c67915), + new ctx.UInt64(0xc67178f2, 0xe372532b), + new ctx.UInt64(0xca273ece, 0xea26619c), + new ctx.UInt64(0xd186b8c7, 0x21c0c207), + new ctx.UInt64(0xeada7dd6, 0xcde0eb1e), + new ctx.UInt64(0xf57d4f7f, 0xee6ed178), + new ctx.UInt64(0x06f067aa, 0x72176fba), + new ctx.UInt64(0x0a637dc5, 0xa2c898a6), + new ctx.UInt64(0x113f9804, 0xbef90dae), + new ctx.UInt64(0x1b710b35, 0x131c471b), + new ctx.UInt64(0x28db77f5, 0x23047d84), + new ctx.UInt64(0x32caab7b, 0x40c72493), + new ctx.UInt64(0x3c9ebe0a, 0x15c9bebc), + new ctx.UInt64(0x431d67c4, 0x9c100d4c), + new ctx.UInt64(0x4cc5d4be, 0xcb3e42b6), + new ctx.UInt64(0x597f299c, 0xfc657e2a), + new ctx.UInt64(0x5fcb6fab, 0x3ad6faec), + new ctx.UInt64(0x6c44198c, 0x4a475817), + ]; + + return HASH512; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + HASH512: HASH512, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/hmac.js b/packages/bls-verify/src/vendor/amcl-js/src/hmac.js new file mode 100644 index 000000000..b4b85ae3d --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/hmac.js @@ -0,0 +1,764 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var HMAC = function (ctx) { + 'use strict'; + + var HMAC = { + MC_SHA2: 2, + MC_SHA3: 3, + + /* Convert Integer to n-byte array */ + inttobytes: function (n, len) { + var b = [], + i; + + for (i = 0; i < len; i++) { + b[i] = 0; + } + + i = len; + while (n > 0 && i > 0) { + i--; + b[i] = n & 0xff; + n = Math.floor(n / 256); + } + + return b; + }, + + GPhashit: function (hash, sha, pad, zpad, A, n, B) { + var R = [], + H, + W, + i, + len; + + if (hash == this.MC_SHA2) { + if (sha == 32) { + H = new ctx.HASH256(); + } else if (sha == 48) { + H = new ctx.HASH384(); + } else if (sha == 64) { + H = new ctx.HASH512(); + } + } + if (hash == this.MC_SHA3) { + H = new ctx.SHA3(sha); + } + + for (i = 0; i < zpad; i++) H.process(0); + + if (A != null) { + H.process_array(A); + } + + if (n >= 0) { + H.process_num(n); + } + if (B != null) { + H.process_array(B); + } + R = H.hash(); + + if (R.length == 0) { + return null; + } + + if (pad == 0) { + return R; + } + + W = []; + + len = pad; + + if (sha >= len) { + for (i = 0; i < len; i++) { + W[i] = R[i]; + } + } else { + for (i = 0; i < sha; i++) { + W[i + len - sha] = R[i]; + } + + for (i = 0; i < len - sha; i++) { + W[i] = 0; + } + } + + return W; + }, + + SPhashit: function (hash, sha, A) { + return this.GPhashit(hash, sha, 0, 0, A, -1, null); + }, + + KDF2: function (hash, sha, Z, P, olen) { + /* NOTE: the parameter olen is the length of the output k in bytes */ + var hlen = sha, + K = [], + B = [], + k = 0, + counter, + cthreshold, + i; + + for (i = 0; i < K.length; i++) { + K[i] = 0; // redundant? + } + + cthreshold = Math.floor(olen / hlen); + if (olen % hlen !== 0) { + cthreshold++; + } + + for (counter = 1; counter <= cthreshold; counter++) { + B = this.GPhashit(hash, sha, 0, 0, Z, counter, P); + + if (k + hlen > olen) { + for (i = 0; i < olen % hlen; i++) { + K[k++] = B[i]; + } + } else { + for (i = 0; i < hlen; i++) { + K[k++] = B[i]; + } + } + } + + return K; + }, + + /* Password based Key Derivation Function */ + /* Input password p, salt s, and repeat count */ + /* Output key of length olen */ + + PBKDF2: function (hash, sha, Pass, Salt, rep, olen) { + var F = new Array(sha), + U = [], + S = [], + K = [], + opt = 0, + i, + j, + k, + d, + N, + key; + + d = Math.floor(olen / sha); + + if (olen % sha !== 0) { + d++; + } + + opt = 0; + + for (i = 1; i <= d; i++) { + for (j = 0; j < Salt.length; j++) { + S[j] = Salt[j]; + } + + N = this.inttobytes(i, 4); + + for (j = 0; j < 4; j++) { + S[Salt.length + j] = N[j]; + } + + this.HMAC1(hash, sha, F, sha, Pass, S); + + for (j = 0; j < sha; j++) { + U[j] = F[j]; + } + + for (j = 2; j <= rep; j++) { + this.HMAC1(hash, sha, U, sha, Pass, U); + for (k = 0; k < sha; k++) { + F[k] ^= U[k]; + } + } + + for (j = 0; j < sha; j++) { + K[opt++] = F[j]; + } + } + + key = []; + for (i = 0; i < olen; i++) { + key[i] = K[i]; + } + + return key; + }, + + blksize: function (hash, sha) { + var b = 0; + if (hash == this.MC_SHA2) { + b = 64; + if (sha > 32) b = 128; + } + if (hash == this.MC_SHA3) { + b = 200 - 2 * sha; + } + return b; + }, + + HMAC1: function (hash, sha, tag, olen, K, M) { + /* Input is from an octet m * + * olen is requested output length in bytes. k is the key * + * The output is the calculated tag */ + var B = [], + b = 0, + K0, + i; + + b = this.blksize(hash, sha); + if (b == 0) return 0; + + K0 = new Array(b); + + for (i = 0; i < b; i++) { + K0[i] = 0; + } + + if (K.length > b) { + B = this.SPhashit(hash, sha, K); + for (i = 0; i < sha; i++) { + K0[i] = B[i]; + } + } else { + for (i = 0; i < K.length; i++) { + K0[i] = K[i]; + } + } + + for (i = 0; i < b; i++) { + K0[i] ^= 0x36; + } + + B = this.GPhashit(hash, sha, 0, 0, K0, -1, M); + + for (i = 0; i < b; i++) { + K0[i] ^= 0x6a; + } + + B = this.GPhashit(hash, sha, olen, 0, K0, -1, B); + + for (i = 0; i < olen; i++) { + tag[i] = B[i]; + } + + return 1; + }, + + HKDF_Extract: function (hash, hlen, SALT, IKM) { + var PRK = []; + if (SALT == null) { + var H = []; + for (var i = 0; i < hlen; i++) H[i] = 0; + this.HMAC1(hash, hlen, PRK, hlen, H, IKM); + } else { + this.HMAC1(hash, hlen, PRK, hlen, SALT, IKM); + } + return PRK; + }, + + HKDF_Expand: function (hash, hlen, olen, PRK, INFO) { + var i, + j, + k, + m, + n = Math.floor(olen / hlen); + var flen = olen % hlen; + + var OKM = []; + var T = []; + var K = []; + + k = m = 0; + for (i = 1; i <= n; i++) { + for (j = 0; j < INFO.length; j++) T[k++] = INFO[j]; + T[k++] = i; + this.HMAC1(hash, hlen, K, hlen, PRK, T); + k = 0; + T = []; + for (j = 0; j < hlen; j++) { + OKM[m++] = K[j]; + T[k++] = K[j]; + } + } + if (flen > 0) { + for (j = 0; j < INFO.length; j++) T[k++] = INFO[j]; + T[k++] = n + 1; + this.HMAC1(hash, hlen, K, flen, PRK, T); + for (j = 0; j < flen; j++) OKM[m++] = K[j]; + } + return OKM; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + XOF_Expand: function (hlen, olen, DST, MSG) { + var OKM = []; + var H = new ctx.SHA3(hlen); + for (var i = 0; i < MSG.length; i++) H.process(MSG[i]); + H.process((olen >> 8) & 0xff); + H.process(olen & 0xff); + + for (var i = 0; i < DST.length; i++) H.process(DST[i]); + H.process(DST.length); + + H.shake(OKM, olen); + return OKM; + }, + + XMD_Expand(hash, hlen, olen, DST, MSG) { + var OKM = []; + var H1 = []; + var TMP = []; + var TMP2 = []; + + var ell = this.ceil(olen, hlen); + var blk = this.blksize(hash, hlen); + TMP[0] = (olen >> 8) & 0xff; + TMP[1] = olen & 0xff; + TMP[2] = 0; + for (var j = 0; j < DST.length; j++) TMP[3 + j] = DST[j]; + TMP[3 + DST.length] = DST.length; + + var H0 = this.GPhashit(hash, hlen, 0, blk, MSG, -1, TMP); + + var k = 0; + for (var j = 0; j < hlen; j++) H1[j] = 0; + + for (var i = 1; i <= ell; i++) { + for (var j = 0; j < hlen; j++) H1[j] ^= H0[j]; + TMP2[0] = i; + for (var j = 0; j < DST.length; j++) TMP2[1 + j] = DST[j]; + TMP2[1 + DST.length] = DST.length; + H1 = this.GPhashit(hash, hlen, 0, 0, H1, -1, TMP2); + for (var j = 0; j < hlen && k < olen; j++) OKM[k++] = H1[j]; + } + + return OKM; + }, + + SHA256: 32, + SHA384: 48, + SHA512: 64, + + /* SHAXXX identifier strings */ + SHA256ID: [ + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, 0x04, 0x20, + ], + SHA384ID: [ + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, + 0x05, 0x00, 0x04, 0x30, + ], + SHA512ID: [ + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, + 0x05, 0x00, 0x04, 0x40, + ], + + /* Mask Generation Function */ + MGF1: function (sha, Z, olen, K) { + var hlen = sha, + B = [], + k = 0, + counter, + cthreshold, + i; + + for (i = 0; i < K.length; i++) { + K[i] = 0; + } + + cthreshold = Math.floor(olen / hlen); + if (olen % hlen !== 0) { + cthreshold++; + } + + for (counter = 0; counter < cthreshold; counter++) { + B = this.GPhashit(this.MC_SHA2, sha, 0, 0, Z, counter, null); + //B = this.hashit(sha, Z, counter); + + if (k + hlen > olen) { + for (i = 0; i < olen % hlen; i++) { + K[k++] = B[i]; + } + } else { + for (i = 0; i < hlen; i++) { + K[k++] = B[i]; + } + } + } + }, + + MGF1XOR: function (sha, Z, K) { + var hlen = sha, + B = [], + k = 0, + counter, + cthreshold, + i; + var olen = K.length; + + cthreshold = Math.floor(olen / hlen); + if (olen % hlen !== 0) { + cthreshold++; + } + + for (counter = 0; counter < cthreshold; counter++) { + B = this.GPhashit(this.MC_SHA2, sha, 0, 0, Z, counter, null); + //B = this.hashit(sha, Z, counter); + + if (k + hlen > olen) { + for (i = 0; i < olen % hlen; i++) { + K[k++] ^= B[i]; + } + } else { + for (i = 0; i < hlen; i++) { + K[k++] ^= B[i]; + } + } + } + }, + + PKCS15: function (sha, m, w, RFS) { + var olen = RFS, + hlen = sha, + idlen = 19, + H, + i, + j; + + if (olen < idlen + hlen + 10) { + return false; + } + H = this.SPhashit(this.MC_SHA2, sha, m); + //H = this.hashit(sha, m, -1); + + for (i = 0; i < w.length; i++) { + w[i] = 0; + } + + i = 0; + w[i++] = 0; + w[i++] = 1; + for (j = 0; j < olen - idlen - hlen - 3; j++) { + w[i++] = 0xff; + } + w[i++] = 0; + + if (hlen == this.SHA256) { + for (j = 0; j < idlen; j++) { + w[i++] = this.SHA256ID[j]; + } + } else if (hlen == this.SHA384) { + for (j = 0; j < idlen; j++) { + w[i++] = this.SHA384ID[j]; + } + } else if (hlen == this.SHA512) { + for (j = 0; j < idlen; j++) { + w[i++] = this.SHA512ID[j]; + } + } + + for (j = 0; j < hlen; j++) { + w[i++] = H[j]; + } + + return true; + }, + + PSS_ENCODE: function (sha, m, rng, RFS) { + var emlen = RFS; + var embits = 8 * emlen - 1; + var hlen = sha; + var SALT = []; + for (i = 0; i < hlen; i++) { + SALT[i] = rng.getByte(); + } + var mask = 0xff >> (8 * emlen - embits); + + var H = this.SPhashit(this.MC_SHA2, sha, m); + + if (emlen < hlen + hlen + 2) return null; + + var MD = []; + + for (var i = 0; i < 8; i++) MD[i] = 0; + for (var i = 0; i < hlen; i++) MD[8 + i] = H[i]; + for (var i = 0; i < hlen; i++) MD[8 + hlen + i] = SALT[i]; + + H = this.SPhashit(this.MC_SHA2, sha, MD); + + var f = []; + for (var i = 0; i < emlen - hlen - hlen - 2; i++) f[i] = 0; + f[emlen - hlen - hlen - 2] = 0x1; + for (var i = 0; i < hlen; i++) f[emlen + i - hlen - hlen - 1] = SALT[i]; + this.MGF1XOR(sha, H, f); + f[0] &= mask; + for (var i = 0; i < hlen; i++) f[emlen + i - hlen - 1] = H[i]; + f[emlen - 1] = 0xbc; + return f; + }, + + PSS_VERIFY: function (sha, m, f) { + var emlen = f.length; + var embits = 8 * emlen - 1; + var hlen = sha; + var SALT = []; + var mask = 0xff >> (8 * emlen - embits); + + var HMASK = this.SPhashit(this.MC_SHA2, sha, m); + if (emlen < hlen + hlen + 2) return false; + if (f[emlen - 1] != 0xbc) return false; + if ((f[0] & ~mask) != 0) return false; + + var DB = []; + for (var i = 0; i < emlen - hlen - 1; i++) DB[i] = f[i]; + var H = []; + for (var i = 0; i < hlen; i++) H[i] = f[emlen + i - hlen - 1]; + this.MGF1XOR(sha, H, DB); + DB[0] &= mask; + var k = 0; + for (var i = 0; i < emlen - hlen - hlen - 2; i++) k |= DB[i]; + if (k != 0) return false; + if (DB[emlen - hlen - hlen - 2] != 0x01) return false; + + for (var i = 0; i < hlen; i++) SALT[i] = DB[emlen + i - hlen - hlen - 1]; + + var MD = []; + for (var i = 0; i < 8; i++) MD[i] = 0; + for (var i = 0; i < hlen; i++) MD[8 + i] = HMASK[i]; + for (var i = 0; i < hlen; i++) MD[8 + hlen + i] = SALT[i]; + + HMASK = this.SPhashit(this.MC_SHA2, sha, MD); + + k = 0; + for (var i = 0; i < hlen; i++) k |= H[i] - HMASK[i]; + if (k != 0) return false; + return true; + }, + /* OAEP Message Encoding for Encryption */ + OAEP_ENCODE: function (sha, m, rng, p, RFS) { + var olen = RFS - 1, + mlen = m.length, + SEED = [], + DBMASK = [], + f = [], + hlen, + seedlen, + slen, + i, + d, + h; + + seedlen = hlen = sha; + + if (mlen > olen - hlen - seedlen - 1) { + return null; + } + + h = this.SPhashit(this.MC_SHA2, sha, p); + //h = this.hashit(sha, p, -1); + for (i = 0; i < hlen; i++) { + f[i] = h[i]; + } + + slen = olen - mlen - hlen - seedlen - 1; + + for (i = 0; i < slen; i++) { + f[hlen + i] = 0; + } + f[hlen + slen] = 1; + for (i = 0; i < mlen; i++) { + f[hlen + slen + 1 + i] = m[i]; + } + + for (i = 0; i < seedlen; i++) { + SEED[i] = rng.getByte(); + } + this.MGF1(sha, SEED, olen - seedlen, DBMASK); + + for (i = 0; i < olen - seedlen; i++) { + DBMASK[i] ^= f[i]; + } + this.MGF1(sha, DBMASK, seedlen, f); + + for (i = 0; i < seedlen; i++) { + f[i] ^= SEED[i]; + } + + for (i = 0; i < olen - seedlen; i++) { + f[i + seedlen] = DBMASK[i]; + } + + /* pad to length RFS */ + d = 1; + for (i = RFS - 1; i >= d; i--) { + f[i] = f[i - d]; + } + for (i = d - 1; i >= 0; i--) { + f[i] = 0; + } + + return f; + }, + + /* OAEP Message Decoding for Decryption */ + OAEP_DECODE: function (sha, p, f, RFS) { + var olen = RFS - 1, + SEED = [], + CHASH = [], + DBMASK = [], + comp, + hlen, + seedlen, + x, + t, + d, + i, + k, + h, + r; + + seedlen = hlen = sha; + if (olen < seedlen + hlen + 1) { + return null; + } + + for (i = 0; i < olen - seedlen; i++) { + DBMASK[i] = 0; + } + + if (f.length < RFS) { + d = RFS - f.length; + for (i = RFS - 1; i >= d; i--) { + f[i] = f[i - d]; + } + for (i = d - 1; i >= 0; i--) { + f[i] = 0; + } + } + h = this.SPhashit(this.MC_SHA2, sha, p); + //h = this.hashit(sha, p, -1); + for (i = 0; i < hlen; i++) { + CHASH[i] = h[i]; + } + + x = f[0]; + + for (i = seedlen; i < olen; i++) { + DBMASK[i - seedlen] = f[i + 1]; + } + + this.MGF1(sha, DBMASK, seedlen, SEED); + for (i = 0; i < seedlen; i++) { + SEED[i] ^= f[i + 1]; + } + this.MGF1(sha, SEED, olen - seedlen, f); + for (i = 0; i < olen - seedlen; i++) { + DBMASK[i] ^= f[i]; + } + + comp = true; + for (i = 0; i < hlen; i++) { + if (CHASH[i] != DBMASK[i]) { + comp = false; + } + } + + for (i = 0; i < olen - seedlen - hlen; i++) { + DBMASK[i] = DBMASK[i + hlen]; + } + + for (i = 0; i < hlen; i++) { + SEED[i] = CHASH[i] = 0; + } + + for (k = 0; ; k++) { + if (k >= olen - seedlen - hlen) { + return null; + } + + if (DBMASK[k] !== 0) { + break; + } + } + + t = DBMASK[k]; + if (!comp || x !== 0 || t != 0x01) { + for (i = 0; i < olen - seedlen; i++) { + DBMASK[i] = 0; + } + return null; + } + r = []; + + for (i = 0; i < olen - seedlen - hlen - k - 1; i++) { + r[i] = DBMASK[i + k + 1]; + } + + for (i = 0; i < olen - seedlen; i++) { + DBMASK[i] = 0; + } + + return r; + }, + }; + + return HMAC; +}; + +/* + var MSG=ctx.ECDH.asciitobytes("abc"); + var DST=ctx.ECDH.asciitobytes("P256_XMD:SHA-256_SSWU_RO_TESTGEN"); + + var OKM=ctx.HMAC.XOF_Expand(ctx.SHA3.SHAKE128,48,DST,MSG); + mywindow.document.write("OKM : 0x"+ctx.ECDH.bytestostring(OKM) + "
"); + + OKM=ctx.HMAC.XMD_Expand(ctx.HMAC.MC_SHA2,32,48,DST,MSG); + mywindow.document.write("OKM : 0x"+ctx.ECDH.bytestostring(OKM) + "
"); + + ikm=[]; + salt=[]; + info=[]; + + for (i=0;i<22;i++) ikm[i]=0x0b; + for (i=0;i<13;i++) salt[i]=i; + for (i=0;i<10;i++) info[i]=(0xf0+i); + + var prk=ctx.HMAC.HKDF_Extract(ctx.HMAC.MC_SHA2,32,salt,ikm); + window.document.write("PRK= "+ctx.NHS.bytestostring(prk)+ "
"); + + var okm=ctx.HMAC.HKDF_Expand(ctx.HMAC.MC_SHA2,32,42,prk,info); + window.document.write("PRK= "+ctx.NHS.bytestostring(okm)+ "
"); +*/ + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + HMAC: HMAC, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/hpke.js b/packages/bls-verify/src/vendor/amcl-js/src/hpke.js new file mode 100644 index 000000000..9a5927f50 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/hpke.js @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Hybrid Public Key Encryption */ + +/* Following https://datatracker.ietf.org/doc/draft-irtf-cfrg-hpke/?include_text=1 */ + +var HPKE = function (ctx) { + 'use strict'; + + var HPKE = { + reverse: function (X) { + var i, + ch, + lx = X.length; + for (i = 0; i < lx / 2; i++) { + ch = X[i]; + X[i] = X[lx - i - 1]; + X[lx - i - 1] = ch; + } + }, + + LabeledExtract: function (SALT, SUITE_ID, label, IKM) { + var rfc = 'HPKE-07'; + var RFC = ctx.ECDH.asciitobytes(rfc); + var LABEL = ctx.ECDH.asciitobytes(label); + var LIKM = []; + var k = 0; + for (var i = 0; i < RFC.length; i++) LIKM[k++] = RFC[i]; + for (var i = 0; i < SUITE_ID.length; i++) LIKM[k++] = SUITE_ID[i]; + for (var i = 0; i < LABEL.length; i++) LIKM[k++] = LABEL[i]; + if (IKM != null) { + for (var i = 0; i < IKM.length; i++) LIKM[k++] = IKM[i]; + } + return ctx.HMAC.HKDF_Extract(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, SALT, LIKM); + }, + + LabeledExpand: function (PRK, SUITE_ID, label, INFO, L) { + var AR = ctx.HMAC.inttobytes(L, 2); + var rfc = 'HPKE-07'; + var RFC = ctx.ECDH.asciitobytes(rfc); + var LABEL = ctx.ECDH.asciitobytes(label); + var LINFO = []; + LINFO[0] = AR[0]; + LINFO[1] = AR[1]; + var k = 2; + for (var i = 0; i < RFC.length; i++) LINFO[k++] = RFC[i]; + for (var i = 0; i < SUITE_ID.length; i++) LINFO[k++] = SUITE_ID[i]; + for (var i = 0; i < LABEL.length; i++) LINFO[k++] = LABEL[i]; + if (INFO != null) { + for (var i = 0; i < INFO.length; i++) LINFO[k++] = INFO[i]; + } + return ctx.HMAC.HKDF_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, PRK, LINFO); + }, + + ExtractAndExpand: function (config_id, DH, CONTEXT) { + var kem = config_id & 255; + var txt = 'KEM'; + var KEM_ID = ctx.HMAC.inttobytes(kem, 2); + var KEM = ctx.ECDH.asciitobytes(txt); + var SUITE_ID = []; + var k = KEM.length; + for (var i = 0; i < k; i++) SUITE_ID[i] = KEM[i]; + SUITE_ID[k] = KEM_ID[0]; + SUITE_ID[k + 1] = KEM_ID[1]; + var PRK = this.LabeledExtract(null, SUITE_ID, 'eae_prk', DH); + return this.LabeledExpand(PRK, SUITE_ID, 'shared_secret', CONTEXT, ctx.ECP.HASH_TYPE); + }, + + DeriveKeyPair: function (config_id, SK, PK, SEED) { + var counter = 0; + var INFO = []; + var kem = config_id & 255; + var txt = 'KEM'; + var KEM_ID = ctx.HMAC.inttobytes(kem, 2); + var KEM = ctx.ECDH.asciitobytes(txt); + var SUITE_ID = []; + var k = KEM.length; + for (var i = 0; i < k; i++) SUITE_ID[i] = KEM[i]; + SUITE_ID[k] = KEM_ID[0]; + SUITE_ID[k + 1] = KEM_ID[1]; + + var PRK = this.LabeledExtract(null, SUITE_ID, 'dkp_prk', SEED); + var S; + if (kem == 32 || kem == 33) { + S = this.LabeledExpand(PRK, SUITE_ID, 'sk', null, ctx.ECDH.EGS); + this.reverse(S); + if (kem == 32) { + S[ctx.ECDH.EGS - 1] &= 248; + S[0] &= 127; + S[0] |= 64; + } else { + S[ctx.ECDH.EGS - 1] &= 252; + S[0] |= 128; + } + } else { + var bit_mask; + if (kem == 18) bit_mask = 1; + else bit_mask = 0xff; + S = []; + for (var i = 0; i < ctx.ECDH.EGS; i++) S[i] = 0; + while (!ctx.ECDH.IN_RANGE(S) && counter < 256) { + INFO[0] = counter; + S = this.LabeledExpand(PRK, SUITE_ID, 'candidate', INFO, ctx.ECDH.EGS); + S[0] &= bit_mask; + counter++; + } + } + for (var i = 0; i < ctx.ECDH.EGS; i++) SK[i] = S[i]; + ctx.ECDH.KEY_PAIR_GENERATE(null, SK, PK); + if (kem == 32 || kem == 33) this.reverse(PK); + if (counter < 256) return true; + return false; + }, + + encap: function (config_id, skE, pkE, pkR) { + var DH = []; + var KEMCONTEXT = []; + var kem = config_id & 255; + + if (kem == 32 || kem == 33) { + this.reverse(pkR); + ctx.ECDH.ECPSVDP_DH(skE, pkR, DH, 0); + this.reverse(pkR); + this.reverse(DH); + } else { + ctx.ECDH.ECPSVDP_DH(skE, pkR, DH, 0); + } + var k = 0; + for (var i = 0; i < pkE.length; i++) KEMCONTEXT[k++] = pkE[i]; + for (var i = 0; i < pkR.length; i++) KEMCONTEXT[k++] = pkR[i]; + + return this.ExtractAndExpand(config_id, DH, KEMCONTEXT); + }, + + decap: function (config_id, skR, pkE, pkR) { + var DH = []; + var KEMCONTEXT = []; + var kem = config_id & 255; + + if (kem == 32 || kem == 33) { + this.reverse(pkE); + ctx.ECDH.ECPSVDP_DH(skR, pkE, DH, 0); + this.reverse(pkE); + this.reverse(DH); + } else { + ctx.ECDH.ECPSVDP_DH(skR, pkE, DH, 0); + } + + var k = 0; + for (var i = 0; i < pkE.length; i++) KEMCONTEXT[k++] = pkE[i]; + for (var i = 0; i < pkR.length; i++) KEMCONTEXT[k++] = pkR[i]; + + return this.ExtractAndExpand(config_id, DH, KEMCONTEXT); + }, + + authEncap: function (config_id, skE, skS, pkE, pkR, pkS) { + var pklen = pkE.length; + var DH = []; + var DH1 = []; + var KEMCONTEXT = []; + + var kem = config_id & 255; + + if (kem == 32 || kem == 33) { + this.reverse(pkR); + ctx.ECDH.ECPSVDP_DH(skE, pkR, DH, 0); + ctx.ECDH.ECPSVDP_DH(skS, pkR, DH1, 0); + this.reverse(pkR); + this.reverse(DH); + this.reverse(DH1); + } else { + ctx.ECDH.ECPSVDP_DH(skE, pkR, DH, 0); + ctx.ECDH.ECPSVDP_DH(skS, pkR, DH1, 0); + } + var ZZ = []; + for (var i = 0; i < ctx.ECDH.EFS; i++) { + ZZ[i] = DH[i]; + ZZ[ctx.ECDH.EFS + i] = DH1[i]; + } + + for (var i = 0; i < pklen; i++) { + KEMCONTEXT[i] = pkE[i]; + KEMCONTEXT[pklen + i] = pkR[i]; + KEMCONTEXT[2 * pklen + i] = pkS[i]; + } + + return this.ExtractAndExpand(config_id, ZZ, KEMCONTEXT); + }, + + authDecap: function (config_id, skR, pkE, pkR, pkS) { + var pklen = pkE.length; + var DH = []; + var DH1 = []; + var KEMCONTEXT = []; + + var kem = config_id & 255; + + if (kem == 32 || kem == 33) { + this.reverse(pkE); + this.reverse(pkS); + ctx.ECDH.ECPSVDP_DH(skR, pkE, DH, 0); + ctx.ECDH.ECPSVDP_DH(skR, pkS, DH1, 0); + this.reverse(pkE); + this.reverse(pkS); + this.reverse(DH); + this.reverse(DH1); + } else { + ctx.ECDH.ECPSVDP_DH(skR, pkE, DH, 0); + ctx.ECDH.ECPSVDP_DH(skR, pkS, DH1, 0); + } + + var ZZ = []; + for (var i = 0; i < ctx.ECDH.EFS; i++) { + ZZ[i] = DH[i]; + ZZ[ctx.ECDH.EFS + i] = DH1[i]; + } + + for (var i = 0; i < pklen; i++) { + KEMCONTEXT[i] = pkE[i]; + KEMCONTEXT[pklen + i] = pkR[i]; + KEMCONTEXT[2 * pklen + i] = pkS[i]; + } + + return this.ExtractAndExpand(config_id, ZZ, KEMCONTEXT); + }, + + keySchedule: function (config_id, key, nonce, exp_secret, mode, Z, info, psk, pskID) { + var context = []; + var kem = config_id & 255; + var kdf = (config_id >> 8) & 3; + var aead = (config_id >> 10) & 3; + var num, k; + var txt = 'HPKE'; + var KEM = ctx.ECDH.asciitobytes(txt); + var SUITE_ID = []; + k = KEM.length; + for (var i = 0; i < k; i++) SUITE_ID[i] = KEM[i]; + num = ctx.HMAC.inttobytes(kem, 2); + SUITE_ID[k++] = num[0]; + SUITE_ID[k++] = num[1]; + num = ctx.HMAC.inttobytes(kdf, 2); + SUITE_ID[k++] = num[0]; + SUITE_ID[k++] = num[1]; + num = ctx.HMAC.inttobytes(aead, 2); + SUITE_ID[k++] = num[0]; + SUITE_ID[k++] = num[1]; + k = 0; + var ar = ctx.HMAC.inttobytes(mode, 1); + for (var i = 0; i < ar.length; i++) context[k++] = ar[i]; + + var H = this.LabeledExtract(null, SUITE_ID, 'psk_id_hash', pskID); + for (var i = 0; i < ctx.ECP.HASH_TYPE; i++) context[k++] = H[i]; + H = this.LabeledExtract(null, SUITE_ID, 'info_hash', info); + for (var i = 0; i < ctx.ECP.HASH_TYPE; i++) context[k++] = H[i]; + + //H=this.LabeledExtract(null,SUITE_ID,"psk_hash",psk); + //var secret=this.LabeledExtract(H,SUITE_ID,"secret",Z); + + var secret = this.LabeledExtract(Z, SUITE_ID, 'secret', psk); + + var ex = this.LabeledExpand(secret, SUITE_ID, 'key', context, ctx.ECP.AESKEY); + for (var i = 0; i < ex.length; i++) key[i] = ex[i]; + + ex = this.LabeledExpand(secret, SUITE_ID, 'base_nonce', context, 12); + for (var i = 0; i < ex.length; i++) nonce[i] = ex[i]; + + if (exp_secret != null) { + ex = this.LabeledExpand(secret, SUITE_ID, 'exp', context, ctx.ECP.HASH_TYPE); + for (var i = 0; i < ex.length; i++) exp_secret[i] = ex[i]; + } + }, + }; + return HPKE; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + HPKE: HPKE, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/mpin.js b/packages/bls-verify/src/vendor/amcl-js/src/mpin.js new file mode 100644 index 000000000..399e3a8cd --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/mpin.js @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* MPIN 128-bit API Functions */ + +var MPIN = function (ctx) { + 'use strict'; + + var MPIN = { + BAD_PARAMS: -11, + INVALID_POINT: -14, + WRONG_ORDER: -18, + BAD_PIN: -19, + /* configure PIN here */ + MAXPIN: 10000, + /* max PIN */ + PBLEN: 14, + /* MAXPIN length in bits */ + TS: 12, + /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */ + + EFS: ctx.BIG.MODBYTES, + EGS: ctx.BIG.MODBYTES, + + SHA256: 32, + SHA384: 48, + SHA512: 64, + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + comparebytes: function (a, b) { + if (a.length != b.length) { + return false; + } + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + + return true; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + ENCODE_TO_CURVE: function (DST, ID, HCID) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var k = q.nbits(); + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var m = r.nbits(); + var L = this.ceil(k + this.ceil(m, 2), 8); + var OKM = ctx.HMAC.XMD_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, DST, ID); + var fd = []; + + for (var j = 0; j < L; j++) fd[j] = OKM[j]; + var dx = ctx.DBIG.fromBytes(fd); + var u = new ctx.FP(dx.mod(q)); + var P = ctx.ECP.map2point(u); + P.cfp(); + P.affine(); + P.toBytes(HCID, false); + }, + + /* create random secret S */ + RANDOM_GENERATE: function (rng, S) { + var r = new ctx.BIG(0), + s; + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + s = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + s.toBytes(S); + return 0; + }, + + /* Extract PIN from TOKEN for identity CID */ + EXTRACT_PIN: function (CID, pin, TOKEN) { + var P, R; + P = ctx.ECP.fromBytes(TOKEN); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + R = ctx.ECP.fromBytes(CID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + pin %= this.MAXPIN; + R = R.pinmul(pin, this.PBLEN); + P.sub(R); + P.toBytes(TOKEN, false); + return 0; + }, + + /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ + GET_SERVER_SECRET: function (S, SST) { + var s, Q; + Q = ctx.ECP2.generator(); + s = ctx.BIG.fromBytes(S); + Q = ctx.PAIR.G2mul(Q, s); + Q.toBytes(SST, false); + return 0; + }, + + /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ + GET_CLIENT_SECRET: function (S, IDHTC, CST) { + var s = ctx.BIG.fromBytes(S); + var P = ctx.ECP.fromBytes(IDHTC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + ctx.PAIR.G1mul(P, s).toBytes(CST, false); + return 0; + }, + + /* Implement step 1 on client side of MPin protocol */ + CLIENT_1: function (CID, rng, X, pin, TOKEN, SEC, xID) { + var r = new ctx.BIG(0), + x, + P, + T, + W; + + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (rng !== null) { + x = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + x.toBytes(X); + } else { + x = ctx.BIG.fromBytes(X); + } + P = ctx.ECP.fromBytes(CID); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + T = ctx.ECP.fromBytes(TOKEN); + if (T.is_infinity()) { + return this.INVALID_POINT; + } + + pin %= this.MAXPIN; + W = P.pinmul(pin, this.PBLEN); + T.add(W); + + P = ctx.PAIR.G1mul(P, x); + P.toBytes(xID, false); + + T.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 on client side of MPin protocol */ + CLIENT_2: function (X, Y, SEC) { + var r = new ctx.BIG(0), + P, + px, + py; + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + P = ctx.ECP.fromBytes(SEC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + px = ctx.BIG.fromBytes(X); + py = ctx.BIG.fromBytes(Y); + px.add(py); + px.mod(r); + + P = ctx.PAIR.G1mul(P, px); + P.neg(); + P.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 of MPin protocol on server side. */ + SERVER: function (HID, Y, SST, xID, mSEC) { + var Q, sQ, R, y, P, g; + Q = ctx.ECP2.generator(); + sQ = ctx.ECP2.fromBytes(SST); + if (sQ.is_infinity()) { + return this.INVALID_POINT; + } + if (xID == null) { + return this.BAD_PARAMS; + } + R = ctx.ECP.fromBytes(xID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + y = ctx.BIG.fromBytes(Y); + if (HID == null) { + return this.BAD_PARAMS; + } + P = ctx.ECP.fromBytes(HID); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + + P = ctx.PAIR.G1mul(P, y); + P.add(R); + R = ctx.ECP.fromBytes(mSEC); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + + g = ctx.PAIR.ate2(Q, R, sQ, P); + g = ctx.PAIR.fexp(g); + + if (!g.isunity()) { + return this.BAD_PIN; + } + return 0; + }, + }; + + return MPIN; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + MPIN: MPIN, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/mpin192.js b/packages/bls-verify/src/vendor/amcl-js/src/mpin192.js new file mode 100644 index 000000000..478bc05c8 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/mpin192.js @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* MPIN 192-bit API Functions */ + +var MPIN192 = function (ctx) { + 'use strict'; + + var MPIN192 = { + BAD_PARAMS: -11, + INVALID_POINT: -14, + WRONG_ORDER: -18, + BAD_PIN: -19, + /* configure PIN here */ + MAXPIN: 10000, + /* max PIN */ + PBLEN: 14, + /* MAXPIN length in bits */ + TS: 12, + /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */ + EFS: ctx.BIG.MODBYTES, + EGS: ctx.BIG.MODBYTES, + + SHA256: 32, + SHA384: 48, + SHA512: 64, + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + comparebytes: function (a, b) { + if (a.length != b.length) { + return false; + } + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + + return true; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + ENCODE_TO_CURVE: function (DST, ID, HCID) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var k = q.nbits(); + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var m = r.nbits(); + var L = this.ceil(k + this.ceil(m, 2), 8); + var OKM = ctx.HMAC.XMD_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, DST, ID); + var fd = []; + + for (var j = 0; j < L; j++) fd[j] = OKM[j]; + var dx = ctx.DBIG.fromBytes(fd); + var u = new ctx.FP(dx.mod(q)); + var P = ctx.ECP.map2point(u); + P.cfp(); + P.affine(); + P.toBytes(HCID, false); + }, + + /* create random secret S */ + RANDOM_GENERATE: function (rng, S) { + var r = new ctx.BIG(0), + s; + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + s = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + s.toBytes(S); + return 0; + }, + + /* Extract PIN from TOKEN for identity CID */ + EXTRACT_PIN: function (CID, pin, TOKEN) { + var P, R; + P = ctx.ECP.fromBytes(TOKEN); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + R = ctx.ECP.fromBytes(CID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + pin %= this.MAXPIN; + R = R.pinmul(pin, this.PBLEN); + P.sub(R); + P.toBytes(TOKEN, false); + return 0; + }, + + /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ + GET_SERVER_SECRET: function (S, SST) { + var s, Q; + Q = ctx.ECP4.generator(); + s = ctx.BIG.fromBytes(S); + Q = ctx.PAIR4.G2mul(Q, s); + Q.toBytes(SST, false); + return 0; + }, + + /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ + GET_CLIENT_SECRET: function (S, IDHTC, CST) { + var s = ctx.BIG.fromBytes(S); + var P = ctx.ECP.fromBytes(IDHTC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + ctx.PAIR4.G1mul(P, s).toBytes(CST, false); + return 0; + }, + + /* Implement step 1 on client side of MPin protocol */ + CLIENT_1: function (CID, rng, X, pin, TOKEN, SEC, xID) { + var r = new ctx.BIG(0), + x, + P, + T, + W; + + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (rng !== null) { + x = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + x.toBytes(X); + } else { + x = ctx.BIG.fromBytes(X); + } + P = ctx.ECP.fromBytes(CID); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + T = ctx.ECP.fromBytes(TOKEN); + if (T.is_infinity()) { + return this.INVALID_POINT; + } + + pin %= this.MAXPIN; + W = P.pinmul(pin, this.PBLEN); + T.add(W); + + P = ctx.PAIR4.G1mul(P, x); + P.toBytes(xID, false); + + T.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 on client side of MPin protocol */ + CLIENT_2: function (X, Y, SEC) { + var r = new ctx.BIG(0), + P, + px, + py; + + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + P = ctx.ECP.fromBytes(SEC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + px = ctx.BIG.fromBytes(X); + py = ctx.BIG.fromBytes(Y); + px.add(py); + px.mod(r); + + P = ctx.PAIR4.G1mul(P, px); + P.neg(); + P.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 of MPin protocol on server side. */ + SERVER: function (HID, Y, SST, xID, mSEC) { + var Q, sQ, R, y, P, g; + Q = ctx.ECP4.generator(); + sQ = ctx.ECP4.fromBytes(SST); + if (sQ.is_infinity()) { + return this.INVALID_POINT; + } + if (xID == null) { + return this.BAD_PARAMS; + } + R = ctx.ECP.fromBytes(xID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + y = ctx.BIG.fromBytes(Y); + if (HID == null) { + return this.BAD_PARAMS; + } + P = ctx.ECP.fromBytes(HID); + + if (P.is_infinity()) { + return this.INVALID_POINT; + } + + P = ctx.PAIR4.G1mul(P, y); + P.add(R); + R = ctx.ECP.fromBytes(mSEC); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + + g = ctx.PAIR4.ate2(Q, R, sQ, P); + g = ctx.PAIR4.fexp(g); + + if (!g.isunity()) { + return this.BAD_PIN; + } + return 0; + }, + }; + + return MPIN192; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + MPIN192: MPIN192, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/mpin256.js b/packages/bls-verify/src/vendor/amcl-js/src/mpin256.js new file mode 100644 index 000000000..09f3a0d81 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/mpin256.js @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* MPIN 256-bit API Functions */ + +var MPIN256 = function (ctx) { + 'use strict'; + + var MPIN256 = { + BAD_PARAMS: -11, + INVALID_POINT: -14, + WRONG_ORDER: -18, + BAD_PIN: -19, + /* configure PIN here */ + MAXPIN: 10000, + /* max PIN */ + PBLEN: 14, + /* MAXPIN length in bits */ + TS: 12, + /* 10 for 4 digit PIN, 14 for 6-digit PIN - 2^TS/TS approx = sqrt(MAXPIN) */ + + EFS: ctx.BIG.MODBYTES, + EGS: ctx.BIG.MODBYTES, + + SHA256: 32, + SHA384: 48, + SHA512: 64, + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + + asciitobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i += 2) { + b.push(parseInt(s.substr(i, 2), 16)); + } + + return b; + }, + + comparebytes: function (a, b) { + if (a.length != b.length) { + return false; + } + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + + return true; + }, + + ceil: function (a, b) { + return Math.floor((a - 1) / b + 1); + }, + + ENCODE_TO_CURVE: function (DST, ID, HCID) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_FIELD.Modulus); + var k = q.nbits(); + var r = new ctx.BIG(0); + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + var m = r.nbits(); + var L = this.ceil(k + this.ceil(m, 2), 8); + var OKM = ctx.HMAC.XMD_Expand(ctx.HMAC.MC_SHA2, ctx.ECP.HASH_TYPE, L, DST, ID); + var fd = []; + + for (var j = 0; j < L; j++) fd[j] = OKM[j]; + var dx = ctx.DBIG.fromBytes(fd); + var u = new ctx.FP(dx.mod(q)); + var P = ctx.ECP.map2point(u); + P.cfp(); + P.affine(); + P.toBytes(HCID, false); + }, + + /* create random secret S */ + RANDOM_GENERATE: function (rng, S) { + var r = new ctx.BIG(0), + s; + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + s = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + s.toBytes(S); + return 0; + }, + + /* Extract PIN from TOKEN for identity CID */ + EXTRACT_PIN: function (CID, pin, TOKEN) { + var P, R; + P = ctx.ECP.fromBytes(TOKEN); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + R = ctx.ECP.fromBytes(CID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + pin %= this.MAXPIN; + R = R.pinmul(pin, this.PBLEN); + P.sub(R); + P.toBytes(TOKEN, false); + return 0; + }, + + /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */ + GET_SERVER_SECRET: function (S, SST) { + var s, Q; + Q = ctx.ECP8.generator(); + s = ctx.BIG.fromBytes(S); + Q = ctx.PAIR8.G2mul(Q, s); + Q.toBytes(SST, false); + return 0; + }, + + /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */ + GET_CLIENT_SECRET: function (S, IDHTC, CST) { + var s = ctx.BIG.fromBytes(S); + var P = ctx.ECP.fromBytes(IDHTC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + ctx.PAIR8.G1mul(P, s).toBytes(CST, false); + return 0; + }, + + /* Implement step 1 on client side of MPin protocol */ + CLIENT_1: function (CID, rng, X, pin, TOKEN, SEC, xID) { + var r = new ctx.BIG(0), + x, + P, + T, + W; + + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (rng !== null) { + x = ctx.BIG.randtrunc(r, 16 * ctx.ECP.AESKEY, rng); + x.toBytes(X); + } else { + x = ctx.BIG.fromBytes(X); + } + P = ctx.ECP.fromBytes(CID); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + T = ctx.ECP.fromBytes(TOKEN); + if (T.is_infinity()) { + return this.INVALID_POINT; + } + + pin %= this.MAXPIN; + W = P.pinmul(pin, this.PBLEN); + T.add(W); + + P = ctx.PAIR8.G1mul(P, x); + P.toBytes(xID, false); + + T.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 on client side of MPin protocol */ + CLIENT_2: function (X, Y, SEC) { + var r = new ctx.BIG(0), + P, + px, + py; + + r.rcopy(ctx.ROM_CURVE.CURVE_Order); + + P = ctx.ECP.fromBytes(SEC); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + px = ctx.BIG.fromBytes(X); + py = ctx.BIG.fromBytes(Y); + px.add(py); + px.mod(r); + + P = ctx.PAIR8.G1mul(P, px); + P.neg(); + P.toBytes(SEC, false); + return 0; + }, + + /* Implement step 2 of MPin protocol on server side. */ + SERVER: function (HID, Y, SST, xID, mSEC) { + var Q, sQ, R, y, P, g; + Q = ctx.ECP8.generator(); + sQ = ctx.ECP8.fromBytes(SST); + if (sQ.is_infinity()) { + return this.INVALID_POINT; + } + if (xID == null) { + return this.BAD_PARAMS; + } + R = ctx.ECP.fromBytes(xID); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + y = ctx.BIG.fromBytes(Y); + if (HID == null) { + return this.BAD_PARAMS; + } + P = ctx.ECP.fromBytes(HID); + if (P.is_infinity()) { + return this.INVALID_POINT; + } + + P = ctx.PAIR8.G1mul(P, y); + P.add(R); + R = ctx.ECP.fromBytes(mSEC); + if (R.is_infinity()) { + return this.INVALID_POINT; + } + + g = ctx.PAIR8.ate2(Q, R, sQ, P); + g = ctx.PAIR8.fexp(g); + + if (!g.isunity()) { + return this.BAD_PIN; + } + return 0; + }, + }; + + return MPIN256; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + MPIN256: MPIN256, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/nhs.js b/packages/bls-verify/src/vendor/amcl-js/src/nhs.js new file mode 100644 index 000000000..bf86f040c --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/nhs.js @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* NewHope API high-level functions */ + +var NHS = function (ctx) { + 'use strict'; + + var NHS = { + round: function (a, b) { + return Math.floor((a + (b >> 1)) / b); + }, + + /* constant time absolute value */ + nabs: function (x) { + var mask = x >> 31; + return (x + mask) ^ mask; + }, + + /* Montgomery stuff */ + + redc: function (T) { + var m = ((T & 0x3ffffff) * NHS.ND) & 0x3ffffff; + return (m * NHS.PRIME + T) * NHS.MODINV; + }, + + nres: function (x) { + return NHS.redc(x * NHS.R2MODP); + }, + + modmul: function (a, b) { + return NHS.redc(a * b); + }, + + /* NTT code */ + /* Cooley-Tukey NTT */ + + ntt: function (x) { + var t = NHS.DEGREE / 2, + q = NHS.PRIME, + m, + i, + j, + k, + S, + U, + V; + + /* Convert to Montgomery form */ + for (j = 0; j < NHS.DEGREE; j++) { + x[j] = NHS.nres(x[j]); + } + + m = 1; + while (m < NHS.DEGREE) { + k = 0; + + for (i = 0; i < m; i++) { + S = NHS.roots[m + i]; + + for (j = k; j < k + t; j++) { + U = x[j]; + V = NHS.modmul(x[j + t], S); + x[j] = U + V; + x[j + t] = U + 2 * q - V; + } + + k += 2 * t; + } + + t /= 2; + m *= 2; + } + }, + + /* Gentleman-Sande INTT */ + intt: function (x) { + var q = NHS.PRIME, + t = 1, + m, + i, + j, + k, + S, + U, + V, + W; + + m = NHS.DEGREE / 2; + while (m > 1) { + k = 0; + + for (i = 0; i < m; i++) { + S = NHS.iroots[m + i]; + + for (j = k; j < k + t; j++) { + U = x[j]; + V = x[j + t]; + x[j] = U + V; + W = U + NHS.DEGREE * q - V; + x[j + t] = NHS.modmul(W, S); + } + + k += 2 * t; + } + + t *= 2; + m /= 2; + } + /* Last iteration merged with n^-1 */ + + t = NHS.DEGREE / 2; + for (j = 0; j < t; j++) { + U = x[j]; + V = x[j + t]; + W = U + NHS.DEGREE * q - V; + x[j + t] = NHS.modmul(W, NHS.invpr); + x[j] = NHS.modmul(U + V, NHS.inv); + } + + /* convert back from Montgomery to "normal" form */ + for (j = 0; j < NHS.DEGREE; j++) { + x[j] = NHS.redc(x[j]); + x[j] -= q; + x[j] += (x[j] >> (NHS.WL - 1)) & q; + } + }, + + /* See https://eprint.iacr.org/2016/1157.pdf */ + + Encode: function (key, poly) { + var i, j, b, k, kj, q2; + + q2 = NHS.PRIME / 2; + for (i = j = 0; i < 256; ) { + kj = key[j++]; + + for (k = 0; k < 8; k++) { + b = kj & 1; + poly[i] = b * q2; + poly[i + 256] = b * q2; + poly[i + 512] = b * q2; + poly[i + 768] = b * q2; + kj >>= 1; + i++; + } + } + }, + + Decode: function (poly, key) { + var q2 = NHS.PRIME / 2, + i, + j, + k, + b, + t; + + for (i = 0; i < 32; i++) { + key[i] = 0; + } + + for (i = j = 0; i < 256; ) { + for (k = 0; k < 8; k++) { + t = + NHS.nabs(poly[i] - q2) + + NHS.nabs(poly[i + 256] - q2) + + NHS.nabs(poly[i + 512] - q2) + + NHS.nabs(poly[i + 768] - q2); + + b = t - NHS.PRIME; + b = (b >> 31) & 1; + key[j] = ((key[j] & 0xff) >> 1) + (b << 7); + i++; + } + + j++; + } + }, + + /* convert 32-byte seed to random polynomial */ + + Parse: function (seed, poly) { + var sh = new ctx.SHA3(ctx.SHA3.SHAKE128), + hash = [], + i, + j, + n; + + for (i = 0; i < 32; i++) { + sh.process(seed[i]); + } + sh.shake(hash, 4 * NHS.DEGREE); + + for (i = j = 0; i < NHS.DEGREE; i++) { + n = hash[j] & 0x7f; + n <<= 8; + n += hash[j + 1] & 0xff; + n <<= 8; + n += hash[j + 2] & 0xff; + n <<= 8; + n += hash[j + 3] & 0xff; + j += 4; + poly[i] = NHS.nres(n); + //poly[i] = NHS.modmul(n, NHS.ONE); // reduce 31-bit random number mod q + } + }, + + /* Compress 14 bits polynomial coefficients into byte array */ + /* 7 bytes is 3x14 */ + pack: function (poly, array) { + var i, j, a, b, c, d; + + for (i = j = 0; i < NHS.DEGREE; ) { + a = poly[i++]; + b = poly[i++]; + c = poly[i++]; + d = poly[i++]; + array[j++] = a & 0xff; + array[j++] = ((a >> 8) | (b << 6)) & 0xff; + array[j++] = (b >> 2) & 0xff; + array[j++] = ((b >> 10) | (c << 4)) & 0xff; + array[j++] = (c >> 4) & 0xff; + array[j++] = ((c >> 12) | (d << 2)) & 0xff; + array[j++] = d >> 6; + } + }, + + unpack: function (array, poly) { + var i, j, a, b, c, d, e, f, g; + + for (i = j = 0; i < NHS.DEGREE; ) { + a = array[j++] & 0xff; + b = array[j++] & 0xff; + c = array[j++] & 0xff; + d = array[j++] & 0xff; + e = array[j++] & 0xff; + f = array[j++] & 0xff; + g = array[j++] & 0xff; + poly[i++] = a | ((b & 0x3f) << 8); + poly[i++] = (b >> 6) | (c << 2) | ((d & 0xf) << 10); + poly[i++] = (d >> 4) | (e << 4) | ((f & 3) << 12); + poly[i++] = (f >> 2) | (g << 6); + } + }, + + /* See https://eprint.iacr.org/2016/1157.pdf */ + + Compress: function (poly, array) { + var col = 0, + i, + j, + k, + b; + + for (i = j = 0; i < NHS.DEGREE; ) { + for (k = 0; k < 8; k++) { + b = NHS.round(poly[i] * 8, NHS.PRIME) & 7; + col = (col << 3) + b; + i++; + } + + array[j] = col & 0xff; + array[j + 1] = (col >>> 8) & 0xff; + array[j + 2] = (col >>> 16) & 0xff; + j += 3; + col = 0; + } + }, + + Decompress: function (array, poly) { + var col = 0, + i, + j, + k, + b; + + for (i = j = 0; i < NHS.DEGREE; ) { + col = array[j + 2] & 0xff; + col = (col << 8) + (array[j + 1] & 0xff); + col = (col << 8) + (array[j] & 0xff); + j += 3; + + for (k = 0; k < 8; k++) { + b = (col & 0xe00000) >>> 21; + col <<= 3; + poly[i] = NHS.round(b * NHS.PRIME, 8); + i++; + } + } + }, + + /* generate centered binomial distribution */ + + Error: function (RNG, poly) { + var n1, n2, r, i, j; + + for (i = 0; i < NHS.DEGREE; i++) { + n1 = RNG.getByte() + (RNG.getByte() << 8); + n2 = RNG.getByte() + (RNG.getByte() << 8); + r = 0; + + for (j = 0; j < 16; j++) { + r += (n1 & 1) - (n2 & 1); + n1 >>= 1; + n2 >>= 1; + } + + poly[i] = r + NHS.PRIME; + } + }, + + redc_it: function (p) { + var i; + for (i = 0; i < NHS.DEGREE; i++) { + p[i] = NHS.redc(p[i]); + } + }, + + nres_it: function (p) { + var i; + for (i = 0; i < NHS.DEGREE; i++) { + p[i] = NHS.nres(p[i]); + } + }, + + poly_mul: function (p1, p2, p3) { + var i; + + for (i = 0; i < NHS.DEGREE; i++) { + p1[i] = NHS.modmul(p2[i], p3[i]); + } + }, + + poly_add: function (p1, p2, p3) { + var i; + + for (i = 0; i < NHS.DEGREE; i++) { + p1[i] = p2[i] + p3[i]; + } + }, + + poly_sub: function (p1, p2, p3) { + var i; + + for (i = 0; i < NHS.DEGREE; i++) { + p1[i] = p2[i] + NHS.PRIME - p3[i]; + } + }, + + /* reduces inputs < 2q */ + poly_soft_reduce: function (poly) { + var i, e; + + for (i = 0; i < NHS.DEGREE; i++) { + e = poly[i] - NHS.PRIME; + poly[i] = e + ((e >> (NHS.WL - 1)) & NHS.PRIME); + } + }, + + /* fully reduces modulo q */ + poly_hard_reduce: function (poly) { + var i, e; + + for (i = 0; i < NHS.DEGREE; i++) { + e = NHS.modmul(poly[i], NHS.ONE); + e = e - NHS.PRIME; + poly[i] = e + ((e >> (NHS.WL - 1)) & NHS.PRIME); + } + }, + + bytestostring: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + + return s; + }, + /* API files */ + + SERVER_1: function (RNG, SB, S) { + var seed = new Uint8Array(32), + array = new Uint8Array(1792), + s = new Int32Array(NHS.DEGREE), + e = new Int32Array(NHS.DEGREE), + b = new Int32Array(NHS.DEGREE), + i; + + for (i = 0; i < 32; i++) { + seed[i] = RNG.getByte(); + } + + NHS.Parse(seed, b); + + NHS.Error(RNG, e); + NHS.Error(RNG, s); + + NHS.ntt(s); + NHS.ntt(e); + NHS.poly_mul(b, b, s); + NHS.poly_add(b, b, e); + NHS.poly_hard_reduce(b); + + NHS.redc_it(b); + NHS.pack(b, array); + + for (i = 0; i < 32; i++) { + SB[i] = seed[i]; + } + + for (i = 0; i < 1792; i++) { + SB[i + 32] = array[i]; + } + + NHS.poly_hard_reduce(s); + + NHS.pack(s, array); + + for (i = 0; i < 1792; i++) { + S[i] = array[i]; + } + }, + + CLIENT: function (RNG, SB, UC, KEY) { + var sh = new ctx.SHA3(ctx.SHA3.HASH256), + seed = new Uint8Array(32), + array = new Uint8Array(1792), + key = new Uint8Array(32), + cc = new Uint8Array(384), + sd = new Int32Array(NHS.DEGREE), + ed = new Int32Array(NHS.DEGREE), + u = new Int32Array(NHS.DEGREE), + k = new Int32Array(NHS.DEGREE), + c = new Int32Array(NHS.DEGREE), + i; + + NHS.Error(RNG, sd); + NHS.Error(RNG, ed); + + NHS.ntt(sd); + NHS.ntt(ed); + + for (i = 0; i < 32; i++) { + seed[i] = SB[i]; + } + + for (i = 0; i < 1792; i++) { + array[i] = SB[i + 32]; + } + + NHS.Parse(seed, u); + + NHS.poly_mul(u, u, sd); + NHS.poly_add(u, u, ed); + NHS.poly_hard_reduce(u); + + for (i = 0; i < 32; i++) { + key[i] = RNG.getByte(); + } + + for (i = 0; i < 32; i++) { + sh.process(key[i]); + } + + key = sh.hash(); + + NHS.Encode(key, k); + + NHS.unpack(array, c); + NHS.nres_it(c); + + NHS.poly_mul(c, c, sd); + NHS.intt(c); + NHS.Error(RNG, ed); + NHS.poly_add(c, c, ed); + NHS.poly_add(c, c, k); + + NHS.Compress(c, cc); + + sh.init(ctx.SHA3.HASH256); + for (i = 0; i < 32; i++) { + sh.process(key[i]); + } + key = sh.hash(); + + for (i = 0; i < 32; i++) { + KEY[i] = key[i]; + } + + NHS.redc_it(u); + NHS.pack(u, array); + + for (i = 0; i < 1792; i++) { + UC[i] = array[i]; + } + + for (i = 0; i < 384; i++) { + UC[i + 1792] = cc[i]; + } + }, + + SERVER_2: function (S, UC, KEY) { + var sh = new ctx.SHA3(ctx.SHA3.HASH256), + c = new Int32Array(NHS.DEGREE), + s = new Int32Array(NHS.DEGREE), + k = new Int32Array(NHS.DEGREE), + array = new Uint8Array(1792), + key = new Uint8Array(32), + cc = new Uint8Array(384), + i; + + for (i = 0; i < 1792; i++) { + array[i] = UC[i]; + } + + NHS.unpack(array, k); + NHS.nres_it(k); + + for (i = 0; i < 384; i++) { + cc[i] = UC[i + 1792]; + } + + NHS.Decompress(cc, c); + + for (i = 0; i < 1792; i++) { + array[i] = S[i]; + } + + NHS.unpack(array, s); + + NHS.poly_mul(k, k, s); + NHS.intt(k); + NHS.poly_sub(k, c, k); + NHS.poly_soft_reduce(k); + + NHS.Decode(k, key); + + for (i = 0; i < 32; i++) { + sh.process(key[i]); + } + key = sh.hash(); + + for (i = 0; i < 32; i++) { + KEY[i] = key[i]; + } + }, + }; + + //q=12289 + NHS.PRIME = 0x3001; // q in Hex + NHS.LGN = 10; // Degree n=2^LGN + NHS.ND = 0x3002fff; // 1/(R-q) mod R + NHS.ONE = 0x2aac; // R mod q + NHS.R2MODP = 0x1da2; // R^2 mod q + + NHS.MODINV = Math.pow(2, -26); + + NHS.DEGREE = 1024; // 1<< LGN + NHS.WL = 26; + + NHS.inv = 0xffb; + NHS.invpr = 0x1131; + + NHS.roots = [ + 0x2aac, 0xd6f, 0x1c67, 0x2c5b, 0x2dbd, 0x2697, 0x29f6, 0x8d3, 0x1b7c, 0x9eb, 0x20eb, 0x264a, + 0x27d0, 0x121b, 0x58c, 0x4d7, 0x17a2, 0x29eb, 0x1b72, 0x13b0, 0x19b1, 0x1581, 0x2ac9, 0x25e8, + 0x249d, 0x2d5e, 0x363, 0x1f74, 0x1f8f, 0x20a4, 0x2cb2, 0x2d04, 0x1407, 0x2df9, 0x3ad, 0x23f7, + 0x1a72, 0xa91, 0x37f, 0xdb3, 0x2315, 0x5e6, 0xa8f, 0x211d, 0xdad, 0x1f2b, 0x2e29, 0x26b0, + 0x2009, 0x2fdd, 0x2881, 0x399, 0x586, 0x2781, 0x2ab5, 0x971, 0x234b, 0x1df3, 0x1d2a, 0x15dd, + 0x1a6d, 0x2774, 0x7ff, 0x1ebe, 0x230, 0x1cf4, 0x180b, 0xb58, 0x198c, 0x2b40, 0x127b, 0x1d9d, + 0x137f, 0xfa0, 0x144, 0x4b, 0x2fac, 0xb09, 0x1c7f, 0x1b5, 0xeec, 0xc58, 0x1248, 0x243c, 0x108a, + 0x14b8, 0xe9, 0x2dfe, 0xfb, 0x2602, 0x2aec, 0x1bb7, 0x1098, 0x23d8, 0x783, 0x1b13, 0x2067, + 0x20d6, 0x171c, 0x4, 0x662, 0x1097, 0x24b9, 0x1b9d, 0x27c4, 0x276e, 0x6bf, 0x757, 0x2e16, 0x472, + 0x1d11, 0x1649, 0x2904, 0xed4, 0x6c5, 0x14ae, 0x2ef8, 0x2ae0, 0x2e7c, 0x2735, 0x1186, 0x4f2, + 0x17bb, 0x297f, 0x1dc7, 0x1ae5, 0x2a43, 0x2c02, 0xed6, 0x2b70, 0x1c7b, 0x18d1, 0x20ae, 0x6ad, + 0x2404, 0x113a, 0x209e, 0x31b, 0x159d, 0x48f, 0xe09, 0x1bb2, 0x14f7, 0x385, 0x1c4, 0x1cdb, + 0x22d6, 0x21d8, 0xc, 0x1aae, 0x2ece, 0x2d81, 0xd56, 0x5c1, 0x12da, 0x8cf, 0x1605, 0x1bc4, + 0x18b7, 0x19b9, 0x21be, 0x135e, 0x28d6, 0x2891, 0x2208, 0x17e1, 0x2971, 0x926, 0x211b, 0xff, + 0x51f, 0xa85, 0xe1, 0x2c35, 0x2585, 0x121, 0xe27, 0x2e64, 0x29f8, 0x2d46, 0xcb2, 0x292a, 0x33d, + 0xaf9, 0xb86, 0x2e3a, 0x2138, 0x1978, 0x2324, 0xf3f, 0x2d10, 0x1dfd, 0x13c3, 0x6cc, 0x1a79, + 0x1221, 0x250f, 0xacd, 0xfff, 0x7b4, 0x650, 0x1893, 0xe85, 0x1f5d, 0x12dc, 0x2d42, 0xd8e, + 0x1240, 0x1082, 0x12ef, 0x11b6, 0xfa8, 0xb0f, 0xdac, 0x191c, 0x1242, 0x1ea, 0x155, 0x270a, + 0x9ed, 0x2e5b, 0x25d8, 0x222c, 0x7e9, 0x1fb3, 0x10ac, 0x2919, 0x2584, 0xbe3, 0x24fa, 0x23ed, + 0x618, 0x2d80, 0x6fa, 0x140e, 0x588, 0x355, 0x1054, 0x26c4, 0x1e4f, 0x1681, 0x1f6f, 0x1c53, + 0xfe4, 0xacb, 0x1680, 0x2fe8, 0x6c, 0x165a, 0x10bb, 0x2c39, 0x1804, 0x1196, 0x884, 0x2622, + 0x629, 0x1ac1, 0x2232, 0x2f9b, 0xd3e, 0x20ff, 0x12c0, 0x27ec, 0x5a, 0x2a0, 0x5f1, 0x1cda, 0x403, + 0x1ea8, 0x1719, 0x1fc7, 0x2d23, 0x5ea, 0x25d1, 0xb6, 0x49c, 0xac7, 0x2d9c, 0x204e, 0x2142, + 0x11e8, 0xed0, 0x15f0, 0x514, 0xa3f, 0xf43, 0x1de5, 0x2d97, 0x1543, 0x2c7b, 0x241a, 0x2223, + 0x2fb8, 0x25b7, 0x1b4c, 0x2f36, 0x26e2, 0x100, 0x2555, 0x266c, 0x2e10, 0x271c, 0x5aa, 0x1789, + 0x2199, 0x291d, 0x1088, 0x2046, 0x1ea1, 0xf89, 0x1c7a, 0x1e98, 0x137, 0x1b65, 0x24ed, 0xf37, + 0x2ec3, 0xd0c, 0x7c7, 0x123f, 0xb2e, 0x1a97, 0x1a03, 0x1bcd, 0x3b2, 0x714, 0x2979, 0xaef, + 0x2b3c, 0x2d91, 0xe03, 0xe5b, 0x1fbc, 0xcae, 0x432, 0x23a4, 0xb1d, 0x1ccc, 0x1fb6, 0x2f58, + 0x2a5a, 0x723, 0x2c99, 0x2d70, 0xa, 0x263c, 0x2701, 0xdeb, 0x2d08, 0x1c34, 0x200c, 0x1e88, + 0x396, 0x18d5, 0x1c45, 0xc4, 0x18bc, 0x2cd7, 0x1744, 0x8f1, 0x1c5c, 0xbe6, 0x2a89, 0x17a0, + 0x207, 0x19ce, 0x2024, 0x23e3, 0x299b, 0x685, 0x2baf, 0x539, 0x2d49, 0x24b5, 0x158d, 0xfd, + 0x2a95, 0x24d, 0xab3, 0x1125, 0x12f9, 0x15ba, 0x6a8, 0x2c36, 0x6e7, 0x1044, 0x36e, 0xfe8, + 0x112d, 0x2717, 0x24a0, 0x1c09, 0xe1d, 0x828, 0x2f7, 0x1f5b, 0xfab, 0xcf6, 0x1332, 0x1c72, + 0x2683, 0x15ce, 0x1ad3, 0x1a36, 0x24c, 0xb33, 0x253f, 0x1583, 0x1d69, 0x29ec, 0xba7, 0x2f97, + 0x16df, 0x1068, 0xaee, 0xc4f, 0x153c, 0x24eb, 0x20cd, 0x1398, 0x2366, 0x11f9, 0xe77, 0x103d, + 0x260a, 0xce, 0xaea, 0x236b, 0x2b11, 0x5f8, 0xe4f, 0x750, 0x1569, 0x10f5, 0x284e, 0xa38, 0x2e06, + 0xe0, 0xeaa, 0x99e, 0x249b, 0x8eb, 0x2b97, 0x2fdf, 0x29c1, 0x1b00, 0x2fe3, 0x1d4f, 0x83f, + 0x2d06, 0x10e, 0x183f, 0x27ba, 0x132, 0xfbf, 0x296d, 0x154a, 0x40a, 0x2767, 0xad, 0xc09, 0x974, + 0x2821, 0x1e2e, 0x28d2, 0xfac, 0x3c4, 0x2f19, 0xdd4, 0x2ddf, 0x1e43, 0x1e90, 0x2dc9, 0x1144, + 0x28c3, 0x653, 0xf3c, 0x1e32, 0x2a4a, 0x391, 0x1123, 0xdb, 0x2da0, 0xe1e, 0x667, 0x23b5, 0x2039, + 0xa92, 0x1552, 0x5d3, 0x169a, 0x1f03, 0x1342, 0x2004, 0x1b5d, 0x2d01, 0x2e9b, 0x41f, 0x2bc7, + 0xa94, 0xd0, 0x2e6a, 0x2b38, 0x14ac, 0x2724, 0x3ba, 0x6bc, 0x18ac, 0x2da5, 0x213c, 0x2c5c, + 0xdd3, 0xaae, 0x2e08, 0x6cd, 0x1677, 0x2025, 0x1e1c, 0x5b4, 0xdc4, 0x60, 0x156c, 0x2669, 0x1c01, + 0x26ab, 0x1ebb, 0x26d4, 0x21e1, 0x156b, 0x567, 0x1a, 0x29ce, 0x23d4, 0x684, 0xb79, 0x1953, + 0x1046, 0x1d8c, 0x17b5, 0x1c28, 0x1ce5, 0x2478, 0x18d8, 0x1b16, 0x2c2f, 0x21c9, 0x19bb, 0xbbc, + 0x291b, 0x19f6, 0x1879, 0x2fe4, 0x58e, 0x294a, 0x19e8, 0x27c7, 0x2fba, 0x1a29, 0x2319, 0x1ecb, + 0x203b, 0x2f05, 0x2b82, 0x192f, 0x26aa, 0x2482, 0xaed, 0x1216, 0x708, 0x11a1, 0xc22, 0x908, + 0x28f8, 0x2427, 0x7f8, 0x172e, 0xf50, 0xaa8, 0x184a, 0x1f67, 0x22d1, 0xeba, 0x215b, 0xf47, + 0x2877, 0xd5e, 0x8dc, 0x20d, 0x2dae, 0x1d3e, 0x775, 0xbf3, 0x872, 0x2667, 0x1ff6, 0xd9f, 0x13c4, + 0x105, 0x65f, 0x21ec, 0x6dd, 0x1a09, 0xc6e, 0x1fd, 0x1426, 0xae3, 0x494, 0x2d82, 0x22cd, 0x25d6, + 0x11c1, 0x1c, 0x2cae, 0x141f, 0x110a, 0x147, 0x2657, 0x23fd, 0x2f39, 0x360, 0x2294, 0x1f1e, + 0xb73, 0xbfc, 0x2f17, 0x7ca, 0x2f63, 0xbf, 0x28c2, 0xc1a, 0x255e, 0x226e, 0x1aa8, 0x229e, + 0x161a, 0x273, 0x106d, 0x2c40, 0x7cf, 0x1408, 0x7d8, 0x100a, 0x759, 0x1db4, 0x24be, 0x2ebb, + 0xc17, 0x1894, 0x244e, 0x15bd, 0x748, 0x1fe9, 0x23d, 0x1da, 0x2be, 0x18a3, 0xc5c, 0x9f9, 0x3d5, + 0x2ce4, 0x54, 0x2abf, 0x279c, 0x1e81, 0x2d59, 0x2847, 0x23f4, 0xda8, 0xa20, 0x258, 0x1cfe, + 0x240c, 0x2c2e, 0x2790, 0x2dd5, 0x2bf2, 0x2e34, 0x1724, 0x211, 0x1009, 0x27b9, 0x6f9, 0x23d9, + 0x19a2, 0x627, 0x156d, 0x169e, 0x7e7, 0x30f, 0x24b6, 0x5c2, 0x1ce4, 0x28dd, 0x20, 0x16ab, + 0x1cce, 0x20a9, 0x2390, 0x2884, 0x2245, 0x5f7, 0xab7, 0x1b6a, 0x11e7, 0x2a53, 0x2f94, 0x294c, + 0x1ee5, 0x1364, 0x1b9a, 0xff7, 0x5eb, 0x2c30, 0x1c02, 0x5a1, 0x1b87, 0x2402, 0x1cc8, 0x2ee1, + 0x1fbe, 0x138c, 0x2487, 0x1bf8, 0xd96, 0x1d68, 0x2fb3, 0x1fc1, 0x1fcc, 0xd66, 0x953, 0x2141, + 0x157a, 0x2477, 0x18e3, 0x2f30, 0x75e, 0x1de1, 0x14b2, 0x2faa, 0x1697, 0x2334, 0x12d1, 0xb76, + 0x2aa8, 0x1e7a, 0xd5, 0x2c60, 0x26b8, 0x1753, 0x124a, 0x1f57, 0x1425, 0xd84, 0x1c05, 0x641, + 0xf3a, 0x1b8c, 0xd7d, 0x2f52, 0x2f4, 0xc73, 0x151b, 0x1589, 0x1819, 0x1b18, 0xb9b, 0x1ae9, + 0x2b1f, 0x2b44, 0x2f5a, 0x2d37, 0x2cb1, 0x26f5, 0x233e, 0x276f, 0x276, 0x1260, 0x2997, 0x9f2, + 0x1c15, 0x1694, 0x11ac, 0x1e6d, 0x1bef, 0x2966, 0x18b2, 0x4fa, 0x2044, 0x1b70, 0x1f3e, 0x221e, + 0x28ca, 0x1d56, 0x7ae, 0x98d, 0x238c, 0x17b8, 0xad3, 0x113f, 0x1f1b, 0x4d2, 0x1757, 0xcb1, + 0x2ef1, 0x2e02, 0x17fc, 0x2f11, 0x2a74, 0x2029, 0x700, 0x154e, 0x1cef, 0x226a, 0x21bf, 0x27a6, + 0x14bc, 0x2b2b, 0x2fc6, 0x13b6, 0x21e6, 0x1663, 0xcbd, 0x752, 0x1624, 0x881, 0x2fc0, 0x1276, + 0xa7f, 0x274f, 0x2b53, 0x670, 0x1fb7, 0x1e41, 0x2a1e, 0x2612, 0x297, 0x19de, 0x18b, 0x249, + 0x1c88, 0xe9e, 0x1ef1, 0x213, 0x47b, 0x1e20, 0x28c1, 0x1d5e, 0x977, 0x1dca, 0x990, 0x1df6, + 0x2b62, 0x870, 0x1f4, 0x1829, 0x1e0a, 0x46, 0x1b9f, 0x2102, 0x16b, 0x1b32, 0x568, 0x2050, + 0x15b4, 0x191a, 0x1dd0, 0x5df, 0x55c, 0x1d21, 0x19db, 0x12d9, 0xe96, 0x680, 0x2349, 0x9b9, + 0x155d, 0xe31, 0x249f, 0x20f8, 0xb30, 0x337, 0x2da3, 0x11c3, 0x248f, 0x1cf9, 0x10ee, 0x6d8, + 0x6eb, 0xa0d, 0x101b, 0x1ae4, 0x1801, 0x24cd, 0x813, 0x2e98, 0x1574, 0x50, 0x11da, 0x1802, + 0xf56, 0x1839, 0x219c, 0x105b, 0x43b, 0x2c9, 0x917, 0x14c1, 0x1b79, 0xdab, 0x2ab9, 0x265c, + 0x71a, 0x1d90, 0x89f, 0x2bc2, 0x2777, 0x1014, 0x1e64, 0x14b4, 0x692, 0xddb, 0x56e, 0x2190, + 0x2d1b, 0x1016, 0x12d6, 0x1c81, 0x2628, 0x4a1, 0x1268, 0x2597, 0x2926, 0x7c5, 0x1dcd, 0x53f, + 0x11a9, 0x1a41, 0x5a2, 0x1c65, 0x7e8, 0xd71, 0x29c8, 0x427, 0x32f, 0x5dc, 0x16b1, 0x2a1d, + 0x1787, 0x2224, 0x620, 0x6a4, 0x1351, 0x1038, 0xe6c, 0x111b, 0x2f13, 0x441, 0x2cfd, 0x2f2f, + 0xd25, 0x9b8, 0x1b24, 0x762, 0x19b6, 0x2611, 0x85e, 0xe37, 0x1f5, 0x503, 0x1c46, 0x23cc, 0x4bb, + 0x243e, 0x122b, 0x28e2, 0x133e, 0x2db9, 0xdb2, 0x1a5c, 0x29a9, 0xca, 0x2113, 0x13d1, 0x15ec, + 0x2079, 0x18da, 0x2d50, 0x2c45, 0xaa2, 0x135a, 0x800, 0x18f7, 0x17f3, 0x5fd, 0x1f5a, 0x2d0, + 0x2cd1, 0x9ee, 0x218b, 0x19fd, 0x53b, 0x28c5, 0xe33, 0x1911, 0x26cc, 0x2018, 0x2f88, 0x1b01, + 0x2637, 0x1cd9, 0x126b, 0x1a0b, 0x5b0, 0x24e0, 0xe82, 0xb1, 0x21f7, 0x1a16, 0x2f24, 0x1cb1, + 0x1f7d, 0x28a0, 0x167e, 0xc3, + ]; + NHS.iroots = [ + 0x2aac, 0x2292, 0x3a6, 0x139a, 0x272e, 0x60b, 0x96a, 0x244, 0x2b2a, 0x2a75, 0x1de6, 0x831, + 0x9b7, 0xf16, 0x2616, 0x1485, 0x2fd, 0x34f, 0xf5d, 0x1072, 0x108d, 0x2c9e, 0x2a3, 0xb64, 0xa19, + 0x538, 0x1a80, 0x1650, 0x1c51, 0x148f, 0x616, 0x185f, 0x1143, 0x2802, 0x88d, 0x1594, 0x1a24, + 0x12d7, 0x120e, 0xcb6, 0x2690, 0x54c, 0x880, 0x2a7b, 0x2c68, 0x780, 0x24, 0xff8, 0x951, 0x1d8, + 0x10d6, 0x2254, 0xee4, 0x2572, 0x2a1b, 0xcec, 0x224e, 0x2c82, 0x2570, 0x158f, 0xc0a, 0x2c54, + 0x208, 0x1bfa, 0x3ff, 0x5be, 0x151c, 0x123a, 0x682, 0x1846, 0x2b0f, 0x1e7b, 0x8cc, 0x185, 0x521, + 0x109, 0x1b53, 0x293c, 0x212d, 0x6fd, 0x19b8, 0x12f0, 0x2b8f, 0x1eb, 0x28aa, 0x2942, 0x893, + 0x83d, 0x1464, 0xb48, 0x1f6a, 0x299f, 0x2ffd, 0x18e5, 0xf2b, 0xf9a, 0x14ee, 0x287e, 0xc29, + 0x1f69, 0x144a, 0x515, 0x9ff, 0x2f06, 0x203, 0x2f18, 0x1b49, 0x1f77, 0xbc5, 0x1db9, 0x23a9, + 0x2115, 0x2e4c, 0x1382, 0x24f8, 0x55, 0x2fb6, 0x2ebd, 0x2061, 0x1c82, 0x1264, 0x1d86, 0x4c1, + 0x1675, 0x24a9, 0x17f6, 0x130d, 0x2dd1, 0x29d8, 0x9df, 0x277d, 0x1e6b, 0x17fd, 0x3c8, 0x1f46, + 0x19a7, 0x2f95, 0x19, 0x1981, 0x2536, 0x201d, 0x13ae, 0x1092, 0x1980, 0x11b2, 0x93d, 0x1fad, + 0x2cac, 0x2a79, 0x1bf3, 0x2907, 0x281, 0x29e9, 0xc14, 0xb07, 0x241e, 0xa7d, 0x6e8, 0x1f55, + 0x104e, 0x2818, 0xdd5, 0xa29, 0x1a6, 0x2614, 0x8f7, 0x2eac, 0x2e17, 0x1dbf, 0x16e5, 0x2255, + 0x24f2, 0x2059, 0x1e4b, 0x1d12, 0x1f7f, 0x1dc1, 0x2273, 0x2bf, 0x1d25, 0x10a4, 0x217c, 0x176e, + 0x29b1, 0x284d, 0x2002, 0x2534, 0xaf2, 0x1de0, 0x1588, 0x2935, 0x1c3e, 0x1204, 0x2f1, 0x20c2, + 0xcdd, 0x1689, 0xec9, 0x1c7, 0x247b, 0x2508, 0x2cc4, 0x6d7, 0x234f, 0x2bb, 0x609, 0x19d, 0x21da, + 0x2ee0, 0xa7c, 0x3cc, 0x2f20, 0x257c, 0x2ae2, 0x2f02, 0xee6, 0x26db, 0x690, 0x1820, 0xdf9, + 0x770, 0x72b, 0x1ca3, 0xe43, 0x1648, 0x174a, 0x143d, 0x19fc, 0x2732, 0x1d27, 0x2a40, 0x22ab, + 0x280, 0x133, 0x1553, 0x2ff5, 0xe29, 0xd2b, 0x1326, 0x2e3d, 0x2c7c, 0x1b0a, 0x144f, 0x21f8, + 0x2b72, 0x1a64, 0x2ce6, 0xf63, 0x1ec7, 0xbfd, 0x2954, 0xf53, 0x1730, 0x1386, 0x491, 0x212b, + 0x222e, 0x3a5, 0xec5, 0x25c, 0x1755, 0x2945, 0x2c47, 0x8dd, 0x1b55, 0x4c9, 0x197, 0x2f31, + 0x256d, 0x43a, 0x2be2, 0x166, 0x300, 0x14a4, 0xffd, 0x1cbf, 0x10fe, 0x1967, 0x2a2e, 0x1aaf, + 0x256f, 0xfc8, 0xc4c, 0x299a, 0x21e3, 0x261, 0x2f26, 0x1ede, 0x2c70, 0x5b7, 0x11cf, 0x20c5, + 0x29ae, 0x73e, 0x1ebd, 0x238, 0x1171, 0x11be, 0x222, 0x222d, 0xe8, 0x2c3d, 0x2055, 0x72f, + 0x11d3, 0x7e0, 0x268d, 0x23f8, 0x2f54, 0x89a, 0x2bf7, 0x1ab7, 0x694, 0x2042, 0x2ecf, 0x847, + 0x17c2, 0x2ef3, 0x2fb, 0x27c2, 0x12b2, 0x1e, 0x1501, 0x640, 0x22, 0x46a, 0x2716, 0xb66, 0x2663, + 0x2157, 0x2f21, 0x1fb, 0x25c9, 0x7b3, 0x1f0c, 0x1a98, 0x28b1, 0x21b2, 0x2a09, 0x4f0, 0xc96, + 0x2517, 0x2f33, 0x9f7, 0x1fc4, 0x218a, 0x1e08, 0xc9b, 0x1c69, 0xf34, 0xb16, 0x1ac5, 0x23b2, + 0x2513, 0x1f99, 0x1922, 0x6a, 0x245a, 0x615, 0x1298, 0x1a7e, 0xac2, 0x24ce, 0x2db5, 0x15cb, + 0x152e, 0x1a33, 0x97e, 0x138f, 0x1ccf, 0x230b, 0x2056, 0x10a6, 0x2d0a, 0x27d9, 0x21e4, 0x13f8, + 0xb61, 0x8ea, 0x1ed4, 0x2019, 0x2c93, 0x1fbd, 0x291a, 0x3cb, 0x2959, 0x1a47, 0x1d08, 0x1edc, + 0x254e, 0x2db4, 0x56c, 0x2f04, 0x1a74, 0xb4c, 0x2b8, 0x2ac8, 0x452, 0x297c, 0x666, 0xc1e, 0xfdd, + 0x1633, 0x2dfa, 0x1861, 0x578, 0x241b, 0x13a5, 0x2710, 0x18bd, 0x32a, 0x1745, 0x2f3d, 0x13bc, + 0x172c, 0x2c6b, 0x1179, 0xff5, 0x13cd, 0x2f9, 0x2216, 0x900, 0x9c5, 0x2ff7, 0x291, 0x368, + 0x28de, 0x5a7, 0xa9, 0x104b, 0x1335, 0x24e4, 0xc5d, 0x2bcf, 0x2353, 0x1045, 0x21a6, 0x21fe, + 0x270, 0x4c5, 0x2512, 0x688, 0x28ed, 0x2c4f, 0x1434, 0x15fe, 0x156a, 0x24d3, 0x1dc2, 0x283a, + 0x22f5, 0x13e, 0x20ca, 0xb14, 0x149c, 0x2eca, 0x1169, 0x1387, 0x2078, 0x1160, 0xfbb, 0x1f79, + 0x6e4, 0xe68, 0x1878, 0x2a57, 0x8e5, 0x1f1, 0x995, 0xaac, 0x2f01, 0x91f, 0xcb, 0x14b5, 0xa4a, + 0x49, 0xdde, 0xbe7, 0x386, 0x1abe, 0x26a, 0x121c, 0x20be, 0x25c2, 0x2aed, 0x1a11, 0x2131, + 0x1e19, 0xebf, 0xfb3, 0x265, 0x253a, 0x2b65, 0x2f4b, 0xa30, 0x2a17, 0x2de, 0x103a, 0x18e8, + 0x1159, 0x2bfe, 0x1327, 0x2a10, 0x2d61, 0x2fa7, 0x815, 0x1d41, 0xf02, 0x22c3, 0x66, 0xdcf, + 0x1540, 0x2f3e, 0x1983, 0x761, 0x1084, 0x1350, 0xdd, 0x15eb, 0xe0a, 0x2f50, 0x217f, 0xb21, + 0x2a51, 0x15f6, 0x1d96, 0x1328, 0x9ca, 0x1500, 0x79, 0xfe9, 0x935, 0x16f0, 0x21ce, 0x73c, + 0x2ac6, 0x1604, 0xe76, 0x2613, 0x330, 0x2d31, 0x10a7, 0x2a04, 0x180e, 0x170a, 0x2801, 0x1ca7, + 0x255f, 0x3bc, 0x2b1, 0x1727, 0xf88, 0x1a15, 0x1c30, 0xeee, 0x2f37, 0x658, 0x15a5, 0x224f, + 0x248, 0x1cc3, 0x71f, 0x1dd6, 0xbc3, 0x2b46, 0xc35, 0x13bb, 0x2afe, 0x2e0c, 0x21ca, 0x27a3, + 0x9f0, 0x164b, 0x289f, 0x14dd, 0x2649, 0x22dc, 0xd2, 0x304, 0x2bc0, 0xee, 0x1ee6, 0x2195, + 0x1fc9, 0x1cb0, 0x295d, 0x29e1, 0xddd, 0x187a, 0x5e4, 0x1950, 0x2a25, 0x2cd2, 0x2bda, 0x639, + 0x2290, 0x2819, 0x139c, 0x2a5f, 0x15c0, 0x1e58, 0x2ac2, 0x1234, 0x283c, 0x6db, 0xa6a, 0x1d99, + 0x2b60, 0x9d9, 0x1380, 0x1d2b, 0x1feb, 0x2e6, 0xe71, 0x2a93, 0x2226, 0x296f, 0x1b4d, 0x119d, + 0x1fed, 0x88a, 0x43f, 0x2762, 0x1271, 0x28e7, 0x9a5, 0x548, 0x2256, 0x1488, 0x1b40, 0x26ea, + 0x2d38, 0x2bc6, 0x1fa6, 0xe65, 0x17c8, 0x20ab, 0x17ff, 0x1e27, 0x2fb1, 0x1a8d, 0x169, 0x27ee, + 0xb34, 0x1800, 0x151d, 0x1fe6, 0x25f4, 0x2916, 0x2929, 0x1f13, 0x1308, 0xb72, 0x1e3e, 0x25e, + 0x2cca, 0x24d1, 0xf09, 0xb62, 0x21d0, 0x1aa4, 0x2648, 0xcb8, 0x2981, 0x216b, 0x1d28, 0x1626, + 0x12e0, 0x2aa5, 0x2a22, 0x1231, 0x16e7, 0x1a4d, 0xfb1, 0x2a99, 0x14cf, 0x2e96, 0xeff, 0x1462, + 0x2fbb, 0x11f7, 0x17d8, 0x2e0d, 0x2791, 0x49f, 0x120b, 0x2671, 0x1237, 0x268a, 0x12a3, 0x740, + 0x11e1, 0x2b86, 0x2dee, 0x1110, 0x2163, 0x1379, 0x2db8, 0x2e76, 0x1623, 0x2d6a, 0x9ef, 0x5e3, + 0x11c0, 0x104a, 0x2991, 0x4ae, 0x8b2, 0x2582, 0x1d8b, 0x41, 0x2780, 0x19dd, 0x28af, 0x2344, + 0x199e, 0xe1b, 0x1c4b, 0x3b, 0x4d6, 0x1b45, 0x85b, 0xe42, 0xd97, 0x1312, 0x1ab3, 0x2901, 0xfd8, + 0x58d, 0xf0, 0x1805, 0x1ff, 0x110, 0x2350, 0x18aa, 0x2b2f, 0x10e6, 0x1ec2, 0x252e, 0x1849, + 0xc75, 0x2674, 0x2853, 0x12ab, 0x737, 0xde3, 0x10c3, 0x1491, 0xfbd, 0x2b07, 0x174f, 0x69b, + 0x1412, 0x1194, 0x1e55, 0x196d, 0x13ec, 0x260f, 0x66a, 0x1da1, 0x2d8b, 0x892, 0xcc3, 0x90c, + 0x350, 0x2ca, 0xa7, 0x4bd, 0x4e2, 0x1518, 0x2466, 0x14e9, 0x17e8, 0x1a78, 0x1ae6, 0x238e, + 0x2d0d, 0xaf, 0x2284, 0x1475, 0x20c7, 0x29c0, 0x13fc, 0x227d, 0x1bdc, 0x10aa, 0x1db7, 0x18ae, + 0x949, 0x3a1, 0x2f2c, 0x1187, 0x559, 0x248b, 0x1d30, 0xccd, 0x196a, 0x57, 0x1b4f, 0x1220, + 0x28a3, 0xd1, 0x171e, 0xb8a, 0x1a87, 0xec0, 0x26ae, 0x229b, 0x1035, 0x1040, 0x4e, 0x1299, + 0x226b, 0x1409, 0xb7a, 0x1c75, 0x1043, 0x120, 0x1339, 0xbff, 0x147a, 0x2a60, 0x13ff, 0x3d1, + 0x2a16, 0x200a, 0x1467, 0x1c9d, 0x111c, 0x6b5, 0x6d, 0x5ae, 0x1e1a, 0x1497, 0x254a, 0x2a0a, + 0xdbc, 0x77d, 0xc71, 0xf58, 0x1333, 0x1956, 0x2fe1, 0x724, 0x131d, 0x2a3f, 0xb4b, 0x2cf2, + 0x281a, 0x1963, 0x1a94, 0x29da, 0x165f, 0xc28, 0x2908, 0x848, 0x1ff8, 0x2df0, 0x18dd, 0x1cd, + 0x40f, 0x22c, 0x871, 0x3d3, 0xbf5, 0x1303, 0x2da9, 0x25e1, 0x2259, 0xc0d, 0x7ba, 0x2a8, 0x1180, + 0x865, 0x542, 0x2fad, 0x31d, 0x2c2c, 0x2608, 0x23a5, 0x175e, 0x2d43, 0x2e27, 0x2dc4, 0x1018, + 0x28b9, 0x1a44, 0xbb3, 0x176d, 0x23ea, 0x146, 0xb43, 0x124d, 0x28a8, 0x1ff7, 0x2829, 0x1bf9, + 0x2832, 0x3c1, 0x1f94, 0x2d8e, 0x19e7, 0xd63, 0x1559, 0xd93, 0xaa3, 0x23e7, 0x73f, 0x2f42, 0x9e, + 0x2837, 0xea, 0x2405, 0x248e, 0x10e3, 0xd6d, 0x2ca1, 0xc8, 0xc04, 0x9aa, 0x2eba, 0x1ef7, 0x1be2, + 0x353, 0x2fe5, 0x1e40, 0xa2b, 0xd34, 0x27f, 0x2b6d, 0x251e, 0x1bdb, 0x2e04, 0x2393, 0x15f8, + 0x2924, 0xe15, 0x29a2, 0x2efc, 0x1c3d, 0x2262, 0x100b, 0x99a, 0x278f, 0x240e, 0x288c, 0x12c3, + 0x253, 0x2df4, 0x2725, 0x22a3, 0x78a, 0x20ba, 0xea6, 0x2147, 0xd30, 0x109a, 0x17b7, 0x2559, + 0x20b1, 0x18d3, 0x2809, 0xbda, 0x709, 0x26f9, 0x23df, 0x1e60, 0x28f9, 0x1deb, 0x2514, 0xb7f, + 0x957, 0x16d2, 0x47f, 0xfc, 0xfc6, 0x1136, 0xce8, 0x15d8, 0x47, 0x83a, 0x1619, 0x6b7, 0x2a73, + 0x1d, 0x1788, 0x160b, 0x6e6, 0x2445, 0x1646, 0xe38, 0x3d2, 0x14eb, 0x1729, 0xb89, 0x131c, + 0x13d9, 0x184c, 0x1275, 0x1fbb, 0x16ae, 0x2488, 0x297d, 0xc2d, 0x633, 0x2fe7, 0x2a9a, 0x1a96, + 0xe20, 0x92d, 0x1146, 0x956, 0x1400, 0x998, 0x1a95, 0x2fa1, 0x223d, 0x2a4d, 0x11e5, 0xfdc, + 0x198a, 0x2934, 0x1f9, 0x2553, + ]; + + return NHS; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.NHS = NHS; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/pair.js b/packages/bls-verify/src/vendor/amcl-js/src/pair.js new file mode 100644 index 000000000..057dbe517 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/pair.js @@ -0,0 +1,1076 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var PAIR = function (ctx) { + 'use strict'; + + var PAIR = { + dbl: function (A, AA, BB, CC) { + CC.copy(A.getx()); + var YY = new ctx.FP2(A.gety()); + BB.copy(A.getz()); + AA.copy(YY); + + AA.mul(BB); //YZ + CC.sqr(); //X^2 + YY.sqr(); //Y^2 + BB.sqr(); //Z^2 + + AA.add(AA); + AA.neg(); + AA.norm(); //-2AA + AA.mul_ip(); + AA.norm(); + + var sb = 3 * ctx.ROM_CURVE.CURVE_B_I; + BB.imul(sb); + CC.imul(3); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + YY.mul_ip(); + YY.norm(); + CC.mul_ip(); + CC.norm(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + BB.mul_ip(); + BB.norm(); + } + BB.sub(YY); + BB.norm(); + + A.dbl(); + }, + + add: function (A, B, AA, BB, CC) { + AA.copy(A.getx()); // X1 + CC.copy(A.gety()); // Y1 + var T1 = new ctx.FP2(A.getz()); // Z1 + BB.copy(A.getz()); // Z1 + + T1.mul(B.gety()); // T1=Z1.Y2 + BB.mul(B.getx()); // T2=Z1.X2 + + AA.sub(BB); + AA.norm(); // X1=X1-Z1.X2 + CC.sub(T1); + CC.norm(); // Y1=Y1-Z1.Y2 + + T1.copy(AA); // T1=X1-Z1.X2 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + AA.mul_ip(); + AA.norm(); + } + + T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2 + + BB.copy(CC); // T2=Y1-Z1.Y2 + BB.mul(B.getx()); // T2=(Y1-Z1.Y2).X2 + BB.sub(T1); + BB.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 + CC.neg(); + CC.norm(); // Y1=-(Y1-Z1.Y2).Xs + + A.add(B); + }, + + /* Line function */ + line: function (A, B, Qx, Qy) { + var r = new ctx.FP12(1); + + var a, b, c; + var AA = new ctx.FP2(0); + var BB = new ctx.FP2(0); + var CC = new ctx.FP2(0); + if (A == B) PAIR.dbl(A, AA, BB, CC); + else PAIR.add(A, B, AA, BB, CC); + + CC.pmul(Qx); + AA.pmul(Qy); + + a = new ctx.FP4(AA, BB); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP4(CC); // L(0,1) | L(0,0) | L(1,0) + c = new ctx.FP4(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP4(0); + c = new ctx.FP4(CC); + c.times_i(); + } + + r.set(a, b, c); + r.settype(ctx.FP.SPARSER); + + return r; + }, + + /* prepare for multi-pairing */ + initmp: function () { + var r = []; + for (var i = 0; i < ctx.ECP.ATE_BITS; i++) r[i] = new ctx.FP12(1); + return r; + }, + + /* basic Miller loop */ + miller: function (r) { + var res = new ctx.FP12(1); + for (var i = ctx.ECP.ATE_BITS - 1; i >= 1; i--) { + res.sqr(); + res.ssmul(r[i]); + r[i].zero(); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) res.conj(); + res.ssmul(r[0]); + r[0].zero(); + + return res; + }, + + // Store precomputed line details in an FP4 + pack: function (AA, BB, CC) { + var i = new ctx.FP2(CC); + i.inverse(null); + var a = new ctx.FP2(AA); + a.mul(i); + var b = new ctx.FP2(BB); + b.mul(i); + return new ctx.FP4(a, b); + }, + + unpack: function (T, Qx, Qy) { + var a, b, c; + a = new ctx.FP4(T); + a.geta().pmul(Qy); + var t = new ctx.FP2(Qx); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP4(t); + c = new ctx.FP4(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP4(0); + c = new ctx.FP4(t); + c.times_i(); + } + var v = new ctx.FP12(a, b, c); + v.settype(ctx.FP.SPARSEST); + return v; + }, + + precomp: function (GV) { + var f; + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR.lbits(n3, n); + var P = new ctx.ECP2(); + P.copy(GV); + var AA = new ctx.FP2(0); + var BB = new ctx.FP2(0); + var CC = new ctx.FP2(0); + var j, bt; + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + var fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + var fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + f.inverse(null); + f.norm(); + } + } + var A = new ctx.ECP2(); + A.copy(P); + var MP = new ctx.ECP2(); + MP.copy(P); + MP.neg(); + j = 0; + + var T = []; + for (var i = nb - 2; i >= 1; i--) { + PAIR.dbl(A, AA, BB, CC); + T[j++] = PAIR.pack(AA, BB, CC); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + PAIR.add(A, P, AA, BB, CC); + T[j++] = PAIR.pack(AA, BB, CC); + } + if (bt == -1) { + PAIR.add(A, MP, AA, BB, CC); + T[j++] = PAIR.pack(AA, BB, CC); + } + } + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + A.neg(); + } + var K = new ctx.ECP2(); + K.copy(P); + K.frob(f); + PAIR.add(A, K, AA, BB, CC); + T[j++] = PAIR.pack(AA, BB, CC); + K.frob(f); + K.neg(); + PAIR.add(A, K, AA, BB, CC); + T[j++] = PAIR.pack(AA, BB, CC); + } + return T; + }, + + /* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ + another_pc(r, T, QV) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR.lbits(n3, n); + var lv, lv2; + var j, bt; + + if (QV.is_infinity()) return; + + var Q = new ctx.ECP(); + Q.copy(QV); + Q.affine(); + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + j = 0; + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR.unpack(T[j++], Qx, Qy); + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + lv = PAIR.unpack(T[j++], Qx, Qy); + lv2 = PAIR.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + r[0].ssmul(lv); + } + }, + + /* Accumulate another set of line functions for n-pairing */ + another: function (r, P1, Q1) { + var f; + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var K = new ctx.ECP2(); + var lv, lv2; + var bt; + + if (Q1.is_infinity()) return; + // P is needed in affine form for line function, Q for (Qx,Qy) extraction + var P = new ctx.ECP2(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + P.affine(); + Q.affine(); + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + var fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + var fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + f.inverse(null); + f.norm(); + } + } + + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + var A = new ctx.ECP2(); + A.copy(P); + + var MP = new ctx.ECP2(); + MP.copy(P); + MP.neg(); + + var nb = PAIR.lbits(n3, n); + + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR.line(A, A, Qx, Qy); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR.line(A, MP, Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + + /* R-ate fixup required for BN curves */ + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + A.neg(); + } + K.copy(P); + K.frob(f); + lv = PAIR.line(A, K, Qx, Qy); + K.frob(f); + K.neg(); + lv2 = PAIR.line(A, K, Qx, Qy); + lv.smul(lv2); + r[0].ssmul(lv); + } + }, + + /* Optimal R-ate pairing */ + ate: function (P1, Q1) { + var fa, fb, f, n, n3, K, lv, lv2, Qx, Qy, A, NP, r, nb, bt, i; + + if (Q1.is_infinity()) return new ctx.FP12(1); + + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + K = new ctx.ECP2(); + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + f.inverse(null); + f.norm(); + } + } + + var P = new ctx.ECP2(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + A = new ctx.ECP2(); + r = new ctx.FP12(1); + A.copy(P); + + NP = new ctx.ECP2(); + NP.copy(P); + NP.neg(); + + nb = PAIR.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR.line(A, A, Qx, Qy); + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv2 = PAIR.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR.line(A, NP, Qx, Qy); + lv.smul(lv2); + } + r.ssmul(lv); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + /* R-ate fixup */ + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + A.neg(); + } + + K.copy(P); + K.frob(f); + + lv = PAIR.line(A, K, Qx, Qy); + K.frob(f); + K.neg(); + lv2 = PAIR.line(A, K, Qx, Qy); + lv.smul(lv2); + r.ssmul(lv); + } + + return r; + }, + + /* Optimal R-ate double pairing e(P,Q).e(R,S) */ + + ate2: function (P1, Q1, R1, S1) { + var fa, fb, f, n, n3, K, lv, lv2, Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt, i; + + if (Q1.is_infinity()) return PAIR.ate(R1, S1); + if (S1.is_infinity()) return PAIR.ate(P1, Q1); + + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + K = new ctx.ECP2(); + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + f.inverse(null); + f.norm(); + } + } + + var P = new ctx.ECP2(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + var R = new ctx.ECP2(); + R.copy(R1); + R.affine(); + var S = new ctx.ECP(); + S.copy(S1); + S.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + Sx = new ctx.FP(S.getx()); + Sy = new ctx.FP(S.gety()); + + A = new ctx.ECP2(); + B = new ctx.ECP2(); + r = new ctx.FP12(1); + + A.copy(P); + B.copy(R); + + NP = new ctx.ECP2(); + NP.copy(P); + NP.neg(); + NR = new ctx.ECP2(); + NR.copy(R); + NR.neg(); + + nb = PAIR.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR.line(A, A, Qx, Qy); + lv2 = PAIR.line(B, B, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv = PAIR.line(A, P, Qx, Qy); + lv2 = PAIR.line(B, R, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + if (bt == -1) { + lv = PAIR.line(A, NP, Qx, Qy); + lv2 = PAIR.line(B, NR, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + // R-ate fixup required for BN curves + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + A.neg(); + B.neg(); + } + K.copy(P); + K.frob(f); + + lv = PAIR.line(A, K, Qx, Qy); + K.frob(f); + K.neg(); + lv2 = PAIR.line(A, K, Qx, Qy); + lv.smul(lv2); + r.ssmul(lv); + + K.copy(R); + K.frob(f); + + lv = PAIR.line(B, K, Sx, Sy); + K.frob(f); + K.neg(); + lv2 = PAIR.line(B, K, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + + return r; + }, + + /* final exponentiation - keep separate for multi-pairings */ + fexp: function (m) { + var fa, fb, f, x, r, lv; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + r = new ctx.FP12(m); + + /* Easy part of final exp */ + lv = new ctx.FP12(r); + lv.inverse(); + r.conj(); + r.mul(lv); + lv.copy(r); + r.frob(f); + r.frob(f); + r.mul(lv); + + /* Hard part of final exp */ + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + var x0, x1, x2, x3, x4, x5; + + lv.copy(r); + lv.frob(f); + x0 = new ctx.FP12(lv); //x0.copy(lv); + x0.frob(f); + lv.mul(r); + x0.mul(lv); + x0.frob(f); + x1 = new ctx.FP12(r); //x1.copy(r); + x1.conj(); + + x4 = r.pow(x); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) { + x4.conj(); + } + + x3 = new ctx.FP12(x4); //x3.copy(x4); + x3.frob(f); + x2 = x4.pow(x); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) { + x2.conj(); + } + x5 = new ctx.FP12(x2); /*x5.copy(x2);*/ + x5.conj(); + lv = x2.pow(x); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) { + lv.conj(); + } + x2.frob(f); + r.copy(x2); + r.conj(); + + x4.mul(r); + x2.frob(f); + + r.copy(lv); + r.frob(f); + lv.mul(r); + + lv.usqr(); + lv.mul(x4); + lv.mul(x5); + r.copy(x3); + r.mul(x5); + r.mul(lv); + lv.mul(x2); + r.usqr(); + r.mul(lv); + r.usqr(); + lv.copy(r); + lv.mul(x1); + r.mul(x0); + lv.usqr(); + r.mul(lv); + r.reduce(); + } else { + // See https://eprint.iacr.org/2020/875.pdf + var t0, y0, y1; + y1 = new ctx.FP12(r); + y1.usqr(); + y1.mul(r); // y1=r^3 + + y0 = new ctx.FP12(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0 = new ctx.FP12(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + // ^(x+p) + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.frob(f); + r.copy(y0); + r.mul(t0); + + // ^(x^2+p^2-1) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f); + t0.frob(f); + y0.mul(t0); + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + r.mul(y1); + r.reduce(); + + /* + var y0, y1, y2, y3; + // Ghamman & Fouotsa Method + y0 = new ctx.FP12(r); + y0.usqr(); + y1 = y0.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + y1.conj(); + } + x.fshr(1); + y2 = y1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + y2.conj(); + } + x.fshl(1); + y3 = new ctx.FP12(r); + y3.conj(); + y1.mul(y3); + + y1.conj(); + y1.mul(y2); + + y2 = y1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + y2.conj(); + } + + y3 = y2.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + y3.conj(); + } + y1.conj(); + y3.mul(y1); + + y1.conj(); + y1.frob(f); + y1.frob(f); + y1.frob(f); + y2.frob(f); + y2.frob(f); + y1.mul(y2); + + y2 = y3.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + y2.conj(); + } + y2.mul(y0); + y2.mul(r); + + y1.mul(y2); + y2.copy(y3); + y2.frob(f); + y1.mul(y2); + r.copy(y1); + r.reduce(); +*/ + } + + return r; + }, + }; + + /* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ + PAIR.lbits = function (n3, n) { + n.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + n.pmul(6); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) { + n.inc(2); + } else { + n.dec(2); + } + } + + n.norm(); + n3.copy(n); + n3.pmul(3); + n3.norm(); + return n3.nbits(); + }; + + /* GLV method */ + PAIR.glv = function (e) { + var u = [], + t, + q, + v, + d, + x, + x2, + i, + j; + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + t = new ctx.BIG(0); + q = new ctx.BIG(0); + v = []; + + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + for (i = 0; i < 2; i++) { + t.rcopy(ctx.ROM_CURVE.CURVE_W[i]); + d = ctx.BIG.mul(t, e); + v[i] = new ctx.BIG(d.div(q)); + u[i] = new ctx.BIG(0); + } + + u[0].copy(e); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + t.rcopy(ctx.ROM_CURVE.CURVE_SB[j][i]); + t.copy(ctx.BIG.modmul(v[j], t, q)); + u[i].add(q); + u[i].sub(t); + u[i].mod(q); + } + } + } else { + // -(x^2).P = (Beta.x,y) + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + x2 = ctx.BIG.smul(x, x); + u[0] = new ctx.BIG(e); + u[0].mod(x2); + u[1] = new ctx.BIG(e); + u[1].div(x2); + u[1].rsub(q); + } + + return u; + }; + + /* Galbraith & Scott Method */ + PAIR.gs = function (e) { + var u = [], + i, + j, + t, + q, + v, + d, + x, + w; + + if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) { + t = new ctx.BIG(0); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + v = []; + + for (i = 0; i < 4; i++) { + t.rcopy(ctx.ROM_CURVE.CURVE_WB[i]); + d = ctx.BIG.mul(t, e); + v[i] = new ctx.BIG(d.div(q)); + u[i] = new ctx.BIG(0); + } + + u[0].copy(e); + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + t.rcopy(ctx.ROM_CURVE.CURVE_BB[j][i]); + t.copy(ctx.BIG.modmul(v[j], t, q)); + u[i].add(q); + u[i].sub(t); + u[i].mod(q); + } + } + } else { + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + w = new ctx.BIG(e); + + for (i = 0; i < 3; i++) { + u[i] = new ctx.BIG(w); + u[i].mod(x); + w.div(x); + } + + u[3] = new ctx.BIG(w); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + u[1].copy(ctx.BIG.modneg(u[1], q)); + u[3].copy(ctx.BIG.modneg(u[3], q)); + } + } + + return u; + }; + + /* Multiply P by e in group G1 */ + PAIR.G1mul = function (P, e) { + var R, Q, q, bcru, cru, t, u, np, nn; + + if (ctx.ROM_CURVE.USE_GLV) { + R = new ctx.ECP(); + R.copy(P); + Q = new ctx.ECP(); + Q.copy(P); + Q.affine(); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + bcru = new ctx.BIG(0); + bcru.rcopy(ctx.ROM_FIELD.CRu); + cru = new ctx.FP(bcru); + t = new ctx.BIG(0); + u = PAIR.glv(e); + + Q.getx().mul(cru); + + np = u[0].nbits(); + t.copy(ctx.BIG.modneg(u[0], q)); + nn = t.nbits(); + if (nn < np) { + u[0].copy(t); + R.neg(); + } + + np = u[1].nbits(); + t.copy(ctx.BIG.modneg(u[1], q)); + nn = t.nbits(); + if (nn < np) { + u[1].copy(t); + Q.neg(); + } + u[0].norm(); + u[1].norm(); + R = R.mul2(u[0], Q, u[1]); + } else { + R = P.mul(e); + } + + return R; + }; + + /* Multiply P by e in group G2 */ + PAIR.G2mul = function (P, e) { + var R, Q, fa, fb, f, q, u, t, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_G2) { + Q = []; + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + f.inverse(null); + f.norm(); + } + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + u = PAIR.gs(e); + t = new ctx.BIG(0); + Q[0] = new ctx.ECP2(); + Q[0].copy(P); + + for (i = 1; i < 4; i++) { + Q[i] = new ctx.ECP2(); + Q[i].copy(Q[i - 1]); + Q[i].frob(f); + } + + for (i = 0; i < 4; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + Q[i].neg(); + } + u[i].norm(); + } + + R = ctx.ECP2.mul4(Q, u); + } else { + R = P.mul(e); + } + return R; + }; + + /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */ + PAIR.GTpow = function (d, e) { + var r, g, fa, fb, f, q, t, u, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_GT) { + g = []; + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + t = new ctx.BIG(0); + u = PAIR.gs(e); + + g[0] = new ctx.FP12(d); + + for (i = 1; i < 4; i++) { + g[i] = new ctx.FP12(0); + g[i].copy(g[i - 1]); + g[i].frob(f); + } + + for (i = 0; i < 4; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + g[i].conj(); + } + u[i].norm(); + } + + r = ctx.FP12.pow4(g, u); + } else { + r = d.pow(e); + } + + return r; + }; + + /* test G1 group membership */ + PAIR.G1member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR.G1mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test G2 group membership */ + PAIR.G2member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR.G2mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test group membership - no longer needed */ + /* Check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ + + PAIR.GTmember = function (m) { + if (m.isunity()) return false; + var r = new ctx.FP12(m); + r.conj(); + r.mul(m); + if (!r.isunity()) return false; + + var fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + var fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + var f = new ctx.FP2(fa, fb); + + r.copy(m); + r.frob(f); + r.frob(f); + var w = new ctx.FP12(r); + w.frob(f); + w.frob(f); + w.mul(m); + if (!w.equals(r)) return false; + + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + w.copy(m); + r.copy(PAIR.GTpow(w, q)); + if (!r.isunity()) return false; + return true; + }; + + return PAIR; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.PAIR = PAIR; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/pair4.js b/packages/bls-verify/src/vendor/amcl-js/src/pair4.js new file mode 100644 index 000000000..3eac108d0 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/pair4.js @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var PAIR4 = function (ctx) { + 'use strict'; + var PAIR4 = { + dbl: function (A, AA, BB, CC) { + CC.copy(A.getx()); + var YY = new ctx.FP4(A.gety()); + BB.copy(A.getz()); + AA.copy(YY); + + AA.mul(BB); //YZ + CC.sqr(); //X^2 + YY.sqr(); //Y^2 + BB.sqr(); //Z^2 + + AA.add(AA); + AA.neg(); + AA.norm(); //-2AA + AA.times_i(); + + var sb = 3 * ctx.ROM_CURVE.CURVE_B_I; + BB.imul(sb); + CC.imul(3); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + YY.times_i(); + CC.times_i(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + BB.times_i(); + } + BB.sub(YY); + BB.norm(); + + A.dbl(); + }, + + add: function (A, B, AA, BB, CC) { + AA.copy(A.getx()); // X1 + CC.copy(A.gety()); // Y1 + var T1 = new ctx.FP4(A.getz()); // Z1 + BB.copy(A.getz()); // Z1 + + T1.mul(B.gety()); // T1=Z1.Y2 + BB.mul(B.getx()); // T2=Z1.X2 + + AA.sub(BB); + AA.norm(); // X1=X1-Z1.X2 + CC.sub(T1); + CC.norm(); // Y1=Y1-Z1.Y2 + + T1.copy(AA); // T1=X1-Z1.X2 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + AA.times_i(); + AA.norm(); + } + + T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2 + + BB.copy(CC); // T2=Y1-Z1.Y2 + BB.mul(B.getx()); // T2=(Y1-Z1.Y2).X2 + BB.sub(T1); + BB.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 + CC.neg(); + CC.norm(); // Y1=-(Y1-Z1.Y2).Xs + + A.add(B); + }, + + /* Line function */ + line: function (A, B, Qx, Qy) { + var r = new ctx.FP24(1); + + var a, b, c; + var AA = new ctx.FP4(0); + var BB = new ctx.FP4(0); + var CC = new ctx.FP4(0); + if (A == B) PAIR4.dbl(A, AA, BB, CC); + else PAIR4.add(A, B, AA, BB, CC); + + CC.qmul(Qx); + AA.qmul(Qy); + + a = new ctx.FP8(AA, BB); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP8(CC); // L(0,1) | L(0,0) | L(1,0) + c = new ctx.FP8(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP8(0); + c = new ctx.FP8(CC); + c.times_i(); + } + + r.set(a, b, c); + r.settype(ctx.FP.SPARSER); + + return r; + }, + + /* prepare for multi-pairing */ + initmp: function () { + var r = []; + for (var i = 0; i < ctx.ECP.ATE_BITS; i++) r[i] = new ctx.FP24(1); + return r; + }, + + /* basic Miller loop */ + miller: function (r) { + var res = new ctx.FP24(1); + for (var i = ctx.ECP.ATE_BITS - 1; i >= 1; i--) { + res.sqr(); + res.ssmul(r[i]); + r[i].zero(); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) res.conj(); + res.ssmul(r[0]); + r[0].zero(); + + return res; + }, + + // Store precomputed line details in an FP8 + pack: function (AA, BB, CC) { + var i = new ctx.FP4(CC); + i.inverse(null); + var a = new ctx.FP4(AA); + a.mul(i); + var b = new ctx.FP4(BB); + b.mul(i); + return new ctx.FP8(a, b); + }, + + unpack: function (T, Qx, Qy) { + var a, b, c; + a = new ctx.FP8(T); + a.geta().qmul(Qy); + var t = new ctx.FP4(Qx); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP8(t); + c = new ctx.FP8(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP8(0); + c = new ctx.FP8(t); + c.times_i(); + } + var v = new ctx.FP24(a, b, c); + v.settype(ctx.FP.SPARSEST); + return v; + }, + + precomp: function (QV) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR4.lbits(n3, n); + var P = new ctx.ECP4(); + P.copy(QV); + var AA = new ctx.FP4(0); + var BB = new ctx.FP4(0); + var CC = new ctx.FP4(0); + var j, bt; + + var A = new ctx.ECP4(); + A.copy(P); + var MP = new ctx.ECP4(); + MP.copy(P); + MP.neg(); + j = 0; + + var T = []; + for (var i = nb - 2; i >= 1; i--) { + PAIR4.dbl(A, AA, BB, CC); + T[j++] = PAIR4.pack(AA, BB, CC); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + PAIR4.add(A, P, AA, BB, CC); + T[j++] = PAIR4.pack(AA, BB, CC); + } + if (bt == -1) { + PAIR4.add(A, MP, AA, BB, CC); + T[j++] = PAIR4.pack(AA, BB, CC); + } + } + return T; + }, + + /* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ + another_pc(r, T, QV) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR4.lbits(n3, n); + var lv, lv2; + var j, bt; + + if (QV.is_infinity()) return; + + var Q = new ctx.ECP(); + Q.copy(QV); + Q.affine(); + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + j = 0; + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR4.unpack(T[j++], Qx, Qy); + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR4.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR4.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + }, + + /* Accumulate another set of line functions for n-pairing */ + another: function (r, P1, Q1) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var lv, lv2; + var bt; + + if (Q1.is_infinity()) return; + // P is needed in affine form for line function, Q for (Qx,Qy) extraction + var P = new ctx.ECP4(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + P.affine(); + Q.affine(); + + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + var A = new ctx.ECP4(); + A.copy(P); + + var MP = new ctx.ECP4(); + MP.copy(P); + MP.neg(); + + var nb = PAIR4.lbits(n3, n); + + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR4.line(A, A, Qx, Qy); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR4.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR4.line(A, MP, Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + }, + + /* Optimal R-ate pairing */ + ate: function (P1, Q1) { + var n, n3, lv, lv2, Qx, Qy, A, NP, r, nb, bt, i; + + if (Q1.is_infinity()) return new ctx.FP24(1); + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + + var P = new ctx.ECP4(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + A = new ctx.ECP4(); + r = new ctx.FP24(1); + + A.copy(P); + NP = new ctx.ECP4(); + NP.copy(P); + NP.neg(); + + nb = PAIR4.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR4.line(A, A, Qx, Qy); + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv2 = PAIR4.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR4.line(A, NP, Qx, Qy); + lv.smul(lv2); + } + r.ssmul(lv); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + return r; + }, + + /* Optimal R-ate double pairing e(P,Q).e(R,S) */ + ate2: function (P1, Q1, R1, S1) { + var n, n3, lv, lv2, Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt, i; + + if (Q1.is_infinity()) return PAIR4.ate(R1, S1); + if (S1.is_infinity()) return PAIR4.ate(P1, Q1); + + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + + var P = new ctx.ECP4(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + var R = new ctx.ECP4(); + R.copy(R1); + R.affine(); + var S = new ctx.ECP(); + S.copy(S1); + S.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + Sx = new ctx.FP(S.getx()); + Sy = new ctx.FP(S.gety()); + + A = new ctx.ECP4(); + B = new ctx.ECP4(); + r = new ctx.FP24(1); + + A.copy(P); + B.copy(R); + NP = new ctx.ECP4(); + NP.copy(P); + NP.neg(); + NR = new ctx.ECP4(); + NR.copy(R); + NR.neg(); + + nb = PAIR4.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR4.line(A, A, Qx, Qy); + lv2 = PAIR4.line(B, B, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv = PAIR4.line(A, P, Qx, Qy); + lv2 = PAIR4.line(B, R, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + if (bt == -1) { + lv = PAIR4.line(A, NP, Qx, Qy); + lv2 = PAIR4.line(B, NR, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + return r; + }, + + /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ + fexp: function (m) { + var fa, fb, f, x, r, lv; + // t0,t1,t2,t3,t4,t5,t6,t7; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + r = new ctx.FP24(m); //r.copy(m); + + /* Easy part of final exp */ + lv = new ctx.FP24(r); //lv.copy(r); + lv.inverse(); + r.conj(); + r.mul(lv); + lv.copy(r); + r.frob(f, 4); + r.mul(lv); + + /* Hard part of final exp */ + // See https://eprint.iacr.org/2020/875.pdf + var t0, y0, y1; + y1 = new ctx.FP24(r); + y1.usqr(); + y1.mul(r); // y1=r^3 + + y0 = new ctx.FP24(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0 = new ctx.FP24(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + // ^(x+p) + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.frob(f, 1); + r.copy(y0); + r.mul(t0); + + // ^(x^2+p^2) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f, 2); + r.copy(y0); + r.mul(t0); + + // ^(x^4+p^4-1) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f, 4); + y0.mul(t0); + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + r.mul(y1); + r.reduce(); + + /* + // Ghamman & Fouotsa Method + t7=new ctx.FP24(r); t7.usqr(); + t1=t7.pow(x); + + x.fshr(1); + t2=t1.pow(x); + x.fshl(1); + + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + t3=new ctx.FP24(t1); t3.conj(); + t2.mul(t3); + t2.mul(r); + + t3=t2.pow(x); + t4=t3.pow(x); + t5=t4.pow(x); + + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t3.conj(); t5.conj(); + } + + t3.frob(f,6); t4.frob(f,5); + t3.mul(t4); + + t6=t5.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t6.conj(); + } + + t5.frob(f,4); + t3.mul(t5); + + t0=new ctx.FP24(t2); t0.conj(); + t6.mul(t0); + + t5.copy(t6); + t5.frob(f,3); + + t3.mul(t5); + t5=t6.pow(x); + t6=t5.pow(x); + + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t5.conj(); + } + + t0.copy(t5); + t0.frob(f,2); + t3.mul(t0); + t0.copy(t6); + t0.frob(f,1); + + t3.mul(t0); + t5=t6.pow(x); + + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t5.conj(); + } + t2.frob(f,7); + + t5.mul(t7); + t3.mul(t2); + t3.mul(t5); + + r.mul(t3); + + r.reduce(); +*/ + return r; + }, + }; + + /* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ + PAIR4.lbits = function (n3, n) { + n.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + n3.copy(n); + n3.pmul(3); + n3.norm(); + return n3.nbits(); + }; + + /* GLV method */ + PAIR4.glv = function (e) { + var u = [], + q, + x, + x2; + + // -(x^2).P = (Beta.x,y) + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + x2 = ctx.BIG.smul(x, x); + x = ctx.BIG.smul(x2, x2); + u[0] = new ctx.BIG(e); + u[0].mod(x); + u[1] = new ctx.BIG(e); + u[1].div(x); + u[1].rsub(q); + + return u; + }; + + /* Galbraith & Scott Method */ + PAIR4.gs = function (e) { + var u = [], + i, + q, + x, + w; + + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + w = new ctx.BIG(e); + + for (i = 0; i < 7; i++) { + u[i] = new ctx.BIG(w); + u[i].mod(x); + w.div(x); + } + + u[7] = new ctx.BIG(w); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + u[1].copy(ctx.BIG.modneg(u[1], q)); + u[3].copy(ctx.BIG.modneg(u[3], q)); + u[5].copy(ctx.BIG.modneg(u[5], q)); + u[7].copy(ctx.BIG.modneg(u[7], q)); + } + + return u; + }; + + /* Multiply P by e in group G1 */ + PAIR4.G1mul = function (P, e) { + var R, Q, q, bcru, cru, t, u, np, nn; + + if (ctx.ROM_CURVE.USE_GLV) { + R = new ctx.ECP(); + R.copy(P); + Q = new ctx.ECP(); + Q.copy(P); + Q.affine(); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + bcru = new ctx.BIG(0); + bcru.rcopy(ctx.ROM_FIELD.CRu); + cru = new ctx.FP(bcru); + t = new ctx.BIG(0); + u = PAIR4.glv(e); + + Q.getx().mul(cru); + + np = u[0].nbits(); + t.copy(ctx.BIG.modneg(u[0], q)); + nn = t.nbits(); + if (nn < np) { + u[0].copy(t); + R.neg(); + } + + np = u[1].nbits(); + t.copy(ctx.BIG.modneg(u[1], q)); + nn = t.nbits(); + if (nn < np) { + u[1].copy(t); + Q.neg(); + } + u[0].norm(); + u[1].norm(); + R = R.mul2(u[0], Q, u[1]); + } else { + R = P.mul(e); + } + + return R; + }; + + /* Multiply P by e in group G2 */ + PAIR4.G2mul = function (P, e) { + var R, Q, F, q, u, t, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_G2) { + Q = []; + F = ctx.ECP4.frob_constants(); + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + u = PAIR4.gs(e); + t = new ctx.BIG(0); + + Q[0] = new ctx.ECP4(); + Q[0].copy(P); + + for (i = 1; i < 8; i++) { + Q[i] = new ctx.ECP4(); + Q[i].copy(Q[i - 1]); + Q[i].frob(F, 1); + } + + for (i = 0; i < 8; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + Q[i].neg(); + } + u[i].norm(); + } + + R = ctx.ECP4.mul8(Q, u); + } else { + R = P.mul(e); + } + return R; + }; + + /* Note that this method requires a lot of RAM */ + PAIR4.GTpow = function (d, e) { + var r, g, fa, fb, f, q, t, u, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_GT) { + g = []; + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + t = new ctx.BIG(0); + u = PAIR4.gs(e); + + g[0] = new ctx.FP24(d); + + for (i = 1; i < 8; i++) { + g[i] = new ctx.FP24(0); + g[i].copy(g[i - 1]); + g[i].frob(f, 1); + } + + for (i = 0; i < 8; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + g[i].conj(); + } + u[i].norm(); + } + + r = ctx.FP24.pow8(g, u); + } else { + r = d.pow(e); + } + + return r; + }; + + /* test G1 group membership */ + PAIR4.G1member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR4.G1mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test G2 group membership */ + PAIR4.G2member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR4.G2mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test group membership - no longer needed */ + /* Check that m!=1, conj(m)*m==1, and m.m^{p^8}=m^{p^4} */ + + PAIR4.GTmember = function (m) { + if (m.isunity()) return false; + var r = new ctx.FP24(m); + r.conj(); + r.mul(m); + if (!r.isunity()) return false; + + var fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + var fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + var f = new ctx.FP2(fa, fb); + + r.copy(m); + r.frob(f, 4); + var w = new ctx.FP24(r); + w.frob(f, 4); + w.mul(m); + if (!w.equals(r)) return false; + + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + w.copy(m); + r.copy(PAIR4.GTpow(w, q)); + if (!r.isunity()) return false; + return true; + }; + + return PAIR4; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.PAIR4 = PAIR4; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/pair8.js b/packages/bls-verify/src/vendor/amcl-js/src/pair8.js new file mode 100644 index 000000000..d23f941e3 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/pair8.js @@ -0,0 +1,918 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var PAIR8 = function (ctx) { + 'use strict'; + + var PAIR8 = { + dbl: function (A, AA, BB, CC) { + CC.copy(A.getx()); + var YY = new ctx.FP8(A.gety()); + BB.copy(A.getz()); + AA.copy(YY); + + AA.mul(BB); //YZ + CC.sqr(); //X^2 + YY.sqr(); //Y^2 + BB.sqr(); //Z^2 + + AA.add(AA); + AA.neg(); + AA.norm(); //-2AA + AA.times_i(); + + var sb = 3 * ctx.ROM_CURVE.CURVE_B_I; + BB.imul(sb); + CC.imul(3); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + YY.times_i(); + CC.times_i(); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + BB.times_i(); + } + BB.sub(YY); + BB.norm(); + + A.dbl(); + }, + + add: function (A, B, AA, BB, CC) { + AA.copy(A.getx()); // X1 + CC.copy(A.gety()); // Y1 + var T1 = new ctx.FP8(A.getz()); // Z1 + BB.copy(A.getz()); // Z1 + + T1.mul(B.gety()); // T1=Z1.Y2 + BB.mul(B.getx()); // T2=Z1.X2 + + AA.sub(BB); + AA.norm(); // X1=X1-Z1.X2 + CC.sub(T1); + CC.norm(); // Y1=Y1-Z1.Y2 + + T1.copy(AA); // T1=X1-Z1.X2 + + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + AA.times_i(); + AA.norm(); + } + + T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2 + + BB.copy(CC); // T2=Y1-Z1.Y2 + BB.mul(B.getx()); // T2=(Y1-Z1.Y2).X2 + BB.sub(T1); + BB.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2 + CC.neg(); + CC.norm(); // Y1=-(Y1-Z1.Y2).Xs + + A.add(B); + }, + + /* Line function */ + line: function (A, B, Qx, Qy) { + var r = new ctx.FP48(1); + + var a, b, c; + var AA = new ctx.FP8(0); + var BB = new ctx.FP8(0); + var CC = new ctx.FP8(0); + if (A == B) PAIR8.dbl(A, AA, BB, CC); + else PAIR8.add(A, B, AA, BB, CC); + + CC.tmul(Qx); + AA.tmul(Qy); + + a = new ctx.FP16(AA, BB); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP16(CC); // L(0,1) | L(0,0) | L(1,0) + c = new ctx.FP16(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP16(0); + c = new ctx.FP16(CC); + c.times_i(); + } + + r.set(a, b, c); + r.settype(ctx.FP.SPARSER); + + return r; + }, + + /* prepare for multi-pairing */ + initmp: function () { + var r = []; + for (var i = 0; i < ctx.ECP.ATE_BITS; i++) r[i] = new ctx.FP48(1); + return r; + }, + + /* basic Miller loop */ + miller: function (r) { + var res = new ctx.FP48(1); + for (var i = ctx.ECP.ATE_BITS - 1; i >= 1; i--) { + res.sqr(); + res.ssmul(r[i]); + r[i].zero(); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) res.conj(); + res.ssmul(r[0]); + r[0].zero(); + + return res; + }, + + // Store precomputed line details in an FP8 + pack: function (AA, BB, CC) { + var i = new ctx.FP8(CC); + i.inverse(null); + var a = new ctx.FP8(AA); + a.mul(i); + var b = new ctx.FP8(BB); + b.mul(i); + return new ctx.FP16(a, b); + }, + + unpack: function (T, Qx, Qy) { + var a, b, c; + a = new ctx.FP16(T); + a.geta().tmul(Qy); + var t = new ctx.FP8(Qx); + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) { + b = new ctx.FP16(t); + c = new ctx.FP16(0); + } + if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) { + b = new ctx.FP16(0); + c = new ctx.FP16(t); + c.times_i(); + } + var v = new ctx.FP48(a, b, c); + v.settype(ctx.FP.SPARSEST); + return v; + }, + + precomp: function (QV) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR8.lbits(n3, n); + var P = new ctx.ECP8(); + P.copy(QV); + var AA = new ctx.FP8(0); + var BB = new ctx.FP8(0); + var CC = new ctx.FP8(0); + var j, bt; + + var A = new ctx.ECP8(); + A.copy(P); + var MP = new ctx.ECP8(); + MP.copy(P); + MP.neg(); + j = 0; + + var T = []; + for (var i = nb - 2; i >= 1; i--) { + PAIR8.dbl(A, AA, BB, CC); + T[j++] = PAIR8.pack(AA, BB, CC); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + PAIR8.add(A, P, AA, BB, CC); + T[j++] = PAIR8.pack(AA, BB, CC); + } + if (bt == -1) { + PAIR8.add(A, MP, AA, BB, CC); + T[j++] = PAIR8.pack(AA, BB, CC); + } + } + return T; + }, + + /* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */ + another_pc(r, T, QV) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var nb = PAIR8.lbits(n3, n); + var lv, lv2; + var j, bt; + + if (QV.is_infinity()) return; + + var Q = new ctx.ECP(); + Q.copy(QV); + Q.affine(); + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + j = 0; + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR8.unpack(T[j++], Qx, Qy); + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR8.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR8.unpack(T[j++], Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + }, + + /* Accumulate another set of line functions for n-pairing */ + another: function (r, P1, Q1) { + var n = new ctx.BIG(0); + var n3 = new ctx.BIG(0); + var lv, lv2; + var bt; + + if (Q1.is_infinity()) return; + // P is needed in affine form for line function, Q for (Qx,Qy) extraction + var P = new ctx.ECP8(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + P.affine(); + Q.affine(); + + var Qx = new ctx.FP(Q.getx()); + var Qy = new ctx.FP(Q.gety()); + + var A = new ctx.ECP8(); + A.copy(P); + + var MP = new ctx.ECP8(); + MP.copy(P); + MP.neg(); + + var nb = PAIR8.lbits(n3, n); + + for (var i = nb - 2; i >= 1; i--) { + lv = PAIR8.line(A, A, Qx, Qy); + + bt = n3.bit(i) - n.bit(i); + if (bt == 1) { + lv2 = PAIR8.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR8.line(A, MP, Qx, Qy); + lv.smul(lv2); + } + r[i].ssmul(lv); + } + }, + + /* Optimal R-ate pairing */ + ate: function (P1, Q1) { + var n, n3, lv, lv2, Qx, Qy, A, NP, r, nb, bt, i; + + if (Q1.is_infinity()) return new ctx.FP48(1); + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + + var P = new ctx.ECP8(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + A = new ctx.ECP8(); + r = new ctx.FP48(1); + + A.copy(P); + NP = new ctx.ECP8(); + NP.copy(P); + NP.neg(); + + nb = PAIR8.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR8.line(A, A, Qx, Qy); + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv2 = PAIR8.line(A, P, Qx, Qy); + lv.smul(lv2); + } + if (bt == -1) { + lv2 = PAIR8.line(A, NP, Qx, Qy); + lv.smul(lv2); + } + r.ssmul(lv); + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + return r; + }, + + /* Optimal R-ate double pairing e(P,Q).e(R,S) */ + ate2: function (P1, Q1, R1, S1) { + var n, n3, lv, lv2, Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt, i; + + if (Q1.is_infinity()) return PAIR8.ate(R1, S1); + if (S1.is_infinity()) return PAIR8.ate(P1, Q1); + + n = new ctx.BIG(0); + n3 = new ctx.BIG(0); + + var P = new ctx.ECP8(); + P.copy(P1); + P.affine(); + var Q = new ctx.ECP(); + Q.copy(Q1); + Q.affine(); + var R = new ctx.ECP8(); + R.copy(R1); + R.affine(); + var S = new ctx.ECP(); + S.copy(S1); + S.affine(); + + Qx = new ctx.FP(Q.getx()); + Qy = new ctx.FP(Q.gety()); + + Sx = new ctx.FP(S.getx()); + Sy = new ctx.FP(S.gety()); + + A = new ctx.ECP8(); + B = new ctx.ECP8(); + r = new ctx.FP48(1); + + A.copy(P); + B.copy(R); + NP = new ctx.ECP8(); + NP.copy(P); + NP.neg(); + NR = new ctx.ECP8(); + NR.copy(R); + NR.neg(); + + nb = PAIR8.lbits(n3, n); + + for (i = nb - 2; i >= 1; i--) { + r.sqr(); + lv = PAIR8.line(A, A, Qx, Qy); + lv2 = PAIR8.line(B, B, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + + bt = n3.bit(i) - n.bit(i); + + if (bt == 1) { + lv = PAIR8.line(A, P, Qx, Qy); + lv2 = PAIR8.line(B, R, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + if (bt == -1) { + lv = PAIR8.line(A, NP, Qx, Qy); + lv2 = PAIR8.line(B, NR, Sx, Sy); + lv.smul(lv2); + r.ssmul(lv); + } + } + + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + r.conj(); + } + + return r; + }, + + /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ + fexp: function (m) { + var fa, fb, f, x, r, lv; + // t1,t2,t3,t7; + + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + + r = new ctx.FP48(m); //r.copy(m); + + /* Easy part of final exp */ + lv = new ctx.FP48(r); //lv.copy(r); + lv.inverse(); + r.conj(); + r.mul(lv); + lv.copy(r); + r.frob(f, 8); + r.mul(lv); + + /* Hard part of final exp */ + + // See https://eprint.iacr.org/2020/875.pdf + var t0, y0, y1; + y1 = new ctx.FP48(r); + y1.usqr(); + y1.mul(r); // y1=r^3 + + y0 = new ctx.FP48(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0 = new ctx.FP48(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + // ^(x+p) + y0.copy(r.pow(x)); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + y0.conj(); + } + t0.copy(r); + t0.frob(f, 1); + r.copy(y0); + r.mul(t0); + + // ^(x^2+p^2) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f, 2); + r.copy(y0); + r.mul(t0); + + // ^(x^4+p^4) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f, 4); + r.copy(y0); + r.mul(t0); + + // ^(x^8+p^8-1) + y0.copy(r.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + y0.copy(y0.pow(x)); + t0.copy(r); + t0.frob(f, 8); + y0.mul(t0); + t0.copy(r); + t0.conj(); + r.copy(y0); + r.mul(t0); + + r.mul(y1); + r.reduce(); + + /* + // Ghamman & Fouotsa Method + t7=new ctx.FP48(r); t7.usqr(); + + if (x.parity()==1) + { + t2=r.pow(x); + t1=new ctx.FP48(t2); t1.usqr(); + t2=t2.pow(x); + } else { + t1=t7.pow(x); + x.fshr(1); + t2=t1.pow(x); + x.fshl(1); + } + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3=new ctx.FP48(t1); t3.conj(); + t2.mul(t3); + t2.mul(r); + + r.mul(t7); + + t1=t2.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + t3.copy(t1); + t3.frob(f,14); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,13); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,12); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,11); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,10); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,9); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,8); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t2); t3.conj(); + t1.mul(t3); + t3.copy(t1); + t3.frob(f,7); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,6); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,5); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,4); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,3); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,2); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + t3.copy(t1); + t3.frob(f,1); + r.mul(t3); + t1=t1.pow(x); + if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX) { + t1.conj(); + } + + r.mul(t1); + t2.frob(f,15); + r.mul(t2); + + r.reduce(); +*/ + return r; + }, + }; + + /* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */ + PAIR8.lbits = function (n3, n) { + n.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + n3.copy(n); + n3.pmul(3); + n3.norm(); + return n3.nbits(); + }; + + /* GLV method */ + PAIR8.glv = function (e) { + var u = [], + q, + x, + x2; + + // -(x^2).P = (Beta.x,y) + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + x2 = ctx.BIG.smul(x, x); + x = ctx.BIG.smul(x2, x2); + x2 = ctx.BIG.smul(x, x); + u[0] = new ctx.BIG(e); + u[0].mod(x2); + u[1] = new ctx.BIG(e); + u[1].div(x2); + u[1].rsub(q); + + return u; + }; + + /* Galbraith & Scott Method */ + PAIR8.gs = function (e) { + var u = [], + i, + q, + x, + w; + + x = new ctx.BIG(0); + x.rcopy(ctx.ROM_CURVE.CURVE_Bnx); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + w = new ctx.BIG(e); + + for (i = 0; i < 15; i++) { + u[i] = new ctx.BIG(w); + u[i].mod(x); + w.div(x); + } + + u[15] = new ctx.BIG(w); + if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) { + u[1].copy(ctx.BIG.modneg(u[1], q)); + u[3].copy(ctx.BIG.modneg(u[3], q)); + u[5].copy(ctx.BIG.modneg(u[5], q)); + u[7].copy(ctx.BIG.modneg(u[7], q)); + u[9].copy(ctx.BIG.modneg(u[9], q)); + u[11].copy(ctx.BIG.modneg(u[11], q)); + u[13].copy(ctx.BIG.modneg(u[13], q)); + u[15].copy(ctx.BIG.modneg(u[15], q)); + } + + return u; + }; + + /* Multiply P by e in group G1 */ + PAIR8.G1mul = function (P, e) { + var R, Q, q, bcru, cru, t, u, np, nn; + + if (ctx.ROM_CURVE.USE_GLV) { + R = new ctx.ECP(); + R.copy(P); + Q = new ctx.ECP(); + Q.copy(P); + Q.affine(); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + bcru = new ctx.BIG(0); + bcru.rcopy(ctx.ROM_FIELD.CRu); + cru = new ctx.FP(bcru); + t = new ctx.BIG(0); + u = PAIR8.glv(e); + + Q.getx().mul(cru); + + np = u[0].nbits(); + t.copy(ctx.BIG.modneg(u[0], q)); + nn = t.nbits(); + if (nn < np) { + u[0].copy(t); + R.neg(); + } + + np = u[1].nbits(); + t.copy(ctx.BIG.modneg(u[1], q)); + nn = t.nbits(); + if (nn < np) { + u[1].copy(t); + Q.neg(); + } + u[0].norm(); + u[1].norm(); + R = R.mul2(u[0], Q, u[1]); + } else { + R = P.mul(e); + } + + return R; + }; + + /* Multiply P by e in group G2 */ + PAIR8.G2mul = function (P, e) { + var R, Q, F, q, u, t, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_G2) { + Q = []; + F = ctx.ECP8.frob_constants(); + + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + u = PAIR8.gs(e); + t = new ctx.BIG(0); + + Q[0] = new ctx.ECP8(); + Q[0].copy(P); + + for (i = 1; i < 16; i++) { + Q[i] = new ctx.ECP8(); + Q[i].copy(Q[i - 1]); + Q[i].frob(F, 1); + } + + for (i = 0; i < 16; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + Q[i].neg(); + } + u[i].norm(); + } + + R = ctx.ECP8.mul16(Q, u); + } else { + R = P.mul(e); + } + return R; + }; + + /* Note that this method requires a lot of RAM! */ + PAIR8.GTpow = function (d, e) { + var r, g, fa, fb, f, q, t, u, i, np, nn; + + if (ctx.ROM_CURVE.USE_GS_GT) { + g = []; + fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + f = new ctx.FP2(fa, fb); + q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + t = new ctx.BIG(0); + u = PAIR8.gs(e); + + g[0] = new ctx.FP48(d); + + for (i = 1; i < 16; i++) { + g[i] = new ctx.FP48(0); + g[i].copy(g[i - 1]); + g[i].frob(f, 1); + } + + for (i = 0; i < 16; i++) { + np = u[i].nbits(); + t.copy(ctx.BIG.modneg(u[i], q)); + nn = t.nbits(); + + if (nn < np) { + u[i].copy(t); + g[i].conj(); + } + u[i].norm(); + } + + r = ctx.FP48.pow16(g, u); + } else { + r = d.pow(e); + } + + return r; + }; + + /* test G1 group membership */ + PAIR8.G1member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR8.G1mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test G2 group membership */ + PAIR8.G2member = function (P) { + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + if (P.is_infinity()) return false; + var W = PAIR8.G2mul(P, q); + if (!W.is_infinity()) return false; + return true; + }; + /* test group membership - no longer needed */ + /* Check that m!=1, conj(m)*m==1, and m.m^{p^16}=m^{p^8} */ + + PAIR8.GTmember = function (m) { + if (m.isunity()) return false; + var r = new ctx.FP48(m); + r.conj(); + r.mul(m); + if (!r.isunity()) return false; + + var fa = new ctx.BIG(0); + fa.rcopy(ctx.ROM_FIELD.Fra); + var fb = new ctx.BIG(0); + fb.rcopy(ctx.ROM_FIELD.Frb); + var f = new ctx.FP2(fa, fb); + + r.copy(m); + r.frob(f, 8); + var w = new ctx.FP48(r); + w.frob(f, 8); + w.mul(m); + if (!w.equals(r)) return false; + + var q = new ctx.BIG(0); + q.rcopy(ctx.ROM_CURVE.CURVE_Order); + + w.copy(m); + r.copy(PAIR8.GTpow(w, q)); + if (!r.isunity()) return false; + return true; + }; + + return PAIR8; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports.PAIR8 = PAIR8; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/rand.js b/packages/bls-verify/src/vendor/amcl-js/src/rand.js new file mode 100644 index 000000000..5f2932fc7 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/rand.js @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Cryptographic strong random number generator + * + * Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers + * Slow - but secure + * + * See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification + */ + +/* Marsaglia & Zaman Random number generator constants */ + +var RAND = function (ctx) { + 'use strict'; + + var RAND = function () { + /* Cryptographically strong pseudo-random number generator */ + this.ira = []; /* random number... */ + this.rndptr = 0; /* ...array & pointer */ + this.borrow = 0; + this.pool_ptr = 0; + this.pool = []; /* random pool */ + this.clean(); + }; + + RAND.prototype = { + NK: 21, + NJ: 6, + NV: 8, + + /* Terminate and clean up */ + clean: function () { + var i; + + for (i = 0; i < 32; i++) { + this.pool[i] = 0; + } + + for (i = 0; i < this.NK; i++) { + this.ira[i] = 0; + } + + this.rndptr = 0; + this.borrow = 0; + this.pool_ptr = 0; + }, + + sbrand: function () { + /* Marsaglia & Zaman random number generator */ + var i, k, pdiff, t; + + this.rndptr++; + if (this.rndptr < this.NK) { + return this.ira[this.rndptr]; + } + + this.rndptr = 0; + + for (i = 0, k = this.NK - this.NJ; i < this.NK; i++, k++) { + /* calculate next NK values */ + if (k == this.NK) { + k = 0; + } + + t = this.ira[k] >>> 0; + pdiff = (t - this.ira[i] - this.borrow) | 0; + pdiff >>>= 0; /* This is seriously weird shit. I got to do this to get a proper unsigned comparison... */ + + if (pdiff < t) { + this.borrow = 0; + } + + if (pdiff > t) { + this.borrow = 1; + } + + this.ira[i] = pdiff | 0; + } + + return this.ira[0]; + }, + + sirand: function (seed) { + var m = 1, + i, + inn, + t; + + this.borrow = 0; + this.rndptr = 0; + seed >>>= 0; + this.ira[0] ^= seed; + + for (i = 1; i < this.NK; i++) { + /* fill initialisation vector */ + inn = (this.NV * i) % this.NK; + this.ira[inn] ^= m; /* note XOR */ + t = m; + m = (seed - m) | 0; + seed = t; + } + + /* "warm-up" & stir the generator */ + for (i = 0; i < 10000; i++) { + this.sbrand(); + } + }, + + fill_pool: function () { + var sh = new ctx.HASH256(), + i; + + for (i = 0; i < 128; i++) { + sh.process(this.sbrand()); + } + + this.pool = sh.hash(); + this.pool_ptr = 0; + }, + + /* Initialize RNG with some real entropy from some external source */ + seed: function (rawlen, raw) { + /* initialise from at least 128 byte string of raw random entropy */ + var sh = new ctx.HASH256(), + digest = [], + b = [], + i; + + this.pool_ptr = 0; + + for (i = 0; i < this.NK; i++) { + this.ira[i] = 0; + } + + if (rawlen > 0) { + for (i = 0; i < rawlen; i++) { + sh.process(raw[i]); + } + + digest = sh.hash(); + + /* initialise PRNG from distilled randomness */ + for (i = 0; i < 8; i++) { + b[0] = digest[4 * i]; + b[1] = digest[4 * i + 1]; + b[2] = digest[4 * i + 2]; + b[3] = digest[4 * i + 3]; + this.sirand(RAND.pack(b)); + } + } + + this.fill_pool(); + }, + + /* get random byte */ + getByte: function () { + var r = this.pool[this.pool_ptr++]; + + if (this.pool_ptr >= 32) { + this.fill_pool(); + } + + return r & 0xff; + }, + }; + + RAND.pack = function (b) { + /* pack 4 bytes into a 32-bit Word */ + return ((b[3] & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff); + }; + + return RAND; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + RAND: RAND, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/rom_curve.js b/packages/bls-verify/src/vendor/amcl-js/src/rom_curve.js new file mode 100644 index 000000000..dd62b296c --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/rom_curve.js @@ -0,0 +1,2705 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Fixed Data in ROM - Field and Curve parameters */ + +var ROM_CURVE_ANSSI, + ROM_CURVE_BLS12383, + ROM_CURVE_BLS24479, + ROM_CURVE_BLS48556, + ROM_CURVE_BLS48286, + ROM_CURVE_BLS48581, + ROM_CURVE_BLS12381, + ROM_CURVE_BLS12461, + ROM_CURVE_BN462, + ROM_CURVE_FP256BN, + ROM_CURVE_FP512BN, + ROM_CURVE_BN254, + ROM_CURVE_BN254CX, + ROM_CURVE_BRAINPOOL, + ROM_CURVE_C25519, + ROM_CURVE_C41417, + ROM_CURVE_C1174, + ROM_CURVE_C1665, + ROM_CURVE_MDC, + ROM_CURVE_ED25519, + ROM_CURVE_GOLDILOCKS, + ROM_CURVE_X448, + ROM_CURVE_HIFIVE, + ROM_CURVE_NIST256, + ROM_CURVE_NIST384, + ROM_CURVE_NIST521, + ROM_CURVE_NUMS256E, + ROM_CURVE_NUMS256W, + ROM_CURVE_NUMS384E, + ROM_CURVE_NUMS384W, + ROM_CURVE_NUMS512E, + ROM_CURVE_NUMS512W, + ROM_CURVE_SECP256K1, + ROM_CURVE_SECP160R1, + ROM_CURVE_SM2, + ROM_CURVE_C13318, + ROM_CURVE_JUBJUB, + ROM_CURVE_TWEEDLEDUM, + ROM_CURVE_TWEEDLEDEE; + +ROM_CURVE_ANSSI = function () { + var ROM_CURVE_ANSSI = { + // ANSSI curve + + CURVE_Cof_I: 1, + CURVE_B_I: 0, + CURVE_B: [ + 0x7bb73f, 0xed967b, 0x803075, 0xe4b1a1, 0xec0c9a, 0xc00fdf, 0x754a44, 0xd4aba, 0x28a930, + 0x3fca54, 0xee35, + ], + CURVE_Order: [ + 0xd655e1, 0xd459c6, 0x941ffd, 0x40d2bf, 0xdc67e1, 0x435b53, 0xe8ce42, 0x10126d, 0x3ad58f, + 0x178c0b, 0xf1fd, + ], + CURVE_Gx: [ + 0x8f5cff, 0x7a2dd9, 0x164c9, 0xaf98b7, 0x27d2dc, 0x23958c, 0x4749d4, 0x31183d, 0xc139eb, + 0xd4c356, 0xb6b3, + ], + CURVE_Gy: [ + 0x62cfb, 0x5a1554, 0xe18311, 0xe8e4c9, 0x1c307, 0xef8c27, 0xf0f3ec, 0x1f9271, 0xb20491, + 0xe0f7c8, 0x6142, + ], + CURVE_HTPC: [ + 0xa725d0, 0x983e21, 0x349ea8, 0xbb477b, 0x4c66d2, 0x5676b5, 0x119a09, 0xac6dc7, 0x18a3ac, + 0x6d4dfd, 0x7290, + ], + }; + return ROM_CURVE_ANSSI; +}; + +ROM_CURVE_BLS12383 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS12383 = { + // BLS12383 Curve + // Base Bits= 23 + + CURVE_Cof_I: 0, + CURVE_B_I: 15, + CURVE_B: [0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x3c0001, 0x33d7fd, 0x5cec82, 0x9069c, 0x5f095a, 0x703bc0, 0x5a62c, 0x2200e4, 0x3809c0, + 0x1801, 0x8006, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x734573, 0x6e7210, 0x11e311, 0x1fa3b8, 0x5dbf08, 0x688b8a, 0x12bc78, 0x43dd6c, 0x742c2f, + 0x6d6103, 0x4c767d, 0x6d8287, 0x74052d, 0x1c706b, 0x5e7b39, 0x5d2adc, 0x41fc, + ], + CURVE_Gy: [ + 0x3f224, 0x2cbd00, 0x7484b4, 0x43fcc7, 0x7d49ec, 0x25bbca, 0x2b7ad3, 0x29854a, 0x449107, + 0xcd76c, 0x7436b7, 0x6236cc, 0x1cdc31, 0x495d, 0x33ecc0, 0xb393a, 0x68f, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x1200, 0x2, 0x40020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x11ff, 0x2, 0x40020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + //CURVE_Cof: [0x169EAB, 0x2AC2AA, 0x7ED541, 0x555DF, 0x2AAC00, 0xAAB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Pxa: [ + 0x7f2d86, 0x676c5a, 0x7850f2, 0x4ae8e9, 0x7dab67, 0x65dd03, 0x3d5895, 0x3f8e48, 0x725bd4, + 0x10a5aa, 0xc9407, 0xf3a32, 0x967cb, 0x180f32, 0x7b00fa, 0x691203, 0x634, + ], + CURVE_Pxb: [ + 0x52de15, 0x483d88, 0x37bf67, 0x2bff30, 0x4ab28d, 0x3aeb6a, 0x23a4b5, 0x6cc5d4, 0x4c89df, + 0x5b3a0b, 0x13d263, 0x1b0ee9, 0x717288, 0x5e6f4e, 0x592e, 0x3c0030, 0x300d, + ], + CURVE_Pya: [ + 0x8cb41, 0x617728, 0x5971a3, 0x106b0c, 0x1ede4f, 0x5ceb69, 0x2a44e8, 0x4bc1d6, 0x1b3e68, + 0x2ce793, 0x3a643b, 0x31a3db, 0x573fe, 0x79293b, 0x4894d1, 0x167c9e, 0x3379, + ], + CURVE_Pyb: [ + 0x479093, 0xc86fe, 0x18eb61, 0x731124, 0x43cb0d, 0x131602, 0x127def, 0x78597a, 0x7a8f7a, + 0x8d67d, 0x73835, 0x53d700, 0x3a7d15, 0x649dcf, 0x33631a, 0x123ee9, 0x20e5, + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: true, + + //debug: false, + }; + + return ROM_CURVE_BLS12383; +}; + +ROM_CURVE_BLS24479 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS24479 = { + // BLS24479 Curve + // Base Bits= 23 + CURVE_Cof_I: 0, + CURVE_B_I: 19, + CURVE_B: [ + 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + ], + CURVE_Order: [ + 0x1, 0x11ffe0, 0x464068, 0x1ffaa8, 0x71e703, 0x645bb5, 0x379fb8, 0x689d35, 0x49d0ce, 0x49091f, + 0x4a7308, 0x286c0b, 0x3b44a0, 0x60b731, 0x6807c3, 0x8002, 0x10010, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x63ccd4, 0x41ebd7, 0x15919d, 0x576cfa, 0x1efe2d, 0x743f98, 0xfc23a, 0x409a3c, 0x595af8, + 0x6f8df1, 0x38b611, 0x65468d, 0x7e4bfd, 0x6b0d9d, 0x7641d, 0x2eccde, 0xb7fea, 0x5bd3c3, + 0x2be521, 0x71a0be, 0x1ab2b, + ], + CURVE_Gy: [ + 0x1e5245, 0x4b95a4, 0x5b132e, 0x462aef, 0x36d660, 0x672e8d, 0x7b4a53, 0x79e459, 0x24920f, + 0x4828b0, 0x58f969, 0x1d527e, 0x4e00f6, 0x457ef3, 0x66924a, 0x294ffb, 0x66a7a4, 0x70c394, + 0x4f91de, 0x386362, 0x47fcb, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x11ff80, 0x400, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x11ff7f, 0x400, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + //CURVE_Cof: [0x7415AB, 0x7F7FF3, 0x5FFF07, 0x2AB555, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Pxaa: [ + 0x624678, 0x26a6e9, 0x22f8a, 0x212c12, 0x60c343, 0x3df8d3, 0x5d9733, 0x6bfc87, 0x2d2888, + 0x758675, 0x259d1c, 0x7e922c, 0x4bab37, 0x11daab, 0x6214a4, 0x758a55, 0x786671, 0x72b190, + 0x32581d, 0x729d1f, 0x959d, + ], + CURVE_Pxab: [ + 0x3099b8, 0x3d75ff, 0x40e1fe, 0x9523, 0x63775a, 0x78470a, 0x5746c7, 0x7cf1b5, 0x26a730, + 0x14fe14, 0x76ca97, 0x61c7c2, 0x669261, 0x6a7c2f, 0x3e5da9, 0x5f2d68, 0x2d39d1, 0x4a3c98, + 0x4cf7f1, 0x68418b, 0x3b0de, + ], + CURVE_Pxba: [ + 0x2d15d3, 0x1bce23, 0x5bb687, 0x46fb70, 0x185317, 0x47c134, 0x2fd0fa, 0x3597b2, 0x56de56, + 0x165b19, 0x1d3f6e, 0x10e136, 0x76b1ef, 0x1913c7, 0x4011ef, 0x1f994f, 0x3fe210, 0x545186, + 0x41ebca, 0x7d6a72, 0x3ec27, + ], + CURVE_Pxbb: [ + 0x60f480, 0x650ebd, 0x2e31ea, 0x21eb62, 0x14556e, 0x1c3973, 0x48b7e0, 0xffefd, 0x50122f, + 0x55ee1f, 0x263bd7, 0x2ed92b, 0x1ba3ad, 0x39c35e, 0x2dd201, 0x17232e, 0x1da7ce, 0x4cb0aa, + 0x1e67df, 0x46de50, 0xa5b3, + ], + CURVE_Pyaa: [ + 0x781aa0, 0x132628, 0x2ac619, 0x181db8, 0x3609da, 0x3f8897, 0x4a9851, 0x189252, 0x4c42a, + 0x768c5c, 0x66b9a2, 0x1c1d70, 0x4fcadc, 0x69ed7c, 0x7d286c, 0xd685, 0x198f9, 0x459da0, + 0x30250d, 0x1aeb9b, 0x5057f, + ], + CURVE_Pyab: [ + 0x2e08fa, 0x58afdd, 0x5ab6ef, 0x5d52fc, 0x78774, 0x348594, 0x32bc26, 0x23c32, 0x3bccf7, + 0xb913f, 0x3e1549, 0x5b907f, 0x77b3e6, 0x22c6ed, 0x7865fe, 0x3daefb, 0x60f558, 0x702d7a, + 0x3a258d, 0x24b30f, 0x2ce2b, + ], + CURVE_Pyba: [ + 0x70cc41, 0x4ed4b, 0x7d5cc, 0x2a9855, 0x7f8932, 0x5f1428, 0x7361e6, 0x14406c, 0x68a9fe, + 0x21dca7, 0x4dc54e, 0x10783e, 0x71f3a4, 0x3aa336, 0x6c5305, 0x1e5adc, 0x1a39dd, 0x7c73f0, + 0x18c69a, 0x2331f7, 0x18070, + ], + CURVE_Pybb: [ + 0x5c1cae, 0x65cca2, 0x2373c6, 0x2ad84c, 0x2d40d3, 0x714eee, 0x10ff70, 0x3ae561, 0x136b6, + 0x3eba67, 0x75cbf3, 0x327450, 0x161ac1, 0x5cb9a1, 0x2c42ee, 0x48bb8f, 0x56d046, 0x725081, + 0x77b22d, 0x2756cd, 0x499d1, + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: true, + + //debug: false, + }; + + return ROM_CURVE_BLS24479; +}; + +ROM_CURVE_BLS48581 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS48581 = { + // Base Bits= 23 + // Ate Bits= 33 + // G2 Table size= 36 + + CURVE_Cof_I: 0, + CURVE_Cof: [ + 0x382, 0x280, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_B_I: 1, + CURVE_B: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Order: [ + 0x671c01, 0x7cdf9a, 0x46297, 0x3e126d, 0x659946, 0x789997, 0x1588c0, 0x2e3e68, 0x2016a8, + 0x698992, 0x65a74, 0x17373a, 0x3c972c, 0x7f5ad, 0x4f2f80, 0x3d1f85, 0x463538, 0x2b81ad, + 0x733058, 0x7119d4, 0x5e2885, 0x5f1524, 0x8e1, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x5af640, 0xe6462, 0x30ef3a, 0x50f36c, 0x4da5d3, 0x70d96e, 0x5a2c45, 0x62bed9, 0x36ebdb, + 0x3b0b24, 0x611d99, 0x37cb22, 0x46a9df, 0x8aa0a, 0x6e7dd5, 0x5d76ff, 0x761abd, 0xd0d19, + 0x15f83a, 0x6f1f9, 0x693f86, 0x6e7be3, 0x4aebca, 0x561a07, 0x2f59b7, 0x5, + ], + CURVE_Gy: [ + 0x587a70, 0x3bc7c4, 0x5db6ed, 0x5c935a, 0x37aef7, 0x65c6be, 0x21db46, 0x3fbbe1, 0x722f48, + 0x30987d, 0x3d9e1, 0x7729f4, 0x7fb98a, 0x776f7d, 0x5c83bd, 0x4eea0d, 0x699127, 0x5714a5, + 0x4f27bf, 0x24452a, 0x7b398a, 0x6745a3, 0x647e1a, 0x7b298f, 0x6fda44, 0x19, + ], + CURVE_HTPC: [ + 0x1193ec, 0x617c06, 0x10ce4f, 0x203ac1, 0x288964, 0x28c418, 0x2a39c3, 0x76df25, 0x6fd560, + 0x4f7aab, 0x41c1ac, 0x25f766, 0x24a962, 0x2766c2, 0x1ab5f1, 0x2af131, 0x30c7, 0x308b53, + 0xb0b77, 0x5a7353, 0x429389, 0x3153fa, 0x653c17, 0x2ee2d7, 0x2348cd, 0x12, + ], + + CURVE_Bnx: [ + 0x381, 0x280, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Pxaaa: [ + 0x68bfab, 0x216959, 0x7b0d3f, 0x110aa6, 0x797663, 0x2062f6, 0x1247d4, 0x26c0, 0x400503, + 0x40c25e, 0x698f2, 0x462114, 0x3aad1a, 0xdfef3, 0x3c55b1, 0x6d9d17, 0x37de64, 0x9b799, + 0x3f1c0d, 0x75d5df, 0x22775d, 0x6ff48b, 0x128e08, 0x53c38f, 0x5615d9, 0xb, + ], + CURVE_Pxaab: [ + 0x347c57, 0x66cced, 0x7c59a6, 0x57d0a1, 0x556a01, 0x1ffaea, 0x65e58c, 0x63b186, 0x4f0c3, + 0x7f4c4a, 0x529dab, 0x6f8b10, 0xabfe, 0x72874, 0x1fd387, 0x6d0918, 0x1526f6, 0x42c47d, + 0x5b6603, 0x45915d, 0x2bc07e, 0x361d0d, 0x14481a, 0x67112c, 0x44973e, 0xf, + ], + CURVE_Pxaba: [ + 0x5a3e6a, 0x2ad94a, 0x519220, 0x359f85, 0x74cded, 0x3fd51d, 0x6e1e75, 0x465efd, 0x555f02, + 0x61a54d, 0x6b9d9b, 0x49217f, 0x41dbd1, 0xc02c3, 0x2d6ada, 0x2be65d, 0x7a6d69, 0x446f94, + 0x1b2a6b, 0x639d45, 0x3ad83b, 0x5d430a, 0x4d386c, 0xcc789, 0x7ccc70, 0x3, + ], + CURVE_Pxabb: [ + 0x7feafe, 0x67976, 0x7c269c, 0x7405e1, 0xb8cb4, 0x14a462, 0x5f0803, 0x18e292, 0x39468c, + 0x6364f3, 0x3b050e, 0x63bb73, 0x5f63e1, 0x43152, 0x62f833, 0x151c9f, 0x21b7b9, 0x5e7cb0, + 0x616b18, 0x7f47ac, 0x154d4b, 0x1b0025, 0x6171e, 0x12e75b, 0x62218c, 0x17, + ], + CURVE_Pxbaa: [ + 0x78cce5, 0x7438a7, 0x6dce70, 0x64ea65, 0x35f746, 0x5018cb, 0x6226a, 0x56aafe, 0x9274f, + 0x1255cb, 0x42cbbd, 0x4ead60, 0x1e4819, 0x33303f, 0x14e19a, 0x73e2c0, 0x675ff0, 0x2c856a, + 0x1d742c, 0x1803e3, 0x2a9dd6, 0x331c99, 0x44e8f1, 0x59ac, 0xb91c6, 0x7, + ], + CURVE_Pxbab: [ + 0x3c093a, 0x1b2294, 0x43c801, 0x7e719b, 0x160910, 0x12ff8f, 0x5d84bc, 0x2d4f8b, 0x5dd759, + 0x738162, 0x55ed02, 0x44cbf5, 0x3835d2, 0x303bec, 0xdd060, 0x33bdd8, 0x3d1a58, 0x612ef4, + 0x4d773b, 0x47bdc7, 0x6cda08, 0x2623c9, 0x6180fc, 0x3f5839, 0x16c779, 0x19, + ], + CURVE_Pxbba: [ + 0x50e057, 0xfcc0e, 0x539058, 0x2e19a, 0x35b0e2, 0x2c6669, 0x49308b, 0xe5f21, 0x432aad, + 0x3df9e6, 0x7432a9, 0x1e7687, 0x7293b1, 0x39de23, 0x2de912, 0x45d160, 0x36db90, 0x2270a5, + 0x106ce7, 0x3306f5, 0x108aee, 0x2f4931, 0x38fc06, 0x63030f, 0x1b7951, 0x17, + ], + CURVE_Pxbbb: [ + 0x46ae34, 0x3401f7, 0x613867, 0x74be1f, 0x2f2fc9, 0x89cad, 0x3afe7f, 0x3cdeb5, 0x545854, + 0x6fc561, 0x29c642, 0x67f9b2, 0x293f29, 0x3f19f9, 0x4a29fe, 0x20b8cb, 0x211cf7, 0x5e8f6a, + 0x6a77be, 0x58f2eb, 0x74aaa2, 0x4c4989, 0x7b14a0, 0x17d95e, 0x27d5c2, 0x10, + ], + CURVE_Pyaaa: [ + 0x2d7971, 0x27fc9a, 0x4c8fb7, 0x9607f, 0x5012ab, 0x2cb208, 0x5fba9b, 0x4cd5fb, 0x163c15, + 0x5b15ca, 0x43dccd, 0x3ba46c, 0x35afa2, 0x6120c4, 0xd7eaa, 0x4f5fe2, 0x66f3b3, 0x334aef, + 0x508e01, 0x25c8c5, 0x52f302, 0x2e42c8, 0x577e92, 0x361bad, 0x6b5335, 0x1, + ], + CURVE_Pyaab: [ + 0x4d5665, 0x3b726d, 0x44451c, 0x2ffe3d, 0x342352, 0x45cb11, 0x5f5d83, 0x97d04, 0x4e1dd2, + 0x125564, 0x170f46, 0xf8c96, 0x6b243b, 0x75f612, 0x4bf2fc, 0x14b239, 0x3a01d7, 0x64bcdf, + 0x108ae8, 0x615bad, 0x15fcad, 0x4ca630, 0x7c5136, 0x4bcf07, 0x4dc75, 0x5, + ], + CURVE_Pyaba: [ + 0x2a8474, 0x54a4d4, 0x79a0cc, 0x61dc7e, 0x47c46f, 0x44d397, 0x546994, 0x60e9ae, 0x65e2f0, + 0x14652b, 0x4554db, 0x48208a, 0x499d0e, 0x6befab, 0x414511, 0x24069b, 0x119d3a, 0x42dab6, + 0x7140c0, 0x779617, 0x367669, 0x3df6e0, 0x48f908, 0x6e8042, 0x36a201, 0x16, + ], + CURVE_Pyabb: [ + 0x41589d, 0x7b5250, 0x4c5884, 0xf299b, 0x3d8b8a, 0x4af1f6, 0x40fb97, 0x33ded2, 0xba10d, + 0x6e84ee, 0x3b4a05, 0x7d206e, 0x224333, 0x59136, 0x48b49d, 0x738870, 0x3dd8b0, 0x1b9dc4, + 0x7b4cd8, 0x58e166, 0x478762, 0x47f77a, 0x1a208, 0x310f6e, 0x6c25a4, 0x15, + ], + CURVE_Pybaa: [ + 0x650137, 0x63f305, 0xfd1e0, 0x7e7bd2, 0x57fddd, 0x6f6110, 0x651744, 0x21809a, 0x64f59f, + 0x1ca256, 0x78b29, 0x66e745, 0x7fa238, 0x5b0b8e, 0x4a615f, 0x402f88, 0x35a959, 0x7bb27, + 0x71506d, 0x512aa6, 0x288325, 0x207f4b, 0x11a459, 0x111d4e, 0x209d5a, 0x1a, + ], + CURVE_Pybab: [ + 0x10bee4, 0x38b19f, 0x1653bb, 0x13679d, 0x59ed82, 0x6cf3b4, 0x32a9ca, 0x57e0cc, 0x139e3a, + 0x78301a, 0x2093d1, 0x420fb, 0xe8c27, 0x750684, 0x2dd413, 0x7102ad, 0x589d82, 0x2ce456, + 0x359bac, 0x48210d, 0x2d537b, 0x2673ab, 0x5e944f, 0x22b9b5, 0x50d037, 0xf, + ], + CURVE_Pybba: [ + 0x323986, 0x75d5fd, 0x2cf507, 0x6cd531, 0x84017, 0x39993d, 0xe7d4f, 0x5a07d3, 0x618b5b, + 0x18e964, 0x307eae, 0x432791, 0x5ae3a2, 0x731e84, 0x669b7, 0xa7264, 0x64155f, 0x108360, + 0x4d93f0, 0x450037, 0x5d17af, 0x5a0bbf, 0x7a8970, 0x8df32, 0x167678, 0x11, + ], + CURVE_Pybbb: [ + 0x2718b6, 0x7f96e6, 0x57599f, 0x2034e2, 0x2c66e8, 0x6e91cb, 0x12accf, 0x1806c6, 0x205417, + 0x7d8e32, 0x6b40cc, 0xf4bf0, 0xe69c3, 0x26747f, 0x32a6a5, 0x5b77c7, 0x487549, 0x7d1ca1, + 0x3c501a, 0x5af034, 0x4f981, 0x4b80fd, 0x274e4e, 0x7fc481, 0x5e2524, 0x6, + ], + // CURVE_W: [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]], + // CURVE_SB: [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]], + // CURVE_WB: [[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]], + // CURVE_BB: [[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]],[[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0],[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0]]], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + }; + + return ROM_CURVE_BLS48581; +}; + +ROM_CURVE_BN462 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BN462 = { + // Base Bits= 23 + // Ate Bits= 118 + // G2 Table size= 125 + + CURVE_Cof_I: 1, + CURVE_Cof: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + CURVE_B_I: 5, + CURVE_B: [ + 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + CURVE_Order: [ + 0x10800d, 0x600fc0, 0x9006, 0x0, 0x7f7c00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, 0x438403, + 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, 0x202401, + 0x2, + ], + CURVE_Gx: [ + 0x36980d, 0x323e6d, 0x44f263, 0x2e6b80, 0x40372e, 0x4f2473, 0x5a82c7, 0x734d20, 0x31bbb4, + 0x5cd13b, 0xf3d2c, 0x1f6df6, 0x15f63b, 0x4c96df, 0x2e6b24, 0x5180b0, 0x3a34a0, 0x323f5b, + 0x7bc940, 0xd36b3, 0x2, + ], + CURVE_Gy: [ + 0x7b03de, 0x669a6d, 0x2aa295, 0x31176, 0x2c6660, 0x68ea86, 0x3ae03, 0xdc572, 0x777df1, + 0x4dcd5, 0x165941, 0x6bc463, 0x4ccfa7, 0x5b5085, 0x29243b, 0x353a19, 0x2b3367, 0x6f5770, + 0x1183df, 0x8c750, 0x0, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x7fbfff, 0x7fffff, 0x7fffff, 0x7fffff, 0x4001ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Pxa: [ + 0x61e4df, 0x7b2695, 0x551a38, 0x4403b4, 0x26a8b4, 0x5c3e15, 0x3800ca, 0x4dd6c9, 0x1ad269, + 0x10411f, 0x4e0810, 0x6b0e48, 0x1cd96e, 0x66fcf8, 0x520b80, 0x465ee2, 0x338e3a, 0x3b41bf, + 0x216d63, 0x12be66, 0x0, + ], + CURVE_Pxb: [ + 0xcd283, 0x174d55, 0x6dcc42, 0x742874, 0x359bf7, 0x6a15f1, 0x60dc63, 0x72aadb, 0x5d86ba, + 0x630269, 0x210162, 0x6c8bb4, 0x730cbe, 0x4546a8, 0x68f263, 0x24ab35, 0xedca8, 0x22055f, + 0xfa166, 0x69721a, 0x1, + ], + CURVE_Pya: [ + 0x37154e, 0x51be1b, 0x5db96d, 0xebe19, 0x40e7b1, 0x6d2b42, 0x38cb80, 0xe4eed, 0x19a1f4, + 0x21e27, 0x6d0bfa, 0x7d3d35, 0x6e23c3, 0x2c68e0, 0x7b280d, 0x510404, 0x517427, 0x5832f2, + 0xe7688, 0x503282, 0x0, + ], + CURVE_Pyb: [ + 0x22a93a, 0x18aa59, 0x7ae853, 0x1a49dc, 0xd5374, 0x70f54d, 0x13be1c, 0x122250, 0x464769, + 0x7ae4b9, 0x6acdc3, 0x59c9f8, 0x69ac57, 0x3cd618, 0x135135, 0x398319, 0x2c8ae3, 0x17c02e, + 0x2f50e3, 0x39f786, 0x0, + ], + CURVE_W: [ + [ + 0x20003, 0xc0, 0x0, 0x0, 0x7ff000, 0x7e7fef, 0x7fffff, 0x7fffff, 0x17ffff, 0x400c00, 0x1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + CURVE_SB: [ + [ + [ + 0x28004, 0xc0, 0x0, 0x0, 0x7fec00, 0x7e7fee, 0x7fffff, 0x7fffff, 0x17ffff, 0x400c00, 0x1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x11000e, 0x600fc0, 0x9006, 0x0, 0x7f7800, 0xf7ee1, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + ], + [ + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x20003, 0xc0, 0x0, 0x0, 0x7ff000, 0x7e7fef, 0x7fffff, 0x7fffff, 0x17ffff, 0x400c00, 0x1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + ], + CURVE_WB: [ + [ + 0x4000, 0x40, 0x0, 0x0, 0x3ffe00, 0x7f7ffb, 0x7fffff, 0x7fffff, 0x7ffff, 0x400400, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7abffb, 0x1ffc7f, 0x7fffff, 0x7fffff, 0x4029ff, 0x100042, 0x240, 0x0, 0x100000, 0x7f7fff, + 0x7dbfd4, 0x7fffff, 0x7fffff, 0x4800bf, 0x401200, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7d3ffd, 0x4ffe3f, 0x7fffff, 0x7fffff, 0x4015ff, 0x80021, 0x120, 0x0, 0x480000, 0x3fbfff, + 0x7edfea, 0x7fffff, 0x7fffff, 0x24005f, 0x600900, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0xc001, 0x40, 0x0, 0x0, 0x3ffa00, 0x7f7ffa, 0x7fffff, 0x7fffff, 0x7ffff, 0x400400, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + CURVE_BB: [ + [ + [ + 0x7fc000, 0x7fffff, 0x7fffff, 0x7fffff, 0x4001ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7fbfff, 0x7fffff, 0x7fffff, 0x7fffff, 0x4001ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7fbfff, 0x7fffff, 0x7fffff, 0x7fffff, 0x4001ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x11000f, 0x600fc0, 0x9006, 0x0, 0x7f7800, 0xf7ee1, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + ], + [ + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x10c00e, 0x600fc0, 0x9006, 0x0, 0x3f7a00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + [ + 0x10c00d, 0x600fc0, 0x9006, 0x0, 0x3f7a00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + [ + 0x10c00e, 0x600fc0, 0x9006, 0x0, 0x3f7a00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + ], + [ + [ + 0x7f7ffe, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7f7fff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + [ + [ + 0x10c00f, 0x600fc0, 0x9006, 0x0, 0x3f7a00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + [ + 0x11800f, 0x600fc0, 0x9006, 0x0, 0x7f7400, 0xf7ee0, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + [ + 0x7f7ffd, 0x7fffff, 0x7fffff, 0x7fffff, 0x3ff, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x10c00f, 0x600fc0, 0x9006, 0x0, 0x3f7a00, 0xf7ee2, 0x3fd9bf, 0x7ffffb, 0x77ffff, + 0x438403, 0x4a423b, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, + 0x202401, 0x2, + ], + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + }; + + return ROM_CURVE_BN462; +}; + +ROM_CURVE_BLS48556 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS48556 = { + // BLS48556 Curve + // Base Bits= 23 + CURVE_Cof_I: 0, + CURVE_B_I: 17, + CURVE_B: [ + 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Order: [ + 0x1, 0x7e0000, 0x421bff, 0x714ed3, 0x455409, 0x53842, 0x7ac588, 0x7e8a68, 0xad8c1, 0x184da5, + 0x7fb5e2, 0x5e936, 0x5ef479, 0x12b881, 0x46fe3f, 0x32fd85, 0x2973c4, 0x3d260d, 0x318df1, + 0x88d57, 0x3f73ea, 0x1887, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x571d33, 0x5a5ecb, 0x3fca1, 0x7f196f, 0x580554, 0x23dc17, 0x591dc, 0x1987f8, 0x7ca7f6, + 0x345e03, 0x203d9a, 0x1734d, 0x444e07, 0x5602b2, 0x5003e, 0x5961d5, 0x30d242, 0x336bc2, + 0x79241, 0xe0499, 0x7edd74, 0x3b712a, 0x215d65, 0x544f49, 0x9, + ], + CURVE_Gy: [ + 0x6ed83a, 0x367fd4, 0x33da69, 0x254538, 0x5c4b95, 0x2b0cef, 0x7aa39a, 0x47d9c8, 0x677b5f, + 0x4f9e3d, 0x6dc8a6, 0x71c0c7, 0x4b44e2, 0x4aa8f1, 0x4c3099, 0x3071e3, 0x240862, 0x1b9ccf, + 0x579c4, 0x4d1997, 0x3349da, 0x3f5c56, 0x5318b1, 0x56c684, 0x0, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x640020, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x64001f, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + //CURVE_Cof: [0x12ABEB, 0x221EFE, 0x528B, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Pxaaa: [ + 0x23ce4a, 0x5d1d12, 0x74aa34, 0x695c09, 0x3d7102, 0x274419, 0x76284c, 0x69f0b2, 0x4637c1, + 0x5fe3fe, 0x242e62, 0x3f853e, 0x4dd2b3, 0x672bde, 0x6ed92, 0x2b9bad, 0x6c4abf, 0x393882, + 0x32ee21, 0x2ef3a1, 0x59487e, 0x92f4b, 0x26870, 0x32bc6c, 0xe, + ], + CURVE_Pxaab: [ + 0xa1be1, 0x1b8b58, 0x7dc9c7, 0x3beb, 0x28fe3b, 0x72e58b, 0x51e10c, 0x31856a, 0x389247, + 0x15b9fd, 0x2847ea, 0x2e35a0, 0x9b0e7, 0x7f92ce, 0x6960c8, 0xc5821, 0x48632d, 0xc919c, + 0x3c27f4, 0x2a934d, 0x348b6e, 0x2f6b1b, 0x179d2a, 0x4a1009, 0x2, + ], + CURVE_Pxaba: [ + 0xc5dc4, 0x6498ee, 0x4b68e9, 0x6ed677, 0x2964ad, 0x7d8e6d, 0x4d0966, 0x550884, 0x1926ac, + 0x47162d, 0x633555, 0x265962, 0x6402b8, 0x48f745, 0x68195f, 0x198b3a, 0x117ce2, 0x5e9efb, + 0x729335, 0x471f6e, 0x3689ba, 0x3bb4f1, 0x3ddb5c, 0x297f7c, 0xb, + ], + CURVE_Pxabb: [ + 0x64b740, 0x52cd34, 0x578358, 0x464902, 0x11fd49, 0x475ba2, 0x5c150c, 0x436206, 0x335e27, + 0x7cfa66, 0x53ba9f, 0x39e20f, 0x41e3c, 0x30cb43, 0x5e7d7a, 0x4869da, 0x6b405, 0x57b683, + 0x77306a, 0x3e774a, 0x63b1a6, 0x4be47e, 0x764b7f, 0x1c2054, 0x9, + ], + CURVE_Pxbaa: [ + 0x71e01f, 0x18c2e5, 0x26ec, 0x1a5853, 0x4311cd, 0x430f11, 0x43e8e4, 0x20204c, 0x35ab89, + 0x775c07, 0x43202c, 0x442943, 0x1e3472, 0xb1bea, 0x14841d, 0x56a6a1, 0x4e27c3, 0x6ac397, + 0x111e6a, 0x453f3c, 0x449d32, 0x6288f9, 0x7d0633, 0x6f0f7b, 0xd, + ], + CURVE_Pxbab: [ + 0x37383d, 0x70470c, 0x66c28, 0x7ccc3f, 0x220253, 0x27a425, 0x147b57, 0x64a9ae, 0x7a0147, + 0x61ce2b, 0x7620bf, 0x1ceb9b, 0x3f1646, 0x5546dc, 0x12aec8, 0x2a6d46, 0x38885e, 0xa7fd0, + 0x3a2974, 0x7872f1, 0x4f91fb, 0x2ade02, 0x632141, 0x16d9d3, 0x8, + ], + CURVE_Pxbba: [ + 0x11939c, 0x7b67ae, 0x6ba5a0, 0x34d20c, 0x1be51d, 0x65ed81, 0x6d5cb3, 0x6465e6, 0x40b384, + 0x146e44, 0x54f471, 0x119f79, 0x11a9b3, 0x5235b8, 0x342402, 0x6b0380, 0x51a403, 0x22e30f, + 0x1f23ba, 0x468cdf, 0x5a9ccf, 0x77c486, 0x613650, 0x411539, 0xa, + ], + CURVE_Pxbbb: [ + 0x6f4899, 0x2150a, 0x750cb5, 0x4952b2, 0x1c51eb, 0x179378, 0x295e64, 0x5b5457, 0x47a789, + 0x1403f8, 0x62578c, 0x2f5d38, 0x7fe82c, 0x6cff62, 0x32162, 0x3acbe5, 0x1e3000, 0x668f, + 0x426a4b, 0x4f46ed, 0x57a328, 0x62acf0, 0xf705b, 0x7baa3c, 0xd, + ], + CURVE_Pyaaa: [ + 0x137844, 0x2f9f68, 0x4ddb82, 0x4ffa79, 0x44ec64, 0x6d10a3, 0x1beaf1, 0x4b2f5c, 0xb8a71, + 0x20ab1c, 0x225b80, 0x663e7c, 0x673c10, 0x7e8ea9, 0x2fc388, 0x66e9cc, 0x202f56, 0x39587c, + 0x343e8c, 0x52c8bf, 0x6190b, 0x11fb0e, 0x6124d5, 0x337685, 0x7, + ], + CURVE_Pyaab: [ + 0x483190, 0x6491db, 0x424978, 0x23544c, 0x2eaaf4, 0x31a65, 0x48eeb1, 0x7eeb0e, 0x91f2f, + 0x2d992c, 0xf07c, 0x4ae56f, 0x688ed2, 0x62e3a0, 0x284758, 0x15cf7, 0x7e205e, 0x9fa40, + 0x24ea65, 0xce87c, 0x7a1c42, 0x1c4d1d, 0x4f76aa, 0x3ce59c, 0x2, + ], + CURVE_Pyaba: [ + 0x185c0d, 0x3fa083, 0xfa771, 0x50c8ee, 0xd404d, 0x759d3, 0x697d52, 0x6598bc, 0x685c7c, + 0x612d58, 0x160d06, 0x2201f3, 0x5c797c, 0x10c374, 0xe7e1c, 0x52fa00, 0x1f60b0, 0x42b24, + 0x7635e0, 0xdd262, 0x140d61, 0x26a7e6, 0x595fbc, 0x22cde4, 0xd, + ], + CURVE_Pyabb: [ + 0x1d42f8, 0x41502b, 0x5d7dbf, 0x88b12, 0x243afd, 0x3cfe57, 0x4ec3fa, 0x2fb013, 0x7c3cff, + 0x1d3717, 0x79401a, 0x33c434, 0x635f37, 0x29e4f6, 0x2ca2db, 0x7a8ef0, 0x3fd902, 0x3309c9, + 0x1f125b, 0x3ff0c9, 0x7310, 0x3137db, 0x280e0b, 0x70755, 0xa, + ], + CURVE_Pybaa: [ + 0x38039f, 0x25673e, 0x184354, 0x3e78d1, 0xee895, 0x1279f, 0x285016, 0x445c85, 0x4bfe85, + 0x7f8597, 0x2aedd5, 0x2e62f9, 0x32710c, 0x4f5b51, 0x59016c, 0x6178c7, 0x6e268e, 0x2d39ef, + 0x2c36b6, 0x717762, 0x1d1abc, 0x323714, 0x7c7bb9, 0x582324, 0x2, + ], + CURVE_Pybab: [ + 0x5f7865, 0x40de52, 0x20e9a7, 0x7439d3, 0x3f0756, 0x595baf, 0x7cfc76, 0x287b18, 0x56074e, + 0x186679, 0x416ec0, 0x1dc812, 0x127fbe, 0x18d9b5, 0x3c4a9d, 0x1c2bb4, 0x135ca4, 0x7a40ac, + 0x739984, 0x6f008c, 0x7180ea, 0x58af6d, 0x5b4b02, 0x9194c, 0x3, + ], + CURVE_Pybba: [ + 0x4c1979, 0x753ecf, 0x6f0760, 0x3bb13c, 0x4aaf9c, 0x6bfb52, 0x470858, 0x41323d, 0x5401d8, + 0x494404, 0x5ccf5c, 0xbcf06, 0x7e6ecf, 0x5a9c20, 0xd2dff, 0x64ff44, 0x31645b, 0x4ee883, + 0x4e22ec, 0x112445, 0x486c5c, 0x5c8211, 0x67da66, 0x400692, 0xc, + ], + CURVE_Pybbb: [ + 0x49f25b, 0x12ac5f, 0x5d33f2, 0x35d356, 0x2c4f80, 0x3a4c9e, 0x3c5a72, 0x426c74, 0x5dac92, + 0x52c146, 0x61366b, 0x6cde77, 0x5a9e8f, 0x6dff70, 0x6d20e3, 0x5a60e6, 0x33df1a, 0x2afa7, + 0x390f0, 0x6320a2, 0x3f5493, 0x1cc373, 0x174990, 0x7b09b, 0xa, + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: true, + + //debug: false, + }; + + return ROM_CURVE_BLS48556; +}; + +ROM_CURVE_BLS48286 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS48286 = { + // BLS48286 Curve + // Base Bits= 23 + CURVE_Cof_I: 62958, + CURVE_Cof: [0xf5ee, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 10, + CURVE_B: [0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x612c81, 0x2365fa, 0x7ff10, 0x1794b8, 0xf2882, 0x1fc453, 0x253ef9, 0x359315, 0x7c9ede, + 0x602a6b, 0x1af27a, 0x4, 0x0, + ], + CURVE_Gx: [ + 0x5d59e0, 0x7d4612, 0x577225, 0x677dd0, 0x597475, 0x9a33b, 0x50693a, 0x602a23, 0x6c0f04, + 0x11f68e, 0x44836e, 0x39219e, 0x69, + ], + CURVE_Gy: [ + 0x2beb43, 0x53f2e1, 0xbbbbd, 0x2c071f, 0x37ce6b, 0x1583e4, 0x7b94ec, 0x519846, 0x7f979a, + 0x5af112, 0x7995b8, 0x472050, 0x203, + ], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Bnx: [0xf5ef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Pxaaa: [ + 0x6106b5, 0x46930a, 0x3fa105, 0x662660, 0x43b1ce, 0x3ea359, 0x6b2bf6, 0x3d4a96, 0x4caeb, + 0x2544f6, 0x4c71c7, 0x67ea02, 0x22a, + ], + CURVE_Pxaab: [ + 0x6d1a55, 0x237b12, 0x6a77b3, 0x29c48e, 0x277185, 0x6ad728, 0x164bfb, 0x264519, 0xc873e, + 0x4b1a4a, 0x2d7216, 0x5dcccb, 0x18d, + ], + CURVE_Pxaba: [ + 0x57a35e, 0x3474cf, 0xe204, 0x662c53, 0x7af4e8, 0x5e8393, 0x41ad4a, 0x6e0cd2, 0x3de1d4, + 0x62f5c5, 0x7829f0, 0x1496ae, 0xa8, + ], + CURVE_Pxabb: [ + 0x7023e8, 0xa4185, 0x428a3a, 0x799e96, 0x191b5c, 0x45b13e, 0x3d77ed, 0xf392e, 0x1f92e8, + 0x1b1776, 0x7eb253, 0x5f06aa, 0x202, + ], + CURVE_Pxbaa: [ + 0x14cb9b, 0x1ab71e, 0x3622e6, 0x7f12aa, 0x217d62, 0x72d443, 0x5b5546, 0x3e38f7, 0x225964, + 0x45096a, 0x78fdd, 0x139b4d, 0x175, + ], + CURVE_Pxbab: [ + 0x60dd54, 0x650d96, 0x10efda, 0x1b8d12, 0x532b9, 0x7d3817, 0x535f9a, 0x6b1c6a, 0x2d3760, + 0x668d88, 0x7a7567, 0xf5242, 0x110, + ], + CURVE_Pxbba: [ + 0x5776da, 0x361573, 0x7e8829, 0x9089a, 0x657276, 0x5b5754, 0x162f92, 0x26f20a, 0xe4aad, + 0x3f9dec, 0x187f90, 0x37e71, 0xf6, + ], + CURVE_Pxbbb: [ + 0x350a8e, 0x447051, 0x2d7cff, 0x1304e7, 0x7554ef, 0x5934ae, 0x648e87, 0x139670, 0x68c000, + 0x2cd8a2, 0x483465, 0x598734, 0x1f0, + ], + CURVE_Pyaaa: [ + 0x6988be, 0x2bfacf, 0x3b89b3, 0x74bc5e, 0x7e5ef8, 0x1d1663, 0x1513c5, 0x781cd9, 0x38694f, + 0x2af8fe, 0x258b35, 0x7c66d, 0x21f, + ], + CURVE_Pyaab: [ + 0x711b92, 0x2cda1b, 0x21de1, 0xf5e2f, 0x333180, 0x681970, 0x4a7c36, 0xdc200, 0x5e1586, + 0x528744, 0x1bfb5e, 0xe0ff6, 0xe0, + ], + CURVE_Pyaba: [ + 0x7dd06a, 0x74cf57, 0x4951f3, 0x467f2c, 0x3cdab0, 0x571cc9, 0x2a634b, 0x12ad70, 0x335eff, + 0x45b3d7, 0xf5afa, 0x7fdc6, 0x12c, + ], + CURVE_Pyabb: [ + 0xa47f4, 0x3fa6f1, 0x4a2cf7, 0x308359, 0x15f9a3, 0x62afa3, 0x4e1447, 0x1a5942, 0x5d352b, + 0x743bb7, 0x6f7ffc, 0x418f2a, 0x156, + ], + CURVE_Pybaa: [ + 0x639e77, 0x36e68b, 0x132dbb, 0x7ca9c6, 0x48190f, 0x232649, 0x37bc94, 0x6fb23e, 0x74193e, + 0x569ebd, 0x6213, 0x472055, 0x73, + ], + CURVE_Pybab: [ + 0x4975c6, 0x50286c, 0x2c0ca0, 0x654460, 0x624ad9, 0x26e477, 0x436b98, 0x50cb4d, 0x369be1, + 0x7238a0, 0x25b890, 0x2c3b34, 0x136, + ], + CURVE_Pybba: [ + 0x3f2d7c, 0x735783, 0x102f4c, 0x59d512, 0x713ef1, 0x6fe36, 0x2674e, 0x5b0a2d, 0x288f81, + 0xbdc69, 0x450f27, 0x541ba, 0x1fb, + ], + + CURVE_Pybbb: [ + 0x1130a6, 0x41a3ca, 0x76aaa6, 0x1b12a9, 0x39e708, 0xd0fdd, 0x59da9f, 0x76d23, 0x32d633, + 0x342eef, 0x1ab27a, 0x79bc6e, 0x193, + ], + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_BLS48286; +}; + +ROM_CURVE_BLS12381 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS12381 = { + // BLS12381 Curve + // Base Bits= 23 + + CURVE_Cof_I: 0, + CURVE_B_I: 4, + CURVE_B: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x1, 0x7ffe00, 0x7bffff, 0x7ff2df, 0x5a402f, 0xaa77, 0x26876, 0x1cec04, 0x7d4833, 0x26533a, + 0x4fb69d, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x22c6bb, 0x6015b6, 0x3feceb, 0x4bd0d7, 0x5e83ff, 0xb0d8a, 0x45c6eb, 0x271d1f, 0x3905a1, + 0x1f2ee9, 0xda231, 0x4d607e, 0x38c4fa, 0x4d2ac, 0x65f5e5, 0x69d398, 0x17f1, + ], + CURVE_Gy: [ + 0x45e7e1, 0x46528d, 0x1032a8, 0x144457, 0x4c744a, 0x7dba07, 0x4b012c, 0x6d8c65, 0xaf600, + 0x2baba0, 0x73d782, 0x6c5727, 0xed741, 0x3413c6, 0x6aa83c, 0x7a40f1, 0x8b3, + ], + CURVE_HTPC: [ + 0x6821b8, 0x20c57b, 0x6df314, 0x72e2bf, 0x69520e, 0x621116, 0x500ff0, 0x376dee, 0x9ff04, + 0x69291a, 0x4bc077, 0x38ded0, 0x4a9a3d, 0x1b671e, 0x5b2fdd, 0x231645, 0x1f7, + ], + + CURVE_Bnx: [ + 0x10000, 0x0, 0x34804, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x10001, 0x0, 0x34804, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + //CURVE_Cof: [0xAAAB, 0x555600, 0x5A3002, 0x2AAF0A, 0x48C005, 0x72D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Pxa: [ + 0x21bdb8, 0x2d9182, 0x3f5201, 0x402ddf, 0x40326a, 0x2ee175, 0x1eb8f4, 0x2885b2, 0x3b02b4, + 0x29f480, 0x1b91eb, 0x28828e, 0x5272dc, 0x24c100, 0x23c2a4, 0x515978, 0x24a, + ], + CURVE_Pxb: [ + 0x42b7e, 0x7a0aba, 0x5f96b1, 0x1ca2ea, 0x4f1121, 0x92669, 0x771fd4, 0x6d30dd, 0x361ab5, + 0x213241, 0x65af43, 0x3a7b2a, 0x3a0882, 0xfb59a, 0x1c67d8, 0x15b029, 0x13e0, + ], + CURVE_Pya: [ + 0x382801, 0x290c11, 0x27864d, 0x5d6514, 0x2c9cc3, 0x259247, 0x545834, 0x214d34, 0x53a76d, + 0x55197b, 0x37f66e, 0x71a8d5, 0x5c6da2, 0x319939, 0x1f5b84, 0x6a93b9, 0xce5, + ], + CURVE_Pyb: [ + 0x5f79be, 0xebfe0, 0x6aaa4, 0x6760ed, 0x70d275, 0x3567e6, 0x55cba6, 0x3a4955, 0x63af26, + 0x7d0b4e, 0x2cf8a1, 0x145cce, 0x2b02bc, 0x6559a, 0x29cd33, 0x625017, 0x606, + ], + + CURVE_HTPC2: [ + 0x78492b, 0x627501, 0x51f09d, 0x7754d1, 0x45087, 0x32e477, 0x7532db, 0x4f9b0e, 0x5735f4, + 0x5c4ea3, 0x7eb54d, 0x6735a4, 0x48c21e, 0x7203ac, 0x1e011, 0x4c45ce, 0x52, + ], + CURVE_Ad: [ + 0x584c1d, 0x50105a, 0x7d73d0, 0x707cb, 0x36f8da, 0x359312, 0x3bf620, 0x744c0d, 0x66a8d8, + 0x2707dc, 0x43aa61, 0x6a4c15, 0x202c96, 0x67ad27, 0x6e3a50, 0x234c51, 0x14, + ], + CURVE_Bd: [ + 0x172be0, 0x11d31c, 0x174731, 0xb6755, 0x3215a3, 0x5eab44, 0x73bcd7, 0x5ce0a7, 0x4070a0, + 0x61e49e, 0x5b07, 0x7771d9, 0x2e8753, 0x3162, 0x5a200c, 0x484688, 0x12e2, + ], + PC: [ + [ + 0x22d229, 0x745d17, 0x7ea722, 0x3269c8, 0x31b80b, 0x6d1849, 0x70931a, 0x605f8d, 0x37bc23, + 0x7c4590, 0x475e75, 0x6f71e9, 0x62381e, 0x17a3d2, 0x9839c, 0x461247, 0x6e0, + ], + [ + 0x5fb7b, 0x3e7e2c, 0x33299f, 0x6142ef, 0x3771f8, 0xcded3, 0xec52, 0x579b0, 0x7f96d5, + 0x3bccf0, 0x69f733, 0x32d86f, 0x409d25, 0x4e5b1d, 0x7381f8, 0xed03c, 0x1032, + ], + [ + 0x390c9e, 0x20cf7c, 0x65fc90, 0x60193b, 0x10b2ed, 0x6ff463, 0x3d2ec6, 0x318a5d, 0x5c9967, + 0x7418, 0x74bb2e, 0x1c7916, 0x7515d1, 0x5c186, 0x73e9f1, 0xfc70d, 0x169b, + ], + [ + 0x17e317, 0x30d509, 0x55b5c6, 0x35ba74, 0x295f29, 0x3bc9f4, 0x4a3174, 0x62cb64, 0x5574a2, + 0x59cf3e, 0x10edd5, 0x74c86e, 0x33563b, 0xf7216, 0x69e3f1, 0x1e78fc, 0x80d, + ], + [ + 0x70c88e, 0x2c31c7, 0x3e732d, 0x47a3ad, 0x7c8f8c, 0x266736, 0x3c3c9d, 0x416317, 0x4db1a6, + 0x564eb6, 0x55b796, 0xbf299, 0x84d11, 0x5d0e87, 0x6af6f8, 0xf3b80, 0x17b8, + ], + [ + 0x39ed84, 0x644b42, 0x2b775f, 0x82976, 0x25128c, 0x6551b4, 0x3e721a, 0x4710c, 0xce190, + 0x4c9e1f, 0x445618, 0x3295fd, 0x6c38ae, 0x2d46e4, 0x79134a, 0x6b2a9f, 0xd6e, + ], + [ + 0x652983, 0x38cde, 0x67344f, 0x5739e8, 0x70d2dc, 0x721410, 0x25f9a3, 0x69d5c8, 0x799b9e, + 0x7bb2a4, 0x6cf2c5, 0x3a55ae, 0x1bf7a, 0x603a24, 0x5cc4ff, 0x619286, 0x1630, + ], + [ + 0x895d9, 0x19d359, 0x114455, 0xf3be, 0x2286f3, 0x3130b, 0x660beb, 0x3775b2, 0x7b3f08, + 0x3424af, 0x676e65, 0xc72a4, 0x4b3e41, 0x6cc856, 0x667d10, 0x393518, 0xe99, + ], + [ + 0x1b6861, 0x10c83b, 0x4f16ce, 0x18838c, 0x6e25ce, 0x106a66, 0x7c6ccc, 0x599944, 0x3f25f1, + 0x4ad51b, 0x5fd791, 0x2aa096, 0x1d307e, 0x69c0c1, 0x731b6d, 0x738b37, 0x1778, + ], + [ + 0x1edcb0, 0x3f3b59, 0x7f805e, 0x504b94, 0x43e3d2, 0x4b92b1, 0x7b1a38, 0x3c7280, 0x3e568, + 0x6652b3, 0x380c91, 0x54d0de, 0xc5d10, 0x3a209, 0x5d9e3b, 0x2edc, 0xd54, + ], + [ + 0x4b83bb, 0x5de367, 0x5ba0d3, 0x18c61a, 0xf2a6f, 0xd6907, 0x1c347a, 0x32f19e, 0x417f5, + 0x365ed5, 0x705f9d, 0x3d40e3, 0x2b2214, 0x60b117, 0x50eacb, 0x2769f4, 0x1729, + ], + [ + 0x4649b7, 0x2cc4e6, 0x3abab0, 0x17316b, 0xc2d5f, 0x590ac2, 0x336d38, 0x313dab, 0x5ff2, + 0x1145ae, 0x2cc0fa, 0x40ac2b, 0x1dd99, 0x170122, 0x20ccd0, 0x2f958f, 0x11a0, + ], + [ + 0x6cdd0a, 0x9a2d1, 0xb58e, 0x5bc328, 0x74e4b4, 0x2b262, 0x5e3cc7, 0x6fa99c, 0x503776, + 0x5d2def, 0x5a0ad3, 0x2b3407, 0x63eb3a, 0x8edad, 0x7a4ab5, 0x609d5c, 0x95f, + ], + [ + 0x21d641, 0x5874f3, 0x411ddb, 0x5dd21b, 0x26692a, 0x6a070, 0x1fce62, 0x806d3, 0x366b74, + 0x3ae2c2, 0x1fe34, 0x3d1e67, 0x33dafc, 0x4bd241, 0x6953e0, 0x767b56, 0xa10, + ], + [ + 0x4c5a5e, 0x33377b, 0x4c47df, 0x688f16, 0x5b9489, 0xb01f4, 0x7e608b, 0x4b70e6, 0x68a819, + 0x43794, 0x39fd8f, 0x780ccb, 0x5b074c, 0x46167e, 0x592a2c, 0x56154e, 0x14a7, + ], + [ + 0x684a3a, 0x6892dd, 0x33b095, 0x786f03, 0x3b3538, 0x539d4e, 0x18abb7, 0x170398, 0x21894e, + 0x335ea7, 0x5c3d5e, 0x4b390a, 0x463e05, 0x21e7c1, 0x5a4d86, 0x655678, 0x772, + ], + [ + 0x6304a5, 0x73453e, 0x4700b7, 0x211478, 0xd24bc, 0x5ee80, 0x492e26, 0x21de77, 0x2d4d0a, + 0x539d39, 0x655cd7, 0x363749, 0x77f050, 0x2aa721, 0x3999ee, 0x2afc72, 0xe73, + ], + [ + 0x32a21e, 0x72b66a, 0x754e74, 0x79abc0, 0x29ba81, 0x5b537a, 0xcecc1, 0x35a274, 0x62bb8d, + 0x334240, 0x7f7f1d, 0x3d03ef, 0x55f43e, 0x14de3, 0xa452a, 0x70b101, 0x13a8, + ], + [ + 0x462cd8, 0x51271b, 0x104c37, 0x7767ae, 0x6d5243, 0x7a092e, 0x70a35b, 0x665455, 0x655154, + 0x7e2d62, 0x6c2090, 0x75aa2, 0x7ef7c4, 0x590755, 0x62b8bf, 0x2ac0d2, 0x342, + ], + [ + 0x383e19, 0x7374b9, 0x73f308, 0x64a7f6, 0x3d0967, 0x559ad4, 0x2c46b3, 0x532700, 0xcd1fc, + 0x5eb4e3, 0x3e2505, 0x14c8fb, 0x629bff, 0x5026fc, 0x68c897, 0x317f2b, 0xb29, + ], + [ + 0x2b3bff, 0x4edd90, 0x279720, 0x658137, 0x2a8846, 0x6ae27b, 0x23122f, 0x13612c, 0xc01, + 0x1419e1, 0x4107a3, 0x29b1b3, 0x11298e, 0x69168e, 0x556710, 0xd2ef5, 0x1256, + ], + [ + 0x521b1c, 0x73f481, 0x6264f3, 0x71a1ef, 0xd681b, 0xc56ab, 0x5ff22b, 0x4ac430, 0x48ba9c, + 0x1746b6, 0x757bd, 0x1fd378, 0x62f4bd, 0x43165c, 0x3fc66b, 0x46aa46, 0x8ca, + ], + [ + 0x48b604, 0x2d7cd3, 0x5c12d1, 0x7600e3, 0x5027ef, 0x3656cc, 0x256bc0, 0x56ea7d, 0x5a3957, + 0x1f092c, 0x2c6076, 0x7975ae, 0x33b42d, 0x49d4a1, 0x43c0f3, 0x5f274c, 0x15e6, + ], + [ + 0x75224b, 0x3ce2a8, 0x5e19ac, 0x2bcd7d, 0x1049b6, 0x1c8d74, 0x4e5a9f, 0x5587ae, 0x6568d9, + 0x3afd0, 0x799cf6, 0x251fe2, 0x1f748c, 0x20542b, 0x1133c4, 0x14b22f, 0x5c1, + ], + [ + 0x180133, 0x27ebb7, 0x110b67, 0x611953, 0x790ad1, 0x3398d9, 0x4f1019, 0x733196, 0x158013, + 0x101a98, 0x55ecec, 0x18aee3, 0xae7be, 0x6e5f80, 0x47b2a6, 0x51ca56, 0x245, + ], + [ + 0x171ef8, 0x9e017, 0x483530, 0xc908f, 0x51c19, 0x67e0d9, 0x1ed18, 0x138874, 0x308ec0, + 0x54684d, 0x6a9ec4, 0x29fa23, 0x16004f, 0x3a2aa1, 0x6e4e6, 0x165608, 0xb18, + ], + [ + 0x74d8e, 0x1149a0, 0x1b381f, 0x5a26b0, 0x1cdf41, 0x6493b, 0x6447d9, 0x35ff3f, 0x42462e, + 0x7155e1, 0x48d566, 0x176e62, 0x143fed, 0x572318, 0x4dbdb7, 0x354847, 0x18b4, + ], + [ + 0x11c132, 0x6235a0, 0x73a04d, 0x71fdd7, 0x73a5cc, 0x420637, 0x58e279, 0xc1f20, 0x493fd1, + 0x16d95e, 0x34bf2f, 0x1fdc9e, 0x38f1d4, 0x41bfa1, 0x5f346f, 0x1f23c9, 0x1971, + ], + [ + 0x731c30, 0x55d794, 0x3caebe, 0x6a75d3, 0x77055d, 0x77367, 0x347935, 0x4c2f3f, 0x76fe06, + 0x4f22b5, 0x10a832, 0xa511e, 0x5e7ada, 0x244757, 0x61af6d, 0x5d3d08, 0xe1b, + ], + [ + 0x5ba587, 0x1caef7, 0xd80dc, 0x3c303d, 0x65201c, 0x57cd3a, 0x7c832, 0x45b735, 0x426c1e, + 0x2ccf3b, 0x3ceaf4, 0x6d0ddc, 0x6221e4, 0x7d1193, 0x659a12, 0x200c5e, 0x9fc, + ], + [ + 0x70fb29, 0x194630, 0x568579, 0x76ff49, 0x64550f, 0x4c85e, 0x309b21, 0x1c6d3, 0x581ffd, + 0x7fc77b, 0x5c2816, 0x3633a0, 0x6bd2ca, 0x7bd324, 0x4eae1b, 0x646a99, 0x987, + ], + [ + 0x69d6f2, 0x710abf, 0x7b2587, 0x307a0a, 0x7ac24, 0x66e8f5, 0x1358d3, 0x18a09e, 0x4cb52, + 0x1457c3, 0x1d6ee3, 0x4b59e7, 0x7d0277, 0x16592e, 0x6b06ef, 0x5cde7, 0x4ab, + ], + [ + 0x33a5f0, 0x75626c, 0x4a66c8, 0x4ad403, 0x76326c, 0x9c407, 0x4eb555, 0x282e1e, 0x37bd76, + 0x295f5b, 0x529f43, 0x53503, 0x11db8f, 0x44423c, 0x18d2da, 0x1fe520, 0x1660, + ], + [ + 0x68fedb, 0x35d9e5, 0x2106db, 0x4c8205, 0x7f8dc0, 0x5b85dc, 0x84d46, 0x419fe9, 0x50b879, + 0x77c79c, 0x6554db, 0x294e20, 0x7e2a21, 0x6b95e9, 0x783fc4, 0x1fef7, 0x8cc, + ], + [ + 0x65f4cb, 0x38ef61, 0x3298d5, 0x7630ef, 0x5aba9, 0x1f3bc8, 0xc947, 0x7251f6, 0x791c09, + 0x721dd6, 0x50aa9e, 0x233abe, 0x51ad87, 0x2f130e, 0x260708, 0x31bb74, 0x1f8, + ], + [ + 0x2de1f6, 0x44818e, 0xee37f, 0x458029, 0x552162, 0x34fa4d, 0x645003, 0x225f25, 0x1ce2c3, + 0x2cb146, 0x154b8b, 0x5a4ca1, 0x4c86a3, 0x5e9470, 0x259b99, 0x3c35d5, 0xcc, + ], + [ + 0x41c696, 0x4eb45c, 0x7f825f, 0x317d45, 0x567119, 0x269ad8, 0x7ad9eb, 0x4831a1, 0x383d0f, + 0x584a9e, 0x488fa5, 0x5a3418, 0x6d776f, 0x3aa206, 0x3b9604, 0x4b5082, 0x1349, + ], + [ + 0x7bb33, 0xae32e, 0xafa61, 0x59dd1e, 0x47aee9, 0x7a79a1, 0x255950, 0x2957b6, 0x69522b, + 0x1c9150, 0x46b44e, 0x6e7d0, 0x709498, 0x4b3a3, 0x6893b8, 0x4be40d, 0x90d, + ], + [ + 0x634b8f, 0xe743a, 0x11055, 0x9a4bc, 0x2f570f, 0x440b94, 0xd5b2a, 0x277e6b, 0x385332, + 0x4bc4e7, 0x47103d, 0x40ce0b, 0x55e0d7, 0x4d6484, 0x37700f, 0x50ec0b, 0xe0f, + ], + [ + 0x6d06f7, 0x38264d, 0x347eb, 0x38a664, 0x517bd8, 0x1c840, 0x1e5092, 0x3a46f9, 0x27c1cb, + 0x29ce52, 0x7d596e, 0x6bb795, 0x50d53c, 0x6c517b, 0x4b93ce, 0x20075, 0x266, + ], + [ + 0x3345cc, 0x6270ae, 0x47a66, 0x1dc856, 0x763e, 0x70d260, 0x680366, 0x2e777c, 0x2267d, + 0x3315be, 0x50cd1b, 0x78a4b2, 0x144b45, 0x786c26, 0x1d9ff8, 0x5ca8a6, 0xad6, + ], + [ + 0x561092, 0x6a53c4, 0x2a5a12, 0x7bf5df, 0x168986, 0x26a2df, 0x33a9e4, 0x7cd44, 0x42d28c, + 0x15df9c, 0x7e53fe, 0x28623b, 0x41e48c, 0x7eb0a5, 0x740cf, 0x5db3a4, 0xacc, + ], + [ + 0xf6aa8, 0x693975, 0x1003e2, 0x7c1830, 0x5c29f4, 0x390e34, 0x398da9, 0x2c8d9b, 0x26290e, + 0x7376c3, 0x71b740, 0x1488ec, 0xa01ad, 0x291e02, 0x29016f, 0x792cf7, 0x4d2, + ], + [ + 0x113f55, 0x691771, 0x78d1bb, 0x294d9a, 0x5ea3d, 0x1f78e7, 0x1fa9f5, 0x42c97, 0x7bb53, + 0x47c27b, 0x485bdd, 0x542481, 0x597d94, 0x1d5040, 0x429b87, 0x2ae6d3, 0x167a, + ], + [ + 0x535d4a, 0x7b3aaa, 0xdac8c, 0x5c9244, 0x7e2f7b, 0x690a59, 0x12fce6, 0x62ba86, 0x5920ab, + 0x498d5e, 0x67ec33, 0x3a6627, 0x54fd1d, 0x63437c, 0x5b1848, 0x647699, 0x1866, + ], + [ + 0x12ed9, 0x2b42b, 0x1183b9, 0x400ef7, 0xf5b00, 0x265724, 0x18d5c, 0x59a7e9, 0x4fd7fe, + 0x3df43e, 0x1690dd, 0x37fb77, 0x5fabba, 0x40779b, 0xfa9fa, 0x77845f, 0x16a3, + ], + [ + 0x6a775c, 0x273224, 0x64f468, 0x2c58fd, 0x29c01a, 0xa3abf, 0x100280, 0x69b2de, 0x78ef5d, + 0x751a19, 0x7bb3f7, 0x4c125a, 0x734ace, 0x787750, 0x2676cb, 0x3e045, 0x1660, + ], + [ + 0x79b7ac, 0xeff55, 0x80b19, 0x7d4e67, 0x38db9d, 0x4c893e, 0x5bc3d6, 0x766c3d, 0x5881c5, + 0xcaaa1, 0x5c054b, 0x418c15, 0x6eaac7, 0x33f64c, 0x61b6cb, 0x7294b8, 0x8d9, + ], + [ + 0x25001d, 0x284623, 0x3768e4, 0x7e976f, 0x315dc0, 0x22d441, 0x7277b2, 0x176d07, 0x3bb054, + 0x3e1ed3, 0x1b4672, 0x146ee6, 0x112f82, 0x160199, 0x17d0f9, 0x703caa, 0xbe0, + ], + [ + 0x5f5416, 0x5b3088, 0x36a349, 0x1414bd, 0x364f2c, 0x682e4e, 0x79c9ab, 0x1ed244, 0x530e12, + 0x37bb79, 0x445717, 0x6da68e, 0x3bf89e, 0x3e41a4, 0x6394e5, 0x69443c, 0x16b7, + ], + [ + 0x3f67f2, 0x716a7b, 0x247894, 0x37cb7c, 0x57cd63, 0x5d94ce, 0x49e734, 0x1ad2ee, 0x7f310c, + 0x2aa35c, 0x631215, 0x758abb, 0x67d6e8, 0x6df555, 0x103689, 0x799833, 0x58d, + ], + [ + 0x49a03d, 0x20585c, 0x54cbd8, 0x1a94f1, 0x426076, 0x3ef14, 0x3d14f8, 0x5081ab, 0x559ca4, + 0x6e6389, 0x17213f, 0x1a45c4, 0x56c43c, 0x434197, 0x604807, 0x6bae11, 0x1962, + ], + [ + 0x3663c1, 0x24a760, 0x34051e, 0x306103, 0x3688ef, 0x4f40fe, 0x56f9cb, 0x619195, 0xbe6ee, + 0x4af130, 0x69b7, 0x7574b, 0x140fad, 0x4a4302, 0x27262c, 0x16261d, 0x1611, + ], + ], + CURVE_Adr: [ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Adi: [ + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Bdr: [ + 0x3f4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Bdi: [ + 0x3f4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + PCR: [ + [ + 0x2a5ed1, 0x555555, 0x46238a, 0x7b38e3, 0xe38d0, 0x2eae13, 0x450ae1, 0x6b0847, 0x10aa22, + 0x4fe9d0, 0x2c52d3, 0x7db0a6, 0x2691f5, 0x5dadbd, 0xe333e, 0x32a0fd, 0x171d, + ], + [ + 0x7fc71e, 0x7fffff, 0x549aa7, 0x5c6aaa, 0x2aaa9c, 0x3028e, 0x53c829, 0x104635, 0xc7f9a, + 0x5bef5c, 0x613e1e, 0x3e447c, 0x7ced78, 0x6424d, 0x6aa66f, 0x5f8bd, 0x1156, + ], + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x2a97d6, 0x555555, 0x7188e2, 0x1ece38, 0x638e34, 0x2bab84, 0x7142b8, 0x5ac211, 0x42a88, + 0x73fa74, 0x4b14b4, 0x3f6c29, 0x29a47d, 0x576b6f, 0x238ccf, 0x2ca83f, 0x5c7, + ], + [0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x718b10, 0x638e38, 0x6786cd, 0x36e25e, 0x1097a5, 0xa49cf, 0x26a89d, 0x74bbe3, 0x6286b0, + 0x6f43c4, 0x586c3c, 0x8d683, 0x43de38, 0x7f7ee0, 0x5b3de6, 0x4d6a1d, 0x124c, + ], + [ + 0x7fc71c, 0x7fffff, 0x549aa7, 0x5c6aaa, 0x2aaa9c, 0x3028e, 0x53c829, 0x104635, 0xc7f9a, + 0x5bef5c, 0x613e1e, 0x3e447c, 0x7ced78, 0x6424d, 0x6aa66f, 0x5f8bd, 0x1156, + ], + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x46d706, 0xe38e3, 0x204b3f, 0x46497b, 0x425ebf, 0x201f91, 0x1f49f9, 0x221cec, 0x649bf5, + 0x2940fe, 0x3df697, 0x688c98, 0x18b076, 0x6b3498, 0x2d044e, 0x23be3d, 0x1530, + ], + [0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x7fa8fb, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + ], + PCI: [ + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x7fe38d, 0x7fffff, 0x2a4d53, 0x2e3555, 0x15554e, 0x418147, 0x69e414, 0x8231a, 0x63fcd, + 0x2df7ae, 0x309f0f, 0x1f223e, 0x7e76bc, 0x432126, 0x755337, 0x2fc5e, 0x8ab, + ], + [ + 0x7fc71a, 0x7fffff, 0x549aa7, 0x5c6aaa, 0x2aaa9c, 0x3028e, 0x53c829, 0x104635, 0xc7f9a, + 0x5bef5c, 0x613e1e, 0x3e447c, 0x7ced78, 0x6424d, 0x6aa66f, 0x5f8bd, 0x1156, + ], + [ + 0x2a97d6, 0x555555, 0x7188e2, 0x1ece38, 0x638e34, 0x2bab84, 0x7142b8, 0x5ac211, 0x42a88, + 0x73fa74, 0x4b14b4, 0x3f6c29, 0x29a47d, 0x576b6f, 0x238ccf, 0x2ca83f, 0x5c7, + ], + [ + 0x7faa9f, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + [ + 0x7faa63, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x7fe38f, 0x7fffff, 0x2a4d53, 0x2e3555, 0x15554e, 0x418147, 0x69e414, 0x8231a, 0x63fcd, + 0x2df7ae, 0x309f0f, 0x1f223e, 0x7e76bc, 0x432126, 0x755337, 0x2fc5e, 0x8ab, + ], + [ + 0x2a97be, 0x555555, 0x7188e2, 0x1ece38, 0x638e34, 0x2bab84, 0x7142b8, 0x5ac211, 0x42a88, + 0x73fa74, 0x4b14b4, 0x3f6c29, 0x29a47d, 0x576b6f, 0x238ccf, 0x2ca83f, 0x5c7, + ], + [ + 0x46d706, 0xe38e3, 0x204b3f, 0x46497b, 0x425ebf, 0x201f91, 0x1f49f9, 0x221cec, 0x649bf5, + 0x2940fe, 0x3df697, 0x688c98, 0x18b076, 0x6b3498, 0x2d044e, 0x23be3d, 0x1530, + ], + [ + 0x7faa99, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + [ + 0x7fa9d3, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + [ + 0x7fa8fb, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_BLS12381; +}; + +ROM_CURVE_BLS12461 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BLS12461 = { + // BLS12461 Curve + // Base Bits= 23 + + CURVE_Cof_I: 0, + CURVE_B_I: 9, + CURVE_B: [ + 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + CURVE_Order: [ + 0x1, 0x0, 0x700000, 0x7f7fff, 0x7feff, 0x22000, 0x7f2000, 0x7e00bf, 0xe801, 0x40bfa0, 0x5ff, + 0x7fe00c, 0x7fff7f, 0x1ff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Gx: [ + 0x5ee93d, 0x4d515, 0x504534, 0x773a5b, 0x2d9c00, 0x6358fe, 0x6606d4, 0x4114e1, 0x4dc921, + 0x21a6ac, 0x282599, 0x7be149, 0x436166, 0x45632e, 0x1a2fa4, 0x38967b, 0xc8132, 0x476e74, + 0x3a66d1, 0x56873a, 0x0, + ], + CURVE_Gy: [ + 0x51d465, 0x462af5, 0x51c3dd, 0x64627f, 0x517884, 0x71a42b, 0x6799a, 0x2ce854, 0x245f49, + 0x15cb86, 0x2e1244, 0x45fd20, 0x16eecb, 0x3f197d, 0x3322fe, 0x1793bd, 0x5f1c3f, 0x3ed192, + 0x452cc1, 0x3bde6d, 0x0, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x0, 0x7ffc00, 0x7fffef, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x1, 0x7ffc00, 0x7fffef, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + ], + //CURVE_Cof: [0x2AAAAB, 0x7FFD55, 0x5AAA9F, 0x5580AA, 0x7D55AA, 0x2A9FFF, 0x5555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Pxa: [ + 0x50a37c, 0x20630d, 0x31196d, 0x173aee, 0x1c2e49, 0x2d0f15, 0x7e467, 0x7ab270, 0x74ff92, + 0x610db6, 0x19a00f, 0x36ac0d, 0x6d78d4, 0x78520f, 0x224be5, 0x1e1386, 0x767945, 0x4a1535, + 0x4e281a, 0x662a0, 0x1, + ], + CURVE_Pxb: [ + 0x41c0ad, 0x395185, 0x37a7e1, 0x6212e5, 0x16cd66, 0x4512c1, 0x4a546, 0x200d63, 0x3ebee2, + 0x7aa535, 0x7d96c5, 0x504e99, 0x45af5b, 0x6e3da9, 0x4b9350, 0x123533, 0x2279d2, 0x1d46f9, + 0x53f96b, 0x4ae0fd, 0x0, + ], + CURVE_Pya: [ + 0x2fb006, 0x218360, 0xcdf33, 0x525095, 0x53d194, 0x125912, 0x5833f3, 0x6345a4, 0xf39f, + 0x1e7536, 0x7b46e8, 0x3edde2, 0x4dfd8a, 0x5ef53, 0x3489f3, 0x7a739f, 0x6070f4, 0x74fcce, + 0x1239fa, 0x113564, 0x0, + ], + CURVE_Pyb: [ + 0x71457c, 0xd5bfb, 0x2a294, 0x6e0261, 0x4d6a31, 0x6dc7f6, 0x26a3c4, 0x2b3475, 0x64492f, + 0x2e7877, 0x19e84a, 0x25f55d, 0x220be7, 0x5c70ad, 0x7c1310, 0x228ab, 0x2ab1d0, 0x6805d4, + 0x6d3eae, 0x71c080, 0x0, + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_BLS12461; +}; + +ROM_CURVE_FP256BN = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_FP256BN = { + // FP256BN Curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_B_I: 3, + CURVE_B: [0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0xb500d, 0x536cd1, 0x1af62d, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + CURVE_Gx: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Gy: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Bnx: [0xb0a801, 0xf5c030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Pxa: [ + 0xc09efb, 0x16b689, 0x3cd226, 0x12bf84, 0x1c539a, 0x913ace, 0x577c28, 0x28560f, 0xc96c20, + 0x3350b4, 0xfe0c, + ], + CURVE_Pxb: [ + 0x7e6a2b, 0xed34a3, 0x89d269, 0x87d035, 0xdd78e2, 0x13b924, 0xc637d8, 0xdb5ae1, 0x8ac054, + 0x605773, 0x4ea6, + ], + CURVE_Pya: [ + 0xdc27ff, 0xb481be, 0x48e909, 0x8d6158, 0xcb2475, 0x3e51ef, 0x75124e, 0x76770d, 0x42a3b3, + 0x46e7c5, 0x7020, + ], + CURVE_Pyb: [ + 0xad049b, 0x81114a, 0xb3e012, 0x821a98, 0x4cbe80, 0xb29f8b, 0x49297e, 0x42eea6, 0x88c290, + 0xe3bcd3, 0x554, + ], + + CURVE_W: [ + [0x54003, 0x36e1b, 0x663af0, 0xfffe78, 0xffffff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_SB: [ + [ + [0x669004, 0xeeee7c, 0x670bf5, 0xfffe78, 0xffffff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x6100a, 0x4ffeb6, 0xb4bb3d, 0x129b19, 0xdc65fb, 0xa49d0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + ], + ], + CURVE_WB: [ + [0x30a800, 0x678f0d, 0xcc1020, 0x5554d2, 0x555555, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x7dc805, 0x764c0d, 0xad1ad6, 0xa10bc3, 0xde8fbe, 0x104467, 0x806160, 0xd105eb, 0x0, 0x0, + 0x0, + ], + [ + 0x173803, 0xb6061f, 0xd6c1ac, 0x5085e1, 0xef47df, 0x82233, 0xc030b0, 0x6882f5, 0x0, 0x0, + 0x0, + ], + [0x91f801, 0x530f6e, 0xcce126, 0x5554d2, 0x555555, 0x55, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_BB: [ + [ + [ + 0x5aa80d, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [ + 0x5aa80c, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [ + 0x5aa80c, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [0x615002, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x5aa80c, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [ + 0x5aa80d, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [ + 0x5aa80c, 0x5daca0, 0x1a8daa, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + ], + [ + [0x615002, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x615001, 0xeb8061, 0xd105, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0xb0a802, 0xf5c030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0xc2a002, 0xd700c2, 0x1a20b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0xaa000a, 0x67ec6f, 0x1a2527, 0x129992, 0xdc65fb, 0xa49e0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + [0xb0a802, 0xf5c030, 0x6882, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_FP256BN; +}; + +ROM_CURVE_FP512BN = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_FP512BN = { + // FP512BN Curve + + // Base Bits= 23 + + CURVE_Cof_I: 1, + CURVE_B_I: 3, + CURVE_B: [ + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Order: [ + 0x1a09ed, 0x14bea3, 0x501a99, 0x27cd15, 0x313e0, 0x346942, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + CURVE_Gx: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Gy: [ + 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + + CURVE_Bnx: [ + 0x1bd80f, 0xd76bc, 0x4042cc, 0x587bf, 0x2f5c03, 0xd10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Cof: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + + CURVE_Pxa: [ + 0x3646b5, 0x52dc1b, 0x7a3c1e, 0x48397f, 0xf8731, 0x71e443, 0x6f2ef1, 0x2bdf10, 0x4dc6dc, + 0x70c6a2, 0x40914d, 0x3c6685, 0x5a57cc, 0x3736af, 0x4d63c3, 0x5de94d, 0x6a1e4b, 0x25e79, + 0x6e9d, 0x244ac4, 0x1e1386, 0x62ca67, 0xe, + ], + CURVE_Pxb: [ + 0xae0e9, 0x17dfb5, 0x6cf6d7, 0x6c4488, 0x4a411c, 0x5b9c81, 0x4e0f56, 0x286b70, 0x6e0d5e, + 0x650aa4, 0x607889, 0x5ca6cb, 0x302566, 0x48ed51, 0x1b1bbc, 0x532b6e, 0x34825e, 0x157d1, + 0x6d311a, 0x3f3644, 0x3f8506, 0x38279, 0x12, + ], + CURVE_Pya: [ + 0x5e67a1, 0x6255b, 0x178920, 0xaf7dc, 0x217ad6, 0x778b9b, 0xa022d, 0x11892a, 0x3e8edd, + 0x7bd82a, 0x5b3462, 0x34cea5, 0x65c158, 0x1ba07d, 0x5982bf, 0x42d8ef, 0x4f2770, 0x19746e, + 0x3bd6ac, 0x3dc149, 0x4c827c, 0x603d90, 0x1b, + ], + CURVE_Pyb: [ + 0x4f8e8b, 0x630d90, 0x5a162d, 0x25fbb0, 0x5c222, 0x11bfe, 0x7b89e7, 0x18856b, 0x714a4, + 0x7c5ca, 0xa25ff, 0xca0ed, 0x3d0496, 0x61936c, 0x46219e, 0xa1c60, 0x591f02, 0x62beeb, 0xd9030, + 0x3c18d6, 0x48b04e, 0x34779d, 0x14, + ], + CURVE_W: [ + [ + 0x34583, 0x712e93, 0x4fc443, 0x68b50b, 0x5fb911, 0x47fd2c, 0x7fff3d, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + CURVE_SB: [ + [ + [ + 0x4b9564, 0x56411a, 0x4f3eab, 0x5da58c, 0x1010b, 0x47e30c, 0x7fff3d, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x6259ce, 0x79d12a, 0x4f9500, 0x1cbd96, 0x245bda, 0x344f21, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ], + [ + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x34583, 0x712e93, 0x4fc443, 0x68b50b, 0x5fb911, 0x47fd2c, 0x7fff3d, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + ], + CURVE_WB: [ + [ + 0x5a29f0, 0x66d56a, 0x305b6a, 0x2c1e98, 0x442c60, 0x42bf7f, 0x555514, 0x2aaaaa, 0x555555, + 0x2aaaaa, 0x555555, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x355d4b, 0x25744, 0x45fbac, 0x6bfc27, 0x20fc1f, 0x6bcb9e, 0x2778ae, 0x2c497d, 0x5ad40f, + 0x72c0c9, 0x4549d2, 0x29a8b1, 0x576bc3, 0x42cc1, 0x587bf8, 0x75c030, 0xd105, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + ], + [ + 0x289aad, 0x7e700, 0x431f3c, 0x38c1f3, 0x282c11, 0x35ec57, 0x53bc57, 0x5624be, 0x6d6a07, + 0x396064, 0x62a4e9, 0x54d458, 0x6bb5e1, 0x21660, 0x2c3dfc, 0x7ae018, 0x6882, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + ], + [ + 0x2279d1, 0x4be7f2, 0x2fd5d2, 0x210f19, 0x65745a, 0x42a55e, 0x555514, 0x2aaaaa, 0x555555, + 0x2aaaaa, 0x555555, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + CURVE_BB: [ + [ + [ + 0x1bd810, 0xd76bc, 0x4042cc, 0x587bf, 0x2f5c03, 0xd10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x1bd80f, 0xd76bc, 0x4042cc, 0x587bf, 0x2f5c03, 0xd10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x1bd80f, 0xd76bc, 0x4042cc, 0x587bf, 0x2f5c03, 0xd10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x6259cf, 0x79d12a, 0x4f9500, 0x1cbd96, 0x245bda, 0x344f21, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ], + [ + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7e31de, 0x747e6, 0xfd7cd, 0x224556, 0x53b7dd, 0x345c31, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + [ + 0x7e31dd, 0x747e6, 0xfd7cd, 0x224556, 0x53b7dd, 0x345c31, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + [ + 0x7e31de, 0x747e6, 0xfd7cd, 0x224556, 0x53b7dd, 0x345c31, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ], + [ + [ + 0x37b01e, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x37b01f, 0x1aed78, 0x8598, 0xb0f7f, 0x5eb806, 0x1a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + ], + [ + [ + 0x7e31df, 0x0747e6, 0x0fd7cd, 0x224556, 0x53b7dd, 0x345c31, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + [ + 0x2aa9af, 0x5ee3b2, 0x4f0f68, 0x11ae17, 0x45a3d4, 0x343500, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + [ + 0x37b01d, 0x1aed78, 0x008598, 0x0b0f7f, 0x5eb806, 0x001a20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + [ + 0x7e31df, 0x0747e6, 0x0fd7cd, 0x224556, 0x53b7dd, 0x345c31, 0x2ac99e, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a22, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_FP512BN; +}; + +ROM_CURVE_BN254 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BN254 = { + // BN254 Curve + + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_B_I: 2, + CURVE_B: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0xd, 0x0, 0x10a100, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523, + ], + CURVE_Gx: [ + 0x12, 0x0, 0x13a700, 0x0, 0x210000, 0x861, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523, + ], + CURVE_Gy: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Bnx: [0x1, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Pxa: [ + 0x3fb2b, 0x4224c8, 0xd91ee, 0x4898bf, 0x648bbb, 0xedb6a4, 0x7e8c61, 0xeb8d8c, 0x9eb62f, + 0x10bb51, 0x61a, + ], + CURVE_Pxb: [ + 0xd54cf3, 0x34c1e7, 0xb70d8c, 0xae3784, 0x4d746b, 0xaa5b1f, 0x8c5982, 0x310aa7, 0x737833, + 0xaaf9ba, 0x516, + ], + CURVE_Pya: [ + 0xcd2b9a, 0xe07891, 0xbd19f0, 0xbdbe09, 0xbd0ae6, 0x822329, 0x96698c, 0x9a90e0, 0xaf9343, + 0x97a06b, 0x218, + ], + CURVE_Pyb: [ + 0x3ace9b, 0x1aec6b, 0x578a2d, 0xd739c9, 0x9006ff, 0x8d37b0, 0x56f5f3, 0x8f6d44, 0x8b1526, + 0x2b0e7c, 0xebb, + ], + CURVE_W: [ + [0x3, 0x0, 0x20400, 0x0, 0x818000, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_SB: [ + [ + [0x4, 0x0, 0x28500, 0x0, 0x818000, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0xa, 0x0, 0xe9d00, 0x0, 0x1e0000, 0x79e, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + ], + ], + CURVE_WB: [ + [0x0, 0x0, 0x4080, 0x0, 0x808000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x5, 0x0, 0x54a80, 0x0, 0x70000, 0x1c7, 0x800000, 0x312241, 0x0, 0x0, 0x0], + [0x3, 0x0, 0x2c580, 0x0, 0x838000, 0xe3, 0xc00000, 0x189120, 0x0, 0x0, 0x0], + [0x1, 0x0, 0xc180, 0x0, 0x808000, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_BB: [ + [ + [0xd, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0xc, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0xc, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0x2, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0xc, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0xd, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0xc, 0x0, 0x106080, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + ], + [ + [0x2, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x1, 0x0, 0x8100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x2, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x2, 0x0, 0x10200, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0xa, 0x0, 0x102000, 0x0, 0x9f8000, 0x7ff, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + [0x2, 0x0, 0x4080, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_BN254; +}; + +ROM_CURVE_BN254CX = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_BN254CX = { + // BN254CX Curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_B_I: 2, + CURVE_B: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0xeb1f6d, 0xc0a636, 0xcebe11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, 0x8, + 0x2400, + ], + CURVE_Gx: [ + 0x1b55b2, 0x23ef5c, 0xe1be66, 0x18093e, 0x3fd6ee, 0x66d324, 0x647a63, 0xb0bddf, 0x702a0d, 0x8, + 0x2400, + ], + CURVE_Gy: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Bnx: [0xc012b1, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + + CURVE_Pxa: [ + 0xd2ec74, 0x1ceee4, 0x26c085, 0xa03e27, 0x7c85bf, 0x4bbb90, 0xf5c3, 0x358b25, 0x53b256, + 0x2d2c70, 0x1968, + ], + CURVE_Pxb: [ + 0x29cfe1, 0x8e8b2e, 0xf47a5, 0xc209c3, 0x1b97b0, 0x9743f8, 0x37a8e9, 0xa011c9, 0x19f64a, + 0xb9ec3e, 0x1466, + ], + CURVE_Pya: [ + 0xbe09f, 0xfcebcf, 0xb30cfb, 0x847ec1, 0x61b33d, 0xe20963, 0x157dae, 0xd81e22, 0x332b8d, + 0xedd972, 0xa79, + ], + CURVE_Pyb: [ + 0x98ee9d, 0x4b2288, 0xebed90, 0x69d2ed, 0x864ea5, 0x3461c2, 0x512d8d, 0x35c6e4, 0xc4c090, + 0xc39ec, 0x616, + ], + + CURVE_W: [ + [0x2feb83, 0x634916, 0x120054, 0xb4038, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_SB: [ + [ + [0xb010e4, 0x63491d, 0x128054, 0xb4038, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0xbb33ea, 0x5d5d20, 0xbcbdbd, 0x188ce, 0x3fd6ee, 0x66d264, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + ], + ], + CURVE_WB: [ + [0x7a84b0, 0x211856, 0xb0401c, 0x3c012, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x220475, 0xf995be, 0x9a36cd, 0xa8ca7f, 0x7e94ed, 0x2a0dc0, 0x870, 0x300000, 0x0, 0x0, 0x0], + [0xf10b93, 0xfccae0, 0xcd3b66, 0xd4653f, 0x3f4a76, 0x1506e0, 0x438, 0x180000, 0x0, 0x0, 0x0], + [0xfaaa11, 0x21185d, 0xb0c01c, 0x3c012, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + CURVE_BB: [ + [ + [ + 0x2b0cbd, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [ + 0x2b0cbc, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [ + 0x2b0cbc, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [0x802562, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x2b0cbc, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [ + 0x2b0cbd, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [ + 0x2b0cbc, 0xc0a633, 0xce7e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + ], + [ + [0x802562, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x802561, 0x7, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + [ + [0xc012b2, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [0x4ac2, 0xf, 0x10000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + [ + 0x6afa0a, 0xc0a62f, 0xce3e11, 0xcc906, 0x3fd6ee, 0x66d2c4, 0x647a63, 0xb0bddf, 0x702a0d, + 0x8, 0x2400, + ], + [0xc012b2, 0x3, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ], + ], + + USE_GLV: true, + USE_GS_G2: true, + USE_GS_GT: true, + GT_STRONG: false, + + //debug: false, + }; + + return ROM_CURVE_BN254CX; +}; + +ROM_CURVE_BRAINPOOL = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + /* Note that the original curve has been transformed to an isomorphic curve with A=-3 */ + + var ROM_CURVE_BRAINPOOL = { + // Brainpool curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_B_I: 0, + CURVE_B: [ + 0xe92b04, 0x8101fe, 0x256ae5, 0xaf2f49, 0x93ebc4, 0x76b7bf, 0x733d0b, 0xfe66a7, 0xd84ea4, + 0x61c430, 0x662c, + ], + CURVE_Order: [ + 0x4856a7, 0xe8297, 0xf7901e, 0xb561a6, 0x397aa3, 0x8d718c, 0x909d83, 0x3e660a, 0xeea9bc, + 0x57dba1, 0xa9fb, + ], + CURVE_Gx: [ + 0x1305f4, 0x91562e, 0x2b79a1, 0x7aafbc, 0xa142c4, 0x6149af, 0xb23a65, 0x732213, 0xcfe7b7, + 0xeb3cc1, 0xa3e8, + ], + CURVE_Gy: [ + 0x25c9be, 0xe8f35b, 0x1dab, 0x39d027, 0xbcb6de, 0x417e69, 0xe14644, 0x7f7b22, 0x39c56d, + 0x6c8234, 0x2d99, + ], + CURVE_HTPC: [ + 0xbc7b16, 0x14bb03, 0x88ebbc, 0x2deae8, 0x4730d2, 0xfd9592, 0xdf0183, 0x737593, 0xc052e1, + 0xc79cf0, 0x6665, + ], + }; + return ROM_CURVE_BRAINPOOL; +}; + +ROM_CURVE_C25519 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_C25519 = { + // C25519 Curve + + CURVE_Cof_I: 8, + CURVE_B_I: 0, + CURVE_B: [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0xf5d3ed, 0x631a5c, 0xd65812, 0xa2f79c, 0xdef9de, 0x14, 0x0, 0x0, 0x0, 0x0, 0x1000, + ], + CURVE_Gx: [0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Gy: [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [ + 0x7504f, 0xd93a5, 0x3c6277, 0x5697f2, 0xa18c03, 0xebd397, 0x4c9efd, 0x95a680, 0xe0ef85, + 0x924027, 0x55c1, + ], + }; + return ROM_CURVE_C25519; +}; + +ROM_CURVE_C41417 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_C41417 = { + // C41417 curve + CURVE_Cof_I: 8, + CURVE_B_I: 3617, + CURVE_B: [ + 0xe21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_Order: [ + 0x6af79, 0x69784, 0x1b0e7, 0x18f3c6, 0x338ad, 0xdbc70, 0x6022b, 0x533dc, 0x3cc924, 0x3fffac, + 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x7fff, + ], + CURVE_Gx: [ + 0xbc595, 0x204bcf, 0xc4fd3, 0x14df19, 0x33faa8, 0x4c069, 0x16ba11, 0x2ad35b, 0x1498a4, + 0x15ffcd, 0x3ec7f, 0x27d130, 0xd4636, 0x9b97f, 0x631c3, 0x8630, 0x144330, 0x241450, 0x1a334, + ], + CURVE_Gy: [ + 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_HTPC: [ + 0x3fffee, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3ffff, + ], + }; + + return ROM_CURVE_C41417; +}; + +ROM_CURVE_C1174 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_C1174 = { + // C1174 curve + CURVE_Cof_I: 4, + CURVE_Cof: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: -1174, + CURVE_B: [ + 0xfffb61, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x7ff, + ], + CURVE_Order: [ + 0x66c971, 0xd45fd1, 0x348944, 0xdfd307, 0x7965c4, 0xfffff7, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x1ff, + ], + CURVE_Gx: [ + 0xe29eda, 0x3f27bc, 0x651612, 0x492ecd, 0x21d96a, 0xa190c0, 0xe7c029, 0x9343ae, 0x308c47, + 0xbb0cea, 0x37f, + ], + CURVE_Gy: [ + 0x46360e, 0xb1bf9b, 0x6ba4cc, 0xaf3f97, 0xe2dee2, 0xe0c4f, 0x116984, 0x665684, 0x7fb7cc, + 0x2f82d4, 0x6b7, + ], + CURVE_HTPC: [ + 0xfffff6, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x7ff, + ], + }; + + return ROM_CURVE_C1174; +}; + +ROM_CURVE_C1665 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_C1665 = { + // C1665 curve + CURVE_Cof_I: 4, + CURVE_Cof: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 5766, + CURVE_B: [0x1686, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [0x3a8b27, 0x61533b, 0x40603f, 0x7feaf7, 0x7fffff, 0x7fffff, 0x7fffff, 0x7], + CURVE_Gx: [0x552398, 0x73b7f3, 0x1b19c6, 0x7707b3, 0x1a0618, 0x20b701, 0x325369, 0xa], + CURVE_Gy: [0x120345, 0xf6489, 0x70b1c2, 0x1ceb16, 0x3bfc77, 0x378142, 0x505152, 0x14], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + }; + + return ROM_CURVE_C1665; +}; + +ROM_CURVE_MDC = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_MDC = { + // Million Dollar curve + CURVE_Cof_I: 4, + CURVE_Cof: [0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 0, + CURVE_B: [ + 0xcf89, 0x92503, 0x41ee93, 0x3f21f0, 0x1270f6, 0xb9625f, 0xccfb0c, 0x7cdfbf, 0x65b68a, + 0x45219, 0x5713, + ], + CURVE_Order: [ + 0xb0f7fb, 0x52f421, 0xbb5885, 0xfaf974, 0xb38975, 0x7f534f, 0xbf75e9, 0x14cbe4, 0x15abed, + 0xda2e75, 0x3c4e, + ], + CURVE_Gx: [ + 0x68363b, 0x25bfee, 0xe2232c, 0x8d2713, 0xd72abb, 0xcf6350, 0x1e03cb, 0xd85b42, 0x903b83, + 0x886a7f, 0xb681, + ], + CURVE_Gy: [ + 0x2864b5, 0xc355bd, 0x3a7e73, 0x81a93a, 0xa8bc3d, 0xda421d, 0xcf6563, 0x59814d, 0x9c0b03, + 0x34e1b5, 0xca67, + ], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + }; + + return ROM_CURVE_MDC; +}; + +ROM_CURVE_ED25519 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_ED25519 = { + // ED25519 Curve + + CURVE_Cof_I: 8, + CURVE_B_I: 0, + CURVE_B: [ + 0x5978a3, 0x4dca13, 0xab75eb, 0x4141d8, 0x700a4d, 0xe89800, 0x797779, 0x8cc740, 0x6ffe73, + 0x6cee2b, 0x5203, + ], + CURVE_Order: [ + 0xf5d3ed, 0x631a5c, 0xd65812, 0xa2f79c, 0xdef9de, 0x14, 0x0, 0x0, 0x0, 0x0, 0x1000, + ], + CURVE_Gx: [ + 0x25d51a, 0x2d608f, 0xb2c956, 0x9525a7, 0x2cc760, 0xdc5c69, 0x31fdd6, 0xc0a4e2, 0x6e53fe, + 0x36d3cd, 0x2169, + ], + CURVE_Gy: [ + 0x666658, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, 0x666666, + 0x666666, 0x6666, + ], + CURVE_HTPC: [ + 0x7504f, 0xd93a5, 0x3c6277, 0x5697f2, 0xa18c03, 0xebd397, 0x4c9efd, 0x95a680, 0xe0ef85, + 0x924027, 0x55c1, + ], + }; + return ROM_CURVE_ED25519; +}; + +ROM_CURVE_GOLDILOCKS = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_GOLDILOCKS = { + // GOLDILOCKS curve + CURVE_Cof_I: 4, + CURVE_B_I: -39081, + CURVE_B: [ + 0x7f6756, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7dffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7ff, + ], + CURVE_Order: [ + 0x5844f3, 0x52556, 0x548de3, 0x6e2c7a, 0x4c2728, 0x52042d, 0x6bb58d, 0x276da4, 0x23e9c4, + 0x7ef994, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x1ff, + ], + CURVE_Gx: [ + 0x555555, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, + 0x52aaaa, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, 0x2aaaaa, 0x555555, + 0x2aaaaa, 0x555, + ], + CURVE_Gy: [ + 0x1386ed, 0x779bd5, 0x2f6bab, 0xe6d03, 0x4b2bed, 0x131777, 0x4e8a8c, 0x32b2c1, 0x44b80d, + 0x6515b1, 0x5f8db5, 0x426ebd, 0x7a0358, 0x6dda, 0x21b0ac, 0x6b1028, 0xdb359, 0x15ae09, + 0x17a58d, 0x570, + ], + CURVE_HTPC: [ + 0x7ffffe, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7dffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7ff, + ], + }; + return ROM_CURVE_GOLDILOCKS; +}; + +ROM_CURVE_X448 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_X448 = { + // X448 curve + CURVE_Cof_I: 4, + CURVE_Cof: [ + 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_B_I: 0, + CURVE_B: [ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_Order: [ + 0x5844f3, 0x52556, 0x548de3, 0x6e2c7a, 0x4c2728, 0x52042d, 0x6bb58d, 0x276da4, 0x23e9c4, + 0x7ef994, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x1ff, + ], + CURVE_Gx: [ + 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_Gy: [ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + CURVE_HTPC: [ + 0x7ffffe, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7dffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7ff, + ], + }; + return ROM_CURVE_X448; +}; + +ROM_CURVE_HIFIVE = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_HIFIVE = { + // HIFIVE curve + + CURVE_Cof_I: 8, + CURVE_B_I: 11111, + CURVE_B: [0x2b67, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x1fa805, 0x2b2e7d, 0x29ecbe, 0x3fc9dd, 0xbd6b8, 0x530a18, 0x45057e, 0x3, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x800, + ], + CURVE_Gx: [0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Gy: [ + 0x7e8632, 0xd0a0b, 0x6c4afb, 0x501b2e, 0x55650c, 0x36db6b, 0x1fbd0d, 0x61c08e, 0x314b46, + 0x70a7a3, 0x587401, 0xc70e0, 0x56502e, 0x38c2d6, 0x303, + ], + CURVE_HTPC: [ + 0x531622, 0x37d80a, 0x3928ff, 0x1b054e, 0x35d63a, 0x6a25b3, 0x406ae8, 0x278495, 0x339df0, + 0x2ac208, 0xe9a97, 0x1fb80f, 0x70856c, 0x3c1fc, 0xd8, + ], + }; + return ROM_CURVE_HIFIVE; +}; + +ROM_CURVE_NIST256 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NIST256 = { + // NIST256 Curve + CURVE_Cof_I: 1, + CURVE_B_I: 0, + CURVE_B: [ + 0xd2604b, 0x3c3e27, 0xf63bce, 0xcc53b0, 0x1d06b0, 0x86bc65, 0x557698, 0xb3ebbd, 0x3a93e7, + 0x35d8aa, 0x5ac6, + ], + CURVE_Order: [ + 0x632551, 0xcac2fc, 0x84f3b9, 0xa7179e, 0xe6faad, 0xffffbc, 0xffffff, 0xffffff, 0x0, 0xffff00, + 0xffff, + ], + CURVE_Gx: [ + 0x98c296, 0x3945d8, 0xa0f4a1, 0x2deb33, 0x37d81, 0x40f277, 0xe563a4, 0xf8bce6, 0x2c4247, + 0xd1f2e1, 0x6b17, + ], + CURVE_Gy: [ + 0xbf51f5, 0x406837, 0xcecbb6, 0x6b315e, 0xce3357, 0x9e162b, 0x4a7c0f, 0x8ee7eb, 0x1a7f9b, + 0x42e2fe, 0x4fe3, + ], + CURVE_HTPC: [ + 0x613926, 0x47959c, 0xd42eb8, 0x452a9d, 0x3eb001, 0x55548d, 0x8f44a6, 0x5240b3, 0x3723a4, + 0xd82cb6, 0x6a2a, + ], + }; + return ROM_CURVE_NIST256; +}; + +ROM_CURVE_SM2 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_SM2 = { + // SM2 Curve + + CURVE_Cof_I: 1, + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 0, + CURVE_B: [ + 0x940e93, 0xbd414d, 0x92ddbc, 0x15ab8f, 0x9789f5, 0x9a7f3, 0x4bcf65, 0x4d5a9e, 0x9f5e34, + 0xfa9e9d, 0x28e9, + ], + CURVE_Order: [ + 0xd54123, 0xf40939, 0x2b53bb, 0x21c605, 0x3df6b, 0xffff72, 0xffffff, 0xffffff, 0xffffff, + 0xfffeff, 0xffff, + ], + CURVE_Gx: [ + 0x4c74c7, 0x458933, 0xe1715a, 0xf2660b, 0xe30bbf, 0xc9948f, 0x466a39, 0x5f9904, 0x198119, + 0xae2c1f, 0x32c4, + ], + CURVE_Gy: [ + 0x39f0a0, 0x32e521, 0x4002df, 0xc62a47, 0xa9877c, 0x2153d0, 0xe36b69, 0x59bdce, 0xf6779c, + 0x36a2f4, 0xbc37, + ], + CURVE_HTPC: [ + 0xffffff, 0xffffff, 0x55ffff, 0x555555, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xaaa9ff, 0xaaaa, + ], + }; + return ROM_CURVE_SM2; +}; + +ROM_CURVE_NIST384 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NIST384 = { + // NIST384 curve + CURVE_Cof_I: 1, + CURVE_B_I: 0, + CURVE_B: [ + 0x6c2aef, 0x11dba7, 0x74aa17, 0x51768c, 0x6398d8, 0x6b58ca, 0x5404e1, 0xa0447, 0x411203, + 0x5dfd02, 0x607671, 0x4168c8, 0x56be3f, 0x1311c0, 0xfb9f9, 0x17d3f1, 0xb331, + ], + CURVE_Order: [ + 0x452973, 0x32d599, 0x6bb3b0, 0x45853b, 0x20db24, 0x3beb03, 0x7d0dcb, 0x31a6c0, 0x7fffc7, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + CURVE_Gx: [ + 0x760ab7, 0x3c70e4, 0x30e951, 0x7aa94b, 0x2f25db, 0x470aa0, 0x20950a, 0x7ba0f0, 0x1b9859, + 0x45174f, 0x3874ed, 0x56ba3, 0x71ef32, 0x71d638, 0x22c14d, 0x65115f, 0xaa87, + ], + CURVE_Gy: [ + 0x6a0e5f, 0x3af921, 0x75e90c, 0x6bf40c, 0xb1ce1, 0x18014c, 0x6d7c2e, 0x6d1889, 0x147ce9, + 0x7a5134, 0x63d076, 0x16e14f, 0xbf929, 0x6bb3d3, 0x98b1b, 0x6f254b, 0x3617, + ], + CURVE_HTPC: [ + 0x5cd21b, 0x589a81, 0x4cf909, 0x3aa056, 0x42d2a8, 0x7dda0a, 0x421117, 0x2fb357, 0x63b4bd, + 0x6a06e8, 0x225e, 0x43e017, 0x3feca5, 0x97ad4, 0x5c5492, 0x787911, 0xbc6e, + ], + }; + return ROM_CURVE_NIST384; +}; + +ROM_CURVE_NIST521 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NIST521 = { + // NIST521 curve + + CURVE_Cof_I: 1, + CURVE_B_I: 0, + CURVE_B: [ + 0x503f00, 0x3fa8d6, 0x47bd14, 0x6961a7, 0x3df883, 0x60e6ae, 0x4eec6f, 0x29605e, 0x137b16, + 0x23d8fd, 0x5864e5, 0x84f0a, 0x1918ef, 0x771691, 0x6cc57c, 0x392dcc, 0x6ea2da, 0x6d0a81, + 0x688682, 0x50fc94, 0x18e1c9, 0x27d72c, 0x1465, + ], + CURVE_Order: [ + 0x386409, 0x6e3d22, 0x3aedbe, 0x4ce23d, 0x5c9b88, 0x3a0776, 0x3dc269, 0x6600a4, 0x166b7f, + 0x77e5f, 0x461a1e, 0x7fffd2, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fff, + ], + CURVE_Gx: [ + 0x65bd66, 0x7c6385, 0x6fe5f9, 0x2b5214, 0xb3c18, 0x1bc669, 0x68bfea, 0xee093, 0x5928fe, + 0x6fdfce, 0x52d79, 0x69edd5, 0x7606b4, 0x3f0515, 0x4fed48, 0x409c82, 0x429c64, 0x472b68, + 0x7b2d98, 0x4e6cf1, 0x70404e, 0x31c0d6, 0x31a1, + ], + CURVE_Gy: [ + 0x516650, 0x28ed3f, 0x222fa, 0x139612, 0x47086a, 0x6c26a7, 0x4feb41, 0x285c80, 0x2640c5, + 0x32bde8, 0x5fb9ca, 0x733164, 0x517273, 0x2f5f7, 0x66d11a, 0x2224ab, 0x5998f5, 0x58fa37, + 0x297ed0, 0x22e4, 0x9a3bc, 0x252d4f, 0x460e, + ], + CURVE_HTPC: [ + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3fff, + ], + }; + return ROM_CURVE_NIST521; +}; + +ROM_CURVE_NUMS256E = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS256E = { + // NUMS256E Curve + CURVE_Cof_I: 4, + CURVE_B_I: -15342, + CURVE_B: [ + 0xffc355, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + CURVE_Order: [ + 0xdd4af5, 0xb190ee, 0x9b1a47, 0x2f5943, 0x955aa5, 0x41, 0x0, 0x0, 0x0, 0x0, 0x4000, + ], + CURVE_Gx: [ + 0xed13da, 0xc0902e, 0x86a0de, 0xe30835, 0x398a0e, 0x9bd60c, 0x5f6920, 0xcd1e3d, 0xea237d, + 0x14fb6a, 0x8a75, + ], + CURVE_Gy: [ + 0x8a89e6, 0x16e779, 0xd32fa6, 0x10856e, 0x5f61d8, 0x801071, 0xd9a64b, 0xce9665, 0xd925c7, + 0x3e9fd9, 0x44d5, + ], + CURVE_HTPC: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + }; + return ROM_CURVE_NUMS256E; +}; + +ROM_CURVE_NUMS256W = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS256W = { + // NUMS256W Curve + CURVE_Cof_I: 1, + CURVE_B_I: 152961, + CURVE_B: [0x25581, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x51a825, 0x202947, 0x6020ab, 0xea265c, 0x3c8275, 0xffffe4, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + CURVE_Gx: [ + 0x1aacb1, 0xee1eb2, 0x3abc52, 0x3d4c7, 0x579b09, 0xcb0983, 0xa04f42, 0x297a95, 0xaadb61, + 0xd6b65a, 0xbc9e, + ], + CURVE_Gy: [ + 0x84de9f, 0xb9cb21, 0xbb80b5, 0x15310f, 0x55c3d1, 0xe035c9, 0xf77e04, 0x73448b, 0x99b6a6, + 0xc0f133, 0xd08f, + ], + CURVE_HTPC: [ + 0x2b84d6, 0x6f7595, 0x9e05fc, 0x2040e8, 0x4092c6, 0xc6ae46, 0x70cadd, 0xb22ed0, 0x11e3b5, + 0x44e454, 0xcf7f, + ], + }; + return ROM_CURVE_NUMS256W; +}; + +ROM_CURVE_NUMS384E = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS384E = { + // NUMS384E Curve + CURVE_Cof_I: 4, + CURVE_B_I: -11556, + CURVE_B: [ + 0x7fd19f, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + CURVE_Order: [ + 0x23897d, 0x3989cd, 0x6482e7, 0x59ae43, 0x4555aa, 0x39ec3c, 0x2d1af8, 0x238d0e, 0x7fffe2, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3fff, + ], + CURVE_Gx: [ + 0x206bde, 0x1c8d8, 0x4d4355, 0x2a2ca0, 0x292b16, 0x680dfe, 0x3ccc58, 0x31ffd4, 0x4c0057, + 0xdcb7c, 0x4c2fd1, 0x2aedad, 0x2129ae, 0x1816d4, 0x6a499b, 0x8fda2, 0x61b1, + ], + CURVE_Gy: [ + 0x729392, 0x7c3e0, 0x727634, 0x376246, 0x2b0f94, 0x49600e, 0x7d9165, 0x7cc7b, 0x5f5683, + 0x69e284, 0x5ab609, 0x86eb8, 0x1a423b, 0x10e716, 0x69bbac, 0x1f33dc, 0x8298, + ], + CURVE_HTPC: [ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + }; + return ROM_CURVE_NUMS384E; +}; + +ROM_CURVE_NUMS384W = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS384W = { + // NUMS384W Curve + CURVE_Cof_I: 1, + CURVE_B_I: -34568, + CURVE_B: [ + 0x7f77bb, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + CURVE_Order: [ + 0xe61b9, 0x3ecf6, 0x698136, 0x61bf13, 0x29d3d4, 0x1037db, 0x3ad75a, 0xf578f, 0x7fffd6, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + CURVE_Gx: [ + 0x18152a, 0x740841, 0x6fae72, 0x7b0e23, 0x6ed100, 0x684a45, 0x4a9b31, 0x5e948d, 0x79f4f3, + 0x1bf703, 0x89707, 0x2f8d30, 0x222410, 0x91019, 0x5bc607, 0x2b7858, 0x7579, + ], + CURVE_Gy: [ + 0x180716, 0x71d8cc, 0x1971d2, 0x7fa569, 0x6b4dbb, 0x6fd79a, 0x4486a0, 0x1041be, 0x739cb9, + 0x6ff0fe, 0x4011a5, 0x267bf5, 0x530058, 0x1afc67, 0x66e38e, 0x71b470, 0xacde, + ], + CURVE_HTPC: [ + 0x7fff61, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fff, + ], + }; + return ROM_CURVE_NUMS384W; +}; + +ROM_CURVE_NUMS512E = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS512E = { + // NUMS512E Curve + CURVE_Cof_I: 4, + CURVE_B_I: -78296, + CURVE_B: [ + 0x7ecbef, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + CURVE_Order: [ + 0x6ed46d, 0x19ea37, 0x7d9d1a, 0x6f7f67, 0x605786, 0x5ea548, 0x5c2da1, 0x1fec64, 0x11ba9e, + 0x5a5f9f, 0x53c18d, 0x7ffffd, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xf, + ], + CURVE_Gx: [ + 0x6c57fe, 0x565333, 0x5716e6, 0x662780, 0x525427, 0x15a1fc, 0x15a241, 0x5ee4c9, 0x730f78, + 0x1ddc8c, 0x188705, 0x5c0a3a, 0x6be273, 0x44f42f, 0x7128e0, 0x73cfa6, 0x332fd1, 0x11a78a, + 0x632de2, 0x34e3d0, 0x5128db, 0x71c62d, 0x37, + ], + CURVE_Gy: [ + 0x62f5e1, 0x3d8183, 0x7cc9b7, 0x5f8e80, 0x6d38a9, 0x3fa04c, 0xabb30, 0xd0343, 0x356260, + 0x65d32c, 0x3294f, 0x741a09, 0x395909, 0x55256d, 0x96748, 0x7b936c, 0x6ee476, 0x50544a, + 0x43d5de, 0x538cc5, 0x39d49c, 0x2137fe, 0x1b, + ], + CURVE_HTPC: [ + 0x7ffdc6, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + }; + return ROM_CURVE_NUMS512E; +}; + +ROM_CURVE_NUMS512W = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_NUMS512W = { + // NUMS512W Curve + CURVE_Cof_I: 1, + CURVE_B_I: 121243, + CURVE_B: [ + 0x1d99b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + ], + CURVE_Order: [ + 0x33555d, 0x7e7208, 0xf3854, 0x3e692, 0x68b366, 0x38c76a, 0x65f42f, 0x612c76, 0x31b4f, + 0x7729cf, 0x6cf293, 0x7ffffa, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + CURVE_Gx: [ + 0x2bae57, 0xf2b19, 0xb720a, 0x6b7aef, 0x560137, 0x3063ab, 0x95585, 0x3ca143, 0x359e93, + 0x220ed6, 0x408685, 0x36cfca, 0xc2530, 0x28a0dc, 0x407da1, 0x6c1dda, 0x5298ca, 0x407a76, + 0x2dc00a, 0x549ed1, 0x7141d0, 0x580688, 0xe, + ], + CURVE_Gy: [ + 0x3527a6, 0xec070, 0x248e82, 0x67e87f, 0x35c1e4, 0x4059e5, 0x2c9695, 0x10d420, 0x6de9c1, + 0x35161d, 0xa1057, 0xa78a5, 0x60c7bd, 0x11e964, 0x6f2ee3, 0x6def55, 0x4b97, 0x47d762, + 0x3bbb71, 0x359e70, 0x229ad5, 0x74a99, 0x25, + ], + CURVE_HTPC: [ + 0x7ffee3, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x1f, + ], + }; + return ROM_CURVE_NUMS512W; +}; + +ROM_CURVE_SECP256K1 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_SECP256K1 = { + // SECP256K1 Curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_B_I: 7, + CURVE_B: [0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0x364141, 0x5e8cd0, 0x3bbfd2, 0xaf48a0, 0xaedce6, 0xfffeba, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + CURVE_Gx: [ + 0xf81798, 0x815b16, 0xd959f2, 0x2dce28, 0x9bfcdb, 0xb0702, 0x95ce87, 0x55a062, 0xdcbbac, + 0x667ef9, 0x79be, + ], + CURVE_Gy: [ + 0x10d4b8, 0xd08ffb, 0x199c47, 0xa68554, 0x17b448, 0x8a8fd, 0xfc0e11, 0x5da4fb, 0xa3c465, + 0xda7726, 0x483a, + ], + CURVE_HTPC: [ + 0x8624aa, 0x13789e, 0x8ecdc8, 0xc23f50, 0xfdca45, 0xcd8bbb, 0x640a39, 0xf4d5b4, 0x3ffe30, + 0xe9e881, 0xcce8, + ], + + CURVE_Ad: [ + 0x444533, 0x47c01a, 0x5d4054, 0xcb6f0e, 0x53d363, 0xd272e9, 0x58f0f5, 0xa08a55, 0x661adc, + 0x31abdd, 0x3f87, + ], + CURVE_Bd: [0x6eb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + PC: [ + [ + 0xaaa88c, 0xe38daa, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, + 0xe38e38, 0x8e38, + ], + [ + 0x9dd262, 0xd0b53d, 0x314ecb, 0x37c40, 0x506144, 0xcaece4, 0xdeca25, 0xe2a413, 0xf234e6, + 0x328d23, 0x534c, + ], + [ + 0x7c6581, 0x1044f1, 0x92dfff, 0xbf63b, 0x95d2fc, 0x44c5d5, 0xcea7fd, 0xb9f315, 0xc321d5, + 0xd4c80b, 0x7d3, + ], + [ + 0xaaa8c7, 0xe38daa, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, 0xe38e38, + 0xe38e38, 0x8e38, + ], + [ + 0x8c6d14, 0x56612a, 0xbbc52a, 0x1f5e41, 0xd36b64, 0x225406, 0xd51b54, 0xf7c4b2, 0x83dc1d, + 0xc6f643, 0xedad, + ], + [ + 0x1eb49b, 0xb74578, 0x7d9fe6, 0x42f848, 0xcd4095, 0x40dd86, 0xcbb7b6, 0x9ca34c, 0x94918a, + 0x71193d, 0xd357, + ], + [ + 0xe38d84, 0xa12f38, 0xf684bd, 0x4bda12, 0xa12f68, 0xf684bd, 0x4bda12, 0xa12f68, 0xf684bd, + 0x4bda12, 0x2f68, + ], + [ + 0xcee931, 0xe85a9e, 0x18a765, 0x1be20, 0x2830a2, 0xe57672, 0xef6512, 0x715209, 0xf91a73, + 0x194691, 0x29a6, + ], + [ + 0x1d71a3, 0x90fc20, 0x6fdffc, 0xd686da, 0x7ab046, 0xa6d564, 0x4b12a0, 0xa9d0a5, 0xcb7c0f, + 0xc32d5, 0xc75e, + ], + [ + 0x38e23c, 0x684b8e, 0xbda12f, 0x12f684, 0x684bda, 0xbda12f, 0x12f684, 0x684bda, 0xbda12f, + 0x12f684, 0x4bda, + ], + [ + 0xd2a76f, 0x8192bf, 0x99a7bf, 0x2f0d62, 0x3d2116, 0x337e0a, 0x3fa8fe, 0xf3a70c, 0x45ca2c, + 0xaa7165, 0x6484, + ], + [ + 0x5c2573, 0x25d268, 0x78dfb4, 0xc8e8d9, 0x67c1bf, 0xc29894, 0x632722, 0xd5e9e6, 0xbdb49f, + 0x534bb8, 0x7a06, + ], + [ + 0xfff93b, 0xfffeff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + ], + }; + return ROM_CURVE_SECP256K1; +}; + +ROM_CURVE_SECP160R1 = function () { + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_CURVE_SECP160R1 = { + // SECP160R1 Curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 0, + CURVE_B: [0x65fa45, 0xd4adc5, 0x9f81d4, 0x65acf8, 0xbd7a8b, 0xbefc54, 0x1c97], + CURVE_Order: [0x752257, 0xaed3ca, 0xc8f927, 0x1f4, 0x0, 0x0, 0x10000], + CURVE_Gx: [0xcbfc82, 0x8bb913, 0x8968c3, 0x466469, 0xf57328, 0xb5688e, 0x4a96], + CURVE_Gy: [0xc5fb32, 0x51377a, 0x120423, 0x59dcc9, 0x68947d, 0x285531, 0x23a6], + CURVE_HTPC: [0x5bc0da, 0xfaf3a2, 0x7305da, 0xface6a, 0x5a6106, 0xbd02cd, 0x1e50], + }; + return ROM_CURVE_SECP160R1; +}; + +ROM_CURVE_JUBJUB = function () { + // Fixed Data in ROM - Field and Curve parameters + + var ROM_CURVE_JUBJUB = { + // JUBJUB Curve + // Base Bits= 24 + + CURVE_Cof_I: 8, + CURVE_Cof: [0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 0, + CURVE_B: [ + 0x343eb1, 0x5fd6d6, 0x260106, 0x37579d, 0x2d7f6d, 0x7fd429, 0x7e6bd, 0xf5fd92, 0xfa2b48, + 0x18e74b, 0x2a93, + ], + CURVE_Order: [ + 0xf72cb7, 0xe5ed6, 0x82d097, 0xccc810, 0x682093, 0x3b00a6, 0x10134, 0x6673b, 0x33afa9, + 0xb4ea65, 0xe7d, + ], + CURVE_Gx: [ + 0xf976c4, 0xcf1a74, 0xde7f4e, 0xf2f39e, 0xc546b, 0x488200, 0xdf0038, 0xa624b4, 0xeff38c, + 0x972af8, 0x5183, + ], + CURVE_Gy: [ + 0x49702e, 0xad7093, 0x3b146b, 0xffa683, 0x6c8707, 0xc30809, 0x5abd9d, 0x9e8fcc, 0xa2fc2c, + 0xf8472c, 0x3b43, + ], + CURVE_HTPC: [ + 0x7bbbb6, 0xaef9e4, 0xa9907, 0x517532, 0x5dff51, 0xd546e2, 0xcb473c, 0x3e3ee, 0x37b1d4, + 0x68b42b, 0x62fd, + ], + }; + return ROM_CURVE_JUBJUB; +}; + +ROM_CURVE_C13318 = function () { + // Fixed Data in ROM - Field and Curve parameters + + var ROM_CURVE_C13318 = { + // C13318 Curve + // Base Bits= 24 + + CURVE_Cof_I: 1, + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 13318, + CURVE_B: [0x3406, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [ + 0xc2cbe3, 0x12dc4d, 0x16eb7d, 0x3deb8d, 0xf654f8, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x8000, + ], + CURVE_Gx: [0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Gy: [ + 0x6ead0b, 0xd3546b, 0xb5b8c8, 0xcf016d, 0x4ccb04, 0x66369d, 0xe51669, 0x381630, 0xbca6f1, + 0xaad926, 0x6675, + ], + CURVE_HTPC: [ + 0x7504f, 0xd93a5, 0x3c6277, 0x5697f2, 0xa18c03, 0xebd397, 0x4c9efd, 0x95a680, 0xe0ef85, + 0x924027, 0x55c1, + ], + }; + return ROM_CURVE_C13318; +}; + +ROM_CURVE_TWEEDLEDUM = function () { + // Fixed Data in ROM - Field and Curve parameters + + var ROM_CURVE_TWEEDLEDUM = { + //*** rom curve parameters ***** + CURVE_Cof_I: 1, + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 5, + CURVE_B: [0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [0x1, 0xafd400, 0xc9842c, 0x696286, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + CURVE_Gx: [0x0, 0x64e200, 0xb9a140, 0x6c3f59, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + CURVE_Gy: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [ + 0x381795, 0x755341, 0xc366d6, 0xd03cfb, 0x10aeeb, 0xbaa53e, 0x8b6caa, 0xef14d8, 0x20bf4, + 0x6cf337, 0x3ab4, + ], + }; + return ROM_CURVE_TWEEDLEDUM; +}; + +ROM_CURVE_TWEEDLEDEE = function () { + // Fixed Data in ROM - Field and Curve parameters + + var ROM_CURVE_TWEEDLEDEE = { + //*** rom curve parameters ***** + CURVE_Cof_I: 1, + CURVE_Cof: [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_B_I: 5, + CURVE_B: [0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_Order: [0x1, 0x64e200, 0xb9a140, 0x6c3f59, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + CURVE_Gx: [0x0, 0xafd400, 0xc9842c, 0x696286, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + CURVE_Gy: [0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + CURVE_HTPC: [ + 0x69c848, 0x1cbdad, 0x873386, 0x672ef6, 0xac0754, 0xe9704, 0xe5bc1a, 0x82c6a2, 0x649720, + 0x88de2a, 0x3ac1, + ], + }; + return ROM_CURVE_TWEEDLEDEE; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + ROM_CURVE_ANSSI: ROM_CURVE_ANSSI, + ROM_CURVE_BLS12383: ROM_CURVE_BLS12383, + ROM_CURVE_BLS24479: ROM_CURVE_BLS24479, + ROM_CURVE_BLS48556: ROM_CURVE_BLS48556, + ROM_CURVE_BLS48286: ROM_CURVE_BLS48286, + ROM_CURVE_BLS48581: ROM_CURVE_BLS48581, + ROM_CURVE_BLS12381: ROM_CURVE_BLS12381, + ROM_CURVE_BLS12461: ROM_CURVE_BLS12461, + ROM_CURVE_BN462: ROM_CURVE_BN462, + ROM_CURVE_FP256BN: ROM_CURVE_FP256BN, + ROM_CURVE_FP512BN: ROM_CURVE_FP512BN, + ROM_CURVE_BN254: ROM_CURVE_BN254, + ROM_CURVE_BN254CX: ROM_CURVE_BN254CX, + ROM_CURVE_BRAINPOOL: ROM_CURVE_BRAINPOOL, + ROM_CURVE_C25519: ROM_CURVE_C25519, + ROM_CURVE_C41417: ROM_CURVE_C41417, + ROM_CURVE_C1174: ROM_CURVE_C1174, + ROM_CURVE_C1665: ROM_CURVE_C1665, + ROM_CURVE_MDC: ROM_CURVE_MDC, + ROM_CURVE_ED25519: ROM_CURVE_ED25519, + ROM_CURVE_GOLDILOCKS: ROM_CURVE_GOLDILOCKS, + ROM_CURVE_X448: ROM_CURVE_X448, + ROM_CURVE_HIFIVE: ROM_CURVE_HIFIVE, + ROM_CURVE_NIST256: ROM_CURVE_NIST256, + ROM_CURVE_NIST384: ROM_CURVE_NIST384, + ROM_CURVE_NIST521: ROM_CURVE_NIST521, + ROM_CURVE_NUMS256E: ROM_CURVE_NUMS256E, + ROM_CURVE_NUMS256W: ROM_CURVE_NUMS256W, + ROM_CURVE_NUMS384E: ROM_CURVE_NUMS384E, + ROM_CURVE_NUMS384W: ROM_CURVE_NUMS384W, + ROM_CURVE_NUMS512E: ROM_CURVE_NUMS512E, + ROM_CURVE_NUMS512W: ROM_CURVE_NUMS512W, + ROM_CURVE_SECP256K1: ROM_CURVE_SECP256K1, + ROM_CURVE_SECP160R1: ROM_CURVE_SECP160R1, + ROM_CURVE_SM2: ROM_CURVE_SM2, + ROM_CURVE_C13318: ROM_CURVE_C13318, + ROM_CURVE_JUBJUB: ROM_CURVE_JUBJUB, + ROM_CURVE_TWEEDLEDEE: ROM_CURVE_TWEEDLEDEE, + ROM_CURVE_TWEEDLEDUM: ROM_CURVE_TWEEDLEDUM, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/rom_field.js b/packages/bls-verify/src/vendor/amcl-js/src/rom_field.js new file mode 100644 index 000000000..2a221a701 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/rom_field.js @@ -0,0 +1,1101 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Fixed Data in ROM - Field and Curve parameters */ + +var ROM_FIELD_25519, + ROM_FIELD_256PM, + ROM_FIELD_384PM, + ROM_FIELD_512PM, + ROM_FIELD_ANSSI, + ROM_FIELD_BLS12383, + ROM_FIELD_BLS24479, + ROM_FIELD_BLS48556, + ROM_FIELD_BLS48286, + ROM_FIELD_BLS48581, + ROM_FIELD_BLS12381, + ROM_FIELD_BLS12461, + ROM_FIELD_BN462, + ROM_FIELD_FP256BN, + ROM_FIELD_FP512BN, + ROM_FIELD_BN254, + ROM_FIELD_BN254CX, + ROM_FIELD_BRAINPOOL, + ROM_FIELD_C41417, + ROM_FIELD_C1174, + ROM_FIELD_C1665, + ROM_FIELD_MDC, + ROM_FIELD_GOLDILOCKS, + ROM_FIELD_HIFIVE, + ROM_FIELD_NIST256, + ROM_FIELD_NIST384, + ROM_FIELD_NIST521, + ROM_FIELD_SECP256K1, + ROM_FIELD_SECP160R1, + ROM_FIELD_SM2, + ROM_FIELD_JUBJUB, + ROM_FIELD_TWEEDLEDUM, + ROM_FIELD_TWEEDLEDEE; + +ROM_FIELD_25519 = function () { + 'use strict'; + + var ROM_FIELD_25519 = { + // 25519 Curve Modulus + Modulus: [ + 0xffffed, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x7fff, + ], + ROI: [ + 0xea0b0, 0x1b274a, 0x78c4ee, 0xad2fe4, 0x431806, 0xd7a72f, 0x993dfb, 0x2b4d00, 0xc1df0b, + 0x24804f, 0x2b83, + ], + R2modp: [0xa40000, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + MConst: 0x13, + }; + return ROM_FIELD_25519; +}; + +ROM_FIELD_256PM = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_256PM = { + // NUMS256 Curve Modulus + // Base Bits= 24 + Modulus: [ + 0xffff43, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + ROI: [ + 0xffff42, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + R2modp: [0x890000, 0x8b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + MConst: 0xbd, + }; + return ROM_FIELD_256PM; +}; + +ROM_FIELD_384PM = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_384PM = { + // NUMS384 Curve Modulus + // Base Bits= 23 + Modulus: [ + 0x7ffec3, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + ROI: [ + 0x7ffec2, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + R2modp: [ + 0x224000, 0xc4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ], + MConst: 0x13d, + }; + return ROM_FIELD_384PM; +}; + +ROM_FIELD_512PM = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_512PM = { + // NUMS512 Curve Modulus + // Base Bits= 23 + Modulus: [ + 0x7ffdc7, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ROI: [ + 0x7ffdc6, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + R2modp: [ + 0x0, 0x58800, 0x4f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + ], + MConst: 0x239, + }; + return ROM_FIELD_512PM; +}; + +ROM_FIELD_ANSSI = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_ANSSI = { + // ANSSI modulus + // Base Bits= 24 + Modulus: [ + 0x6e9c03, 0xf353d8, 0x6de8fc, 0xabc8ca, 0x61adbc, 0x435b39, 0xe8ce42, 0x10126d, 0x3ad58f, + 0x178c0b, 0xf1fd, + ], + ROI: [ + 0x6e9c02, 0xf353d8, 0x6de8fc, 0xabc8ca, 0x61adbc, 0x435b39, 0xe8ce42, 0x10126d, 0x3ad58f, + 0x178c0b, 0xf1fd, + ], + R2modp: [ + 0xacece3, 0x924166, 0xb10fce, 0x6cfbb6, 0x87ec2, 0x3de43d, 0xd2cf67, 0xa67dde, 0xad30f2, + 0xbcaae, 0xdf98, + ], + MConst: 0x4e1155, + }; + return ROM_FIELD_ANSSI; +}; + +ROM_FIELD_BLS12383 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS12383 = { + // BLS12383 Modulus + // Base Bits= 23 + Modulus: [ + 0x2ab0ab, 0x3ac90b, 0x2f68dc, 0x532429, 0x43f298, 0x1e8f51, 0x5a5849, 0x18dc00, 0x2511ac, + 0x59e6cb, 0x2b518, 0x549425, 0x5c41fe, 0x340db5, 0x2adbad, 0x2b4ab2, 0x5565, + ], + ROI: [ + 0x2ab0aa, 0x3ac90b, 0x2f68dc, 0x532429, 0x43f298, 0x1e8f51, 0x5a5849, 0x18dc00, 0x2511ac, + 0x59e6cb, 0x2b518, 0x549425, 0x5c41fe, 0x340db5, 0x2adbad, 0x2b4ab2, 0x5565, + ], + R2modp: [ + 0x250a44, 0x68f66f, 0xe3c74, 0x791772, 0x3525e3, 0xe1e15, 0x356616, 0x54f624, 0x508069, + 0x272663, 0x4a4cb0, 0x359293, 0x5b6573, 0x9f27f, 0x5ea3b4, 0x60fd2d, 0x5167, + ], + MConst: 0x3435fd, + SQRTm3: [ + 0x2ad4a8, 0x6277af, 0x677d3e, 0x5ad233, 0x7add9b, 0x31dfb7, 0x401708, 0x395349, 0x3da818, + 0x7988aa, 0x7fed10, 0x3ff320, 0xc3ede, 0x7403b5, 0x2adbac, 0x2b4ab2, 0x5565, + ], + CRu: [ + 0x2ac2a9, 0x4ea05d, 0x4b730d, 0x16fb2e, 0x5f681a, 0x683784, 0xd37a8, 0x2917a5, 0x715ce2, + 0x69b7ba, 0x15114, 0x4a43a3, 0x34406e, 0x1408b5, 0x2adbad, 0x2b4ab2, 0x5565, + ], + Fra: [ + 0x11dac1, 0x2e5a66, 0x614b, 0x733b9f, 0x13480f, 0x19146d, 0x395436, 0x2b3a25, 0x1a8682, + 0x247f74, 0x3931b3, 0x5a9788, 0x7c2c11, 0x67173, 0x1fda2f, 0x6adf81, 0x22ac, + ], + Frb: [ + 0x18d5ea, 0xc6ea5, 0x2f0791, 0x5fe88a, 0x30aa88, 0x57ae4, 0x210413, 0x6da1db, 0xa8b29, + 0x356757, 0x498365, 0x79fc9c, 0x6015ec, 0x2d9c41, 0xb017e, 0x406b31, 0x32b8, + ], + }; + + return ROM_FIELD_BLS12383; +}; + +ROM_FIELD_BLS24479 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS24479 = { + // BLS24479 Modulus + // Base Bits= 23 + + Modulus: [ + 0x6152b, 0x2ce94, 0x6be113, 0x416986, 0x2ffe2e, 0x36d4c8, 0x47172f, 0x1945b7, 0x5f068a, + 0xe6441, 0x110186, 0x4f0f9, 0x33568e, 0x4a0f2e, 0x306ea0, 0x173bf2, 0x6e803f, 0x735d8, + 0x3316ea, 0x3c01e, 0x555c0, + ], + ROI: [ + 0x6152a, 0x2ce94, 0x6be113, 0x416986, 0x2ffe2e, 0x36d4c8, 0x47172f, 0x1945b7, 0x5f068a, + 0xe6441, 0x110186, 0x4f0f9, 0x33568e, 0x4a0f2e, 0x306ea0, 0x173bf2, 0x6e803f, 0x735d8, + 0x3316ea, 0x3c01e, 0x555c0, + ], + R2modp: [ + 0x22d6fa, 0x7aa299, 0x4c307e, 0x68e711, 0x7da4ae, 0x383cc3, 0x12048c, 0x11b7d, 0x3ca412, + 0x2ce421, 0x4932ac, 0x27a306, 0x340b6a, 0x666e, 0x3f6575, 0x2f823c, 0xa0de6, 0x137ec5, + 0x37d4bc, 0x48a54e, 0x4c28b, + ], + MConst: 0x15fe7d, + SQRTm3: [ + 0x291428, 0x198323, 0x663cce, 0x7745ac, 0x1747e3, 0x5222a9, 0x41f479, 0x54b5f9, 0x1861bc, + 0xde532, 0x2be5aa, 0x1e67ea, 0x5cb732, 0x67ab99, 0xb7c9f, 0x71250d, 0x741800, 0x26db7, + 0x2b165a, 0x3c01e, 0x555c0, + ], + CRu: [ + 0x5794a9, 0x4e28db, 0x690ef0, 0x1c5799, 0x63a309, 0x447bb8, 0x4485d4, 0x36fdd8, 0x7bb423, + 0xe24b9, 0x5e7398, 0x11ac71, 0x806e0, 0x18dd64, 0x5df5a0, 0x4307f, 0x314c20, 0x4d1c8, + 0x2f16a2, 0x3c01e, 0x555c0, + ], + Fra: [ + 0x796f1d, 0x4e9577, 0x6eb572, 0x68637f, 0x41ff8b, 0x46e8d3, 0x7a7898, 0x7c72a4, 0x248407, + 0x6e79d9, 0x56499e, 0x4eb47f, 0x27cbd6, 0x33c662, 0x4e9746, 0xc2798, 0x397549, 0x4a5b1b, + 0x5c90b6, 0x3dca73, 0x4bbc8, + ], + Frb: [ + 0xca60e, 0x34391c, 0x7d2ba0, 0x590606, 0x6dfea2, 0x6febf4, 0x4c9e96, 0x1cd312, 0x3a8282, + 0x1fea68, 0x3ab7e7, 0x363c79, 0xb8ab7, 0x1648cc, 0x61d75a, 0xb1459, 0x350af6, 0x3cdabd, + 0x568633, 0x45f5aa, 0x99f7, + ], + TWK: [ + 0x6a62f3, 0x12416d, 0x735296, 0x62f9eb, 0x1cb389, 0x794c37, 0x37ddda, 0x7acf76, 0x6a6d51, + 0x1625bc, 0x7c5536, 0x518cd7, 0x3e1bc9, 0x47ce1f, 0x8c33b, 0xc7722, 0x62935e, 0x40f556, + 0x4ed046, 0x133767, 0x337a3, + ], + }; + + return ROM_FIELD_BLS24479; +}; + +ROM_FIELD_BLS48581 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS48581 = { + // Base Bits= 23 + Modulus: [ + 0x65912b, 0x2a9cca, 0x30fb70, 0x525245, 0x7df721, 0x414af1, 0x4c5c3b, 0x33d2a8, 0x5af683, + 0x1e8e6d, 0x34c0e5, 0x1566ce, 0x2f6e08, 0x115c87, 0x551129, 0x78f9cb, 0x3be6c0, 0x426376, + 0x3e3448, 0x2b742, 0x7012a0, 0x1c63a8, 0x4c4e09, 0x79a3b7, 0xf73f, 0x25, + ], + ROI: [ + 0x65912a, 0x2a9cca, 0x30fb70, 0x525245, 0x7df721, 0x414af1, 0x4c5c3b, 0x33d2a8, 0x5af683, + 0x1e8e6d, 0x34c0e5, 0x1566ce, 0x2f6e08, 0x115c87, 0x551129, 0x78f9cb, 0x3be6c0, 0x426376, + 0x3e3448, 0x2b742, 0x7012a0, 0x1c63a8, 0x4c4e09, 0x79a3b7, 0xf73f, 0x25, + ], + R2modp: [ + 0x4e2506, 0x1fad8c, 0x618be7, 0x23e9bf, 0x6a8ad9, 0x3529c9, 0xb64d9, 0x1c7a8e, 0x759816, + 0x2ae889, 0x3b1f74, 0x53d536, 0x7cff54, 0x389ee8, 0x4f41f1, 0x2c5d2d, 0x48d19d, 0x6c88a7, + 0x7b224e, 0x3b0db8, 0x3bdcf8, 0x83abf, 0x5b548e, 0x50a9d7, 0x362f43, 0x10, + ], + MConst: 0x1d5a7d, + SQRTm3: [ + 0x565a0a, 0x3f8543, 0x6fd47b, 0x496c66, 0x62daa2, 0x3ac2da, 0x11e09a, 0x92089, 0x3f8ad7, + 0x4ba795, 0x1335b0, 0x35ae9f, 0x48e9b1, 0x12c1dd, 0xedce, 0x21fa85, 0x6fed43, 0x4cc86e, + 0x6b8186, 0x7dc492, 0x2bffd8, 0x451bd5, 0x24231a, 0x4d3b00, 0xf73f, 0x25, + ], + CRu: [ + 0x479b90, 0x358bc3, 0x20937a, 0x4472ef, 0x4d8e3f, 0x43440b, 0x5d3dd0, 0x15590f, 0xdb5d6, + 0x29736c, 0x50c59a, 0x2fdc17, 0x73422b, 0x3f4d54, 0x2a11ad, 0x6b7fa3, 0x65fcbe, 0x7acd83, + 0x695960, 0x427957, 0x620963, 0x2ba3e9, 0x541577, 0x16345b, 0x0, 0x0, + ], + Fra: [ + 0x2aeb25, 0x6d9fc8, 0x7e58ba, 0x3b0569, 0x341942, 0x3d9c9b, 0x15c1c5, 0x7d3ef9, 0x208ac0, + 0x6ef6a2, 0x106240, 0x1f0e46, 0x684849, 0x3030fc, 0xc1f8a, 0x317a4b, 0x4afd6b, 0xe81c7, + 0xf9e16, 0x6823cc, 0x5f6067, 0x7ce7ca, 0x69d735, 0x280a4f, 0x7d30db, 0x1, + ], + Frb: [ + 0x2aeb25, 0x6d9fc8, 0x7e58ba, 0x3b0569, 0x341942, 0x3d9c9b, 0x15c1c5, 0x7d3ef9, 0x208ac0, + 0x6ef6a2, 0x106240, 0x1f0e46, 0x684849, 0x3030fc, 0xc1f8a, 0x317a4b, 0x4afd6b, 0xe81c7, + 0xf9e16, 0x6823cc, 0x5f6067, 0x7ce7ca, 0x69d735, 0x280a4f, 0x7d30db, 0x1, + ], + TWK: [ + 0x426953, 0x67a4be, 0xf5ed0, 0x11dcc3, 0x2ce459, 0x6fc2c1, 0x77e8b4, 0x46145d, 0x7b4bc1, + 0x7f9915, 0x313d8b, 0x497801, 0x661b43, 0x428f02, 0x1fa546, 0x231769, 0x3b8532, 0x614cd0, + 0x281d59, 0x4dd09c, 0x6aeb8c, 0x39bbb3, 0x1d5da, 0x1bde08, 0x3a65a5, 0x0, + ], + }; + + return ROM_FIELD_BLS48581; +}; + +ROM_FIELD_BLS48556 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS48556 = { + // BLS48556 Modulus + // Base Bits= 23 + + Modulus: [ + 0x76ac0b, 0x4c1ff9, 0x67bbdb, 0x5330ef, 0x167009, 0x450805, 0x61c350, 0x609bd4, 0x76b2e, + 0x40410d, 0x169054, 0x353e01, 0x141301, 0x66f371, 0x3b355a, 0x6d4a85, 0x36f405, 0x28840a, + 0x454ab3, 0x2b6433, 0x29047a, 0xb646e, 0xbff3f, 0x68bec2, 0xf, + ], + ROI: [ + 0x76ac0a, 0x4c1ff9, 0x67bbdb, 0x5330ef, 0x167009, 0x450805, 0x61c350, 0x609bd4, 0x76b2e, + 0x40410d, 0x169054, 0x353e01, 0x141301, 0x66f371, 0x3b355a, 0x6d4a85, 0x36f405, 0x28840a, + 0x454ab3, 0x2b6433, 0x29047a, 0xb646e, 0xbff3f, 0x68bec2, 0xf, + ], + R2modp: [ + 0x5f42c2, 0x596e88, 0x2ed8fa, 0x15c970, 0x2518b4, 0x2a75e7, 0x62ce53, 0x431c50, 0x3cf507, + 0x620e44, 0xd6fcd, 0x21a7d, 0x1fda3f, 0x6a099, 0x53487, 0x53eebf, 0x54e2d0, 0x48437d, + 0x2233d8, 0x63296f, 0x21ee21, 0x611417, 0x619d35, 0x13a61a, 0xb, + ], + MConst: 0x5a805d, + SQRTm3: [ + 0x9c48, 0x6dd9b9, 0x4445d6, 0x401e84, 0x5f13b, 0x5b1ce6, 0x3c70c7, 0x798d07, 0x7e0544, + 0x62ca1b, 0x75113, 0x557bb6, 0x3a11f4, 0x1426f2, 0x27ef0c, 0x1763b3, 0x7ee9f8, 0x3cf4db, + 0x4cdb7e, 0x6bf8c, 0x263a76, 0x3d63a0, 0x5bbf38, 0x68bec1, 0xf, + ], + CRu: [ + 0x3ba429, 0x1cfcd9, 0x1600d9, 0x49a7ba, 0x4e30a2, 0x101275, 0xf1a0c, 0x6d146e, 0x42b839, + 0x118594, 0x4ef0b4, 0x55cdb, 0x67127b, 0x3d8d31, 0x319233, 0x2571c, 0x1aeeff, 0x72bc73, + 0x91318, 0x1911e0, 0x279f78, 0x646407, 0x73df3b, 0x68bec1, 0xf, + ], + Fra: [ + 0x25bf89, 0x79fb26, 0x56f988, 0x399a14, 0x507ea3, 0x77995, 0x3ee83a, 0x52eca9, 0x3e3474, + 0x5f1e13, 0x2e7cb0, 0x255f3d, 0x3ae7f8, 0x2e4ef6, 0x3bde94, 0x7b05a, 0x13c83c, 0x7bf664, + 0x1ff27f, 0x6fe082, 0x3b36ce, 0x138113, 0x6e2002, 0x4c5c03, 0x2, + ], + Frb: [ + 0x25bf89, 0x79fb26, 0x56f988, 0x399a14, 0x507ea3, 0x77995, 0x3ee83a, 0x52eca9, 0x3e3474, + 0x5f1e13, 0x2e7cb0, 0x255f3d, 0x3ae7f8, 0x2e4ef6, 0x3bde94, 0x7b05a, 0x13c83c, 0x7bf664, + 0x1ff27f, 0x6fe082, 0x3b36ce, 0x138113, 0x6e2002, 0x4c5c03, 0x2, + ], + TWK: [ + 0x6f9937, 0x4f5442, 0x12b489, 0x31b13f, 0xbd341, 0x4006d0, 0x7a84d9, 0x4dd830, 0x6d4c49, + 0x59d972, 0x1a71ca, 0x687e1, 0x40c8dc, 0x206554, 0x5de9a7, 0x2817c7, 0x6556ed, 0x27c11a, + 0x3ec6ef, 0x764e01, 0x6dd577, 0x7cffdd, 0x246857, 0x1907ce, 0x4, + ], + }; + + return ROM_FIELD_BLS48556; +}; + +ROM_FIELD_BLS48286 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS48286 = { + // BLS48286 Modulus + // Base Bits= 23 + + Modulus: [ + 0x1c345b, 0x57241, 0x3679d4, 0x1471a9, 0x641c45, 0x1355e, 0x6b012, 0x36463f, 0x145a8, + 0x604039, 0x31ef5e, 0x16298f, 0x297, + ], + R2modp: [ + 0x116bcb, 0x4a9ce9, 0xd861f, 0x5ca282, 0x66469, 0x30c42d, 0x299fc6, 0x442c07, 0x1735e0, + 0x516724, 0x325ec8, 0x294de1, 0x35, + ], + ROI: [ + 0x1c345a, 0x57241, 0x3679d4, 0x1471a9, 0x641c45, 0x1355e, 0x6b012, 0x36463f, 0x145a8, + 0x604039, 0x31ef5e, 0x16298f, 0x297, + ], + SQRTm3: [ + 0x524a9c, 0x48e5cc, 0x66335e, 0xe9944, 0x35b814, 0x1d666a, 0x269c21, 0x4bac4c, 0x2987b9, + 0x614644, 0x63d761, 0xe12a3, 0x297, + ], + CRu: [ + 0x773f7b, 0x272c06, 0xe5699, 0x518577, 0x4cea2c, 0x4f4de4, 0x56a619, 0xf945, 0x5566b1, + 0x20c33e, 0x4ae360, 0x121e19, 0x297, + ], + MConst: 0x6a242d, + Fra: [ + 0x490183, 0x52be7f, 0x4dbaa1, 0xde9f4, 0x556bed, 0x6134f8, 0x3c09a3, 0x1ec81f, 0x2fe004, + 0x1d15d8, 0x48b045, 0x20bf62, 0xd9, + ], + Frb: [ + 0x5332d8, 0x32b3c1, 0x68bf32, 0x687b4, 0xeb058, 0x200066, 0x4aa66e, 0x177e1f, 0x5165a4, + 0x432a60, 0x693f19, 0x756a2c, 0x1bd, + ], + TWK: [ + 0x505dcc, 0x2e6b87, 0x2e69f6, 0x2a1538, 0x197054, 0x458d43, 0x4532ea, 0x7de65e, 0x367221, + 0x233e6e, 0x1228cd, 0x76f7a, 0x1d2, + ], + }; + + return ROM_FIELD_BLS48286; +}; + +ROM_FIELD_BN462 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BN462 = { + // Base Bits= 23 + Modulus: [ + 0x138013, 0x601080, 0x9006, 0x0, 0x7f6400, 0xdfed0, 0x3fd9bf, 0x7ffffb, 0xfffff, 0x39004, + 0x4a423d, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, 0x202401, + 0x2, + ], + ROI: [ + 0x138012, 0x601080, 0x9006, 0x0, 0x7f6400, 0xdfed0, 0x3fd9bf, 0x7ffffb, 0xfffff, 0x39004, + 0x4a423d, 0x6c0, 0x0, 0x37f940, 0x3dadf6, 0x7b7f86, 0x7fffff, 0x47fff, 0x580480, 0x202401, + 0x2, + ], + R2modp: [ + 0x8b8d, 0x7265c, 0x56003a, 0xe1112, 0x275149, 0x50bff0, 0x1e3e2e, 0x2dedf3, 0x43d666, + 0x644751, 0x2a7239, 0x1dca94, 0x5f2ff8, 0x41cff0, 0x41494f, 0x34b04a, 0x47932f, 0x5e4bbc, + 0x50bc6, 0x30f0fb, 0x1, + ], + MConst: 0x1bb5e5, + SQRTm3: [ + 0x210022, 0x1980, 0x9009, 0x0, 0x7ef800, 0x60fe25, 0x3fd2fe, 0x7ffffb, 0x2fffff, 0x4f806, + 0x5102bb, 0x6c0, 0x0, 0x5ff700, 0x7d77f4, 0x7b7f81, 0x7fffff, 0x47fff, 0x580480, 0x202401, + 0x2, + ], + CRu: [ + 0x1a401a, 0x701500, 0x9007, 0x0, 0x3f2e00, 0x777e7b, 0x3fd65e, 0x7ffffb, 0x1fffff, 0x44405, + 0x4da27c, 0x6c0, 0x0, 0x4bf820, 0x1d92f5, 0x7b7f84, 0x7fffff, 0x47fff, 0x580480, 0x202401, + 0x2, + ], + Fra: [ + 0x575d1a, 0x7c7fe4, 0x6f7b92, 0x44b2ce, 0xfc7d, 0x27f423, 0x517476, 0x3c6c86, 0x3310cc, + 0xac42e, 0x3551f0, 0x3c9282, 0x7e11c, 0x207535, 0x2164bb, 0x8b938, 0x35a8cc, 0x179fb, + 0x5232ed, 0xb7fa1, 0x0, + ], + Frb: [ + 0x5ff85b, 0x15c12a, 0x2d8881, 0x432bdf, 0x90238, 0x2c6144, 0x653d2f, 0x786807, 0x27a84f, + 0x362943, 0x2c76eb, 0x6c72, 0x685f7b, 0x794003, 0x6c9d24, 0x5b4192, 0x2008e6, 0x21d510, + 0x2503a, 0x1e1bfc, 0x2, + ], + }; + + return ROM_FIELD_BN462; +}; + +ROM_FIELD_BLS12381 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS12381 = { + // BLS12381 Modulus + // Base Bits= 23 + + Modulus: [ + 0x7faaab, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + ROI: [ + 0x7faaaa, 0x7fffff, 0x7ee7fb, 0xa9fff, 0x3fffeb, 0x4483d5, 0x3dac3d, 0x186950, 0x12bf67, + 0x9e70a, 0x11dd2e, 0x5d66bb, 0x7b6434, 0x496374, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + R2modp: [ + 0x40c6e6, 0xe1a28, 0x3d1c6c, 0x6d2448, 0x1bb111, 0x4eafa8, 0x229c8c, 0x4cee55, 0x46d2ad, + 0x7ba87c, 0x708835, 0x2413d1, 0x6702e3, 0x390116, 0xd9e3f, 0x4bd65c, 0x9a3, + ], + MConst: 0x7cfffd, + SQRTm3: [ + 0x1aaae, 0x0, 0x6d77ec, 0x69ffff, 0x44fd7e, 0x224c4f, 0x4a2ff2, 0x64c014, 0x22e9ab, 0x6c3ecc, + 0x3e8efd, 0x70819f, 0x156845, 0x319d1b, 0x5ff9a6, 0x8f51c, 0x1a01, + ], + CRu: [ + 0x7efffe, 0x7fffff, 0x8b807, 0x105000, 0x7d8136, 0x511bc2, 0x79be25, 0x59d49d, 0x77eadd, + 0xed41e, 0x69a718, 0x36728d, 0x72fdf7, 0xbe32c, 0x0, 0x0, 0x0, + ], + Fra: [ + 0x235fb8, 0x6bdb24, 0x76341d, 0x1f3c09, 0x6a53d6, 0x389ecf, 0x612eae, 0x1221eb, 0x5f4f7b, + 0x7a797a, 0x3f580f, 0x6068f8, 0x6b4202, 0x784637, 0x2ec199, 0x69df81, 0x1904, + ], + Frb: [ + 0x5c4af3, 0x1424db, 0x8b3de, 0x6b63f6, 0x55ac14, 0xbe505, 0x5c7d8f, 0x64764, 0x336fec, + 0xf6d8f, 0x52851e, 0x7cfdc2, 0x102231, 0x511d3d, 0x31380c, 0x1f159b, 0xfc, + ], + }; + + return ROM_FIELD_BLS12381; +}; + +ROM_FIELD_BLS12461 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BLS12461 = { + // BLS12461 Modulus + // Base Bits= 23 + Modulus: [ + 0x2aaaab, 0x155, 0x2aaab0, 0x2aaa55, 0x55, 0x80004, 0x555fc0, 0x135548, 0x1cc00f, 0x3ff4b8, + 0x2d0aa3, 0x58a424, 0x2cca47, 0x465b17, 0x6f5bc7, 0xa49af, 0x55d694, 0x34aab4, 0x155535, + 0x2aaaaa, 0x1, + ], + ROI: [ + 0x2aaaaa, 0x155, 0x2aaab0, 0x2aaa55, 0x55, 0x80004, 0x555fc0, 0x135548, 0x1cc00f, 0x3ff4b8, + 0x2d0aa3, 0x58a424, 0x2cca47, 0x465b17, 0x6f5bc7, 0xa49af, 0x55d694, 0x34aab4, 0x155535, + 0x2aaaaa, 0x1, + ], + R2modp: [ + 0x621498, 0x3b585f, 0x41688, 0x6f780d, 0x17c239, 0x158d8a, 0x491a92, 0x737df1, 0x22a06, + 0x460263, 0x275ff2, 0x5496c3, 0x6d4ad2, 0x3a7b46, 0x3a6323, 0x1723b1, 0x76204b, 0x66fd26, + 0x4e743e, 0x1be66e, 0x0, + ], + MConst: 0x7ffffd, + SQRTm3: [ + 0x2aaaae, 0x7ff955, 0x2aaa8f, 0x2aac55, 0x355, 0x440028, 0x54fd80, 0x4d50d6, 0x415095, + 0x7b9ed2, 0x4566e7, 0x514ff0, 0x2ead34, 0x325192, 0x3f33c7, 0xb89b0, 0x51d694, 0x34aab4, + 0x155535, 0x2aaaaa, 0x1, + ], + CRu: [ + 0x7ffffe, 0x3ff, 0x10, 0x7fff00, 0x7ffe7f, 0x61ffed, 0x311f, 0x630239, 0x6db7bc, 0x622af2, + 0x73d1dd, 0x43aa19, 0x3f0e89, 0xa04c2, 0x581400, 0x7f5fff, 0x1ffff, 0x0, 0x0, 0x0, 0x0, + ], + Fra: [ + 0x12a3a, 0x2f7f37, 0x3dc4, 0x52cce2, 0x1c6308, 0xb7f14, 0x4381d4, 0x52d328, 0x58d45f, + 0x359c90, 0x1dc2cc, 0x616582, 0x7c61eb, 0x6b11c5, 0x64341c, 0x421b30, 0x4dfefa, 0x3cabc4, + 0x12dfda, 0x172028, 0x1, + ], + Frb: [ + 0x298071, 0x50821e, 0x2a6ceb, 0x57dd73, 0x639d4c, 0x7c80ef, 0x11ddeb, 0x408220, 0x43ebaf, + 0xa5827, 0xf47d7, 0x773ea2, 0x30685b, 0x5b4951, 0xb27aa, 0x482e7f, 0x7d799, 0x77fef0, 0x2755a, + 0x138a82, 0x0, + ], + }; + + return ROM_FIELD_BLS12461; +}; + +ROM_FIELD_FP256BN = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_FP256BN = { + // FP256BN Modulus + // Base Bits= 24 + Modulus: [ + 0xd33013, 0x2ddbae, 0x82d329, 0x12980a, 0xdc65fb, 0xa49f0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + ROI: [ + 0xd33012, 0x2ddbae, 0x82d329, 0x12980a, 0xdc65fb, 0xa49f0c, 0x5eee71, 0x46e5f2, 0xfcf0cd, + 0xffffff, 0xffff, + ], + R2modp: [ + 0x2f4801, 0xf779d1, 0x3e7f6e, 0xb42a3a, 0xc919c9, 0xc26c08, 0x1bb715, 0xca2ed6, 0x54293e, + 0xe578e, 0x78ea, + ], + MConst: 0x37e5e5, + SQRTm3: [ + 0x8fc004, 0x199267, 0x451cf1, 0x2f71b0, 0x40b6bf, 0x73d3d5, 0xddca51, 0xd3d42f, 0xfcf0ca, + 0xffffff, 0xffff, + ], + CRu: [ + 0xa1b807, 0xa24a3, 0x1edb1c, 0xf1932d, 0xcdd79d, 0x18659b, 0x409210, 0x3988e1, 0x1, 0x0, 0x0, + ], + Fra: [ + 0x943106, 0x328af, 0x8f7476, 0x1e3ab2, 0xa17151, 0x67cf39, 0x8ddb08, 0x2d1a6e, 0x786f35, + 0x7662ca, 0x3d61, + ], + Frb: [ + 0x3eff0d, 0x2ab2ff, 0xf35eb3, 0xf45d57, 0x3af4a9, 0x3ccfd3, 0xd11369, 0x19cb83, 0x848198, + 0x899d35, 0xc29e, + ], + }; + + return ROM_FIELD_FP256BN; +}; + +ROM_FIELD_FP512BN = function () { + 'use strict'; + + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_FP512BN = { + // FP512BN Modulus + // Base Bits= 23 + Modulus: [ + 0x2def33, 0x501245, 0x1ed3ac, 0x7a6323, 0x255ce5, 0x7c322d, 0x2ac8db, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a2a, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + ROI: [ + 0x2def32, 0x501245, 0x1ed3ac, 0x7a6323, 0x255ce5, 0x7c322d, 0x2ac8db, 0x4632ef, 0x18b8e4, + 0x3d597d, 0x451b3c, 0x77a2a, 0x3c111b, 0x78177c, 0x32d4c1, 0x5d0ec, 0x7f01c6, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + R2modp: [ + 0x23e65d, 0x575a37, 0x411cd0, 0x295fb3, 0x640669, 0x375c69, 0x92395, 0x738492, 0x780d6d, + 0x1bcd9d, 0x417caa, 0x2dc6fb, 0x7eacfb, 0x327043, 0x7f2fc7, 0xf268c, 0x73d733, 0x2147c9, + 0x2accd3, 0x32eaf8, 0x3b2c1e, 0xd46a2, 0x30, + ], + MConst: 0x4c5c05, + // SQRTm3: [0x332330,0x505BC6,0x1C3175,0x1D56FC,0x52DE91,0x5E48D,0x345737,0x415677,0x83CB6,0x651720,0x753DC3,0xA8065,0x35CDD1,0x6B9137,0x2960D9,0x24905A,0x7C8EB4,0x7FF3D8,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x7FFFFF,0x3F], + SQRTm3: [ + 0x4463e2, 0x8702c, 0x6b848c, 0x3e4e58, 0x37724d, 0x287986, 0x346054, 0x415677, 0x83cb6, + 0x651720, 0x753dc3, 0xa8005, 0x35cdd1, 0x6b9137, 0x2960d9, 0x24905a, 0x7c8eb4, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + CRu: [ + 0x79298a, 0x2c4138, 0x52c1c, 0x5c58be, 0x6e6799, 0x1255d9, 0x2f9498, 0x43c4b3, 0x507acd, + 0x11384e, 0x1d2c80, 0x8fd18, 0x78ef76, 0x71d459, 0x2e1acd, 0x1530a3, 0x7dc83d, 0x7ff3d8, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3f, + ], + Fra: [ + 0x373ab2, 0x2f63e9, 0x47d258, 0x101576, 0x1514f6, 0x503c2e, 0x34ef61, 0x4fb040, 0x2cbbb5, + 0x553d0a, 0x63a7e2, 0x10341c, 0x48cf2e, 0x3564d7, 0x25bde4, 0x50c529, 0x468b4e, 0x2d518f, + 0x6de46, 0x7c84ad, 0x1cf5bb, 0x5ee355, 0x7, + ], + Frb: [ + 0x76b481, 0x20ae5b, 0x570154, 0x6a4dac, 0x1047ef, 0x2bf5ff, 0x75d97a, 0x7682ae, 0x6bfd2e, + 0x681c72, 0x617359, 0x77460d, 0x7341ec, 0x42b2a4, 0xd16dd, 0x350bc3, 0x387677, 0x52a249, + 0x7921b9, 0x37b52, 0x630a44, 0x211caa, 0x38, + ], + }; + + return ROM_FIELD_FP512BN; +}; + +ROM_FIELD_BN254 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BN254 = { + // BN254 Modulus + // Base Bits= 24 + Modulus: [0x13, 0x0, 0x13a700, 0x0, 0x210000, 0x861, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + ROI: [0x12, 0x0, 0x13a700, 0x0, 0x210000, 0x861, 0x800000, 0xba344d, 0x1, 0x648240, 0x2523], + R2modp: [ + 0x2f2aa7, 0x537047, 0xf8f174, 0xc3e364, 0xab8c1c, 0x3c2035, 0x69549, 0x379287, 0x3be629, + 0x75617a, 0x1f47, + ], + MConst: 0x9435e5, + SQRTm3: [0x4, 0x0, 0x60c00, 0x0, 0xf0000, 0x3cf, 0x0, 0x26cd89, 0x1, 0x648240, 0x2523], + CRu: [0x7, 0x0, 0x6cd80, 0x0, 0x90000, 0x249, 0x400000, 0x49b362, 0x0, 0x0, 0x0], + Fra: [ + 0x2a6de9, 0xe6c06f, 0xc2e17d, 0x4d3f77, 0x97492, 0x953f85, 0x50a846, 0xb6499b, 0x2e7c8c, + 0x761921, 0x1b37, + ], + Frb: [ + 0xd5922a, 0x193f90, 0x50c582, 0xb2c088, 0x178b6d, 0x6ac8dc, 0x2f57b9, 0x3eab2, 0xd18375, + 0xee691e, 0x9eb, + ], + }; + + return ROM_FIELD_BN254; +}; + +ROM_FIELD_BN254CX = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BN254CX = { + // BN254CX Modulus + // Base Bits= 24 + Modulus: [ + 0x1b55b3, 0x23ef5c, 0xe1be66, 0x18093e, 0x3fd6ee, 0x66d324, 0x647a63, 0xb0bddf, 0x702a0d, 0x8, + 0x2400, + ], + ROI: [ + 0x1b55b2, 0x23ef5c, 0xe1be66, 0x18093e, 0x3fd6ee, 0x66d324, 0x647a63, 0xb0bddf, 0x702a0d, 0x8, + 0x2400, + ], + R2modp: [ + 0x8ee63d, 0x721fde, 0xcc0891, 0x10c28b, 0xd4f5a, 0x4c18fb, 0x9036fa, 0x3f845f, 0xa507e4, + 0x78eb29, 0x1587, + ], + MConst: 0x789e85, + SQRTm3: [ + 0xd49c84, 0xfdc033, 0x355aa4, 0x342a30, 0xc41825, 0xe8aaa2, 0x646112, 0x20bddf, 0x702a0d, 0x8, + 0x2400, + ], + CRu: [ + 0x235c97, 0x931794, 0x5631e0, 0x71ef87, 0xbddf64, 0x3f1440, 0xca8, 0x480000, 0x0, 0x0, 0x0, + ], + Fra: [ + 0xc80ea3, 0x83355, 0x215bd9, 0xf173f8, 0x677326, 0x189868, 0x8aaca7, 0xafe18b, 0x3a0164, + 0x82fa6, 0x1359, + ], + Frb: [ + 0x534710, 0x1bbc06, 0xc0628d, 0x269546, 0xd863c7, 0x4e3abb, 0xd9cdbc, 0xdc53, 0x3628a9, + 0xf7d062, 0x10a6, + ], + }; + + return ROM_FIELD_BN254CX; +}; + +ROM_FIELD_BRAINPOOL = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_BRAINPOOL = { + // Brainpool modulus + // Base Bits= 24 + Modulus: [ + 0x6e5377, 0x481d1f, 0x282013, 0xd52620, 0x3bf623, 0x8d726e, 0x909d83, 0x3e660a, 0xeea9bc, + 0x57dba1, 0xa9fb, + ], + ROI: [ + 0x6e5376, 0x481d1f, 0x282013, 0xd52620, 0x3bf623, 0x8d726e, 0x909d83, 0x3e660a, 0xeea9bc, + 0x57dba1, 0xa9fb, + ], + R2modp: [ + 0x35b819, 0xb03428, 0xecaf0f, 0x3854a4, 0x4a0ed5, 0x2421ea, 0xaa562c, 0xf9c45, 0xddae58, + 0x4350fd, 0x52b8, + ], + MConst: 0xfd89b9, + }; + return ROM_FIELD_BRAINPOOL; +}; + +ROM_FIELD_C41417 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_C41417 = { + // C41417 modulus + // Base Bits= 22 + Modulus: [ + 0x3fffef, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3ffff, + ], + ROI: [ + 0x3fffee, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, 0x3fffff, + 0x3ffff, + ], + R2modp: [ + 0x12100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, + ], + MConst: 0x11, + }; + return ROM_FIELD_C41417; +}; + +ROM_FIELD_C1174 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_C1174 = { + // C1174 modulus + // Base Bits= 24 + Modulus: [ + 0xfffff7, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x7ff, + ], + R2modp: [0x0, 0x144, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ROI: [ + 0xfffff6, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0x7ff, + ], + MConst: 0x9, + }; + return ROM_FIELD_C1174; +}; + +ROM_FIELD_C1665 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + var ROM_FIELD_C1665 = { + // C1665 modulus + // Base Bits= 23 + Modulus: [0x7ffffb, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x1f], + R2modp: [0x0, 0x32000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + ROI: [0x7ffffa, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x1f], + MConst: 0x5, + }; + return ROM_FIELD_C1665; +}; + +ROM_FIELD_MDC = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + var ROM_FIELD_MDC = { + // Million Dollar Curve modulus + // Base Bits= 24 + Modulus: [ + 0x79ec13, 0x104057, 0x9ec137, 0xef07af, 0x6a9037, 0xfd4f08, 0xfdd7a5, 0x532f92, 0x56afb4, + 0x68b9d4, 0xf13b, + ], + R2modp: [ + 0xfff702, 0x31619a, 0xba623e, 0xc672c1, 0xf5883f, 0x39e4ab, 0x4589, 0x972c4a, 0xd61255, + 0x6e22d, 0x7c41, + ], + ROI: [ + 0x79ec12, 0x104057, 0x9ec137, 0xef07af, 0x6a9037, 0xfd4f08, 0xfdd7a5, 0x532f92, 0x56afb4, + 0x68b9d4, 0xf13b, + ], + MConst: 0xe541e5, + }; + return ROM_FIELD_MDC; +}; + +ROM_FIELD_GOLDILOCKS = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_GOLDILOCKS = { + // GOLDILOCKS modulus + // Base Bits= 23 + Modulus: [ + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7dffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7ff, + ], + ROI: [ + 0x7ffffe, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7dffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7ff, + ], + R2modp: [ + 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, + ], + MConst: 0x1, + }; + return ROM_FIELD_GOLDILOCKS; +}; + +ROM_FIELD_HIFIVE = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_HIFIVE = { + // HIFIVE modulus + // Base Bits= 23 + Modulus: [ + 0x7ffffd, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x3fff, + ], + ROI: [ + 0x59d3b8, 0x104fea, 0xdae01, 0x49f563, 0x14538b, 0x2bb499, 0x7f2a2e, 0x30f6d4, 0x18c41f, + 0x2a7bef, 0x62cad1, 0x408fe1, 0x1ef527, 0x787c06, 0x3e4f, + ], + R2modp: [0x240000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + MConst: 0x3, + }; + return ROM_FIELD_HIFIVE; +}; + +ROM_FIELD_NIST256 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_NIST256 = { + // NIST256 Modulus + // Base Bits= 24 + Modulus: [0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x0, 0x0, 0x0, 0x0, 0x1, 0xffff00, 0xffff], + ROI: [0xfffffe, 0xffffff, 0xffffff, 0xffffff, 0x0, 0x0, 0x0, 0x0, 0x1, 0xffff00, 0xffff], + R2modp: [ + 0x30000, 0x0, 0x0, 0xffff00, 0xfbffff, 0xffffff, 0xfffffe, 0xffffff, 0xfdffff, 0xffffff, 0x4, + ], + MConst: 0x1, + }; + return ROM_FIELD_NIST256; +}; + +ROM_FIELD_SM2 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_SM2 = { + // SM2 Modulus + // Base Bits= 24 + Modulus: [ + 0xffffff, 0xffffff, 0xffff, 0x0, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xfffeff, + 0xffff, + ], + ROI: [ + 0xfffffe, 0xffffff, 0xffff, 0x0, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xfffeff, + 0xffff, + ], + R2modp: [0x30000, 0x0, 0x2, 0xffff00, 0x2ffff, 0x0, 0x1, 0x100, 0x20000, 0x0, 0x4], + MConst: 0x1, + }; + return ROM_FIELD_SM2; +}; + +ROM_FIELD_NIST384 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_NIST384 = { + // NIST384 modulus + // Base Bits= 23 + Modulus: [ + 0x7fffff, 0x1ff, 0x0, 0x0, 0x7ffff0, 0x7fdfff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + ROI: [ + 0x7ffffe, 0x1ff, 0x0, 0x0, 0x7ffff0, 0x7fdfff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0xffff, + ], + R2modp: [ + 0x4000, 0x0, 0x7ffffe, 0x1ff, 0x80000, 0x0, 0x0, 0x7fc000, 0x3fffff, 0x0, 0x200, 0x20000, 0x0, + 0x0, 0x0, 0x0, 0x0, + ], + MConst: 0x1, + }; + return ROM_FIELD_NIST384; +}; + +ROM_FIELD_NIST521 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_NIST521 = { + // NIST521 modulus + // Base Bits= 23 + Modulus: [ + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fff, + ], + ROI: [ + 0x7ffffe, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, + 0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff, 0x7fff, + ], + R2modp: [ + 0x10000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + ], + MConst: 0x1, + }; + return ROM_FIELD_NIST521; +}; + +ROM_FIELD_SECP256K1 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_SECP256K1 = { + // SECP256K1 modulus + // Base Bits= 24 + Modulus: [ + 0xfffc2f, 0xfffeff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + ROI: [ + 0xfffc2e, 0xfffeff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, + 0xffffff, 0xffff, + ], + R2modp: [0xa10000, 0xe90, 0x7a2, 0x100, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], + MConst: 0x253531, + SQRTm3: [ + 0xd5f852, 0x27ae1c, 0xd47d8d, 0xda14ec, 0x1f6d15, 0x962cc6, 0xc2a797, 0x233770, 0x7f1df, + 0x2ba935, 0xa2d, + ], + }; + return ROM_FIELD_SECP256K1; +}; + +ROM_FIELD_SECP160R1 = function () { + 'use strict'; + /* Fixed Data in ROM - Field and Curve parameters */ + + var ROM_FIELD_SECP160R1 = { + // SECP160R1 modulus + // Base Bits= 24 + Modulus: [0xffffff, 0xffff7f, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffff], + R2modp: [0x10000, 0x0, 0x1, 0x40, 0x0, 0x0, 0x0], + ROI: [0xfffffe, 0xffff7f, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffff], + MConst: 0x1, + }; + return ROM_FIELD_SECP160R1; +}; + +ROM_FIELD_JUBJUB = function () { + 'use strict'; + // Fixed Data in ROM - Field and Curve parameters + + var ROM_FIELD_JUBJUB = { + // Base Bits= 24 + Modulus: [ + 0x1, 0xffff00, 0xfeffff, 0xfffe5b, 0xbda402, 0xd80553, 0x809a1, 0x3339d8, 0x9d7d48, 0xa75329, + 0x73ed, + ], + R2modp: [ + 0x6cefea, 0x4089c, 0xafe991, 0x7687f1, 0x3f3f50, 0x45bbe1, 0x94826, 0x101d61, 0xb3be6b, + 0xb9a93, 0x8f8, + ], + ROI: [ + 0x912f1f, 0x8f500b, 0x941b78, 0x70b3e0, 0x24ff2, 0xd6c0c4, 0xc8d168, 0xfd56d, 0x416b6f, + 0xd79e5b, 0x212, + ], + MConst: 0xffffff, + }; + return ROM_FIELD_JUBJUB; +}; + +ROM_FIELD_TWEEDLEDUM = function () { + 'use strict'; + // Fixed Data in ROM - Field and Curve parameters + + var ROM_FIELD_TWEEDLEDUM = { + // Base bits= 24 + Modulus: [0x1, 0x64e200, 0xb9a140, 0x6c3f59, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + R2modp: [ + 0xffcde, 0xf3fc00, 0x817083, 0x90fd10, 0x4e767f, 0x919928, 0x94c659, 0x28e190, 0xedd7b, + 0x7ccca, 0x2d91, + ], + ROI: [ + 0x8837ce, 0x9f31b8, 0xd653de, 0xf3ea99, 0x46e8f3, 0x2d57ff, 0xeaaf8c, 0xf624f2, 0xee2fc, + 0x511789, 0x2ae4, + ], + SQRTm3: [ + 0xde6c70, 0xd7ab7, 0x6c960f, 0x34f725, 0x86aae0, 0x84cb12, 0xd7220f, 0xc8286d, 0x2d06d6, + 0x7d4a94, 0x15ef, + ], + MConst: 0xffffff, + }; + return ROM_FIELD_TWEEDLEDUM; +}; + +ROM_FIELD_TWEEDLEDEE = function () { + 'use strict'; + // Fixed Data in ROM - Field and Curve parameters + + var ROM_FIELD_TWEEDLEDEE = { + // Base bits= 24 + Modulus: [0x1, 0xafd400, 0xc9842c, 0x696286, 0x8aa127, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4000], + R2modp: [ + 0xffcde, 0x29d800, 0x45e681, 0x2b8642, 0x18e911, 0x7e0b8d, 0x3aa0a2, 0xe6fcb0, 0x13f4c0, + 0x68860, 0x2d91, + ], + ROI: [ + 0x9d57ec, 0x323486, 0xbf1cbd, 0xb8084f, 0x287dd1, 0x72930a, 0x645a98, 0xf1dbcb, 0xc03c0b, + 0xfc510d, 0x113e, + ], + SQRTm3: [ + 0x1f49fa, 0xd5a629, 0xb902fc, 0xd867d6, 0x147aa6, 0x3ffcd0, 0xbff2e6, 0xf5b16, 0x934b1, + 0xda743c, 0x2d8c, + ], + MConst: 0xffffff, + }; + return ROM_FIELD_TWEEDLEDEE; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + ROM_FIELD_25519: ROM_FIELD_25519, + ROM_FIELD_256PM: ROM_FIELD_256PM, + ROM_FIELD_384PM: ROM_FIELD_384PM, + ROM_FIELD_512PM: ROM_FIELD_512PM, + ROM_FIELD_ANSSI: ROM_FIELD_ANSSI, + ROM_FIELD_FP256BN: ROM_FIELD_FP256BN, + ROM_FIELD_FP512BN: ROM_FIELD_FP512BN, + ROM_FIELD_BN254: ROM_FIELD_BN254, + ROM_FIELD_BN254CX: ROM_FIELD_BN254CX, + ROM_FIELD_BRAINPOOL: ROM_FIELD_BRAINPOOL, + ROM_FIELD_C41417: ROM_FIELD_C41417, + ROM_FIELD_GOLDILOCKS: ROM_FIELD_GOLDILOCKS, + ROM_FIELD_HIFIVE: ROM_FIELD_HIFIVE, + ROM_FIELD_NIST256: ROM_FIELD_NIST256, + ROM_FIELD_NIST384: ROM_FIELD_NIST384, + ROM_FIELD_NIST521: ROM_FIELD_NIST521, + ROM_FIELD_SECP256K1: ROM_FIELD_SECP256K1, + ROM_FIELD_BLS12383: ROM_FIELD_BLS12383, + ROM_FIELD_BLS24479: ROM_FIELD_BLS24479, + ROM_FIELD_BLS48556: ROM_FIELD_BLS48556, + ROM_FIELD_BLS48286: ROM_FIELD_BLS48286, + ROM_FIELD_BLS48581: ROM_FIELD_BLS48581, + ROM_FIELD_BLS12381: ROM_FIELD_BLS12381, + ROM_FIELD_BLS12461: ROM_FIELD_BLS12461, + ROM_FIELD_BN462: ROM_FIELD_BN462, + ROM_FIELD_C1174: ROM_FIELD_C1174, + ROM_FIELD_C1665: ROM_FIELD_C1665, + ROM_FIELD_MDC: ROM_FIELD_MDC, + ROM_FIELD_SECP160R1: ROM_FIELD_SECP160R1, + ROM_FIELD_SM2: ROM_FIELD_SM2, + ROM_FIELD_JUBJUB: ROM_FIELD_JUBJUB, + ROM_FIELD_TWEEDLEDUM: ROM_FIELD_TWEEDLEDUM, + ROM_FIELD_TWEEDLEDEE: ROM_FIELD_TWEEDLEDEE, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/rsa.js b/packages/bls-verify/src/vendor/amcl-js/src/rsa.js new file mode 100644 index 000000000..9134e6b75 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/rsa.js @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* RSA API Functions */ +var RSA, rsa_private_key, rsa_public_key; + +RSA = function (ctx) { + 'use strict'; + + var RSA = { + RFS: ctx.BIG.MODBYTES * ctx.FF.FFLEN, + HASH_TYPE: 32, + + bytestohex: function (b) { + var s = '', + len = b.length, + ch, + i; + + for (i = 0; i < len; i++) { + ch = b[i]; + s += ((ch >>> 4) & 15).toString(16); + s += (ch & 15).toString(16); + } + return s; + }, + + bytestostring: function (b) { + var s = '', + i; + + for (i = 0; i < b.length; i++) { + s += String.fromCharCode(b[i]); + } + + return s; + }, + + stringtobytes: function (s) { + var b = [], + i; + + for (i = 0; i < s.length; i++) { + b.push(s.charCodeAt(i)); + } + + return b; + }, + + KEY_PAIR: function (rng, e, PRIV, PUB) { + /* IEEE1363 A16.11/A16.12 more or less */ + var n = PUB.n.length >> 1, + t = new ctx.FF(n), + p1 = new ctx.FF(n), + q1 = new ctx.FF(n); + + for (;;) { + PRIV.p.random(rng); + + while (PRIV.p.lastbits(2) != 3) { + PRIV.p.inc(1); + } + + while (!ctx.FF.prime(PRIV.p, rng)) { + PRIV.p.inc(4); + } + + p1.copy(PRIV.p); + p1.dec(1); + + if (p1.cfactor(e)) { + continue; + } + + break; + } + + for (;;) { + PRIV.q.random(rng); + + while (PRIV.q.lastbits(2) != 3) { + PRIV.q.inc(1); + } + + while (!ctx.FF.prime(PRIV.q, rng)) { + PRIV.q.inc(4); + } + + q1.copy(PRIV.q); + q1.dec(1); + + if (q1.cfactor(e)) { + continue; + } + + break; + } + + PUB.n = ctx.FF.mul(PRIV.p, PRIV.q); + PUB.e = e; + + t.copy(p1); + t.shr(); + PRIV.dp.set(e); + PRIV.dp.invmodp(t); + if (PRIV.dp.parity() === 0) { + PRIV.dp.add(t); + } + PRIV.dp.norm(); + + t.copy(q1); + t.shr(); + PRIV.dq.set(e); + PRIV.dq.invmodp(t); + if (PRIV.dq.parity() === 0) { + PRIV.dq.add(t); + } + PRIV.dq.norm(); + + PRIV.c.copy(PRIV.p); + PRIV.c.invmodp(PRIV.q); + + return; + }, + + /* destroy the Private Key structure */ + PRIVATE_KEY_KILL: function (PRIV) { + PRIV.p.zero(); + PRIV.q.zero(); + PRIV.dp.zero(); + PRIV.dq.zero(); + PRIV.c.zero(); + }, + + /* RSA encryption with the public key */ + ENCRYPT: function (PUB, F, G) { + var n = PUB.n.getlen(), + f = new ctx.FF(n); + + ctx.FF.fromBytes(f, F); + + f.power(PUB.e, PUB.n); + + f.toBytes(G); + }, + + /* RSA decryption with the private key */ + DECRYPT: function (PRIV, G, F) { + var n = PRIV.p.getlen(), + g = new ctx.FF(2 * n), + jp, + jq, + t; + + ctx.FF.fromBytes(g, G); + + jp = g.dmod(PRIV.p); + jq = g.dmod(PRIV.q); + + jp.skpow(PRIV.dp, PRIV.p); + jq.skpow(PRIV.dq, PRIV.q); + + g.zero(); + g.dscopy(jp); + jp.mod(PRIV.q); + if (ctx.FF.comp(jp, jq) > 0) { + jq.add(PRIV.q); + } + jq.sub(jp); + jq.norm(); + + t = ctx.FF.mul(PRIV.c, jq); + jq = t.dmod(PRIV.q); + + t = ctx.FF.mul(jq, PRIV.p); + g.add(t); + g.norm(); + + g.toBytes(F); + }, + }; + + return RSA; +}; + +rsa_private_key = function (ctx) { + 'use strict'; + + var rsa_private_key = function (n) { + this.p = new ctx.FF(n); + this.q = new ctx.FF(n); + this.dp = new ctx.FF(n); + this.dq = new ctx.FF(n); + this.c = new ctx.FF(n); + }; + + rsa_private_key.prototype = { + set: function (p, q, dp, dq, c) { + this.p = p; + this.q = q; + this.dp = dp; + this.dq = dq; + this.c = c; + }, + + set_p: function (p) { + this.p = p; + }, + + set_q: function (q) { + this.q = q; + }, + + set_dp: function (dp) { + this.dp = dp; + }, + + set_dq: function (dq) { + this.dq = dq; + }, + + set_c: function (c) { + this.c = c; + }, + }; + + rsa_private_key.get_instance = function (p, q, dp, dq, c) { + let priv = new rsa_private_key(ctx.FF.HFLEN); + priv.set(p, q, dp, dq, c); + return priv; + }; + + return rsa_private_key; +}; + +rsa_public_key = function (ctx) { + 'use strict'; + + var rsa_public_key = function (m) { + this.e = 0; + this.n = new ctx.FF(m); + }; + + rsa_public_key.prototype = { + set: function (n, e) { + this.e = e; + ctx.FF.fromBytes(this.n, n); + }, + + set_e: function (e) { + this.e = e; + }, + + set_n: function (n) { + ctx.FF.fromBytes(this.n, n); + }, + }; + + rsa_public_key.get_instance = function (n, e) { + var pub = new rsa_public_key(ctx.FF.FFLEN); + pub.set(n, e); + return pub; + }; + + return rsa_public_key; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + RSA: RSA, + rsa_private_key: rsa_private_key, + rsa_public_key: rsa_public_key, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/sha3.js b/packages/bls-verify/src/vendor/amcl-js/src/sha3.js new file mode 100644 index 000000000..8d3fc1bfd --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/sha3.js @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Implementation of the Secure Hashing Algorithm SHA-3 + + * Generates a message digest. It should be impossible to come + * come up with two messages that hash to the same value ("collision free"). + * + * For use with byte-oriented messages only. + */ + +var SHA3 = function (ctx) { + 'use strict'; + + var SHA3 = function (olen) { + this.length = 0; + this.rate = 0; + this.len = 0; + this.S = []; + this.init(olen); + }; + + SHA3.prototype = { + transform: function () { + var C = [], + D = [], + B = [], + i, + j, + k; + + for (k = 0; k < SHA3.ROUNDS; k++) { + C[0] = new ctx.UInt64( + this.S[0][0].top ^ + this.S[0][1].top ^ + this.S[0][2].top ^ + this.S[0][3].top ^ + this.S[0][4].top, + this.S[0][0].bot ^ + this.S[0][1].bot ^ + this.S[0][2].bot ^ + this.S[0][3].bot ^ + this.S[0][4].bot, + ); + C[1] = new ctx.UInt64( + this.S[1][0].top ^ + this.S[1][1].top ^ + this.S[1][2].top ^ + this.S[1][3].top ^ + this.S[1][4].top, + this.S[1][0].bot ^ + this.S[1][1].bot ^ + this.S[1][2].bot ^ + this.S[1][3].bot ^ + this.S[1][4].bot, + ); + C[2] = new ctx.UInt64( + this.S[2][0].top ^ + this.S[2][1].top ^ + this.S[2][2].top ^ + this.S[2][3].top ^ + this.S[2][4].top, + this.S[2][0].bot ^ + this.S[2][1].bot ^ + this.S[2][2].bot ^ + this.S[2][3].bot ^ + this.S[2][4].bot, + ); + C[3] = new ctx.UInt64( + this.S[3][0].top ^ + this.S[3][1].top ^ + this.S[3][2].top ^ + this.S[3][3].top ^ + this.S[3][4].top, + this.S[3][0].bot ^ + this.S[3][1].bot ^ + this.S[3][2].bot ^ + this.S[3][3].bot ^ + this.S[3][4].bot, + ); + C[4] = new ctx.UInt64( + this.S[4][0].top ^ + this.S[4][1].top ^ + this.S[4][2].top ^ + this.S[4][3].top ^ + this.S[4][4].top, + this.S[4][0].bot ^ + this.S[4][1].bot ^ + this.S[4][2].bot ^ + this.S[4][3].bot ^ + this.S[4][4].bot, + ); + + D[0] = SHA3.xor(C[4], SHA3.rotl(C[1], 1)); + D[1] = SHA3.xor(C[0], SHA3.rotl(C[2], 1)); + D[2] = SHA3.xor(C[1], SHA3.rotl(C[3], 1)); + D[3] = SHA3.xor(C[2], SHA3.rotl(C[4], 1)); + D[4] = SHA3.xor(C[3], SHA3.rotl(C[0], 1)); + + for (i = 0; i < 5; i++) { + B[i] = []; + for (j = 0; j < 5; j++) { + B[i][j] = new ctx.UInt64(0, 0); + this.S[i][j] = SHA3.xor(this.S[i][j], D[i]); + } + } + + B[0][0] = this.S[0][0].copy(); + B[1][3] = SHA3.rotl(this.S[0][1], 36); + B[2][1] = SHA3.rotl(this.S[0][2], 3); + B[3][4] = SHA3.rotl(this.S[0][3], 41); + B[4][2] = SHA3.rotl(this.S[0][4], 18); + + B[0][2] = SHA3.rotl(this.S[1][0], 1); + B[1][0] = SHA3.rotl(this.S[1][1], 44); + B[2][3] = SHA3.rotl(this.S[1][2], 10); + B[3][1] = SHA3.rotl(this.S[1][3], 45); + B[4][4] = SHA3.rotl(this.S[1][4], 2); + + B[0][4] = SHA3.rotl(this.S[2][0], 62); + B[1][2] = SHA3.rotl(this.S[2][1], 6); + B[2][0] = SHA3.rotl(this.S[2][2], 43); + B[3][3] = SHA3.rotl(this.S[2][3], 15); + B[4][1] = SHA3.rotl(this.S[2][4], 61); + + B[0][1] = SHA3.rotl(this.S[3][0], 28); + B[1][4] = SHA3.rotl(this.S[3][1], 55); + B[2][2] = SHA3.rotl(this.S[3][2], 25); + B[3][0] = SHA3.rotl(this.S[3][3], 21); + B[4][3] = SHA3.rotl(this.S[3][4], 56); + + B[0][3] = SHA3.rotl(this.S[4][0], 27); + B[1][1] = SHA3.rotl(this.S[4][1], 20); + B[2][4] = SHA3.rotl(this.S[4][2], 39); + B[3][2] = SHA3.rotl(this.S[4][3], 8); + B[4][0] = SHA3.rotl(this.S[4][4], 14); + + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + this.S[i][j] = SHA3.xor( + B[i][j], + SHA3.and(SHA3.not(B[(i + 1) % 5][j]), B[(i + 2) % 5][j]), + ); + } + } + + this.S[0][0] = SHA3.xor(this.S[0][0], SHA3.RC[k]); + } + }, + + copy: function (b) { + var i, j; + this.length = b.length; + this.len = b.len; + this.rate = b.rate; + for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) this.S[i][j] = b.S[i][j].copy(); + }, + + /* Initialise Hash function */ + init: function (olen) { + /* initialise */ + var i, j; + for (i = 0; i < 5; i++) { + this.S[i] = []; + for (j = 0; j < 5; j++) { + this.S[i][j] = new ctx.UInt64(0, 0); + } + } + this.length = 0; + this.len = olen; + this.rate = 200 - 2 * olen; + }, + + /* process a single byte */ + process: function (byt) { + /* process the next message byte */ + var i, j, k, b, cnt, el; + + cnt = this.length % this.rate; + b = cnt % 8; + cnt >>= 3; + i = cnt % 5; + j = Math.floor(cnt / 5); /* process by columns! */ + + el = new ctx.UInt64(0, byt); + for (k = 0; k < b; k++) { + el.shlb(); + } + this.S[i][j] = SHA3.xor(this.S[i][j], el); + + this.length++; + if (this.length % this.rate == 0) { + this.transform(); + } + }, + + /* process an array of bytes */ + process_array: function (b) { + for (var i = 0; i < b.length; i++) { + this.process(b[i]); + } + }, + + /* process a 32-bit integer */ + process_num: function (n) { + this.process((n >> 24) & 0xff); + this.process((n >> 16) & 0xff); + this.process((n >> 8) & 0xff); + this.process(n & 0xff); + }, + + /* squeeze the sponge */ + squeeze: function (buff, olen) { + var done, + m = 0, + i, + j, + k, + el; + + /* extract by columns */ + done = false; + + for (;;) { + for (j = 0; j < 5; j++) { + for (i = 0; i < 5; i++) { + el = this.S[i][j].copy(); + for (k = 0; k < 8; k++) { + buff[m++] = el.bot & 0xff; + if (m >= olen || m % this.rate == 0) { + done = true; + break; + } + el = SHA3.rotl(el, 56); + } + + if (done) { + break; + } + } + + if (done) { + break; + } + } + + if (m >= olen) { + break; + } + + done = false; + this.transform(); + } + }, + + hash: function () { + /* pad message and finish - supply digest */ + var buff = []; + var q = this.rate - (this.length % this.rate); + if (q == 1) { + this.process(0x86); + } else { + this.process(0x06); /* 0x06 for SHA-3 */ + while (this.length % this.rate != this.rate - 1) { + this.process(0x00); + } + this.process(0x80); /* this will force a final transform */ + } + this.squeeze(buff, this.len); + return buff; + }, + + continuing_hash() { + var sh = new SHA3(); + sh.copy(this); + return sh.hash(); + }, + + shake: function (buff, olen) { + /* pad message and finish - supply digest */ + var q = this.rate - (this.length % this.rate); + if (q == 1) { + this.process(0x9f); + } else { + this.process(0x1f); /* 0x06 for SHA-3 */ + while (this.length % this.rate != this.rate - 1) { + this.process(0x00); + } + this.process(0x80); /* this will force a final transform */ + } + this.squeeze(buff, olen); + }, + + continuing_shake(buff, olen) { + var sh = new SHA3(); + sh.copy(this); + sh.shake(buff, olen); + }, + }; + + /* static functions */ + SHA3.rotl = function (x, n) { + if (n == 0) { + return x; + } + + if (n < 32) { + return new ctx.UInt64( + (x.top << n) | (x.bot >>> (32 - n)), + (x.bot << n) | (x.top >>> (32 - n)), + ); + } else { + return new ctx.UInt64( + (x.bot << (n - 32)) | (x.top >>> (64 - n)), + (x.top << (n - 32)) | (x.bot >>> (64 - n)), + ); + } + }; + + SHA3.xor = function (a, b) { + return new ctx.UInt64(a.top ^ b.top, a.bot ^ b.bot); + }; + + SHA3.and = function (a, b) { + return new ctx.UInt64(a.top & b.top, a.bot & b.bot); + }; + + SHA3.not = function (a) { + return new ctx.UInt64(~a.top, ~a.bot); + }; + + /* constants */ + SHA3.ROUNDS = 24; + SHA3.HASH224 = 28; + SHA3.HASH256 = 32; + SHA3.HASH384 = 48; + SHA3.HASH512 = 64; + SHA3.SHAKE128 = 16; + SHA3.SHAKE256 = 32; + + SHA3.RC = [ + new ctx.UInt64(0x00000000, 0x00000001), + new ctx.UInt64(0x00000000, 0x00008082), + new ctx.UInt64(0x80000000, 0x0000808a), + new ctx.UInt64(0x80000000, 0x80008000), + new ctx.UInt64(0x00000000, 0x0000808b), + new ctx.UInt64(0x00000000, 0x80000001), + new ctx.UInt64(0x80000000, 0x80008081), + new ctx.UInt64(0x80000000, 0x00008009), + new ctx.UInt64(0x00000000, 0x0000008a), + new ctx.UInt64(0x00000000, 0x00000088), + new ctx.UInt64(0x00000000, 0x80008009), + new ctx.UInt64(0x00000000, 0x8000000a), + new ctx.UInt64(0x00000000, 0x8000808b), + new ctx.UInt64(0x80000000, 0x0000008b), + new ctx.UInt64(0x80000000, 0x00008089), + new ctx.UInt64(0x80000000, 0x00008003), + new ctx.UInt64(0x80000000, 0x00008002), + new ctx.UInt64(0x80000000, 0x00000080), + new ctx.UInt64(0x00000000, 0x0000800a), + new ctx.UInt64(0x80000000, 0x8000000a), + new ctx.UInt64(0x80000000, 0x80008081), + new ctx.UInt64(0x80000000, 0x00008080), + new ctx.UInt64(0x00000000, 0x80000001), + new ctx.UInt64(0x80000000, 0x80008008), + ]; + + return SHA3; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + SHA3: SHA3, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/share.js b/packages/bls-verify/src/vendor/amcl-js/src/share.js new file mode 100644 index 000000000..5075f1b41 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/share.js @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Shamir threshold secret sharing module */ +/* Split any byte array into number of shares < 256 */ +/* Specify number of shares required for recovery - nsr */ + +/* See TestMPIN.html for an example of use */ + +var SHARE = function (ctx) { + 'use strict'; + + /* Return a share of M */ + /* input id - Unique share ID */ + /* input nsr - Number of shares required for recovery */ + /* input Message M to be shared */ + /* input Random seed R */ + /* return share structure */ + var SHARE = function (id, nsr, M, R) { + this.ID = 0; + this.NSR = 0; + this.B = []; + if (id < 1 || id >= 256 || nsr < 2 || nsr >= 256) return; + this.ID = id; + this.NSR = nsr; + var m = M.length; + var rng = new ctx.RAND(); + rng.clean(); + rng.seed(R.length, R); + for (var j = 0; j < m; j++) { + var x = this.ID; + this.B[j] = M[j]; + for (var n = 1; n < nsr; n++) { + this.B[j] = SHARE.add(this.B[j], SHARE.mul(rng.getByte(), x)); + x = SHARE.mul(x, this.ID); + } + } + }; + + /* recover M from shares */ + SHARE.recover = function (S) { + var m = S[0].B.length; + var nsr = S[0].NSR; + if (nsr != S.length) return null; + for (var i = 1; i < nsr; i++) { + if (S[i].NSR != nsr || S[i].B.length != m) return null; + } + var M = []; + var x = []; + var y = []; + for (var j = 0; j < m; j++) { + for (var i = 0; i < nsr; i++) { + x[i] = S[i].ID; + y[i] = S[i].B[j]; + } + M[j] = SHARE.interpolate(nsr, x, y); + } + return M; + }; + + /* Internal functions */ + + SHARE.add = function (x, y) { + return x ^ y; + }; + + SHARE.mul = function (x, y) { + var ix = x & 0xff, + iy = y & 0xff, + lx = SHARE.ltab[ix] & 0xff, + ly = SHARE.ltab[iy] & 0xff; + + if (x !== 0 && y !== 0) { + return SHARE.ptab[(lx + ly) % 255]; + } else { + return 0; + } + }; + + SHARE.inv = function (x) { + var ix = x & 0xff; + var lx = SHARE.ltab[ix] & 0xff; + return SHARE.ptab[255 - lx]; + }; + + SHARE.interpolate = function (n, x, y) { + var i, j; + var p, + yp = 0; + for (i = 0; i < n; i++) { + p = 1; + for (j = 0; j < n; j++) + if (i != j) p = SHARE.mul(p, SHARE.mul(x[j], SHARE.inv(SHARE.add(x[i], x[j])))); + yp = SHARE.add(yp, SHARE.mul(p, y[i])); + } + return yp; + }; + + SHARE.ptab = [ + 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, + 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, + 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, + 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, + 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11, + 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, + 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, 94, + 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, + 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, + 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, + 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, + 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162, 253, + 28, 36, 108, 180, 199, 82, 246, 1, + ]; + SHARE.ltab = [ + 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, + 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, + 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, + 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, 48, + 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, + 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, + 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, 215, + 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, + 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, + 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, + 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, + 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, + 140, 128, 192, 247, 112, 7, + ]; + return SHARE; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + SHARE: SHARE, + }; +} diff --git a/packages/bls-verify/src/vendor/amcl-js/src/uint64.js b/packages/bls-verify/src/vendor/amcl-js/src/uint64.js new file mode 100644 index 000000000..75cbd7137 --- /dev/null +++ b/packages/bls-verify/src/vendor/amcl-js/src/uint64.js @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012-2020 MIRACL UK Ltd. + * + * This file is part of MIRACL Core + * (see https://github.com/miracl/core). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* rudimentary unsigned 64-bit type for SHA384 and SHA512 */ + +var UInt64 = function () { + 'use strict'; + + var UInt64 = function (top, bot) { + this.top = top; + this.bot = bot; + }; + + UInt64.prototype = { + add: function (y) { + var t = (this.bot >>> 0) + (y.bot >>> 0), + low = t >>> 0, + high = (this.top >>> 0) + (y.top >>> 0); + + this.bot = low; + + if (low != t) { + this.top = (high + 1) >>> 0; + } else { + this.top = high; + } + + return this; + }, + + copy: function () { + var r = new UInt64(this.top, this.bot); + return r; + }, + + shlb: function () { + var t = this.bot >>> 24; + this.top = t + (this.top << 8); + this.bot <<= 8; + return this; + }, + }; + + return UInt64; +}; + +if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { + module.exports = { + UInt64: UInt64, + }; +} From ea1c46b092e6feea122fce87f285173b9f612232 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 8 Sep 2022 15:25:22 -0700 Subject: [PATCH 4/5] changelog --- docs/generated/changelog.html | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/generated/changelog.html b/docs/generated/changelog.html index 0be4a7707..1ec36b0ce 100644 --- a/docs/generated/changelog.html +++ b/docs/generated/changelog.html @@ -12,15 +12,24 @@

Agent-JS Changelog

Version 0.13.3

    +
  • + New package: @dfinity/bls-verify. This package provides a pure-js implementation of BLS + verification using the miracl-core package. This can be used to polyfill BLS verification + for agent-js, but it is notably very slow (~3s per verification). Optimization may be + possible with a significant refactoring +
  • adds ability to polyfill bls verification in Certificate
  • Auth Client moves key fallback generation to the create method instead of login and makes the _key non-nullable. This fixes a regression with async window.open behavior in Safari
  • - HttpAgent now offers a method to sync time with the replica, provided a specific canister. - This can be used to set proper Expiry times when a device has fallen out of sync with the replica. + HttpAgent now offers a method to sync time with the replica, provided a specific canister. + This can be used to set proper Expiry times when a device has fallen out of sync with the + replica. +
+

Version 0.13.2

  • auth-client avoids localstorage global and can be used in a web worker or nodejs
  • From f0f7e387687d3c8e4d300821bb7cd393cf73d705 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Fri, 9 Sep 2022 11:11:13 -0700 Subject: [PATCH 5/5] removing declarations, deleting lib files --- packages/bls-verify/.gitignore | 2 + packages/bls-verify/lib/cjs/index.js | 20 ---------- packages/bls-verify/lib/cjs/utils.js | 59 ---------------------------- packages/bls-verify/lib/esm/index.js | 16 -------- packages/bls-verify/lib/esm/utils.js | 52 ------------------------ packages/bls-verify/tsconfig.json | 6 +-- 6 files changed, 5 insertions(+), 150 deletions(-) delete mode 100644 packages/bls-verify/lib/cjs/index.js delete mode 100644 packages/bls-verify/lib/cjs/utils.js delete mode 100644 packages/bls-verify/lib/esm/index.js delete mode 100644 packages/bls-verify/lib/esm/utils.js diff --git a/packages/bls-verify/.gitignore b/packages/bls-verify/.gitignore index ebb03fc9f..0f8c5c094 100644 --- a/packages/bls-verify/.gitignore +++ b/packages/bls-verify/.gitignore @@ -15,3 +15,5 @@ dist/ !webpack.config.js !jest.config.js !test-setup.js + +lib/** diff --git a/packages/bls-verify/lib/cjs/index.js b/packages/bls-verify/lib/cjs/index.js deleted file mode 100644 index dffc55576..000000000 --- a/packages/bls-verify/lib/cjs/index.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -exports.blsVerify = void 0; -const bls12_381_1 = require('@noble/bls12-381'); -const utils_1 = require('./utils'); -/** - * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation - * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature - * @param {Uint8Array | string} signature - digital signature - * @param {Uint8Array | string} message - message to verify - * @returns boolean - */ -const blsVerify = async (publicKey, signature, message) => { - const pk = typeof publicKey === 'string' ? publicKey : (0, utils_1.toHex)(publicKey); - const sig = typeof signature === 'string' ? signature : (0, utils_1.toHex)(signature); - const msg = typeof message === 'string' ? message : (0, utils_1.toHex)(message); - return await (0, bls12_381_1.verify)(sig, msg, pk); -}; -exports.blsVerify = blsVerify; -//# sourceMappingURL=index.js.map diff --git a/packages/bls-verify/lib/cjs/utils.js b/packages/bls-verify/lib/cjs/utils.js deleted file mode 100644 index a9e3de4d9..000000000 --- a/packages/bls-verify/lib/cjs/utils.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -Object.defineProperty(exports, '__esModule', { value: true }); -exports.compare = exports.fromHex = exports.toHex = exports.concat = void 0; -/** - * Concatenate multiple array buffers. - * @param buffers The buffers to concatenate. - */ -function concat(...buffers) { - const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); - let index = 0; - for (const b of buffers) { - result.set(new Uint8Array(b), index); - index += b.byteLength; - } - return result.buffer; -} -exports.concat = concat; -/** - * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. - * @param buffer The buffer to return the hexadecimal string of. - */ -function toHex(buffer) { - return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); -} -exports.toHex = toHex; -const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); -/** - * Transforms a hexadecimal string into an array buffer. - * @param hex The hexadecimal string to use. - */ -function fromHex(hex) { - if (!hexRe.test(hex)) { - throw new Error('Invalid hexadecimal string.'); - } - const buffer = [...hex] - .reduce((acc, curr, i) => { - // tslint:disable-next-line:no-bitwise - acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; - return acc; - }, []) - .map(x => Number.parseInt(x, 16)); - return new Uint8Array(buffer).buffer; -} -exports.fromHex = fromHex; -function compare(b1, b2) { - if (b1.byteLength !== b2.byteLength) { - return b1.byteLength - b2.byteLength; - } - const u1 = new Uint8Array(b1); - const u2 = new Uint8Array(b2); - for (let i = 0; i < u1.length; i++) { - if (u1[i] !== u2[i]) { - return u1[i] - u2[i]; - } - } - return 0; -} -exports.compare = compare; -//# sourceMappingURL=utils.js.map diff --git a/packages/bls-verify/lib/esm/index.js b/packages/bls-verify/lib/esm/index.js deleted file mode 100644 index 4c18c62cf..000000000 --- a/packages/bls-verify/lib/esm/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import { verify } from '@noble/bls12-381'; -import { toHex } from './utils'; -/** - * BLS Verification to be used in an IC Agent, using the @noble/bls-12-381 pure JS implementation - * @param {Uint8Array | string} publicKey - Uint8Array or string of the public key used to verify a BLS signature - * @param {Uint8Array | string} signature - digital signature - * @param {Uint8Array | string} message - message to verify - * @returns boolean - */ -export const blsVerify = async (publicKey, signature, message) => { - const pk = typeof publicKey === 'string' ? publicKey : toHex(publicKey); - const sig = typeof signature === 'string' ? signature : toHex(signature); - const msg = typeof message === 'string' ? message : toHex(message); - return await verify(sig, msg, pk); -}; -//# sourceMappingURL=index.js.map diff --git a/packages/bls-verify/lib/esm/utils.js b/packages/bls-verify/lib/esm/utils.js deleted file mode 100644 index 27e0702dd..000000000 --- a/packages/bls-verify/lib/esm/utils.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Concatenate multiple array buffers. - * @param buffers The buffers to concatenate. - */ -export function concat(...buffers) { - const result = new Uint8Array(buffers.reduce((acc, curr) => acc + curr.byteLength, 0)); - let index = 0; - for (const b of buffers) { - result.set(new Uint8Array(b), index); - index += b.byteLength; - } - return result.buffer; -} -/** - * Transforms a buffer to an hexadecimal string. This will use the buffer as an Uint8Array. - * @param buffer The buffer to return the hexadecimal string of. - */ -export function toHex(buffer) { - return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, '0')).join(''); -} -const hexRe = new RegExp(/^([0-9A-F]{2})*$/i); -/** - * Transforms a hexadecimal string into an array buffer. - * @param hex The hexadecimal string to use. - */ -export function fromHex(hex) { - if (!hexRe.test(hex)) { - throw new Error('Invalid hexadecimal string.'); - } - const buffer = [...hex] - .reduce((acc, curr, i) => { - // tslint:disable-next-line:no-bitwise - acc[(i / 2) | 0] = (acc[(i / 2) | 0] || '') + curr; - return acc; - }, []) - .map(x => Number.parseInt(x, 16)); - return new Uint8Array(buffer).buffer; -} -export function compare(b1, b2) { - if (b1.byteLength !== b2.byteLength) { - return b1.byteLength - b2.byteLength; - } - const u1 = new Uint8Array(b1); - const u2 = new Uint8Array(b2); - for (let i = 0; i < u1.length; i++) { - if (u1[i] !== u2[i]) { - return u1[i] - u2[i]; - } - } - return 0; -} -//# sourceMappingURL=utils.js.map diff --git a/packages/bls-verify/tsconfig.json b/packages/bls-verify/tsconfig.json index f62927784..f1fae3494 100644 --- a/packages/bls-verify/tsconfig.json +++ b/packages/bls-verify/tsconfig.json @@ -3,9 +3,9 @@ "compilerOptions": { "allowJs": true, "baseUrl": "./", - "composite": true, - "declaration": true, - "esModuleInterop": true, + "composite": false, + "declaration": false, + "esModuleInterop": false, "forceConsistentCasingInFileNames": true, "incremental": true, "module": "ES2020",