From c23cb258adfca7d3cd9a99e6f7fa57fc48e994d6 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Wed, 5 Mar 2025 16:11:47 +0100 Subject: [PATCH 01/10] vm: [DIRTY] use vitest coverage for blockchain tests (see full commit msg for instructions) edit files to run in testRunnerVitest.spec.ts command: `npx vitest run ./test/tester/testRunnerVitest --coverage.allowExternal --coverage.enabled` --- .../tester/runners/BlockchainTestsRunner.ts | 48 +-- .../vm/test/tester/testRunnerVitest.spec.ts | 310 ++++++++++++++++++ 2 files changed, 313 insertions(+), 45 deletions(-) create mode 100755 packages/vm/test/tester/testRunnerVitest.spec.ts diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index 91557937781..b4cf69a81a0 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -35,10 +35,9 @@ function formatBlockHeader(data: any) { return formatted } -export async function runBlockchainTest(options: any, testData: any, t: tape.Test) { +export async function runBlockchainTest(options: any, testData: any) { // ensure that the test data is the right fork data if (testData.network !== options.forkConfigTestSuite) { - t.comment(`skipping test: no data available for ${options.forkConfigTestSuite}`) return } @@ -71,9 +70,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // Only run with block validation when sealEngine present in test file // and being set to Ethash PoW validation if (testData.sealEngine === 'Ethash') { - if (common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) { - t.skip('SealEngine setting is not matching chain consensus type, skip test.') - } validatePow = true } @@ -85,7 +81,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes if (typeof testData.genesisRLP === 'string') { const rlp = toBytes(testData.genesisRLP) - t.deepEquals(genesisBlock.serialize(), rlp, 'correct genesis RLP') } const consensusDict: ConsensusDict = {} @@ -122,19 +117,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes // set up pre-state await setupPreConditions(vm.stateManager, testData) - t.deepEquals( - await vm.stateManager.getStateRoot(), - genesisBlock.header.stateRoot, - 'correct pre stateRoot', - ) - - async function handleError(error: string | undefined, expectException: string | boolean) { - if (expectException !== false) { - t.pass(`Expected exception ${expectException}`) - } else { - t.fail(error) - } - } + async function handleError(error: string | undefined, expectException: string | boolean) {} let currentBlock = BigInt(0) for (const raw of testData.blocks) { @@ -185,20 +168,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes string >[]) { const shouldFail = txData.valid === 'false' - try { - const txRLP = hexToBytes(txData.rawBytes as PrefixedHexString) - const tx = createTxFromRLP(txRLP, { common }) - await blockBuilder.addTransaction(tx) - if (shouldFail) { - t.fail('tx should fail, but did not fail') - } - } catch (e: any) { - if (!shouldFail) { - t.fail(`tx should not fail, but failed: ${e.message}`) - } else { - t.pass('tx successfully failed') - } - } } await blockBuilder.revert() // will only revert if checkpointed } @@ -262,14 +231,13 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes const headBlock = await (vm.blockchain as Blockchain).getIteratorHead() await vm.stateManager.setStateRoot(headBlock.header.stateRoot) } else { - await verifyPostConditions(stateTree, testData.postState, t) + //await verifyPostConditions(stateTree, testData.postState, t) } throw e } if (expectException !== false) { - t.fail(`expected exception but test did not throw an exception: ${expectException}`) return } } catch (error: any) { @@ -279,16 +247,6 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes } } - t.equal( - bytesToHex(blockchain['_headHeaderHash']), - '0x' + testData.lastblockhash, - 'correct last header block', - ) - - const end = Date.now() - const timeSpent = `${(end - begin) / 1000} secs` - t.comment(`Time: ${timeSpent}`) - // Explicitly delete objects for memory optimization (early GC) common = blockchain = stateTree = stateManager = vm = cacheDB = null as any } diff --git a/packages/vm/test/tester/testRunnerVitest.spec.ts b/packages/vm/test/tester/testRunnerVitest.spec.ts new file mode 100755 index 00000000000..683b979b61e --- /dev/null +++ b/packages/vm/test/tester/testRunnerVitest.spec.ts @@ -0,0 +1,310 @@ +/* eslint-disable no-console */ +import { MCLBLS, NobleBLS, NobleBN254, RustBN254 } from '@ethereumjs/evm' +import { trustedSetup } from '@paulmillr/trusted-setups/fast.js' +import * as mcl from 'mcl-wasm' +import { KZG as microEthKZG } from 'micro-eth-signer/kzg' +import * as minimist from 'minimist' +import * as path from 'path' +import * as process from 'process' +import { initRustBN } from 'rustbn-wasm' +import * as tape from 'tape' +import { assert, describe, it } from 'vitest' + +import { + DEFAULT_FORK_CONFIG, + DEFAULT_TESTS_PATH, + getCommon, + getExpectedTests, + getRequiredForkConfigAlias, + getSkipTests, + getTestDirs, +} from './config.js' +import { runBlockchainTest } from './runners/BlockchainTestsRunner.js' +import { runStateTest } from './runners/GeneralStateTestsRunner.js' +import { getTestFromSource, getTestsFromArgs } from './testLoader.js' + +import type { Common } from '@ethereumjs/common' +import type { EVMBLSInterface, EVMBN254Interface } from '@ethereumjs/evm' + +/** + * Test runner + * CLI arguments: + * --state: boolean. Run state tests + * --blockchain: boolean. Run blockchain tests + * --fork: string. Fork to use for these tests + * --skip: string. Comma-separated list of tests to skip. choices of: all,broken,permanent,slow. Defaults to all + * --runSkipped: string. Comma-separated list of tests to skip if --skip is not set. choices of: all,broken,permanent,slow. Defaults to none + * --file: string. Test file to run + * --test: string. Test name to run + * --dir: string. Test directory to look for tests + * --excludeDir: string. Test directory to exclude from testing + * --testsPath: string. Root directory of tests to look (default: '../ethereum-tests') + * --customTestsPath: string. Custom directory to look for tests (e.g. '../../my_custom_test_folder') + * --customStateTest: string. Run a file with a custom state test (not in test directory) + * --jsontrace: boolean. Enable json step tracing in state tests + * --dist: boolean. Use the compiled version of the VM + * --data: number. Only run this state test if the transaction has this calldata + * --gas: number. Only run this state test if the transaction has this gasLimit + * --value: number. Only run this state test if the transaction has this call value + * --debug: boolean. Enable BlockchainTests debugger (compares post state against the expected post state) + * --expected-test-amount: number. If passed, check after tests are ran if at least this amount of tests have passed (inclusive) + * --verify-test-amount-alltests: number. If passed, get the expected amount from tests and verify afterwards if this is the count of tests (expects tests are ran with default settings) + * --reps: number. If passed, each test case will be run the number of times indicated + * --bls: string. BLS library being used, choices: Noble, MCL (default: MCL) + * --bn254: string. BN254 (alt_BN128) library being used, choices: Noble, RustBN (default: RustBN) + * --profile If this flag is passed, the state/blockchain tests will profile + */ + +const argv = { + _: [], + 'stack-size': 1500, + blockchain: true, + fork: 'Prague', + dir: '../fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/', +} + +describe('VM tests', () => { + it('run all tests', async () => { + async function runTests() { + let name: 'GeneralStateTests' | 'BlockchainTests' + let runner: any + if ((argv.state as boolean) === true) { + name = 'GeneralStateTests' + runner = runStateTest + } else if ((argv.blockchain as boolean) === true) { + name = 'BlockchainTests' + runner = runBlockchainTest + } else { + console.log('TEST', argv) + console.log(`Test type not supported or provided`) + process.exit(1) + } + + const RUN_PROFILER: boolean = argv.profile ?? false + + const FORK_CONFIG: string = argv.fork !== undefined ? argv.fork : DEFAULT_FORK_CONFIG + const FORK_CONFIG_TEST_SUITE = getRequiredForkConfigAlias(FORK_CONFIG) + + // Examples: Istanbul -> istanbul, MuirGlacier -> muirGlacier + const FORK_CONFIG_VM = FORK_CONFIG.charAt(0).toLowerCase() + FORK_CONFIG.substring(1) + + /** + * Configuration for getting the tests from the ethereum/tests repository + */ + const testGetterArgs: { + skipTests: string[] + runSkipped: string[] + forkConfig: string + file?: string + test?: string + dir?: string + excludeDir?: string + testsPath?: string + customStateTest?: string + directory?: string + } = { + skipTests: getSkipTests(argv.skip, argv.runSkipped !== undefined ? 'NONE' : 'ALL'), + runSkipped: getSkipTests(argv.runSkipped, 'NONE'), + forkConfig: FORK_CONFIG_TEST_SUITE, + file: argv.file, + test: argv.test, + dir: argv.dir, + excludeDir: argv.excludeDir, + testsPath: argv.testsPath, + customStateTest: argv.customStateTest, + } + + let bls: EVMBLSInterface + if (argv.bls !== undefined && argv.bls.toLowerCase() === 'mcl') { + await mcl.init(mcl.BLS12_381) + bls = new MCLBLS(mcl) + console.log('BLS library used: MCL (WASM)') + } else { + console.log('BLS library used: Noble (JavaScript)') + bls = new NobleBLS() + } + + let bn254: EVMBN254Interface + if (argv.bn254 !== undefined && argv.bn254.toLowerCase() === 'mcl') { + const rustBN = await initRustBN() + bn254 = new RustBN254(rustBN) + console.log('BN254 (alt_BN128) library used: rustbn.js (WASM)') + } else { + console.log('BN254 (alt_BN128) library used: Noble (JavaScript)') + bn254 = new NobleBN254() + } + + /** + * Run-time configuration + */ + const kzg = new microEthKZG(trustedSetup) + const runnerArgs: { + forkConfigVM: string + forkConfigTestSuite: string + common: Common + jsontrace?: boolean + dist?: boolean + data?: number + gasLimit?: number + value?: number + debug?: boolean + reps?: number + profile: boolean + bls: EVMBLSInterface + bn254: EVMBN254Interface + stateManager: string + } = { + forkConfigVM: FORK_CONFIG_VM, + forkConfigTestSuite: FORK_CONFIG_TEST_SUITE, + common: getCommon(FORK_CONFIG_VM, kzg), + jsontrace: argv.jsontrace, + dist: argv.dist, + data: argv.data, // GeneralStateTests + gasLimit: argv.gas, // GeneralStateTests + value: argv.value, // GeneralStateTests + debug: argv.debug, // BlockchainTests + reps: argv.reps, // test repetitions + bls, + profile: RUN_PROFILER, + bn254, + stateManager: argv.stateManager, + } + + /** + * Modify the forkConfig string to ensure it works with RegEx (escape `+` characters) + */ + if (testGetterArgs.forkConfig.includes('+')) { + let str = testGetterArgs.forkConfig + const indices = [] + for (let i = 0; i < str.length; i++) { + if (str[i] === '+') { + indices.push(i) + } + } + // traverse array in reverse order to ensure indices match when we replace the '+' with '/+' + for (let i = indices.length - 1; i >= 0; i--) { + str = `${str.substr(0, indices[i])}\\${str.substr(indices[i])}` + } + testGetterArgs.forkConfig = str + } + + const expectedTests: number | undefined = + argv['verify-test-amount-alltests'] > 0 + ? getExpectedTests(FORK_CONFIG_VM, name) + : argv['expected-test-amount'] !== undefined && argv['expected-test-amount'] > 0 + ? argv['expected-test-amount'] + : undefined + + /** + * Initialization output to console + */ + const width = 50 + const fillWidth = width + const fillParam = 20 + const delimiter = `| `.padEnd(fillWidth) + ' |' + const formatArgs = (args: any) => { + return Object.assign( + {}, + ...Object.entries(args) + .filter(([_k, v]) => typeof v === 'string' || (Array.isArray(v) && v.length !== 0)) + .map(([k, v]) => ({ + [k]: Array.isArray(v) && v.length > 0 ? v.length : v, + })), + ) + } + const formattedGetterArgs = formatArgs(testGetterArgs) + const formattedRunnerArgs = formatArgs(runnerArgs) + + console.log(`+${'-'.repeat(width)}+`) + console.log(`| VM -> ${name} `.padEnd(fillWidth) + ' |') + console.log(delimiter) + console.log(`| TestGetterArgs`.padEnd(fillWidth) + ' |') + for (const [key, value] of Object.entries(formattedGetterArgs)) { + console.log(`| ${key.padEnd(fillParam)}: ${value}`.padEnd(fillWidth) + ' |') + } + console.log(delimiter) + console.log(`| RunnerArgs`.padEnd(fillWidth) + ' |') + for (const [key, value] of Object.entries(formattedRunnerArgs)) { + if (key === 'common') { + const hf = (value as Common).hardfork() + console.log(`| ${key.padEnd(fillParam)}: ${hf}`.padEnd(fillWidth) + ' |') + } else { + console.log(`| ${key.padEnd(fillParam)}: ${value}`.padEnd(fillWidth) + ' |') + } + } + console.log(`+${'-'.repeat(width)}+`) + console.log() + + if (argv.customStateTest !== undefined) { + const fileName: string = argv.customStateTest + //@ts-ignore tsx/esbuild can't figure out this namespace import thing but it works fine :shrug: + tape(name, (t) => { + getTestFromSource(fileName, async (err: string | null, test: any) => { + if (err !== null) { + return t.fail(err) + } + t.comment(`file: ${fileName} test: ${test.testName}`) + await runStateTest(runnerArgs, test, t) + t.end() + }) + }) + } else { + let testIdentifier: string + const failingTests: Record = {} + // Tests for HFs before Istanbul have been moved under `LegacyTests/Constantinople`: + // https://github.com/ethereum/tests/releases/tag/v7.0.0-beta.1 + + const dirs = getTestDirs(FORK_CONFIG_VM, name) + console.time('Total (including setup)') + for (const dir of dirs) { + await new Promise((resolve, reject) => { + if (argv.customTestsPath !== undefined) { + testGetterArgs.directory = argv.customTestsPath as string + } else { + const testDir = testGetterArgs.dir ?? '' + const testsPath = testGetterArgs.testsPath ?? DEFAULT_TESTS_PATH + testGetterArgs.directory = path.join(testsPath, dir, testDir) + } + console.log('default method call') + getTestsFromArgs( + dir, + async (fileName: string, subDir: string, testName: string, test: any) => { + const runSkipped = testGetterArgs.runSkipped + const inRunSkipped = runSkipped.includes(fileName) + if (runSkipped.length === 0 || inRunSkipped === true) { + testIdentifier = `file: ${subDir} test: ${testName}` + await runner(runnerArgs, test) + } + }, + testGetterArgs, + ) + .then(() => { + resolve() + }) + .catch((error: string) => { + reject() + }) + }) + } + + for (const failingTestIdentifier in failingTests) { + console.log(`Errors thrown in ${failingTestIdentifier}:`) + const errors = failingTests[failingTestIdentifier] as string[] + for (let i = 0; i < errors.length; i++) { + console.log('\t' + errors[i]) + } + } + + if (expectedTests !== undefined) { + const { assertCount } = t as any + t.ok(assertCount >= expectedTests, `expected ${expectedTests} checks, got ${assertCount}`) + } + + console.log() + console.timeEnd('Total (including setup)') + } + } + + await runTests() // eslint-disable-line @typescript-eslint/no-floating-promises + }, 0) +}, 0) From 5965b2dab75c081330f75964befcec22716ae5ef Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 19 Apr 2025 04:22:52 +0200 Subject: [PATCH 02/10] attempt to insert noble curves in coverage report (DOES NOT WORK) --- packages/vm/coverage.sh | 4 ++++ .../test/tester/runners/BlockchainTestsRunner.ts | 2 ++ packages/vm/test/tester/testRunnerVitest.spec.ts | 4 ++-- packages/vm/vitest.config.ts | 15 ++++++++++++++- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 packages/vm/coverage.sh diff --git a/packages/vm/coverage.sh b/packages/vm/coverage.sh new file mode 100644 index 00000000000..108a22c0e2c --- /dev/null +++ b/packages/vm/coverage.sh @@ -0,0 +1,4 @@ +npx vitest run ./test/tester/testRunnerVitest \ + --coverage.enabled \ + --coverage.allowExternal \ + && open ../../coverage/index.html \ No newline at end of file diff --git a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts index b4cf69a81a0..e1b22283e3d 100644 --- a/packages/vm/test/tester/runners/BlockchainTestsRunner.ts +++ b/packages/vm/test/tester/runners/BlockchainTestsRunner.ts @@ -41,6 +41,8 @@ export async function runBlockchainTest(options: any, testData: any) { return } + console.log('Running test, description: ', testData._info?.description) + // fix for BlockchainTests/GeneralStateTests/stRandom/* testData.lastblockhash = stripHexPrefix(testData.lastblockhash) diff --git a/packages/vm/test/tester/testRunnerVitest.spec.ts b/packages/vm/test/tester/testRunnerVitest.spec.ts index 683b979b61e..2b4bd27163f 100755 --- a/packages/vm/test/tester/testRunnerVitest.spec.ts +++ b/packages/vm/test/tester/testRunnerVitest.spec.ts @@ -1,10 +1,10 @@ +import * as path from 'path' /* eslint-disable no-console */ import { MCLBLS, NobleBLS, NobleBN254, RustBN254 } from '@ethereumjs/evm' import { trustedSetup } from '@paulmillr/trusted-setups/fast.js' import * as mcl from 'mcl-wasm' import { KZG as microEthKZG } from 'micro-eth-signer/kzg' import * as minimist from 'minimist' -import * as path from 'path' import * as process from 'process' import { initRustBN } from 'rustbn-wasm' import * as tape from 'tape' @@ -60,7 +60,7 @@ const argv = { 'stack-size': 1500, blockchain: true, fork: 'Prague', - dir: '../fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/', + dir: '../fixtures/blockchain_tests/prague/eip2537_bls_12_381_precompiles/bls12_g1add', } describe('VM tests', () => { diff --git a/packages/vm/vitest.config.ts b/packages/vm/vitest.config.ts index 5f639465bc4..6247e644f5f 100644 --- a/packages/vm/vitest.config.ts +++ b/packages/vm/vitest.config.ts @@ -5,9 +5,22 @@ import baseConfig from '../../config/vitest.config.mts' export default mergeConfig( baseConfig, defineConfig({ + root: '../..', plugins: [topLevelAwait()], optimizeDeps: { - exclude: ['kzg-wasm'], + exclude: ['kzg-wasm', '@noble/curves'], + }, + ssr: { + noExternal: ['@noble/curves'], + }, + test: { + coverage: { + enabled: true, + allowExternal: true, + include: ['**/packages/**/src/**/*.{ts,js}', '**/node_modules/@noble/curves/**/*.{ts,js}'], + exclude: ['packages/ethereum-tests'], + reporter: ['text', 'html'], + }, }, }), ) From 5b76c86c2766833bd951b6aa73c3b3c886fb9896 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 19 Apr 2025 04:29:08 +0200 Subject: [PATCH 03/10] update scripts with new inclusion --- packages/vm/coverage.sh | 2 +- packages/vm/vitest.config.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vm/coverage.sh b/packages/vm/coverage.sh index 108a22c0e2c..b7edd5a2935 100644 --- a/packages/vm/coverage.sh +++ b/packages/vm/coverage.sh @@ -1,4 +1,4 @@ npx vitest run ./test/tester/testRunnerVitest \ --coverage.enabled \ --coverage.allowExternal \ - && open ../../coverage/index.html \ No newline at end of file + && open ./coverage/index.html \ No newline at end of file diff --git a/packages/vm/vitest.config.ts b/packages/vm/vitest.config.ts index 6247e644f5f..2e389497bea 100644 --- a/packages/vm/vitest.config.ts +++ b/packages/vm/vitest.config.ts @@ -5,7 +5,7 @@ import baseConfig from '../../config/vitest.config.mts' export default mergeConfig( baseConfig, defineConfig({ - root: '../..', + //root: '../..', plugins: [topLevelAwait()], optimizeDeps: { exclude: ['kzg-wasm', '@noble/curves'], @@ -17,8 +17,8 @@ export default mergeConfig( coverage: { enabled: true, allowExternal: true, - include: ['**/packages/**/src/**/*.{ts,js}', '**/node_modules/@noble/curves/**/*.{ts,js}'], - exclude: ['packages/ethereum-tests'], + include: ['**/packages/*/src/**/*.{ts,js}'], + exclude: ['**/packages/ethereum-tests'], reporter: ['text', 'html'], }, }, From 398f1e8ef025f89cd2b64e5cbc9032efe3bcfd70 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 19 Apr 2025 04:31:48 +0200 Subject: [PATCH 04/10] tmp: add noble-curves as package so we can add it to coverage --- packages/noble-curves/LICENSE | 21 + packages/noble-curves/README.md | 1113 +++++++++++++ packages/noble-curves/_shortw_utils.d.ts | 16 + packages/noble-curves/_shortw_utils.d.ts.map | 1 + packages/noble-curves/_shortw_utils.js | 25 + packages/noble-curves/_shortw_utils.js.map | 1 + packages/noble-curves/abstract/bls.d.ts | 165 ++ packages/noble-curves/abstract/bls.d.ts.map | 1 + packages/noble-curves/abstract/bls.js | 360 +++++ packages/noble-curves/abstract/bls.js.map | 1 + packages/noble-curves/abstract/curve.d.ts | 124 ++ packages/noble-curves/abstract/curve.d.ts.map | 1 + packages/noble-curves/abstract/curve.js | 368 +++++ packages/noble-curves/abstract/curve.js.map | 1 + packages/noble-curves/abstract/edwards.d.ts | 106 ++ .../noble-curves/abstract/edwards.d.ts.map | 1 + packages/noble-curves/abstract/edwards.js | 448 ++++++ packages/noble-curves/abstract/edwards.js.map | 1 + .../noble-curves/abstract/hash-to-curve.d.ts | 99 ++ .../abstract/hash-to-curve.d.ts.map | 1 + .../noble-curves/abstract/hash-to-curve.js | 184 +++ .../abstract/hash-to-curve.js.map | 1 + packages/noble-curves/abstract/modular.d.ts | 168 ++ .../noble-curves/abstract/modular.d.ts.map | 1 + packages/noble-curves/abstract/modular.js | 485 ++++++ packages/noble-curves/abstract/modular.js.map | 1 + .../noble-curves/abstract/montgomery.d.ts | 26 + .../noble-curves/abstract/montgomery.d.ts.map | 1 + packages/noble-curves/abstract/montgomery.js | 162 ++ .../noble-curves/abstract/montgomery.js.map | 1 + packages/noble-curves/abstract/poseidon.d.ts | 39 + .../noble-curves/abstract/poseidon.d.ts.map | 1 + packages/noble-curves/abstract/poseidon.js | 104 ++ .../noble-curves/abstract/poseidon.js.map | 1 + packages/noble-curves/abstract/tower.d.ts | 126 ++ packages/noble-curves/abstract/tower.d.ts.map | 1 + packages/noble-curves/abstract/tower.js | 520 +++++++ packages/noble-curves/abstract/tower.js.map | 1 + packages/noble-curves/abstract/utils.d.ts | 126 ++ packages/noble-curves/abstract/utils.d.ts.map | 1 + packages/noble-curves/abstract/utils.js | 340 ++++ packages/noble-curves/abstract/utils.js.map | 1 + .../noble-curves/abstract/weierstrass.d.ts | 241 +++ .../abstract/weierstrass.d.ts.map | 1 + packages/noble-curves/abstract/weierstrass.js | 1139 ++++++++++++++ .../noble-curves/abstract/weierstrass.js.map | 1 + packages/noble-curves/bls12-381.d.ts | 14 + packages/noble-curves/bls12-381.d.ts.map | 1 + packages/noble-curves/bls12-381.js | 756 +++++++++ packages/noble-curves/bls12-381.js.map | 1 + packages/noble-curves/bn254.d.ts | 15 + packages/noble-curves/bn254.d.ts.map | 1 + packages/noble-curves/bn254.js | 237 +++ packages/noble-curves/bn254.js.map | 1 + packages/noble-curves/ed25519.d.ts | 101 ++ packages/noble-curves/ed25519.d.ts.map | 1 + packages/noble-curves/ed25519.js | 510 ++++++ packages/noble-curves/ed25519.js.map | 1 + packages/noble-curves/ed448.d.ts | 82 + packages/noble-curves/ed448.d.ts.map | 1 + packages/noble-curves/ed448.js | 470 ++++++ packages/noble-curves/ed448.js.map | 1 + packages/noble-curves/esm/_shortw_utils.d.ts | 16 + .../noble-curves/esm/_shortw_utils.d.ts.map | 1 + packages/noble-curves/esm/_shortw_utils.js | 21 + .../noble-curves/esm/_shortw_utils.js.map | 1 + packages/noble-curves/esm/abstract/bls.d.ts | 165 ++ .../noble-curves/esm/abstract/bls.d.ts.map | 1 + packages/noble-curves/esm/abstract/bls.js | 357 +++++ packages/noble-curves/esm/abstract/bls.js.map | 1 + packages/noble-curves/esm/abstract/curve.d.ts | 124 ++ .../noble-curves/esm/abstract/curve.d.ts.map | 1 + packages/noble-curves/esm/abstract/curve.js | 362 +++++ .../noble-curves/esm/abstract/curve.js.map | 1 + .../noble-curves/esm/abstract/edwards.d.ts | 106 ++ .../esm/abstract/edwards.d.ts.map | 1 + packages/noble-curves/esm/abstract/edwards.js | 445 ++++++ .../noble-curves/esm/abstract/edwards.js.map | 1 + .../esm/abstract/hash-to-curve.d.ts | 99 ++ .../esm/abstract/hash-to-curve.d.ts.map | 1 + .../esm/abstract/hash-to-curve.js | 173 +++ .../esm/abstract/hash-to-curve.js.map | 1 + .../noble-curves/esm/abstract/modular.d.ts | 168 ++ .../esm/abstract/modular.d.ts.map | 1 + packages/noble-curves/esm/abstract/modular.js | 464 ++++++ .../noble-curves/esm/abstract/modular.js.map | 1 + .../noble-curves/esm/abstract/montgomery.d.ts | 26 + .../esm/abstract/montgomery.d.ts.map | 1 + .../noble-curves/esm/abstract/montgomery.js | 159 ++ .../esm/abstract/montgomery.js.map | 1 + .../noble-curves/esm/abstract/poseidon.d.ts | 39 + .../esm/abstract/poseidon.d.ts.map | 1 + .../noble-curves/esm/abstract/poseidon.js | 99 ++ .../noble-curves/esm/abstract/poseidon.js.map | 1 + packages/noble-curves/esm/abstract/tower.d.ts | 126 ++ .../noble-curves/esm/abstract/tower.d.ts.map | 1 + packages/noble-curves/esm/abstract/tower.js | 515 ++++++ .../noble-curves/esm/abstract/tower.js.map | 1 + packages/noble-curves/esm/abstract/utils.d.ts | 126 ++ .../noble-curves/esm/abstract/utils.d.ts.map | 1 + packages/noble-curves/esm/abstract/utils.js | 311 ++++ .../noble-curves/esm/abstract/utils.js.map | 1 + .../esm/abstract/weierstrass.d.ts | 241 +++ .../esm/abstract/weierstrass.d.ts.map | 1 + .../noble-curves/esm/abstract/weierstrass.js | 1131 ++++++++++++++ .../esm/abstract/weierstrass.js.map | 1 + packages/noble-curves/esm/bls12-381.d.ts | 14 + packages/noble-curves/esm/bls12-381.d.ts.map | 1 + packages/noble-curves/esm/bls12-381.js | 747 +++++++++ packages/noble-curves/esm/bls12-381.js.map | 1 + packages/noble-curves/esm/bn254.d.ts | 15 + packages/noble-curves/esm/bn254.d.ts.map | 1 + packages/noble-curves/esm/bn254.js | 233 +++ packages/noble-curves/esm/bn254.js.map | 1 + packages/noble-curves/esm/ed25519.d.ts | 101 ++ packages/noble-curves/esm/ed25519.d.ts.map | 1 + packages/noble-curves/esm/ed25519.js | 493 ++++++ packages/noble-curves/esm/ed25519.js.map | 1 + packages/noble-curves/esm/ed448.d.ts | 82 + packages/noble-curves/esm/ed448.d.ts.map | 1 + packages/noble-curves/esm/ed448.js | 447 ++++++ packages/noble-curves/esm/ed448.js.map | 1 + packages/noble-curves/esm/index.d.ts | 2 + packages/noble-curves/esm/index.d.ts.map | 1 + packages/noble-curves/esm/index.js | 19 + packages/noble-curves/esm/index.js.map | 1 + packages/noble-curves/esm/jubjub.d.ts | 5 + packages/noble-curves/esm/jubjub.d.ts.map | 1 + packages/noble-curves/esm/jubjub.js | 60 + packages/noble-curves/esm/jubjub.js.map | 1 + packages/noble-curves/esm/p256.d.ts | 11 + packages/noble-curves/esm/p256.d.ts.map | 1 + packages/noble-curves/esm/p256.js | 54 + packages/noble-curves/esm/p256.js.map | 1 + packages/noble-curves/esm/p384.d.ts | 11 + packages/noble-curves/esm/p384.d.ts.map | 1 + packages/noble-curves/esm/p384.js | 68 + packages/noble-curves/esm/p384.js.map | 1 + packages/noble-curves/esm/p521.d.ts | 12 + packages/noble-curves/esm/p521.d.ts.map | 1 + packages/noble-curves/esm/p521.js | 76 + packages/noble-curves/esm/p521.js.map | 1 + packages/noble-curves/esm/package.json | 4 + packages/noble-curves/esm/pasta.d.ts | 8 + packages/noble-curves/esm/pasta.d.ts.map | 1 + packages/noble-curves/esm/pasta.js | 34 + packages/noble-curves/esm/pasta.js.map | 1 + packages/noble-curves/esm/secp256k1.d.ts | 71 + packages/noble-curves/esm/secp256k1.d.ts.map | 1 + packages/noble-curves/esm/secp256k1.js | 299 ++++ packages/noble-curves/esm/secp256k1.js.map | 1 + packages/noble-curves/index.d.ts | 1 + packages/noble-curves/index.d.ts.map | 1 + packages/noble-curves/index.js | 19 + packages/noble-curves/index.js.map | 1 + packages/noble-curves/jubjub.d.ts | 5 + packages/noble-curves/jubjub.d.ts.map | 1 + packages/noble-curves/jubjub.js | 67 + packages/noble-curves/jubjub.js.map | 1 + packages/noble-curves/p256.d.ts | 11 + packages/noble-curves/p256.d.ts.map | 1 + packages/noble-curves/p256.js | 63 + packages/noble-curves/p256.js.map | 1 + packages/noble-curves/p384.d.ts | 11 + packages/noble-curves/p384.d.ts.map | 1 + packages/noble-curves/p384.js | 75 + packages/noble-curves/p384.js.map | 1 + packages/noble-curves/p521.d.ts | 12 + packages/noble-curves/p521.d.ts.map | 1 + packages/noble-curves/p521.js | 83 + packages/noble-curves/p521.js.map | 1 + packages/noble-curves/package.json | 163 ++ packages/noble-curves/pasta.d.ts | 8 + packages/noble-curves/pasta.d.ts.map | 1 + packages/noble-curves/pasta.js | 37 + packages/noble-curves/pasta.js.map | 1 + packages/noble-curves/secp256k1.d.ts | 71 + packages/noble-curves/secp256k1.d.ts.map | 1 + packages/noble-curves/secp256k1.js | 295 ++++ packages/noble-curves/secp256k1.js.map | 1 + packages/noble-curves/src/_shortw_utils.ts | 30 + packages/noble-curves/src/abstract/bls.ts | 574 +++++++ packages/noble-curves/src/abstract/curve.ts | 457 ++++++ packages/noble-curves/src/abstract/edwards.ts | 565 +++++++ .../src/abstract/hash-to-curve.ts | 255 +++ packages/noble-curves/src/abstract/modular.ts | 555 +++++++ .../noble-curves/src/abstract/montgomery.ts | 190 +++ .../noble-curves/src/abstract/poseidon.ts | 136 ++ packages/noble-curves/src/abstract/tower.ts | 664 ++++++++ packages/noble-curves/src/abstract/utils.ts | 367 +++++ .../noble-curves/src/abstract/weierstrass.ts | 1383 +++++++++++++++++ packages/noble-curves/src/bls12-381.ts | 774 +++++++++ packages/noble-curves/src/bn254.ts | 254 +++ packages/noble-curves/src/ed25519.ts | 544 +++++++ packages/noble-curves/src/ed448.ts | 514 ++++++ packages/noble-curves/src/index.ts | 17 + packages/noble-curves/src/jubjub.ts | 63 + packages/noble-curves/src/p256.ts | 57 + packages/noble-curves/src/p384.ts | 71 + packages/noble-curves/src/p521.ts | 80 + packages/noble-curves/src/package.json | 3 + packages/noble-curves/src/pasta.ts | 39 + packages/noble-curves/src/secp256k1.ts | 333 ++++ 203 files changed, 25763 insertions(+) create mode 100644 packages/noble-curves/LICENSE create mode 100644 packages/noble-curves/README.md create mode 100644 packages/noble-curves/_shortw_utils.d.ts create mode 100644 packages/noble-curves/_shortw_utils.d.ts.map create mode 100644 packages/noble-curves/_shortw_utils.js create mode 100644 packages/noble-curves/_shortw_utils.js.map create mode 100644 packages/noble-curves/abstract/bls.d.ts create mode 100644 packages/noble-curves/abstract/bls.d.ts.map create mode 100644 packages/noble-curves/abstract/bls.js create mode 100644 packages/noble-curves/abstract/bls.js.map create mode 100644 packages/noble-curves/abstract/curve.d.ts create mode 100644 packages/noble-curves/abstract/curve.d.ts.map create mode 100644 packages/noble-curves/abstract/curve.js create mode 100644 packages/noble-curves/abstract/curve.js.map create mode 100644 packages/noble-curves/abstract/edwards.d.ts create mode 100644 packages/noble-curves/abstract/edwards.d.ts.map create mode 100644 packages/noble-curves/abstract/edwards.js create mode 100644 packages/noble-curves/abstract/edwards.js.map create mode 100644 packages/noble-curves/abstract/hash-to-curve.d.ts create mode 100644 packages/noble-curves/abstract/hash-to-curve.d.ts.map create mode 100644 packages/noble-curves/abstract/hash-to-curve.js create mode 100644 packages/noble-curves/abstract/hash-to-curve.js.map create mode 100644 packages/noble-curves/abstract/modular.d.ts create mode 100644 packages/noble-curves/abstract/modular.d.ts.map create mode 100644 packages/noble-curves/abstract/modular.js create mode 100644 packages/noble-curves/abstract/modular.js.map create mode 100644 packages/noble-curves/abstract/montgomery.d.ts create mode 100644 packages/noble-curves/abstract/montgomery.d.ts.map create mode 100644 packages/noble-curves/abstract/montgomery.js create mode 100644 packages/noble-curves/abstract/montgomery.js.map create mode 100644 packages/noble-curves/abstract/poseidon.d.ts create mode 100644 packages/noble-curves/abstract/poseidon.d.ts.map create mode 100644 packages/noble-curves/abstract/poseidon.js create mode 100644 packages/noble-curves/abstract/poseidon.js.map create mode 100644 packages/noble-curves/abstract/tower.d.ts create mode 100644 packages/noble-curves/abstract/tower.d.ts.map create mode 100644 packages/noble-curves/abstract/tower.js create mode 100644 packages/noble-curves/abstract/tower.js.map create mode 100644 packages/noble-curves/abstract/utils.d.ts create mode 100644 packages/noble-curves/abstract/utils.d.ts.map create mode 100644 packages/noble-curves/abstract/utils.js create mode 100644 packages/noble-curves/abstract/utils.js.map create mode 100644 packages/noble-curves/abstract/weierstrass.d.ts create mode 100644 packages/noble-curves/abstract/weierstrass.d.ts.map create mode 100644 packages/noble-curves/abstract/weierstrass.js create mode 100644 packages/noble-curves/abstract/weierstrass.js.map create mode 100644 packages/noble-curves/bls12-381.d.ts create mode 100644 packages/noble-curves/bls12-381.d.ts.map create mode 100644 packages/noble-curves/bls12-381.js create mode 100644 packages/noble-curves/bls12-381.js.map create mode 100644 packages/noble-curves/bn254.d.ts create mode 100644 packages/noble-curves/bn254.d.ts.map create mode 100644 packages/noble-curves/bn254.js create mode 100644 packages/noble-curves/bn254.js.map create mode 100644 packages/noble-curves/ed25519.d.ts create mode 100644 packages/noble-curves/ed25519.d.ts.map create mode 100644 packages/noble-curves/ed25519.js create mode 100644 packages/noble-curves/ed25519.js.map create mode 100644 packages/noble-curves/ed448.d.ts create mode 100644 packages/noble-curves/ed448.d.ts.map create mode 100644 packages/noble-curves/ed448.js create mode 100644 packages/noble-curves/ed448.js.map create mode 100644 packages/noble-curves/esm/_shortw_utils.d.ts create mode 100644 packages/noble-curves/esm/_shortw_utils.d.ts.map create mode 100644 packages/noble-curves/esm/_shortw_utils.js create mode 100644 packages/noble-curves/esm/_shortw_utils.js.map create mode 100644 packages/noble-curves/esm/abstract/bls.d.ts create mode 100644 packages/noble-curves/esm/abstract/bls.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/bls.js create mode 100644 packages/noble-curves/esm/abstract/bls.js.map create mode 100644 packages/noble-curves/esm/abstract/curve.d.ts create mode 100644 packages/noble-curves/esm/abstract/curve.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/curve.js create mode 100644 packages/noble-curves/esm/abstract/curve.js.map create mode 100644 packages/noble-curves/esm/abstract/edwards.d.ts create mode 100644 packages/noble-curves/esm/abstract/edwards.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/edwards.js create mode 100644 packages/noble-curves/esm/abstract/edwards.js.map create mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.d.ts create mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.js create mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.js.map create mode 100644 packages/noble-curves/esm/abstract/modular.d.ts create mode 100644 packages/noble-curves/esm/abstract/modular.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/modular.js create mode 100644 packages/noble-curves/esm/abstract/modular.js.map create mode 100644 packages/noble-curves/esm/abstract/montgomery.d.ts create mode 100644 packages/noble-curves/esm/abstract/montgomery.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/montgomery.js create mode 100644 packages/noble-curves/esm/abstract/montgomery.js.map create mode 100644 packages/noble-curves/esm/abstract/poseidon.d.ts create mode 100644 packages/noble-curves/esm/abstract/poseidon.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/poseidon.js create mode 100644 packages/noble-curves/esm/abstract/poseidon.js.map create mode 100644 packages/noble-curves/esm/abstract/tower.d.ts create mode 100644 packages/noble-curves/esm/abstract/tower.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/tower.js create mode 100644 packages/noble-curves/esm/abstract/tower.js.map create mode 100644 packages/noble-curves/esm/abstract/utils.d.ts create mode 100644 packages/noble-curves/esm/abstract/utils.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/utils.js create mode 100644 packages/noble-curves/esm/abstract/utils.js.map create mode 100644 packages/noble-curves/esm/abstract/weierstrass.d.ts create mode 100644 packages/noble-curves/esm/abstract/weierstrass.d.ts.map create mode 100644 packages/noble-curves/esm/abstract/weierstrass.js create mode 100644 packages/noble-curves/esm/abstract/weierstrass.js.map create mode 100644 packages/noble-curves/esm/bls12-381.d.ts create mode 100644 packages/noble-curves/esm/bls12-381.d.ts.map create mode 100644 packages/noble-curves/esm/bls12-381.js create mode 100644 packages/noble-curves/esm/bls12-381.js.map create mode 100644 packages/noble-curves/esm/bn254.d.ts create mode 100644 packages/noble-curves/esm/bn254.d.ts.map create mode 100644 packages/noble-curves/esm/bn254.js create mode 100644 packages/noble-curves/esm/bn254.js.map create mode 100644 packages/noble-curves/esm/ed25519.d.ts create mode 100644 packages/noble-curves/esm/ed25519.d.ts.map create mode 100644 packages/noble-curves/esm/ed25519.js create mode 100644 packages/noble-curves/esm/ed25519.js.map create mode 100644 packages/noble-curves/esm/ed448.d.ts create mode 100644 packages/noble-curves/esm/ed448.d.ts.map create mode 100644 packages/noble-curves/esm/ed448.js create mode 100644 packages/noble-curves/esm/ed448.js.map create mode 100644 packages/noble-curves/esm/index.d.ts create mode 100644 packages/noble-curves/esm/index.d.ts.map create mode 100644 packages/noble-curves/esm/index.js create mode 100644 packages/noble-curves/esm/index.js.map create mode 100644 packages/noble-curves/esm/jubjub.d.ts create mode 100644 packages/noble-curves/esm/jubjub.d.ts.map create mode 100644 packages/noble-curves/esm/jubjub.js create mode 100644 packages/noble-curves/esm/jubjub.js.map create mode 100644 packages/noble-curves/esm/p256.d.ts create mode 100644 packages/noble-curves/esm/p256.d.ts.map create mode 100644 packages/noble-curves/esm/p256.js create mode 100644 packages/noble-curves/esm/p256.js.map create mode 100644 packages/noble-curves/esm/p384.d.ts create mode 100644 packages/noble-curves/esm/p384.d.ts.map create mode 100644 packages/noble-curves/esm/p384.js create mode 100644 packages/noble-curves/esm/p384.js.map create mode 100644 packages/noble-curves/esm/p521.d.ts create mode 100644 packages/noble-curves/esm/p521.d.ts.map create mode 100644 packages/noble-curves/esm/p521.js create mode 100644 packages/noble-curves/esm/p521.js.map create mode 100644 packages/noble-curves/esm/package.json create mode 100644 packages/noble-curves/esm/pasta.d.ts create mode 100644 packages/noble-curves/esm/pasta.d.ts.map create mode 100644 packages/noble-curves/esm/pasta.js create mode 100644 packages/noble-curves/esm/pasta.js.map create mode 100644 packages/noble-curves/esm/secp256k1.d.ts create mode 100644 packages/noble-curves/esm/secp256k1.d.ts.map create mode 100644 packages/noble-curves/esm/secp256k1.js create mode 100644 packages/noble-curves/esm/secp256k1.js.map create mode 100644 packages/noble-curves/index.d.ts create mode 100644 packages/noble-curves/index.d.ts.map create mode 100644 packages/noble-curves/index.js create mode 100644 packages/noble-curves/index.js.map create mode 100644 packages/noble-curves/jubjub.d.ts create mode 100644 packages/noble-curves/jubjub.d.ts.map create mode 100644 packages/noble-curves/jubjub.js create mode 100644 packages/noble-curves/jubjub.js.map create mode 100644 packages/noble-curves/p256.d.ts create mode 100644 packages/noble-curves/p256.d.ts.map create mode 100644 packages/noble-curves/p256.js create mode 100644 packages/noble-curves/p256.js.map create mode 100644 packages/noble-curves/p384.d.ts create mode 100644 packages/noble-curves/p384.d.ts.map create mode 100644 packages/noble-curves/p384.js create mode 100644 packages/noble-curves/p384.js.map create mode 100644 packages/noble-curves/p521.d.ts create mode 100644 packages/noble-curves/p521.d.ts.map create mode 100644 packages/noble-curves/p521.js create mode 100644 packages/noble-curves/p521.js.map create mode 100644 packages/noble-curves/package.json create mode 100644 packages/noble-curves/pasta.d.ts create mode 100644 packages/noble-curves/pasta.d.ts.map create mode 100644 packages/noble-curves/pasta.js create mode 100644 packages/noble-curves/pasta.js.map create mode 100644 packages/noble-curves/secp256k1.d.ts create mode 100644 packages/noble-curves/secp256k1.d.ts.map create mode 100644 packages/noble-curves/secp256k1.js create mode 100644 packages/noble-curves/secp256k1.js.map create mode 100644 packages/noble-curves/src/_shortw_utils.ts create mode 100644 packages/noble-curves/src/abstract/bls.ts create mode 100644 packages/noble-curves/src/abstract/curve.ts create mode 100644 packages/noble-curves/src/abstract/edwards.ts create mode 100644 packages/noble-curves/src/abstract/hash-to-curve.ts create mode 100644 packages/noble-curves/src/abstract/modular.ts create mode 100644 packages/noble-curves/src/abstract/montgomery.ts create mode 100644 packages/noble-curves/src/abstract/poseidon.ts create mode 100644 packages/noble-curves/src/abstract/tower.ts create mode 100644 packages/noble-curves/src/abstract/utils.ts create mode 100644 packages/noble-curves/src/abstract/weierstrass.ts create mode 100644 packages/noble-curves/src/bls12-381.ts create mode 100644 packages/noble-curves/src/bn254.ts create mode 100644 packages/noble-curves/src/ed25519.ts create mode 100644 packages/noble-curves/src/ed448.ts create mode 100644 packages/noble-curves/src/index.ts create mode 100644 packages/noble-curves/src/jubjub.ts create mode 100644 packages/noble-curves/src/p256.ts create mode 100644 packages/noble-curves/src/p384.ts create mode 100644 packages/noble-curves/src/p521.ts create mode 100644 packages/noble-curves/src/package.json create mode 100644 packages/noble-curves/src/pasta.ts create mode 100644 packages/noble-curves/src/secp256k1.ts diff --git a/packages/noble-curves/LICENSE b/packages/noble-curves/LICENSE new file mode 100644 index 00000000000..9297a046d01 --- /dev/null +++ b/packages/noble-curves/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 Paul Miller (https://paulmillr.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/packages/noble-curves/README.md b/packages/noble-curves/README.md new file mode 100644 index 00000000000..02527331b9b --- /dev/null +++ b/packages/noble-curves/README.md @@ -0,0 +1,1113 @@ +# noble-curves + +Audited & minimal JS implementation of elliptic curve cryptography. + +- 🔒 [**Audited**](#security) by independent security firms +- 🔻 Tree-shakeable: unused code is excluded from your builds +- 🏎 Fast: hand-optimized for caveats of JS engines +- 🔍 Reliable: cross-library / wycheproof tests and fuzzing ensure correctness +- ➰ Short Weierstrass, Edwards, Montgomery curves +- ✍️ ECDSA, EdDSA, Schnorr, BLS, ECDH, hashing to curves, Poseidon ZK-friendly hash +- 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519 & ed448 +- 🪶 93KB for everything with hashes, 26KB (11KB gzipped) for single-curve build + +Curves have 4KB sister projects +[secp256k1](https://github.com/paulmillr/noble-secp256k1) & [ed25519](https://github.com/paulmillr/noble-ed25519). +They have smaller attack surface, but less features. + +Take a glance at [GitHub Discussions](https://github.com/paulmillr/noble-curves/discussions) for questions and support. + +### This library belongs to _noble_ cryptography + +> **noble cryptography** — high-security, easily auditable set of contained cryptographic libraries and tools. + +- Zero or minimal dependencies +- Highly readable TypeScript / JS code +- PGP-signed releases and transparent NPM builds +- All libraries: + [ciphers](https://github.com/paulmillr/noble-ciphers), + [curves](https://github.com/paulmillr/noble-curves), + [hashes](https://github.com/paulmillr/noble-hashes), + [post-quantum](https://github.com/paulmillr/noble-post-quantum), + 4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) / + [ed25519](https://github.com/paulmillr/noble-ed25519) +- [Check out homepage](https://paulmillr.com/noble/) + for reading resources, documentation and apps built with noble + +## Usage + +> `npm install @noble/curves` + +> `deno add jsr:@noble/curves` + +> `deno doc jsr:@noble/curves` # command-line documentation + +We support all major platforms and runtimes. +For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values). +A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available. + +```js +// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size +import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js +// import { secp256k1 } from 'npm:@noble/curves@1.6.0/secp256k1'; // Deno +``` + +- [Implementations](#implementations) + - [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others) + - [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy) + - [ECDH: Elliptic Curve Diffie-Hellman](#ecdh-elliptic-curve-diffie-hellman) + - [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340) + - [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255) + - [ed448, X448, decaf448](#ed448-x448-decaf448) + - [bls12-381](#bls12-381) + - [bn254 aka alt_bn128](#bn254-aka-alt_bn128) + - [Multi-scalar-multiplication](#multi-scalar-multiplication) + - [Accessing a curve's variables](#accessing-a-curves-variables) + - [All available imports](#all-available-imports) +- [Abstract API](#abstract-api) + - [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve) + - [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve) + - [montgomery: Montgomery curve](#montgomery-montgomery-curve) + - [bls: Barreto-Lynn-Scott curves](#bls-barreto-lynn-scott-curves) + - [hash-to-curve: Hashing strings to curve points](#hash-to-curve-hashing-strings-to-curve-points) + - [poseidon: Poseidon hash](#poseidon-poseidon-hash) + - [modular: Modular arithmetics utilities](#modular-modular-arithmetics-utilities) + - [Creating private keys from hashes](#creating-private-keys-from-hashes) + - [utils: Useful utilities](#utils-useful-utilities) +- [Security](#security) +- [Speed](#speed) +- [Upgrading](#upgrading) +- [Contributing & testing](#contributing--testing) +- [License](#license) + +### Implementations + +Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes). +If you want to use a different hashing library, [abstract API](#abstract-api) doesn't depend on them. + +#### ECDSA signatures over secp256k1 and others + +```ts +import { secp256k1 } from '@noble/curves/secp256k1'; +// import { p256 } from '@noble/curves/p256'; // or p384 / p521 + +const priv = secp256k1.utils.randomPrivateKey(); +const pub = secp256k1.getPublicKey(priv); +const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa +const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available +const isValid = secp256k1.verify(sig, msg, pub) === true; + +// hex strings are also supported besides Uint8Array-s: +const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236'; +const pub2 = secp256k1.getPublicKey(privHex); +``` + +The same code would work for NIST P256 (secp256r1), P384 (secp384r1) & P521 (secp521r1). + +#### ECDSA public key recovery & extra entropy + +```ts +// let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex) +// sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format +sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery + +// extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html +const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true }); +``` + +#### ECDH: Elliptic Curve Diffie-Hellman + +```ts +// 1. The output includes parity byte. Strip it using shared.slice(1) +// 2. The output is not hashed. More secure way is sha256(shared) or hkdf(shared) +const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey()); +const shared = secp256k1.getSharedSecret(priv, someonesPub); +``` + +#### Schnorr signatures over secp256k1 (BIP340) + +```ts +import { schnorr } from '@noble/curves/secp256k1'; +const priv = schnorr.utils.randomPrivateKey(); +const pub = schnorr.getPublicKey(priv); +const msg = new TextEncoder().encode('hello'); +const sig = schnorr.sign(msg, priv); +const isValid = schnorr.verify(sig, msg, pub); +``` + +#### ed25519, X25519, ristretto255 + +```ts +import { ed25519 } from '@noble/curves/ed25519'; +const priv = ed25519.utils.randomPrivateKey(); +const pub = ed25519.getPublicKey(priv); +const msg = new TextEncoder().encode('hello'); +const sig = ed25519.sign(msg, priv); +ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 +ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 +``` + +Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and +[can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am). +It has SUF-CMA (strong unforgeability under chosen message attacks). +`zip215: false` option switches verification criteria to strict +[RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final) +and additionally provides [non-repudiation with SBS](#edwards-twisted-edwards-curve). + +X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748). + +```ts +// Variants from RFC8032: with context, prehashed +import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519'; + +// ECDH using curve25519 aka x25519 +import { x25519 } from '@noble/curves/ed25519'; +const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; +const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; +x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases +x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); +x25519.getPublicKey(x25519.utils.randomPrivateKey()); + +// ed25519 => x25519 conversion +import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519'; +edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey())); +edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey()); +``` + +ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448). + +```ts +// hash-to-curve, ristretto255 +import { utf8ToBytes } from '@noble/hashes/utils'; +import { sha512 } from '@noble/hashes/sha512'; +import { + hashToCurve, + encodeToCurve, + RistrettoPoint, + hashToRistretto255, +} from '@noble/curves/ed25519'; + +const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee'); +hashToCurve(msg); + +const rp = RistrettoPoint.fromHex( + '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919' +); +RistrettoPoint.BASE.multiply(2n).add(rp).subtract(RistrettoPoint.BASE).toRawBytes(); +RistrettoPoint.ZERO.equals(dp) === false; +// pre-hashed hash-to-curve +RistrettoPoint.hashToCurve(sha512(msg)); +// full hash-to-curve including domain separation tag +hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' }); +``` + +#### ed448, X448, decaf448 + +```ts +import { ed448 } from '@noble/curves/ed448'; +const priv = ed448.utils.randomPrivateKey(); +const pub = ed448.getPublicKey(priv); +const msg = new TextEncoder().encode('whatsup'); +const sig = ed448.sign(msg, priv); +ed448.verify(sig, msg, pub); + +// Variants from RFC8032: prehashed +import { ed448ph } from '@noble/curves/ed448'; +``` + +ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748). + +```ts +import { x448 } from '@noble/curves/ed448'; +x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases +x448.getPublicKey(priv) === x448.scalarMultBase(priv); + +// ed448 => x448 conversion +import { edwardsToMontgomeryPub } from '@noble/curves/ed448'; +edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey())); +``` + +decaf448 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448). + +```ts +import { utf8ToBytes } from '@noble/hashes/utils'; +import { shake256 } from '@noble/hashes/sha3'; +import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448'; + +const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee'); +hashToCurve(msg); + +const dp = DecafPoint.fromHex( + 'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75' +); +DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toRawBytes(); +DecafPoint.ZERO.equals(dp) === false; +// pre-hashed hash-to-curve +DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 })); +// full hash-to-curve including domain separation tag +hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' }); +``` + +Same RFC7748 / RFC8032 / IRTF draft are followed. + +#### bls12-381 + +```ts +import { bls12_381 as bls } from '@noble/curves/bls12-381'; + +// G1 keys, G2 signatures +const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; +const message = '64726e3da8'; +const publicKey = bls.getPublicKey(privateKey); +const signature = bls.sign(message, privateKey); +const isValid = bls.verify(signature, message, publicKey); +console.log({ publicKey, signature, isValid }); + +// G2 keys, G1 signatures +// getPublicKeyForShortSignatures(privateKey) +// signShortSignature(message, privateKey) +// verifyShortSignature(signature, message, publicKey) +// aggregateShortSignatures(signatures) + +// Custom DST +const htfEthereum = { DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_' }; +const signatureEth = bls.sign(message, privateKey, htfEthereum); +const isValidEth = bls.verify(signature, message, publicKey, htfEthereum); + +// Aggregation +const aggregatedKey = bls.aggregatePublicKeys([bls.utils.randomPrivateKey(), bls.utils.randomPrivateKey()]) +// const aggregatedSig = bls.aggregateSignatures(sigs) + +// Pairings, with and without final exponentiation +// bls.pairing(PointG1, PointG2); +// bls.pairing(PointG1, PointG2, false); +// bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(PointG1, PointG2)); + +// Others +// bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE; +// bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr; +``` + +See [abstract/bls](#bls-barreto-lynn-scott-curves). +For example usage, check out [the implementation of BLS EVM precompiles](https://github.com/ethereumjs/ethereumjs-monorepo/blob/361f4edbc239e795a411ac2da7e5567298b9e7e5/packages/evm/src/precompiles/bls12_381/noble.ts). + +#### bn254 aka alt_bn128 + +```ts +import { bn254 } from '@noble/curves/bn254'; + +console.log( + bn254.G1, + bn254.G2, + bn254.pairing +) +``` + +The API mirrors [BLS](#bls12-381). The curve was previously called alt_bn128. +The implementation is compatible with [EIP-196](https://eips.ethereum.org/EIPS/eip-196) and +[EIP-197](https://eips.ethereum.org/EIPS/eip-197). + +Keep in mind that we don't implement Point methods toHex / toRawBytes. It's because +different implementations of bn254 do it differently - there is no standard. Points of divergence: + +- Endianness: LE vs BE (byte-swapped) +- Flags as first hex bits (similar to BLS) vs no-flags +- Imaginary part last in G2 vs first (c0, c1 vs c1, c0) + +For example usage, check out [the implementation of bn254 EVM precompiles](https://github.com/paulmillr/noble-curves/blob/3ed792f8ad9932765b84d1064afea8663a255457/test/bn254.test.js#L697). + +#### Multi-scalar-multiplication + +```ts +import { secp256k1 } from '@noble/curves/secp256k1'; +const p = secp256k1.ProjectivePoint; +const points = [p.BASE, p.BASE.multiply(2n), p.BASE.multiply(4n), p.BASE.multiply(8n)]; +p.msm(points, [3n, 5n, 7n, 11n]).equals(p.BASE.multiply(129n)); // 129*G +``` + +Pippenger algorithm is used underneath. +Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`. +It's 10-30x faster vs naive addition for large amount of points. + +#### Accessing a curve's variables + +```ts +import { secp256k1 } from '@noble/curves/secp256k1'; +// Every curve has `CURVE` object that contains its parameters, field, and others +console.log(secp256k1.CURVE.p); // field modulus +console.log(secp256k1.CURVE.n); // curve order +console.log(secp256k1.CURVE.a, secp256k1.CURVE.b); // equation params +console.log(secp256k1.CURVE.Gx, secp256k1.CURVE.Gy); // base point coordinates +``` + + +#### All available imports + +```typescript +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { pallas, vesta } from '@noble/curves/pasta'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128 +import { jubjub } from '@noble/curves/jubjub'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + +## Abstract API + +Abstract API allows to define custom curves. All arithmetics is done with JS +bigints over finite fields, which is defined from `modular` sub-module. For +scalar multiplication, we use +[precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). +Precomputes are enabled for weierstrass and edwards BASE points of a curve. You +could precompute any other point (e.g. for ECDH) using `utils.precompute()` +method: check out examples. + +### weierstrass: Short Weierstrass curve + +```ts +import { weierstrass } from '@noble/curves/abstract/weierstrass'; +import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics +import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash +import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256() +import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities + +const hmacSha256 = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)); + +// secq256k1: cycle of secp256k1 with Fp/N flipped. +// https://personaelabs.org/posts/spartan-ecdsa +// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves +const secq256k1 = weierstrass({ + // Curve equation params a, b + a: 0n, + b: 7n, + // Field over which we'll do calculations + Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n), + // Curve order, total count of valid points in the field. + n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n, + // Base point (x, y) aka generator point + Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n, + Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n, + + hash: sha256, + hmac: hmacSha256, + randomBytes, +}); + +// NIST secp192r1 aka p192 https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1 +const secp192r1 = weierstrass({ + a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'), + b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'), + Fp: Field(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')), + n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'), + Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'), + Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'), + h: BigInt(1), + hash: sha256, + hmac: hmacSha256, + randomBytes, +}); + + +// Replace weierstrass() with weierstrassPoints() if you don't need ECDSA, hash, hmac, randomBytes +``` + +Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` +expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h` +and coordinates `Gx`, `Gy` of generator point. + +**`k` generation** is done deterministically, following +[RFC6979](https://www.rfc-editor.org/rfc/rfc6979). It is suggested to use `extraEntropy` +option, which incorporates randomness into signatures to increase their security. + +For k generation, specifying `hmac` & `hash` is required, +which in our implementations is done by noble-hashes. If +you're using different hashing library, make sure to wrap it in the following interface: + +```ts +type CHash = { + (message: Uint8Array): Uint8Array; + blockLen: number; + outputLen: number; + create(): any; +}; + +// example +function sha256(message: Uint8Array) { + return _internal_lowlvl(message); +} +sha256.outputLen = 32; // 32 bytes of output for sha2-256 +``` + +**Message hash** is expected instead of message itself: + +- `sign(msgHash, privKey)` is default behavior, assuming you pre-hash msg with sha2, or other hash +- `sign(msg, privKey, {prehash: true})` option can be used if you want to pass the message itself + +**Weierstrass points:** + +1. Exported as `ProjectivePoint` +2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) +3. Use complete exception-free formulas for addition and doubling +4. Can be decoded/encoded from/to Uint8Array / hex strings using + `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()` +5. Have `assertValidity()` which checks for being on-curve +6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates + +```ts +// `weierstrassPoints()` returns `CURVE` and `ProjectivePoint` +// `weierstrass()` returns `CurveFn` +type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array }; +type CurveFn = { + CURVE: ReturnType; + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array; + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array; + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType; + verify: ( + signature: Hex | SignatureType, + msgHash: Hex, + publicKey: Hex, + opts?: { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' } + ) => boolean; + ProjectivePoint: ProjectivePointConstructor; + Signature: SignatureConstructor; + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint; + isValidPrivateKey(key: PrivKey): boolean; + randomPrivateKey: () => Uint8Array; + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType; + }; +}; + +// T is usually bigint, but can be something else like complex numbers in BLS curves +interface ProjPointType extends Group> { + readonly px: T; + readonly py: T; + readonly pz: T; + get x(): bigint; + get y(): bigint; + multiply(scalar: bigint): ProjPointType; + multiplyUnsafe(scalar: bigint): ProjPointType; + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined; + toAffine(iz?: T): AffinePoint; + isTorsionFree(): boolean; + clearCofactor(): ProjPointType; + assertValidity(): void; + hasEvenY(): boolean; + toRawBytes(isCompressed?: boolean): Uint8Array; + toHex(isCompressed?: boolean): string; +} +// Static methods for 3d XYZ points +interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType; + fromAffine(p: AffinePoint): ProjPointType; + fromHex(hex: Hex): ProjPointType; + fromPrivateKey(privateKey: PrivKey): ProjPointType; + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType; +} +``` + +**ECDSA signatures** are represented by `Signature` instances and can be +described by the interface: + +```ts +interface SignatureType { + readonly r: bigint; + readonly s: bigint; + readonly recovery?: number; + assertValidity(): void; + addRecoveryBit(recovery: number): SignatureType; + hasHighS(): boolean; + normalizeS(): SignatureType; + recoverPublicKey(msgHash: Hex): ProjPointType; + toCompactRawBytes(): Uint8Array; + toCompactHex(): string; + // DER-encoded + toDERRawBytes(): Uint8Array; + toDERHex(): string; +} +type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType; + fromCompact(hex: Hex): SignatureType; + fromDER(hex: Hex): SignatureType; +}; +``` + +More examples: + +```typescript +// All curves expose same generic interface. +const priv = secq256k1.utils.randomPrivateKey(); +secq256k1.getPublicKey(priv); // Convert private key to public. +const sig = secq256k1.sign(msg, priv); // Sign msg with private key. +const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg) +secq256k1.verify(sig, msg, priv); // Verify if sig is correct. + +// Default behavior is "try DER, then try compact if fails". Can be explicit: +secq256k1.verify(sig.toCompactHex(), msg, priv, { format: 'compact' }); + +const Point = secq256k1.ProjectivePoint; +const point = Point.BASE; // Elliptic curve Point class and BASE point static var. +point.add(point).equals(point.double()); // add(), equals(), double() methods +point.subtract(point).equals(Point.ZERO); // subtract() method, ZERO static var +point.negate(); // Flips point over x/y coordinate. +point.multiply(31415n); // Multiplication of Point by scalar. + +point.assertValidity(); // Checks for being on-curve +point.toAffine(); // Converts to 2d affine xy coordinates + +secq256k1.CURVE.n; +secq256k1.CURVE.p; +secq256k1.CURVE.Fp.mod(); +secq256k1.CURVE.hash(); + +// precomputes +const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey)); +fast.multiply(privKey); // much faster ECDH now +``` + +### edwards: Twisted Edwards curve + +```ts +import { twistedEdwards } from '@noble/curves/abstract/edwards'; +import { Field } from '@noble/curves/abstract/modular'; +import { sha512 } from '@noble/hashes/sha512'; +import { randomBytes } from '@noble/hashes/utils'; + +const Fp = Field(2n ** 255n - 19n); +const ed25519 = twistedEdwards({ + a: Fp.create(-1n), + d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p + Fp: Fp, + n: 2n ** 252n + 27742317777372353535851937790883648493n, + h: 8n, + Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n, + Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n, + hash: sha512, + randomBytes, + adjustScalarBytes(bytes) { + // optional; but mandatory in ed25519 + bytes[0] &= 248; + bytes[31] &= 127; + bytes[31] |= 64; + return bytes; + }, +} as const); +``` + +Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h` +and coordinates `Gx`, `Gy` of generator point. + +For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified. + +We support [non-repudiation](https://eprint.iacr.org/2020/1244), which help in following scenarios: + +- Contract Signing: if A signed an agreement with B using key that allows repudiation, it can later claim that it signed a different contract +- E-voting: malicious voters may pick keys that allow repudiation in order to deny results +- Blockchains: transaction of amount X might also be valid for a different amount Y + +**Edwards points:** + +1. Exported as `ExtendedPoint` +2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z) +3. Use complete exception-free formulas for addition and doubling +4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()` +5. Have `assertValidity()` which checks for being on-curve +6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates +7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions + +```ts +// `twistedEdwards()` returns `CurveFn` of following type: +type CurveFn = { + CURVE: ReturnType; + getPublicKey: (privateKey: Hex) => Uint8Array; + sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array; + verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean; + ExtendedPoint: ExtPointConstructor; + utils: { + randomPrivateKey: () => Uint8Array; + getExtendedPublicKey: (key: PrivKey) => { + head: Uint8Array; + prefix: Uint8Array; + scalar: bigint; + point: PointType; + pointBytes: Uint8Array; + }; + }; +}; + +interface ExtPointType extends Group { + readonly ex: bigint; + readonly ey: bigint; + readonly ez: bigint; + readonly et: bigint; + get x(): bigint; + get y(): bigint; + assertValidity(): void; + multiply(scalar: bigint): ExtPointType; + multiplyUnsafe(scalar: bigint): ExtPointType; + isSmallOrder(): boolean; + isTorsionFree(): boolean; + clearCofactor(): ExtPointType; + toAffine(iz?: bigint): AffinePoint; + toRawBytes(isCompressed?: boolean): Uint8Array; + toHex(isCompressed?: boolean): string; +} +// Static methods of Extended Point with coordinates in X, Y, Z, T +interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType; + fromAffine(p: AffinePoint): ExtPointType; + fromHex(hex: Hex): ExtPointType; + fromPrivateKey(privateKey: Hex): ExtPointType; + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType; +} +``` + +### montgomery: Montgomery curve + +```typescript +import { montgomery } from '@noble/curves/abstract/montgomery'; +import { Field } from '@noble/curves/abstract/modular'; + +const x25519 = montgomery({ + a: 486662n, + Gu: 9n, + P: 2n ** 255n - 19n, + montgomeryBits: 255, + nByteLength: 32, + // Optional param + adjustScalarBytes(bytes) { + bytes[0] &= 248; + bytes[31] &= 127; + bytes[31] |= 64; + return bytes; + }, +}); +``` + +The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. +Proper Elliptic Curve Points are not implemented yet. + +You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`. + +### bls: Barreto-Lynn-Scott curves + +The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction. +They allow to construct [zk-SNARKs](https://z.cash/technology/zksnarks/) and +use aggregated, batch-verifiable +[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716), +using Boneh-Lynn-Shacham signature scheme. + +The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead. +Only BLS12-381 is currently implemented. +Defining BLS12-377 and BLS24 should be straightforward. + +The default BLS uses short public keys (with public keys in G1 and signatures in G2). +Short signatures (public keys in G2 and signatures in G1) are also supported. + +### hash-to-curve: Hashing strings to curve points + +The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + +Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security: + +```ts +import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1'; +import { randomBytes } from '@noble/hashes/utils'; +hashToCurve('0102abcd'); +console.log(hashToCurve(randomBytes())); +console.log(encodeToCurve(randomBytes())); + +import { bls12_381 } from '@noble/curves/bls12-381'; +bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' }); +bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' }); +``` + +Low-level methods from the spec: + +```ts +// produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. +function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash // For CHash see abstract/weierstrass docs section +): Uint8Array; +// produces a uniformly random byte string using an extendable-output function (XOF) H. +function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash +): Uint8Array; +// Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F +function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][]; + +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +type UnicodeOrBytes = string | Uint8Array; +type Opts = { + DST: UnicodeOrBytes; + p: bigint; + m: number; + k: number; + expand?: 'xmd' | 'xof'; + hash: CHash; +}; +``` + +### poseidon: Poseidon hash + +Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + +There are many poseidon variants with different constants. +We don't provide them: you should construct them manually. +Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + +```ts +import { poseidon } from '@noble/curves/abstract/poseidon'; + +type PoseidonOpts = { + Fp: Field; + t: number; + roundsFull: number; + roundsPartial: number; + sboxPower?: number; + reversePartialPowIdx?: boolean; + mds: bigint[][]; + roundConstants: bigint[][]; +}; +const instance = poseidon(opts: PoseidonOpts); +``` + +### modular: Modular arithmetics utilities + +```ts +import * as mod from '@noble/curves/abstract/modular'; + +// Finite Field utils +const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19 +fp.mul(591n, 932n); // multiplication +fp.pow(481n, 11024858120n); // exponentiation +fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17) +fp.inv(5n); // modular inverse +fp.sqrt(21n); // square root + +// Non-Field generic utils are also available +mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10 +mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse +mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion +``` + +Field operations are not constant-time: they are using JS bigints, see [security](#security). +The fact is mostly irrelevant, but the important method to keep in mind is `pow`, +which may leak exponent bits, when used naïvely. + +`mod.Field` is always **field over prime number**. Non-prime fields aren't supported for now. +We don't test for prime-ness for speed and because algorithms are probabilistic anyway. +Initializing a non-prime field could make your app suspectible to +DoS (infilite loop) on Tonelli-Shanks square root calculation. + +Unlike `mod.inv`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself. + +#### Creating private keys from hashes + +You can't simply make a 32-byte private key from a 32-byte hash. +Doing so will make the key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/). + +To make the bias negligible, we follow [FIPS 186-5 A.2](https://csrc.nist.gov/publications/detail/fips/186/5/final) +and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). +This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level. + +`hashToPrivateScalar()` that hashes to **private key** was created for this purpose. +Use [abstract/hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points) +if you need to hash to **public key**. + +```ts +import { p256 } from '@noble/curves/p256'; +import { sha256 } from '@noble/hashes/sha256'; +import { hkdf } from '@noble/hashes/hkdf'; +import * as mod from '@noble/curves/abstract/modular'; +const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2) +const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv +const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n); +``` + +### utils: Useful utilities + +```ts +import * as utils from '@noble/curves/abstract/utils'; + +utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); +utils.hexToBytes('deadbeef'); +utils.numberToHexUnpadded(123n); +utils.hexToNumber(); + +utils.bytesToNumberBE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); +utils.bytesToNumberLE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); +utils.numberToBytesBE(123n, 32); +utils.numberToBytesLE(123n, 64); + +utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef])); +utils.nLength(255n); +utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde])); +``` + +## Security + +The library has been independently audited: + +- at version 1.6.0, in Sep 2024, by [Cure53](https://cure53.de) + - PDFs: [website](https://cure53.de/audit-report_noble-crypto-libs.pdf), [in-repo](./audit/2024-09-cure53-audit-nbl4.pdf) + - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.6.0..main) + - Scope: ed25519, ed448, their add-ons, bls12-381, bn254, + hash-to-curve, low-level primitives bls, tower, edwards, montgomery. + - The audit has been funded by [OpenSats](https://opensats.org) +- at version 1.2.0, in Sep 2023, by [Kudelski Security](https://kudelskisecurity.com) + - PDFs: [in-repo](./audit/2023-09-kudelski-audit-starknet.pdf) + - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.2.0..main) + - Scope: [scure-starknet](https://github.com/paulmillr/scure-starknet) and its related + abstract modules of noble-curves: `curve`, `modular`, `poseidon`, `weierstrass` + - The audit has been funded by [Starkware](https://starkware.co) +- at version 0.7.3, in Feb 2023, by [Trail of Bits](https://www.trailofbits.com) + - PDFs: [website](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf), + [in-repo](./audit/2023-01-trailofbits-audit-curves.pdf) + - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main) + - Scope: abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass` and + top-level modules `_shortw_utils` and `secp256k1` + - The audit has been funded by [Ryan Shea](https://www.shea.io) + +It is tested against property-based, cross-library and Wycheproof vectors, +and has fuzzing by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). + +If you see anything unusual: investigate and report. + +### Constant-timeness + +_JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to +achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance +in a scripting language. Which means _any other JS library can't have +constant-timeness_. Even statically typed Rust, a language without GC, +[makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) +for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. +Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time. + +### Supply chain security + +- **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures. +- **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs +- **Rare releasing** is followed to ensure less re-audit need for end-users +- **Dependencies** are minimized and locked-down: + - If your app has 500 dependencies, any dep could get hacked and you'll be downloading + malware with every install. We make sure to use as few dependencies as possible + - We prevent automatic dependency updates by locking-down version ranges. Every update is checked with `npm-diff` + - One dependency [noble-hashes](https://github.com/paulmillr/noble-hashes) is used, by the same author, to provide hashing functionality +- **Dev Dependencies** are only used if you want to contribute to the repo. They are disabled for end-users: + - scure-base, scure-bip32, scure-bip39, micro-bmark and micro-should are developed by the same author and follow identical security practices + - prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully + +### Randomness + +We're deferring to built-in +[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) +which is considered cryptographically secure (CSPRNG). + +In the past, browsers had bugs that made it weak: it may happen again. +Implementing a userspace CSPRNG to get resilient to the weakness +is even worse: there is no reliable userspace source of quality entropy. + +### Quantum computers + +Cryptographically relevant quantum computer, if built, will allow to +break elliptic curve cryptography (both ECDSA / EdDSA & ECDH) using Shor's algorithm. + +Consider switching to newer / hybrid algorithms, such as SPHINCS+. They are available in +[noble-post-quantum](https://github.com/paulmillr/noble-post-quantum). + +NIST prohibits classical cryptography (RSA, DSA, ECDSA, ECDH) [after 2035](https://nvlpubs.nist.gov/nistpubs/ir/2024/NIST.IR.8547.ipd.pdf). Australian ASD prohibits it [after 2030](https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography). + +## Speed + +Benchmark results on Apple M2 with node v22: + +``` +secp256k1 +init x 68 ops/sec @ 14ms/op +getPublicKey x 6,839 ops/sec @ 146μs/op +sign x 5,226 ops/sec @ 191μs/op +verify x 893 ops/sec @ 1ms/op +getSharedSecret x 538 ops/sec @ 1ms/op +recoverPublicKey x 923 ops/sec @ 1ms/op +schnorr.sign x 700 ops/sec @ 1ms/op +schnorr.verify x 919 ops/sec @ 1ms/op + +ed25519 +init x 51 ops/sec @ 19ms/op +getPublicKey x 9,809 ops/sec @ 101μs/op +sign x 4,976 ops/sec @ 200μs/op +verify x 1,018 ops/sec @ 981μs/op + +ed448 +init x 19 ops/sec @ 50ms/op +getPublicKey x 3,723 ops/sec @ 268μs/op +sign x 1,759 ops/sec @ 568μs/op +verify x 344 ops/sec @ 2ms/op + +p256 +init x 39 ops/sec @ 25ms/op +getPublicKey x 6,518 ops/sec @ 153μs/op +sign x 5,148 ops/sec @ 194μs/op +verify x 609 ops/sec @ 1ms/op + +p384 +init x 17 ops/sec @ 57ms/op +getPublicKey x 2,933 ops/sec @ 340μs/op +sign x 2,327 ops/sec @ 429μs/op +verify x 244 ops/sec @ 4ms/op + +p521 +init x 8 ops/sec @ 112ms/op +getPublicKey x 1,484 ops/sec @ 673μs/op +sign x 1,264 ops/sec @ 790μs/op +verify x 124 ops/sec @ 8ms/op + +ristretto255 +add x 680,735 ops/sec @ 1μs/op +multiply x 10,766 ops/sec @ 92μs/op +encode x 15,835 ops/sec @ 63μs/op +decode x 15,972 ops/sec @ 62μs/op + +decaf448 +add x 345,303 ops/sec @ 2μs/op +multiply x 300 ops/sec @ 3ms/op +encode x 5,987 ops/sec @ 167μs/op +decode x 5,892 ops/sec @ 169μs/op + +ecdh +├─x25519 x 1,477 ops/sec @ 676μs/op +├─secp256k1 x 537 ops/sec @ 1ms/op +├─p256 x 512 ops/sec @ 1ms/op +├─p384 x 198 ops/sec @ 5ms/op +├─p521 x 99 ops/sec @ 10ms/op +└─x448 x 504 ops/sec @ 1ms/op + +bls12-381 +init x 36 ops/sec @ 27ms/op +getPublicKey x 960 ops/sec @ 1ms/op +sign x 60 ops/sec @ 16ms/op +verify x 47 ops/sec @ 21ms/op +pairing x 125 ops/sec @ 7ms/op +pairing10 x 40 ops/sec @ 24ms/op ± 23.27% (min: 21ms, max: 48ms) +MSM 4096 scalars x points x 0 ops/sec @ 4655ms/op +aggregatePublicKeys/8 x 129 ops/sec @ 7ms/op +aggregatePublicKeys/32 x 34 ops/sec @ 28ms/op +aggregatePublicKeys/128 x 8 ops/sec @ 113ms/op +aggregatePublicKeys/512 x 2 ops/sec @ 449ms/op +aggregatePublicKeys/2048 x 0 ops/sec @ 1792ms/op +aggregateSignatures/8 x 62 ops/sec @ 15ms/op +aggregateSignatures/32 x 16 ops/sec @ 60ms/op +aggregateSignatures/128 x 4 ops/sec @ 238ms/op +aggregateSignatures/512 x 1 ops/sec @ 946ms/op +aggregateSignatures/2048 x 0 ops/sec @ 3774ms/op + +hash-to-curve +hash_to_field x 91,600 ops/sec @ 10μs/op +secp256k1 x 2,373 ops/sec @ 421μs/op +p256 x 4,310 ops/sec @ 231μs/op +p384 x 1,664 ops/sec @ 600μs/op +p521 x 807 ops/sec @ 1ms/op +ed25519 x 3,088 ops/sec @ 323μs/op +ed448 x 1,247 ops/sec @ 801μs/op +``` + +## Upgrading + +Previously, the library was split into single-feature packages +[noble-secp256k1](https://github.com/paulmillr/noble-secp256k1), +[noble-ed25519](https://github.com/paulmillr/noble-ed25519) and +[noble-bls12-381](https://github.com/paulmillr/noble-bls12-381). + +Curves continue their original work. The single-feature packages changed their +direction towards providing minimal 4kb implementations of cryptography, +which means they have less features. + +Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible. + +Upgrading from noble-secp256k1 1.7: + +- `getPublicKey` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + argument `isCompressed` to `false`: `getPublicKey(priv, false)` +- `sign` + - is now sync + - now returns `Signature` instance with `{ r, s, recovery }` properties + - `canonical` option was renamed to `lowS` + - `recovered` option has been removed because recovery bit is always returned now + - `der` option has been removed. There are 2 options: + 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`. + Compact encoding is simply a concatenation of 32-byte r and 32-byte s. + 2. If you must use DER encoding, switch to noble-curves (see above). +- `verify` + - is now sync + - `strict` option was renamed to `lowS` +- `getSharedSecret` + - now produce 33-byte compressed signatures by default + - to use old behavior, which produced 65-byte uncompressed keys, set + argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` +- `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` +- `number` type for private keys have been removed: use `bigint` instead +- `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) +- `utils` were split into `utils` (same api as in noble-curves) and + `etc` (`hmacSha256Sync` and others) + +Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7: + +- Methods are now sync by default +- `bigint` is no longer allowed in `getPublicKey`, `sign`, `verify`. Reason: ed25519 is LE, can lead to bugs +- `Point` (2d xy) has been changed to `ExtendedPoint` (xyzt) +- `Signature` was removed: just use raw bytes or hex now +- `utils` were split into `utils` (same api as in noble-curves) and + `etc` (`sha512Sync` and others) +- `getSharedSecret` was moved to `x25519` module +- `toX25519` has been moved to `edwardsToMontgomeryPub` and `edwardsToMontgomeryPriv` methods + +Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381): + +- Methods and classes were renamed: + - PointG1 -> G1.Point, PointG2 -> G2.Point + - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode +- Fp2 ORDER was corrected + +## Contributing & testing + +* `npm install && npm run build && npm test` will build the code and run tests. +* `npm run lint` / `npm run format` will run linter / fix linter issues. +* `npm run bench` will run benchmarks, which may need their deps first (`npm run bench:install`) +* `cd build && npm install && npm run build:release` will build single file + +Check out [github.com/paulmillr/guidelines](https://github.com/paulmillr/guidelines) +for general coding practices and rules. + +See [paulmillr.com/noble](https://paulmillr.com/noble/) +for useful resources, articles, documentation and demos +related to the library. + +## License + +The MIT License (MIT) + +Copyright (c) 2022 Paul Miller [(https://paulmillr.com)](https://paulmillr.com) + +See LICENSE file. diff --git a/packages/noble-curves/_shortw_utils.d.ts b/packages/noble-curves/_shortw_utils.d.ts new file mode 100644 index 00000000000..02064fbb558 --- /dev/null +++ b/packages/noble-curves/_shortw_utils.d.ts @@ -0,0 +1,16 @@ +import { randomBytes } from '@noble/hashes/utils' +import type { CHash } from './abstract/utils.js' +import { type CurveFn, type CurveType } from './abstract/weierstrass.js' +/** connects noble-curves to noble-hashes */ +export declare function getHash(hash: CHash): { + hash: CHash + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array + randomBytes: typeof randomBytes +} +/** Same API as @noble/hashes, with ability to create curve with custom hash */ +export type CurveDef = Readonly> +export type CurveFnWithCreate = CurveFn & { + create: (hash: CHash) => CurveFn +} +export declare function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate +//# sourceMappingURL=_shortw_utils.d.ts.map diff --git a/packages/noble-curves/_shortw_utils.d.ts.map b/packages/noble-curves/_shortw_utils.d.ts.map new file mode 100644 index 00000000000..e1caf75120a --- /dev/null +++ b/packages/noble-curves/_shortw_utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG;IACpC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,KAAK,UAAU,CAAC;IAC7D,WAAW,EAAE,OAAO,WAAW,CAAC;CACjC,CAMA;AACD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,GAAG,iBAAiB,CAGjF"} \ No newline at end of file diff --git a/packages/noble-curves/_shortw_utils.js b/packages/noble-curves/_shortw_utils.js new file mode 100644 index 00000000000..c0d0396660c --- /dev/null +++ b/packages/noble-curves/_shortw_utils.js @@ -0,0 +1,25 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.getHash = getHash +exports.createCurve = createCurve +/** + * Utilities for short weierstrass curves, combined with noble-hashes. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const hmac_1 = require('@noble/hashes/hmac') +const utils_1 = require('@noble/hashes/utils') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +/** connects noble-curves to noble-hashes */ +function getHash(hash) { + return { + hash, + hmac: (key, ...msgs) => (0, hmac_1.hmac)(hash, key, (0, utils_1.concatBytes)(...msgs)), + randomBytes: utils_1.randomBytes, + } +} +function createCurve(curveDef, defHash) { + const create = (hash) => (0, weierstrass_js_1.weierstrass)({ ...curveDef, ...getHash(hash) }) + return { ...create(defHash), create } +} +//# sourceMappingURL=_shortw_utils.js.map diff --git a/packages/noble-curves/_shortw_utils.js.map b/packages/noble-curves/_shortw_utils.js.map new file mode 100644 index 00000000000..9b3bc4dc02e --- /dev/null +++ b/packages/noble-curves/_shortw_utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"_shortw_utils.js","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":";;AAWA,0BAUC;AAKD,kCAGC;AA7BD;;;GAGG;AACH,sEAAsE;AACtE,6CAA0C;AAC1C,+CAA+D;AAE/D,8DAAsF;AAEtF,4CAA4C;AAC5C,SAAgB,OAAO,CAAC,IAAW;IAKjC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,CAAC,GAAe,EAAE,GAAG,IAAkB,EAAE,EAAE,CAAC,IAAA,WAAI,EAAC,IAAI,EAAE,GAAG,EAAE,IAAA,mBAAW,EAAC,GAAG,IAAI,CAAC,CAAC;QACvF,WAAW,EAAX,mBAAW;KACZ,CAAC;AACJ,CAAC;AAKD,SAAgB,WAAW,CAAC,QAAkB,EAAE,OAAc;IAC5D,MAAM,MAAM,GAAG,CAAC,IAAW,EAAW,EAAE,CAAC,IAAA,4BAAW,EAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/bls.d.ts b/packages/noble-curves/abstract/bls.d.ts new file mode 100644 index 00000000000..cc7aae5e409 --- /dev/null +++ b/packages/noble-curves/abstract/bls.d.ts @@ -0,0 +1,165 @@ +import { + type Opts as HTFOpts, + type MapToCurve, + createHasher, + type htfBasicOpts, +} from './hash-to-curve.js' +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' +import { type CHash, type Hex, type PrivKey } from './utils.js' +import { type CurvePointsRes, type CurvePointsType, type ProjPointType } from './weierstrass.js' +type Fp = bigint +export type TwistType = 'multiplicative' | 'divisive' +export type ShortSignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} +export type SignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} +export type PostPrecomputePointAddFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, +) => { + Rx: Fp2 + Ry: Fp2 + Rz: Fp2 +} +export type PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => void +export type CurveType = { + G1: Omit, 'n'> & { + ShortSignature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + G2: Omit, 'n'> & { + Signature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + fields: { + Fp: IField + Fr: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + } + params: { + ateLoopSize: bigint + xNegative: boolean + r: bigint + twistType: TwistType + } + htfDefaults: HTFOpts + hash: CHash + randomBytes: (bytesLength?: number) => Uint8Array + postPrecompute?: PostPrecomputeFn +} +type PrecomputeSingle = [Fp2, Fp2, Fp2][] +type Precompute = PrecomputeSingle[] +export type CurveFn = { + getPublicKey: (privateKey: PrivKey) => Uint8Array + getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array + sign: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + signShortSignature: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + verify: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyShortSignature: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyBatch: ( + signature: Hex | ProjPointType, + messages: (Hex | ProjPointType)[], + publicKeys: (Hex | ProjPointType)[], + htfOpts?: htfBasicOpts, + ) => boolean + aggregatePublicKeys: { + (publicKeys: Hex[]): Uint8Array + (publicKeys: ProjPointType[]): ProjPointType + } + aggregateSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + aggregateShortSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 + pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 + pairingBatch: ( + pairs: { + g1: ProjPointType + g2: ProjPointType + }[], + withFinalExponent?: boolean, + ) => Fp12 + G1: CurvePointsRes & ReturnType> + G2: CurvePointsRes & ReturnType> + Signature: SignatureCoder + ShortSignature: ShortSignatureCoder + params: { + ateLoopSize: bigint + r: bigint + G1b: bigint + G2b: Fp2 + } + fields: { + Fp: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + Fr: IField + } + utils: { + randomPrivateKey: () => Uint8Array + calcPairingPrecomputes: (p: ProjPointType) => Precompute + } +} +export declare function bls(CURVE: CurveType): CurveFn +export {} +//# sourceMappingURL=bls.d.ts.map diff --git a/packages/noble-curves/abstract/bls.d.ts.map b/packages/noble-curves/abstract/bls.d.ts.map new file mode 100644 index 00000000000..9aaa0b4dfd0 --- /dev/null +++ b/packages/noble-curves/abstract/bls.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bls.d.ts","sourceRoot":"","sources":["../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/bls.js b/packages/noble-curves/abstract/bls.js new file mode 100644 index 00000000000..c544ee14cc6 --- /dev/null +++ b/packages/noble-curves/abstract/bls.js @@ -0,0 +1,360 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.bls = bls +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// TODO: import { AffinePoint } from './curve.js'; +const modular_js_1 = require('./modular.js') +const utils_js_1 = require('./utils.js') +// prettier-ignore +const hash_to_curve_js_1 = require('./hash-to-curve.js') +const weierstrass_js_1 = require('./weierstrass.js') +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. +function NAfDecomposition(a) { + const res = [] + // a>1 because of marker bit + for (; a > _1n; a >>= _1n) { + if ((a & _1n) === _0n) res.unshift(0) + else if ((a & _3n) === _3n) { + res.unshift(-1) + a += _1n + } else res.unshift(1) + } + return res +} +function bls(CURVE) { + // Fields are specific for curve, so for now we'll need to pass them with opts + const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields + const BLS_X_IS_NEGATIVE = CURVE.params.xNegative + const TWIST = CURVE.params.twistType + // Point on G1 curve: (x, y) + const G1_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G1 }) + const G1 = Object.assign( + G1_, + (0, hash_to_curve_js_1.createHasher)(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G1.htfDefaults, + }), + ) + // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) + const G2_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G2 }) + const G2 = Object.assign( + G2_, + (0, hash_to_curve_js_1.createHasher)(G2_.ProjectivePoint, CURVE.G2.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G2.htfDefaults, + }), + ) + // Applies sparse multiplication as line function + let lineFunction + if (TWIST === 'multiplicative') { + lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) + } else if (TWIST === 'divisive') { + // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of + // precompute calculations. + lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) + } else throw new Error('bls: unknown twist type') + const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) + function pointDouble(ell, Rx, Ry, Rz) { + const t0 = Fp2.sqr(Ry) // Ry² + const t1 = Fp2.sqr(Rz) // Rz² + const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B + const t3 = Fp2.mul(t2, _3n) // 3 * T2 + const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 + const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) + const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² + const c2 = Fp2.neg(t4) // -T4 (-h) + ell.push([c0, c1, c2]) + Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 + Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² + Rz = Fp2.mul(t0, t4) // T0 * T4 + return { Rx, Ry, Rz } + } + function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) { + // Addition + const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz + const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz + const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy + const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry + const c2 = t1 // == Rx - Qx * Rz + ell.push([c0, c1, c2]) + const t2 = Fp2.sqr(t1) // T1² + const t3 = Fp2.mul(t2, t1) // T2 * T1 + const t4 = Fp2.mul(t2, Rx) // T2 * Rx + const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz + Rx = Fp2.mul(t1, t5) // T1 * T5 + Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry + Rz = Fp2.mul(Rz, t3) // Rz * T3 + return { Rx, Ry, Rz } + } + // Pre-compute coefficients for sparse multiplication + // Point addition and point double calculations is reused for coefficients + // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine + // add + double in windowed precomputes here, otherwise it would be single op (since X is static) + const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) + const calcPairingPrecomputes = (0, utils_js_1.memoized)((point) => { + const p = point + const { x, y } = p.toAffine() + // prettier-ignore + const Qx = x, + Qy = y, + negQy = Fp2.neg(y) + // prettier-ignore + let Rx = Qx, + Ry = Qy, + Rz = Fp2.ONE + const ell = [] + for (const bit of ATE_NAF) { + const cur = [] + ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) + if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) + ell.push(cur) + } + if (CURVE.postPrecompute) { + const last = ell[ell.length - 1] + CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) + } + return ell + }) + function millerLoopBatch(pairs, withFinalExponent = false) { + let f12 = Fp12.ONE + if (pairs.length) { + const ellLen = pairs[0][0].length + for (let i = 0; i < ellLen; i++) { + f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings + // NOTE: we apply multiple pairings in parallel here + for (const [ell, Px, Py] of pairs) { + for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) + } + } + } + if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) + return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 + } + // Calculates product of multiple pairings + // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` + function pairingBatch(pairs, withFinalExponent = true) { + const res = [] + // This cache precomputed toAffine for all points + G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) + G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) + for (const { g1, g2 } of pairs) { + if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) + throw new Error('pairing is not available for ZERO point') + // This uses toAffine inside + g1.assertValidity() + g2.assertValidity() + const Qa = g1.toAffine() + res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) + } + return millerLoopBatch(res, withFinalExponent) + } + // Calculates bilinear pairing + function pairing(Q, P, withFinalExponent = true) { + return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) + } + const utils = { + randomPrivateKey: () => { + const length = (0, modular_js_1.getMinHashLength)(Fr.ORDER) + return (0, modular_js_1.mapHashToField)(CURVE.randomBytes(length), Fr.ORDER) + }, + calcPairingPrecomputes, + } + const { ShortSignature } = CURVE.G1 + const { Signature } = CURVE.G2 + function normP1(point) { + return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point) + } + function normP1Hash(point, htfOpts) { + return point instanceof G1.ProjectivePoint + ? point + : G1.hashToCurve((0, utils_js_1.ensureBytes)('point', point), htfOpts) + } + function normP2(point) { + return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) + } + function normP2Hash(point, htfOpts) { + return point instanceof G2.ProjectivePoint + ? point + : G2.hashToCurve((0, utils_js_1.ensureBytes)('point', point), htfOpts) + } + // Multiplies generator (G1) by private key. + // P = pk x G + function getPublicKey(privateKey) { + return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + // Multiplies generator (G2) by private key. + // P = pk x G + function getPublicKeyForShortSignatures(privateKey) { + return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + function sign(message, privateKey, htfOpts) { + const msgPoint = normP2Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G2.ProjectivePoint) return sigPoint + return Signature.toRawBytes(sigPoint) + } + function signShortSignature(message, privateKey, htfOpts) { + const msgPoint = normP1Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G1.ProjectivePoint) return sigPoint + return ShortSignature.toRawBytes(sigPoint) + } + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(P, H(m)) == e(G, S) + function verify(signature, message, publicKey, htfOpts) { + const P = normP1(publicKey) + const Hm = normP2Hash(message, htfOpts) + const G = G1.ProjectivePoint.BASE + const S = normP2(signature) + const exp = pairingBatch([ + { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); + { g1: G, g2: S }, // eGS = pairing(G, S, false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(S, G) == e(H(m), P) + function verifyShortSignature(signature, message, publicKey, htfOpts) { + const P = normP2(publicKey) + const Hm = normP1Hash(message, htfOpts) + const G = G2.ProjectivePoint.BASE + const S = normP1(signature) + const exp = pairingBatch([ + { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); + { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + function aNonEmpty(arr) { + if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') + } + function aggregatePublicKeys(publicKeys) { + aNonEmpty(publicKeys) + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (publicKeys[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + // toRawBytes ensures point validity + return aggAffine.toRawBytes(true) + } + function aggregateSignatures(signatures) { + aNonEmpty(signatures) + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G2.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return Signature.toRawBytes(aggAffine) + } + function aggregateShortSignatures(signatures) { + aNonEmpty(signatures) + const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return ShortSignature.toRawBytes(aggAffine) + } + // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 + // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) + function verifyBatch( + signature, + // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? + messages, + publicKeys, + htfOpts, + ) { + aNonEmpty(messages) + if (publicKeys.length !== messages.length) + throw new Error('amount of public keys and messages should be equal') + const sig = normP2(signature) + const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) + const nPublicKeys = publicKeys.map(normP1) + // NOTE: this works only for exact same object + const messagePubKeyMap = new Map() + for (let i = 0; i < nPublicKeys.length; i++) { + const pub = nPublicKeys[i] + const msg = nMessages[i] + let keys = messagePubKeyMap.get(msg) + if (keys === undefined) { + keys = [] + messagePubKeyMap.set(msg, keys) + } + keys.push(pub) + } + const paired = [] + try { + for (const [msg, keys] of messagePubKeyMap) { + const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) + paired.push({ g1: groupPublicKey, g2: msg }) + } + paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) + return Fp12.eql(pairingBatch(paired), Fp12.ONE) + } catch { + return false + } + } + G1.ProjectivePoint.BASE._setWindowSize(4) + return { + getPublicKey, + getPublicKeyForShortSignatures, + sign, + signShortSignature, + verify, + verifyBatch, + verifyShortSignature, + aggregatePublicKeys, + aggregateSignatures, + aggregateShortSignatures, + millerLoopBatch, + pairing, + pairingBatch, + G1, + G2, + Signature, + ShortSignature, + fields: { + Fr, + Fp, + Fp2, + Fp6, + Fp12, + }, + params: { + ateLoopSize: CURVE.params.ateLoopSize, + r: CURVE.params.r, + G1b: CURVE.G1.b, + G2b: CURVE.G2.b, + }, + utils, + } +} +//# sourceMappingURL=bls.js.map diff --git a/packages/noble-curves/abstract/bls.js.map b/packages/noble-curves/abstract/bls.js.map new file mode 100644 index 00000000000..e6c9ece3311 --- /dev/null +++ b/packages/noble-curves/abstract/bls.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bls.js","sourceRoot":"","sources":["../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/curve.d.ts b/packages/noble-curves/abstract/curve.d.ts new file mode 100644 index 00000000000..b4984cb067f --- /dev/null +++ b/packages/noble-curves/abstract/curve.d.ts @@ -0,0 +1,124 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +export type AffinePoint = { + x: T + y: T +} & { + z?: never + t?: never +} +export interface Group> { + double(): T + negate(): T + add(other: T): T + subtract(other: T): T + equals(other: T): boolean + multiply(scalar: bigint): T +} +export type GroupConstructor = { + BASE: T + ZERO: T +} +export type Mapper = (i: T[]) => T[] +export type IWNAF> = { + constTimeNegate: >(condition: boolean, item: T) => T + hasPrecomputes(elm: T): boolean + unsafeLadder(elm: T, n: bigint, p?: T): T + precomputeWindow(elm: T, W: number): Group[] + wNAF( + W: number, + precomputes: T[], + n: bigint, + ): { + p: T + f: T + } + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T + getPrecomputes(W: number, P: T, transform: Mapper): T[] + wNAFCached( + P: T, + n: bigint, + transform: Mapper, + ): { + p: T + f: T + } + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T + setWindowSize(P: T, W: number): void +} +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export declare function wNAF>(c: GroupConstructor, bits: number): IWNAF +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster with precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export declare function pippenger>( + c: GroupConstructor, + fieldN: IField, + points: T[], + scalars: bigint[], +): T +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export declare function precomputeMSMUnsafe>( + c: GroupConstructor, + fieldN: IField, + points: T[], + windowSize: number, +): (scalars: bigint[]) => T +/** + * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. + * Though generator can be different (Fp2 / Fp6 for BLS). + */ +export type BasicCurve = { + Fp: IField + n: bigint + nBitLength?: number + nByteLength?: number + h: bigint + hEff?: bigint + Gx: T + Gy: T + allowInfinityPoint?: boolean +} +export declare function validateBasic( + curve: BasicCurve & T, +): Readonly< + { + readonly nBitLength: number + readonly nByteLength: number + } & BasicCurve & + T & { + p: bigint + } +> +//# sourceMappingURL=curve.d.ts.map diff --git a/packages/noble-curves/abstract/curve.d.ts.map b/packages/noble-curves/abstract/curve.d.ts.map new file mode 100644 index 00000000000..cc9403631ef --- /dev/null +++ b/packages/noble-curves/abstract/curve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/curve.js b/packages/noble-curves/abstract/curve.js new file mode 100644 index 00000000000..c93b3847bdf --- /dev/null +++ b/packages/noble-curves/abstract/curve.js @@ -0,0 +1,368 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.wNAF = wNAF +exports.pippenger = pippenger +exports.precomputeMSMUnsafe = precomputeMSMUnsafe +exports.validateBasic = validateBasic +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const modular_js_1 = require('./modular.js') +const utils_js_1 = require('./utils.js') +const _0n = BigInt(0) +const _1n = BigInt(1) +function constTimeNegate(condition, item) { + const neg = item.negate() + return condition ? neg : item +} +function validateW(W, bits) { + if (!Number.isSafeInteger(W) || W <= 0 || W > bits) + throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) +} +function calcWOpts(W, bits) { + validateW(W, bits) + const windows = Math.ceil(bits / W) + 1 // +1, because + const windowSize = 2 ** (W - 1) // -1 because we skip zero + return { windows, windowSize } +} +function validateMSMPoints(points, c) { + if (!Array.isArray(points)) throw new Error('array expected') + points.forEach((p, i) => { + if (!(p instanceof c)) throw new Error('invalid point at index ' + i) + }) +} +function validateMSMScalars(scalars, field) { + if (!Array.isArray(scalars)) throw new Error('array of scalars expected') + scalars.forEach((s, i) => { + if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) + }) +} +// Since points in different groups cannot be equal (different object constructor), +// we can have single place to store precomputes +const pointPrecomputes = new WeakMap() +const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) +function getW(P) { + return pointWindowSizes.get(P) || 1 +} +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +function wNAF(c, bits) { + return { + constTimeNegate, + hasPrecomputes(elm) { + return getW(elm) !== 1 + }, + // non-const time multiplication ladder + unsafeLadder(elm, n, p = c.ZERO) { + let d = elm + while (n > _0n) { + if (n & _1n) p = p.add(d) + d = d.double() + n >>= _1n + } + return p + }, + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param elm Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(elm, W) { + const { windows, windowSize } = calcWOpts(W, bits) + const points = [] + let p = elm + let base = p + for (let window = 0; window < windows; window++) { + base = p + points.push(base) + // =1, because we skip zero + for (let i = 1; i < windowSize; i++) { + base = base.add(p) + points.push(base) + } + p = base.double() + } + return points + }, + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @returns real and fake (for const-time) points + */ + wNAF(W, precomputes, n) { + // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise + // But need to carefully remove other checks before wNAF. ORDER == bits here + const { windows, windowSize } = calcWOpts(W, bits) + let p = c.ZERO + let f = c.BASE + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + // Extract W bits. + let wbits = Number(n & mask) + // Shift number by W bits. + n >>= shiftBy + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + // This code was first written with assumption that 'f' and 'p' will never be infinity point: + // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, + // there is negate now: it is possible that negated element from low value + // would be the same as high element, which will create carry into next window. + // It's not obvious how this can fail, but still worth investigating later. + // Check if we're onto Zero point. + // Add random point inside current window to f. + const offset1 = offset + const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero + const cond1 = window % 2 !== 0 + const cond2 = wbits < 0 + if (wbits === 0) { + // The most important part for const-time getPublicKey + f = f.add(constTimeNegate(cond1, precomputes[offset1])) + } else { + p = p.add(constTimeNegate(cond2, precomputes[offset2])) + } + } + // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() + // Even if the variable is still unused, there are some checks which will + // throw an exception, so compiler needs to prove they won't happen, which is hard. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. + return { p, f } + }, + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(W, precomputes, n, acc = c.ZERO) { + const { windows, windowSize } = calcWOpts(W, bits) + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + if (n === _0n) break // No need to go over empty scalar + // Extract W bits. + let wbits = Number(n & mask) + // Shift number by W bits. + n >>= shiftBy + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + if (wbits === 0) continue + let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero + if (wbits < 0) curr = curr.negate() + // NOTE: by re-using acc, we can save a lot of additions in case of MSM + acc = acc.add(curr) + } + return acc + }, + getPrecomputes(W, P, transform) { + // Calculate precomputes on a first run, reuse them after + let comp = pointPrecomputes.get(P) + if (!comp) { + comp = this.precomputeWindow(P, W) + if (W !== 1) pointPrecomputes.set(P, transform(comp)) + } + return comp + }, + wNAFCached(P, n, transform) { + const W = getW(P) + return this.wNAF(W, this.getPrecomputes(W, P, transform), n) + }, + wNAFCachedUnsafe(P, n, transform, prev) { + const W = getW(P) + if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster + return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) + }, + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + setWindowSize(P, W) { + validateW(W, bits) + pointWindowSizes.set(P, W) + pointPrecomputes.delete(P) + }, + } +} +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster with precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +function pippenger(c, fieldN, points, scalars) { + // If we split scalars by some window (let's say 8 bits), every chunk will only + // take 256 buckets even if there are 4096 scalars, also re-uses double. + // TODO: + // - https://eprint.iacr.org/2024/750.pdf + // - https://tches.iacr.org/index.php/TCHES/article/view/10287 + // 0 is accepted in scalars + validateMSMPoints(points, c) + validateMSMScalars(scalars, fieldN) + if (points.length !== scalars.length) + throw new Error('arrays of points and scalars must have equal length') + const zero = c.ZERO + const wbits = (0, utils_js_1.bitLen)(BigInt(points.length)) + const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits + const MASK = (1 << windowSize) - 1 + const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array + const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize + let sum = zero + for (let i = lastBits; i >= 0; i -= windowSize) { + buckets.fill(zero) + for (let j = 0; j < scalars.length; j++) { + const scalar = scalars[j] + const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) + buckets[wbits] = buckets[wbits].add(points[j]) + } + let resI = zero // not using this will do small speed-up, but will lose ct + // Skip first bucket, because it is zero + for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { + sumI = sumI.add(buckets[j]) + resI = resI.add(sumI) + } + sum = sum.add(resI) + if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() + } + return sum +} +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +function precomputeMSMUnsafe(c, fieldN, points, windowSize) { + /** + * Performance Analysis of Window-based Precomputation + * + * Base Case (256-bit scalar, 8-bit window): + * - Standard precomputation requires: + * - 31 additions per scalar × 256 scalars = 7,936 ops + * - Plus 255 summary additions = 8,191 total ops + * Note: Summary additions can be optimized via accumulator + * + * Chunked Precomputation Analysis: + * - Using 32 chunks requires: + * - 255 additions per chunk + * - 256 doublings + * - Total: (255 × 32) + 256 = 8,416 ops + * + * Memory Usage Comparison: + * Window Size | Standard Points | Chunked Points + * ------------|-----------------|--------------- + * 4-bit | 520 | 15 + * 8-bit | 4,224 | 255 + * 10-bit | 13,824 | 1,023 + * 16-bit | 557,056 | 65,535 + * + * Key Advantages: + * 1. Enables larger window sizes due to reduced memory overhead + * 2. More efficient for smaller scalar counts: + * - 16 chunks: (16 × 255) + 256 = 4,336 ops + * - ~2x faster than standard 8,191 ops + * + * Limitations: + * - Not suitable for plain precomputes (requires 256 constant doublings) + * - Performance degrades with larger scalar counts: + * - Optimal for ~256 scalars + * - Less efficient for 4096+ scalars (Pippenger preferred) + */ + validateW(windowSize, fieldN.BITS) + validateMSMPoints(points, c) + const zero = c.ZERO + const tableSize = 2 ** windowSize - 1 // table size (without zero) + const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item + const MASK = BigInt((1 << windowSize) - 1) + const tables = points.map((p) => { + const res = [] + for (let i = 0, acc = p; i < tableSize; i++) { + res.push(acc) + acc = acc.add(p) + } + return res + }) + return (scalars) => { + validateMSMScalars(scalars, fieldN) + if (scalars.length > points.length) + throw new Error('array of scalars must be smaller than array of points') + let res = zero + for (let i = 0; i < chunks; i++) { + // No need to double if accumulator is still zero. + if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() + const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) + for (let j = 0; j < scalars.length; j++) { + const n = scalars[j] + const curr = Number((n >> shiftBy) & MASK) + if (!curr) continue // skip zero scalars chunks + res = res.add(tables[j][curr - 1]) + } + } + return res + } +} +function validateBasic(curve) { + ;(0, modular_js_1.validateField)(curve.Fp) + ;(0, utils_js_1.validateObject)( + curve, + { + n: 'bigint', + h: 'bigint', + Gx: 'field', + Gy: 'field', + }, + { + nBitLength: 'isSafeInteger', + nByteLength: 'isSafeInteger', + }, + ) + // Set defaults + return Object.freeze({ + ...(0, modular_js_1.nLength)(curve.n, curve.nBitLength), + ...curve, + ...{ p: curve.Fp.ORDER }, + }) +} +//# sourceMappingURL=curve.js.map diff --git a/packages/noble-curves/abstract/curve.js.map b/packages/noble-curves/abstract/curve.js.map new file mode 100644 index 00000000000..1fe22d973a2 --- /dev/null +++ b/packages/noble-curves/abstract/curve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"curve.js","sourceRoot":"","sources":["../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/edwards.d.ts b/packages/noble-curves/abstract/edwards.d.ts new file mode 100644 index 00000000000..cfd6867cfb1 --- /dev/null +++ b/packages/noble-curves/abstract/edwards.d.ts @@ -0,0 +1,106 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' +import { type FHash, type Hex } from './utils.js' +/** Edwards curves must declare params a & d. */ +export type CurveType = BasicCurve & { + a: bigint + d: bigint + hash: FHash + randomBytes: (bytesLength?: number) => Uint8Array + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + uvRatio?: ( + u: bigint, + v: bigint, + ) => { + isValid: boolean + value: bigint + } + prehash?: FHash + mapToCurve?: (scalar: bigint[]) => AffinePoint +} +export type CurveTypeWithLength = Readonly< + CurveType & { + nByteLength: number + nBitLength: number + } +> +declare function validateOpts(curve: CurveType): CurveTypeWithLength +/** Instance of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointType extends Group { + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + get x(): bigint + get y(): bigint + assertValidity(): void + multiply(scalar: bigint): ExtPointType + multiplyUnsafe(scalar: bigint): ExtPointType + isSmallOrder(): boolean + isTorsionFree(): boolean + clearCofactor(): ExtPointType + toAffine(iz?: bigint): AffinePoint + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + _setWindowSize(windowSize: number): void +} +/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType + fromAffine(p: AffinePoint): ExtPointType + fromHex(hex: Hex): ExtPointType + fromPrivateKey(privateKey: Hex): ExtPointType + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType +} +/** + * Edwards Curve interface. + * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. + */ +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: Hex) => Uint8Array + sign: ( + message: Hex, + privateKey: Hex, + options?: { + context?: Hex + }, + ) => Uint8Array + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { + context?: Hex + zip215: boolean + }, + ) => boolean + ExtendedPoint: ExtPointConstructor + utils: { + randomPrivateKey: () => Uint8Array + getExtendedPublicKey: (key: Hex) => { + head: Uint8Array + prefix: Uint8Array + scalar: bigint + point: ExtPointType + pointBytes: Uint8Array + } + precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType + } +} +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export declare function twistedEdwards(curveDef: CurveType): CurveFn +export {} +//# sourceMappingURL=edwards.d.ts.map diff --git a/packages/noble-curves/abstract/edwards.d.ts.map b/packages/noble-curves/abstract/edwards.d.ts.map new file mode 100644 index 00000000000..48de4faf5b9 --- /dev/null +++ b/packages/noble-curves/abstract/edwards.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"edwards.d.ts","sourceRoot":"","sources":["../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/edwards.js b/packages/noble-curves/abstract/edwards.js new file mode 100644 index 00000000000..bca78b2e482 --- /dev/null +++ b/packages/noble-curves/abstract/edwards.js @@ -0,0 +1,448 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.twistedEdwards = twistedEdwards +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const curve_js_1 = require('./curve.js') +const modular_js_1 = require('./modular.js') +const ut = require('./utils.js') +const utils_js_1 = require('./utils.js') +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _8n = BigInt(8) +// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: +const VERIFY_DEFAULT = { zip215: true } +function validateOpts(curve) { + const opts = (0, curve_js_1.validateBasic)(curve) + ut.validateObject( + curve, + { + hash: 'function', + a: 'bigint', + d: 'bigint', + randomBytes: 'function', + }, + { + adjustScalarBytes: 'function', + domain: 'function', + uvRatio: 'function', + mapToCurve: 'function', + }, + ) + // Set defaults + return Object.freeze({ ...opts }) +} +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +function twistedEdwards(curveDef) { + const CURVE = validateOpts(curveDef) + const { + Fp, + n: CURVE_ORDER, + prehash: prehash, + hash: cHash, + randomBytes, + nByteLength, + h: cofactor, + } = CURVE + // Important: + // There are some places where Fp.BYTES is used instead of nByteLength. + // So far, everything has been tested with curves of Fp.BYTES == nByteLength. + // TODO: test and find curves which behave otherwise. + const MASK = _2n << (BigInt(nByteLength * 8) - _1n) + const modP = Fp.create // Function overrides + const Fn = (0, modular_js_1.Field)(CURVE.n, CURVE.nBitLength) + // sqrt(u/v) + const uvRatio = + CURVE.uvRatio || + ((u, v) => { + try { + return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } + } catch (e) { + return { isValid: false, value: _0n } + } + }) + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) // NOOP + const domain = + CURVE.domain || + ((data, ctx, phflag) => { + ;(0, utils_js_1.abool)('phflag', phflag) + if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') + return data + }) // NOOP + // 0 <= n < MASK + // Coordinates larger than Fp.ORDER are allowed for zip215 + function aCoordinate(title, n) { + ut.aInRange('coordinate ' + title, n, _0n, MASK) + } + function assertPoint(other) { + if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + const toAffineMemo = (0, utils_js_1.memoized)((p, iz) => { + const { ex: x, ey: y, ez: z } = p + const is0 = p.is0() + if (iz == null) iz = is0 ? _8n : Fp.inv(z) // 8 was chosen arbitrarily + const ax = modP(x * iz) + const ay = modP(y * iz) + const zz = modP(z * iz) + if (is0) return { x: _0n, y: _1n } + if (zz !== _1n) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + const assertValidMemo = (0, utils_js_1.memoized)((p) => { + const { a, d } = CURVE + if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? + // Equation in affine coordinates: ax² + y² = 1 + dx²y² + // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² + const { ex: X, ey: Y, ez: Z, et: T } = p + const X2 = modP(X * X) // X² + const Y2 = modP(Y * Y) // Y² + const Z2 = modP(Z * Z) // Z² + const Z4 = modP(Z2 * Z2) // Z⁴ + const aX2 = modP(X2 * a) // aX² + const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² + const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² + if (left !== right) throw new Error('bad point: equation left != right (1)') + // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T + const XY = modP(X * Y) + const ZT = modP(Z * T) + if (XY !== ZT) throw new Error('bad point: equation left != right (2)') + return true + }) + // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). + // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates + class Point { + constructor(ex, ey, ez, et) { + this.ex = ex + this.ey = ey + this.ez = ez + this.et = et + aCoordinate('x', ex) + aCoordinate('y', ey) + aCoordinate('z', ez) + aCoordinate('t', et) + Object.freeze(this) + } + get x() { + return this.toAffine().x + } + get y() { + return this.toAffine().y + } + static fromAffine(p) { + if (p instanceof Point) throw new Error('extended point not allowed') + const { x, y } = p || {} + aCoordinate('x', x) + aCoordinate('y', y) + return new Point(x, y, _1n, modP(x * y)) + } + static normalizeZ(points) { + const toInv = Fp.invertBatch(points.map((p) => p.ez)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + // Multiscalar Multiplication + static msm(points, scalars) { + return (0, curve_js_1.pippenger)(Point, Fn, points, scalars) + } + // "Private method", don't use it directly + _setWindowSize(windowSize) { + wnaf.setWindowSize(this, windowSize) + } + // Not required for fromHex(), which always creates valid points. + // Could be useful for fromAffine(). + assertValidity() { + assertValidMemo(this) + } + // Compare one point to another. + equals(other) { + assertPoint(other) + const { ex: X1, ey: Y1, ez: Z1 } = this + const { ex: X2, ey: Y2, ez: Z2 } = other + const X1Z2 = modP(X1 * Z2) + const X2Z1 = modP(X2 * Z1) + const Y1Z2 = modP(Y1 * Z2) + const Y2Z1 = modP(Y2 * Z1) + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 + } + is0() { + return this.equals(Point.ZERO) + } + negate() { + // Flips point sign to a negative one (-x, y in affine coords) + return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) + } + // Fast algo for doubling Extended Point. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd + // Cost: 4M + 4S + 1*a + 6add + 1*2. + double() { + const { a } = CURVE + const { ex: X1, ey: Y1, ez: Z1 } = this + const A = modP(X1 * X1) // A = X12 + const B = modP(Y1 * Y1) // B = Y12 + const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 + const D = modP(a * A) // D = a*A + const x1y1 = X1 + Y1 + const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B + const G = D + B // G = D+B + const F = G - C // F = G-C + const H = D - B // H = D-B + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + // Fast algo for adding 2 Extended Points. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd + // Cost: 9M + 1*a + 1*d + 7add. + add(other) { + assertPoint(other) + const { a, d } = CURVE + const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this + const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other + // Faster algo for adding 2 Extended Points when curve's a=-1. + // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 + // Cost: 8M + 8add + 2*2. + // Note: It does not check whether the `other` point is valid. + if (a === BigInt(-1)) { + const A = modP((Y1 - X1) * (Y2 + X2)) + const B = modP((Y1 + X1) * (Y2 - X2)) + const F = modP(B - A) + if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing + const C = modP(Z1 * _2n * T2) + const D = modP(T1 * _2n * Z2) + const E = D + C + const G = B + A + const H = D - C + const X3 = modP(E * F) + const Y3 = modP(G * H) + const T3 = modP(E * H) + const Z3 = modP(F * G) + return new Point(X3, Y3, Z3, T3) + } + const A = modP(X1 * X2) // A = X1*X2 + const B = modP(Y1 * Y2) // B = Y1*Y2 + const C = modP(T1 * d * T2) // C = T1*d*T2 + const D = modP(Z1 * Z2) // D = Z1*Z2 + const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B + const F = D - C // F = D-C + const G = D + C // G = D+C + const H = modP(B - a * A) // H = B-a*A + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + subtract(other) { + return this.add(other.negate()) + } + wNAF(n) { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + // Constant-time multiplication. + multiply(scalar) { + const n = scalar + ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L + const { p, f } = this.wNAF(n) + return Point.normalizeZ([p, f])[0] + } + // Non-constant-time multiplication. Uses double-and-add algorithm. + // It's faster, but should only be used when you don't care about + // an exposed private key e.g. sig verification. + // Does NOT allow scalars higher than CURVE.n. + // Accepts optional accumulator to merge with multiply (important for sparse scalars) + multiplyUnsafe(scalar, acc = Point.ZERO) { + const n = scalar + ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L + if (n === _0n) return I + if (this.is0() || n === _1n) return this + return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) + } + // Checks if point is of small order. + // If you add something to small order point, you will have "dirty" + // point with torsion component. + // Multiplies point by cofactor and checks if the result is 0. + isSmallOrder() { + return this.multiplyUnsafe(cofactor).is0() + } + // Multiplies point by curve order and checks if the result is 0. + // Returns `false` is the point is dirty. + isTorsionFree() { + return wnaf.unsafeLadder(this, CURVE_ORDER).is0() + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + toAffine(iz) { + return toAffineMemo(this, iz) + } + clearCofactor() { + const { h: cofactor } = CURVE + if (cofactor === _1n) return this + return this.multiplyUnsafe(cofactor) + } + // Converts hash string or Uint8Array to Point. + // Uses algo from RFC8032 5.1.3. + static fromHex(hex, zip215 = false) { + const { d, a } = CURVE + const len = Fp.BYTES + hex = (0, utils_js_1.ensureBytes)('pointHex', hex, len) // copy hex to a new array + ;(0, utils_js_1.abool)('zip215', zip215) + const normed = hex.slice() // copy again, we'll manipulate it + const lastByte = hex[len - 1] // select last byte + normed[len - 1] = lastByte & ~0x80 // clear last bit + const y = ut.bytesToNumberLE(normed) + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // RFC8032 prohibits >= p, but ZIP215 doesn't + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + const max = zip215 ? MASK : Fp.ORDER + ut.aInRange('pointHex.y', y, _0n, max) + // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: + // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) + const y2 = modP(y * y) // denominator is always non-0 mod p. + const u = modP(y2 - _1n) // u = y² - 1 + const v = modP(d * y2 - a) // v = d y² + 1. + let { isValid, value: x } = uvRatio(u, v) // √(u/v) + if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') + const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper + const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1') + if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x + return Point.fromAffine({ x, y }) + } + static fromPrivateKey(privKey) { + return getExtendedPublicKey(privKey).point + } + toRawBytes() { + const { x, y } = this.toAffine() + const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) + bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y + return bytes // and use the last byte to encode sign of x + } + toHex() { + return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. + } + } + Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) + Point.ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 + const { BASE: G, ZERO: I } = Point + const wnaf = (0, curve_js_1.wNAF)(Point, nByteLength * 8) + function modN(a) { + return (0, modular_js_1.mod)(a, CURVE_ORDER) + } + // Little-endian SHA512 with modulo n + function modN_LE(hash) { + return modN(ut.bytesToNumberLE(hash)) + } + /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ + function getExtendedPublicKey(key) { + const len = Fp.BYTES + key = (0, utils_js_1.ensureBytes)('private key', key, len) + // Hash private key with curve's hash function to produce uniformingly random input + // Check byte lengths: ensure(64, h(ensure(32, key))) + const hashed = (0, utils_js_1.ensureBytes)('hashed private key', cHash(key), 2 * len) + const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE + const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) + const scalar = modN_LE(head) // The actual private scalar + const point = G.multiply(scalar) // Point on Edwards curve aka public key + const pointBytes = point.toRawBytes() // Uint8Array representation + return { head, prefix, scalar, point, pointBytes } + } + // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared + function getPublicKey(privKey) { + return getExtendedPublicKey(privKey).pointBytes + } + // int('LE', SHA512(dom2(F, C) || msgs)) mod N + function hashDomainToScalar(context = new Uint8Array(), ...msgs) { + const msg = ut.concatBytes(...msgs) + return modN_LE(cHash(domain(msg, (0, utils_js_1.ensureBytes)('context', context), !!prehash))) + } + /** Signs message with privateKey. RFC8032 5.1.6 */ + function sign(msg, privKey, options = {}) { + msg = (0, utils_js_1.ensureBytes)('message', msg) + if (prehash) msg = prehash(msg) // for ed25519ph etc. + const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) + const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) + const R = G.multiply(r).toRawBytes() // R = rG + const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) + const s = modN(r + k * scalar) // S = (r + k * s) mod L + ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l + const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) + return (0, utils_js_1.ensureBytes)('result', res, Fp.BYTES * 2) // 64-byte signature + } + const verifyOpts = VERIFY_DEFAULT + /** + * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + * An extended group equation is checked. + */ + function verify(sig, msg, publicKey, options = verifyOpts) { + const { context, zip215 } = options + const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + sig = (0, utils_js_1.ensureBytes)('signature', sig, 2 * len) // An extended group equation is checked. + msg = (0, utils_js_1.ensureBytes)('message', msg) + publicKey = (0, utils_js_1.ensureBytes)('publicKey', publicKey, len) + if (zip215 !== undefined) (0, utils_js_1.abool)('zip215', zip215) + if (prehash) msg = prehash(msg) // for ed25519ph, etc + const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) + let A, R, SB + try { + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + A = Point.fromHex(publicKey, zip215) + R = Point.fromHex(sig.slice(0, len), zip215) + SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside + } catch (error) { + return false + } + if (!zip215 && A.isSmallOrder()) return false + const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) + const RkA = R.add(A.multiplyUnsafe(k)) + // Extended group equation + // [8][S]B = [8]R + [8][k]A' + return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) + } + G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. + const utils = { + getExtendedPublicKey, + // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. + randomPrivateKey: () => randomBytes(Fp.BYTES), + /** + * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT + * values. This slows down first getPublicKey() by milliseconds (see Speed section), + * but allows to speed-up subsequent getPublicKey() calls up to 20x. + * @param windowSize 2, 4, 8, 16 + */ + precompute(windowSize = 8, point = Point.BASE) { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) + return point + }, + } + return { + CURVE, + getPublicKey, + sign, + verify, + ExtendedPoint: Point, + utils, + } +} +//# sourceMappingURL=edwards.js.map diff --git a/packages/noble-curves/abstract/edwards.js.map b/packages/noble-curves/abstract/edwards.js.map new file mode 100644 index 00000000000..91e38bbf020 --- /dev/null +++ b/packages/noble-curves/abstract/edwards.js.map @@ -0,0 +1 @@ +{"version":3,"file":"edwards.js","sourceRoot":"","sources":["../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/hash-to-curve.d.ts b/packages/noble-curves/abstract/hash-to-curve.d.ts new file mode 100644 index 00000000000..646647f9280 --- /dev/null +++ b/packages/noble-curves/abstract/hash-to-curve.d.ts @@ -0,0 +1,99 @@ +/** + * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import type { AffinePoint, Group, GroupConstructor } from './curve.js' +import { type IField } from './modular.js' +import type { CHash } from './utils.js' +export type UnicodeOrBytes = string | Uint8Array +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +export type Opts = { + DST: UnicodeOrBytes + p: bigint + m: number + k: number + expand: 'xmd' | 'xof' + hash: CHash +} +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export declare function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash, +): Uint8Array +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export declare function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash, +): Uint8Array +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export declare function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] +export type XY = ( + x: T, + y: T, +) => { + x: T + y: T +} +export declare function isogenyMap>( + field: F, + map: [T[], T[], T[], T[]], +): XY +/** Point interface, which curves must implement to work correctly with the module. */ +export interface H2CPoint extends Group> { + add(rhs: H2CPoint): H2CPoint + toAffine(iz?: bigint): AffinePoint + clearCofactor(): H2CPoint + assertValidity(): void +} +export interface H2CPointConstructor extends GroupConstructor> { + fromAffine(ap: AffinePoint): H2CPoint +} +export type MapToCurve = (scalar: bigint[]) => AffinePoint +export type htfBasicOpts = { + DST: UnicodeOrBytes +} +export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint +export type MapMethod = (scalars: bigint[]) => H2CPoint +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export declare function createHasher( + Point: H2CPointConstructor, + mapToCurve: MapToCurve, + def: Opts & { + encodeDST?: UnicodeOrBytes + }, +): { + hashToCurve: HTFMethod + encodeToCurve: HTFMethod + mapToCurve: MapMethod +} +//# sourceMappingURL=hash-to-curve.d.ts.map diff --git a/packages/noble-curves/abstract/hash-to-curve.d.ts.map b/packages/noble-curves/abstract/hash-to-curve.d.ts.map new file mode 100644 index 00000000000..cd7dda14a2d --- /dev/null +++ b/packages/noble-curves/abstract/hash-to-curve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-to-curve.d.ts","sourceRoot":"","sources":["../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/hash-to-curve.js b/packages/noble-curves/abstract/hash-to-curve.js new file mode 100644 index 00000000000..8e48fcffc8a --- /dev/null +++ b/packages/noble-curves/abstract/hash-to-curve.js @@ -0,0 +1,184 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.expand_message_xmd = expand_message_xmd +exports.expand_message_xof = expand_message_xof +exports.hash_to_field = hash_to_field +exports.isogenyMap = isogenyMap +exports.createHasher = createHasher +const modular_js_1 = require('./modular.js') +const utils_js_1 = require('./utils.js') +// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. +const os2ip = utils_js_1.bytesToNumberBE +// Integer to Octet Stream (numberToBytesBE) +function i2osp(value, length) { + anum(value) + anum(length) + if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) + 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 +} +function anum(item) { + if (!Number.isSafeInteger(item)) throw new Error('number expected') +} +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +function expand_message_xmd(msg, DST, lenInBytes, H) { + ;(0, utils_js_1.abytes)(msg) + ;(0, utils_js_1.abytes)(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + if (DST.length > 255) + DST = H((0, utils_js_1.concatBytes)((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-'), DST)) + const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H + const ell = Math.ceil(lenInBytes / b_in_bytes) + if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') + const DST_prime = (0, utils_js_1.concatBytes)(DST, i2osp(DST.length, 1)) + const Z_pad = i2osp(0, r_in_bytes) + const l_i_b_str = i2osp(lenInBytes, 2) // len_in_bytes_str + const b = new Array(ell) + const b_0 = H((0, utils_js_1.concatBytes)(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) + b[0] = H((0, utils_js_1.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] = H((0, utils_js_1.concatBytes)(...args)) + } + const pseudo_random_bytes = (0, utils_js_1.concatBytes)(...b) + return pseudo_random_bytes.slice(0, lenInBytes) +} +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +function expand_message_xof(msg, DST, lenInBytes, k, H) { + ;(0, utils_js_1.abytes)(msg) + ;(0, utils_js_1.abytes)(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); + if (DST.length > 255) { + const dkLen = Math.ceil((2 * k) / 8) + DST = H.create({ dkLen }) + .update((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-')) + .update(DST) + .digest() + } + if (lenInBytes > 65535 || DST.length > 255) + throw new Error('expand_message_xof: invalid lenInBytes') + return ( + H.create({ dkLen: lenInBytes }) + .update(msg) + .update(i2osp(lenInBytes, 2)) + // 2. DST_prime = DST || I2OSP(len(DST), 1) + .update(DST) + .update(i2osp(DST.length, 1)) + .digest() + ) +} +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +function hash_to_field(msg, count, options) { + ;(0, utils_js_1.validateObject)(options, { + DST: 'stringOrUint8Array', + p: 'bigint', + m: 'isSafeInteger', + k: 'isSafeInteger', + hash: 'hash', + }) + const { p, k, m, hash, expand, DST: _DST } = options + ;(0, utils_js_1.abytes)(msg) + anum(count) + const DST = typeof _DST === 'string' ? (0, utils_js_1.utf8ToBytes)(_DST) : _DST + const log2p = p.toString(2).length + const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above + const len_in_bytes = count * m * L + let prb // pseudo_random_bytes + if (expand === 'xmd') { + prb = expand_message_xmd(msg, DST, len_in_bytes, hash) + } else if (expand === 'xof') { + prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) + } else if (expand === '_internal_pass') { + // for internal tests only + prb = msg + } else { + throw new Error('expand must be "xmd" or "xof"') + } + const u = new Array(count) + for (let i = 0; i < count; i++) { + const e = new Array(m) + for (let j = 0; j < m; j++) { + const elm_offset = L * (j + i * m) + const tv = prb.subarray(elm_offset, elm_offset + L) + e[j] = (0, modular_js_1.mod)(os2ip(tv), p) + } + u[i] = e + } + return u +} +function isogenyMap(field, map) { + // Make same order as in spec + const COEFF = map.map((i) => Array.from(i).reverse()) + return (x, y) => { + const [xNum, xDen, yNum, yDen] = COEFF.map((val) => + val.reduce((acc, i) => field.add(field.mul(acc, x), i)), + ) + x = field.div(xNum, xDen) // xNum / xDen + y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) + return { x: x, y: y } + } +} +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +function createHasher(Point, mapToCurve, def) { + if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') + return { + // Encodes byte string to elliptic curve. + // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + hashToCurve(msg, options) { + const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options }) + const u0 = Point.fromAffine(mapToCurve(u[0])) + const u1 = Point.fromAffine(mapToCurve(u[1])) + const P = u0.add(u1).clearCofactor() + P.assertValidity() + return P + }, + // Encodes byte string to elliptic curve. + // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + encodeToCurve(msg, options) { + const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options }) + const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() + P.assertValidity() + return P + }, + // Same as encodeToCurve, but without hash + mapToCurve(scalars) { + if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') + for (const i of scalars) + if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') + const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() + P.assertValidity() + return P + }, + } +} +//# sourceMappingURL=hash-to-curve.js.map diff --git a/packages/noble-curves/abstract/hash-to-curve.js.map b/packages/noble-curves/abstract/hash-to-curve.js.map new file mode 100644 index 00000000000..e005e9630da --- /dev/null +++ b/packages/noble-curves/abstract/hash-to-curve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-to-curve.js","sourceRoot":"","sources":["../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/modular.d.ts b/packages/noble-curves/abstract/modular.d.ts new file mode 100644 index 00000000000..c95a932142e --- /dev/null +++ b/packages/noble-curves/abstract/modular.d.ts @@ -0,0 +1,168 @@ +export declare function mod(a: bigint, b: bigint): bigint +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export declare function invert(number: bigint, modulo: bigint): bigint +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export declare function tonelliShanks(P: bigint): (Fp: IField, n: T) => T +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export declare function FpSqrt(P: bigint): (Fp: IField, n: T) => T +export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean +/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ +export interface IField { + ORDER: bigint + isLE: boolean + BYTES: number + BITS: number + MASK: bigint + ZERO: T + ONE: T + create: (num: T) => T + isValid: (num: T) => boolean + is0: (num: T) => boolean + neg(num: T): T + inv(num: T): T + sqrt(num: T): T + sqr(num: T): T + eql(lhs: T, rhs: T): boolean + add(lhs: T, rhs: T): T + sub(lhs: T, rhs: T): T + mul(lhs: T, rhs: T | bigint): T + pow(lhs: T, power: bigint): T + div(lhs: T, rhs: T | bigint): T + addN(lhs: T, rhs: T): T + subN(lhs: T, rhs: T): T + mulN(lhs: T, rhs: T | bigint): T + sqrN(num: T): T + isOdd?(num: T): boolean + pow(lhs: T, power: bigint): T + invertBatch: (lst: T[]) => T[] + toBytes(num: T): Uint8Array + fromBytes(bytes: Uint8Array): T + cmov(a: T, b: T, c: boolean): T +} +export declare function validateField(field: IField): IField +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export declare function FpPow(f: IField, num: T, power: bigint): T +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export declare function FpInvertBatch(f: IField, nums: T[]): T[] +export declare function FpDiv(f: IField, lhs: T, rhs: T | bigint): T +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export declare function FpLegendre(order: bigint): (f: IField, x: T) => T +export declare function FpIsSquare(f: IField): (x: T) => boolean +export declare function nLength( + n: bigint, + nBitLength?: number, +): { + nBitLength: number + nByteLength: number +} +type FpField = IField & Required, 'isOdd'>> +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export declare function Field( + ORDER: bigint, + bitLen?: number, + isLE?: boolean, + redef?: Partial>, +): Readonly +export declare function FpSqrtOdd(Fp: IField, elm: T): T +export declare function FpSqrtEven(Fp: IField, elm: T): T +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export declare function hashToPrivateScalar( + hash: string | Uint8Array, + groupOrder: bigint, + isLE?: boolean, +): bigint +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export declare function getFieldBytesLength(fieldOrder: bigint): number +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export declare function getMinHashLength(fieldOrder: bigint): number +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export declare function mapHashToField( + key: Uint8Array, + fieldOrder: bigint, + isLE?: boolean, +): Uint8Array +export {} +//# sourceMappingURL=modular.d.ts.map diff --git a/packages/noble-curves/abstract/modular.d.ts.map b/packages/noble-curves/abstract/modular.d.ts.map new file mode 100644 index 00000000000..d1a5311a14a --- /dev/null +++ b/packages/noble-curves/abstract/modular.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"modular.d.ts","sourceRoot":"","sources":["../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/modular.js b/packages/noble-curves/abstract/modular.js new file mode 100644 index 00000000000..9f63624e1e7 --- /dev/null +++ b/packages/noble-curves/abstract/modular.js @@ -0,0 +1,485 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.isNegativeLE = void 0 +exports.mod = mod +exports.pow = pow +exports.pow2 = pow2 +exports.invert = invert +exports.tonelliShanks = tonelliShanks +exports.FpSqrt = FpSqrt +exports.validateField = validateField +exports.FpPow = FpPow +exports.FpInvertBatch = FpInvertBatch +exports.FpDiv = FpDiv +exports.FpLegendre = FpLegendre +exports.FpIsSquare = FpIsSquare +exports.nLength = nLength +exports.Field = Field +exports.FpSqrtOdd = FpSqrtOdd +exports.FpSqrtEven = FpSqrtEven +exports.hashToPrivateScalar = hashToPrivateScalar +exports.getFieldBytesLength = getFieldBytesLength +exports.getMinHashLength = getMinHashLength +exports.mapHashToField = mapHashToField +/** + * Utils for modular division and finite fields. + * A finite field over 11 is integer number operations `mod 11`. + * There is no division: it is replaced by modular multiplicative inverse. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const utils_js_1 = require('./utils.js') +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = /* @__PURE__ */ BigInt(2), + _3n = /* @__PURE__ */ BigInt(3) +// prettier-ignore +const _4n = /* @__PURE__ */ BigInt(4), + _5n = /* @__PURE__ */ BigInt(5), + _8n = /* @__PURE__ */ BigInt(8) +// prettier-ignore +const _9n = /* @__PURE__ */ BigInt(9), + _16n = /* @__PURE__ */ BigInt(16) +// Calculates a modulo b +function mod(a, b) { + const result = a % b + return result >= _0n ? result : b + result +} +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +function pow(num, power, modulo) { + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (modulo <= _0n) throw new Error('invalid modulus') + 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 +} +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +function pow2(x, power, modulo) { + let res = x + while (power-- > _0n) { + res *= res + res %= modulo + } + return res +} +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +function invert(number, modulo) { + if (number === _0n) throw new Error('invert: expected non-zero number') + if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) + // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. + let a = mod(number, modulo) + let b = modulo + // prettier-ignore + let x = _0n, + y = _1n, + u = _1n, + v = _0n + while (a !== _0n) { + // JIT applies optimization if those two lines follow each other + const q = b / a + const r = b % a + const m = x - u * q + const n = y - v * q + // prettier-ignore + ;(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) +} +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +function tonelliShanks(P) { + // Legendre constant: used to calculate Legendre symbol (a | p), + // which denotes the value of a^((p-1)/2) (mod p). + // (a | p) ≡ 1 if a is a square (mod p) + // (a | p) ≡ -1 if a is not a square (mod p) + // (a | p) ≡ 0 if a ≡ 0 (mod p) + const legendreC = (P - _1n) / _2n + let Q, S, Z + // Step 1: By factoring out powers of 2 from p - 1, + // find q and s such that p - 1 = q*(2^s) with q odd + for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); + // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq + for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { + // Crash instead of infinity loop, we cannot reasonable count until P. + if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') + } + // Fast-path + if (S === 1) { + const p1div4 = (P + _1n) / _4n + return function tonelliFast(Fp, n) { + const root = Fp.pow(n, p1div4) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // Slow-path + const Q1div2 = (Q + _1n) / _2n + return function tonelliSlow(Fp, n) { + // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 + if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') + let r = S + // TODO: will fail at Fp2/etc + let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b + let x = Fp.pow(n, Q1div2) // first guess at the square root + let b = Fp.pow(n, Q) // first guess at the fudge factor + while (!Fp.eql(b, Fp.ONE)) { + if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) + // Find m such b^(2^m)==1 + let m = 1 + for (let t2 = Fp.sqr(b); m < r; m++) { + if (Fp.eql(t2, Fp.ONE)) break + t2 = Fp.sqr(t2) // t2 *= t2 + } + // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow + const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) + g = Fp.sqr(ge) // g = ge * ge + x = Fp.mul(x, ge) // x *= ge + b = Fp.mul(b, g) // b *= g + r = m + } + return x + } +} +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +function FpSqrt(P) { + // P ≡ 3 (mod 4) + // √n = n^((P+1)/4) + if (P % _4n === _3n) { + // Not all roots possible! + // const ORDER = + // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; + // const NUM = 72057594037927816n; + const p1div4 = (P + _1n) / _4n + return function sqrt3mod4(Fp, n) { + const root = Fp.pow(n, p1div4) + // Throw if root**2 != n + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) + if (P % _8n === _5n) { + const c1 = (P - _5n) / _8n + return function sqrt5mod8(Fp, n) { + const n2 = Fp.mul(n, _2n) + const v = Fp.pow(n2, c1) + const nv = Fp.mul(n, v) + const i = Fp.mul(Fp.mul(nv, _2n), v) + const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // P ≡ 9 (mod 16) + if (P % _16n === _9n) { + // NOTE: tonelli is too slow for bls-Fp2 calculations even on start + // Means we cannot use sqrt for constants at all! + // + // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F + // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F + // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F + // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic + // sqrt = (x) => { + // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 + // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 + // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 + // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 + // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x + // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x + // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x + // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x + // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x + // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 + // } + } + // Other cases: Tonelli-Shanks algorithm + return tonelliShanks(P) +} +// Little-endian check for first LE bit (last BE bit); +const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n +exports.isNegativeLE = isNegativeLE +// prettier-ignore +const FIELD_FIELDS = [ + 'create', + 'isValid', + 'is0', + 'neg', + 'inv', + 'sqrt', + 'sqr', + 'eql', + 'add', + 'sub', + 'mul', + 'pow', + 'div', + 'addN', + 'subN', + 'mulN', + 'sqrN', +] +function validateField(field) { + const initial = { + ORDER: 'bigint', + MASK: 'bigint', + BYTES: 'isSafeInteger', + BITS: 'isSafeInteger', + } + const opts = FIELD_FIELDS.reduce((map, val) => { + map[val] = 'function' + return map + }, initial) + return (0, utils_js_1.validateObject)(field, opts) +} +// Generic field functions +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +function FpPow(f, num, power) { + // Should have same speed as pow for bigints + // TODO: benchmark! + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (power === _0n) return f.ONE + if (power === _1n) return num + let p = f.ONE + let d = num + while (power > _0n) { + if (power & _1n) p = f.mul(p, d) + d = f.sqr(d) + power >>= _1n + } + return p +} +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +function FpInvertBatch(f, nums) { + const tmp = new Array(nums.length) + // Walk from first to last, multiply them by each other MOD p + const lastMultiplied = nums.reduce((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = acc + return f.mul(acc, num) + }, f.ONE) + // Invert last element + const inverted = f.inv(lastMultiplied) + // Walk from last to first, multiply them by inverted each other MOD p + nums.reduceRight((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = f.mul(acc, tmp[i]) + return f.mul(acc, num) + }, inverted) + return tmp +} +function FpDiv(f, lhs, rhs) { + return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) +} +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +function FpLegendre(order) { + const legendreConst = (order - _1n) / _2n // Integer arithmetic + return (f, x) => f.pow(x, legendreConst) +} +// This function returns True whenever the value x is a square in the field F. +function FpIsSquare(f) { + const legendre = FpLegendre(f.ORDER) + return (x) => { + const p = legendre(f, x) + return f.eql(p, f.ZERO) || f.eql(p, f.ONE) + } +} +// CURVE.n lengths +function nLength(n, nBitLength) { + // Bit size, byte size of CURVE.n + const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length + const nByteLength = Math.ceil(_nBitLength / 8) + return { nBitLength: _nBitLength, nByteLength } +} +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +function Field(ORDER, bitLen, isLE = false, redef = {}) { + if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) + const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) + if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') + let sqrtP // cached sqrtP + const f = Object.freeze({ + ORDER, + isLE, + BITS, + BYTES, + MASK: (0, utils_js_1.bitMask)(BITS), + ZERO: _0n, + ONE: _1n, + create: (num) => mod(num, ORDER), + isValid: (num) => { + if (typeof num !== 'bigint') + throw new Error('invalid field element: expected bigint, got ' + typeof num) + return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible + }, + is0: (num) => num === _0n, + isOdd: (num) => (num & _1n) === _1n, + neg: (num) => mod(-num, ORDER), + eql: (lhs, rhs) => lhs === rhs, + sqr: (num) => mod(num * num, ORDER), + add: (lhs, rhs) => mod(lhs + rhs, ORDER), + sub: (lhs, rhs) => mod(lhs - rhs, ORDER), + mul: (lhs, rhs) => mod(lhs * rhs, ORDER), + pow: (num, power) => FpPow(f, num, power), + div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + // Same as above, but doesn't normalize + sqrN: (num) => num * num, + addN: (lhs, rhs) => lhs + rhs, + subN: (lhs, rhs) => lhs - rhs, + mulN: (lhs, rhs) => lhs * rhs, + inv: (num) => invert(num, ORDER), + sqrt: + redef.sqrt || + ((n) => { + if (!sqrtP) sqrtP = FpSqrt(ORDER) + return sqrtP(f, n) + }), + invertBatch: (lst) => FpInvertBatch(f, lst), + // TODO: do we really need constant cmov? + // We don't have const-time bigints anyway, so probably will be not very useful + cmov: (a, b, c) => (c ? b : a), + toBytes: (num) => + isLE + ? (0, utils_js_1.numberToBytesLE)(num, BYTES) + : (0, utils_js_1.numberToBytesBE)(num, BYTES), + fromBytes: (bytes) => { + if (bytes.length !== BYTES) + throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) + return isLE ? (0, utils_js_1.bytesToNumberLE)(bytes) : (0, utils_js_1.bytesToNumberBE)(bytes) + }, + }) + return Object.freeze(f) +} +function FpSqrtOdd(Fp, elm) { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? root : Fp.neg(root) +} +function FpSqrtEven(Fp, elm) { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? Fp.neg(root) : root +} +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +function hashToPrivateScalar(hash, groupOrder, isLE = false) { + hash = (0, utils_js_1.ensureBytes)('privateHash', hash) + const hashLen = hash.length + const minLen = nLength(groupOrder).nByteLength + 8 + if (minLen < 24 || hashLen < minLen || hashLen > 1024) + throw new Error( + 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, + ) + const num = isLE ? (0, utils_js_1.bytesToNumberLE)(hash) : (0, utils_js_1.bytesToNumberBE)(hash) + return mod(num, groupOrder - _1n) + _1n +} +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +function getFieldBytesLength(fieldOrder) { + if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') + const bitLength = fieldOrder.toString(2).length + return Math.ceil(bitLength / 8) +} +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +function getMinHashLength(fieldOrder) { + const length = getFieldBytesLength(fieldOrder) + return length + Math.ceil(length / 2) +} +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +function mapHashToField(key, fieldOrder, isLE = false) { + const len = key.length + const fieldLen = getFieldBytesLength(fieldOrder) + const minLen = getMinHashLength(fieldOrder) + // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. + if (len < 16 || len < minLen || len > 1024) + throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) + const num = isLE ? (0, utils_js_1.bytesToNumberLE)(key) : (0, utils_js_1.bytesToNumberBE)(key) + // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 + const reduced = mod(num, fieldOrder - _1n) + _1n + return isLE + ? (0, utils_js_1.numberToBytesLE)(reduced, fieldLen) + : (0, utils_js_1.numberToBytesBE)(reduced, fieldLen) +} +//# sourceMappingURL=modular.js.map diff --git a/packages/noble-curves/abstract/modular.js.map b/packages/noble-curves/abstract/modular.js.map new file mode 100644 index 00000000000..89e17765c36 --- /dev/null +++ b/packages/noble-curves/abstract/modular.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modular.js","sourceRoot":"","sources":["../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/montgomery.d.ts b/packages/noble-curves/abstract/montgomery.d.ts new file mode 100644 index 00000000000..64a01ea5d1c --- /dev/null +++ b/packages/noble-curves/abstract/montgomery.d.ts @@ -0,0 +1,26 @@ +type Hex = string | Uint8Array +export type CurveType = { + P: bigint + nByteLength: number + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + a: bigint + montgomeryBits: number + powPminus2?: (x: bigint) => bigint + xyToU?: (x: bigint, y: bigint) => bigint + Gu: bigint + randomBytes?: (bytesLength?: number) => Uint8Array +} +export type CurveFn = { + scalarMult: (scalar: Hex, u: Hex) => Uint8Array + scalarMultBase: (scalar: Hex) => Uint8Array + getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array + getPublicKey: (privateKey: Hex) => Uint8Array + utils: { + randomPrivateKey: () => Uint8Array + } + GuBytes: Uint8Array +} +export declare function montgomery(curveDef: CurveType): CurveFn +export {} +//# sourceMappingURL=montgomery.d.ts.map diff --git a/packages/noble-curves/abstract/montgomery.d.ts.map b/packages/noble-curves/abstract/montgomery.d.ts.map new file mode 100644 index 00000000000..5b04dc83510 --- /dev/null +++ b/packages/noble-curves/abstract/montgomery.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../src/abstract/montgomery.ts"],"names":[],"mappings":"AAkBA,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACtD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC;IAC5E,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IACnE,YAAY,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAC9C,KAAK,EAAE;QAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;KAAE,CAAC;IAC9C,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAsBF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAqIvD"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/montgomery.js b/packages/noble-curves/abstract/montgomery.js new file mode 100644 index 00000000000..97e5d70ea11 --- /dev/null +++ b/packages/noble-curves/abstract/montgomery.js @@ -0,0 +1,162 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.montgomery = montgomery +/** + * Montgomery curve methods. It's not really whole montgomery curve, + * just bunch of very specific methods for X25519 / X448 from + * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const modular_js_1 = require('./modular.js') +const utils_js_1 = require('./utils.js') +const _0n = BigInt(0) +const _1n = BigInt(1) +function validateOpts(curve) { + ;(0, utils_js_1.validateObject)( + curve, + { + a: 'bigint', + }, + { + montgomeryBits: 'isSafeInteger', + nByteLength: 'isSafeInteger', + adjustScalarBytes: 'function', + domain: 'function', + powPminus2: 'function', + Gu: 'bigint', + }, + ) + // Set defaults + return Object.freeze({ ...curve }) +} +// Uses only one coordinate instead of two +function montgomery(curveDef) { + const CURVE = validateOpts(curveDef) + const { P } = CURVE + const modP = (n) => (0, modular_js_1.mod)(n, P) + const montgomeryBits = CURVE.montgomeryBits + const montgomeryBytes = Math.ceil(montgomeryBits / 8) + const fieldLen = CURVE.nByteLength + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) + const powPminus2 = CURVE.powPminus2 || ((x) => (0, modular_js_1.pow)(x, P - BigInt(2), P)) + // cswap from RFC7748. But it is not from RFC7748! + /* + cswap(swap, x_2, x_3): + dummy = mask(swap) AND (x_2 XOR x_3) + x_2 = x_2 XOR dummy + x_3 = x_3 XOR dummy + Return (x_2, x_3) + Where mask(swap) is the all-1 or all-0 word of the same length as x_2 + and x_3, computed, e.g., as mask(swap) = 0 - swap. + */ + function cswap(swap, x_2, x_3) { + const dummy = modP(swap * (x_2 - x_3)) + x_2 = modP(x_2 - dummy) + x_3 = modP(x_3 + dummy) + return [x_2, x_3] + } + // x25519 from 4 + // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 + const a24 = (CURVE.a - BigInt(2)) / BigInt(4) + /** + * + * @param pointU u coordinate (x) on Montgomery Curve 25519 + * @param scalar by which the point would be multiplied + * @returns new Point on Montgomery curve + */ + function montgomeryLadder(u, scalar) { + ;(0, utils_js_1.aInRange)('u', u, _0n, P) + ;(0, utils_js_1.aInRange)('scalar', scalar, _0n, P) + // Section 5: Implementations MUST accept non-canonical values and process them as + // if they had been reduced modulo the field prime. + const k = scalar + const x_1 = u + let x_2 = _1n + let z_2 = _0n + let x_3 = u + let z_3 = _1n + let swap = _0n + let sw + for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { + const k_t = (k >> t) & _1n + swap ^= k_t + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + swap = k_t + const A = x_2 + z_2 + const AA = modP(A * A) + const B = x_2 - z_2 + const BB = modP(B * B) + const E = AA - BB + const C = x_3 + z_3 + const D = x_3 - z_3 + const DA = modP(D * A) + const CB = modP(C * B) + const dacb = DA + CB + const da_cb = DA - CB + x_3 = modP(dacb * dacb) + z_3 = modP(x_1 * modP(da_cb * da_cb)) + x_2 = modP(AA * BB) + z_2 = modP(E * (AA + modP(a24 * E))) + } + // (x_2, x_3) = cswap(swap, x_2, x_3) + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + // (z_2, z_3) = cswap(swap, z_2, z_3) + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + // z_2^(p - 2) + const z2 = powPminus2(z_2) + // Return x_2 * (z_2^(p - 2)) + return modP(x_2 * z2) + } + function encodeUCoordinate(u) { + return (0, utils_js_1.numberToBytesLE)(modP(u), montgomeryBytes) + } + function decodeUCoordinate(uEnc) { + // Section 5: When receiving such an array, implementations of X25519 + // MUST mask the most significant bit in the final byte. + const u = (0, utils_js_1.ensureBytes)('u coordinate', uEnc, montgomeryBytes) + if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 + return (0, utils_js_1.bytesToNumberLE)(u) + } + function decodeScalar(n) { + const bytes = (0, utils_js_1.ensureBytes)('scalar', n) + const len = bytes.length + if (len !== montgomeryBytes && len !== fieldLen) { + let valid = '' + montgomeryBytes + ' or ' + fieldLen + throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) + } + return (0, utils_js_1.bytesToNumberLE)(adjustScalarBytes(bytes)) + } + function scalarMult(scalar, u) { + const pointU = decodeUCoordinate(u) + const _scalar = decodeScalar(scalar) + const pu = montgomeryLadder(pointU, _scalar) + // The result was not contributory + // https://cr.yp.to/ecdh.html#validate + if (pu === _0n) throw new Error('invalid private or public key received') + return encodeUCoordinate(pu) + } + // Computes public key from private. By doing scalar multiplication of base point. + const GuBytes = encodeUCoordinate(CURVE.Gu) + function scalarMultBase(scalar) { + return scalarMult(scalar, GuBytes) + } + return { + scalarMult, + scalarMultBase, + getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey), + getPublicKey: (privateKey) => scalarMultBase(privateKey), + utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) }, + GuBytes: GuBytes, + } +} +//# sourceMappingURL=montgomery.js.map diff --git a/packages/noble-curves/abstract/montgomery.js.map b/packages/noble-curves/abstract/montgomery.js.map new file mode 100644 index 00000000000..f7c44bbf434 --- /dev/null +++ b/packages/noble-curves/abstract/montgomery.js.map @@ -0,0 +1 @@ +{"version":3,"file":"montgomery.js","sourceRoot":"","sources":["../src/abstract/montgomery.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/poseidon.d.ts b/packages/noble-curves/abstract/poseidon.d.ts new file mode 100644 index 00000000000..37c473b1465 --- /dev/null +++ b/packages/noble-curves/abstract/poseidon.d.ts @@ -0,0 +1,39 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +export type PoseidonOpts = { + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean + mds: bigint[][] + roundConstants: bigint[][] +} +export declare function validateOpts(opts: PoseidonOpts): Readonly<{ + rounds: number + sboxFn: (n: bigint) => bigint + roundConstants: bigint[][] + mds: bigint[][] + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean +}> +export declare function splitConstants(rc: bigint[], t: number): bigint[][] +/** Poseidon NTT-friendly hash. */ +export declare function poseidon(opts: PoseidonOpts): { + (values: bigint[]): bigint[] + roundConstants: bigint[][] +} +//# sourceMappingURL=poseidon.d.ts.map diff --git a/packages/noble-curves/abstract/poseidon.d.ts.map b/packages/noble-curves/abstract/poseidon.d.ts.map new file mode 100644 index 00000000000..f984629539b --- /dev/null +++ b/packages/noble-curves/abstract/poseidon.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"poseidon.d.ts","sourceRoot":"","sources":["../src/abstract/poseidon.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sEAAsE;AACtE,OAAO,EAAS,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,CA6CD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAalE;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG;IAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAE7B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAmCA"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/poseidon.js b/packages/noble-curves/abstract/poseidon.js new file mode 100644 index 00000000000..66b16492669 --- /dev/null +++ b/packages/noble-curves/abstract/poseidon.js @@ -0,0 +1,104 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.validateOpts = validateOpts +exports.splitConstants = splitConstants +exports.poseidon = poseidon +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const modular_js_1 = require('./modular.js') +function validateOpts(opts) { + const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts + const { roundsFull, roundsPartial, sboxPower, t } = opts + ;(0, modular_js_1.validateField)(Fp) + for (const i of ['t', 'roundsFull', 'roundsPartial']) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + // MDS is TxT matrix + if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') + const _mds = mds.map((mdsRow) => { + if (!Array.isArray(mdsRow) || mdsRow.length !== t) + throw new Error('invalid MDS matrix row: ' + mdsRow) + return mdsRow.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) + return Fp.create(i) + }) + }) + if (rev !== undefined && typeof rev !== 'boolean') + throw new Error('invalid param reversePartialPowIdx=' + rev) + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) + const rounds = roundsFull + roundsPartial + if (!Array.isArray(rc) || rc.length !== rounds) + throw new Error('Poseidon: invalid round constants') + const roundConstants = rc.map((rc) => { + if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') + return rc.map((i) => { + if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') + return Fp.create(i) + }) + }) + if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') + const _sboxPower = BigInt(sboxPower) + let sboxFn = (n) => (0, modular_js_1.FpPow)(Fp, n, _sboxPower) + // Unwrapped sbox power for common cases (195->142μs) + if (sboxPower === 3) sboxFn = (n) => Fp.mul(Fp.sqrN(n), n) + else if (sboxPower === 5) sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) + return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) +} +function splitConstants(rc, t) { + if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') + if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') + const res = [] + let tmp = [] + for (let i = 0; i < rc.length; i++) { + tmp.push(rc[i]) + if (tmp.length === t) { + res.push(tmp) + tmp = [] + } + } + return res +} +/** Poseidon NTT-friendly hash. */ +function poseidon(opts) { + const _opts = validateOpts(opts) + const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts + const halfRoundsFull = _opts.roundsFull / 2 + const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 + const poseidonRound = (values, isFull, idx) => { + values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) + if (isFull) values = values.map((i) => sboxFn(i)) + else values[partialIdx] = sboxFn(values[partialIdx]) + // Matrix multiplication + values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) + return values + } + const poseidonHash = function poseidonHash(values) { + if (!Array.isArray(values) || values.length !== t) + throw new Error('invalid values, expected array of bigints with length ' + t) + values = values.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) + return Fp.create(i) + }) + let lastRound = 0 + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + // Apply r_p partial rounds. + for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + if (lastRound !== totalRounds) throw new Error('invalid number of rounds') + return values + } + // For verification in tests + poseidonHash.roundConstants = roundConstants + return poseidonHash +} +//# sourceMappingURL=poseidon.js.map diff --git a/packages/noble-curves/abstract/poseidon.js.map b/packages/noble-curves/abstract/poseidon.js.map new file mode 100644 index 00000000000..eabe9f385c1 --- /dev/null +++ b/packages/noble-curves/abstract/poseidon.js.map @@ -0,0 +1 @@ +{"version":3,"file":"poseidon.js","sourceRoot":"","sources":["../src/abstract/poseidon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/tower.d.ts b/packages/noble-curves/abstract/tower.d.ts new file mode 100644 index 00000000000..34d68c39e3b --- /dev/null +++ b/packages/noble-curves/abstract/tower.d.ts @@ -0,0 +1,126 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.js' +import type { ProjConstructor, ProjPointType } from './weierstrass.js' +export type BigintTuple = [bigint, bigint] +export type Fp = bigint +export type Fp2 = { + c0: bigint + c1: bigint +} +export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] +export type Fp6 = { + c0: Fp2 + c1: Fp2 + c2: Fp2 +} +export type Fp12 = { + c0: Fp6 + c1: Fp6 +} +export type BigintTwelve = [ + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, +] +export type Fp2Bls = mod.IField & { + reim: (num: Fp2) => { + re: Fp + im: Fp + } + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + fromBigTuple(num: [bigint, bigint]): Fp2 +} +export type Fp12Bls = mod.IField & { + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + fromBigTwelve(num: BigintTwelve): Fp12 +} +export declare function psiFrobenius( + Fp: mod.IField, + Fp2: Fp2Bls, + base: Fp2, +): { + psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] + psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] + G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType + G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType + PSI_X: Fp2 + PSI_Y: Fp2 + PSI2_X: Fp2 + PSI2_Y: Fp2 +} +export type Tower12Opts = { + ORDER: bigint + NONRESIDUE?: Fp + FP2_NONRESIDUE: BigintTuple + Fp2sqrt?: (num: Fp2) => Fp2 + Fp2mulByB: (num: Fp2) => Fp2 + Fp12cyclotomicSquare: (num: Fp12) => Fp12 + Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 + Fp12finalExponentiate: (num: Fp12) => Fp12 +} +export declare function tower12(opts: Tower12Opts): { + Fp: Readonly & Required, 'isOdd'>>> + Fp2: mod.IField & { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { + re: bigint + im: bigint + } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + Fp6: mod.IField & { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + Fp4Square: ( + a: Fp2, + b: Fp2, + ) => { + first: Fp2 + second: Fp2 + } + Fp12: mod.IField & { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } +} +//# sourceMappingURL=tower.d.ts.map diff --git a/packages/noble-curves/abstract/tower.d.ts.map b/packages/noble-curves/abstract/tower.d.ts.map new file mode 100644 index 00000000000..436e2fecb8d --- /dev/null +++ b/packages/noble-curves/abstract/tower.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"tower.d.ts","sourceRoot":"","sources":["../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/tower.js b/packages/noble-curves/abstract/tower.js new file mode 100644 index 00000000000..0094e80cdcc --- /dev/null +++ b/packages/noble-curves/abstract/tower.js @@ -0,0 +1,520 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.psiFrobenius = psiFrobenius +exports.tower12 = tower12 +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const mod = require('./modular.js') +const utils_js_1 = require('./utils.js') +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) { + const _divisor = BigInt(divisor === undefined ? degree : divisor) + const towerModulus = modulus ** BigInt(degree) + const res = [] + for (let i = 0; i < num; i++) { + const a = BigInt(i + 1) + const powers = [] + for (let j = 0, qPower = _1n; j < degree; j++) { + const power = ((a * qPower - a) / _divisor) % towerModulus + powers.push(Fp.pow(nonResidue, power)) + qPower *= modulus + } + res.push(powers) + } + return res +} +// This works same at least for bls12-381, bn254 and bls12-377 +function psiFrobenius(Fp, Fp2, base) { + // Ψ endomorphism + const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) + const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) + function psi(x, y) { + // This x10 faster than previous version in bls12-381 + const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) + const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) + return [x2, y2] + } + // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) + const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) + // This equals -1, which causes y to be Fp2.neg(y). + // But not sure if there are case when this is not true? + const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) + if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') + function psi2(x, y) { + return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] + } + // Map points + const mapAffine = (fn) => (c, P) => { + const affine = P.toAffine() + const p = fn(affine.x, affine.y) + return c.fromAffine({ x: p[0], y: p[1] }) + } + const G2psi = mapAffine(psi) + const G2psi2 = mapAffine(psi2) + return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } +} +function tower12(opts) { + const { ORDER } = opts + // Fp + const Fp = mod.Field(ORDER) + const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) + const FpLegendre = mod.FpLegendre(ORDER) + const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 + // Fp2 + const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] + const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp.add(c0, r0), + c1: Fp.add(c1, r1), + }) + const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp.sub(c0, r0), + c1: Fp.sub(c1, r1), + }) + const Fp2Multiply = ({ c0, c1 }, rhs) => { + if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } + // (a+bi)(c+di) = (ac−bd) + (ad+bc)i + const { c0: r0, c1: r1 } = rhs + let t1 = Fp.mul(c0, r0) // c0 * o0 + let t2 = Fp.mul(c1, r1) // c1 * o1 + // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i + const o0 = Fp.sub(t1, t2) + const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) + return { c0: o0, c1: o1 } + } + const Fp2Square = ({ c0, c1 }) => { + const a = Fp.add(c0, c1) + const b = Fp.sub(c0, c1) + const c = Fp.add(c0, c0) + return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } + } + const Fp2fromBigTuple = (tuple) => { + if (tuple.length !== 2) throw new Error('invalid tuple') + const fps = tuple.map((n) => Fp.create(n)) + return { c0: fps[0], c1: fps[1] } + } + const FP2_ORDER = ORDER * ORDER + const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) + const Fp2 = { + ORDER: FP2_ORDER, + isLE: Fp.isLE, + NONRESIDUE: Fp2Nonresidue, + BITS: (0, utils_js_1.bitLen)(FP2_ORDER), + BYTES: Math.ceil((0, utils_js_1.bitLen)(FP2_ORDER) / 8), + MASK: (0, utils_js_1.bitMask)((0, utils_js_1.bitLen)(FP2_ORDER)), + ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, + ONE: { c0: Fp.ONE, c1: Fp.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', + is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1), + neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), + pow: (num, power) => mod.FpPow(Fp2, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), + // Normalized + add: Fp2Add, + sub: Fp2Subtract, + mul: Fp2Multiply, + sqr: Fp2Square, + // NonNormalized stuff + addN: Fp2Add, + subN: Fp2Subtract, + mulN: Fp2Multiply, + sqrN: Fp2Square, + // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? + div: (lhs, rhs) => + Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), + inv: ({ c0: a, c1: b }) => { + // We wish to find the multiplicative inverse of a nonzero + // element a + bu in Fp2. We leverage an identity + // + // (a + bu)(a - bu) = a² + b² + // + // which holds because u² = -1. This can be rewritten as + // + // (a + bu)(a - bu)/(a² + b²) = 1 + // + // because a² + b² = 0 has no nonzero solutions for (a, b). + // This gives that (a - bu)/(a² + b²) is the inverse + // of (a + bu). Importantly, this can be computing using + // only a single inversion in Fp. + const factor = Fp.inv(Fp.create(a * a + b * b)) + return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } + }, + sqrt: (num) => { + if (opts.Fp2sqrt) return opts.Fp2sqrt(num) + // This is generic for all quadratic extensions (Fp2) + const { c0, c1 } = num + if (Fp.is0(c1)) { + // if c0 is quadratic residue + if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) + else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) + } + const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) + let d = Fp.mul(Fp.add(a, c0), Fpdiv2) + const legendre = FpLegendre(Fp, d) + // -1, Quadratic non residue + if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) + const a0 = Fp.sqrt(d) + const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) + if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') + // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num + const x1 = candidateSqrt + const x2 = Fp2.neg(x1) + const { re: re1, im: im1 } = Fp2.reim(x1) + const { re: re2, im: im2 } = Fp2.reim(x2) + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 + return x2 + }, + // Same as sgn0_m_eq_2 in RFC 9380 + isOdd: (x) => { + const { re: x0, im: x1 } = Fp2.reim(x) + const sign_0 = x0 % _2n + const zero_0 = x0 === _0n + const sign_1 = x1 % _2n + return BigInt(sign_0 || (zero_0 && sign_1)) == _1n + }, + // Bytes util + fromBytes(b) { + if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } + }, + toBytes: ({ c0, c1 }) => (0, utils_js_1.concatBytes)(Fp.toBytes(c0), Fp.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp.cmov(c0, r0, c), + c1: Fp.cmov(c1, r1, c), + }), + reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), + // multiply by u + 1 + mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), + mulByB: opts.Fp2mulByB, + fromBigTuple: Fp2fromBigTuple, + frobeniusMap: ({ c0, c1 }, power) => ({ + c0, + c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), + }), + } + // Fp6 + const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ + c0: Fp2.add(c0, r0), + c1: Fp2.add(c1, r1), + c2: Fp2.add(c2, r2), + }) + const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ + c0: Fp2.sub(c0, r0), + c1: Fp2.sub(c1, r1), + c2: Fp2.sub(c2, r2), + }) + const Fp6Multiply = ({ c0, c1, c2 }, rhs) => { + if (typeof rhs === 'bigint') { + return { + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + } + } + const { c0: r0, c1: r1, c2: r2 } = rhs + const t0 = Fp2.mul(c0, r0) // c0 * o0 + const t1 = Fp2.mul(c1, r1) // c1 * o1 + const t2 = Fp2.mul(c2, r2) // c2 * o2 + return { + // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) + c0: Fp2.add( + t0, + Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), + ), + // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) + c1: Fp2.add( + Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), + Fp2.mulByNonresidue(t2), + ), + // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 + c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), + } + } + const Fp6Square = ({ c0, c1, c2 }) => { + let t0 = Fp2.sqr(c0) // c0² + let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 + let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 + let t4 = Fp2.sqr(c2) // c2² + return { + c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 + c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 + // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 + c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), + } + } + const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 6, + 2, + 3, + ) + const Fp6 = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp2.isLE, + BITS: 3 * Fp2.BITS, + BYTES: 3 * Fp2.BYTES, + MASK: (0, utils_js_1.bitMask)(3 * Fp2.BITS), + ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, + ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, + create: (num) => num, + isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), + is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), + neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), + eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => + Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), + sqrt: utils_js_1.notImplemented, + // Do we need division by bigint at all? Should be done via order: + div: (lhs, rhs) => + Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp6, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), + // Normalized + add: Fp6Add, + sub: Fp6Subtract, + mul: Fp6Multiply, + sqr: Fp6Square, + // NonNormalized stuff + addN: Fp6Add, + subN: Fp6Subtract, + mulN: Fp6Multiply, + sqrN: Fp6Square, + inv: ({ c0, c1, c2 }) => { + let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) + let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 + let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 + // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) + let t4 = Fp2.inv( + Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), + ) + return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } + }, + // Bytes utils + fromBytes: (b) => { + if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), + c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), + c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), + } + }, + toBytes: ({ c0, c1, c2 }) => + (0, utils_js_1.concatBytes)(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), + cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({ + c0: Fp2.cmov(c0, r0, c), + c1: Fp2.cmov(c1, r1, c), + c2: Fp2.cmov(c2, r2, c), + }), + fromBigSix: (t) => { + if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') + return { + c0: Fp2.fromBigTuple(t.slice(0, 2)), + c1: Fp2.fromBigTuple(t.slice(2, 4)), + c2: Fp2.fromBigTuple(t.slice(4, 6)), + } + }, + frobeniusMap: ({ c0, c1, c2 }, power) => ({ + c0: Fp2.frobeniusMap(c0, power), + c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + }), + mulByFp2: ({ c0, c1, c2 }, rhs) => ({ + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + }), + mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), + // Sparse multiplication + mul1: ({ c0, c1, c2 }, b1) => ({ + c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), + c1: Fp2.mul(c0, b1), + c2: Fp2.mul(c1, b1), + }), + // Sparse multiplication + mul01({ c0, c1, c2 }, b0, b1) { + let t0 = Fp2.mul(c0, b0) // c0 * b0 + let t1 = Fp2.mul(c1, b1) // c1 * b1 + return { + // ((c1 + c2) * b1 - T1) * (u + 1) + T0 + c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), + // (b0 + b1) * (c0 + c1) - T0 - T1 + c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), + // (c0 + c2) * b0 - T0 + T1 + c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), + } + }, + } + // Fp12 + const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 12, + 1, + 6, + )[0] + const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp6.add(c0, r0), + c1: Fp6.add(c1, r1), + }) + const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp6.sub(c0, r0), + c1: Fp6.sub(c1, r1), + }) + const Fp12Multiply = ({ c0, c1 }, rhs) => { + if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } + let { c0: r0, c1: r1 } = rhs + let t1 = Fp6.mul(c0, r0) // c0 * r0 + let t2 = Fp6.mul(c1, r1) // c1 * r1 + return { + c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v + // (c0 + c1) * (r0 + r1) - (T1 + T2) + c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), + } + } + const Fp12Square = ({ c0, c1 }) => { + let ab = Fp6.mul(c0, c1) // c0 * c1 + return { + // (c1 * v + c0) * (c0 + c1) - AB - AB * v + c0: Fp6.sub( + Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), + Fp6.mulByNonresidue(ab), + ), + c1: Fp6.add(ab, ab), + } // AB + AB + } + function Fp4Square(a, b) { + const a2 = Fp2.sqr(a) + const b2 = Fp2.sqr(b) + return { + first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² + second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² + } + } + const Fp12 = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp6.isLE, + BITS: 2 * Fp2.BITS, + BYTES: 2 * Fp2.BYTES, + MASK: (0, utils_js_1.bitMask)(2 * Fp2.BITS), + ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, + ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), + is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), + neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), + sqrt: utils_js_1.notImplemented, + inv: ({ c0, c1 }) => { + let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) + return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w + }, + div: (lhs, rhs) => + Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp12, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), + // Normalized + add: Fp12Add, + sub: Fp12Subtract, + mul: Fp12Multiply, + sqr: Fp12Square, + // NonNormalized stuff + addN: Fp12Add, + subN: Fp12Subtract, + mulN: Fp12Multiply, + sqrN: Fp12Square, + // Bytes utils + fromBytes: (b) => { + if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), + c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), + } + }, + toBytes: ({ c0, c1 }) => (0, utils_js_1.concatBytes)(Fp6.toBytes(c0), Fp6.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp6.cmov(c0, r0, c), + c1: Fp6.cmov(c1, r1, c), + }), + // Utils + // toString() { + // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); + // }, + // fromTuple(c: [Fp6, Fp6]) { + // return new Fp12(...c); + // } + fromBigTwelve: (t) => ({ + c0: Fp6.fromBigSix(t.slice(0, 6)), + c1: Fp6.fromBigSix(t.slice(6, 12)), + }), + // Raises to q**i -th power + frobeniusMap(lhs, power) { + const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] + return { + c0: Fp6.frobeniusMap(lhs.c0, power), + c1: Fp6.create({ + c0: Fp2.mul(c0, coeff), + c1: Fp2.mul(c1, coeff), + c2: Fp2.mul(c2, coeff), + }), + } + }, + mulByFp2: ({ c0, c1 }, rhs) => ({ + c0: Fp6.mulByFp2(c0, rhs), + c1: Fp6.mulByFp2(c1, rhs), + }), + conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }), + // Sparse multiplication + mul014: ({ c0, c1 }, o0, o1, o4) => { + let t0 = Fp6.mul01(c0, o0, o1) + let t1 = Fp6.mul1(c1, o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 + // (c1 + c0) * [o0, o1+o4] - T0 - T1 + c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), + } + }, + mul034: ({ c0, c1 }, o0, o3, o4) => { + const a = Fp6.create({ + c0: Fp2.mul(c0.c0, o0), + c1: Fp2.mul(c0.c1, o0), + c2: Fp2.mul(c0.c2, o0), + }) + const b = Fp6.mul01(c1, o3, o4) + const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(b), a), + c1: Fp6.sub(e, Fp6.add(a, b)), + } + }, + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + _cyclotomicSquare: opts.Fp12cyclotomicSquare, + _cyclotomicExp: opts.Fp12cyclotomicExp, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + finalExponentiate: opts.Fp12finalExponentiate, + } + return { Fp, Fp2, Fp6, Fp4Square, Fp12 } +} +//# sourceMappingURL=tower.js.map diff --git a/packages/noble-curves/abstract/tower.js.map b/packages/noble-curves/abstract/tower.js.map new file mode 100644 index 00000000000..d148f00a2a9 --- /dev/null +++ b/packages/noble-curves/abstract/tower.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tower.js","sourceRoot":"","sources":["../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/utils.d.ts b/packages/noble-curves/abstract/utils.d.ts new file mode 100644 index 00000000000..405e6bef69d --- /dev/null +++ b/packages/noble-curves/abstract/utils.d.ts @@ -0,0 +1,126 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +export type Hex = Uint8Array | string +export type PrivKey = Hex | bigint +export type CHash = { + (message: Uint8Array | string): Uint8Array + blockLen: number + outputLen: number + create(opts?: { + dkLen?: number + }): any +} +export type FHash = (message: Uint8Array | string) => Uint8Array +export declare function isBytes(a: unknown): a is Uint8Array +export declare function abytes(item: unknown): void +export declare function abool(title: string, value: boolean): void +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export declare function bytesToHex(bytes: Uint8Array): string +export declare function numberToHexUnpadded(num: number | bigint): string +export declare function hexToNumber(hex: string): bigint +/** + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export declare function hexToBytes(hex: string): Uint8Array +export declare function bytesToNumberBE(bytes: Uint8Array): bigint +export declare function bytesToNumberLE(bytes: Uint8Array): bigint +export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array +export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array +export declare function numberToVarBytesBE(n: number | bigint): Uint8Array +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export declare function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array +/** + * Copies several Uint8Arrays into one. + */ +export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array +export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export declare function utf8ToBytes(str: string): Uint8Array +export declare function inRange(n: bigint, min: bigint, max: bigint): boolean +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export declare function aInRange(title: string, n: bigint, min: bigint, max: bigint): void +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export declare function bitLen(n: bigint): number +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export declare function bitGet(n: bigint, pos: number): bigint +/** + * Sets single bit at position. + */ +export declare function bitSet(n: bigint, pos: number, value: boolean): bigint +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export declare const bitMask: (n: number) => bigint +type Pred = (v: Uint8Array) => T | undefined +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export declare function createHmacDrbg( + hashLen: number, + qByteLen: number, + hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, +): (seed: Uint8Array, predicate: Pred) => T +declare const validatorFns: { + readonly bigint: (val: any) => boolean + readonly function: (val: any) => boolean + readonly boolean: (val: any) => boolean + readonly string: (val: any) => boolean + readonly stringOrUint8Array: (val: any) => boolean + readonly isSafeInteger: (val: any) => boolean + readonly array: (val: any) => boolean + readonly field: (val: any, object: any) => any + readonly hash: (val: any) => boolean +} +type Validator = keyof typeof validatorFns +type ValMap> = { + [K in keyof T]?: Validator +} +export declare function validateObject>( + object: T, + validators: ValMap, + optValidators?: ValMap, +): T +/** + * throws not implemented error + */ +export declare const notImplemented: () => never +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export declare function memoized( + fn: (arg: T, ...args: O) => R, +): (arg: T, ...args: O) => R +export {} +//# sourceMappingURL=utils.d.ts.map diff --git a/packages/noble-curves/abstract/utils.d.ts.map b/packages/noble-curves/abstract/utils.d.ts.map new file mode 100644 index 00000000000..350f5c0e2f0 --- /dev/null +++ b/packages/noble-curves/abstract/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/utils.js b/packages/noble-curves/abstract/utils.js new file mode 100644 index 00000000000..20607d42562 --- /dev/null +++ b/packages/noble-curves/abstract/utils.js @@ -0,0 +1,340 @@ +'use strict' +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +Object.defineProperty(exports, '__esModule', { value: true }) +exports.notImplemented = exports.bitMask = void 0 +exports.isBytes = isBytes +exports.abytes = abytes +exports.abool = abool +exports.bytesToHex = bytesToHex +exports.numberToHexUnpadded = numberToHexUnpadded +exports.hexToNumber = hexToNumber +exports.hexToBytes = hexToBytes +exports.bytesToNumberBE = bytesToNumberBE +exports.bytesToNumberLE = bytesToNumberLE +exports.numberToBytesBE = numberToBytesBE +exports.numberToBytesLE = numberToBytesLE +exports.numberToVarBytesBE = numberToVarBytesBE +exports.ensureBytes = ensureBytes +exports.concatBytes = concatBytes +exports.equalBytes = equalBytes +exports.utf8ToBytes = utf8ToBytes +exports.inRange = inRange +exports.aInRange = aInRange +exports.bitLen = bitLen +exports.bitGet = bitGet +exports.bitSet = bitSet +exports.createHmacDrbg = createHmacDrbg +exports.validateObject = validateObject +exports.memoized = memoized +// 100 lines of code in the file are duplicated from noble-hashes (utils). +// This is OK: `abstract` directory does not use noble-hashes. +// User may opt-in into using different hashing library. This way, noble-hashes +// won't be included into their bundle. +const _0n = /* @__PURE__ */ BigInt(0) +const _1n = /* @__PURE__ */ BigInt(1) +const _2n = /* @__PURE__ */ BigInt(2) +function isBytes(a) { + return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') +} +function abytes(item) { + if (!isBytes(item)) throw new Error('Uint8Array expected') +} +function abool(title, value) { + if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) +} +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +function bytesToHex(bytes) { + abytes(bytes) + // pre-caching improves the speed 6x + let hex = '' + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]] + } + return hex +} +function numberToHexUnpadded(num) { + const hex = num.toString(16) + return hex.length & 1 ? '0' + hex : hex +} +function hexToNumber(hex) { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian +} +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } +function asciiToBase16(ch) { + if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 + if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) + if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) + return +} +/** + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +function hexToBytes(hex) { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + const hl = hex.length + const al = hl / 2 + if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) + const array = new Uint8Array(al) + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)) + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1] + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) + } + array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 + } + return array +} +// BE: Big Endian, LE: Little Endian +function bytesToNumberBE(bytes) { + return hexToNumber(bytesToHex(bytes)) +} +function bytesToNumberLE(bytes) { + abytes(bytes) + return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) +} +function numberToBytesBE(n, len) { + return hexToBytes(n.toString(16).padStart(len * 2, '0')) +} +function numberToBytesLE(n, len) { + return numberToBytesBE(n, len).reverse() +} +// Unpadded, rarely used +function numberToVarBytesBE(n) { + return hexToBytes(numberToHexUnpadded(n)) +} +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +function ensureBytes(title, hex, expectedLength) { + let res + if (typeof hex === 'string') { + try { + res = hexToBytes(hex) + } catch (e) { + throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) + } + } else if (isBytes(hex)) { + // Uint8Array.from() instead of hash.slice() because node.js Buffer + // is instance of Uint8Array, and its slice() creates **mutable** copy + res = Uint8Array.from(hex) + } else { + throw new Error(title + ' must be hex string or Uint8Array') + } + const len = res.length + if (typeof expectedLength === 'number' && len !== expectedLength) + throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) + return res +} +/** + * Copies several Uint8Arrays into one. + */ +function concatBytes(...arrays) { + let sum = 0 + for (let i = 0; i < arrays.length; i++) { + const a = arrays[i] + abytes(a) + sum += a.length + } + const res = new Uint8Array(sum) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const a = arrays[i] + res.set(a, pad) + pad += a.length + } + return res +} +// Compares 2 u8a-s in kinda constant time +function equalBytes(a, b) { + if (a.length !== b.length) return false + let diff = 0 + for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] + return diff === 0 +} +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +function utf8ToBytes(str) { + if (typeof str !== 'string') throw new Error('string expected') + return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 +} +// Is positive bigint +const isPosBig = (n) => typeof n === 'bigint' && _0n <= n +function inRange(n, min, max) { + return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max +} +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +function aInRange(title, n, min, max) { + // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? + // consider P=256n, min=0n, max=P + // - a for min=0 would require -1: `inRange('x', x, -1n, P)` + // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` + // - our way is the cleanest: `inRange('x', x, 0n, P) + if (!inRange(n, min, max)) + throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) +} +// Bit operations +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +function bitLen(n) { + let len + for (len = 0; n > _0n; n >>= _1n, len += 1); + return len +} +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +function bitGet(n, pos) { + return (n >> BigInt(pos)) & _1n +} +/** + * Sets single bit at position. + */ +function bitSet(n, pos, value) { + return n | ((value ? _1n : _0n) << BigInt(pos)) +} +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n +exports.bitMask = bitMask +// DRBG +const u8n = (data) => new Uint8Array(data) // creates Uint8Array +const u8fr = (arr) => Uint8Array.from(arr) // another shortcut +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +function createHmacDrbg(hashLen, qByteLen, hmacFn) { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') + if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0 // Iterations counter, will throw when over 1000 + const reset = () => { + v.fill(1) + k.fill(0) + i = 0 + } + const h = (...b) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) + const reseed = (seed = u8n()) => { + // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) + v = h() // v = hmac(k || v) + if (seed.length === 0) return + k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) + v = h() // v = hmac(k || v) + } + const gen = () => { + // HMAC-DRBG generate() function + if (i++ >= 1000) throw new Error('drbg: tried 1000 values') + let len = 0 + const out = [] + while (len < qByteLen) { + v = h() + const sl = v.slice() + out.push(sl) + len += v.length + } + return concatBytes(...out) + } + const genUntil = (seed, pred) => { + reset() + reseed(seed) // Steps D-G + let res = undefined // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed() + reset() + return res + } + return genUntil +} +// Validating curves and fields +const validatorFns = { + bigint: (val) => typeof val === 'bigint', + function: (val) => typeof val === 'function', + boolean: (val) => typeof val === 'boolean', + string: (val) => typeof val === 'string', + stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val), + isSafeInteger: (val) => Number.isSafeInteger(val), + array: (val) => Array.isArray(val), + field: (val, object) => object.Fp.isValid(val), + hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen), +} +// type Record = { [P in K]: T; } +function validateObject(object, validators, optValidators = {}) { + const checkField = (fieldName, type, isOptional) => { + const checkVal = validatorFns[type] + if (typeof checkVal !== 'function') throw new Error('invalid validator function') + const val = object[fieldName] + if (isOptional && val === undefined) return + if (!checkVal(val, object)) { + throw new Error( + 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, + ) + } + } + for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false) + for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true) + return object +} +// validate type tests +// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; +// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! +// // Should fail type-check +// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); +// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); +// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); +// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); +/** + * throws not implemented error + */ +const notImplemented = () => { + throw new Error('not implemented') +} +exports.notImplemented = notImplemented +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +function memoized(fn) { + const map = new WeakMap() + return (arg, ...args) => { + const val = map.get(arg) + if (val !== undefined) return val + const computed = fn(arg, ...args) + map.set(arg, computed) + return computed + } +} +//# sourceMappingURL=utils.js.map diff --git a/packages/noble-curves/abstract/utils.js.map b/packages/noble-curves/abstract/utils.js.map new file mode 100644 index 00000000000..6f9fc1c881b --- /dev/null +++ b/packages/noble-curves/abstract/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/weierstrass.d.ts b/packages/noble-curves/abstract/weierstrass.d.ts new file mode 100644 index 00000000000..f79b0c73b8e --- /dev/null +++ b/packages/noble-curves/abstract/weierstrass.d.ts @@ -0,0 +1,241 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' +import { type IField } from './modular.js' +import { type CHash, type Hex, type PrivKey } from './utils.js' +export type { AffinePoint } +type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array +type EndomorphismOpts = { + beta: bigint + splitScalar: (k: bigint) => { + k1neg: boolean + k1: bigint + k2neg: boolean + k2: bigint + } +} +export type BasicWCurve = BasicCurve & { + a: T + b: T + allowedPrivateKeyLengths?: readonly number[] + wrapPrivateKey?: boolean + endo?: EndomorphismOpts + isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean + clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType +} +type Entropy = Hex | boolean +export type SignOpts = { + lowS?: boolean + extraEntropy?: Entropy + prehash?: boolean +} +export type VerOpts = { + lowS?: boolean + prehash?: boolean + format?: 'compact' | 'der' | undefined +} +export interface ProjPointType extends Group> { + readonly px: T + readonly py: T + readonly pz: T + get x(): T + get y(): T + multiply(scalar: bigint): ProjPointType + toAffine(iz?: T): AffinePoint + isTorsionFree(): boolean + clearCofactor(): ProjPointType + assertValidity(): void + hasEvenY(): boolean + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + multiplyUnsafe(scalar: bigint): ProjPointType + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined + _setWindowSize(windowSize: number): void +} +export interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType + fromAffine(p: AffinePoint): ProjPointType + fromHex(hex: Hex): ProjPointType + fromPrivateKey(privateKey: PrivKey): ProjPointType + normalizeZ(points: ProjPointType[]): ProjPointType[] + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType +} +export type CurvePointsType = BasicWCurve & { + fromBytes?: (bytes: Uint8Array) => AffinePoint + toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array +} +export type CurvePointsTypeWithLength = Readonly< + CurvePointsType & { + nByteLength: number + nBitLength: number + } +> +declare function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength +export type CurvePointsRes = { + CURVE: ReturnType> + ProjectivePoint: ProjConstructor + normPrivateKeyToScalar: (key: PrivKey) => bigint + weierstrassEquation: (x: T) => T + isWithinCurveOrder: (num: bigint) => boolean +} +export declare class DERErr extends Error { + constructor(m?: string) +} +export type IDER = { + Err: typeof DERErr + _tlv: { + encode: (tag: number, data: string) => string + decode( + tag: number, + data: Uint8Array, + ): { + v: Uint8Array + l: Uint8Array + } + } + _int: { + encode(num: bigint): string + decode(data: Uint8Array): bigint + } + toSig(hex: string | Uint8Array): { + r: bigint + s: bigint + } + hexFromSig(sig: { + r: bigint + s: bigint + }): string +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export declare const DER: IDER +export declare function weierstrassPoints(opts: CurvePointsType): CurvePointsRes +export interface SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + assertValidity(): void + addRecoveryBit(recovery: number): RecoveredSignatureType + hasHighS(): boolean + normalizeS(): SignatureType + recoverPublicKey(msgHash: Hex): ProjPointType + toCompactRawBytes(): Uint8Array + toCompactHex(): string + toDERRawBytes(isCompressed?: boolean): Uint8Array + toDERHex(isCompressed?: boolean): string +} +export type RecoveredSignatureType = SignatureType & { + readonly recovery: number +} +export type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType + fromCompact(hex: Hex): SignatureType + fromDER(hex: Hex): SignatureType +} +type SignatureLike = { + r: bigint + s: bigint +} +export type PubKey = Hex | ProjPointType +export type CurveType = BasicWCurve & { + hash: CHash + hmac: HmacFnSync + randomBytes: (bytesLength?: number) => Uint8Array + lowS?: boolean + bits2int?: (bytes: Uint8Array) => bigint + bits2int_modN?: (bytes: Uint8Array) => bigint +} +declare function validateOpts(curve: CurveType): Readonly< + CurveType & { + nByteLength: number + nBitLength: number + } +> +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType + verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean + ProjectivePoint: ProjConstructor + Signature: SignatureConstructor + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint + isValidPrivateKey(privateKey: PrivKey): boolean + randomPrivateKey: () => Uint8Array + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType + } +} +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export declare function weierstrass(curveDef: CurveType): CurveFn +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export declare function SWUFpSqrtRatio( + Fp: IField, + Z: T, +): ( + u: T, + v: T, +) => { + isValid: boolean + value: T +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export declare function mapToCurveSimpleSWU( + Fp: IField, + opts: { + A: T + B: T + Z: T + }, +): (u: T) => { + x: T + y: T +} +//# sourceMappingURL=weierstrass.d.ts.map diff --git a/packages/noble-curves/abstract/weierstrass.d.ts.map b/packages/noble-curves/abstract/weierstrass.d.ts.map new file mode 100644 index 00000000000..8bf023e0581 --- /dev/null +++ b/packages/noble-curves/abstract/weierstrass.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"weierstrass.d.ts","sourceRoot":"","sources":["../src/abstract/weierstrass.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/weierstrass.js b/packages/noble-curves/abstract/weierstrass.js new file mode 100644 index 00000000000..e7b0342dc1f --- /dev/null +++ b/packages/noble-curves/abstract/weierstrass.js @@ -0,0 +1,1139 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.DER = exports.DERErr = void 0 +exports.weierstrassPoints = weierstrassPoints +exports.weierstrass = weierstrass +exports.SWUFpSqrtRatio = SWUFpSqrtRatio +exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const curve_js_1 = require('./curve.js') +const modular_js_1 = require('./modular.js') +const ut = require('./utils.js') +const utils_js_1 = require('./utils.js') +function validateSigVerOpts(opts) { + if (opts.lowS !== undefined) (0, utils_js_1.abool)('lowS', opts.lowS) + if (opts.prehash !== undefined) (0, utils_js_1.abool)('prehash', opts.prehash) +} +function validatePointOpts(curve) { + const opts = (0, curve_js_1.validateBasic)(curve) + ut.validateObject( + opts, + { + a: 'field', + b: 'field', + }, + { + allowedPrivateKeyLengths: 'array', + wrapPrivateKey: 'boolean', + isTorsionFree: 'function', + clearCofactor: 'function', + allowInfinityPoint: 'boolean', + fromBytes: 'function', + toBytes: 'function', + }, + ) + const { endo, Fp, a } = opts + if (endo) { + if (!Fp.eql(a, Fp.ZERO)) { + throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') + } + if ( + typeof endo !== 'object' || + typeof endo.beta !== 'bigint' || + typeof endo.splitScalar !== 'function' + ) { + throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') + } + } + return Object.freeze({ ...opts }) +} +const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut +class DERErr extends Error { + constructor(m = '') { + super(m) + } +} +exports.DERErr = DERErr +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +exports.DER = { + // asn.1 DER encoding utils + Err: DERErr, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag, data) => { + const { Err: E } = exports.DER + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length & 1) throw new E('tlv.encode: unpadded data') + const dataLen = data.length / 2 + const len = ut.numberToHexUnpadded(dataLen) + if ((len.length / 2) & 128) throw new E('tlv.encode: long form length too big') + // length of length with long form flag + const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 128) : '' + const t = ut.numberToHexUnpadded(tag) + return t + lenLen + len + data + }, + // v - value, l - left bytes (unparsed) + decode(tag, data) { + const { Err: E } = exports.DER + let pos = 0 + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') + const first = data[pos++] + const isLong = !!(first & 128) // First bit of first length byte is flag for short/long form + let length = 0 + if (!isLong) length = first + else { + // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] + const lenLen = first & 127 + if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') + if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js + const lengthBytes = data.subarray(pos, pos + lenLen) + if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') + if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') + for (const b of lengthBytes) length = (length << 8) | b + pos += lenLen + if (length < 128) throw new E('tlv.decode(long): not minimal encoding') + } + const v = data.subarray(pos, pos + length) + if (v.length !== length) throw new E('tlv.decode: wrong value length') + return { v, l: data.subarray(pos + length) } + }, + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num) { + const { Err: E } = exports.DER + if (num < _0n) throw new E('integer: negative integers are not allowed') + let hex = ut.numberToHexUnpadded(num) + // Pad with zero byte if negative flag is present + if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex + if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') + return hex + }, + decode(data) { + const { Err: E } = exports.DER + if (data[0] & 128) throw new E('invalid signature integer: negative') + if (data[0] === 0x00 && !(data[1] & 128)) + throw new E('invalid signature integer: unnecessary leading zero') + return b2n(data) + }, + }, + toSig(hex) { + // parse DER signature + const { Err: E, _int: int, _tlv: tlv } = exports.DER + const data = typeof hex === 'string' ? h2b(hex) : hex + ut.abytes(data) + const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) + if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) + const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) + if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + return { r: int.decode(rBytes), s: int.decode(sBytes) } + }, + hexFromSig(sig) { + const { _tlv: tlv, _int: int } = exports.DER + const rs = tlv.encode(0x02, int.encode(sig.r)) + const ss = tlv.encode(0x02, int.encode(sig.s)) + const seq = rs + ss + return tlv.encode(0x30, seq) + }, +} +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) +function weierstrassPoints(opts) { + const CURVE = validatePointOpts(opts) + const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ + const Fn = (0, modular_js_1.Field)(CURVE.n, CURVE.nBitLength) + const toBytes = + CURVE.toBytes || + ((_c, point, _isCompressed) => { + const a = point.toAffine() + return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) + }) + const fromBytes = + CURVE.fromBytes || + ((bytes) => { + // const head = bytes[0]; + const tail = bytes.subarray(1) + // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + }) + /** + * y² = x³ + ax + b: Short weierstrass curve formula + * @returns y² + */ + function weierstrassEquation(x) { + const { a, b } = CURVE + const x2 = Fp.sqr(x) // x * x + const x3 = Fp.mul(x2, x) // x2 * x + return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b + } + // Validate whether the passed curve params are valid. + // We check if curve equation works for generator point. + // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. + // ProjectivePoint class has not been initialized yet. + if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) + throw new Error('bad generator point: equation left != right') + // Valid group elements reside in range 1..n-1 + function isWithinCurveOrder(num) { + return ut.inRange(num, _1n, CURVE.n) + } + // Validates if priv key is valid and converts it to bigint. + // Supports options allowedPrivateKeyLengths and wrapPrivateKey. + function normPrivateKeyToScalar(key) { + const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE + if (lengths && typeof key !== 'bigint') { + if (ut.isBytes(key)) key = ut.bytesToHex(key) + // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes + if (typeof key !== 'string' || !lengths.includes(key.length)) + throw new Error('invalid private key') + key = key.padStart(nByteLength * 2, '0') + } + let num + try { + num = + typeof key === 'bigint' + ? key + : ut.bytesToNumberBE((0, utils_js_1.ensureBytes)('private key', key, nByteLength)) + } catch (error) { + throw new Error( + 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, + ) + } + if (wrapPrivateKey) num = (0, modular_js_1.mod)(num, N) // disabled by default, enabled for BLS + ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] + return num + } + function assertPrjPoint(other) { + if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') + } + // Memoized toAffine / validity check. They are heavy. Points are immutable. + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + const toAffineMemo = (0, utils_js_1.memoized)((p, iz) => { + const { px: x, py: y, pz: z } = p + // Fast-path for normalized points + if (Fp.eql(z, Fp.ONE)) return { x, y } + const is0 = p.is0() + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 1. + if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) + const ax = Fp.mul(x, iz) + const ay = Fp.mul(y, iz) + const zz = Fp.mul(z, iz) + if (is0) return { x: Fp.ZERO, y: Fp.ZERO } + if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + // NOTE: on exception this will crash 'cached' and no value will be set. + // Otherwise true will be return + const assertValidMemo = (0, utils_js_1.memoized)((p) => { + if (p.is0()) { + // (0, 1, 0) aka ZERO is invalid in most contexts. + // In BLS, ZERO can be serialized, so we allow it. + // (0, 0, 0) is invalid representation of ZERO. + if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return + throw new Error('bad point: ZERO') + } + // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` + const { x, y } = p.toAffine() + // Check if x, y are valid field elements + if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') + const left = Fp.sqr(y) // y² + const right = weierstrassEquation(x) // x³ + ax + b + if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') + if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') + return true + }) + /** + * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) + * Default Point works in 2d / affine coordinates: (x, y) + * We're doing calculations in projective, because its operations don't require costly inversion. + */ + class Point { + constructor(px, py, pz) { + this.px = px + this.py = py + this.pz = pz + if (px == null || !Fp.isValid(px)) throw new Error('x required') + if (py == null || !Fp.isValid(py)) throw new Error('y required') + if (pz == null || !Fp.isValid(pz)) throw new Error('z required') + Object.freeze(this) + } + // Does not validate if the point is on-curve. + // Use fromHex instead, or call assertValidity() later. + static fromAffine(p) { + const { x, y } = p || {} + if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') + if (p instanceof Point) throw new Error('projective point not allowed') + const is0 = (i) => Fp.eql(i, Fp.ZERO) + // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) + if (is0(x) && is0(y)) return Point.ZERO + return new Point(x, y, Fp.ONE) + } + get x() { + return this.toAffine().x + } + get y() { + return this.toAffine().y + } + /** + * Takes a bunch of Projective Points but executes only one + * inversion on all of them. Inversion is very slow operation, + * so this improves performance massively. + * Optimization: converts a list of projective points to a list of identical points with Z=1. + */ + static normalizeZ(points) { + const toInv = Fp.invertBatch(points.map((p) => p.pz)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + /** + * Converts hash string or Uint8Array to Point. + * @param hex short/long ECDSA hex + */ + static fromHex(hex) { + const P = Point.fromAffine(fromBytes((0, utils_js_1.ensureBytes)('pointHex', hex))) + P.assertValidity() + return P + } + // Multiplies generator point by privateKey. + static fromPrivateKey(privateKey) { + return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) + } + // Multiscalar Multiplication + static msm(points, scalars) { + return (0, curve_js_1.pippenger)(Point, Fn, points, scalars) + } + // "Private method", don't use it directly + _setWindowSize(windowSize) { + wnaf.setWindowSize(this, windowSize) + } + // A point on curve is valid if it conforms to equation. + assertValidity() { + assertValidMemo(this) + } + hasEvenY() { + const { y } = this.toAffine() + if (Fp.isOdd) return !Fp.isOdd(y) + throw new Error("Field doesn't support isOdd") + } + /** + * Compare one point to another. + */ + equals(other) { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) + const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) + return U1 && U2 + } + /** + * Flips point to one corresponding to (x, -y) in Affine coordinates. + */ + negate() { + return new Point(this.px, Fp.neg(this.py), this.pz) + } + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a, b } = CURVE + const b3 = Fp.mul(b, _3n) + const { px: X1, py: Y1, pz: Z1 } = this + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + let t0 = Fp.mul(X1, X1) // step 1 + let t1 = Fp.mul(Y1, Y1) + let t2 = Fp.mul(Z1, Z1) + let t3 = Fp.mul(X1, Y1) + t3 = Fp.add(t3, t3) // step 5 + Z3 = Fp.mul(X1, Z1) + Z3 = Fp.add(Z3, Z3) + X3 = Fp.mul(a, Z3) + Y3 = Fp.mul(b3, t2) + Y3 = Fp.add(X3, Y3) // step 10 + X3 = Fp.sub(t1, Y3) + Y3 = Fp.add(t1, Y3) + Y3 = Fp.mul(X3, Y3) + X3 = Fp.mul(t3, X3) + Z3 = Fp.mul(b3, Z3) // step 15 + t2 = Fp.mul(a, t2) + t3 = Fp.sub(t0, t2) + t3 = Fp.mul(a, t3) + t3 = Fp.add(t3, Z3) + Z3 = Fp.add(t0, t0) // step 20 + t0 = Fp.add(Z3, t0) + t0 = Fp.add(t0, t2) + t0 = Fp.mul(t0, t3) + Y3 = Fp.add(Y3, t0) + t2 = Fp.mul(Y1, Z1) // step 25 + t2 = Fp.add(t2, t2) + t0 = Fp.mul(t2, t3) + X3 = Fp.sub(X3, t0) + Z3 = Fp.mul(t2, t1) + Z3 = Fp.add(Z3, Z3) // step 30 + Z3 = Fp.add(Z3, Z3) + return new Point(X3, Y3, Z3) + } + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(other) { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + const a = CURVE.a + const b3 = Fp.mul(CURVE.b, _3n) + let t0 = Fp.mul(X1, X2) // step 1 + let t1 = Fp.mul(Y1, Y2) + let t2 = Fp.mul(Z1, Z2) + let t3 = Fp.add(X1, Y1) + let t4 = Fp.add(X2, Y2) // step 5 + t3 = Fp.mul(t3, t4) + t4 = Fp.add(t0, t1) + t3 = Fp.sub(t3, t4) + t4 = Fp.add(X1, Z1) + let t5 = Fp.add(X2, Z2) // step 10 + t4 = Fp.mul(t4, t5) + t5 = Fp.add(t0, t2) + t4 = Fp.sub(t4, t5) + t5 = Fp.add(Y1, Z1) + X3 = Fp.add(Y2, Z2) // step 15 + t5 = Fp.mul(t5, X3) + X3 = Fp.add(t1, t2) + t5 = Fp.sub(t5, X3) + Z3 = Fp.mul(a, t4) + X3 = Fp.mul(b3, t2) // step 20 + Z3 = Fp.add(X3, Z3) + X3 = Fp.sub(t1, Z3) + Z3 = Fp.add(t1, Z3) + Y3 = Fp.mul(X3, Z3) + t1 = Fp.add(t0, t0) // step 25 + t1 = Fp.add(t1, t0) + t2 = Fp.mul(a, t2) + t4 = Fp.mul(b3, t4) + t1 = Fp.add(t1, t2) + t2 = Fp.sub(t0, t2) // step 30 + t2 = Fp.mul(a, t2) + t4 = Fp.add(t4, t2) + t0 = Fp.mul(t1, t4) + Y3 = Fp.add(Y3, t0) + t0 = Fp.mul(t5, t4) // step 35 + X3 = Fp.mul(t3, X3) + X3 = Fp.sub(X3, t0) + t0 = Fp.mul(t3, t1) + Z3 = Fp.mul(t5, Z3) + Z3 = Fp.add(Z3, t0) // step 40 + return new Point(X3, Y3, Z3) + } + subtract(other) { + return this.add(other.negate()) + } + is0() { + return this.equals(Point.ZERO) + } + wNAF(n) { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed private key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(sc) { + const { endo, n: N } = CURVE + ut.aInRange('scalar', sc, _0n, N) + const I = Point.ZERO + if (sc === _0n) return I + if (this.is0() || sc === _1n) return this + // Case a: no endomorphism. Case b: has precomputes. + if (!endo || wnaf.hasPrecomputes(this)) + return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) + // Case c: endomorphism + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) + let k1p = I + let k2p = I + let d = this + while (k1 > _0n || k2 > _0n) { + if (k1 & _1n) k1p = k1p.add(d) + if (k2 & _1n) k2p = k2p.add(d) + d = d.double() + k1 >>= _1n + k2 >>= _1n + } + if (k1neg) k1p = k1p.negate() + if (k2neg) k2p = k2p.negate() + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + return k1p.add(k2p) + } + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(scalar) { + const { endo, n: N } = CURVE + ut.aInRange('scalar', scalar, _1n, N) + let point, fake // Fake point is used to const-time mult + if (endo) { + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) + let { p: k1p, f: f1p } = this.wNAF(k1) + let { p: k2p, f: f2p } = this.wNAF(k2) + k1p = wnaf.constTimeNegate(k1neg, k1p) + k2p = wnaf.constTimeNegate(k2neg, k2p) + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + point = k1p.add(k2p) + fake = f1p.add(f2p) + } else { + const { p, f } = this.wNAF(scalar) + point = p + fake = f + } + // Normalize `z` for both points, but return only real one + return Point.normalizeZ([point, fake])[0] + } + /** + * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. + * Not using Strauss-Shamir trick: precomputation tables are faster. + * The trick could be useful if both P and Q are not G (not in our case). + * @returns non-zero affine point + */ + multiplyAndAddUnsafe(Q, a, b) { + const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes + const mul = ( + P, + a, // Select faster multiply() method + ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) + const sum = mul(this, a).add(mul(Q, b)) + return sum.is0() ? undefined : sum + } + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + toAffine(iz) { + return toAffineMemo(this, iz) + } + isTorsionFree() { + const { h: cofactor, isTorsionFree } = CURVE + if (cofactor === _1n) return true // No subgroups, always torsion-free + if (isTorsionFree) return isTorsionFree(Point, this) + throw new Error('isTorsionFree() has not been declared for the elliptic curve') + } + clearCofactor() { + const { h: cofactor, clearCofactor } = CURVE + if (cofactor === _1n) return this // Fast-path + if (clearCofactor) return clearCofactor(Point, this) + return this.multiplyUnsafe(CURVE.h) + } + toRawBytes(isCompressed = true) { + ;(0, utils_js_1.abool)('isCompressed', isCompressed) + this.assertValidity() + return toBytes(Point, this, isCompressed) + } + toHex(isCompressed = true) { + ;(0, utils_js_1.abool)('isCompressed', isCompressed) + return ut.bytesToHex(this.toRawBytes(isCompressed)) + } + } + Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) + Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) + const _bits = CURVE.nBitLength + const wnaf = (0, curve_js_1.wNAF)(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) + // Validate if generator point is on curve + return { + CURVE, + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } +} +function validateOpts(curve) { + const opts = (0, curve_js_1.validateBasic)(curve) + ut.validateObject( + opts, + { + hash: 'hash', + hmac: 'function', + randomBytes: 'function', + }, + { + bits2int: 'function', + bits2int_modN: 'function', + lowS: 'boolean', + }, + ) + return Object.freeze({ lowS: true, ...opts }) +} +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +function weierstrass(curveDef) { + const CURVE = validateOpts(curveDef) + const { Fp, n: CURVE_ORDER } = CURVE + const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 + const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 + function modN(a) { + return (0, modular_js_1.mod)(a, CURVE_ORDER) + } + function invN(a) { + return (0, modular_js_1.invert)(a, CURVE_ORDER) + } + const { + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } = weierstrassPoints({ + ...CURVE, + toBytes(_c, point, isCompressed) { + const a = point.toAffine() + const x = Fp.toBytes(a.x) + const cat = ut.concatBytes + ;(0, utils_js_1.abool)('isCompressed', isCompressed) + if (isCompressed) { + return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) + } else { + return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) + } + }, + fromBytes(bytes) { + const len = bytes.length + const head = bytes[0] + const tail = bytes.subarray(1) + // this.assertValidity() is done inside of fromHex + if (len === compressedLen && (head === 0x02 || head === 0x03)) { + const x = ut.bytesToNumberBE(tail) + if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') + const y2 = weierstrassEquation(x) // y² = x³ + ax + b + let y + try { + y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 + } catch (sqrtError) { + const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' + throw new Error('Point is not on curve' + suffix) + } + const isYOdd = (y & _1n) === _1n + // ECDSA + const isHeadOdd = (head & 1) === 1 + if (isHeadOdd !== isYOdd) y = Fp.neg(y) + return { x, y } + } else if (len === uncompressedLen && head === 0x04) { + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + } else { + const cl = compressedLen + const ul = uncompressedLen + throw new Error( + 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, + ) + } + }, + }) + const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) + function isBiggerThanHalfOrder(number) { + const HALF = CURVE_ORDER >> _1n + return number > HALF + } + function normalizeS(s) { + return isBiggerThanHalfOrder(s) ? modN(-s) : s + } + // slice bytes num + const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to)) + /** + * ECDSA signature with its (r, s) properties. Supports DER & compact representations. + */ + class Signature { + constructor(r, s, recovery) { + this.r = r + this.s = s + this.recovery = recovery + this.assertValidity() + } + // pair (bytes of r, bytes of s) + static fromCompact(hex) { + const l = CURVE.nByteLength + hex = (0, utils_js_1.ensureBytes)('compactSignature', hex, l * 2) + return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) + } + // DER encoded ECDSA signature + // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script + static fromDER(hex) { + const { r, s } = exports.DER.toSig((0, utils_js_1.ensureBytes)('DER', hex)) + return new Signature(r, s) + } + assertValidity() { + ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] + ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] + } + addRecoveryBit(recovery) { + return new Signature(this.r, this.s, recovery) + } + recoverPublicKey(msgHash) { + const { r, s, recovery: rec } = this + const h = bits2int_modN((0, utils_js_1.ensureBytes)('msgHash', msgHash)) // Truncate hash + if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') + const radj = rec === 2 || rec === 3 ? r + CURVE.n : r + if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') + const prefix = (rec & 1) === 0 ? '02' : '03' + const R = Point.fromHex(prefix + numToNByteStr(radj)) + const ir = invN(radj) // r^-1 + const u1 = modN(-h * ir) // -hr^-1 + const u2 = modN(s * ir) // sr^-1 + const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) + if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked + Q.assertValidity() + return Q + } + // Signatures should be low-s, to prevent malleability. + hasHighS() { + return isBiggerThanHalfOrder(this.s) + } + normalizeS() { + return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this + } + // DER-encoded + toDERRawBytes() { + return ut.hexToBytes(this.toDERHex()) + } + toDERHex() { + return exports.DER.hexFromSig({ r: this.r, s: this.s }) + } + // padded bytes of r, then padded bytes of s + toCompactRawBytes() { + return ut.hexToBytes(this.toCompactHex()) + } + toCompactHex() { + return numToNByteStr(this.r) + numToNByteStr(this.s) + } + } + const utils = { + isValidPrivateKey(privateKey) { + try { + normPrivateKeyToScalar(privateKey) + return true + } catch (error) { + return false + } + }, + normPrivateKeyToScalar: normPrivateKeyToScalar, + /** + * Produces cryptographically secure private key from random of size + * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. + */ + randomPrivateKey: () => { + const length = (0, modular_js_1.getMinHashLength)(CURVE.n) + return (0, modular_js_1.mapHashToField)(CURVE.randomBytes(length), CURVE.n) + }, + /** + * Creates precompute table for an arbitrary EC point. Makes point "cached". + * Allows to massively speed-up `point.multiply(scalar)`. + * @returns cached point + * @example + * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); + * fast.multiply(privKey); // much faster ECDH now + */ + precompute(windowSize = 8, point = Point.BASE) { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here + return point + }, + } + /** + * Computes public key for a private key. Checks for validity of the private key. + * @param privateKey private key + * @param isCompressed whether to return compact (default), or full key + * @returns Public key, full when isCompressed=false; short when isCompressed=true + */ + function getPublicKey(privateKey, isCompressed = true) { + return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) + } + /** + * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. + */ + function isProbPub(item) { + const arr = ut.isBytes(item) + const str = typeof item === 'string' + const len = (arr || str) && item.length + if (arr) return len === compressedLen || len === uncompressedLen + if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen + if (item instanceof Point) return true + return false + } + /** + * ECDH (Elliptic Curve Diffie Hellman). + * Computes shared public key from private key and public key. + * Checks: 1) private key validity 2) shared key is on-curve. + * Does NOT hash the result. + * @param privateA private key + * @param publicB different public key + * @param isCompressed whether to return compact (default), or full key + * @returns shared public key + */ + function getSharedSecret(privateA, publicB, isCompressed = true) { + if (isProbPub(privateA)) throw new Error('first arg must be private key') + if (!isProbPub(publicB)) throw new Error('second arg must be public key') + const b = Point.fromHex(publicB) // check for being on-curve + return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) + } + // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. + // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. + // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. + // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors + const bits2int = + CURVE.bits2int || + function (bytes) { + // Our custom check "just in case" + if (bytes.length > 8192) throw new Error('input is too large') + // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) + // for some cases, since bytes.length * 8 is not actual bitLength. + const num = ut.bytesToNumberBE(bytes) // check for == u8 done here + const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits + return delta > 0 ? num >> BigInt(delta) : num + } + const bits2int_modN = + CURVE.bits2int_modN || + function (bytes) { + return modN(bits2int(bytes)) // can't use bytesToNumberBE here + } + // NOTE: pads output with zero as per spec + const ORDER_MASK = ut.bitMask(CURVE.nBitLength) + /** + * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. + */ + function int2octets(num) { + ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) + // works with order, can have different size than numToField! + return ut.numberToBytesBE(num, CURVE.nByteLength) + } + // Steps A, D of RFC6979 3.2 + // Creates RFC6979 seed; converts msg/privKey to numbers. + // Used only in sign, not in verify. + // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, + // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 + function prepSig(msgHash, privateKey, opts = defaultSigOpts) { + if (['recovered', 'canonical'].some((k) => k in opts)) + throw new Error('sign() legacy options not supported') + const { hash, randomBytes } = CURVE + let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default + if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash + msgHash = (0, utils_js_1.ensureBytes)('msgHash', msgHash) + validateSigVerOpts(opts) + if (prehash) msgHash = (0, utils_js_1.ensureBytes)('prehashed msgHash', hash(msgHash)) + // We can't later call bits2octets, since nested bits2int is broken for curves + // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. + // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) + const h1int = bits2int_modN(msgHash) + const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint + const seedArgs = [int2octets(d), int2octets(h1int)] + // extraEntropy. RFC6979 3.6: additional k' (optional). + if (ent != null && ent !== false) { + // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is + seedArgs.push((0, utils_js_1.ensureBytes)('extraEntropy', e)) // check for being bytes + } + const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 + const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! + // Converts signature params into point w r/s, checks result for validity. + function k2sig(kBytes) { + // RFC 6979 Section 3.2, step 3: k = bits2int(T) + const k = bits2int(kBytes) // Cannot use fields methods, since it is group element + if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N + const ik = invN(k) // k^-1 mod n + const q = Point.BASE.multiply(k).toAffine() // q = Gk + const r = modN(q.x) // r = q.x mod n + if (r === _0n) return + // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to + // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: + // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT + const s = modN(ik * modN(m + r * d)) // Not using blinding here + if (s === _0n) return + let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) + let normS = s + if (lowS && isBiggerThanHalfOrder(s)) { + normS = normalizeS(s) // if lowS was passed, ensure s is always + recovery ^= 1 // // in the bottom half of N + } + return new Signature(r, normS, recovery) // use normS, not s + } + return { seed, k2sig } + } + const defaultSigOpts = { lowS: CURVE.lowS, prehash: false } + const defaultVerOpts = { lowS: CURVE.lowS, prehash: false } + /** + * Signs message hash with a private key. + * ``` + * sign(m, d, k) where + * (x, y) = G × k + * r = x mod n + * s = (m + dr)/k mod n + * ``` + * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. + * @param privKey private key + * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. + * @returns signature with recovery param + */ + function sign(msgHash, privKey, opts = defaultSigOpts) { + const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. + const C = CURVE + const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) + return drbg(seed, k2sig) // Steps B, C, D, E, F, G + } + // Enable precomputes. Slows down first publicKey computation by 20ms. + Point.BASE._setWindowSize(8) + // utils.precompute(8, ProjectivePoint.BASE) + /** + * Verifies a signature against message hash and public key. + * Rejects lowS signatures by default: to override, + * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: + * + * ``` + * verify(r, s, h, P) where + * U1 = hs^-1 mod n + * U2 = rs^-1 mod n + * R = U1⋅G - U2⋅P + * mod(R.x, n) == r + * ``` + */ + function verify(signature, msgHash, publicKey, opts = defaultVerOpts) { + const sg = signature + msgHash = (0, utils_js_1.ensureBytes)('msgHash', msgHash) + publicKey = (0, utils_js_1.ensureBytes)('publicKey', publicKey) + const { lowS, prehash, format } = opts + // Verify opts, deduce signature format + validateSigVerOpts(opts) + if ('strict' in opts) throw new Error('options.strict was renamed to lowS') + if (format !== undefined && format !== 'compact' && format !== 'der') + throw new Error('format must be compact or der') + const isHex = typeof sg === 'string' || ut.isBytes(sg) + const isObj = + !isHex && + !format && + typeof sg === 'object' && + sg !== null && + typeof sg.r === 'bigint' && + typeof sg.s === 'bigint' + if (!isHex && !isObj) + throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') + let _sig = undefined + let P + try { + if (isObj) _sig = new Signature(sg.r, sg.s) + if (isHex) { + // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). + // Since DER can also be 2*nByteLength bytes, we check for it first. + try { + if (format !== 'compact') _sig = Signature.fromDER(sg) + } catch (derError) { + if (!(derError instanceof exports.DER.Err)) throw derError + } + if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) + } + P = Point.fromHex(publicKey) + } catch (error) { + return false + } + if (!_sig) return false + if (lowS && _sig.hasHighS()) return false + if (prehash) msgHash = CURVE.hash(msgHash) + const { r, s } = _sig + const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element + const is = invN(s) // s^-1 + const u1 = modN(h * is) // u1 = hs^-1 mod n + const u2 = modN(r * is) // u2 = rs^-1 mod n + const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P + if (!R) return false + const v = modN(R.x) + return v === r + } + return { + CURVE, + getPublicKey, + getSharedSecret, + sign, + verify, + ProjectivePoint: Point, + Signature, + utils, + } +} +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +function SWUFpSqrtRatio(Fp, Z) { + // Generic implementation + const q = Fp.ORDER + let l = _0n + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n + const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. + // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. + // 2n ** c1 == 2n << (c1-1) + const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) + const _2n_pow_c1 = _2n_pow_c1_1 * _2n + const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 + const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) + let sqrtRatio = (u, v) => { + let tv1 = c6 // 1. tv1 = c6 + let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 + let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 + tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v + let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 + tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 + tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 + tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v + tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u + let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 + tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 + let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 + tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 + tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) + // 17. for i in (c1, c1 - 1, ..., 2): + for (let i = c1; i > _1n; i--) { + let tv5 = i - _2n // 18. tv5 = i - 2 + tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 + let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 + const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 + tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 + tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 + tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) + } + return { isValid: isQR, value: tv3 } + } + if (Fp.ORDER % _4n === _3n) { + // sqrt_ratio_3mod4(u, v) + const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) + sqrtRatio = (u, v) => { + let tv1 = Fp.sqr(v) // 1. tv1 = v^2 + const tv2 = Fp.mul(u, v) // 2. tv2 = u * v + tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 + let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 + y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 + const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 + const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v + const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u + let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) + return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 + } + } + // No curves uses that + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 + return sqrtRatio +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +function mapToCurveSimpleSWU(Fp, opts) { + ;(0, modular_js_1.validateField)(Fp) + if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) + throw new Error('mapToCurveSimpleSWU: invalid opts') + const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) + if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') + // Input: u, an element of F. + // Output: (x, y), a point on E. + return (u) => { + // prettier-ignore + let tv1, tv2, tv3, tv4, tv5, tv6, x, y + tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 + tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 + tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 + tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 + tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 + tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) + tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 + tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 + tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 + tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 + tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 + tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 + tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 + tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 + tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 + x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 + const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 + y = Fp.mul(y, value) // 20. y = y * y1 + x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) + y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) + const e1 = Fp.isOdd(u) === Fp.isOdd(y) // 23. e1 = sgn0(u) == sgn0(y) + y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) + x = Fp.div(x, tv4) // 25. x = x / tv4 + return { x, y } + } +} +//# sourceMappingURL=weierstrass.js.map diff --git a/packages/noble-curves/abstract/weierstrass.js.map b/packages/noble-curves/abstract/weierstrass.js.map new file mode 100644 index 00000000000..1c741346840 --- /dev/null +++ b/packages/noble-curves/abstract/weierstrass.js.map @@ -0,0 +1 @@ +{"version":3,"file":"weierstrass.js","sourceRoot":"","sources":["../src/abstract/weierstrass.ts"],"names":[],"mappings":"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,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,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"} \ No newline at end of file diff --git a/packages/noble-curves/bls12-381.d.ts b/packages/noble-curves/bls12-381.d.ts new file mode 100644 index 00000000000..8de19050c1e --- /dev/null +++ b/packages/noble-curves/bls12-381.d.ts @@ -0,0 +1,14 @@ +import { type CurveFn } from './abstract/bls.js' +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export declare const bls12_381: CurveFn +//# sourceMappingURL=bls12-381.d.ts.map diff --git a/packages/noble-curves/bls12-381.d.ts.map b/packages/noble-curves/bls12-381.d.ts.map new file mode 100644 index 00000000000..c7b4579f259 --- /dev/null +++ b/packages/noble-curves/bls12-381.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bls12-381.d.ts","sourceRoot":"","sources":["src/bls12-381.ts"],"names":[],"mappings":"AA+DA,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAkXtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,OAqUtB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/bls12-381.js b/packages/noble-curves/bls12-381.js new file mode 100644 index 00000000000..a8abbaf2682 --- /dev/null +++ b/packages/noble-curves/bls12-381.js @@ -0,0 +1,756 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.bls12_381 = void 0 +/** + * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: + * * Construct zk-SNARKs at the ~120-bit security + * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: + * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr + * + * ### Summary + * 1. BLS Relies on Bilinear Pairing (expensive) + * 2. Private Keys: 32 bytes + * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. + * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. + * - The signature is a point on the G2 subgroup, which is defined over a finite field + * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the + * complex numbers). + * - We also support reversed 96-byte pubkeys & 48-byte short signatures. + * 5. The 12 stands for the Embedding degree. + * + * ### Formulas + * - `P = pk x G` - public keys + * - `S = pk x H(m)` - signing + * - `e(P, H(m)) == e(G, S)` - verification using pairings + * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation + * + * ### Compatibility and notes + * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. + * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. + * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". + * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) + * 4. Compatible with specs: + * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), + * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), + * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * + * ### Params + * To verify curve parameters, see + * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). + * Basic math is done over finite fields over p. + * More complicated math is done over polynominal extension fields. + * To simplify calculations in Fp12, we construct extension tower: + * + * Embedding degree (k): 12 + * Seed (X): -15132376222941642752 + * Fr: (x⁴-x²+1) + * Fp: ((x-1)² ⋅ r(x)/3+x) + * (E/Fp): Y²=X³+4 + * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) + * Ate loop size: X + * + * ### Towers + * - Fp₁₂ = Fp₆² => Fp₂³ + * - Fp(u) / (u² - β) where β = -1 + * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 + * - Fp₆(w) / (w² - γ) where γ = v + * - Fp²[u] = Fp/u²+1 + * - Fp⁶[v] = Fp²/v³-1-u + * - Fp¹²[w] = Fp⁶/w²-v + * + * @todo construct bls & bn fp/fr from seed. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha256_1 = require('@noble/hashes/sha256') +const utils_1 = require('@noble/hashes/utils') +const bls_js_1 = require('./abstract/bls.js') +const mod = require('./abstract/modular.js') +const utils_js_1 = require('./abstract/utils.js') +// Types +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const tower_js_1 = require('./abstract/tower.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) +// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! +const BLS_X = BigInt('0xd201000000010000') +const BLS_X_LEN = (0, utils_js_1.bitLen)(BLS_X) +// CURVE FIELDS +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_js_1.tower12)({ + // Order of Fp + ORDER: BigInt( + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', + ), + // Finite extension field over irreducible polynominal. + // Fp(u) / (u² - β) where β = -1 + FP2_NONRESIDUE: [_1n, _1n], + Fp2mulByB: ({ c0, c1 }) => { + const t0 = Fp.mul(c0, _4n) // 4 * c0 + const t1 = Fp.mul(c1, _4n) // 4 * c1 + // (T0-T1) + (T0+T1)*i + return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } + }, + // Fp12 + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }) => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if ((0, utils_js_1.bitGet)(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const x = BLS_X + // this^(q⁶) / this + const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) + // t0^(q²) * t0 + const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) + const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) + const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) + const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) + const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) + const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) + const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) + const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) + const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) + const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) + const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) + // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 + return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) + }, +}) +// Finite field over r. +// This particular field is not used anywhere in bls12-381, but it is still useful. +const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) +// END OF CURVE FIELDS +// HashToCurve +// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 +const isogenyMapG2 = (0, hash_to_curve_js_1.isogenyMap)( + Fp2, + [ + // xNum + [ + [ + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + ], + [ + '0x0', + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', + ], + [ + '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', + '0x0', + ], + ], + // xDen + [ + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', + ], + [ + '0xc', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', + ], + ['0x1', '0x0'], // LAST 1 + ], + // yNum + [ + [ + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + ], + [ + '0x0', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', + ], + [ + '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', + '0x0', + ], + ], + // yDen + [ + [ + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + ], + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', + ], + [ + '0x12', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', + ], + ['0x1', '0x0'], // LAST 1 + ], + ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))), +) +// 11-isogeny map from E' to E +const isogenyMapG1 = (0, hash_to_curve_js_1.isogenyMap)( + Fp, + [ + // xNum + [ + '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', + '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', + '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', + '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', + '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', + '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', + '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', + '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', + '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', + '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', + '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', + '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', + ], + // xDen + [ + '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', + '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', + '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', + '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', + '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', + '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', + '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', + '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', + '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', + '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', + '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', + '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', + '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', + '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', + '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', + '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', + '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', + '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', + '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', + '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', + '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', + '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', + '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', + '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', + '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', + ], + // yDen + [ + '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', + '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', + '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', + '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', + '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', + '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', + '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', + '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', + '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', + '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', + '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', + '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', + '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', + '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', + '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))), +) +// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i +const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, { + A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I + B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) + Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) +}) +// Optimized SWU Map - Fp to G1 +const G1_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, { + A: Fp.create( + BigInt( + '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', + ), + ), + B: Fp.create( + BigInt( + '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', + ), + ), + Z: Fp.create(BigInt(11)), +}) +// Endomorphisms (for fast cofactor clearing) +// Ψ(P) endomorphism +const { G2psi, G2psi2 } = (0, tower_js_1.psiFrobenius)(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) +// Default hash_to_field options are for hash to G2. +// +// Parameter definitions are in section 5.3 of the spec unless otherwise noted. +// Parameter values come from section 8.8.2 of the spec. +// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 +// +// Base field F is GF(p^m) +// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +// m = 2 (or 1 for G1 see section 8.8.1) +// k = 128 +const htfDefaults = Object.freeze({ + // DST: a domain separation tag + // defined in section 2.2.5 + // Use utils.getDSTLabel(), utils.setDSTLabel(value) + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + // p: the characteristic of F + // where F is a finite field of characteristic p and order q = p^m + p: Fp.ORDER, + // m: the extension degree of F, m >= 1 + // where F is a finite field of characteristic p and order q = p^m + m: 2, + // k: the target security level for the suite in bits + // defined in section 5.1 + k: 128, + // option to use a message that has already been processed by + // expand_message_xmd + expand: 'xmd', + // Hash functions for: expand_message_xmd is appropriate for use with a + // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. + // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 + hash: sha256_1.sha256, +}) +// Encoding utils +// Point on G1 curve: (x, y) +// Compressed point of infinity +const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits +function parseMask(bytes) { + // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. + bytes = bytes.slice() + const mask = bytes[0] & 224 + const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) + const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) + const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) + bytes[0] &= 31 // clear mask (zero first 3 bits) + return { compressed, infinity, sort, value: bytes } +} +function setMask(bytes, mask) { + if (bytes[0] & 224) throw new Error('setMask: non-empty mask') + if (mask.compressed) bytes[0] |= 128 + if (mask.infinity) bytes[0] |= 64 + if (mask.sort) bytes[0] |= 32 + return bytes +} +function signatureG1ToRawBytes(point) { + point.assertValidity() + const isZero = point.equals(exports.bls12_381.G1.ProjectivePoint.ZERO) + const { x, y } = point.toAffine() + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort }) +} +function signatureG2ToRawBytes(point) { + // NOTE: by some reasons it was missed in bls12-381, looks like bug + point.assertValidity() + const len = Fp.BYTES + if (point.equals(exports.bls12_381.G2.ProjectivePoint.ZERO)) + return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len)) + const { x, y } = point.toAffine() + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + const tmp = y1 > _0n ? y1 * _2n : y0 * _2n + const sort = Boolean((tmp / Fp.ORDER) & _1n) + const z2 = x0 + return (0, utils_js_1.concatBytes)( + setMask((0, utils_js_1.numberToBytesBE)(x1, len), { sort, compressed: true }), + (0, utils_js_1.numberToBytesBE)(z2, len), + ) +} +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +exports.bls12_381 = (0, bls_js_1.bls)({ + // Fields + fields: { + Fp, + Fp2, + Fp6, + Fp12, + Fr, + }, + // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where + // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 + G1: { + Fp, + // cofactor; (z - 1)²/3 + h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), + // generator's coordinates + // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 + // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 + Gx: BigInt( + '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', + ), + Gy: BigInt( + '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', + ), + a: Fp.ZERO, + b: _4n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, point) => { + // φ endomorphism + const cubicRootOfUnityModP = BigInt( + '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', + ) + const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) + // todo: unroll + const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P + const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P + return u2P.equals(phi) + // https://eprint.iacr.org/2019/814.pdf + // (z² − 1)/3 + // const c1 = BigInt('0x396c8c005555e1560000000055555555'); + // const P = this; + // const S = P.sigma(); + // const Q = S.double(); + // const S2 = S.sigma(); + // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O + // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); + // const C = left.subtract(S2); + // return C.isZero(); + }, + // Clear cofactor of G1 + // https://eprint.iacr.org/2019/403 + clearCofactor: (_c, point) => { + // return this.multiplyUnsafe(CURVE.h); + return point.multiplyUnsafe(BLS_X).add(point) // x*P + P + }, + mapToCurve: (scalars) => { + const { x, y } = G1_SWU(Fp.create(scalars[0])) + return isogenyMapG1(x, y) + }, + fromBytes: (bytes) => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if (value.length === 48 && compressed) { + // TODO: Fp.bytes + const P = Fp.ORDER + const compressedValue = (0, utils_js_1.bytesToNumberBE)(value) + // Zero + const x = Fp.create(compressedValue & Fp.MASK) + if (infinity) { + if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') + return { x: _0n, y: _0n } + } + const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) + return { x: Fp.create(x), y: Fp.create(y) } + } else if (value.length === 96 && !compressed) { + // Check if the infinity flag is set + const x = (0, utils_js_1.bytesToNumberBE)(value.subarray(0, Fp.BYTES)) + const y = (0, utils_js_1.bytesToNumberBE)(value.subarray(Fp.BYTES)) + if (infinity) { + if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') + return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine() + } + return { x: Fp.create(x), y: Fp.create(y) } + } else { + throw new Error('invalid point G1, expected 48/96 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort }) + } else { + if (isZero) { + // 2x PUBLIC_KEY_LENGTH + const x = (0, utils_js_1.concatBytes)( + new Uint8Array([0x40]), + new Uint8Array(2 * Fp.BYTES - 1), + ) + return x + } else { + return (0, utils_js_1.concatBytes)( + (0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), + (0, utils_js_1.numberToBytesBE)(y, Fp.BYTES), + ) + } + } + }, + ShortSignature: { + fromHex(hex) { + const { infinity, sort, value } = parseMask( + (0, utils_js_1.ensureBytes)('signatureHex', hex, 48), + ) + const P = Fp.ORDER + const compressedValue = (0, utils_js_1.bytesToNumberBE)(value) + // Zero + if (infinity) return exports.bls12_381.G1.ProjectivePoint.ZERO + const x = Fp.create(compressedValue & Fp.MASK) + const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + const aflag = BigInt(sort) + if ((y * _2n) / P !== aflag) y = Fp.neg(y) + const point = exports.bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point) { + return signatureG1ToRawBytes(point) + }, + toHex(point) { + return (0, utils_js_1.bytesToHex)(signatureG1ToRawBytes(point)) + }, + }, + }, + // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), + // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where + // G² - 1 + // h2q + G2: { + Fp: Fp2, + // cofactor + h: BigInt( + '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', + ), + Gx: Fp2.fromBigTuple([ + BigInt( + '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', + ), + BigInt( + '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', + ), + ]), + // y = + // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, + // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + Gy: Fp2.fromBigTuple([ + BigInt( + '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', + ), + BigInt( + '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', + ), + ]), + a: Fp2.ZERO, + b: Fp2.fromBigTuple([_4n, _4n]), + hEff: BigInt( + '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', + ), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: (scalars) => { + const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) + return isogenyMapG2(x, y) + }, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, P) => { + return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) + // Older version: https://eprint.iacr.org/2019/814.pdf + // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O + // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); + }, + // Maps the point into the prime-order subgroup G2. + // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 + // https://eprint.iacr.org/2017/419.pdf + // prettier-ignore + clearCofactor: (c, P) => { + const x = BLS_X + let t1 = P.multiplyUnsafe(x).negate() // [-x]P + let t2 = G2psi(c, P) // Ψ(P) + let t3 = P.double() // 2P + t3 = G2psi2(c, t3) // Ψ²(2P) + t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) + t2 = t1.add(t2) // [-x]P + Ψ(P) + t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) + t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P + const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P + return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) + }, + fromBytes: (bytes) => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if ( + (!compressed && !infinity && sort) || // 00100000 + (!compressed && infinity && sort) || // 01100000 + (sort && infinity && compressed) // 11100000 + ) { + throw new Error('invalid encoding flag: ' + (bytes[0] & 224)) + } + const L = Fp.BYTES + const slc = (b, from, to) => (0, utils_js_1.bytesToNumberBE)(b.slice(from, to)) + if (value.length === 96 && compressed) { + const b = exports.bls12_381.params.G2b + const P = Fp.ORDER + if (infinity) { + // check that all bytes are 0 + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid compressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x_1 = slc(value, 0, L) + const x_0 = slc(value, L, 2 * L) + const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) + const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b + let y = Fp2.sqrt(right) + const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n + y = sort && Y_bit > 0 ? y : Fp2.neg(y) + return { x, y } + } else if (value.length === 192 && !compressed) { + if (infinity) { + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid uncompressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x1 = slc(value, 0, L) + const x0 = slc(value, L, 2 * L) + const y1 = slc(value, 2 * L, 3 * L) + const y0 = slc(value, 3 * L, 4 * L) + return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } + } else { + throw new Error('invalid point G2, expected 96/192 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const { BYTES: len, ORDER: P } = Fp + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) + return (0, utils_js_1.concatBytes)( + COMPRESSED_ZERO, + (0, utils_js_1.numberToBytesBE)(_0n, len), + ) + const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) + return (0, utils_js_1.concatBytes)( + setMask((0, utils_js_1.numberToBytesBE)(x.c1, len), { compressed: true, sort: flag }), + (0, utils_js_1.numberToBytesBE)(x.c0, len), + ) + } else { + if (isZero) + return (0, utils_js_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + return (0, utils_js_1.concatBytes)( + (0, utils_js_1.numberToBytesBE)(x1, len), + (0, utils_js_1.numberToBytesBE)(x0, len), + (0, utils_js_1.numberToBytesBE)(y1, len), + (0, utils_js_1.numberToBytesBE)(y0, len), + ) + } + }, + Signature: { + // TODO: Optimize, it's very slow because of sqrt. + fromHex(hex) { + const { infinity, sort, value } = parseMask( + (0, utils_js_1.ensureBytes)('signatureHex', hex), + ) + const P = Fp.ORDER + const half = value.length / 2 + if (half !== 48 && half !== 96) + throw new Error('invalid compressed signature length, must be 96 or 192') + const z1 = (0, utils_js_1.bytesToNumberBE)(value.slice(0, half)) + const z2 = (0, utils_js_1.bytesToNumberBE)(value.slice(half)) + // Indicates the infinity point + if (infinity) return exports.bls12_381.G2.ProjectivePoint.ZERO + const x1 = Fp.create(z1 & Fp.MASK) + const x2 = Fp.create(z2) + const x = Fp2.create({ c0: x2, c1: x1 }) + const y2 = Fp2.add(Fp2.pow(x, _3n), exports.bls12_381.params.G2b) // y² = x³ + 4 + // The slow part + let y = Fp2.sqrt(y2) + if (!y) throw new Error('Failed to find a square root') + // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 + // If y1 happens to be zero, then use the bit of y0 + const { re: y0, im: y1 } = Fp2.reim(y) + const aflag1 = BigInt(sort) + const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 + const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 + if (isGreater || isZero) y = Fp2.neg(y) + const point = exports.bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point) { + return signatureG2ToRawBytes(point) + }, + toHex(point) { + return (0, utils_js_1.bytesToHex)(signatureG2ToRawBytes(point)) + }, + }, + }, + params: { + ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 + r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves + xNegative: true, + twistType: 'multiplicative', + }, + htfDefaults, + hash: sha256_1.sha256, + randomBytes: utils_1.randomBytes, +}) +//# sourceMappingURL=bls12-381.js.map diff --git a/packages/noble-curves/bls12-381.js.map b/packages/noble-curves/bls12-381.js.map new file mode 100644 index 00000000000..d9c120ba5e6 --- /dev/null +++ b/packages/noble-curves/bls12-381.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bls12-381.js","sourceRoot":"","sources":["src/bls12-381.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/bn254.d.ts b/packages/noble-curves/bn254.d.ts new file mode 100644 index 00000000000..94c05dba695 --- /dev/null +++ b/packages/noble-curves/bn254.d.ts @@ -0,0 +1,15 @@ +import { type CurveFn as BLSCurveFn, type PostPrecomputeFn } from './abstract/bls.js' +import { type CurveFn } from './abstract/weierstrass.js' +export declare const _postPrecompute: PostPrecomputeFn +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export declare const bn254: BLSCurveFn +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + */ +export declare const bn254_weierstrass: CurveFn +//# sourceMappingURL=bn254.d.ts.map diff --git a/packages/noble-curves/bn254.d.ts.map b/packages/noble-curves/bn254.d.ts.map new file mode 100644 index 00000000000..478f468e6d2 --- /dev/null +++ b/packages/noble-curves/bn254.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bn254.d.ts","sourceRoot":"","sources":["src/bn254.ts"],"names":[],"mappings":"AAkDA,OAAO,EAEL,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAgGtE,eAAO,MAAM,eAAe,EAAE,gBAY7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UA6DlB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAS9B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/bn254.js b/packages/noble-curves/bn254.js new file mode 100644 index 00000000000..434d7ac7584 --- /dev/null +++ b/packages/noble-curves/bn254.js @@ -0,0 +1,237 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.bn254_weierstrass = exports.bn254 = exports._postPrecompute = void 0 +/** + * bn254, previously known as alt_bn_128, when it had 128-bit security. + +Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, +so the naming has been adjusted to its prime bit count: +https://hal.science/hal-01534101/file/main.pdf. +Compatible with EIP-196 and EIP-197. + +There are huge compatibility issues in the ecosystem: + +1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". +2. libff has bn128, but it's a different curve with different G2: + https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 +3. halo2curves bn256 is also incompatible and returns different outputs + +The goal of our implementation is to support "Ethereum" variant of the curve, +because it at least has specs: + +- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM +- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings +- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 +- The existing implementations are bad. Some are deprecated: + - https://github.com/paritytech/bn (old version) + - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) + - https://github.com/zcash-hackworks/bn + - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs +- Python implementations use different towers and produce different Fp12 outputs: + - https://github.com/ethereum/py_pairing + - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py +- Points are encoded differently in different implementations + +### Params +Seed (X): 4965661367192848881 +Fr: (36x⁴+36x³+18x²+6x+1) +Fp: (36x⁴+36x³+24x²+6x+1) +(E / Fp ): Y² = X³+3 +(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) +Ate loop size: 6x+2 + +### Towers +- Fp²[u] = Fp/u²+1 +- Fp⁶[v] = Fp²/v³-9-u +- Fp¹²[w] = Fp⁶/w²-v + + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha256_1 = require('@noble/hashes/sha256') +const utils_1 = require('@noble/hashes/utils') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const bls_js_1 = require('./abstract/bls.js') +const modular_js_1 = require('./abstract/modular.js') +const tower_js_1 = require('./abstract/tower.js') +const utils_js_1 = require('./abstract/utils.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +const _6n = BigInt(6) +const BN_X = BigInt('4965661367192848881') +const BN_X_LEN = (0, utils_js_1.bitLen)(BN_X) +const SIX_X_SQUARED = _6n * BN_X ** _2n +// Finite field over r. It's for convenience and is not used in the code below. +const Fr = (0, modular_js_1.Field)( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) +// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) +const Fp2B = { + c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), + c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), +} +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_js_1.tower12)({ + ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), + FP2_NONRESIDUE: [BigInt(9), _1n], + Fp2mulByB: (num) => Fp2.mul(num, Fp2B), + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }) => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BN_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if ((0, utils_js_1.bitGet)(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const powMinusX = (num) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) + const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) + const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) + const y1 = Fp12._cyclotomicSquare(powMinusX(r)) + const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) + const y4 = powMinusX(y2) + const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) + const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) + const y9 = Fp12.mul(y8, y1) + return Fp12.mul( + Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), + Fp12.mul( + Fp12.frobeniusMap(y8, 2), + Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), + ), + ) + }, +}) +// END OF CURVE FIELDS +const { G2psi, psi } = (0, tower_js_1.psiFrobenius)(Fp, Fp2, Fp2.NONRESIDUE) +/* +No hashToCurve for now (and signatures): + +- RFC 9380 doesn't mention bn254 and doesn't provide test vectors +- Overall seems like nobody is using BLS signatures on top of bn254 +- Seems like it can utilize SVDW, which is not implemented yet +*/ +const htfDefaults = Object.freeze({ + // DST: a domain separation tag defined in section 2.2.5 + DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + p: Fp.ORDER, + m: 2, + k: 128, + expand: 'xmd', + hash: sha256_1.sha256, +}) +const _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => { + const q = psi(Qx, Qy) + ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) + const q2 = psi(q[0], q[1]) + pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) +} +exports._postPrecompute = _postPrecompute +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +exports.bn254 = (0, bls_js_1.bls)({ + // Fields + fields: { Fp, Fp2, Fp6, Fp12, Fr }, + G1: { + Fp, + h: BigInt(1), + Gx: BigInt(1), + Gy: BigInt(2), + a: Fp.ZERO, + b: _3n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: utils_js_1.notImplemented, + fromBytes: utils_js_1.notImplemented, + toBytes: utils_js_1.notImplemented, + ShortSignature: { + fromHex: utils_js_1.notImplemented, + toRawBytes: utils_js_1.notImplemented, + toHex: utils_js_1.notImplemented, + }, + }, + G2: { + Fp: Fp2, + // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 + h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + Gx: Fp2.fromBigTuple([ + BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), + BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), + ]), + Gy: Fp2.fromBigTuple([ + BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), + BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), + ]), + a: Fp2.ZERO, + b: Fp2B, + hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P + mapToCurve: utils_js_1.notImplemented, + fromBytes: utils_js_1.notImplemented, + toBytes: utils_js_1.notImplemented, + Signature: { + fromHex: utils_js_1.notImplemented, + toRawBytes: utils_js_1.notImplemented, + toHex: utils_js_1.notImplemented, + }, + }, + params: { + ateLoopSize: BN_X * _6n + _2n, + r: Fr.ORDER, + xNegative: false, + twistType: 'divisive', + }, + htfDefaults, + hash: sha256_1.sha256, + randomBytes: utils_1.randomBytes, + postPrecompute: exports._postPrecompute, +}) +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + */ +exports.bn254_weierstrass = (0, weierstrass_js_1.weierstrass)({ + a: BigInt(0), + b: BigInt(3), + Fp, + n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), + Gx: BigInt(1), + Gy: BigInt(2), + h: BigInt(1), + ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), +}) +//# sourceMappingURL=bn254.js.map diff --git a/packages/noble-curves/bn254.js.map b/packages/noble-curves/bn254.js.map new file mode 100644 index 00000000000..7d179f56e3b --- /dev/null +++ b/packages/noble-curves/bn254.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bn254.js","sourceRoot":"","sources":["src/bn254.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/ed25519.d.ts b/packages/noble-curves/ed25519.d.ts new file mode 100644 index 00000000000..b7f9565cc9a --- /dev/null +++ b/packages/noble-curves/ed25519.d.ts @@ -0,0 +1,101 @@ +import { type AffinePoint, type Group } from './abstract/curve.js' +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' +import { type CurveFn as XCurveFn } from './abstract/montgomery.js' +import { type Hex } from './abstract/utils.js' +export declare const ED25519_TORSION_SUBGROUP: string[] +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export declare const ed25519: CurveFn +export declare const ed25519ctx: CurveFn +export declare const ed25519ph: CurveFn +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export declare const x25519: XCurveFn +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export declare function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array +export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export declare function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array +export declare const hashToCurve: HTFMethod +export declare const encodeToCurve: HTFMethod +type ExtendedPoint = ExtPointType +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +declare class RistPoint implements Group { + private readonly ep + static BASE: RistPoint + static ZERO: RistPoint + constructor(ep: ExtendedPoint) + static fromAffine(ap: AffinePoint): RistPoint + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex: Hex): RistPoint + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex: Hex): RistPoint + static msm(points: RistPoint[], scalars: bigint[]): RistPoint + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes(): Uint8Array + toHex(): string + toString(): string + equals(other: RistPoint): boolean + add(other: RistPoint): RistPoint + subtract(other: RistPoint): RistPoint + multiply(scalar: bigint): RistPoint + multiplyUnsafe(scalar: bigint): RistPoint + double(): RistPoint + negate(): RistPoint +} +export declare const RistrettoPoint: typeof RistPoint +export declare const hashToRistretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint +export declare const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint +export {} +//# sourceMappingURL=ed25519.d.ts.map diff --git a/packages/noble-curves/ed25519.d.ts.map b/packages/noble-curves/ed25519.d.ts.map new file mode 100644 index 00000000000..3f6674549f0 --- /dev/null +++ b/packages/noble-curves/ed25519.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["src/ed25519.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAa,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AAmE7B,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAS5C,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,OAAmE,CAAC;AAY1F,eAAO,MAAM,UAAU,EAAE,OAIlB,CAAC;AACR,eAAO,MAAM,SAAS,EAAE,OAMlB,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,EAAE,QAed,CAAC;AAER;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAIlE;AACD,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAG3E;AA0FD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AAiC5F,KAAK,aAAa,GAAG,YAAY,CAAC;AA0BlC;;;;;;GAMG;AACH,cAAM,SAAU,YAAW,KAAK,CAAC,SAAS,CAAC;IAK7B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;gBAGM,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS;IAIrD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IASvC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IA2BnC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;IAK7D;;;OAGG;IACH,UAAU,IAAI,UAAU;IA4BxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAKlB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAWjC,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKhC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAInC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAIzC,MAAM,IAAI,SAAS;IAInB,MAAM,IAAI,SAAS;CAGpB;AACD,eAAO,MAAM,cAAc,EAAE,OAAO,SAIhC,CAAC;AAGL,eAAO,MAAM,kBAAkB,QAAS,UAAU,WAAW,YAAY,KAAG,SAM3E,CAAC;AACF,eAAO,MAAM,oBAAoB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,KAAK,SAC3D,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/ed25519.js b/packages/noble-curves/ed25519.js new file mode 100644 index 00000000000..c585f99fa87 --- /dev/null +++ b/packages/noble-curves/ed25519.js @@ -0,0 +1,510 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.hash_to_ristretto255 = + exports.hashToRistretto255 = + exports.RistrettoPoint = + exports.encodeToCurve = + exports.hashToCurve = + exports.edwardsToMontgomery = + exports.x25519 = + exports.ed25519ph = + exports.ed25519ctx = + exports.ed25519 = + exports.ED25519_TORSION_SUBGROUP = + void 0 +exports.edwardsToMontgomeryPub = edwardsToMontgomeryPub +exports.edwardsToMontgomeryPriv = edwardsToMontgomeryPriv +/** + * ed25519 Twisted Edwards curve with following addons: + * - X25519 ECDH + * - Ristretto cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha512_1 = require('@noble/hashes/sha512') +const utils_1 = require('@noble/hashes/utils') +const curve_js_1 = require('./abstract/curve.js') +const edwards_js_1 = require('./abstract/edwards.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const montgomery_js_1 = require('./abstract/montgomery.js') +const utils_js_1 = require('./abstract/utils.js') +const ED25519_P = BigInt( + '57896044618658097711785492504343953926634992332820282019728792003956564819949', +) +// √(-1) aka √(a) aka 2^((p-1)/4) +const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( + '19681161376707505956807079304988542015446066515923890162744021073123829784752', +) +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// prettier-ignore +const _5n = BigInt(5), + _8n = BigInt(8) +function ed25519_pow_2_252_3(x) { + // prettier-ignore + const _10n = BigInt(10), + _20n = BigInt(20), + _40n = BigInt(40), + _80n = BigInt(80) + const P = ED25519_P + const x2 = (x * x) % P + const b2 = (x2 * x) % P // x^3, 11 + const b4 = ((0, modular_js_1.pow2)(b2, _2n, P) * b2) % P // x^15, 1111 + const b5 = ((0, modular_js_1.pow2)(b4, _1n, P) * x) % P // x^31 + const b10 = ((0, modular_js_1.pow2)(b5, _5n, P) * b5) % P + const b20 = ((0, modular_js_1.pow2)(b10, _10n, P) * b10) % P + const b40 = ((0, modular_js_1.pow2)(b20, _20n, P) * b20) % P + const b80 = ((0, modular_js_1.pow2)(b40, _40n, P) * b40) % P + const b160 = ((0, modular_js_1.pow2)(b80, _80n, P) * b80) % P + const b240 = ((0, modular_js_1.pow2)(b160, _80n, P) * b80) % P + const b250 = ((0, modular_js_1.pow2)(b240, _10n, P) * b10) % P + const pow_p_5_8 = ((0, modular_js_1.pow2)(b250, _2n, P) * x) % P + // ^ To pow to (p+3)/8, multiply it by x. + return { pow_p_5_8, b2 } +} +function adjustScalarBytes(bytes) { + // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, + // set the three least significant bits of the first byte + bytes[0] &= 248 // 0b1111_1000 + // and the most significant bit of the last to zero, + bytes[31] &= 127 // 0b0111_1111 + // set the second most significant bit of the last byte to 1 + bytes[31] |= 64 // 0b0100_0000 + return bytes +} +// sqrt(u/v) +function uvRatio(u, v) { + const P = ED25519_P + const v3 = (0, modular_js_1.mod)(v * v * v, P) // v³ + const v7 = (0, modular_js_1.mod)(v3 * v3 * v, P) // v⁷ + // (p+3)/8 and (p-5)/8 + const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 + let x = (0, modular_js_1.mod)(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 + const vx2 = (0, modular_js_1.mod)(v * x * x, P) // vx² + const root1 = x // First root candidate + const root2 = (0, modular_js_1.mod)(x * ED25519_SQRT_M1, P) // Second root candidate + const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root + const useRoot2 = vx2 === (0, modular_js_1.mod)(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) + const noRoot = vx2 === (0, modular_js_1.mod)(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) + if (useRoot1) x = root1 + if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time + if ((0, modular_js_1.isNegativeLE)(x, P)) x = (0, modular_js_1.mod)(-x, P) + return { isValid: useRoot1 || useRoot2, value: x } +} +// Just in case +exports.ED25519_TORSION_SUBGROUP = [ + '0100000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', + '0000000000000000000000000000000000000000000000000000000000000080', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', + '0000000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', +] +const Fp = /* @__PURE__ */ (() => (0, modular_js_1.Field)(ED25519_P, undefined, true))() +const ed25519Defaults = /* @__PURE__ */ (() => ({ + // Param: a + a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster + // d is equal to -121665/121666 over finite field. + // Negative number is P - number, and division is invert(number, P) + d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), + // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n + Fp, + // Subgroup order: how many points curve has + // 2n**252n + 27742317777372353535851937790883648493n; + n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), + // Cofactor + h: _8n, + // Base point (x, y) aka generator point + Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), + Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), + hash: sha512_1.sha512, + randomBytes: utils_1.randomBytes, + adjustScalarBytes, + // dom2 + // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. + // Constant-time, u/√v + uvRatio, +}))() +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +exports.ed25519 = (() => (0, edwards_js_1.twistedEdwards)(ed25519Defaults))() +function ed25519_domain(data, ctx, phflag) { + if (ctx.length > 255) throw new Error('Context is too big') + return (0, utils_1.concatBytes)( + (0, utils_1.utf8ToBytes)('SigEd25519 no Ed25519 collisions'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) +} +exports.ed25519ctx = (() => + (0, edwards_js_1.twistedEdwards)({ + ...ed25519Defaults, + domain: ed25519_domain, + }))() +exports.ed25519ph = (() => + (0, edwards_js_1.twistedEdwards)( + Object.assign({}, ed25519Defaults, { + domain: ed25519_domain, + prehash: sha512_1.sha512, + }), + ))() +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +exports.x25519 = (() => + (0, montgomery_js_1.montgomery)({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x) => { + const P = ED25519_P + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) + return (0, modular_js_1.mod)((0, modular_js_1.pow2)(pow_p_5_8, _3n, P) * b2, P) + }, + adjustScalarBytes, + randomBytes: utils_1.randomBytes, + }))() +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +function edwardsToMontgomeryPub(edwardsPub) { + const { y } = exports.ed25519.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) +} +exports.edwardsToMontgomery = edwardsToMontgomeryPub // deprecated +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +function edwardsToMontgomeryPriv(edwardsPriv) { + const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) + return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) +} +// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) +// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since +// SageMath returns different root first and everything falls apart +const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic +const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 +const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) +// prettier-ignore +function map_to_curve_elligator2_curve25519(u) { + const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic + const ELL2_J = BigInt(486662) + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 + let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not + let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) + let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 + tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 + tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 + tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 + tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 + let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) + y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) + let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 + tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 + tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd + let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 + let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt + let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd + let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u + y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 + let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 + let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) + tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 + tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 + let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt + tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd + let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 + let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) +} +const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => + (0, modular_js_1.FpSqrtEven)(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 +function map_to_curve_elligator2_edwards25519(u) { + const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = + // map_to_curve_elligator2_curve25519(u) + let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd + xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 + let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM + let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd + let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) + let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd + let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 + xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) + xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) + yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) + yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) + const inv = Fp.invertBatch([xd, yd]) // batch division + return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) +} +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.ed25519.ExtendedPoint, + (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512_1.sha512, + }, + ))() +exports.hashToCurve = (() => htf.hashToCurve)() +exports.encodeToCurve = (() => htf.encodeToCurve)() +function assertRstPoint(other) { + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') +} +// √(-1) aka √(a) aka 2^((p-1)/4) +const SQRT_M1 = ED25519_SQRT_M1 +// √(ad - 1) +const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( + '25063068953384623474111414158702152701244531502492656460079210482610430750235', +) +// 1 / √(a-d) +const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( + '54469307008909316920995813868745141605393597292927456921205312896311721017578', +) +// 1-d² +const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( + '1159843021668779879193775521855586647937357759715417654439879720876111806838', +) +// (d-1)² +const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( + '40440834346308536858101042469323190826248399146238708352240133220865137265952', +) +// Calculates 1/√(number) +const invertSqrt = (number) => uvRatio(_1n, number) +const MAX_255B = /* @__PURE__ */ BigInt( + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes255ToNumberLE = (bytes) => + exports.ed25519.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B) +// Computes Elligator map for Ristretto +// https://ristretto.group/formulas/elligator.html +function calcElligatorRistrettoMap(r0) { + const { d } = exports.ed25519.CURVE + const P = exports.ed25519.CURVE.Fp.ORDER + const mod = exports.ed25519.CURVE.Fp.create + const r = mod(SQRT_M1 * r0 * r0) // 1 + const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 + let c = BigInt(-1) // 3 + const D = mod((c - d * r) * mod(r + d)) // 4 + let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 + let s_ = mod(s * r0) // 6 + if (!(0, modular_js_1.isNegativeLE)(s_, P)) s_ = mod(-s_) + if (!Ns_D_is_sq) s = s_ // 7 + if (!Ns_D_is_sq) c = r // 8 + const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 + const s2 = s * s + const W0 = mod((s + s) * D) // 10 + const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 + const W2 = mod(_1n - s2) // 12 + const W3 = mod(_1n + s2) // 13 + return new exports.ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class RistPoint { + // Private property to discourage combining ExtendedPoint + RistrettoPoint + // Always use Ristretto encoding/decoding instead. + constructor(ep) { + this.ep = ep + } + static fromAffine(ap) { + return new RistPoint(exports.ed25519.ExtendedPoint.fromAffine(ap)) + } + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex) { + hex = (0, utils_js_1.ensureBytes)('ristrettoHash', hex, 64) + const r1 = bytes255ToNumberLE(hex.slice(0, 32)) + const R1 = calcElligatorRistrettoMap(r1) + const r2 = bytes255ToNumberLE(hex.slice(32, 64)) + const R2 = calcElligatorRistrettoMap(r2) + return new RistPoint(R1.add(R2)) + } + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex) { + hex = (0, utils_js_1.ensureBytes)('ristrettoHex', hex, 32) + const { a, d } = exports.ed25519.CURVE + const P = exports.ed25519.CURVE.Fp.ORDER + const mod = exports.ed25519.CURVE.Fp.create + const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' + const s = bytes255ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 3. Check that s is non-negative, or else abort + if ( + !(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 32), hex) || + (0, modular_js_1.isNegativeLE)(s, P) + ) + throw new Error(emsg) + const s2 = mod(s * s) + const u1 = mod(_1n + a * s2) // 4 (a is -1) + const u2 = mod(_1n - a * s2) // 5 + const u1_2 = mod(u1 * u1) + const u2_2 = mod(u2 * u2) + const v = mod(a * d * u1_2 - u2_2) // 6 + const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 + const Dx = mod(I * u2) // 8 + const Dy = mod(I * Dx * v) // 9 + let x = mod((s + s) * Dx) // 10 + if ((0, modular_js_1.isNegativeLE)(x, P)) x = mod(-x) // 10 + const y = mod(u1 * Dy) // 11 + const t = mod(x * y) // 12 + if (!isValid || (0, modular_js_1.isNegativeLE)(t, P) || y === _0n) throw new Error(emsg) + return new RistPoint(new exports.ed25519.ExtendedPoint(x, y, _1n, t)) + } + static msm(points, scalars) { + const Fn = (0, modular_js_1.Field)(exports.ed25519.CURVE.n, exports.ed25519.CURVE.nBitLength) + return (0, curve_js_1.pippenger)(RistPoint, Fn, points, scalars) + } + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes() { + let { ex: x, ey: y, ez: z, et: t } = this.ep + const P = exports.ed25519.CURVE.Fp.ORDER + const mod = exports.ed25519.CURVE.Fp.create + const u1 = mod(mod(z + y) * mod(z - y)) // 1 + const u2 = mod(x * y) // 2 + // Square root always exists + const u2sq = mod(u2 * u2) + const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 + const D1 = mod(invsqrt * u1) // 4 + const D2 = mod(invsqrt * u2) // 5 + const zInv = mod(D1 * D2 * t) // 6 + let D // 7 + if ((0, modular_js_1.isNegativeLE)(t * zInv, P)) { + let _x = mod(y * SQRT_M1) + let _y = mod(x * SQRT_M1) + x = _x + y = _y + D = mod(D1 * INVSQRT_A_MINUS_D) + } else { + D = D2 // 8 + } + if ((0, modular_js_1.isNegativeLE)(x * zInv, P)) y = mod(-y) // 9 + let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) + if ((0, modular_js_1.isNegativeLE)(s, P)) s = mod(-s) + return (0, utils_js_1.numberToBytesLE)(s, 32) // 11 + } + toHex() { + return (0, utils_js_1.bytesToHex)(this.toRawBytes()) + } + toString() { + return this.toHex() + } + // Compare one point to another. + equals(other) { + assertRstPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = exports.ed25519.CURVE.Fp.create + // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) + const one = mod(X1 * Y2) === mod(Y1 * X2) + const two = mod(Y1 * Y2) === mod(X1 * X2) + return one || two + } + add(other) { + assertRstPoint(other) + return new RistPoint(this.ep.add(other.ep)) + } + subtract(other) { + assertRstPoint(other) + return new RistPoint(this.ep.subtract(other.ep)) + } + multiply(scalar) { + return new RistPoint(this.ep.multiply(scalar)) + } + multiplyUnsafe(scalar) { + return new RistPoint(this.ep.multiplyUnsafe(scalar)) + } + double() { + return new RistPoint(this.ep.double()) + } + negate() { + return new RistPoint(this.ep.negate()) + } +} +exports.RistrettoPoint = (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(exports.ed25519.ExtendedPoint.BASE) + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(exports.ed25519.ExtendedPoint.ZERO) + return RistPoint +})() +// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B +const hashToRistretto255 = (msg, options) => { + const d = options.DST + const DST = typeof d === 'string' ? (0, utils_1.utf8ToBytes)(d) : d + const uniform_bytes = (0, hash_to_curve_js_1.expand_message_xmd)(msg, DST, 64, sha512_1.sha512) + const P = RistPoint.hashToCurve(uniform_bytes) + return P +} +exports.hashToRistretto255 = hashToRistretto255 +exports.hash_to_ristretto255 = exports.hashToRistretto255 // legacy +//# sourceMappingURL=ed25519.js.map diff --git a/packages/noble-curves/ed25519.js.map b/packages/noble-curves/ed25519.js.map new file mode 100644 index 00000000000..57fa3ea2c9b --- /dev/null +++ b/packages/noble-curves/ed25519.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["src/ed25519.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/ed448.d.ts b/packages/noble-curves/ed448.d.ts new file mode 100644 index 00000000000..82ac0fb743e --- /dev/null +++ b/packages/noble-curves/ed448.d.ts @@ -0,0 +1,82 @@ +import type { AffinePoint, Group } from './abstract/curve.js' +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' +import { type CurveFn as XCurveFn } from './abstract/montgomery.js' +import { type Hex } from './abstract/utils.js' +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export declare const ed448: CurveFn +export declare const ed448ph: CurveFn +/** + * ECDH using curve448 aka x448. + */ +export declare const x448: XCurveFn +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export declare function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array +export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub +export declare const hashToCurve: HTFMethod +export declare const encodeToCurve: HTFMethod +type ExtendedPoint = ExtPointType +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +declare class DcfPoint implements Group { + private readonly ep + static BASE: DcfPoint + static ZERO: DcfPoint + constructor(ep: ExtendedPoint) + static fromAffine(ap: AffinePoint): DcfPoint + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex: Hex): DcfPoint + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex: Hex): DcfPoint + static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes(): Uint8Array + toHex(): string + toString(): string + equals(other: DcfPoint): boolean + add(other: DcfPoint): DcfPoint + subtract(other: DcfPoint): DcfPoint + multiply(scalar: bigint): DcfPoint + multiplyUnsafe(scalar: bigint): DcfPoint + double(): DcfPoint + negate(): DcfPoint +} +export declare const DecafPoint: typeof DcfPoint +export declare const hashToDecaf448: (msg: Uint8Array, options: htfBasicOpts) => DcfPoint +export declare const hash_to_decaf448: typeof hashToDecaf448 +export {} +//# sourceMappingURL=ed448.d.ts.map diff --git a/packages/noble-curves/ed448.d.ts.map b/packages/noble-curves/ed448.d.ts.map new file mode 100644 index 00000000000..c8d1f0ab571 --- /dev/null +++ b/packages/noble-curves/ed448.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ed448.d.ts","sourceRoot":"","sources":["src/ed448.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AA8G7B;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,EAAE,OAAmD,CAAC;AAExE,eAAO,MAAM,OAAO,EAAE,OAGpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,QAgBZ,CAAC;AAER;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAIlF;AAED,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AA8FzF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AA2B5F,KAAK,aAAa,GAAG,YAAY,CAAC;AAiClC;;;;;;GAMG;AACH,cAAM,QAAS,YAAW,KAAK,CAAC,QAAQ,CAAC;IAK3B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;IACtB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAGO,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,QAAQ;IAIpD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAStC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IA8BlC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ;IAK3D;;;OAGG;IACH,UAAU,IAAI,UAAU;IAoBxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAMlB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAShC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAK9B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIlC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIxC,MAAM,IAAI,QAAQ;IAIlB,MAAM,IAAI,QAAQ;CAGnB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,QAM5B,CAAC;AAGL,eAAO,MAAM,cAAc,QAAS,UAAU,WAAW,YAAY,KAAG,QAMvE,CAAC;AACF,eAAO,MAAM,gBAAgB,EAAE,OAAO,cAA+B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/ed448.js b/packages/noble-curves/ed448.js new file mode 100644 index 00000000000..528f4d47d39 --- /dev/null +++ b/packages/noble-curves/ed448.js @@ -0,0 +1,470 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.hash_to_decaf448 = + exports.hashToDecaf448 = + exports.DecafPoint = + exports.encodeToCurve = + exports.hashToCurve = + exports.edwardsToMontgomery = + exports.x448 = + exports.ed448ph = + exports.ed448 = + void 0 +exports.edwardsToMontgomeryPub = edwardsToMontgomeryPub +/** + * Edwards448 (not Ed448-Goldilocks) curve with following addons: + * - X448 ECDH + * - Decaf cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha3_1 = require('@noble/hashes/sha3') +const utils_1 = require('@noble/hashes/utils') +const curve_js_1 = require('./abstract/curve.js') +const edwards_js_1 = require('./abstract/edwards.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const montgomery_js_1 = require('./abstract/montgomery.js') +const utils_js_1 = require('./abstract/utils.js') +const shake256_114 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 114 })) +const shake256_64 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 64 })) +const ed448P = BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', +) +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4), + _11n = BigInt(11) +// prettier-ignore +const _22n = BigInt(22), + _44n = BigInt(44), + _88n = BigInt(88), + _223n = BigInt(223) +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +// Used for efficient square root calculation. +// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] +function ed448_pow_Pminus3div4(x) { + const P = ed448P + const b2 = (x * x * x) % P + const b3 = (b2 * b2 * x) % P + const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P + const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P + const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P + const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P + const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P + const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P + const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P + const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P + const b222 = ((0, modular_js_1.pow2)(b220, _2n, P) * b2) % P + const b223 = ((0, modular_js_1.pow2)(b222, _1n, P) * x) % P + return ((0, modular_js_1.pow2)(b223, _223n, P) * b222) % P +} +function adjustScalarBytes(bytes) { + // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most + // significant bit of the last byte to 1. + bytes[0] &= 252 // 0b11111100 + // and the most significant bit of the last byte to 1. + bytes[55] |= 128 // 0b10000000 + // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) + bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) + return bytes +} +// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. +// Uses algo from RFC8032 5.1.3. +function uvRatio(u, v) { + const P = ed448P + // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 + // To compute the square root of (u/v), the first step is to compute the + // candidate root x = (u/v)^((p+1)/4). This can be done using the + // following trick, to use a single modular powering for both the + // inversion of v and the square root: + // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) + const u2v = (0, modular_js_1.mod)(u * u * v, P) // u²v + const u3v = (0, modular_js_1.mod)(u2v * u, P) // u³v + const u5v3 = (0, modular_js_1.mod)(u3v * u2v * v, P) // u⁵v³ + const root = ed448_pow_Pminus3div4(u5v3) + const x = (0, modular_js_1.mod)(u3v * root, P) + // Verify that root is exists + const x2 = (0, modular_js_1.mod)(x * x, P) // x² + // If vx² = u, the recovered x-coordinate is x. Otherwise, no + // square root exists, and the decoding fails. + return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x } +} +const Fp = (0, modular_js_1.Field)(ed448P, 456, true) +const ED448_DEF = { + // Param: a + a: BigInt(1), + // -39081. Negative number is P - number + d: BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', + ), + // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n + Fp, + // Subgroup order: how many points curve has; + // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n + n: BigInt( + '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', + ), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + nBitLength: 456, + // Cofactor + h: BigInt(4), + // Base point (x, y) aka generator point + Gx: BigInt( + '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', + ), + Gy: BigInt( + '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', + ), + // SHAKE256(dom4(phflag,context)||x, 114) + hash: shake256_114, + randomBytes: utils_1.randomBytes, + adjustScalarBytes, + // dom4 + domain: (data, ctx, phflag) => { + if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) + return (0, utils_1.concatBytes)( + (0, utils_1.utf8ToBytes)('SigEd448'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) + }, + uvRatio, +} +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF) +// NOTE: there is no ed448ctx, since ed448 supports ctx by default +exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ + ...ED448_DEF, + prehash: shake256_64, +}) +/** + * ECDH using curve448 aka x448. + */ +exports.x448 = (() => + (0, montgomery_js_1.montgomery)({ + a: BigInt(156326), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + montgomeryBits: 448, + nByteLength: 56, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x) => { + const P = ed448P + const Pminus3div4 = ed448_pow_Pminus3div4(x) + const Pminus3 = (0, modular_js_1.pow2)(Pminus3div4, BigInt(2), P) + return (0, modular_js_1.mod)(Pminus3 * x, P) // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes: utils_1.randomBytes, + }))() +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +function edwardsToMontgomeryPub(edwardsPub) { + const { y } = exports.ed448.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) +} +exports.edwardsToMontgomery = edwardsToMontgomeryPub // deprecated +// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version +// Hash To Curve Elligator2 Map +const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic +const ELL2_J = BigInt(156326) +function map_to_curve_elligator2_curve448(u) { + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 + tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 + let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 + let x1n = Fp.neg(ELL2_J) // 5. x1n = -J + let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 + tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd + tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 + let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) + y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) + let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd + let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u + y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) + tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 + let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) + return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) +} +function map_to_curve_elligator2_edwards448(u) { + let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) + let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 + let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 + let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 + let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 + let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 + let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 + let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 + xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 + xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd + xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn + xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 + tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 + tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 + let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 + let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 + tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 + let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 + tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn + let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 + let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 + yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 + yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 + tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 + tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 + tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd + tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 + tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 + let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 + tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 + yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 + tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd + let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 + xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) + xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) + yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) + yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) + const inv = Fp.invertBatch([xEd, yEd]) // batch division + return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) +} +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.ed448.ExtendedPoint, + (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), + { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: sha3_1.shake256, + }, + ))() +exports.hashToCurve = (() => htf.hashToCurve)() +exports.encodeToCurve = (() => htf.encodeToCurve)() +function assertDcfPoint(other) { + if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') +} +// 1-d +const ONE_MINUS_D = BigInt('39082') +// 1-2d +const ONE_MINUS_TWO_D = BigInt('78163') +// √(-d) +const SQRT_MINUS_D = BigInt( + '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', +) +// 1 / √(-d) +const INVSQRT_MINUS_D = BigInt( + '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', +) +// Calculates 1/√(number) +const invertSqrt = (number) => uvRatio(_1n, number) +const MAX_448B = BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes448ToNumberLE = (bytes) => + exports.ed448.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_448B) +// Computes Elligator map for Decaf +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 +function calcElligatorDecafMap(r0) { + const { d } = exports.ed448.CURVE + const P = exports.ed448.CURVE.Fp.ORDER + const mod = exports.ed448.CURVE.Fp.create + const r = mod(-(r0 * r0)) // 1 + const u0 = mod(d * (r - _1n)) // 2 + const u1 = mod((u0 + _1n) * (u0 - r)) // 3 + const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 + let v_prime = v // 5 + if (!was_square) v_prime = mod(r0 * v) + let sgn = _1n // 6 + if (!was_square) sgn = mod(-_1n) + const s = mod(v_prime * (r + _1n)) // 7 + let s_abs = s + if ((0, modular_js_1.isNegativeLE)(s, P)) s_abs = mod(-s) + const s2 = s * s + const W0 = mod(s_abs * _2n) // 8 + const W1 = mod(s2 + _1n) // 9 + const W2 = mod(s2 - _1n) // 10 + const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 + return new exports.ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class DcfPoint { + // Private property to discourage combining ExtendedPoint + DecafPoint + // Always use Decaf encoding/decoding instead. + constructor(ep) { + this.ep = ep + } + static fromAffine(ap) { + return new DcfPoint(exports.ed448.ExtendedPoint.fromAffine(ap)) + } + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex) { + hex = (0, utils_js_1.ensureBytes)('decafHash', hex, 112) + const r1 = bytes448ToNumberLE(hex.slice(0, 56)) + const R1 = calcElligatorDecafMap(r1) + const r2 = bytes448ToNumberLE(hex.slice(56, 112)) + const R2 = calcElligatorDecafMap(r2) + return new DcfPoint(R1.add(R2)) + } + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex) { + hex = (0, utils_js_1.ensureBytes)('decafHex', hex, 56) + const { d } = exports.ed448.CURVE + const P = exports.ed448.CURVE.Fp.ORDER + const mod = exports.ed448.CURVE.Fp.create + const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' + const s = bytes448ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 2. Check that s is non-negative, or else abort + if ( + !(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 56), hex) || + (0, modular_js_1.isNegativeLE)(s, P) + ) + throw new Error(emsg) + const s2 = mod(s * s) // 1 + const u1 = mod(_1n + s2) // 2 + const u1sq = mod(u1 * u1) + const u2 = mod(u1sq - _4n * d * s2) // 3 + const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 + let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 + if ((0, modular_js_1.isNegativeLE)(u3, P)) u3 = mod(-u3) + const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 + const y = mod((_1n - s2) * invsqrt * u1) // 7 + const t = mod(x * y) // 8 + if (!isValid) throw new Error(emsg) + return new DcfPoint(new exports.ed448.ExtendedPoint(x, y, _1n, t)) + } + static msm(points, scalars) { + const Fn = (0, modular_js_1.Field)(exports.ed448.CURVE.n, exports.ed448.CURVE.nBitLength) + return (0, curve_js_1.pippenger)(DcfPoint, Fn, points, scalars) + } + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes() { + let { ex: x, ey: _y, ez: z, et: t } = this.ep + const P = exports.ed448.CURVE.Fp.ORDER + const mod = exports.ed448.CURVE.Fp.create + const u1 = mod(mod(x + t) * mod(x - t)) // 1 + const x2 = mod(x * x) + const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 + let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 + if ((0, modular_js_1.isNegativeLE)(ratio, P)) ratio = mod(-ratio) + const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 + let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 + if ((0, modular_js_1.isNegativeLE)(s, P)) s = mod(-s) + return (0, utils_js_1.numberToBytesLE)(s, 56) + } + toHex() { + return (0, utils_js_1.bytesToHex)(this.toRawBytes()) + } + toString() { + return this.toHex() + } + // Compare one point to another. + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 + equals(other) { + assertDcfPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = exports.ed448.CURVE.Fp.create + // (x1 * y2 == y1 * x2) + return mod(X1 * Y2) === mod(Y1 * X2) + } + add(other) { + assertDcfPoint(other) + return new DcfPoint(this.ep.add(other.ep)) + } + subtract(other) { + assertDcfPoint(other) + return new DcfPoint(this.ep.subtract(other.ep)) + } + multiply(scalar) { + return new DcfPoint(this.ep.multiply(scalar)) + } + multiplyUnsafe(scalar) { + return new DcfPoint(this.ep.multiplyUnsafe(scalar)) + } + double() { + return new DcfPoint(this.ep.double()) + } + negate() { + return new DcfPoint(this.ep.negate()) + } +} +exports.DecafPoint = (() => { + // decaf448 base point is ed448 base x 2 + // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 + if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(exports.ed448.ExtendedPoint.BASE).multiply(_2n) + if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(exports.ed448.ExtendedPoint.ZERO) + return DcfPoint +})() +// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C +const hashToDecaf448 = (msg, options) => { + const d = options.DST + const DST = typeof d === 'string' ? (0, utils_1.utf8ToBytes)(d) : d + const uniform_bytes = (0, hash_to_curve_js_1.expand_message_xof)( + msg, + DST, + 112, + 224, + sha3_1.shake256, + ) + const P = DcfPoint.hashToCurve(uniform_bytes) + return P +} +exports.hashToDecaf448 = hashToDecaf448 +exports.hash_to_decaf448 = exports.hashToDecaf448 // legacy +//# sourceMappingURL=ed448.js.map diff --git a/packages/noble-curves/ed448.js.map b/packages/noble-curves/ed448.js.map new file mode 100644 index 00000000000..75d39454acb --- /dev/null +++ b/packages/noble-curves/ed448.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ed448.js","sourceRoot":"","sources":["src/ed448.ts"],"names":[],"mappings":";;;AAyLA,wDAIC;AA7LD;;;;;;;GAOG;AACH,sEAAsE;AACtE,6CAA8C;AAC9C,+CAA6F;AAE7F,kDAAgD;AAChD,sDAAwF;AACxF,kEAKqC;AACrC,sDAAuE;AACvE,4DAAgF;AAChF,kDAO6B;AAE7B,MAAM,YAAY,GAAG,IAAA,uBAAe,EAAC,GAAG,EAAE,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAC5E,MAAM,WAAW,GAAG,IAAA,uBAAe,EAAC,GAAG,EAAE,CAAC,eAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC1E,MAAM,MAAM,GAAG,MAAM,CACnB,yIAAyI,CAC1I,CAAC;AAEF,kBAAkB;AAClB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;AAC5F,kBAAkB;AAClB,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AAEnF,8DAA8D;AAC9D,8CAA8C;AAC9C,+DAA+D;AAC/D,SAAS,qBAAqB,CAAC,CAAS;IACtC,MAAM,CAAC,GAAG,MAAM,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAiB;IAC1C,yGAAyG;IACzG,yCAAyC;IACzC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,aAAa;IAC9B,sDAAsD;IACtD,KAAK,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,aAAa;IAC/B,sDAAsD;IACtD,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,+CAA+C;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mFAAmF;AACnF,gCAAgC;AAChC,SAAS,OAAO,CAAC,CAAS,EAAE,CAAS;IACnC,MAAM,CAAC,GAAG,MAAM,CAAC;IACjB,uDAAuD;IACvD,wEAAwE;IACxE,oEAAoE;IACpE,iEAAiE;IACjE,sCAAsC;IACtC,wDAAwD;IACxD,MAAM,GAAG,GAAG,IAAA,gBAAG,EAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM;IACrC,MAAM,GAAG,GAAG,IAAA,gBAAG,EAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM;IACnC,MAAM,IAAI,GAAG,IAAA,gBAAG,EAAC,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;IAC3C,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,IAAA,gBAAG,EAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7B,6BAA6B;IAC7B,MAAM,EAAE,GAAG,IAAA,gBAAG,EAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;IAC/B,8DAA8D;IAC9D,8CAA8C;IAC9C,OAAO,EAAE,OAAO,EAAE,IAAA,gBAAG,EAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,EAAE,GAAG,IAAA,kBAAK,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AAEpC,MAAM,SAAS,GAAG;IAChB,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,CAAC,EAAE,MAAM,CACP,yIAAyI,CAC1I;IACD,8EAA8E;IAC9E,EAAE;IACF,6CAA6C;IAC7C,mFAAmF;IACnF,CAAC,EAAE,MAAM,CACP,yIAAyI,CAC1I;IACD,uDAAuD;IACvD,UAAU,EAAE,GAAG;IACf,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,EAAE,EAAE,MAAM,CACR,yIAAyI,CAC1I;IACD,EAAE,EAAE,MAAM,CACR,yIAAyI,CAC1I;IACD,yCAAyC;IACzC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAX,mBAAW;IACX,iBAAiB;IACjB,OAAO;IACP,MAAM,EAAE,CAAC,IAAgB,EAAE,GAAe,EAAE,MAAe,EAAE,EAAE;QAC7D,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9F,OAAO,IAAA,mBAAW,EAChB,IAAA,mBAAW,EAAC,UAAU,CAAC,EACvB,IAAI,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAC5C,GAAG,EACH,IAAI,CACL,CAAC;IACJ,CAAC;IACD,OAAO;CACC,CAAC;AAEX;;;;;;;;;GASG;AACU,QAAA,KAAK,GAA4B,IAAA,2BAAc,EAAC,SAAS,CAAC,CAAC;AACxE,kEAAkE;AACrD,QAAA,OAAO,GAA4B,IAAA,2BAAc,EAAC;IAC7D,GAAG,SAAS;IACZ,OAAO,EAAE,WAAW;CACrB,CAAC,CAAC;AAEH;;GAEG;AACU,QAAA,IAAI,GAA6B,CAAC,GAAG,EAAE,CAClD,IAAA,0BAAU,EAAC;IACT,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC;IACjB,uDAAuD;IACvD,cAAc,EAAE,GAAG;IACnB,WAAW,EAAE,EAAE;IACf,CAAC,EAAE,MAAM;IACT,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,UAAU,EAAE,CAAC,CAAS,EAAU,EAAE;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC;QACjB,MAAM,WAAW,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAA,iBAAI,EAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAChD,OAAO,IAAA,gBAAG,EAAC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,wBAAwB;IACtD,CAAC;IACD,iBAAiB;IACjB,WAAW,EAAX,mBAAW;CACZ,CAAC,CAAC,EAAE,CAAC;AAER;;;;;;;GAOG;AACH,SAAgB,sBAAsB,CAAC,UAA+B;IACpE,MAAM,EAAE,CAAC,EAAE,GAAG,aAAK,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAEY,QAAA,mBAAmB,GAAkC,sBAAsB,CAAC,CAAC,aAAa;AACvG,gEAAgE;AAEhE,+BAA+B;AAC/B,MAAM,OAAO,GAAG,CAAC,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mDAAmD;AACvG,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE9B,SAAS,gCAAgC,CAAC,CAAS;IACjD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB;IACrC,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,qBAAqB;IACnD,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,8DAA8D;IAC/F,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAClD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe;IACzC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,2CAA2C;IACtE,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,6CAA6C;IACpF,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,qDAAqD;IAC7E,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,4DAA4D;IACpF,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,oEAAoE;IAC5F,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB;IACzC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,0CAA0C;IAClE,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,4CAA4C;IACpE,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,4DAA4D;IAC3F,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,wEAAwE;IAC9F,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,oEAAoE;IACxG,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,mBAAmB;IAC3C,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,4BAA4B;IAC3D,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACnC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,uBAAuB;IAClD,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,6DAA6D;IAC7F,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,6DAA6D;IAC1F,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,gDAAgD;IACtE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,mCAAmC;IACzE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,4BAA4B;AACpE,CAAC;AAED,SAAS,kCAAkC,CAAC,CAAS;IACnD,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,gCAAgC,CAAC,CAAC,CAAC,CAAC,CAAC,4DAA4D;IAC1H,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB;IACzC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB;IAC5C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB;IAC5C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAC5C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,oBAAoB;IAChD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB;IAC5C,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,qBAAqB;IAChD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB;IAC5C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB;IACpD,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAClD,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,sBAAsB;IAC9C,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB;IACnD,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAC5D,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAC3D,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAC3D,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAE3D,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB;IACzD,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,kCAAkC;AAC/F,CAAC;AAED,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EACV,aAAK,CAAC,aAAa,EACnB,CAAC,OAAiB,EAAE,EAAE,CAAC,kCAAkC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EACrE;IACE,GAAG,EAAE,kCAAkC;IACvC,SAAS,EAAE,kCAAkC;IAC7C,CAAC,EAAE,EAAE,CAAC,KAAK;IACX,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAQ;CACf,CACF,CAAC,EAAE,CAAC;AACM,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AAC3E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;AAE5F,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM;AACN,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AACpC,OAAO;AACP,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;AACxC,QAAQ;AACR,MAAM,YAAY,GAAG,MAAM,CACzB,wIAAwI,CACzI,CAAC;AACF,YAAY;AACZ,MAAM,eAAe,GAAG,MAAM,CAC5B,yIAAyI,CAC1I,CAAC;AACF,yBAAyB;AACzB,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAE5D,MAAM,QAAQ,GAAG,MAAM,CACrB,oHAAoH,CACrH,CAAC;AACF,MAAM,kBAAkB,GAAG,CAAC,KAAiB,EAAE,EAAE,CAC/C,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAA,0BAAe,EAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,CAAC;AAI3D,mCAAmC;AACnC,2GAA2G;AAC3G,SAAS,qBAAqB,CAAC,EAAU;IACvC,MAAM,EAAE,CAAC,EAAE,GAAG,aAAK,CAAC,KAAK,CAAC;IAC1B,MAAM,CAAC,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;IAC/B,MAAM,GAAG,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;IAElC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;IAC/B,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;IACnC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;IAE3C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;IAE7F,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI;IACrB,IAAI,CAAC,UAAU;QAAE,OAAO,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAEvC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI;IACnB,IAAI,CAAC,UAAU;QAAE,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAEjC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,IAAA,yBAAY,EAAC,CAAC,EAAE,CAAC,CAAC;QAAE,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAExC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI;IACjC,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI;IAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK;IAC/B,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK;IACtE,OAAO,IAAI,aAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,QAAQ;IAGZ,sEAAsE;IACtE,8CAA8C;IAC9C,YAA6B,EAAiB;QAAjB,OAAE,GAAF,EAAE,CAAe;IAAG,CAAC;IAElD,MAAM,CAAC,UAAU,CAAC,EAAuB;QACvC,OAAO,IAAI,QAAQ,CAAC,aAAK,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAQ;QACzB,GAAG,GAAG,IAAA,sBAAW,EAAC,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACzC,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACrC,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAQ;QACrB,GAAG,GAAG,IAAA,sBAAW,EAAC,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACvC,MAAM,EAAE,CAAC,EAAE,GAAG,aAAK,CAAC,KAAK,CAAC;QAC1B,MAAM,CAAC,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;QAC/B,MAAM,GAAG,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;QAClC,MAAM,IAAI,GAAG,iEAAiE,CAAC;QAC/E,MAAM,CAAC,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAElC,qFAAqF;QACrF,iDAAiD;QACjD,IAAI,CAAC,IAAA,qBAAU,EAAC,IAAA,0BAAe,EAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,IAAA,yBAAY,EAAC,CAAC,EAAE,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;QAE1F,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;QAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1B,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;QAEzC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAEpE,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI;QACzD,IAAI,IAAA,yBAAY,EAAC,EAAE,EAAE,CAAC,CAAC;YAAE,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAEvC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,OAAO,GAAG,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI;QACxD,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;QAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QAE1B,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,IAAI,QAAQ,CAAC,IAAI,aAAK,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,MAAkB,EAAE,OAAiB;QAC9C,MAAM,EAAE,GAAG,IAAA,kBAAK,EAAC,aAAK,CAAC,KAAK,CAAC,CAAC,EAAE,aAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACxD,OAAO,IAAA,oBAAS,EAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;QAC/B,MAAM,GAAG,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;QAElC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;QAC7C,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;QAEvE,IAAI,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI;QAClD,IAAI,IAAA,yBAAY,EAAC,KAAK,EAAE,CAAC,CAAC;YAAE,KAAK,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAEhD,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QAErD,IAAI,CAAC,GAAG,GAAG,CAAC,WAAW,GAAG,OAAO,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;QACjD,IAAI,IAAA,yBAAY,EAAC,CAAC,EAAE,CAAC,CAAC;YAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpC,OAAO,IAAA,0BAAe,EAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,OAAO,IAAA,qBAAU,EAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,gCAAgC;IAChC,+FAA+F;IAC/F,MAAM,CAAC,KAAe;QACpB,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,aAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;QAClC,uBAAuB;QACvB,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,GAAG,CAAC,KAAe;QACjB,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,QAAQ,CAAC,KAAe;QACtB,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,QAAQ,CAAC,MAAc;QACrB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;CACF;AAEY,QAAA,UAAU,GAAoC,CAAC,GAAG,EAAE;IAC/D,wCAAwC;IACxC,kIAAkI;IAClI,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzF,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3E,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC,EAAE,CAAC;AAEL,yEAAyE;AAClE,MAAM,cAAc,GAAG,CAAC,GAAe,EAAE,OAAqB,EAAY,EAAE;IACjF,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAA,mBAAW,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,IAAA,qCAAkB,EAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,eAAQ,CAAC,CAAC;IACvE,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAC9C,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AANW,QAAA,cAAc,kBAMzB;AACW,QAAA,gBAAgB,GAA0B,sBAAc,CAAC,CAAC,SAAS"} \ No newline at end of file diff --git a/packages/noble-curves/esm/_shortw_utils.d.ts b/packages/noble-curves/esm/_shortw_utils.d.ts new file mode 100644 index 00000000000..02064fbb558 --- /dev/null +++ b/packages/noble-curves/esm/_shortw_utils.d.ts @@ -0,0 +1,16 @@ +import { randomBytes } from '@noble/hashes/utils' +import type { CHash } from './abstract/utils.js' +import { type CurveFn, type CurveType } from './abstract/weierstrass.js' +/** connects noble-curves to noble-hashes */ +export declare function getHash(hash: CHash): { + hash: CHash + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array + randomBytes: typeof randomBytes +} +/** Same API as @noble/hashes, with ability to create curve with custom hash */ +export type CurveDef = Readonly> +export type CurveFnWithCreate = CurveFn & { + create: (hash: CHash) => CurveFn +} +export declare function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate +//# sourceMappingURL=_shortw_utils.d.ts.map diff --git a/packages/noble-curves/esm/_shortw_utils.d.ts.map b/packages/noble-curves/esm/_shortw_utils.d.ts.map new file mode 100644 index 00000000000..aed6a3c4299 --- /dev/null +++ b/packages/noble-curves/esm/_shortw_utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["../src/_shortw_utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG;IACpC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,KAAK,UAAU,CAAC;IAC7D,WAAW,EAAE,OAAO,WAAW,CAAC;CACjC,CAMA;AACD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,GAAG,iBAAiB,CAGjF"} \ No newline at end of file diff --git a/packages/noble-curves/esm/_shortw_utils.js b/packages/noble-curves/esm/_shortw_utils.js new file mode 100644 index 00000000000..c32dd38a6dc --- /dev/null +++ b/packages/noble-curves/esm/_shortw_utils.js @@ -0,0 +1,21 @@ +/** + * Utilities for short weierstrass curves, combined with noble-hashes. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { hmac } from '@noble/hashes/hmac' +import { concatBytes, randomBytes } from '@noble/hashes/utils' +import { weierstrass } from './abstract/weierstrass.js' +/** connects noble-curves to noble-hashes */ +export function getHash(hash) { + return { + hash, + hmac: (key, ...msgs) => hmac(hash, key, concatBytes(...msgs)), + randomBytes, + } +} +export function createCurve(curveDef, defHash) { + const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) }) + return { ...create(defHash), create } +} +//# sourceMappingURL=_shortw_utils.js.map diff --git a/packages/noble-curves/esm/_shortw_utils.js.map b/packages/noble-curves/esm/_shortw_utils.js.map new file mode 100644 index 00000000000..0f19fb0873e --- /dev/null +++ b/packages/noble-curves/esm/_shortw_utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"_shortw_utils.js","sourceRoot":"","sources":["../src/_shortw_utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAgC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,IAAW;IAKjC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,CAAC,GAAe,EAAE,GAAG,IAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;QACvF,WAAW;KACZ,CAAC;AACJ,CAAC;AAKD,MAAM,UAAU,WAAW,CAAC,QAAkB,EAAE,OAAc;IAC5D,MAAM,MAAM,GAAG,CAAC,IAAW,EAAW,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/bls.d.ts b/packages/noble-curves/esm/abstract/bls.d.ts new file mode 100644 index 00000000000..cc7aae5e409 --- /dev/null +++ b/packages/noble-curves/esm/abstract/bls.d.ts @@ -0,0 +1,165 @@ +import { + type Opts as HTFOpts, + type MapToCurve, + createHasher, + type htfBasicOpts, +} from './hash-to-curve.js' +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' +import { type CHash, type Hex, type PrivKey } from './utils.js' +import { type CurvePointsRes, type CurvePointsType, type ProjPointType } from './weierstrass.js' +type Fp = bigint +export type TwistType = 'multiplicative' | 'divisive' +export type ShortSignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} +export type SignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} +export type PostPrecomputePointAddFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, +) => { + Rx: Fp2 + Ry: Fp2 + Rz: Fp2 +} +export type PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => void +export type CurveType = { + G1: Omit, 'n'> & { + ShortSignature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + G2: Omit, 'n'> & { + Signature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + fields: { + Fp: IField + Fr: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + } + params: { + ateLoopSize: bigint + xNegative: boolean + r: bigint + twistType: TwistType + } + htfDefaults: HTFOpts + hash: CHash + randomBytes: (bytesLength?: number) => Uint8Array + postPrecompute?: PostPrecomputeFn +} +type PrecomputeSingle = [Fp2, Fp2, Fp2][] +type Precompute = PrecomputeSingle[] +export type CurveFn = { + getPublicKey: (privateKey: PrivKey) => Uint8Array + getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array + sign: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + signShortSignature: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + verify: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyShortSignature: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyBatch: ( + signature: Hex | ProjPointType, + messages: (Hex | ProjPointType)[], + publicKeys: (Hex | ProjPointType)[], + htfOpts?: htfBasicOpts, + ) => boolean + aggregatePublicKeys: { + (publicKeys: Hex[]): Uint8Array + (publicKeys: ProjPointType[]): ProjPointType + } + aggregateSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + aggregateShortSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 + pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 + pairingBatch: ( + pairs: { + g1: ProjPointType + g2: ProjPointType + }[], + withFinalExponent?: boolean, + ) => Fp12 + G1: CurvePointsRes & ReturnType> + G2: CurvePointsRes & ReturnType> + Signature: SignatureCoder + ShortSignature: ShortSignatureCoder + params: { + ateLoopSize: bigint + r: bigint + G1b: bigint + G2b: Fp2 + } + fields: { + Fp: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + Fr: IField + } + utils: { + randomPrivateKey: () => Uint8Array + calcPairingPrecomputes: (p: ProjPointType) => Precompute + } +} +export declare function bls(CURVE: CurveType): CurveFn +export {} +//# sourceMappingURL=bls.d.ts.map diff --git a/packages/noble-curves/esm/abstract/bls.d.ts.map b/packages/noble-curves/esm/abstract/bls.d.ts.map new file mode 100644 index 00000000000..5b282a96635 --- /dev/null +++ b/packages/noble-curves/esm/abstract/bls.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bls.d.ts","sourceRoot":"","sources":["../../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/bls.js b/packages/noble-curves/esm/abstract/bls.js new file mode 100644 index 00000000000..a132739adce --- /dev/null +++ b/packages/noble-curves/esm/abstract/bls.js @@ -0,0 +1,357 @@ +// prettier-ignore +import { createHasher } from './hash-to-curve.js' +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// TODO: import { AffinePoint } from './curve.js'; +import { getMinHashLength, mapHashToField } from './modular.js' +import { ensureBytes, memoized } from './utils.js' +import { weierstrassPoints } from './weierstrass.js' +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. +function NAfDecomposition(a) { + const res = [] + // a>1 because of marker bit + for (; a > _1n; a >>= _1n) { + if ((a & _1n) === _0n) res.unshift(0) + else if ((a & _3n) === _3n) { + res.unshift(-1) + a += _1n + } else res.unshift(1) + } + return res +} +export function bls(CURVE) { + // Fields are specific for curve, so for now we'll need to pass them with opts + const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields + const BLS_X_IS_NEGATIVE = CURVE.params.xNegative + const TWIST = CURVE.params.twistType + // Point on G1 curve: (x, y) + const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) + const G1 = Object.assign( + G1_, + createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G1.htfDefaults, + }), + ) + // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) + const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) + const G2 = Object.assign( + G2_, + createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G2.htfDefaults, + }), + ) + // Applies sparse multiplication as line function + let lineFunction + if (TWIST === 'multiplicative') { + lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) + } else if (TWIST === 'divisive') { + // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of + // precompute calculations. + lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) + } else throw new Error('bls: unknown twist type') + const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) + function pointDouble(ell, Rx, Ry, Rz) { + const t0 = Fp2.sqr(Ry) // Ry² + const t1 = Fp2.sqr(Rz) // Rz² + const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B + const t3 = Fp2.mul(t2, _3n) // 3 * T2 + const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 + const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) + const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² + const c2 = Fp2.neg(t4) // -T4 (-h) + ell.push([c0, c1, c2]) + Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 + Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² + Rz = Fp2.mul(t0, t4) // T0 * T4 + return { Rx, Ry, Rz } + } + function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) { + // Addition + const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz + const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz + const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy + const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry + const c2 = t1 // == Rx - Qx * Rz + ell.push([c0, c1, c2]) + const t2 = Fp2.sqr(t1) // T1² + const t3 = Fp2.mul(t2, t1) // T2 * T1 + const t4 = Fp2.mul(t2, Rx) // T2 * Rx + const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz + Rx = Fp2.mul(t1, t5) // T1 * T5 + Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry + Rz = Fp2.mul(Rz, t3) // Rz * T3 + return { Rx, Ry, Rz } + } + // Pre-compute coefficients for sparse multiplication + // Point addition and point double calculations is reused for coefficients + // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine + // add + double in windowed precomputes here, otherwise it would be single op (since X is static) + const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) + const calcPairingPrecomputes = memoized((point) => { + const p = point + const { x, y } = p.toAffine() + // prettier-ignore + const Qx = x, + Qy = y, + negQy = Fp2.neg(y) + // prettier-ignore + let Rx = Qx, + Ry = Qy, + Rz = Fp2.ONE + const ell = [] + for (const bit of ATE_NAF) { + const cur = [] + ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) + if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) + ell.push(cur) + } + if (CURVE.postPrecompute) { + const last = ell[ell.length - 1] + CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) + } + return ell + }) + function millerLoopBatch(pairs, withFinalExponent = false) { + let f12 = Fp12.ONE + if (pairs.length) { + const ellLen = pairs[0][0].length + for (let i = 0; i < ellLen; i++) { + f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings + // NOTE: we apply multiple pairings in parallel here + for (const [ell, Px, Py] of pairs) { + for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) + } + } + } + if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) + return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 + } + // Calculates product of multiple pairings + // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` + function pairingBatch(pairs, withFinalExponent = true) { + const res = [] + // This cache precomputed toAffine for all points + G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) + G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) + for (const { g1, g2 } of pairs) { + if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) + throw new Error('pairing is not available for ZERO point') + // This uses toAffine inside + g1.assertValidity() + g2.assertValidity() + const Qa = g1.toAffine() + res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) + } + return millerLoopBatch(res, withFinalExponent) + } + // Calculates bilinear pairing + function pairing(Q, P, withFinalExponent = true) { + return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) + } + const utils = { + randomPrivateKey: () => { + const length = getMinHashLength(Fr.ORDER) + return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) + }, + calcPairingPrecomputes, + } + const { ShortSignature } = CURVE.G1 + const { Signature } = CURVE.G2 + function normP1(point) { + return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point) + } + function normP1Hash(point, htfOpts) { + return point instanceof G1.ProjectivePoint + ? point + : G1.hashToCurve(ensureBytes('point', point), htfOpts) + } + function normP2(point) { + return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) + } + function normP2Hash(point, htfOpts) { + return point instanceof G2.ProjectivePoint + ? point + : G2.hashToCurve(ensureBytes('point', point), htfOpts) + } + // Multiplies generator (G1) by private key. + // P = pk x G + function getPublicKey(privateKey) { + return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + // Multiplies generator (G2) by private key. + // P = pk x G + function getPublicKeyForShortSignatures(privateKey) { + return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + function sign(message, privateKey, htfOpts) { + const msgPoint = normP2Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G2.ProjectivePoint) return sigPoint + return Signature.toRawBytes(sigPoint) + } + function signShortSignature(message, privateKey, htfOpts) { + const msgPoint = normP1Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G1.ProjectivePoint) return sigPoint + return ShortSignature.toRawBytes(sigPoint) + } + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(P, H(m)) == e(G, S) + function verify(signature, message, publicKey, htfOpts) { + const P = normP1(publicKey) + const Hm = normP2Hash(message, htfOpts) + const G = G1.ProjectivePoint.BASE + const S = normP2(signature) + const exp = pairingBatch([ + { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); + { g1: G, g2: S }, // eGS = pairing(G, S, false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(S, G) == e(H(m), P) + function verifyShortSignature(signature, message, publicKey, htfOpts) { + const P = normP2(publicKey) + const Hm = normP1Hash(message, htfOpts) + const G = G2.ProjectivePoint.BASE + const S = normP1(signature) + const exp = pairingBatch([ + { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); + { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + function aNonEmpty(arr) { + if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') + } + function aggregatePublicKeys(publicKeys) { + aNonEmpty(publicKeys) + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (publicKeys[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + // toRawBytes ensures point validity + return aggAffine.toRawBytes(true) + } + function aggregateSignatures(signatures) { + aNonEmpty(signatures) + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G2.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return Signature.toRawBytes(aggAffine) + } + function aggregateShortSignatures(signatures) { + aNonEmpty(signatures) + const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return ShortSignature.toRawBytes(aggAffine) + } + // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 + // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) + function verifyBatch( + signature, + // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? + messages, + publicKeys, + htfOpts, + ) { + aNonEmpty(messages) + if (publicKeys.length !== messages.length) + throw new Error('amount of public keys and messages should be equal') + const sig = normP2(signature) + const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) + const nPublicKeys = publicKeys.map(normP1) + // NOTE: this works only for exact same object + const messagePubKeyMap = new Map() + for (let i = 0; i < nPublicKeys.length; i++) { + const pub = nPublicKeys[i] + const msg = nMessages[i] + let keys = messagePubKeyMap.get(msg) + if (keys === undefined) { + keys = [] + messagePubKeyMap.set(msg, keys) + } + keys.push(pub) + } + const paired = [] + try { + for (const [msg, keys] of messagePubKeyMap) { + const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) + paired.push({ g1: groupPublicKey, g2: msg }) + } + paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) + return Fp12.eql(pairingBatch(paired), Fp12.ONE) + } catch { + return false + } + } + G1.ProjectivePoint.BASE._setWindowSize(4) + return { + getPublicKey, + getPublicKeyForShortSignatures, + sign, + signShortSignature, + verify, + verifyBatch, + verifyShortSignature, + aggregatePublicKeys, + aggregateSignatures, + aggregateShortSignatures, + millerLoopBatch, + pairing, + pairingBatch, + G1, + G2, + Signature, + ShortSignature, + fields: { + Fr, + Fp, + Fp2, + Fp6, + Fp12, + }, + params: { + ateLoopSize: CURVE.params.ateLoopSize, + r: CURVE.params.r, + G1b: CURVE.G1.b, + G2b: CURVE.G2.b, + }, + utils, + } +} +//# sourceMappingURL=bls.js.map diff --git a/packages/noble-curves/esm/abstract/bls.js.map b/packages/noble-curves/esm/abstract/bls.js.map new file mode 100644 index 00000000000..334a1bed9ff --- /dev/null +++ b/packages/noble-curves/esm/abstract/bls.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bls.js","sourceRoot":"","sources":["../../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/curve.d.ts b/packages/noble-curves/esm/abstract/curve.d.ts new file mode 100644 index 00000000000..b4984cb067f --- /dev/null +++ b/packages/noble-curves/esm/abstract/curve.d.ts @@ -0,0 +1,124 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +export type AffinePoint = { + x: T + y: T +} & { + z?: never + t?: never +} +export interface Group> { + double(): T + negate(): T + add(other: T): T + subtract(other: T): T + equals(other: T): boolean + multiply(scalar: bigint): T +} +export type GroupConstructor = { + BASE: T + ZERO: T +} +export type Mapper = (i: T[]) => T[] +export type IWNAF> = { + constTimeNegate: >(condition: boolean, item: T) => T + hasPrecomputes(elm: T): boolean + unsafeLadder(elm: T, n: bigint, p?: T): T + precomputeWindow(elm: T, W: number): Group[] + wNAF( + W: number, + precomputes: T[], + n: bigint, + ): { + p: T + f: T + } + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T + getPrecomputes(W: number, P: T, transform: Mapper): T[] + wNAFCached( + P: T, + n: bigint, + transform: Mapper, + ): { + p: T + f: T + } + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T + setWindowSize(P: T, W: number): void +} +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export declare function wNAF>(c: GroupConstructor, bits: number): IWNAF +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster with precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export declare function pippenger>( + c: GroupConstructor, + fieldN: IField, + points: T[], + scalars: bigint[], +): T +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export declare function precomputeMSMUnsafe>( + c: GroupConstructor, + fieldN: IField, + points: T[], + windowSize: number, +): (scalars: bigint[]) => T +/** + * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. + * Though generator can be different (Fp2 / Fp6 for BLS). + */ +export type BasicCurve = { + Fp: IField + n: bigint + nBitLength?: number + nByteLength?: number + h: bigint + hEff?: bigint + Gx: T + Gy: T + allowInfinityPoint?: boolean +} +export declare function validateBasic( + curve: BasicCurve & T, +): Readonly< + { + readonly nBitLength: number + readonly nByteLength: number + } & BasicCurve & + T & { + p: bigint + } +> +//# sourceMappingURL=curve.d.ts.map diff --git a/packages/noble-curves/esm/abstract/curve.d.ts.map b/packages/noble-curves/esm/abstract/curve.d.ts.map new file mode 100644 index 00000000000..0f2da30ccc0 --- /dev/null +++ b/packages/noble-curves/esm/abstract/curve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/curve.js b/packages/noble-curves/esm/abstract/curve.js new file mode 100644 index 00000000000..c59b639eafc --- /dev/null +++ b/packages/noble-curves/esm/abstract/curve.js @@ -0,0 +1,362 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { nLength, validateField } from './modular.js' +import { bitLen, validateObject } from './utils.js' +const _0n = BigInt(0) +const _1n = BigInt(1) +function constTimeNegate(condition, item) { + const neg = item.negate() + return condition ? neg : item +} +function validateW(W, bits) { + if (!Number.isSafeInteger(W) || W <= 0 || W > bits) + throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) +} +function calcWOpts(W, bits) { + validateW(W, bits) + const windows = Math.ceil(bits / W) + 1 // +1, because + const windowSize = 2 ** (W - 1) // -1 because we skip zero + return { windows, windowSize } +} +function validateMSMPoints(points, c) { + if (!Array.isArray(points)) throw new Error('array expected') + points.forEach((p, i) => { + if (!(p instanceof c)) throw new Error('invalid point at index ' + i) + }) +} +function validateMSMScalars(scalars, field) { + if (!Array.isArray(scalars)) throw new Error('array of scalars expected') + scalars.forEach((s, i) => { + if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) + }) +} +// Since points in different groups cannot be equal (different object constructor), +// we can have single place to store precomputes +const pointPrecomputes = new WeakMap() +const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) +function getW(P) { + return pointWindowSizes.get(P) || 1 +} +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export function wNAF(c, bits) { + return { + constTimeNegate, + hasPrecomputes(elm) { + return getW(elm) !== 1 + }, + // non-const time multiplication ladder + unsafeLadder(elm, n, p = c.ZERO) { + let d = elm + while (n > _0n) { + if (n & _1n) p = p.add(d) + d = d.double() + n >>= _1n + } + return p + }, + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param elm Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(elm, W) { + const { windows, windowSize } = calcWOpts(W, bits) + const points = [] + let p = elm + let base = p + for (let window = 0; window < windows; window++) { + base = p + points.push(base) + // =1, because we skip zero + for (let i = 1; i < windowSize; i++) { + base = base.add(p) + points.push(base) + } + p = base.double() + } + return points + }, + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @returns real and fake (for const-time) points + */ + wNAF(W, precomputes, n) { + // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise + // But need to carefully remove other checks before wNAF. ORDER == bits here + const { windows, windowSize } = calcWOpts(W, bits) + let p = c.ZERO + let f = c.BASE + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + // Extract W bits. + let wbits = Number(n & mask) + // Shift number by W bits. + n >>= shiftBy + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + // This code was first written with assumption that 'f' and 'p' will never be infinity point: + // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, + // there is negate now: it is possible that negated element from low value + // would be the same as high element, which will create carry into next window. + // It's not obvious how this can fail, but still worth investigating later. + // Check if we're onto Zero point. + // Add random point inside current window to f. + const offset1 = offset + const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero + const cond1 = window % 2 !== 0 + const cond2 = wbits < 0 + if (wbits === 0) { + // The most important part for const-time getPublicKey + f = f.add(constTimeNegate(cond1, precomputes[offset1])) + } else { + p = p.add(constTimeNegate(cond2, precomputes[offset2])) + } + } + // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() + // Even if the variable is still unused, there are some checks which will + // throw an exception, so compiler needs to prove they won't happen, which is hard. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. + return { p, f } + }, + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(W, precomputes, n, acc = c.ZERO) { + const { windows, windowSize } = calcWOpts(W, bits) + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + if (n === _0n) break // No need to go over empty scalar + // Extract W bits. + let wbits = Number(n & mask) + // Shift number by W bits. + n >>= shiftBy + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + if (wbits === 0) continue + let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero + if (wbits < 0) curr = curr.negate() + // NOTE: by re-using acc, we can save a lot of additions in case of MSM + acc = acc.add(curr) + } + return acc + }, + getPrecomputes(W, P, transform) { + // Calculate precomputes on a first run, reuse them after + let comp = pointPrecomputes.get(P) + if (!comp) { + comp = this.precomputeWindow(P, W) + if (W !== 1) pointPrecomputes.set(P, transform(comp)) + } + return comp + }, + wNAFCached(P, n, transform) { + const W = getW(P) + return this.wNAF(W, this.getPrecomputes(W, P, transform), n) + }, + wNAFCachedUnsafe(P, n, transform, prev) { + const W = getW(P) + if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster + return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) + }, + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + setWindowSize(P, W) { + validateW(W, bits) + pointWindowSizes.set(P, W) + pointPrecomputes.delete(P) + }, + } +} +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster with precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export function pippenger(c, fieldN, points, scalars) { + // If we split scalars by some window (let's say 8 bits), every chunk will only + // take 256 buckets even if there are 4096 scalars, also re-uses double. + // TODO: + // - https://eprint.iacr.org/2024/750.pdf + // - https://tches.iacr.org/index.php/TCHES/article/view/10287 + // 0 is accepted in scalars + validateMSMPoints(points, c) + validateMSMScalars(scalars, fieldN) + if (points.length !== scalars.length) + throw new Error('arrays of points and scalars must have equal length') + const zero = c.ZERO + const wbits = bitLen(BigInt(points.length)) + const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits + const MASK = (1 << windowSize) - 1 + const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array + const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize + let sum = zero + for (let i = lastBits; i >= 0; i -= windowSize) { + buckets.fill(zero) + for (let j = 0; j < scalars.length; j++) { + const scalar = scalars[j] + const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) + buckets[wbits] = buckets[wbits].add(points[j]) + } + let resI = zero // not using this will do small speed-up, but will lose ct + // Skip first bucket, because it is zero + for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { + sumI = sumI.add(buckets[j]) + resI = resI.add(sumI) + } + sum = sum.add(resI) + if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() + } + return sum +} +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export function precomputeMSMUnsafe(c, fieldN, points, windowSize) { + /** + * Performance Analysis of Window-based Precomputation + * + * Base Case (256-bit scalar, 8-bit window): + * - Standard precomputation requires: + * - 31 additions per scalar × 256 scalars = 7,936 ops + * - Plus 255 summary additions = 8,191 total ops + * Note: Summary additions can be optimized via accumulator + * + * Chunked Precomputation Analysis: + * - Using 32 chunks requires: + * - 255 additions per chunk + * - 256 doublings + * - Total: (255 × 32) + 256 = 8,416 ops + * + * Memory Usage Comparison: + * Window Size | Standard Points | Chunked Points + * ------------|-----------------|--------------- + * 4-bit | 520 | 15 + * 8-bit | 4,224 | 255 + * 10-bit | 13,824 | 1,023 + * 16-bit | 557,056 | 65,535 + * + * Key Advantages: + * 1. Enables larger window sizes due to reduced memory overhead + * 2. More efficient for smaller scalar counts: + * - 16 chunks: (16 × 255) + 256 = 4,336 ops + * - ~2x faster than standard 8,191 ops + * + * Limitations: + * - Not suitable for plain precomputes (requires 256 constant doublings) + * - Performance degrades with larger scalar counts: + * - Optimal for ~256 scalars + * - Less efficient for 4096+ scalars (Pippenger preferred) + */ + validateW(windowSize, fieldN.BITS) + validateMSMPoints(points, c) + const zero = c.ZERO + const tableSize = 2 ** windowSize - 1 // table size (without zero) + const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item + const MASK = BigInt((1 << windowSize) - 1) + const tables = points.map((p) => { + const res = [] + for (let i = 0, acc = p; i < tableSize; i++) { + res.push(acc) + acc = acc.add(p) + } + return res + }) + return (scalars) => { + validateMSMScalars(scalars, fieldN) + if (scalars.length > points.length) + throw new Error('array of scalars must be smaller than array of points') + let res = zero + for (let i = 0; i < chunks; i++) { + // No need to double if accumulator is still zero. + if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() + const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) + for (let j = 0; j < scalars.length; j++) { + const n = scalars[j] + const curr = Number((n >> shiftBy) & MASK) + if (!curr) continue // skip zero scalars chunks + res = res.add(tables[j][curr - 1]) + } + } + return res + } +} +export function validateBasic(curve) { + validateField(curve.Fp) + validateObject( + curve, + { + n: 'bigint', + h: 'bigint', + Gx: 'field', + Gy: 'field', + }, + { + nBitLength: 'isSafeInteger', + nByteLength: 'isSafeInteger', + }, + ) + // Set defaults + return Object.freeze({ + ...nLength(curve.n, curve.nBitLength), + ...curve, + ...{ p: curve.Fp.ORDER }, + }) +} +//# sourceMappingURL=curve.js.map diff --git a/packages/noble-curves/esm/abstract/curve.js.map b/packages/noble-curves/esm/abstract/curve.js.map new file mode 100644 index 00000000000..09e01508f2d --- /dev/null +++ b/packages/noble-curves/esm/abstract/curve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"curve.js","sourceRoot":"","sources":["../../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/edwards.d.ts b/packages/noble-curves/esm/abstract/edwards.d.ts new file mode 100644 index 00000000000..cfd6867cfb1 --- /dev/null +++ b/packages/noble-curves/esm/abstract/edwards.d.ts @@ -0,0 +1,106 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' +import { type FHash, type Hex } from './utils.js' +/** Edwards curves must declare params a & d. */ +export type CurveType = BasicCurve & { + a: bigint + d: bigint + hash: FHash + randomBytes: (bytesLength?: number) => Uint8Array + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + uvRatio?: ( + u: bigint, + v: bigint, + ) => { + isValid: boolean + value: bigint + } + prehash?: FHash + mapToCurve?: (scalar: bigint[]) => AffinePoint +} +export type CurveTypeWithLength = Readonly< + CurveType & { + nByteLength: number + nBitLength: number + } +> +declare function validateOpts(curve: CurveType): CurveTypeWithLength +/** Instance of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointType extends Group { + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + get x(): bigint + get y(): bigint + assertValidity(): void + multiply(scalar: bigint): ExtPointType + multiplyUnsafe(scalar: bigint): ExtPointType + isSmallOrder(): boolean + isTorsionFree(): boolean + clearCofactor(): ExtPointType + toAffine(iz?: bigint): AffinePoint + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + _setWindowSize(windowSize: number): void +} +/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType + fromAffine(p: AffinePoint): ExtPointType + fromHex(hex: Hex): ExtPointType + fromPrivateKey(privateKey: Hex): ExtPointType + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType +} +/** + * Edwards Curve interface. + * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. + */ +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: Hex) => Uint8Array + sign: ( + message: Hex, + privateKey: Hex, + options?: { + context?: Hex + }, + ) => Uint8Array + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { + context?: Hex + zip215: boolean + }, + ) => boolean + ExtendedPoint: ExtPointConstructor + utils: { + randomPrivateKey: () => Uint8Array + getExtendedPublicKey: (key: Hex) => { + head: Uint8Array + prefix: Uint8Array + scalar: bigint + point: ExtPointType + pointBytes: Uint8Array + } + precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType + } +} +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export declare function twistedEdwards(curveDef: CurveType): CurveFn +export {} +//# sourceMappingURL=edwards.d.ts.map diff --git a/packages/noble-curves/esm/abstract/edwards.d.ts.map b/packages/noble-curves/esm/abstract/edwards.d.ts.map new file mode 100644 index 00000000000..7ba0ffa6390 --- /dev/null +++ b/packages/noble-curves/esm/abstract/edwards.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"edwards.d.ts","sourceRoot":"","sources":["../../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/edwards.js b/packages/noble-curves/esm/abstract/edwards.js new file mode 100644 index 00000000000..552735b0ecf --- /dev/null +++ b/packages/noble-curves/esm/abstract/edwards.js @@ -0,0 +1,445 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { pippenger, validateBasic, wNAF } from './curve.js' +import { Field, mod } from './modular.js' +import * as ut from './utils.js' +import { abool, ensureBytes, memoized } from './utils.js' +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _8n = BigInt(8) +// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: +const VERIFY_DEFAULT = { zip215: true } +function validateOpts(curve) { + const opts = validateBasic(curve) + ut.validateObject( + curve, + { + hash: 'function', + a: 'bigint', + d: 'bigint', + randomBytes: 'function', + }, + { + adjustScalarBytes: 'function', + domain: 'function', + uvRatio: 'function', + mapToCurve: 'function', + }, + ) + // Set defaults + return Object.freeze({ ...opts }) +} +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export function twistedEdwards(curveDef) { + const CURVE = validateOpts(curveDef) + const { + Fp, + n: CURVE_ORDER, + prehash: prehash, + hash: cHash, + randomBytes, + nByteLength, + h: cofactor, + } = CURVE + // Important: + // There are some places where Fp.BYTES is used instead of nByteLength. + // So far, everything has been tested with curves of Fp.BYTES == nByteLength. + // TODO: test and find curves which behave otherwise. + const MASK = _2n << (BigInt(nByteLength * 8) - _1n) + const modP = Fp.create // Function overrides + const Fn = Field(CURVE.n, CURVE.nBitLength) + // sqrt(u/v) + const uvRatio = + CURVE.uvRatio || + ((u, v) => { + try { + return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } + } catch (e) { + return { isValid: false, value: _0n } + } + }) + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) // NOOP + const domain = + CURVE.domain || + ((data, ctx, phflag) => { + abool('phflag', phflag) + if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') + return data + }) // NOOP + // 0 <= n < MASK + // Coordinates larger than Fp.ORDER are allowed for zip215 + function aCoordinate(title, n) { + ut.aInRange('coordinate ' + title, n, _0n, MASK) + } + function assertPoint(other) { + if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + const toAffineMemo = memoized((p, iz) => { + const { ex: x, ey: y, ez: z } = p + const is0 = p.is0() + if (iz == null) iz = is0 ? _8n : Fp.inv(z) // 8 was chosen arbitrarily + const ax = modP(x * iz) + const ay = modP(y * iz) + const zz = modP(z * iz) + if (is0) return { x: _0n, y: _1n } + if (zz !== _1n) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + const assertValidMemo = memoized((p) => { + const { a, d } = CURVE + if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? + // Equation in affine coordinates: ax² + y² = 1 + dx²y² + // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² + const { ex: X, ey: Y, ez: Z, et: T } = p + const X2 = modP(X * X) // X² + const Y2 = modP(Y * Y) // Y² + const Z2 = modP(Z * Z) // Z² + const Z4 = modP(Z2 * Z2) // Z⁴ + const aX2 = modP(X2 * a) // aX² + const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² + const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² + if (left !== right) throw new Error('bad point: equation left != right (1)') + // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T + const XY = modP(X * Y) + const ZT = modP(Z * T) + if (XY !== ZT) throw new Error('bad point: equation left != right (2)') + return true + }) + // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). + // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates + class Point { + constructor(ex, ey, ez, et) { + this.ex = ex + this.ey = ey + this.ez = ez + this.et = et + aCoordinate('x', ex) + aCoordinate('y', ey) + aCoordinate('z', ez) + aCoordinate('t', et) + Object.freeze(this) + } + get x() { + return this.toAffine().x + } + get y() { + return this.toAffine().y + } + static fromAffine(p) { + if (p instanceof Point) throw new Error('extended point not allowed') + const { x, y } = p || {} + aCoordinate('x', x) + aCoordinate('y', y) + return new Point(x, y, _1n, modP(x * y)) + } + static normalizeZ(points) { + const toInv = Fp.invertBatch(points.map((p) => p.ez)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + // Multiscalar Multiplication + static msm(points, scalars) { + return pippenger(Point, Fn, points, scalars) + } + // "Private method", don't use it directly + _setWindowSize(windowSize) { + wnaf.setWindowSize(this, windowSize) + } + // Not required for fromHex(), which always creates valid points. + // Could be useful for fromAffine(). + assertValidity() { + assertValidMemo(this) + } + // Compare one point to another. + equals(other) { + assertPoint(other) + const { ex: X1, ey: Y1, ez: Z1 } = this + const { ex: X2, ey: Y2, ez: Z2 } = other + const X1Z2 = modP(X1 * Z2) + const X2Z1 = modP(X2 * Z1) + const Y1Z2 = modP(Y1 * Z2) + const Y2Z1 = modP(Y2 * Z1) + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 + } + is0() { + return this.equals(Point.ZERO) + } + negate() { + // Flips point sign to a negative one (-x, y in affine coords) + return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) + } + // Fast algo for doubling Extended Point. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd + // Cost: 4M + 4S + 1*a + 6add + 1*2. + double() { + const { a } = CURVE + const { ex: X1, ey: Y1, ez: Z1 } = this + const A = modP(X1 * X1) // A = X12 + const B = modP(Y1 * Y1) // B = Y12 + const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 + const D = modP(a * A) // D = a*A + const x1y1 = X1 + Y1 + const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B + const G = D + B // G = D+B + const F = G - C // F = G-C + const H = D - B // H = D-B + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + // Fast algo for adding 2 Extended Points. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd + // Cost: 9M + 1*a + 1*d + 7add. + add(other) { + assertPoint(other) + const { a, d } = CURVE + const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this + const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other + // Faster algo for adding 2 Extended Points when curve's a=-1. + // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 + // Cost: 8M + 8add + 2*2. + // Note: It does not check whether the `other` point is valid. + if (a === BigInt(-1)) { + const A = modP((Y1 - X1) * (Y2 + X2)) + const B = modP((Y1 + X1) * (Y2 - X2)) + const F = modP(B - A) + if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing + const C = modP(Z1 * _2n * T2) + const D = modP(T1 * _2n * Z2) + const E = D + C + const G = B + A + const H = D - C + const X3 = modP(E * F) + const Y3 = modP(G * H) + const T3 = modP(E * H) + const Z3 = modP(F * G) + return new Point(X3, Y3, Z3, T3) + } + const A = modP(X1 * X2) // A = X1*X2 + const B = modP(Y1 * Y2) // B = Y1*Y2 + const C = modP(T1 * d * T2) // C = T1*d*T2 + const D = modP(Z1 * Z2) // D = Z1*Z2 + const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B + const F = D - C // F = D-C + const G = D + C // G = D+C + const H = modP(B - a * A) // H = B-a*A + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + subtract(other) { + return this.add(other.negate()) + } + wNAF(n) { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + // Constant-time multiplication. + multiply(scalar) { + const n = scalar + ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L + const { p, f } = this.wNAF(n) + return Point.normalizeZ([p, f])[0] + } + // Non-constant-time multiplication. Uses double-and-add algorithm. + // It's faster, but should only be used when you don't care about + // an exposed private key e.g. sig verification. + // Does NOT allow scalars higher than CURVE.n. + // Accepts optional accumulator to merge with multiply (important for sparse scalars) + multiplyUnsafe(scalar, acc = Point.ZERO) { + const n = scalar + ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L + if (n === _0n) return I + if (this.is0() || n === _1n) return this + return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) + } + // Checks if point is of small order. + // If you add something to small order point, you will have "dirty" + // point with torsion component. + // Multiplies point by cofactor and checks if the result is 0. + isSmallOrder() { + return this.multiplyUnsafe(cofactor).is0() + } + // Multiplies point by curve order and checks if the result is 0. + // Returns `false` is the point is dirty. + isTorsionFree() { + return wnaf.unsafeLadder(this, CURVE_ORDER).is0() + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + toAffine(iz) { + return toAffineMemo(this, iz) + } + clearCofactor() { + const { h: cofactor } = CURVE + if (cofactor === _1n) return this + return this.multiplyUnsafe(cofactor) + } + // Converts hash string or Uint8Array to Point. + // Uses algo from RFC8032 5.1.3. + static fromHex(hex, zip215 = false) { + const { d, a } = CURVE + const len = Fp.BYTES + hex = ensureBytes('pointHex', hex, len) // copy hex to a new array + abool('zip215', zip215) + const normed = hex.slice() // copy again, we'll manipulate it + const lastByte = hex[len - 1] // select last byte + normed[len - 1] = lastByte & ~0x80 // clear last bit + const y = ut.bytesToNumberLE(normed) + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // RFC8032 prohibits >= p, but ZIP215 doesn't + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + const max = zip215 ? MASK : Fp.ORDER + ut.aInRange('pointHex.y', y, _0n, max) + // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: + // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) + const y2 = modP(y * y) // denominator is always non-0 mod p. + const u = modP(y2 - _1n) // u = y² - 1 + const v = modP(d * y2 - a) // v = d y² + 1. + let { isValid, value: x } = uvRatio(u, v) // √(u/v) + if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') + const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper + const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1') + if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x + return Point.fromAffine({ x, y }) + } + static fromPrivateKey(privKey) { + return getExtendedPublicKey(privKey).point + } + toRawBytes() { + const { x, y } = this.toAffine() + const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) + bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y + return bytes // and use the last byte to encode sign of x + } + toHex() { + return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. + } + } + Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) + Point.ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 + const { BASE: G, ZERO: I } = Point + const wnaf = wNAF(Point, nByteLength * 8) + function modN(a) { + return mod(a, CURVE_ORDER) + } + // Little-endian SHA512 with modulo n + function modN_LE(hash) { + return modN(ut.bytesToNumberLE(hash)) + } + /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ + function getExtendedPublicKey(key) { + const len = Fp.BYTES + key = ensureBytes('private key', key, len) + // Hash private key with curve's hash function to produce uniformingly random input + // Check byte lengths: ensure(64, h(ensure(32, key))) + const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) + const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE + const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) + const scalar = modN_LE(head) // The actual private scalar + const point = G.multiply(scalar) // Point on Edwards curve aka public key + const pointBytes = point.toRawBytes() // Uint8Array representation + return { head, prefix, scalar, point, pointBytes } + } + // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared + function getPublicKey(privKey) { + return getExtendedPublicKey(privKey).pointBytes + } + // int('LE', SHA512(dom2(F, C) || msgs)) mod N + function hashDomainToScalar(context = new Uint8Array(), ...msgs) { + const msg = ut.concatBytes(...msgs) + return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) + } + /** Signs message with privateKey. RFC8032 5.1.6 */ + function sign(msg, privKey, options = {}) { + msg = ensureBytes('message', msg) + if (prehash) msg = prehash(msg) // for ed25519ph etc. + const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) + const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) + const R = G.multiply(r).toRawBytes() // R = rG + const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) + const s = modN(r + k * scalar) // S = (r + k * s) mod L + ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l + const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) + return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature + } + const verifyOpts = VERIFY_DEFAULT + /** + * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + * An extended group equation is checked. + */ + function verify(sig, msg, publicKey, options = verifyOpts) { + const { context, zip215 } = options + const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. + msg = ensureBytes('message', msg) + publicKey = ensureBytes('publicKey', publicKey, len) + if (zip215 !== undefined) abool('zip215', zip215) + if (prehash) msg = prehash(msg) // for ed25519ph, etc + const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) + let A, R, SB + try { + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + A = Point.fromHex(publicKey, zip215) + R = Point.fromHex(sig.slice(0, len), zip215) + SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside + } catch (error) { + return false + } + if (!zip215 && A.isSmallOrder()) return false + const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) + const RkA = R.add(A.multiplyUnsafe(k)) + // Extended group equation + // [8][S]B = [8]R + [8][k]A' + return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) + } + G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. + const utils = { + getExtendedPublicKey, + // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. + randomPrivateKey: () => randomBytes(Fp.BYTES), + /** + * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT + * values. This slows down first getPublicKey() by milliseconds (see Speed section), + * but allows to speed-up subsequent getPublicKey() calls up to 20x. + * @param windowSize 2, 4, 8, 16 + */ + precompute(windowSize = 8, point = Point.BASE) { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) + return point + }, + } + return { + CURVE, + getPublicKey, + sign, + verify, + ExtendedPoint: Point, + utils, + } +} +//# sourceMappingURL=edwards.js.map diff --git a/packages/noble-curves/esm/abstract/edwards.js.map b/packages/noble-curves/esm/abstract/edwards.js.map new file mode 100644 index 00000000000..895922f39f0 --- /dev/null +++ b/packages/noble-curves/esm/abstract/edwards.js.map @@ -0,0 +1 @@ +{"version":3,"file":"edwards.js","sourceRoot":"","sources":["../../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts new file mode 100644 index 00000000000..646647f9280 --- /dev/null +++ b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts @@ -0,0 +1,99 @@ +/** + * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import type { AffinePoint, Group, GroupConstructor } from './curve.js' +import { type IField } from './modular.js' +import type { CHash } from './utils.js' +export type UnicodeOrBytes = string | Uint8Array +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +export type Opts = { + DST: UnicodeOrBytes + p: bigint + m: number + k: number + expand: 'xmd' | 'xof' + hash: CHash +} +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export declare function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash, +): Uint8Array +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export declare function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash, +): Uint8Array +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export declare function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] +export type XY = ( + x: T, + y: T, +) => { + x: T + y: T +} +export declare function isogenyMap>( + field: F, + map: [T[], T[], T[], T[]], +): XY +/** Point interface, which curves must implement to work correctly with the module. */ +export interface H2CPoint extends Group> { + add(rhs: H2CPoint): H2CPoint + toAffine(iz?: bigint): AffinePoint + clearCofactor(): H2CPoint + assertValidity(): void +} +export interface H2CPointConstructor extends GroupConstructor> { + fromAffine(ap: AffinePoint): H2CPoint +} +export type MapToCurve = (scalar: bigint[]) => AffinePoint +export type htfBasicOpts = { + DST: UnicodeOrBytes +} +export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint +export type MapMethod = (scalars: bigint[]) => H2CPoint +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export declare function createHasher( + Point: H2CPointConstructor, + mapToCurve: MapToCurve, + def: Opts & { + encodeDST?: UnicodeOrBytes + }, +): { + hashToCurve: HTFMethod + encodeToCurve: HTFMethod + mapToCurve: MapMethod +} +//# sourceMappingURL=hash-to-curve.d.ts.map diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map new file mode 100644 index 00000000000..ae9703b1822 --- /dev/null +++ b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-to-curve.d.ts","sourceRoot":"","sources":["../../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.js b/packages/noble-curves/esm/abstract/hash-to-curve.js new file mode 100644 index 00000000000..46e18205e77 --- /dev/null +++ b/packages/noble-curves/esm/abstract/hash-to-curve.js @@ -0,0 +1,173 @@ +import { mod } from './modular.js' +import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.js' +// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. +const os2ip = bytesToNumberBE +// Integer to Octet Stream (numberToBytesBE) +function i2osp(value, length) { + anum(value) + anum(length) + if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) + 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 +} +function anum(item) { + if (!Number.isSafeInteger(item)) throw new Error('number expected') +} +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export function expand_message_xmd(msg, DST, lenInBytes, H) { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) + const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H + const ell = Math.ceil(lenInBytes / b_in_bytes) + if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') + 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) // len_in_bytes_str + const b = new Array(ell) + const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) + b[0] = 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] = H(concatBytes(...args)) + } + const pseudo_random_bytes = concatBytes(...b) + return pseudo_random_bytes.slice(0, lenInBytes) +} +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export function expand_message_xof(msg, DST, lenInBytes, k, H) { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); + if (DST.length > 255) { + const dkLen = Math.ceil((2 * k) / 8) + DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() + } + if (lenInBytes > 65535 || DST.length > 255) + throw new Error('expand_message_xof: invalid lenInBytes') + return ( + H.create({ dkLen: lenInBytes }) + .update(msg) + .update(i2osp(lenInBytes, 2)) + // 2. DST_prime = DST || I2OSP(len(DST), 1) + .update(DST) + .update(i2osp(DST.length, 1)) + .digest() + ) +} +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export function hash_to_field(msg, count, options) { + validateObject(options, { + DST: 'stringOrUint8Array', + p: 'bigint', + m: 'isSafeInteger', + k: 'isSafeInteger', + hash: 'hash', + }) + const { p, k, m, hash, expand, DST: _DST } = options + abytes(msg) + anum(count) + const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST + const log2p = p.toString(2).length + const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above + const len_in_bytes = count * m * L + let prb // pseudo_random_bytes + if (expand === 'xmd') { + prb = expand_message_xmd(msg, DST, len_in_bytes, hash) + } else if (expand === 'xof') { + prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) + } else if (expand === '_internal_pass') { + // for internal tests only + prb = msg + } else { + throw new Error('expand must be "xmd" or "xof"') + } + const u = new Array(count) + for (let i = 0; i < count; i++) { + const e = new Array(m) + for (let j = 0; j < m; j++) { + const elm_offset = L * (j + i * m) + const tv = prb.subarray(elm_offset, elm_offset + L) + e[j] = mod(os2ip(tv), p) + } + u[i] = e + } + return u +} +export function isogenyMap(field, map) { + // Make same order as in spec + const COEFF = map.map((i) => Array.from(i).reverse()) + return (x, y) => { + const [xNum, xDen, yNum, yDen] = COEFF.map((val) => + val.reduce((acc, i) => field.add(field.mul(acc, x), i)), + ) + x = field.div(xNum, xDen) // xNum / xDen + y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) + return { x: x, y: y } + } +} +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export function createHasher(Point, mapToCurve, def) { + if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') + return { + // Encodes byte string to elliptic curve. + // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + hashToCurve(msg, options) { + const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options }) + const u0 = Point.fromAffine(mapToCurve(u[0])) + const u1 = Point.fromAffine(mapToCurve(u[1])) + const P = u0.add(u1).clearCofactor() + P.assertValidity() + return P + }, + // Encodes byte string to elliptic curve. + // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + encodeToCurve(msg, options) { + const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options }) + const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() + P.assertValidity() + return P + }, + // Same as encodeToCurve, but without hash + mapToCurve(scalars) { + if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') + for (const i of scalars) + if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') + const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() + P.assertValidity() + return P + }, + } +} +//# sourceMappingURL=hash-to-curve.js.map diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.js.map b/packages/noble-curves/esm/abstract/hash-to-curve.js.map new file mode 100644 index 00000000000..e0029c11254 --- /dev/null +++ b/packages/noble-curves/esm/abstract/hash-to-curve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-to-curve.js","sourceRoot":"","sources":["../../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/modular.d.ts b/packages/noble-curves/esm/abstract/modular.d.ts new file mode 100644 index 00000000000..c95a932142e --- /dev/null +++ b/packages/noble-curves/esm/abstract/modular.d.ts @@ -0,0 +1,168 @@ +export declare function mod(a: bigint, b: bigint): bigint +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export declare function invert(number: bigint, modulo: bigint): bigint +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export declare function tonelliShanks(P: bigint): (Fp: IField, n: T) => T +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export declare function FpSqrt(P: bigint): (Fp: IField, n: T) => T +export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean +/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ +export interface IField { + ORDER: bigint + isLE: boolean + BYTES: number + BITS: number + MASK: bigint + ZERO: T + ONE: T + create: (num: T) => T + isValid: (num: T) => boolean + is0: (num: T) => boolean + neg(num: T): T + inv(num: T): T + sqrt(num: T): T + sqr(num: T): T + eql(lhs: T, rhs: T): boolean + add(lhs: T, rhs: T): T + sub(lhs: T, rhs: T): T + mul(lhs: T, rhs: T | bigint): T + pow(lhs: T, power: bigint): T + div(lhs: T, rhs: T | bigint): T + addN(lhs: T, rhs: T): T + subN(lhs: T, rhs: T): T + mulN(lhs: T, rhs: T | bigint): T + sqrN(num: T): T + isOdd?(num: T): boolean + pow(lhs: T, power: bigint): T + invertBatch: (lst: T[]) => T[] + toBytes(num: T): Uint8Array + fromBytes(bytes: Uint8Array): T + cmov(a: T, b: T, c: boolean): T +} +export declare function validateField(field: IField): IField +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export declare function FpPow(f: IField, num: T, power: bigint): T +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export declare function FpInvertBatch(f: IField, nums: T[]): T[] +export declare function FpDiv(f: IField, lhs: T, rhs: T | bigint): T +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export declare function FpLegendre(order: bigint): (f: IField, x: T) => T +export declare function FpIsSquare(f: IField): (x: T) => boolean +export declare function nLength( + n: bigint, + nBitLength?: number, +): { + nBitLength: number + nByteLength: number +} +type FpField = IField & Required, 'isOdd'>> +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export declare function Field( + ORDER: bigint, + bitLen?: number, + isLE?: boolean, + redef?: Partial>, +): Readonly +export declare function FpSqrtOdd(Fp: IField, elm: T): T +export declare function FpSqrtEven(Fp: IField, elm: T): T +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export declare function hashToPrivateScalar( + hash: string | Uint8Array, + groupOrder: bigint, + isLE?: boolean, +): bigint +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export declare function getFieldBytesLength(fieldOrder: bigint): number +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export declare function getMinHashLength(fieldOrder: bigint): number +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export declare function mapHashToField( + key: Uint8Array, + fieldOrder: bigint, + isLE?: boolean, +): Uint8Array +export {} +//# sourceMappingURL=modular.d.ts.map diff --git a/packages/noble-curves/esm/abstract/modular.d.ts.map b/packages/noble-curves/esm/abstract/modular.d.ts.map new file mode 100644 index 00000000000..474d7bc0d0b --- /dev/null +++ b/packages/noble-curves/esm/abstract/modular.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"modular.d.ts","sourceRoot":"","sources":["../../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/modular.js b/packages/noble-curves/esm/abstract/modular.js new file mode 100644 index 00000000000..c0797abdde6 --- /dev/null +++ b/packages/noble-curves/esm/abstract/modular.js @@ -0,0 +1,464 @@ +/** + * Utils for modular division and finite fields. + * A finite field over 11 is integer number operations `mod 11`. + * There is no division: it is replaced by modular multiplicative inverse. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + bitMask, + bytesToNumberBE, + bytesToNumberLE, + ensureBytes, + numberToBytesBE, + numberToBytesLE, + validateObject, +} from './utils.js' +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = /* @__PURE__ */ BigInt(2), + _3n = /* @__PURE__ */ BigInt(3) +// prettier-ignore +const _4n = /* @__PURE__ */ BigInt(4), + _5n = /* @__PURE__ */ BigInt(5), + _8n = /* @__PURE__ */ BigInt(8) +// prettier-ignore +const _9n = /* @__PURE__ */ BigInt(9), + _16n = /* @__PURE__ */ BigInt(16) +// Calculates a modulo b +export function mod(a, b) { + const result = a % b + return result >= _0n ? result : b + result +} +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export function pow(num, power, modulo) { + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (modulo <= _0n) throw new Error('invalid modulus') + 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 +} +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export function pow2(x, power, modulo) { + let res = x + while (power-- > _0n) { + res *= res + res %= modulo + } + return res +} +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export function invert(number, modulo) { + if (number === _0n) throw new Error('invert: expected non-zero number') + if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) + // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. + let a = mod(number, modulo) + let b = modulo + // prettier-ignore + let x = _0n, + y = _1n, + u = _1n, + v = _0n + while (a !== _0n) { + // JIT applies optimization if those two lines follow each other + const q = b / a + const r = b % a + const m = x - u * q + const n = y - v * q + // prettier-ignore + ;(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) +} +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export function tonelliShanks(P) { + // Legendre constant: used to calculate Legendre symbol (a | p), + // which denotes the value of a^((p-1)/2) (mod p). + // (a | p) ≡ 1 if a is a square (mod p) + // (a | p) ≡ -1 if a is not a square (mod p) + // (a | p) ≡ 0 if a ≡ 0 (mod p) + const legendreC = (P - _1n) / _2n + let Q, S, Z + // Step 1: By factoring out powers of 2 from p - 1, + // find q and s such that p - 1 = q*(2^s) with q odd + for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); + // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq + for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { + // Crash instead of infinity loop, we cannot reasonable count until P. + if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') + } + // Fast-path + if (S === 1) { + const p1div4 = (P + _1n) / _4n + return function tonelliFast(Fp, n) { + const root = Fp.pow(n, p1div4) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // Slow-path + const Q1div2 = (Q + _1n) / _2n + return function tonelliSlow(Fp, n) { + // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 + if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') + let r = S + // TODO: will fail at Fp2/etc + let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b + let x = Fp.pow(n, Q1div2) // first guess at the square root + let b = Fp.pow(n, Q) // first guess at the fudge factor + while (!Fp.eql(b, Fp.ONE)) { + if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) + // Find m such b^(2^m)==1 + let m = 1 + for (let t2 = Fp.sqr(b); m < r; m++) { + if (Fp.eql(t2, Fp.ONE)) break + t2 = Fp.sqr(t2) // t2 *= t2 + } + // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow + const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) + g = Fp.sqr(ge) // g = ge * ge + x = Fp.mul(x, ge) // x *= ge + b = Fp.mul(b, g) // b *= g + r = m + } + return x + } +} +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export function FpSqrt(P) { + // P ≡ 3 (mod 4) + // √n = n^((P+1)/4) + if (P % _4n === _3n) { + // Not all roots possible! + // const ORDER = + // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; + // const NUM = 72057594037927816n; + const p1div4 = (P + _1n) / _4n + return function sqrt3mod4(Fp, n) { + const root = Fp.pow(n, p1div4) + // Throw if root**2 != n + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) + if (P % _8n === _5n) { + const c1 = (P - _5n) / _8n + return function sqrt5mod8(Fp, n) { + const n2 = Fp.mul(n, _2n) + const v = Fp.pow(n2, c1) + const nv = Fp.mul(n, v) + const i = Fp.mul(Fp.mul(nv, _2n), v) + const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + // P ≡ 9 (mod 16) + if (P % _16n === _9n) { + // NOTE: tonelli is too slow for bls-Fp2 calculations even on start + // Means we cannot use sqrt for constants at all! + // + // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F + // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F + // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F + // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic + // sqrt = (x) => { + // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 + // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 + // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 + // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 + // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x + // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x + // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x + // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x + // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x + // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 + // } + } + // Other cases: Tonelli-Shanks algorithm + return tonelliShanks(P) +} +// Little-endian check for first LE bit (last BE bit); +export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n +// prettier-ignore +const FIELD_FIELDS = [ + 'create', + 'isValid', + 'is0', + 'neg', + 'inv', + 'sqrt', + 'sqr', + 'eql', + 'add', + 'sub', + 'mul', + 'pow', + 'div', + 'addN', + 'subN', + 'mulN', + 'sqrN', +] +export function validateField(field) { + const initial = { + ORDER: 'bigint', + MASK: 'bigint', + BYTES: 'isSafeInteger', + BITS: 'isSafeInteger', + } + const opts = FIELD_FIELDS.reduce((map, val) => { + map[val] = 'function' + return map + }, initial) + return validateObject(field, opts) +} +// Generic field functions +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export function FpPow(f, num, power) { + // Should have same speed as pow for bigints + // TODO: benchmark! + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (power === _0n) return f.ONE + if (power === _1n) return num + let p = f.ONE + let d = num + while (power > _0n) { + if (power & _1n) p = f.mul(p, d) + d = f.sqr(d) + power >>= _1n + } + return p +} +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export function FpInvertBatch(f, nums) { + const tmp = new Array(nums.length) + // Walk from first to last, multiply them by each other MOD p + const lastMultiplied = nums.reduce((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = acc + return f.mul(acc, num) + }, f.ONE) + // Invert last element + const inverted = f.inv(lastMultiplied) + // Walk from last to first, multiply them by inverted each other MOD p + nums.reduceRight((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = f.mul(acc, tmp[i]) + return f.mul(acc, num) + }, inverted) + return tmp +} +export function FpDiv(f, lhs, rhs) { + return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) +} +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export function FpLegendre(order) { + const legendreConst = (order - _1n) / _2n // Integer arithmetic + return (f, x) => f.pow(x, legendreConst) +} +// This function returns True whenever the value x is a square in the field F. +export function FpIsSquare(f) { + const legendre = FpLegendre(f.ORDER) + return (x) => { + const p = legendre(f, x) + return f.eql(p, f.ZERO) || f.eql(p, f.ONE) + } +} +// CURVE.n lengths +export function nLength(n, nBitLength) { + // Bit size, byte size of CURVE.n + const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length + const nByteLength = Math.ceil(_nBitLength / 8) + return { nBitLength: _nBitLength, nByteLength } +} +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export function Field(ORDER, bitLen, isLE = false, redef = {}) { + if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) + const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) + if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') + let sqrtP // cached sqrtP + const f = Object.freeze({ + ORDER, + isLE, + BITS, + BYTES, + MASK: bitMask(BITS), + ZERO: _0n, + ONE: _1n, + create: (num) => mod(num, ORDER), + isValid: (num) => { + if (typeof num !== 'bigint') + throw new Error('invalid field element: expected bigint, got ' + typeof num) + return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible + }, + is0: (num) => num === _0n, + isOdd: (num) => (num & _1n) === _1n, + neg: (num) => mod(-num, ORDER), + eql: (lhs, rhs) => lhs === rhs, + sqr: (num) => mod(num * num, ORDER), + add: (lhs, rhs) => mod(lhs + rhs, ORDER), + sub: (lhs, rhs) => mod(lhs - rhs, ORDER), + mul: (lhs, rhs) => mod(lhs * rhs, ORDER), + pow: (num, power) => FpPow(f, num, power), + div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + // Same as above, but doesn't normalize + sqrN: (num) => num * num, + addN: (lhs, rhs) => lhs + rhs, + subN: (lhs, rhs) => lhs - rhs, + mulN: (lhs, rhs) => lhs * rhs, + inv: (num) => invert(num, ORDER), + sqrt: + redef.sqrt || + ((n) => { + if (!sqrtP) sqrtP = FpSqrt(ORDER) + return sqrtP(f, n) + }), + invertBatch: (lst) => FpInvertBatch(f, lst), + // TODO: do we really need constant cmov? + // We don't have const-time bigints anyway, so probably will be not very useful + cmov: (a, b, c) => (c ? b : a), + toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), + fromBytes: (bytes) => { + if (bytes.length !== BYTES) + throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) + return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) + }, + }) + return Object.freeze(f) +} +export function FpSqrtOdd(Fp, elm) { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? root : Fp.neg(root) +} +export function FpSqrtEven(Fp, elm) { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? Fp.neg(root) : root +} +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export function hashToPrivateScalar(hash, groupOrder, isLE = false) { + hash = ensureBytes('privateHash', hash) + const hashLen = hash.length + const minLen = nLength(groupOrder).nByteLength + 8 + if (minLen < 24 || hashLen < minLen || hashLen > 1024) + throw new Error( + 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, + ) + const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) + return mod(num, groupOrder - _1n) + _1n +} +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export function getFieldBytesLength(fieldOrder) { + if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') + const bitLength = fieldOrder.toString(2).length + return Math.ceil(bitLength / 8) +} +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export function getMinHashLength(fieldOrder) { + const length = getFieldBytesLength(fieldOrder) + return length + Math.ceil(length / 2) +} +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export function mapHashToField(key, fieldOrder, isLE = false) { + const len = key.length + const fieldLen = getFieldBytesLength(fieldOrder) + const minLen = getMinHashLength(fieldOrder) + // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. + if (len < 16 || len < minLen || len > 1024) + throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) + const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) + // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 + const reduced = mod(num, fieldOrder - _1n) + _1n + return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) +} +//# sourceMappingURL=modular.js.map diff --git a/packages/noble-curves/esm/abstract/modular.js.map b/packages/noble-curves/esm/abstract/modular.js.map new file mode 100644 index 00000000000..748f7405a2c --- /dev/null +++ b/packages/noble-curves/esm/abstract/modular.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modular.js","sourceRoot":"","sources":["../../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/montgomery.d.ts b/packages/noble-curves/esm/abstract/montgomery.d.ts new file mode 100644 index 00000000000..64a01ea5d1c --- /dev/null +++ b/packages/noble-curves/esm/abstract/montgomery.d.ts @@ -0,0 +1,26 @@ +type Hex = string | Uint8Array +export type CurveType = { + P: bigint + nByteLength: number + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + a: bigint + montgomeryBits: number + powPminus2?: (x: bigint) => bigint + xyToU?: (x: bigint, y: bigint) => bigint + Gu: bigint + randomBytes?: (bytesLength?: number) => Uint8Array +} +export type CurveFn = { + scalarMult: (scalar: Hex, u: Hex) => Uint8Array + scalarMultBase: (scalar: Hex) => Uint8Array + getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array + getPublicKey: (privateKey: Hex) => Uint8Array + utils: { + randomPrivateKey: () => Uint8Array + } + GuBytes: Uint8Array +} +export declare function montgomery(curveDef: CurveType): CurveFn +export {} +//# sourceMappingURL=montgomery.d.ts.map diff --git a/packages/noble-curves/esm/abstract/montgomery.d.ts.map b/packages/noble-curves/esm/abstract/montgomery.d.ts.map new file mode 100644 index 00000000000..28cc704eb38 --- /dev/null +++ b/packages/noble-curves/esm/abstract/montgomery.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"AAkBA,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACtD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC;IAC5E,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IACnE,YAAY,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAC9C,KAAK,EAAE;QAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;KAAE,CAAC;IAC9C,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAsBF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAqIvD"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/montgomery.js b/packages/noble-curves/esm/abstract/montgomery.js new file mode 100644 index 00000000000..d08a39f1318 --- /dev/null +++ b/packages/noble-curves/esm/abstract/montgomery.js @@ -0,0 +1,159 @@ +/** + * Montgomery curve methods. It's not really whole montgomery curve, + * just bunch of very specific methods for X25519 / X448 from + * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { mod, pow } from './modular.js' +import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.js' +const _0n = BigInt(0) +const _1n = BigInt(1) +function validateOpts(curve) { + validateObject( + curve, + { + a: 'bigint', + }, + { + montgomeryBits: 'isSafeInteger', + nByteLength: 'isSafeInteger', + adjustScalarBytes: 'function', + domain: 'function', + powPminus2: 'function', + Gu: 'bigint', + }, + ) + // Set defaults + return Object.freeze({ ...curve }) +} +// Uses only one coordinate instead of two +export function montgomery(curveDef) { + const CURVE = validateOpts(curveDef) + const { P } = CURVE + const modP = (n) => mod(n, P) + const montgomeryBits = CURVE.montgomeryBits + const montgomeryBytes = Math.ceil(montgomeryBits / 8) + const fieldLen = CURVE.nByteLength + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) + const powPminus2 = CURVE.powPminus2 || ((x) => pow(x, P - BigInt(2), P)) + // cswap from RFC7748. But it is not from RFC7748! + /* + cswap(swap, x_2, x_3): + dummy = mask(swap) AND (x_2 XOR x_3) + x_2 = x_2 XOR dummy + x_3 = x_3 XOR dummy + Return (x_2, x_3) + Where mask(swap) is the all-1 or all-0 word of the same length as x_2 + and x_3, computed, e.g., as mask(swap) = 0 - swap. + */ + function cswap(swap, x_2, x_3) { + const dummy = modP(swap * (x_2 - x_3)) + x_2 = modP(x_2 - dummy) + x_3 = modP(x_3 + dummy) + return [x_2, x_3] + } + // x25519 from 4 + // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 + const a24 = (CURVE.a - BigInt(2)) / BigInt(4) + /** + * + * @param pointU u coordinate (x) on Montgomery Curve 25519 + * @param scalar by which the point would be multiplied + * @returns new Point on Montgomery curve + */ + function montgomeryLadder(u, scalar) { + aInRange('u', u, _0n, P) + aInRange('scalar', scalar, _0n, P) + // Section 5: Implementations MUST accept non-canonical values and process them as + // if they had been reduced modulo the field prime. + const k = scalar + const x_1 = u + let x_2 = _1n + let z_2 = _0n + let x_3 = u + let z_3 = _1n + let swap = _0n + let sw + for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { + const k_t = (k >> t) & _1n + swap ^= k_t + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + swap = k_t + const A = x_2 + z_2 + const AA = modP(A * A) + const B = x_2 - z_2 + const BB = modP(B * B) + const E = AA - BB + const C = x_3 + z_3 + const D = x_3 - z_3 + const DA = modP(D * A) + const CB = modP(C * B) + const dacb = DA + CB + const da_cb = DA - CB + x_3 = modP(dacb * dacb) + z_3 = modP(x_1 * modP(da_cb * da_cb)) + x_2 = modP(AA * BB) + z_2 = modP(E * (AA + modP(a24 * E))) + } + // (x_2, x_3) = cswap(swap, x_2, x_3) + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + // (z_2, z_3) = cswap(swap, z_2, z_3) + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + // z_2^(p - 2) + const z2 = powPminus2(z_2) + // Return x_2 * (z_2^(p - 2)) + return modP(x_2 * z2) + } + function encodeUCoordinate(u) { + return numberToBytesLE(modP(u), montgomeryBytes) + } + function decodeUCoordinate(uEnc) { + // Section 5: When receiving such an array, implementations of X25519 + // MUST mask the most significant bit in the final byte. + const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) + if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 + return bytesToNumberLE(u) + } + function decodeScalar(n) { + const bytes = ensureBytes('scalar', n) + const len = bytes.length + if (len !== montgomeryBytes && len !== fieldLen) { + let valid = '' + montgomeryBytes + ' or ' + fieldLen + throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) + } + return bytesToNumberLE(adjustScalarBytes(bytes)) + } + function scalarMult(scalar, u) { + const pointU = decodeUCoordinate(u) + const _scalar = decodeScalar(scalar) + const pu = montgomeryLadder(pointU, _scalar) + // The result was not contributory + // https://cr.yp.to/ecdh.html#validate + if (pu === _0n) throw new Error('invalid private or public key received') + return encodeUCoordinate(pu) + } + // Computes public key from private. By doing scalar multiplication of base point. + const GuBytes = encodeUCoordinate(CURVE.Gu) + function scalarMultBase(scalar) { + return scalarMult(scalar, GuBytes) + } + return { + scalarMult, + scalarMultBase, + getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey), + getPublicKey: (privateKey) => scalarMultBase(privateKey), + utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) }, + GuBytes: GuBytes, + } +} +//# sourceMappingURL=montgomery.js.map diff --git a/packages/noble-curves/esm/abstract/montgomery.js.map b/packages/noble-curves/esm/abstract/montgomery.js.map new file mode 100644 index 00000000000..654013b6480 --- /dev/null +++ b/packages/noble-curves/esm/abstract/montgomery.js.map @@ -0,0 +1 @@ +{"version":3,"file":"montgomery.js","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/poseidon.d.ts b/packages/noble-curves/esm/abstract/poseidon.d.ts new file mode 100644 index 00000000000..37c473b1465 --- /dev/null +++ b/packages/noble-curves/esm/abstract/poseidon.d.ts @@ -0,0 +1,39 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField } from './modular.js' +export type PoseidonOpts = { + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean + mds: bigint[][] + roundConstants: bigint[][] +} +export declare function validateOpts(opts: PoseidonOpts): Readonly<{ + rounds: number + sboxFn: (n: bigint) => bigint + roundConstants: bigint[][] + mds: bigint[][] + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean +}> +export declare function splitConstants(rc: bigint[], t: number): bigint[][] +/** Poseidon NTT-friendly hash. */ +export declare function poseidon(opts: PoseidonOpts): { + (values: bigint[]): bigint[] + roundConstants: bigint[][] +} +//# sourceMappingURL=poseidon.d.ts.map diff --git a/packages/noble-curves/esm/abstract/poseidon.d.ts.map b/packages/noble-curves/esm/abstract/poseidon.d.ts.map new file mode 100644 index 00000000000..50b61631c9a --- /dev/null +++ b/packages/noble-curves/esm/abstract/poseidon.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"poseidon.d.ts","sourceRoot":"","sources":["../../src/abstract/poseidon.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sEAAsE;AACtE,OAAO,EAAS,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,CA6CD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAalE;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG;IAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAE7B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAmCA"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/poseidon.js b/packages/noble-curves/esm/abstract/poseidon.js new file mode 100644 index 00000000000..b169136f07d --- /dev/null +++ b/packages/noble-curves/esm/abstract/poseidon.js @@ -0,0 +1,99 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { FpPow, validateField } from './modular.js' +export function validateOpts(opts) { + const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts + const { roundsFull, roundsPartial, sboxPower, t } = opts + validateField(Fp) + for (const i of ['t', 'roundsFull', 'roundsPartial']) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + // MDS is TxT matrix + if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') + const _mds = mds.map((mdsRow) => { + if (!Array.isArray(mdsRow) || mdsRow.length !== t) + throw new Error('invalid MDS matrix row: ' + mdsRow) + return mdsRow.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) + return Fp.create(i) + }) + }) + if (rev !== undefined && typeof rev !== 'boolean') + throw new Error('invalid param reversePartialPowIdx=' + rev) + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) + const rounds = roundsFull + roundsPartial + if (!Array.isArray(rc) || rc.length !== rounds) + throw new Error('Poseidon: invalid round constants') + const roundConstants = rc.map((rc) => { + if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') + return rc.map((i) => { + if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') + return Fp.create(i) + }) + }) + if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') + const _sboxPower = BigInt(sboxPower) + let sboxFn = (n) => FpPow(Fp, n, _sboxPower) + // Unwrapped sbox power for common cases (195->142μs) + if (sboxPower === 3) sboxFn = (n) => Fp.mul(Fp.sqrN(n), n) + else if (sboxPower === 5) sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) + return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) +} +export function splitConstants(rc, t) { + if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') + if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') + const res = [] + let tmp = [] + for (let i = 0; i < rc.length; i++) { + tmp.push(rc[i]) + if (tmp.length === t) { + res.push(tmp) + tmp = [] + } + } + return res +} +/** Poseidon NTT-friendly hash. */ +export function poseidon(opts) { + const _opts = validateOpts(opts) + const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts + const halfRoundsFull = _opts.roundsFull / 2 + const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 + const poseidonRound = (values, isFull, idx) => { + values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) + if (isFull) values = values.map((i) => sboxFn(i)) + else values[partialIdx] = sboxFn(values[partialIdx]) + // Matrix multiplication + values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) + return values + } + const poseidonHash = function poseidonHash(values) { + if (!Array.isArray(values) || values.length !== t) + throw new Error('invalid values, expected array of bigints with length ' + t) + values = values.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) + return Fp.create(i) + }) + let lastRound = 0 + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + // Apply r_p partial rounds. + for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + if (lastRound !== totalRounds) throw new Error('invalid number of rounds') + return values + } + // For verification in tests + poseidonHash.roundConstants = roundConstants + return poseidonHash +} +//# sourceMappingURL=poseidon.js.map diff --git a/packages/noble-curves/esm/abstract/poseidon.js.map b/packages/noble-curves/esm/abstract/poseidon.js.map new file mode 100644 index 00000000000..8292dcc8b08 --- /dev/null +++ b/packages/noble-curves/esm/abstract/poseidon.js.map @@ -0,0 +1 @@ +{"version":3,"file":"poseidon.js","sourceRoot":"","sources":["../../src/abstract/poseidon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/tower.d.ts b/packages/noble-curves/esm/abstract/tower.d.ts new file mode 100644 index 00000000000..34d68c39e3b --- /dev/null +++ b/packages/noble-curves/esm/abstract/tower.d.ts @@ -0,0 +1,126 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.js' +import type { ProjConstructor, ProjPointType } from './weierstrass.js' +export type BigintTuple = [bigint, bigint] +export type Fp = bigint +export type Fp2 = { + c0: bigint + c1: bigint +} +export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] +export type Fp6 = { + c0: Fp2 + c1: Fp2 + c2: Fp2 +} +export type Fp12 = { + c0: Fp6 + c1: Fp6 +} +export type BigintTwelve = [ + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, +] +export type Fp2Bls = mod.IField & { + reim: (num: Fp2) => { + re: Fp + im: Fp + } + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + fromBigTuple(num: [bigint, bigint]): Fp2 +} +export type Fp12Bls = mod.IField & { + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + fromBigTwelve(num: BigintTwelve): Fp12 +} +export declare function psiFrobenius( + Fp: mod.IField, + Fp2: Fp2Bls, + base: Fp2, +): { + psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] + psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] + G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType + G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType + PSI_X: Fp2 + PSI_Y: Fp2 + PSI2_X: Fp2 + PSI2_Y: Fp2 +} +export type Tower12Opts = { + ORDER: bigint + NONRESIDUE?: Fp + FP2_NONRESIDUE: BigintTuple + Fp2sqrt?: (num: Fp2) => Fp2 + Fp2mulByB: (num: Fp2) => Fp2 + Fp12cyclotomicSquare: (num: Fp12) => Fp12 + Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 + Fp12finalExponentiate: (num: Fp12) => Fp12 +} +export declare function tower12(opts: Tower12Opts): { + Fp: Readonly & Required, 'isOdd'>>> + Fp2: mod.IField & { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { + re: bigint + im: bigint + } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + Fp6: mod.IField & { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + Fp4Square: ( + a: Fp2, + b: Fp2, + ) => { + first: Fp2 + second: Fp2 + } + Fp12: mod.IField & { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } +} +//# sourceMappingURL=tower.d.ts.map diff --git a/packages/noble-curves/esm/abstract/tower.d.ts.map b/packages/noble-curves/esm/abstract/tower.d.ts.map new file mode 100644 index 00000000000..6d00d9f1c9b --- /dev/null +++ b/packages/noble-curves/esm/abstract/tower.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"tower.d.ts","sourceRoot":"","sources":["../../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/tower.js b/packages/noble-curves/esm/abstract/tower.js new file mode 100644 index 00000000000..b2eaa6f69f8 --- /dev/null +++ b/packages/noble-curves/esm/abstract/tower.js @@ -0,0 +1,515 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.js' +import { bitLen, bitMask, concatBytes, notImplemented } from './utils.js' +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) { + const _divisor = BigInt(divisor === undefined ? degree : divisor) + const towerModulus = modulus ** BigInt(degree) + const res = [] + for (let i = 0; i < num; i++) { + const a = BigInt(i + 1) + const powers = [] + for (let j = 0, qPower = _1n; j < degree; j++) { + const power = ((a * qPower - a) / _divisor) % towerModulus + powers.push(Fp.pow(nonResidue, power)) + qPower *= modulus + } + res.push(powers) + } + return res +} +// This works same at least for bls12-381, bn254 and bls12-377 +export function psiFrobenius(Fp, Fp2, base) { + // Ψ endomorphism + const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) + const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) + function psi(x, y) { + // This x10 faster than previous version in bls12-381 + const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) + const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) + return [x2, y2] + } + // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) + const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) + // This equals -1, which causes y to be Fp2.neg(y). + // But not sure if there are case when this is not true? + const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) + if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') + function psi2(x, y) { + return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] + } + // Map points + const mapAffine = (fn) => (c, P) => { + const affine = P.toAffine() + const p = fn(affine.x, affine.y) + return c.fromAffine({ x: p[0], y: p[1] }) + } + const G2psi = mapAffine(psi) + const G2psi2 = mapAffine(psi2) + return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } +} +export function tower12(opts) { + const { ORDER } = opts + // Fp + const Fp = mod.Field(ORDER) + const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) + const FpLegendre = mod.FpLegendre(ORDER) + const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 + // Fp2 + const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] + const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp.add(c0, r0), + c1: Fp.add(c1, r1), + }) + const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp.sub(c0, r0), + c1: Fp.sub(c1, r1), + }) + const Fp2Multiply = ({ c0, c1 }, rhs) => { + if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } + // (a+bi)(c+di) = (ac−bd) + (ad+bc)i + const { c0: r0, c1: r1 } = rhs + let t1 = Fp.mul(c0, r0) // c0 * o0 + let t2 = Fp.mul(c1, r1) // c1 * o1 + // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i + const o0 = Fp.sub(t1, t2) + const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) + return { c0: o0, c1: o1 } + } + const Fp2Square = ({ c0, c1 }) => { + const a = Fp.add(c0, c1) + const b = Fp.sub(c0, c1) + const c = Fp.add(c0, c0) + return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } + } + const Fp2fromBigTuple = (tuple) => { + if (tuple.length !== 2) throw new Error('invalid tuple') + const fps = tuple.map((n) => Fp.create(n)) + return { c0: fps[0], c1: fps[1] } + } + const FP2_ORDER = ORDER * ORDER + const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) + const Fp2 = { + ORDER: FP2_ORDER, + isLE: Fp.isLE, + NONRESIDUE: Fp2Nonresidue, + BITS: bitLen(FP2_ORDER), + BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), + MASK: bitMask(bitLen(FP2_ORDER)), + ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, + ONE: { c0: Fp.ONE, c1: Fp.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', + is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1), + neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), + pow: (num, power) => mod.FpPow(Fp2, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), + // Normalized + add: Fp2Add, + sub: Fp2Subtract, + mul: Fp2Multiply, + sqr: Fp2Square, + // NonNormalized stuff + addN: Fp2Add, + subN: Fp2Subtract, + mulN: Fp2Multiply, + sqrN: Fp2Square, + // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? + div: (lhs, rhs) => + Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), + inv: ({ c0: a, c1: b }) => { + // We wish to find the multiplicative inverse of a nonzero + // element a + bu in Fp2. We leverage an identity + // + // (a + bu)(a - bu) = a² + b² + // + // which holds because u² = -1. This can be rewritten as + // + // (a + bu)(a - bu)/(a² + b²) = 1 + // + // because a² + b² = 0 has no nonzero solutions for (a, b). + // This gives that (a - bu)/(a² + b²) is the inverse + // of (a + bu). Importantly, this can be computing using + // only a single inversion in Fp. + const factor = Fp.inv(Fp.create(a * a + b * b)) + return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } + }, + sqrt: (num) => { + if (opts.Fp2sqrt) return opts.Fp2sqrt(num) + // This is generic for all quadratic extensions (Fp2) + const { c0, c1 } = num + if (Fp.is0(c1)) { + // if c0 is quadratic residue + if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) + else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) + } + const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) + let d = Fp.mul(Fp.add(a, c0), Fpdiv2) + const legendre = FpLegendre(Fp, d) + // -1, Quadratic non residue + if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) + const a0 = Fp.sqrt(d) + const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) + if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') + // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num + const x1 = candidateSqrt + const x2 = Fp2.neg(x1) + const { re: re1, im: im1 } = Fp2.reim(x1) + const { re: re2, im: im2 } = Fp2.reim(x2) + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 + return x2 + }, + // Same as sgn0_m_eq_2 in RFC 9380 + isOdd: (x) => { + const { re: x0, im: x1 } = Fp2.reim(x) + const sign_0 = x0 % _2n + const zero_0 = x0 === _0n + const sign_1 = x1 % _2n + return BigInt(sign_0 || (zero_0 && sign_1)) == _1n + }, + // Bytes util + fromBytes(b) { + if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } + }, + toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp.cmov(c0, r0, c), + c1: Fp.cmov(c1, r1, c), + }), + reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), + // multiply by u + 1 + mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), + mulByB: opts.Fp2mulByB, + fromBigTuple: Fp2fromBigTuple, + frobeniusMap: ({ c0, c1 }, power) => ({ + c0, + c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), + }), + } + // Fp6 + const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ + c0: Fp2.add(c0, r0), + c1: Fp2.add(c1, r1), + c2: Fp2.add(c2, r2), + }) + const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ + c0: Fp2.sub(c0, r0), + c1: Fp2.sub(c1, r1), + c2: Fp2.sub(c2, r2), + }) + const Fp6Multiply = ({ c0, c1, c2 }, rhs) => { + if (typeof rhs === 'bigint') { + return { + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + } + } + const { c0: r0, c1: r1, c2: r2 } = rhs + const t0 = Fp2.mul(c0, r0) // c0 * o0 + const t1 = Fp2.mul(c1, r1) // c1 * o1 + const t2 = Fp2.mul(c2, r2) // c2 * o2 + return { + // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) + c0: Fp2.add( + t0, + Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), + ), + // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) + c1: Fp2.add( + Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), + Fp2.mulByNonresidue(t2), + ), + // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 + c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), + } + } + const Fp6Square = ({ c0, c1, c2 }) => { + let t0 = Fp2.sqr(c0) // c0² + let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 + let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 + let t4 = Fp2.sqr(c2) // c2² + return { + c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 + c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 + // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 + c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), + } + } + const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 6, + 2, + 3, + ) + const Fp6 = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp2.isLE, + BITS: 3 * Fp2.BITS, + BYTES: 3 * Fp2.BYTES, + MASK: bitMask(3 * Fp2.BITS), + ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, + ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, + create: (num) => num, + isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), + is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), + neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), + eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => + Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), + sqrt: notImplemented, + // Do we need division by bigint at all? Should be done via order: + div: (lhs, rhs) => + Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp6, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), + // Normalized + add: Fp6Add, + sub: Fp6Subtract, + mul: Fp6Multiply, + sqr: Fp6Square, + // NonNormalized stuff + addN: Fp6Add, + subN: Fp6Subtract, + mulN: Fp6Multiply, + sqrN: Fp6Square, + inv: ({ c0, c1, c2 }) => { + let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) + let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 + let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 + // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) + let t4 = Fp2.inv( + Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), + ) + return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } + }, + // Bytes utils + fromBytes: (b) => { + if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), + c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), + c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), + } + }, + toBytes: ({ c0, c1, c2 }) => concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), + cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({ + c0: Fp2.cmov(c0, r0, c), + c1: Fp2.cmov(c1, r1, c), + c2: Fp2.cmov(c2, r2, c), + }), + fromBigSix: (t) => { + if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') + return { + c0: Fp2.fromBigTuple(t.slice(0, 2)), + c1: Fp2.fromBigTuple(t.slice(2, 4)), + c2: Fp2.fromBigTuple(t.slice(4, 6)), + } + }, + frobeniusMap: ({ c0, c1, c2 }, power) => ({ + c0: Fp2.frobeniusMap(c0, power), + c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + }), + mulByFp2: ({ c0, c1, c2 }, rhs) => ({ + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + }), + mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), + // Sparse multiplication + mul1: ({ c0, c1, c2 }, b1) => ({ + c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), + c1: Fp2.mul(c0, b1), + c2: Fp2.mul(c1, b1), + }), + // Sparse multiplication + mul01({ c0, c1, c2 }, b0, b1) { + let t0 = Fp2.mul(c0, b0) // c0 * b0 + let t1 = Fp2.mul(c1, b1) // c1 * b1 + return { + // ((c1 + c2) * b1 - T1) * (u + 1) + T0 + c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), + // (b0 + b1) * (c0 + c1) - T0 - T1 + c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), + // (c0 + c2) * b0 - T0 + T1 + c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), + } + }, + } + // Fp12 + const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 12, + 1, + 6, + )[0] + const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp6.add(c0, r0), + c1: Fp6.add(c1, r1), + }) + const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ + c0: Fp6.sub(c0, r0), + c1: Fp6.sub(c1, r1), + }) + const Fp12Multiply = ({ c0, c1 }, rhs) => { + if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } + let { c0: r0, c1: r1 } = rhs + let t1 = Fp6.mul(c0, r0) // c0 * r0 + let t2 = Fp6.mul(c1, r1) // c1 * r1 + return { + c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v + // (c0 + c1) * (r0 + r1) - (T1 + T2) + c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), + } + } + const Fp12Square = ({ c0, c1 }) => { + let ab = Fp6.mul(c0, c1) // c0 * c1 + return { + // (c1 * v + c0) * (c0 + c1) - AB - AB * v + c0: Fp6.sub( + Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), + Fp6.mulByNonresidue(ab), + ), + c1: Fp6.add(ab, ab), + } // AB + AB + } + function Fp4Square(a, b) { + const a2 = Fp2.sqr(a) + const b2 = Fp2.sqr(b) + return { + first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² + second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² + } + } + const Fp12 = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp6.isLE, + BITS: 2 * Fp2.BITS, + BYTES: 2 * Fp2.BYTES, + MASK: bitMask(2 * Fp2.BITS), + ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, + ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), + is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), + neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), + sqrt: notImplemented, + inv: ({ c0, c1 }) => { + let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) + return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w + }, + div: (lhs, rhs) => + Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp12, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), + // Normalized + add: Fp12Add, + sub: Fp12Subtract, + mul: Fp12Multiply, + sqr: Fp12Square, + // NonNormalized stuff + addN: Fp12Add, + subN: Fp12Subtract, + mulN: Fp12Multiply, + sqrN: Fp12Square, + // Bytes utils + fromBytes: (b) => { + if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), + c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), + } + }, + toBytes: ({ c0, c1 }) => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp6.cmov(c0, r0, c), + c1: Fp6.cmov(c1, r1, c), + }), + // Utils + // toString() { + // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); + // }, + // fromTuple(c: [Fp6, Fp6]) { + // return new Fp12(...c); + // } + fromBigTwelve: (t) => ({ + c0: Fp6.fromBigSix(t.slice(0, 6)), + c1: Fp6.fromBigSix(t.slice(6, 12)), + }), + // Raises to q**i -th power + frobeniusMap(lhs, power) { + const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] + return { + c0: Fp6.frobeniusMap(lhs.c0, power), + c1: Fp6.create({ + c0: Fp2.mul(c0, coeff), + c1: Fp2.mul(c1, coeff), + c2: Fp2.mul(c2, coeff), + }), + } + }, + mulByFp2: ({ c0, c1 }, rhs) => ({ + c0: Fp6.mulByFp2(c0, rhs), + c1: Fp6.mulByFp2(c1, rhs), + }), + conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }), + // Sparse multiplication + mul014: ({ c0, c1 }, o0, o1, o4) => { + let t0 = Fp6.mul01(c0, o0, o1) + let t1 = Fp6.mul1(c1, o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 + // (c1 + c0) * [o0, o1+o4] - T0 - T1 + c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), + } + }, + mul034: ({ c0, c1 }, o0, o3, o4) => { + const a = Fp6.create({ + c0: Fp2.mul(c0.c0, o0), + c1: Fp2.mul(c0.c1, o0), + c2: Fp2.mul(c0.c2, o0), + }) + const b = Fp6.mul01(c1, o3, o4) + const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(b), a), + c1: Fp6.sub(e, Fp6.add(a, b)), + } + }, + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + _cyclotomicSquare: opts.Fp12cyclotomicSquare, + _cyclotomicExp: opts.Fp12cyclotomicExp, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + finalExponentiate: opts.Fp12finalExponentiate, + } + return { Fp, Fp2, Fp6, Fp4Square, Fp12 } +} +//# sourceMappingURL=tower.js.map diff --git a/packages/noble-curves/esm/abstract/tower.js.map b/packages/noble-curves/esm/abstract/tower.js.map new file mode 100644 index 00000000000..54014b5bad4 --- /dev/null +++ b/packages/noble-curves/esm/abstract/tower.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tower.js","sourceRoot":"","sources":["../../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/utils.d.ts b/packages/noble-curves/esm/abstract/utils.d.ts new file mode 100644 index 00000000000..405e6bef69d --- /dev/null +++ b/packages/noble-curves/esm/abstract/utils.d.ts @@ -0,0 +1,126 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +export type Hex = Uint8Array | string +export type PrivKey = Hex | bigint +export type CHash = { + (message: Uint8Array | string): Uint8Array + blockLen: number + outputLen: number + create(opts?: { + dkLen?: number + }): any +} +export type FHash = (message: Uint8Array | string) => Uint8Array +export declare function isBytes(a: unknown): a is Uint8Array +export declare function abytes(item: unknown): void +export declare function abool(title: string, value: boolean): void +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export declare function bytesToHex(bytes: Uint8Array): string +export declare function numberToHexUnpadded(num: number | bigint): string +export declare function hexToNumber(hex: string): bigint +/** + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export declare function hexToBytes(hex: string): Uint8Array +export declare function bytesToNumberBE(bytes: Uint8Array): bigint +export declare function bytesToNumberLE(bytes: Uint8Array): bigint +export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array +export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array +export declare function numberToVarBytesBE(n: number | bigint): Uint8Array +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export declare function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array +/** + * Copies several Uint8Arrays into one. + */ +export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array +export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export declare function utf8ToBytes(str: string): Uint8Array +export declare function inRange(n: bigint, min: bigint, max: bigint): boolean +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export declare function aInRange(title: string, n: bigint, min: bigint, max: bigint): void +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export declare function bitLen(n: bigint): number +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export declare function bitGet(n: bigint, pos: number): bigint +/** + * Sets single bit at position. + */ +export declare function bitSet(n: bigint, pos: number, value: boolean): bigint +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export declare const bitMask: (n: number) => bigint +type Pred = (v: Uint8Array) => T | undefined +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export declare function createHmacDrbg( + hashLen: number, + qByteLen: number, + hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, +): (seed: Uint8Array, predicate: Pred) => T +declare const validatorFns: { + readonly bigint: (val: any) => boolean + readonly function: (val: any) => boolean + readonly boolean: (val: any) => boolean + readonly string: (val: any) => boolean + readonly stringOrUint8Array: (val: any) => boolean + readonly isSafeInteger: (val: any) => boolean + readonly array: (val: any) => boolean + readonly field: (val: any, object: any) => any + readonly hash: (val: any) => boolean +} +type Validator = keyof typeof validatorFns +type ValMap> = { + [K in keyof T]?: Validator +} +export declare function validateObject>( + object: T, + validators: ValMap, + optValidators?: ValMap, +): T +/** + * throws not implemented error + */ +export declare const notImplemented: () => never +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export declare function memoized( + fn: (arg: T, ...args: O) => R, +): (arg: T, ...args: O) => R +export {} +//# sourceMappingURL=utils.d.ts.map diff --git a/packages/noble-curves/esm/abstract/utils.d.ts.map b/packages/noble-curves/esm/abstract/utils.d.ts.map new file mode 100644 index 00000000000..f49a4144c3d --- /dev/null +++ b/packages/noble-curves/esm/abstract/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/utils.js b/packages/noble-curves/esm/abstract/utils.js new file mode 100644 index 00000000000..28f2f999afe --- /dev/null +++ b/packages/noble-curves/esm/abstract/utils.js @@ -0,0 +1,311 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// 100 lines of code in the file are duplicated from noble-hashes (utils). +// This is OK: `abstract` directory does not use noble-hashes. +// User may opt-in into using different hashing library. This way, noble-hashes +// won't be included into their bundle. +const _0n = /* @__PURE__ */ BigInt(0) +const _1n = /* @__PURE__ */ BigInt(1) +const _2n = /* @__PURE__ */ BigInt(2) +export function isBytes(a) { + return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') +} +export function abytes(item) { + if (!isBytes(item)) throw new Error('Uint8Array expected') +} +export function abool(title, value) { + if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) +} +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export function bytesToHex(bytes) { + abytes(bytes) + // pre-caching improves the speed 6x + let hex = '' + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]] + } + return hex +} +export function numberToHexUnpadded(num) { + const hex = num.toString(16) + return hex.length & 1 ? '0' + hex : hex +} +export function hexToNumber(hex) { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian +} +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } +function asciiToBase16(ch) { + if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 + if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) + if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) + return +} +/** + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export function hexToBytes(hex) { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + const hl = hex.length + const al = hl / 2 + if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) + const array = new Uint8Array(al) + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)) + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1] + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) + } + array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 + } + return array +} +// BE: Big Endian, LE: Little Endian +export function bytesToNumberBE(bytes) { + return hexToNumber(bytesToHex(bytes)) +} +export function bytesToNumberLE(bytes) { + abytes(bytes) + return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) +} +export function numberToBytesBE(n, len) { + return hexToBytes(n.toString(16).padStart(len * 2, '0')) +} +export function numberToBytesLE(n, len) { + return numberToBytesBE(n, len).reverse() +} +// Unpadded, rarely used +export function numberToVarBytesBE(n) { + return hexToBytes(numberToHexUnpadded(n)) +} +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export function ensureBytes(title, hex, expectedLength) { + let res + if (typeof hex === 'string') { + try { + res = hexToBytes(hex) + } catch (e) { + throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) + } + } else if (isBytes(hex)) { + // Uint8Array.from() instead of hash.slice() because node.js Buffer + // is instance of Uint8Array, and its slice() creates **mutable** copy + res = Uint8Array.from(hex) + } else { + throw new Error(title + ' must be hex string or Uint8Array') + } + const len = res.length + if (typeof expectedLength === 'number' && len !== expectedLength) + throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) + return res +} +/** + * Copies several Uint8Arrays into one. + */ +export function concatBytes(...arrays) { + let sum = 0 + for (let i = 0; i < arrays.length; i++) { + const a = arrays[i] + abytes(a) + sum += a.length + } + const res = new Uint8Array(sum) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const a = arrays[i] + res.set(a, pad) + pad += a.length + } + return res +} +// Compares 2 u8a-s in kinda constant time +export function equalBytes(a, b) { + if (a.length !== b.length) return false + let diff = 0 + for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] + return diff === 0 +} +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export function utf8ToBytes(str) { + if (typeof str !== 'string') throw new Error('string expected') + return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 +} +// Is positive bigint +const isPosBig = (n) => typeof n === 'bigint' && _0n <= n +export function inRange(n, min, max) { + return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max +} +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export function aInRange(title, n, min, max) { + // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? + // consider P=256n, min=0n, max=P + // - a for min=0 would require -1: `inRange('x', x, -1n, P)` + // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` + // - our way is the cleanest: `inRange('x', x, 0n, P) + if (!inRange(n, min, max)) + throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) +} +// Bit operations +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export function bitLen(n) { + let len + for (len = 0; n > _0n; n >>= _1n, len += 1); + return len +} +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export function bitGet(n, pos) { + return (n >> BigInt(pos)) & _1n +} +/** + * Sets single bit at position. + */ +export function bitSet(n, pos, value) { + return n | ((value ? _1n : _0n) << BigInt(pos)) +} +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n +// DRBG +const u8n = (data) => new Uint8Array(data) // creates Uint8Array +const u8fr = (arr) => Uint8Array.from(arr) // another shortcut +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export function createHmacDrbg(hashLen, qByteLen, hmacFn) { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') + if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0 // Iterations counter, will throw when over 1000 + const reset = () => { + v.fill(1) + k.fill(0) + i = 0 + } + const h = (...b) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) + const reseed = (seed = u8n()) => { + // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) + v = h() // v = hmac(k || v) + if (seed.length === 0) return + k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) + v = h() // v = hmac(k || v) + } + const gen = () => { + // HMAC-DRBG generate() function + if (i++ >= 1000) throw new Error('drbg: tried 1000 values') + let len = 0 + const out = [] + while (len < qByteLen) { + v = h() + const sl = v.slice() + out.push(sl) + len += v.length + } + return concatBytes(...out) + } + const genUntil = (seed, pred) => { + reset() + reseed(seed) // Steps D-G + let res = undefined // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed() + reset() + return res + } + return genUntil +} +// Validating curves and fields +const validatorFns = { + bigint: (val) => typeof val === 'bigint', + function: (val) => typeof val === 'function', + boolean: (val) => typeof val === 'boolean', + string: (val) => typeof val === 'string', + stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val), + isSafeInteger: (val) => Number.isSafeInteger(val), + array: (val) => Array.isArray(val), + field: (val, object) => object.Fp.isValid(val), + hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen), +} +// type Record = { [P in K]: T; } +export function validateObject(object, validators, optValidators = {}) { + const checkField = (fieldName, type, isOptional) => { + const checkVal = validatorFns[type] + if (typeof checkVal !== 'function') throw new Error('invalid validator function') + const val = object[fieldName] + if (isOptional && val === undefined) return + if (!checkVal(val, object)) { + throw new Error( + 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, + ) + } + } + for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false) + for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true) + return object +} +// validate type tests +// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; +// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! +// // Should fail type-check +// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); +// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); +// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); +// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); +/** + * throws not implemented error + */ +export const notImplemented = () => { + throw new Error('not implemented') +} +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export function memoized(fn) { + const map = new WeakMap() + return (arg, ...args) => { + const val = map.get(arg) + if (val !== undefined) return val + const computed = fn(arg, ...args) + map.set(arg, computed) + return computed + } +} +//# sourceMappingURL=utils.js.map diff --git a/packages/noble-curves/esm/abstract/utils.js.map b/packages/noble-curves/esm/abstract/utils.js.map new file mode 100644 index 00000000000..2d06284c084 --- /dev/null +++ b/packages/noble-curves/esm/abstract/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/weierstrass.d.ts b/packages/noble-curves/esm/abstract/weierstrass.d.ts new file mode 100644 index 00000000000..f79b0c73b8e --- /dev/null +++ b/packages/noble-curves/esm/abstract/weierstrass.d.ts @@ -0,0 +1,241 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' +import { type IField } from './modular.js' +import { type CHash, type Hex, type PrivKey } from './utils.js' +export type { AffinePoint } +type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array +type EndomorphismOpts = { + beta: bigint + splitScalar: (k: bigint) => { + k1neg: boolean + k1: bigint + k2neg: boolean + k2: bigint + } +} +export type BasicWCurve = BasicCurve & { + a: T + b: T + allowedPrivateKeyLengths?: readonly number[] + wrapPrivateKey?: boolean + endo?: EndomorphismOpts + isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean + clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType +} +type Entropy = Hex | boolean +export type SignOpts = { + lowS?: boolean + extraEntropy?: Entropy + prehash?: boolean +} +export type VerOpts = { + lowS?: boolean + prehash?: boolean + format?: 'compact' | 'der' | undefined +} +export interface ProjPointType extends Group> { + readonly px: T + readonly py: T + readonly pz: T + get x(): T + get y(): T + multiply(scalar: bigint): ProjPointType + toAffine(iz?: T): AffinePoint + isTorsionFree(): boolean + clearCofactor(): ProjPointType + assertValidity(): void + hasEvenY(): boolean + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + multiplyUnsafe(scalar: bigint): ProjPointType + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined + _setWindowSize(windowSize: number): void +} +export interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType + fromAffine(p: AffinePoint): ProjPointType + fromHex(hex: Hex): ProjPointType + fromPrivateKey(privateKey: PrivKey): ProjPointType + normalizeZ(points: ProjPointType[]): ProjPointType[] + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType +} +export type CurvePointsType = BasicWCurve & { + fromBytes?: (bytes: Uint8Array) => AffinePoint + toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array +} +export type CurvePointsTypeWithLength = Readonly< + CurvePointsType & { + nByteLength: number + nBitLength: number + } +> +declare function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength +export type CurvePointsRes = { + CURVE: ReturnType> + ProjectivePoint: ProjConstructor + normPrivateKeyToScalar: (key: PrivKey) => bigint + weierstrassEquation: (x: T) => T + isWithinCurveOrder: (num: bigint) => boolean +} +export declare class DERErr extends Error { + constructor(m?: string) +} +export type IDER = { + Err: typeof DERErr + _tlv: { + encode: (tag: number, data: string) => string + decode( + tag: number, + data: Uint8Array, + ): { + v: Uint8Array + l: Uint8Array + } + } + _int: { + encode(num: bigint): string + decode(data: Uint8Array): bigint + } + toSig(hex: string | Uint8Array): { + r: bigint + s: bigint + } + hexFromSig(sig: { + r: bigint + s: bigint + }): string +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export declare const DER: IDER +export declare function weierstrassPoints(opts: CurvePointsType): CurvePointsRes +export interface SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + assertValidity(): void + addRecoveryBit(recovery: number): RecoveredSignatureType + hasHighS(): boolean + normalizeS(): SignatureType + recoverPublicKey(msgHash: Hex): ProjPointType + toCompactRawBytes(): Uint8Array + toCompactHex(): string + toDERRawBytes(isCompressed?: boolean): Uint8Array + toDERHex(isCompressed?: boolean): string +} +export type RecoveredSignatureType = SignatureType & { + readonly recovery: number +} +export type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType + fromCompact(hex: Hex): SignatureType + fromDER(hex: Hex): SignatureType +} +type SignatureLike = { + r: bigint + s: bigint +} +export type PubKey = Hex | ProjPointType +export type CurveType = BasicWCurve & { + hash: CHash + hmac: HmacFnSync + randomBytes: (bytesLength?: number) => Uint8Array + lowS?: boolean + bits2int?: (bytes: Uint8Array) => bigint + bits2int_modN?: (bytes: Uint8Array) => bigint +} +declare function validateOpts(curve: CurveType): Readonly< + CurveType & { + nByteLength: number + nBitLength: number + } +> +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType + verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean + ProjectivePoint: ProjConstructor + Signature: SignatureConstructor + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint + isValidPrivateKey(privateKey: PrivKey): boolean + randomPrivateKey: () => Uint8Array + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType + } +} +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export declare function weierstrass(curveDef: CurveType): CurveFn +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export declare function SWUFpSqrtRatio( + Fp: IField, + Z: T, +): ( + u: T, + v: T, +) => { + isValid: boolean + value: T +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export declare function mapToCurveSimpleSWU( + Fp: IField, + opts: { + A: T + B: T + Z: T + }, +): (u: T) => { + x: T + y: T +} +//# sourceMappingURL=weierstrass.d.ts.map diff --git a/packages/noble-curves/esm/abstract/weierstrass.d.ts.map b/packages/noble-curves/esm/abstract/weierstrass.d.ts.map new file mode 100644 index 00000000000..1637197cd09 --- /dev/null +++ b/packages/noble-curves/esm/abstract/weierstrass.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"weierstrass.d.ts","sourceRoot":"","sources":["../../src/abstract/weierstrass.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/weierstrass.js b/packages/noble-curves/esm/abstract/weierstrass.js new file mode 100644 index 00000000000..54c6482d356 --- /dev/null +++ b/packages/noble-curves/esm/abstract/weierstrass.js @@ -0,0 +1,1131 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { pippenger, validateBasic, wNAF } from './curve.js' +import { Field, getMinHashLength, invert, mapHashToField, mod, validateField } from './modular.js' +import * as ut from './utils.js' +import { abool, ensureBytes, memoized } from './utils.js' +function validateSigVerOpts(opts) { + if (opts.lowS !== undefined) abool('lowS', opts.lowS) + if (opts.prehash !== undefined) abool('prehash', opts.prehash) +} +function validatePointOpts(curve) { + const opts = validateBasic(curve) + ut.validateObject( + opts, + { + a: 'field', + b: 'field', + }, + { + allowedPrivateKeyLengths: 'array', + wrapPrivateKey: 'boolean', + isTorsionFree: 'function', + clearCofactor: 'function', + allowInfinityPoint: 'boolean', + fromBytes: 'function', + toBytes: 'function', + }, + ) + const { endo, Fp, a } = opts + if (endo) { + if (!Fp.eql(a, Fp.ZERO)) { + throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') + } + if ( + typeof endo !== 'object' || + typeof endo.beta !== 'bigint' || + typeof endo.splitScalar !== 'function' + ) { + throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') + } + } + return Object.freeze({ ...opts }) +} +const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut +export class DERErr extends Error { + constructor(m = '') { + super(m) + } +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export const DER = { + // asn.1 DER encoding utils + Err: DERErr, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag, data) => { + const { Err: E } = DER + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length & 1) throw new E('tlv.encode: unpadded data') + const dataLen = data.length / 2 + const len = ut.numberToHexUnpadded(dataLen) + if ((len.length / 2) & 128) throw new E('tlv.encode: long form length too big') + // length of length with long form flag + const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 128) : '' + const t = ut.numberToHexUnpadded(tag) + return t + lenLen + len + data + }, + // v - value, l - left bytes (unparsed) + decode(tag, data) { + const { Err: E } = DER + let pos = 0 + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') + const first = data[pos++] + const isLong = !!(first & 128) // First bit of first length byte is flag for short/long form + let length = 0 + if (!isLong) length = first + else { + // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] + const lenLen = first & 127 + if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') + if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js + const lengthBytes = data.subarray(pos, pos + lenLen) + if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') + if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') + for (const b of lengthBytes) length = (length << 8) | b + pos += lenLen + if (length < 128) throw new E('tlv.decode(long): not minimal encoding') + } + const v = data.subarray(pos, pos + length) + if (v.length !== length) throw new E('tlv.decode: wrong value length') + return { v, l: data.subarray(pos + length) } + }, + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num) { + const { Err: E } = DER + if (num < _0n) throw new E('integer: negative integers are not allowed') + let hex = ut.numberToHexUnpadded(num) + // Pad with zero byte if negative flag is present + if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex + if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') + return hex + }, + decode(data) { + const { Err: E } = DER + if (data[0] & 128) throw new E('invalid signature integer: negative') + if (data[0] === 0x00 && !(data[1] & 128)) + throw new E('invalid signature integer: unnecessary leading zero') + return b2n(data) + }, + }, + toSig(hex) { + // parse DER signature + const { Err: E, _int: int, _tlv: tlv } = DER + const data = typeof hex === 'string' ? h2b(hex) : hex + ut.abytes(data) + const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) + if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) + const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) + if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + return { r: int.decode(rBytes), s: int.decode(sBytes) } + }, + hexFromSig(sig) { + const { _tlv: tlv, _int: int } = DER + const rs = tlv.encode(0x02, int.encode(sig.r)) + const ss = tlv.encode(0x02, int.encode(sig.s)) + const seq = rs + ss + return tlv.encode(0x30, seq) + }, +} +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) +export function weierstrassPoints(opts) { + const CURVE = validatePointOpts(opts) + const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ + const Fn = Field(CURVE.n, CURVE.nBitLength) + const toBytes = + CURVE.toBytes || + ((_c, point, _isCompressed) => { + const a = point.toAffine() + return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) + }) + const fromBytes = + CURVE.fromBytes || + ((bytes) => { + // const head = bytes[0]; + const tail = bytes.subarray(1) + // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + }) + /** + * y² = x³ + ax + b: Short weierstrass curve formula + * @returns y² + */ + function weierstrassEquation(x) { + const { a, b } = CURVE + const x2 = Fp.sqr(x) // x * x + const x3 = Fp.mul(x2, x) // x2 * x + return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b + } + // Validate whether the passed curve params are valid. + // We check if curve equation works for generator point. + // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. + // ProjectivePoint class has not been initialized yet. + if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) + throw new Error('bad generator point: equation left != right') + // Valid group elements reside in range 1..n-1 + function isWithinCurveOrder(num) { + return ut.inRange(num, _1n, CURVE.n) + } + // Validates if priv key is valid and converts it to bigint. + // Supports options allowedPrivateKeyLengths and wrapPrivateKey. + function normPrivateKeyToScalar(key) { + const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE + if (lengths && typeof key !== 'bigint') { + if (ut.isBytes(key)) key = ut.bytesToHex(key) + // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes + if (typeof key !== 'string' || !lengths.includes(key.length)) + throw new Error('invalid private key') + key = key.padStart(nByteLength * 2, '0') + } + let num + try { + num = + typeof key === 'bigint' + ? key + : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength)) + } catch (error) { + throw new Error( + 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, + ) + } + if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS + ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] + return num + } + function assertPrjPoint(other) { + if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') + } + // Memoized toAffine / validity check. They are heavy. Points are immutable. + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + const toAffineMemo = memoized((p, iz) => { + const { px: x, py: y, pz: z } = p + // Fast-path for normalized points + if (Fp.eql(z, Fp.ONE)) return { x, y } + const is0 = p.is0() + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 1. + if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) + const ax = Fp.mul(x, iz) + const ay = Fp.mul(y, iz) + const zz = Fp.mul(z, iz) + if (is0) return { x: Fp.ZERO, y: Fp.ZERO } + if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + // NOTE: on exception this will crash 'cached' and no value will be set. + // Otherwise true will be return + const assertValidMemo = memoized((p) => { + if (p.is0()) { + // (0, 1, 0) aka ZERO is invalid in most contexts. + // In BLS, ZERO can be serialized, so we allow it. + // (0, 0, 0) is invalid representation of ZERO. + if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return + throw new Error('bad point: ZERO') + } + // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` + const { x, y } = p.toAffine() + // Check if x, y are valid field elements + if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') + const left = Fp.sqr(y) // y² + const right = weierstrassEquation(x) // x³ + ax + b + if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') + if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') + return true + }) + /** + * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) + * Default Point works in 2d / affine coordinates: (x, y) + * We're doing calculations in projective, because its operations don't require costly inversion. + */ + class Point { + constructor(px, py, pz) { + this.px = px + this.py = py + this.pz = pz + if (px == null || !Fp.isValid(px)) throw new Error('x required') + if (py == null || !Fp.isValid(py)) throw new Error('y required') + if (pz == null || !Fp.isValid(pz)) throw new Error('z required') + Object.freeze(this) + } + // Does not validate if the point is on-curve. + // Use fromHex instead, or call assertValidity() later. + static fromAffine(p) { + const { x, y } = p || {} + if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') + if (p instanceof Point) throw new Error('projective point not allowed') + const is0 = (i) => Fp.eql(i, Fp.ZERO) + // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) + if (is0(x) && is0(y)) return Point.ZERO + return new Point(x, y, Fp.ONE) + } + get x() { + return this.toAffine().x + } + get y() { + return this.toAffine().y + } + /** + * Takes a bunch of Projective Points but executes only one + * inversion on all of them. Inversion is very slow operation, + * so this improves performance massively. + * Optimization: converts a list of projective points to a list of identical points with Z=1. + */ + static normalizeZ(points) { + const toInv = Fp.invertBatch(points.map((p) => p.pz)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + /** + * Converts hash string or Uint8Array to Point. + * @param hex short/long ECDSA hex + */ + static fromHex(hex) { + const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) + P.assertValidity() + return P + } + // Multiplies generator point by privateKey. + static fromPrivateKey(privateKey) { + return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) + } + // Multiscalar Multiplication + static msm(points, scalars) { + return pippenger(Point, Fn, points, scalars) + } + // "Private method", don't use it directly + _setWindowSize(windowSize) { + wnaf.setWindowSize(this, windowSize) + } + // A point on curve is valid if it conforms to equation. + assertValidity() { + assertValidMemo(this) + } + hasEvenY() { + const { y } = this.toAffine() + if (Fp.isOdd) return !Fp.isOdd(y) + throw new Error("Field doesn't support isOdd") + } + /** + * Compare one point to another. + */ + equals(other) { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) + const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) + return U1 && U2 + } + /** + * Flips point to one corresponding to (x, -y) in Affine coordinates. + */ + negate() { + return new Point(this.px, Fp.neg(this.py), this.pz) + } + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a, b } = CURVE + const b3 = Fp.mul(b, _3n) + const { px: X1, py: Y1, pz: Z1 } = this + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + let t0 = Fp.mul(X1, X1) // step 1 + let t1 = Fp.mul(Y1, Y1) + let t2 = Fp.mul(Z1, Z1) + let t3 = Fp.mul(X1, Y1) + t3 = Fp.add(t3, t3) // step 5 + Z3 = Fp.mul(X1, Z1) + Z3 = Fp.add(Z3, Z3) + X3 = Fp.mul(a, Z3) + Y3 = Fp.mul(b3, t2) + Y3 = Fp.add(X3, Y3) // step 10 + X3 = Fp.sub(t1, Y3) + Y3 = Fp.add(t1, Y3) + Y3 = Fp.mul(X3, Y3) + X3 = Fp.mul(t3, X3) + Z3 = Fp.mul(b3, Z3) // step 15 + t2 = Fp.mul(a, t2) + t3 = Fp.sub(t0, t2) + t3 = Fp.mul(a, t3) + t3 = Fp.add(t3, Z3) + Z3 = Fp.add(t0, t0) // step 20 + t0 = Fp.add(Z3, t0) + t0 = Fp.add(t0, t2) + t0 = Fp.mul(t0, t3) + Y3 = Fp.add(Y3, t0) + t2 = Fp.mul(Y1, Z1) // step 25 + t2 = Fp.add(t2, t2) + t0 = Fp.mul(t2, t3) + X3 = Fp.sub(X3, t0) + Z3 = Fp.mul(t2, t1) + Z3 = Fp.add(Z3, Z3) // step 30 + Z3 = Fp.add(Z3, Z3) + return new Point(X3, Y3, Z3) + } + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(other) { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + const a = CURVE.a + const b3 = Fp.mul(CURVE.b, _3n) + let t0 = Fp.mul(X1, X2) // step 1 + let t1 = Fp.mul(Y1, Y2) + let t2 = Fp.mul(Z1, Z2) + let t3 = Fp.add(X1, Y1) + let t4 = Fp.add(X2, Y2) // step 5 + t3 = Fp.mul(t3, t4) + t4 = Fp.add(t0, t1) + t3 = Fp.sub(t3, t4) + t4 = Fp.add(X1, Z1) + let t5 = Fp.add(X2, Z2) // step 10 + t4 = Fp.mul(t4, t5) + t5 = Fp.add(t0, t2) + t4 = Fp.sub(t4, t5) + t5 = Fp.add(Y1, Z1) + X3 = Fp.add(Y2, Z2) // step 15 + t5 = Fp.mul(t5, X3) + X3 = Fp.add(t1, t2) + t5 = Fp.sub(t5, X3) + Z3 = Fp.mul(a, t4) + X3 = Fp.mul(b3, t2) // step 20 + Z3 = Fp.add(X3, Z3) + X3 = Fp.sub(t1, Z3) + Z3 = Fp.add(t1, Z3) + Y3 = Fp.mul(X3, Z3) + t1 = Fp.add(t0, t0) // step 25 + t1 = Fp.add(t1, t0) + t2 = Fp.mul(a, t2) + t4 = Fp.mul(b3, t4) + t1 = Fp.add(t1, t2) + t2 = Fp.sub(t0, t2) // step 30 + t2 = Fp.mul(a, t2) + t4 = Fp.add(t4, t2) + t0 = Fp.mul(t1, t4) + Y3 = Fp.add(Y3, t0) + t0 = Fp.mul(t5, t4) // step 35 + X3 = Fp.mul(t3, X3) + X3 = Fp.sub(X3, t0) + t0 = Fp.mul(t3, t1) + Z3 = Fp.mul(t5, Z3) + Z3 = Fp.add(Z3, t0) // step 40 + return new Point(X3, Y3, Z3) + } + subtract(other) { + return this.add(other.negate()) + } + is0() { + return this.equals(Point.ZERO) + } + wNAF(n) { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed private key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(sc) { + const { endo, n: N } = CURVE + ut.aInRange('scalar', sc, _0n, N) + const I = Point.ZERO + if (sc === _0n) return I + if (this.is0() || sc === _1n) return this + // Case a: no endomorphism. Case b: has precomputes. + if (!endo || wnaf.hasPrecomputes(this)) + return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) + // Case c: endomorphism + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) + let k1p = I + let k2p = I + let d = this + while (k1 > _0n || k2 > _0n) { + if (k1 & _1n) k1p = k1p.add(d) + if (k2 & _1n) k2p = k2p.add(d) + d = d.double() + k1 >>= _1n + k2 >>= _1n + } + if (k1neg) k1p = k1p.negate() + if (k2neg) k2p = k2p.negate() + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + return k1p.add(k2p) + } + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(scalar) { + const { endo, n: N } = CURVE + ut.aInRange('scalar', scalar, _1n, N) + let point, fake // Fake point is used to const-time mult + if (endo) { + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) + let { p: k1p, f: f1p } = this.wNAF(k1) + let { p: k2p, f: f2p } = this.wNAF(k2) + k1p = wnaf.constTimeNegate(k1neg, k1p) + k2p = wnaf.constTimeNegate(k2neg, k2p) + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + point = k1p.add(k2p) + fake = f1p.add(f2p) + } else { + const { p, f } = this.wNAF(scalar) + point = p + fake = f + } + // Normalize `z` for both points, but return only real one + return Point.normalizeZ([point, fake])[0] + } + /** + * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. + * Not using Strauss-Shamir trick: precomputation tables are faster. + * The trick could be useful if both P and Q are not G (not in our case). + * @returns non-zero affine point + */ + multiplyAndAddUnsafe(Q, a, b) { + const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes + const mul = ( + P, + a, // Select faster multiply() method + ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) + const sum = mul(this, a).add(mul(Q, b)) + return sum.is0() ? undefined : sum + } + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + toAffine(iz) { + return toAffineMemo(this, iz) + } + isTorsionFree() { + const { h: cofactor, isTorsionFree } = CURVE + if (cofactor === _1n) return true // No subgroups, always torsion-free + if (isTorsionFree) return isTorsionFree(Point, this) + throw new Error('isTorsionFree() has not been declared for the elliptic curve') + } + clearCofactor() { + const { h: cofactor, clearCofactor } = CURVE + if (cofactor === _1n) return this // Fast-path + if (clearCofactor) return clearCofactor(Point, this) + return this.multiplyUnsafe(CURVE.h) + } + toRawBytes(isCompressed = true) { + abool('isCompressed', isCompressed) + this.assertValidity() + return toBytes(Point, this, isCompressed) + } + toHex(isCompressed = true) { + abool('isCompressed', isCompressed) + return ut.bytesToHex(this.toRawBytes(isCompressed)) + } + } + Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) + Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) + const _bits = CURVE.nBitLength + const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) + // Validate if generator point is on curve + return { + CURVE, + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } +} +function validateOpts(curve) { + const opts = validateBasic(curve) + ut.validateObject( + opts, + { + hash: 'hash', + hmac: 'function', + randomBytes: 'function', + }, + { + bits2int: 'function', + bits2int_modN: 'function', + lowS: 'boolean', + }, + ) + return Object.freeze({ lowS: true, ...opts }) +} +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export function weierstrass(curveDef) { + const CURVE = validateOpts(curveDef) + const { Fp, n: CURVE_ORDER } = CURVE + const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 + const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 + function modN(a) { + return mod(a, CURVE_ORDER) + } + function invN(a) { + return invert(a, CURVE_ORDER) + } + const { + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } = weierstrassPoints({ + ...CURVE, + toBytes(_c, point, isCompressed) { + const a = point.toAffine() + const x = Fp.toBytes(a.x) + const cat = ut.concatBytes + abool('isCompressed', isCompressed) + if (isCompressed) { + return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) + } else { + return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) + } + }, + fromBytes(bytes) { + const len = bytes.length + const head = bytes[0] + const tail = bytes.subarray(1) + // this.assertValidity() is done inside of fromHex + if (len === compressedLen && (head === 0x02 || head === 0x03)) { + const x = ut.bytesToNumberBE(tail) + if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') + const y2 = weierstrassEquation(x) // y² = x³ + ax + b + let y + try { + y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 + } catch (sqrtError) { + const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' + throw new Error('Point is not on curve' + suffix) + } + const isYOdd = (y & _1n) === _1n + // ECDSA + const isHeadOdd = (head & 1) === 1 + if (isHeadOdd !== isYOdd) y = Fp.neg(y) + return { x, y } + } else if (len === uncompressedLen && head === 0x04) { + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + } else { + const cl = compressedLen + const ul = uncompressedLen + throw new Error( + 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, + ) + } + }, + }) + const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) + function isBiggerThanHalfOrder(number) { + const HALF = CURVE_ORDER >> _1n + return number > HALF + } + function normalizeS(s) { + return isBiggerThanHalfOrder(s) ? modN(-s) : s + } + // slice bytes num + const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to)) + /** + * ECDSA signature with its (r, s) properties. Supports DER & compact representations. + */ + class Signature { + constructor(r, s, recovery) { + this.r = r + this.s = s + this.recovery = recovery + this.assertValidity() + } + // pair (bytes of r, bytes of s) + static fromCompact(hex) { + const l = CURVE.nByteLength + hex = ensureBytes('compactSignature', hex, l * 2) + return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) + } + // DER encoded ECDSA signature + // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script + static fromDER(hex) { + const { r, s } = DER.toSig(ensureBytes('DER', hex)) + return new Signature(r, s) + } + assertValidity() { + ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] + ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] + } + addRecoveryBit(recovery) { + return new Signature(this.r, this.s, recovery) + } + recoverPublicKey(msgHash) { + const { r, s, recovery: rec } = this + const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash + if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') + const radj = rec === 2 || rec === 3 ? r + CURVE.n : r + if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') + const prefix = (rec & 1) === 0 ? '02' : '03' + const R = Point.fromHex(prefix + numToNByteStr(radj)) + const ir = invN(radj) // r^-1 + const u1 = modN(-h * ir) // -hr^-1 + const u2 = modN(s * ir) // sr^-1 + const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) + if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked + Q.assertValidity() + return Q + } + // Signatures should be low-s, to prevent malleability. + hasHighS() { + return isBiggerThanHalfOrder(this.s) + } + normalizeS() { + return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this + } + // DER-encoded + toDERRawBytes() { + return ut.hexToBytes(this.toDERHex()) + } + toDERHex() { + return DER.hexFromSig({ r: this.r, s: this.s }) + } + // padded bytes of r, then padded bytes of s + toCompactRawBytes() { + return ut.hexToBytes(this.toCompactHex()) + } + toCompactHex() { + return numToNByteStr(this.r) + numToNByteStr(this.s) + } + } + const utils = { + isValidPrivateKey(privateKey) { + try { + normPrivateKeyToScalar(privateKey) + return true + } catch (error) { + return false + } + }, + normPrivateKeyToScalar: normPrivateKeyToScalar, + /** + * Produces cryptographically secure private key from random of size + * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. + */ + randomPrivateKey: () => { + const length = getMinHashLength(CURVE.n) + return mapHashToField(CURVE.randomBytes(length), CURVE.n) + }, + /** + * Creates precompute table for an arbitrary EC point. Makes point "cached". + * Allows to massively speed-up `point.multiply(scalar)`. + * @returns cached point + * @example + * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); + * fast.multiply(privKey); // much faster ECDH now + */ + precompute(windowSize = 8, point = Point.BASE) { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here + return point + }, + } + /** + * Computes public key for a private key. Checks for validity of the private key. + * @param privateKey private key + * @param isCompressed whether to return compact (default), or full key + * @returns Public key, full when isCompressed=false; short when isCompressed=true + */ + function getPublicKey(privateKey, isCompressed = true) { + return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) + } + /** + * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. + */ + function isProbPub(item) { + const arr = ut.isBytes(item) + const str = typeof item === 'string' + const len = (arr || str) && item.length + if (arr) return len === compressedLen || len === uncompressedLen + if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen + if (item instanceof Point) return true + return false + } + /** + * ECDH (Elliptic Curve Diffie Hellman). + * Computes shared public key from private key and public key. + * Checks: 1) private key validity 2) shared key is on-curve. + * Does NOT hash the result. + * @param privateA private key + * @param publicB different public key + * @param isCompressed whether to return compact (default), or full key + * @returns shared public key + */ + function getSharedSecret(privateA, publicB, isCompressed = true) { + if (isProbPub(privateA)) throw new Error('first arg must be private key') + if (!isProbPub(publicB)) throw new Error('second arg must be public key') + const b = Point.fromHex(publicB) // check for being on-curve + return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) + } + // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. + // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. + // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. + // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors + const bits2int = + CURVE.bits2int || + function (bytes) { + // Our custom check "just in case" + if (bytes.length > 8192) throw new Error('input is too large') + // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) + // for some cases, since bytes.length * 8 is not actual bitLength. + const num = ut.bytesToNumberBE(bytes) // check for == u8 done here + const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits + return delta > 0 ? num >> BigInt(delta) : num + } + const bits2int_modN = + CURVE.bits2int_modN || + function (bytes) { + return modN(bits2int(bytes)) // can't use bytesToNumberBE here + } + // NOTE: pads output with zero as per spec + const ORDER_MASK = ut.bitMask(CURVE.nBitLength) + /** + * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. + */ + function int2octets(num) { + ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) + // works with order, can have different size than numToField! + return ut.numberToBytesBE(num, CURVE.nByteLength) + } + // Steps A, D of RFC6979 3.2 + // Creates RFC6979 seed; converts msg/privKey to numbers. + // Used only in sign, not in verify. + // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, + // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 + function prepSig(msgHash, privateKey, opts = defaultSigOpts) { + if (['recovered', 'canonical'].some((k) => k in opts)) + throw new Error('sign() legacy options not supported') + const { hash, randomBytes } = CURVE + let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default + if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash + msgHash = ensureBytes('msgHash', msgHash) + validateSigVerOpts(opts) + if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) + // We can't later call bits2octets, since nested bits2int is broken for curves + // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. + // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) + const h1int = bits2int_modN(msgHash) + const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint + const seedArgs = [int2octets(d), int2octets(h1int)] + // extraEntropy. RFC6979 3.6: additional k' (optional). + if (ent != null && ent !== false) { + // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is + seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes + } + const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 + const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! + // Converts signature params into point w r/s, checks result for validity. + function k2sig(kBytes) { + // RFC 6979 Section 3.2, step 3: k = bits2int(T) + const k = bits2int(kBytes) // Cannot use fields methods, since it is group element + if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N + const ik = invN(k) // k^-1 mod n + const q = Point.BASE.multiply(k).toAffine() // q = Gk + const r = modN(q.x) // r = q.x mod n + if (r === _0n) return + // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to + // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: + // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT + const s = modN(ik * modN(m + r * d)) // Not using blinding here + if (s === _0n) return + let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) + let normS = s + if (lowS && isBiggerThanHalfOrder(s)) { + normS = normalizeS(s) // if lowS was passed, ensure s is always + recovery ^= 1 // // in the bottom half of N + } + return new Signature(r, normS, recovery) // use normS, not s + } + return { seed, k2sig } + } + const defaultSigOpts = { lowS: CURVE.lowS, prehash: false } + const defaultVerOpts = { lowS: CURVE.lowS, prehash: false } + /** + * Signs message hash with a private key. + * ``` + * sign(m, d, k) where + * (x, y) = G × k + * r = x mod n + * s = (m + dr)/k mod n + * ``` + * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. + * @param privKey private key + * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. + * @returns signature with recovery param + */ + function sign(msgHash, privKey, opts = defaultSigOpts) { + const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. + const C = CURVE + const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) + return drbg(seed, k2sig) // Steps B, C, D, E, F, G + } + // Enable precomputes. Slows down first publicKey computation by 20ms. + Point.BASE._setWindowSize(8) + // utils.precompute(8, ProjectivePoint.BASE) + /** + * Verifies a signature against message hash and public key. + * Rejects lowS signatures by default: to override, + * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: + * + * ``` + * verify(r, s, h, P) where + * U1 = hs^-1 mod n + * U2 = rs^-1 mod n + * R = U1⋅G - U2⋅P + * mod(R.x, n) == r + * ``` + */ + function verify(signature, msgHash, publicKey, opts = defaultVerOpts) { + const sg = signature + msgHash = ensureBytes('msgHash', msgHash) + publicKey = ensureBytes('publicKey', publicKey) + const { lowS, prehash, format } = opts + // Verify opts, deduce signature format + validateSigVerOpts(opts) + if ('strict' in opts) throw new Error('options.strict was renamed to lowS') + if (format !== undefined && format !== 'compact' && format !== 'der') + throw new Error('format must be compact or der') + const isHex = typeof sg === 'string' || ut.isBytes(sg) + const isObj = + !isHex && + !format && + typeof sg === 'object' && + sg !== null && + typeof sg.r === 'bigint' && + typeof sg.s === 'bigint' + if (!isHex && !isObj) + throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') + let _sig = undefined + let P + try { + if (isObj) _sig = new Signature(sg.r, sg.s) + if (isHex) { + // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). + // Since DER can also be 2*nByteLength bytes, we check for it first. + try { + if (format !== 'compact') _sig = Signature.fromDER(sg) + } catch (derError) { + if (!(derError instanceof DER.Err)) throw derError + } + if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) + } + P = Point.fromHex(publicKey) + } catch (error) { + return false + } + if (!_sig) return false + if (lowS && _sig.hasHighS()) return false + if (prehash) msgHash = CURVE.hash(msgHash) + const { r, s } = _sig + const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element + const is = invN(s) // s^-1 + const u1 = modN(h * is) // u1 = hs^-1 mod n + const u2 = modN(r * is) // u2 = rs^-1 mod n + const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P + if (!R) return false + const v = modN(R.x) + return v === r + } + return { + CURVE, + getPublicKey, + getSharedSecret, + sign, + verify, + ProjectivePoint: Point, + Signature, + utils, + } +} +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export function SWUFpSqrtRatio(Fp, Z) { + // Generic implementation + const q = Fp.ORDER + let l = _0n + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n + const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. + // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. + // 2n ** c1 == 2n << (c1-1) + const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) + const _2n_pow_c1 = _2n_pow_c1_1 * _2n + const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 + const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) + let sqrtRatio = (u, v) => { + let tv1 = c6 // 1. tv1 = c6 + let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 + let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 + tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v + let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 + tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 + tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 + tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v + tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u + let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 + tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 + let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 + tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 + tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) + // 17. for i in (c1, c1 - 1, ..., 2): + for (let i = c1; i > _1n; i--) { + let tv5 = i - _2n // 18. tv5 = i - 2 + tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 + let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 + const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 + tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 + tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 + tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) + } + return { isValid: isQR, value: tv3 } + } + if (Fp.ORDER % _4n === _3n) { + // sqrt_ratio_3mod4(u, v) + const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) + sqrtRatio = (u, v) => { + let tv1 = Fp.sqr(v) // 1. tv1 = v^2 + const tv2 = Fp.mul(u, v) // 2. tv2 = u * v + tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 + let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 + y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 + const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 + const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v + const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u + let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) + return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 + } + } + // No curves uses that + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 + return sqrtRatio +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export function mapToCurveSimpleSWU(Fp, opts) { + validateField(Fp) + if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) + throw new Error('mapToCurveSimpleSWU: invalid opts') + const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) + if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') + // Input: u, an element of F. + // Output: (x, y), a point on E. + return (u) => { + // prettier-ignore + let tv1, tv2, tv3, tv4, tv5, tv6, x, y + tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 + tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 + tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 + tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 + tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 + tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) + tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 + tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 + tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 + tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 + tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 + tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 + tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 + tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 + tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 + x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 + const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 + y = Fp.mul(y, value) // 20. y = y * y1 + x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) + y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) + const e1 = Fp.isOdd(u) === Fp.isOdd(y) // 23. e1 = sgn0(u) == sgn0(y) + y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) + x = Fp.div(x, tv4) // 25. x = x / tv4 + return { x, y } + } +} +//# sourceMappingURL=weierstrass.js.map diff --git a/packages/noble-curves/esm/abstract/weierstrass.js.map b/packages/noble-curves/esm/abstract/weierstrass.js.map new file mode 100644 index 00000000000..b46193cd5b2 --- /dev/null +++ b/packages/noble-curves/esm/abstract/weierstrass.js.map @@ -0,0 +1 @@ +{"version":3,"file":"weierstrass.js","sourceRoot":"","sources":["../../src/abstract/weierstrass.ts"],"names":[],"mappings":"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AAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GA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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bls12-381.d.ts b/packages/noble-curves/esm/bls12-381.d.ts new file mode 100644 index 00000000000..8de19050c1e --- /dev/null +++ b/packages/noble-curves/esm/bls12-381.d.ts @@ -0,0 +1,14 @@ +import { type CurveFn } from './abstract/bls.js' +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export declare const bls12_381: CurveFn +//# sourceMappingURL=bls12-381.d.ts.map diff --git a/packages/noble-curves/esm/bls12-381.d.ts.map b/packages/noble-curves/esm/bls12-381.d.ts.map new file mode 100644 index 00000000000..141ca4fe3aa --- /dev/null +++ b/packages/noble-curves/esm/bls12-381.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bls12-381.d.ts","sourceRoot":"","sources":["../src/bls12-381.ts"],"names":[],"mappings":"AA+DA,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAkXtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,OAqUtB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bls12-381.js b/packages/noble-curves/esm/bls12-381.js new file mode 100644 index 00000000000..31c7d06e544 --- /dev/null +++ b/packages/noble-curves/esm/bls12-381.js @@ -0,0 +1,747 @@ +/** + * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: + * * Construct zk-SNARKs at the ~120-bit security + * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: + * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr + * + * ### Summary + * 1. BLS Relies on Bilinear Pairing (expensive) + * 2. Private Keys: 32 bytes + * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. + * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. + * - The signature is a point on the G2 subgroup, which is defined over a finite field + * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the + * complex numbers). + * - We also support reversed 96-byte pubkeys & 48-byte short signatures. + * 5. The 12 stands for the Embedding degree. + * + * ### Formulas + * - `P = pk x G` - public keys + * - `S = pk x H(m)` - signing + * - `e(P, H(m)) == e(G, S)` - verification using pairings + * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation + * + * ### Compatibility and notes + * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. + * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. + * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". + * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) + * 4. Compatible with specs: + * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), + * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), + * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * + * ### Params + * To verify curve parameters, see + * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). + * Basic math is done over finite fields over p. + * More complicated math is done over polynominal extension fields. + * To simplify calculations in Fp12, we construct extension tower: + * + * Embedding degree (k): 12 + * Seed (X): -15132376222941642752 + * Fr: (x⁴-x²+1) + * Fp: ((x-1)² ⋅ r(x)/3+x) + * (E/Fp): Y²=X³+4 + * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) + * Ate loop size: X + * + * ### Towers + * - Fp₁₂ = Fp₆² => Fp₂³ + * - Fp(u) / (u² - β) where β = -1 + * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 + * - Fp₆(w) / (w² - γ) where γ = v + * - Fp²[u] = Fp/u²+1 + * - Fp⁶[v] = Fp²/v³-1-u + * - Fp¹²[w] = Fp⁶/w²-v + * + * @todo construct bls & bn fp/fr from seed. + * @module + */ +console.log('N NOBLE CURVEEEEEEEEEEEE') +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { bls } from './abstract/bls.js' +// Types +import { isogenyMap } from './abstract/hash-to-curve.js' +import * as mod from './abstract/modular.js' +import { psiFrobenius, tower12 } from './abstract/tower.js' +import { + bitGet, + bitLen, + bytesToHex, + bytesToNumberBE, + concatBytes as concatB, + ensureBytes, + numberToBytesBE, +} from './abstract/utils.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) +// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! +const BLS_X = BigInt('0xd201000000010000') +const BLS_X_LEN = bitLen(BLS_X) +// CURVE FIELDS +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + // Order of Fp + ORDER: BigInt( + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', + ), + // Finite extension field over irreducible polynominal. + // Fp(u) / (u² - β) where β = -1 + FP2_NONRESIDUE: [_1n, _1n], + Fp2mulByB: ({ c0, c1 }) => { + const t0 = Fp.mul(c0, _4n) // 4 * c0 + const t1 = Fp.mul(c1, _4n) // 4 * c1 + // (T0-T1) + (T0+T1)*i + return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } + }, + // Fp12 + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }) => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const x = BLS_X + // this^(q⁶) / this + const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) + // t0^(q²) * t0 + const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) + const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) + const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) + const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) + const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) + const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) + const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) + const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) + const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) + const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) + const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) + // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 + return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) + }, +}) +// Finite field over r. +// This particular field is not used anywhere in bls12-381, but it is still useful. +const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) +// END OF CURVE FIELDS +// HashToCurve +// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 +const isogenyMapG2 = isogenyMap( + Fp2, + [ + // xNum + [ + [ + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + ], + [ + '0x0', + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', + ], + [ + '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', + '0x0', + ], + ], + // xDen + [ + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', + ], + [ + '0xc', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', + ], + ['0x1', '0x0'], // LAST 1 + ], + // yNum + [ + [ + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + ], + [ + '0x0', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', + ], + [ + '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', + '0x0', + ], + ], + // yDen + [ + [ + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + ], + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', + ], + [ + '0x12', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', + ], + ['0x1', '0x0'], // LAST 1 + ], + ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))), +) +// 11-isogeny map from E' to E +const isogenyMapG1 = isogenyMap( + Fp, + [ + // xNum + [ + '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', + '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', + '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', + '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', + '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', + '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', + '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', + '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', + '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', + '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', + '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', + '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', + ], + // xDen + [ + '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', + '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', + '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', + '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', + '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', + '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', + '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', + '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', + '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', + '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', + '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', + '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', + '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', + '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', + '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', + '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', + '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', + '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', + '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', + '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', + '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', + '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', + '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', + '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', + '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', + ], + // yDen + [ + '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', + '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', + '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', + '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', + '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', + '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', + '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', + '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', + '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', + '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', + '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', + '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', + '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', + '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', + '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))), +) +// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i +const G2_SWU = mapToCurveSimpleSWU(Fp2, { + A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I + B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) + Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) +}) +// Optimized SWU Map - Fp to G1 +const G1_SWU = mapToCurveSimpleSWU(Fp, { + A: Fp.create( + BigInt( + '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', + ), + ), + B: Fp.create( + BigInt( + '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', + ), + ), + Z: Fp.create(BigInt(11)), +}) +// Endomorphisms (for fast cofactor clearing) +// Ψ(P) endomorphism +const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) +// Default hash_to_field options are for hash to G2. +// +// Parameter definitions are in section 5.3 of the spec unless otherwise noted. +// Parameter values come from section 8.8.2 of the spec. +// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 +// +// Base field F is GF(p^m) +// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +// m = 2 (or 1 for G1 see section 8.8.1) +// k = 128 +const htfDefaults = Object.freeze({ + // DST: a domain separation tag + // defined in section 2.2.5 + // Use utils.getDSTLabel(), utils.setDSTLabel(value) + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + // p: the characteristic of F + // where F is a finite field of characteristic p and order q = p^m + p: Fp.ORDER, + // m: the extension degree of F, m >= 1 + // where F is a finite field of characteristic p and order q = p^m + m: 2, + // k: the target security level for the suite in bits + // defined in section 5.1 + k: 128, + // option to use a message that has already been processed by + // expand_message_xmd + expand: 'xmd', + // Hash functions for: expand_message_xmd is appropriate for use with a + // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. + // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 + hash: sha256, +}) +// Encoding utils +// Point on G1 curve: (x, y) +// Compressed point of infinity +const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits +function parseMask(bytes) { + // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. + bytes = bytes.slice() + const mask = bytes[0] & 224 + const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) + const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) + const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) + bytes[0] &= 31 // clear mask (zero first 3 bits) + return { compressed, infinity, sort, value: bytes } +} +function setMask(bytes, mask) { + if (bytes[0] & 224) throw new Error('setMask: non-empty mask') + if (mask.compressed) bytes[0] |= 128 + if (mask.infinity) bytes[0] |= 64 + if (mask.sort) bytes[0] |= 32 + return bytes +} +function signatureG1ToRawBytes(point) { + point.assertValidity() + const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) + const { x, y } = point.toAffine() + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) +} +function signatureG2ToRawBytes(point) { + // NOTE: by some reasons it was missed in bls12-381, looks like bug + point.assertValidity() + const len = Fp.BYTES + if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) + return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const { x, y } = point.toAffine() + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + const tmp = y1 > _0n ? y1 * _2n : y0 * _2n + const sort = Boolean((tmp / Fp.ORDER) & _1n) + const z2 = x0 + return concatB( + setMask(numberToBytesBE(x1, len), { sort, compressed: true }), + numberToBytesBE(z2, len), + ) +} +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export const bls12_381 = bls({ + // Fields + fields: { + Fp, + Fp2, + Fp6, + Fp12, + Fr, + }, + // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where + // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 + G1: { + Fp, + // cofactor; (z - 1)²/3 + h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), + // generator's coordinates + // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 + // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 + Gx: BigInt( + '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', + ), + Gy: BigInt( + '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', + ), + a: Fp.ZERO, + b: _4n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, point) => { + // φ endomorphism + const cubicRootOfUnityModP = BigInt( + '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', + ) + const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) + // todo: unroll + const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P + const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P + return u2P.equals(phi) + // https://eprint.iacr.org/2019/814.pdf + // (z² − 1)/3 + // const c1 = BigInt('0x396c8c005555e1560000000055555555'); + // const P = this; + // const S = P.sigma(); + // const Q = S.double(); + // const S2 = S.sigma(); + // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O + // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); + // const C = left.subtract(S2); + // return C.isZero(); + }, + // Clear cofactor of G1 + // https://eprint.iacr.org/2019/403 + clearCofactor: (_c, point) => { + // return this.multiplyUnsafe(CURVE.h); + return point.multiplyUnsafe(BLS_X).add(point) // x*P + P + }, + mapToCurve: (scalars) => { + const { x, y } = G1_SWU(Fp.create(scalars[0])) + return isogenyMapG1(x, y) + }, + fromBytes: (bytes) => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if (value.length === 48 && compressed) { + // TODO: Fp.bytes + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + const x = Fp.create(compressedValue & Fp.MASK) + if (infinity) { + if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') + return { x: _0n, y: _0n } + } + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) + return { x: Fp.create(x), y: Fp.create(y) } + } else if (value.length === 96 && !compressed) { + // Check if the infinity flag is set + const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) + const y = bytesToNumberBE(value.subarray(Fp.BYTES)) + if (infinity) { + if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') + return bls12_381.G1.ProjectivePoint.ZERO.toAffine() + } + return { x: Fp.create(x), y: Fp.create(y) } + } else { + throw new Error('invalid point G1, expected 48/96 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) + } else { + if (isZero) { + // 2x PUBLIC_KEY_LENGTH + const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) + return x + } else { + return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) + } + } + }, + ShortSignature: { + fromHex(hex) { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + if (infinity) return bls12_381.G1.ProjectivePoint.ZERO + const x = Fp.create(compressedValue & Fp.MASK) + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + const aflag = BigInt(sort) + if ((y * _2n) / P !== aflag) y = Fp.neg(y) + const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point) { + return signatureG1ToRawBytes(point) + }, + toHex(point) { + return bytesToHex(signatureG1ToRawBytes(point)) + }, + }, + }, + // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), + // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where + // G² - 1 + // h2q + G2: { + Fp: Fp2, + // cofactor + h: BigInt( + '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', + ), + Gx: Fp2.fromBigTuple([ + BigInt( + '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', + ), + BigInt( + '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', + ), + ]), + // y = + // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, + // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + Gy: Fp2.fromBigTuple([ + BigInt( + '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', + ), + BigInt( + '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', + ), + ]), + a: Fp2.ZERO, + b: Fp2.fromBigTuple([_4n, _4n]), + hEff: BigInt( + '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', + ), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: (scalars) => { + const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) + return isogenyMapG2(x, y) + }, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, P) => { + return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) + // Older version: https://eprint.iacr.org/2019/814.pdf + // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O + // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); + }, + // Maps the point into the prime-order subgroup G2. + // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 + // https://eprint.iacr.org/2017/419.pdf + // prettier-ignore + clearCofactor: (c, P) => { + const x = BLS_X + let t1 = P.multiplyUnsafe(x).negate() // [-x]P + let t2 = G2psi(c, P) // Ψ(P) + let t3 = P.double() // 2P + t3 = G2psi2(c, t3) // Ψ²(2P) + t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) + t2 = t1.add(t2) // [-x]P + Ψ(P) + t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) + t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P + const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P + return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) + }, + fromBytes: (bytes) => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if ( + (!compressed && !infinity && sort) || // 00100000 + (!compressed && infinity && sort) || // 01100000 + (sort && infinity && compressed) // 11100000 + ) { + throw new Error('invalid encoding flag: ' + (bytes[0] & 224)) + } + const L = Fp.BYTES + const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to)) + if (value.length === 96 && compressed) { + const b = bls12_381.params.G2b + const P = Fp.ORDER + if (infinity) { + // check that all bytes are 0 + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid compressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x_1 = slc(value, 0, L) + const x_0 = slc(value, L, 2 * L) + const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) + const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b + let y = Fp2.sqrt(right) + const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n + y = sort && Y_bit > 0 ? y : Fp2.neg(y) + return { x, y } + } else if (value.length === 192 && !compressed) { + if (infinity) { + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid uncompressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x1 = slc(value, 0, L) + const x0 = slc(value, L, 2 * L) + const y1 = slc(value, 2 * L, 3 * L) + const y0 = slc(value, 3 * L, 4 * L) + return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } + } else { + throw new Error('invalid point G2, expected 96/192 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const { BYTES: len, ORDER: P } = Fp + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) + return concatB( + setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), + numberToBytesBE(x.c0, len), + ) + } else { + if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + return concatB( + numberToBytesBE(x1, len), + numberToBytesBE(x0, len), + numberToBytesBE(y1, len), + numberToBytesBE(y0, len), + ) + } + }, + Signature: { + // TODO: Optimize, it's very slow because of sqrt. + fromHex(hex) { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) + const P = Fp.ORDER + const half = value.length / 2 + if (half !== 48 && half !== 96) + throw new Error('invalid compressed signature length, must be 96 or 192') + const z1 = bytesToNumberBE(value.slice(0, half)) + const z2 = bytesToNumberBE(value.slice(half)) + // Indicates the infinity point + if (infinity) return bls12_381.G2.ProjectivePoint.ZERO + const x1 = Fp.create(z1 & Fp.MASK) + const x2 = Fp.create(z2) + const x = Fp2.create({ c0: x2, c1: x1 }) + const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 + // The slow part + let y = Fp2.sqrt(y2) + if (!y) throw new Error('Failed to find a square root') + // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 + // If y1 happens to be zero, then use the bit of y0 + const { re: y0, im: y1 } = Fp2.reim(y) + const aflag1 = BigInt(sort) + const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 + const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 + if (isGreater || isZero) y = Fp2.neg(y) + const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point) { + return signatureG2ToRawBytes(point) + }, + toHex(point) { + return bytesToHex(signatureG2ToRawBytes(point)) + }, + }, + }, + params: { + ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 + r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves + xNegative: true, + twistType: 'multiplicative', + }, + htfDefaults, + hash: sha256, + randomBytes, +}) +//# sourceMappingURL=bls12-381.js.map diff --git a/packages/noble-curves/esm/bls12-381.js.map b/packages/noble-curves/esm/bls12-381.js.map new file mode 100644 index 00000000000..e895207ab32 --- /dev/null +++ b/packages/noble-curves/esm/bls12-381.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bls12-381.js","sourceRoot":"","sources":["../src/bls12-381.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bn254.d.ts b/packages/noble-curves/esm/bn254.d.ts new file mode 100644 index 00000000000..94c05dba695 --- /dev/null +++ b/packages/noble-curves/esm/bn254.d.ts @@ -0,0 +1,15 @@ +import { type CurveFn as BLSCurveFn, type PostPrecomputeFn } from './abstract/bls.js' +import { type CurveFn } from './abstract/weierstrass.js' +export declare const _postPrecompute: PostPrecomputeFn +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export declare const bn254: BLSCurveFn +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + */ +export declare const bn254_weierstrass: CurveFn +//# sourceMappingURL=bn254.d.ts.map diff --git a/packages/noble-curves/esm/bn254.d.ts.map b/packages/noble-curves/esm/bn254.d.ts.map new file mode 100644 index 00000000000..390306a81dc --- /dev/null +++ b/packages/noble-curves/esm/bn254.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bn254.d.ts","sourceRoot":"","sources":["../src/bn254.ts"],"names":[],"mappings":"AAkDA,OAAO,EAEL,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAgGtE,eAAO,MAAM,eAAe,EAAE,gBAY7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UA6DlB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAS9B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bn254.js b/packages/noble-curves/esm/bn254.js new file mode 100644 index 00000000000..d883a68d504 --- /dev/null +++ b/packages/noble-curves/esm/bn254.js @@ -0,0 +1,233 @@ +/** + * bn254, previously known as alt_bn_128, when it had 128-bit security. + +Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, +so the naming has been adjusted to its prime bit count: +https://hal.science/hal-01534101/file/main.pdf. +Compatible with EIP-196 and EIP-197. + +There are huge compatibility issues in the ecosystem: + +1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". +2. libff has bn128, but it's a different curve with different G2: + https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 +3. halo2curves bn256 is also incompatible and returns different outputs + +The goal of our implementation is to support "Ethereum" variant of the curve, +because it at least has specs: + +- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM +- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings +- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 +- The existing implementations are bad. Some are deprecated: + - https://github.com/paritytech/bn (old version) + - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) + - https://github.com/zcash-hackworks/bn + - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs +- Python implementations use different towers and produce different Fp12 outputs: + - https://github.com/ethereum/py_pairing + - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py +- Points are encoded differently in different implementations + +### Params +Seed (X): 4965661367192848881 +Fr: (36x⁴+36x³+18x²+6x+1) +Fp: (36x⁴+36x³+24x²+6x+1) +(E / Fp ): Y² = X³+3 +(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) +Ate loop size: 6x+2 + +### Towers +- Fp²[u] = Fp/u²+1 +- Fp⁶[v] = Fp²/v³-9-u +- Fp¹²[w] = Fp⁶/w²-v + + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.js' +import { bls } from './abstract/bls.js' +import { Field } from './abstract/modular.js' +import { psiFrobenius, tower12 } from './abstract/tower.js' +import { bitGet, bitLen, notImplemented } from './abstract/utils.js' +import { weierstrass } from './abstract/weierstrass.js' +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +const _6n = BigInt(6) +const BN_X = BigInt('4965661367192848881') +const BN_X_LEN = bitLen(BN_X) +const SIX_X_SQUARED = _6n * BN_X ** _2n +// Finite field over r. It's for convenience and is not used in the code below. +const Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) +// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) +const Fp2B = { + c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), + c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), +} +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), + FP2_NONRESIDUE: [BigInt(9), _1n], + Fp2mulByB: (num) => Fp2.mul(num, Fp2B), + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }) => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BN_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const powMinusX = (num) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) + const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) + const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) + const y1 = Fp12._cyclotomicSquare(powMinusX(r)) + const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) + const y4 = powMinusX(y2) + const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) + const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) + const y9 = Fp12.mul(y8, y1) + return Fp12.mul( + Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), + Fp12.mul( + Fp12.frobeniusMap(y8, 2), + Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), + ), + ) + }, +}) +// END OF CURVE FIELDS +const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) +/* +No hashToCurve for now (and signatures): + +- RFC 9380 doesn't mention bn254 and doesn't provide test vectors +- Overall seems like nobody is using BLS signatures on top of bn254 +- Seems like it can utilize SVDW, which is not implemented yet +*/ +const htfDefaults = Object.freeze({ + // DST: a domain separation tag defined in section 2.2.5 + DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + p: Fp.ORDER, + m: 2, + k: 128, + expand: 'xmd', + hash: sha256, +}) +export const _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => { + const q = psi(Qx, Qy) + ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) + const q2 = psi(q[0], q[1]) + pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) +} +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export const bn254 = bls({ + // Fields + fields: { Fp, Fp2, Fp6, Fp12, Fr }, + G1: { + Fp, + h: BigInt(1), + Gx: BigInt(1), + Gy: BigInt(2), + a: Fp.ZERO, + b: _3n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + ShortSignature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + G2: { + Fp: Fp2, + // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 + h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + Gx: Fp2.fromBigTuple([ + BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), + BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), + ]), + Gy: Fp2.fromBigTuple([ + BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), + BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), + ]), + a: Fp2.ZERO, + b: Fp2B, + hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + Signature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + params: { + ateLoopSize: BN_X * _6n + _2n, + r: Fr.ORDER, + xNegative: false, + twistType: 'divisive', + }, + htfDefaults, + hash: sha256, + randomBytes, + postPrecompute: _postPrecompute, +}) +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + */ +export const bn254_weierstrass = weierstrass({ + a: BigInt(0), + b: BigInt(3), + Fp, + n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), + Gx: BigInt(1), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +//# sourceMappingURL=bn254.js.map diff --git a/packages/noble-curves/esm/bn254.js.map b/packages/noble-curves/esm/bn254.js.map new file mode 100644 index 00000000000..2c0cdbfd3f1 --- /dev/null +++ b/packages/noble-curves/esm/bn254.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bn254.js","sourceRoot":"","sources":["../src/bn254.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed25519.d.ts b/packages/noble-curves/esm/ed25519.d.ts new file mode 100644 index 00000000000..b7f9565cc9a --- /dev/null +++ b/packages/noble-curves/esm/ed25519.d.ts @@ -0,0 +1,101 @@ +import { type AffinePoint, type Group } from './abstract/curve.js' +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' +import { type CurveFn as XCurveFn } from './abstract/montgomery.js' +import { type Hex } from './abstract/utils.js' +export declare const ED25519_TORSION_SUBGROUP: string[] +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export declare const ed25519: CurveFn +export declare const ed25519ctx: CurveFn +export declare const ed25519ph: CurveFn +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export declare const x25519: XCurveFn +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export declare function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array +export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export declare function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array +export declare const hashToCurve: HTFMethod +export declare const encodeToCurve: HTFMethod +type ExtendedPoint = ExtPointType +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +declare class RistPoint implements Group { + private readonly ep + static BASE: RistPoint + static ZERO: RistPoint + constructor(ep: ExtendedPoint) + static fromAffine(ap: AffinePoint): RistPoint + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex: Hex): RistPoint + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex: Hex): RistPoint + static msm(points: RistPoint[], scalars: bigint[]): RistPoint + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes(): Uint8Array + toHex(): string + toString(): string + equals(other: RistPoint): boolean + add(other: RistPoint): RistPoint + subtract(other: RistPoint): RistPoint + multiply(scalar: bigint): RistPoint + multiplyUnsafe(scalar: bigint): RistPoint + double(): RistPoint + negate(): RistPoint +} +export declare const RistrettoPoint: typeof RistPoint +export declare const hashToRistretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint +export declare const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint +export {} +//# sourceMappingURL=ed25519.d.ts.map diff --git a/packages/noble-curves/esm/ed25519.d.ts.map b/packages/noble-curves/esm/ed25519.d.ts.map new file mode 100644 index 00000000000..3784c84d890 --- /dev/null +++ b/packages/noble-curves/esm/ed25519.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAa,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AAmE7B,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAS5C,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,OAAmE,CAAC;AAY1F,eAAO,MAAM,UAAU,EAAE,OAIlB,CAAC;AACR,eAAO,MAAM,SAAS,EAAE,OAMlB,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,EAAE,QAed,CAAC;AAER;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAIlE;AACD,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAG3E;AA0FD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AAiC5F,KAAK,aAAa,GAAG,YAAY,CAAC;AA0BlC;;;;;;GAMG;AACH,cAAM,SAAU,YAAW,KAAK,CAAC,SAAS,CAAC;IAK7B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;gBAGM,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS;IAIrD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IASvC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IA2BnC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;IAK7D;;;OAGG;IACH,UAAU,IAAI,UAAU;IA4BxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAKlB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAWjC,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKhC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAInC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAIzC,MAAM,IAAI,SAAS;IAInB,MAAM,IAAI,SAAS;CAGpB;AACD,eAAO,MAAM,cAAc,EAAE,OAAO,SAIhC,CAAC;AAGL,eAAO,MAAM,kBAAkB,QAAS,UAAU,WAAW,YAAY,KAAG,SAM3E,CAAC;AACF,eAAO,MAAM,oBAAoB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,KAAK,SAC3D,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed25519.js b/packages/noble-curves/esm/ed25519.js new file mode 100644 index 00000000000..a3747505544 --- /dev/null +++ b/packages/noble-curves/esm/ed25519.js @@ -0,0 +1,493 @@ +/** + * ed25519 Twisted Edwards curve with following addons: + * - X25519 ECDH + * - Ristretto cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha512' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { pippenger } from './abstract/curve.js' +import { twistedEdwards } from './abstract/edwards.js' +import { createHasher, expand_message_xmd } from './abstract/hash-to-curve.js' +import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.js' +import { montgomery } from './abstract/montgomery.js' +import { + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.js' +const ED25519_P = BigInt( + '57896044618658097711785492504343953926634992332820282019728792003956564819949', +) +// √(-1) aka √(a) aka 2^((p-1)/4) +const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( + '19681161376707505956807079304988542015446066515923890162744021073123829784752', +) +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// prettier-ignore +const _5n = BigInt(5), + _8n = BigInt(8) +function ed25519_pow_2_252_3(x) { + // prettier-ignore + const _10n = BigInt(10), + _20n = BigInt(20), + _40n = BigInt(40), + _80n = BigInt(80) + const P = ED25519_P + const x2 = (x * x) % P + const b2 = (x2 * x) % P // x^3, 11 + const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 + const b5 = (pow2(b4, _1n, P) * x) % P // x^31 + const b10 = (pow2(b5, _5n, P) * b5) % P + const b20 = (pow2(b10, _10n, P) * b10) % P + const b40 = (pow2(b20, _20n, P) * b20) % P + const b80 = (pow2(b40, _40n, P) * b40) % P + const b160 = (pow2(b80, _80n, P) * b80) % P + const b240 = (pow2(b160, _80n, P) * b80) % P + const b250 = (pow2(b240, _10n, P) * b10) % P + const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P + // ^ To pow to (p+3)/8, multiply it by x. + return { pow_p_5_8, b2 } +} +function adjustScalarBytes(bytes) { + // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, + // set the three least significant bits of the first byte + bytes[0] &= 248 // 0b1111_1000 + // and the most significant bit of the last to zero, + bytes[31] &= 127 // 0b0111_1111 + // set the second most significant bit of the last byte to 1 + bytes[31] |= 64 // 0b0100_0000 + return bytes +} +// sqrt(u/v) +function uvRatio(u, v) { + const P = ED25519_P + const v3 = mod(v * v * v, P) // v³ + const v7 = mod(v3 * v3 * v, P) // v⁷ + // (p+3)/8 and (p-5)/8 + const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 + let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 + const vx2 = mod(v * x * x, P) // vx² + const root1 = x // First root candidate + const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate + const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root + const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) + const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) + if (useRoot1) x = root1 + if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time + if (isNegativeLE(x, P)) x = mod(-x, P) + return { isValid: useRoot1 || useRoot2, value: x } +} +// Just in case +export const ED25519_TORSION_SUBGROUP = [ + '0100000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', + '0000000000000000000000000000000000000000000000000000000000000080', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', + '0000000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', +] +const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() +const ed25519Defaults = /* @__PURE__ */ (() => ({ + // Param: a + a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster + // d is equal to -121665/121666 over finite field. + // Negative number is P - number, and division is invert(number, P) + d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), + // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n + Fp, + // Subgroup order: how many points curve has + // 2n**252n + 27742317777372353535851937790883648493n; + n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), + // Cofactor + h: _8n, + // Base point (x, y) aka generator point + Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), + Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), + hash: sha512, + randomBytes, + adjustScalarBytes, + // dom2 + // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. + // Constant-time, u/√v + uvRatio, +}))() +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export const ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() +function ed25519_domain(data, ctx, phflag) { + if (ctx.length > 255) throw new Error('Context is too big') + return concatBytes( + utf8ToBytes('SigEd25519 no Ed25519 collisions'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) +} +export const ed25519ctx = /* @__PURE__ */ (() => + twistedEdwards({ + ...ed25519Defaults, + domain: ed25519_domain, + }))() +export const ed25519ph = /* @__PURE__ */ (() => + twistedEdwards( + Object.assign({}, ed25519Defaults, { + domain: ed25519_domain, + prehash: sha512, + }), + ))() +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export const x25519 = /* @__PURE__ */ (() => + montgomery({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x) => { + const P = ED25519_P + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) + return mod(pow2(pow_p_5_8, _3n, P) * b2, P) + }, + adjustScalarBytes, + randomBytes, + }))() +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub) { + const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) +} +export const edwardsToMontgomery = edwardsToMontgomeryPub // deprecated +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export function edwardsToMontgomeryPriv(edwardsPriv) { + const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) + return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) +} +// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) +// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since +// SageMath returns different root first and everything falls apart +const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic +const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 +const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) +// prettier-ignore +function map_to_curve_elligator2_curve25519(u) { + const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic + const ELL2_J = BigInt(486662) + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 + let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not + let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) + let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 + tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 + tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 + tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 + tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 + let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) + y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) + let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 + tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 + tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd + let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 + let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt + let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd + let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u + y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 + let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 + let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) + tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 + tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 + let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt + tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd + let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 + let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) +} +const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 +function map_to_curve_elligator2_edwards25519(u) { + const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = + // map_to_curve_elligator2_curve25519(u) + let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd + xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 + let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM + let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd + let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) + let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd + let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 + xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) + xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) + yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) + yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) + const inv = Fp.invertBatch([xd, yd]) // batch division + return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) +} +const htf = /* @__PURE__ */ (() => + createHasher( + ed25519.ExtendedPoint, + (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512, + }, + ))() +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +function assertRstPoint(other) { + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') +} +// √(-1) aka √(a) aka 2^((p-1)/4) +const SQRT_M1 = ED25519_SQRT_M1 +// √(ad - 1) +const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( + '25063068953384623474111414158702152701244531502492656460079210482610430750235', +) +// 1 / √(a-d) +const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( + '54469307008909316920995813868745141605393597292927456921205312896311721017578', +) +// 1-d² +const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( + '1159843021668779879193775521855586647937357759715417654439879720876111806838', +) +// (d-1)² +const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( + '40440834346308536858101042469323190826248399146238708352240133220865137265952', +) +// Calculates 1/√(number) +const invertSqrt = (number) => uvRatio(_1n, number) +const MAX_255B = /* @__PURE__ */ BigInt( + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes255ToNumberLE = (bytes) => ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) +// Computes Elligator map for Ristretto +// https://ristretto.group/formulas/elligator.html +function calcElligatorRistrettoMap(r0) { + const { d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const r = mod(SQRT_M1 * r0 * r0) // 1 + const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 + let c = BigInt(-1) // 3 + const D = mod((c - d * r) * mod(r + d)) // 4 + let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 + let s_ = mod(s * r0) // 6 + if (!isNegativeLE(s_, P)) s_ = mod(-s_) + if (!Ns_D_is_sq) s = s_ // 7 + if (!Ns_D_is_sq) c = r // 8 + const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 + const s2 = s * s + const W0 = mod((s + s) * D) // 10 + const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 + const W2 = mod(_1n - s2) // 12 + const W3 = mod(_1n + s2) // 13 + return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class RistPoint { + // Private property to discourage combining ExtendedPoint + RistrettoPoint + // Always use Ristretto encoding/decoding instead. + constructor(ep) { + this.ep = ep + } + static fromAffine(ap) { + return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) + } + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex) { + hex = ensureBytes('ristrettoHash', hex, 64) + const r1 = bytes255ToNumberLE(hex.slice(0, 32)) + const R1 = calcElligatorRistrettoMap(r1) + const r2 = bytes255ToNumberLE(hex.slice(32, 64)) + const R2 = calcElligatorRistrettoMap(r2) + return new RistPoint(R1.add(R2)) + } + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex) { + hex = ensureBytes('ristrettoHex', hex, 32) + const { a, d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' + const s = bytes255ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 3. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) + const s2 = mod(s * s) + const u1 = mod(_1n + a * s2) // 4 (a is -1) + const u2 = mod(_1n - a * s2) // 5 + const u1_2 = mod(u1 * u1) + const u2_2 = mod(u2 * u2) + const v = mod(a * d * u1_2 - u2_2) // 6 + const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 + const Dx = mod(I * u2) // 8 + const Dy = mod(I * Dx * v) // 9 + let x = mod((s + s) * Dx) // 10 + if (isNegativeLE(x, P)) x = mod(-x) // 10 + const y = mod(u1 * Dy) // 11 + const t = mod(x * y) // 12 + if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) + return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) + } + static msm(points, scalars) { + const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) + return pippenger(RistPoint, Fn, points, scalars) + } + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes() { + let { ex: x, ey: y, ez: z, et: t } = this.ep + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const u1 = mod(mod(z + y) * mod(z - y)) // 1 + const u2 = mod(x * y) // 2 + // Square root always exists + const u2sq = mod(u2 * u2) + const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 + const D1 = mod(invsqrt * u1) // 4 + const D2 = mod(invsqrt * u2) // 5 + const zInv = mod(D1 * D2 * t) // 6 + let D // 7 + if (isNegativeLE(t * zInv, P)) { + let _x = mod(y * SQRT_M1) + let _y = mod(x * SQRT_M1) + x = _x + y = _y + D = mod(D1 * INVSQRT_A_MINUS_D) + } else { + D = D2 // 8 + } + if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 + let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) + if (isNegativeLE(s, P)) s = mod(-s) + return numberToBytesLE(s, 32) // 11 + } + toHex() { + return bytesToHex(this.toRawBytes()) + } + toString() { + return this.toHex() + } + // Compare one point to another. + equals(other) { + assertRstPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed25519.CURVE.Fp.create + // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) + const one = mod(X1 * Y2) === mod(Y1 * X2) + const two = mod(Y1 * Y2) === mod(X1 * X2) + return one || two + } + add(other) { + assertRstPoint(other) + return new RistPoint(this.ep.add(other.ep)) + } + subtract(other) { + assertRstPoint(other) + return new RistPoint(this.ep.subtract(other.ep)) + } + multiply(scalar) { + return new RistPoint(this.ep.multiply(scalar)) + } + multiplyUnsafe(scalar) { + return new RistPoint(this.ep.multiplyUnsafe(scalar)) + } + double() { + return new RistPoint(this.ep.double()) + } + negate() { + return new RistPoint(this.ep.negate()) + } +} +export const RistrettoPoint = /* @__PURE__ */ (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) + return RistPoint +})() +// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B +export const hashToRistretto255 = (msg, options) => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) + const P = RistPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_ristretto255 = hashToRistretto255 // legacy +//# sourceMappingURL=ed25519.js.map diff --git a/packages/noble-curves/esm/ed25519.js.map b/packages/noble-curves/esm/ed25519.js.map new file mode 100644 index 00000000000..378cf93bb6a --- /dev/null +++ b/packages/noble-curves/esm/ed25519.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed448.d.ts b/packages/noble-curves/esm/ed448.d.ts new file mode 100644 index 00000000000..82ac0fb743e --- /dev/null +++ b/packages/noble-curves/esm/ed448.d.ts @@ -0,0 +1,82 @@ +import type { AffinePoint, Group } from './abstract/curve.js' +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' +import { type CurveFn as XCurveFn } from './abstract/montgomery.js' +import { type Hex } from './abstract/utils.js' +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export declare const ed448: CurveFn +export declare const ed448ph: CurveFn +/** + * ECDH using curve448 aka x448. + */ +export declare const x448: XCurveFn +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export declare function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array +export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub +export declare const hashToCurve: HTFMethod +export declare const encodeToCurve: HTFMethod +type ExtendedPoint = ExtPointType +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +declare class DcfPoint implements Group { + private readonly ep + static BASE: DcfPoint + static ZERO: DcfPoint + constructor(ep: ExtendedPoint) + static fromAffine(ap: AffinePoint): DcfPoint + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex: Hex): DcfPoint + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex: Hex): DcfPoint + static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes(): Uint8Array + toHex(): string + toString(): string + equals(other: DcfPoint): boolean + add(other: DcfPoint): DcfPoint + subtract(other: DcfPoint): DcfPoint + multiply(scalar: bigint): DcfPoint + multiplyUnsafe(scalar: bigint): DcfPoint + double(): DcfPoint + negate(): DcfPoint +} +export declare const DecafPoint: typeof DcfPoint +export declare const hashToDecaf448: (msg: Uint8Array, options: htfBasicOpts) => DcfPoint +export declare const hash_to_decaf448: typeof hashToDecaf448 +export {} +//# sourceMappingURL=ed448.d.ts.map diff --git a/packages/noble-curves/esm/ed448.d.ts.map b/packages/noble-curves/esm/ed448.d.ts.map new file mode 100644 index 00000000000..7272aeaf1a3 --- /dev/null +++ b/packages/noble-curves/esm/ed448.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ed448.d.ts","sourceRoot":"","sources":["../src/ed448.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AA8G7B;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,EAAE,OAAmD,CAAC;AAExE,eAAO,MAAM,OAAO,EAAE,OAGpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,QAgBZ,CAAC;AAER;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAIlF;AAED,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AA8FzF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AA2B5F,KAAK,aAAa,GAAG,YAAY,CAAC;AAiClC;;;;;;GAMG;AACH,cAAM,QAAS,YAAW,KAAK,CAAC,QAAQ,CAAC;IAK3B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;IACtB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAGO,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,QAAQ;IAIpD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAStC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IA8BlC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ;IAK3D;;;OAGG;IACH,UAAU,IAAI,UAAU;IAoBxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAMlB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAShC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAK9B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIlC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIxC,MAAM,IAAI,QAAQ;IAIlB,MAAM,IAAI,QAAQ;CAGnB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,QAM5B,CAAC;AAGL,eAAO,MAAM,cAAc,QAAS,UAAU,WAAW,YAAY,KAAG,QAMvE,CAAC;AACF,eAAO,MAAM,gBAAgB,EAAE,OAAO,cAA+B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed448.js b/packages/noble-curves/esm/ed448.js new file mode 100644 index 00000000000..9fb0c3731a9 --- /dev/null +++ b/packages/noble-curves/esm/ed448.js @@ -0,0 +1,447 @@ +/** + * Edwards448 (not Ed448-Goldilocks) curve with following addons: + * - X448 ECDH + * - Decaf cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { shake256 } from '@noble/hashes/sha3' +import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' +import { pippenger } from './abstract/curve.js' +import { twistedEdwards } from './abstract/edwards.js' +import { createHasher, expand_message_xof } from './abstract/hash-to-curve.js' +import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.js' +import { montgomery } from './abstract/montgomery.js' +import { + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.js' +const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) +const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) +const ed448P = BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', +) +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4), + _11n = BigInt(11) +// prettier-ignore +const _22n = BigInt(22), + _44n = BigInt(44), + _88n = BigInt(88), + _223n = BigInt(223) +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +// Used for efficient square root calculation. +// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] +function ed448_pow_Pminus3div4(x) { + const P = ed448P + const b2 = (x * x * x) % P + const b3 = (b2 * b2 * x) % P + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b222 = (pow2(b220, _2n, P) * b2) % P + const b223 = (pow2(b222, _1n, P) * x) % P + return (pow2(b223, _223n, P) * b222) % P +} +function adjustScalarBytes(bytes) { + // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most + // significant bit of the last byte to 1. + bytes[0] &= 252 // 0b11111100 + // and the most significant bit of the last byte to 1. + bytes[55] |= 128 // 0b10000000 + // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) + bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) + return bytes +} +// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. +// Uses algo from RFC8032 5.1.3. +function uvRatio(u, v) { + const P = ed448P + // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 + // To compute the square root of (u/v), the first step is to compute the + // candidate root x = (u/v)^((p+1)/4). This can be done using the + // following trick, to use a single modular powering for both the + // inversion of v and the square root: + // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) + const u2v = mod(u * u * v, P) // u²v + const u3v = mod(u2v * u, P) // u³v + const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ + const root = ed448_pow_Pminus3div4(u5v3) + const x = mod(u3v * root, P) + // Verify that root is exists + const x2 = mod(x * x, P) // x² + // If vx² = u, the recovered x-coordinate is x. Otherwise, no + // square root exists, and the decoding fails. + return { isValid: mod(x2 * v, P) === u, value: x } +} +const Fp = Field(ed448P, 456, true) +const ED448_DEF = { + // Param: a + a: BigInt(1), + // -39081. Negative number is P - number + d: BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', + ), + // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n + Fp, + // Subgroup order: how many points curve has; + // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n + n: BigInt( + '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', + ), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + nBitLength: 456, + // Cofactor + h: BigInt(4), + // Base point (x, y) aka generator point + Gx: BigInt( + '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', + ), + Gy: BigInt( + '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', + ), + // SHAKE256(dom4(phflag,context)||x, 114) + hash: shake256_114, + randomBytes, + adjustScalarBytes, + // dom4 + domain: (data, ctx, phflag) => { + if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) + return concatBytes( + utf8ToBytes('SigEd448'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) + }, + uvRatio, +} +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export const ed448 = /* @__PURE__ */ twistedEdwards(ED448_DEF) +// NOTE: there is no ed448ctx, since ed448 supports ctx by default +export const ed448ph = /* @__PURE__ */ twistedEdwards({ + ...ED448_DEF, + prehash: shake256_64, +}) +/** + * ECDH using curve448 aka x448. + */ +export const x448 = /* @__PURE__ */ (() => + montgomery({ + a: BigInt(156326), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + montgomeryBits: 448, + nByteLength: 56, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x) => { + const P = ed448P + const Pminus3div4 = ed448_pow_Pminus3div4(x) + const Pminus3 = pow2(Pminus3div4, BigInt(2), P) + return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes, + }))() +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub) { + const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) +} +export const edwardsToMontgomery = edwardsToMontgomeryPub // deprecated +// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version +// Hash To Curve Elligator2 Map +const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic +const ELL2_J = BigInt(156326) +function map_to_curve_elligator2_curve448(u) { + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 + tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 + let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 + let x1n = Fp.neg(ELL2_J) // 5. x1n = -J + let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 + tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd + tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 + let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) + y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) + let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd + let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u + y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) + tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 + let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) + return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) +} +function map_to_curve_elligator2_edwards448(u) { + let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) + let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 + let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 + let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 + let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 + let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 + let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 + let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 + xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 + xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd + xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn + xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 + tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 + tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 + let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 + let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 + tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 + let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 + tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn + let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 + let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 + yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 + yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 + tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 + tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 + tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd + tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 + tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 + let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 + tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 + yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 + tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd + let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 + xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) + xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) + yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) + yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) + const inv = Fp.invertBatch([xEd, yEd]) // batch division + return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) +} +const htf = /* @__PURE__ */ (() => + createHasher(ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: shake256, + }))() +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +function assertDcfPoint(other) { + if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') +} +// 1-d +const ONE_MINUS_D = BigInt('39082') +// 1-2d +const ONE_MINUS_TWO_D = BigInt('78163') +// √(-d) +const SQRT_MINUS_D = BigInt( + '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', +) +// 1 / √(-d) +const INVSQRT_MINUS_D = BigInt( + '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', +) +// Calculates 1/√(number) +const invertSqrt = (number) => uvRatio(_1n, number) +const MAX_448B = BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes448ToNumberLE = (bytes) => ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) +// Computes Elligator map for Decaf +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 +function calcElligatorDecafMap(r0) { + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const r = mod(-(r0 * r0)) // 1 + const u0 = mod(d * (r - _1n)) // 2 + const u1 = mod((u0 + _1n) * (u0 - r)) // 3 + const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 + let v_prime = v // 5 + if (!was_square) v_prime = mod(r0 * v) + let sgn = _1n // 6 + if (!was_square) sgn = mod(-_1n) + const s = mod(v_prime * (r + _1n)) // 7 + let s_abs = s + if (isNegativeLE(s, P)) s_abs = mod(-s) + const s2 = s * s + const W0 = mod(s_abs * _2n) // 8 + const W1 = mod(s2 + _1n) // 9 + const W2 = mod(s2 - _1n) // 10 + const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 + return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class DcfPoint { + // Private property to discourage combining ExtendedPoint + DecafPoint + // Always use Decaf encoding/decoding instead. + constructor(ep) { + this.ep = ep + } + static fromAffine(ap) { + return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) + } + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex) { + hex = ensureBytes('decafHash', hex, 112) + const r1 = bytes448ToNumberLE(hex.slice(0, 56)) + const R1 = calcElligatorDecafMap(r1) + const r2 = bytes448ToNumberLE(hex.slice(56, 112)) + const R2 = calcElligatorDecafMap(r2) + return new DcfPoint(R1.add(R2)) + } + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex) { + hex = ensureBytes('decafHex', hex, 56) + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' + const s = bytes448ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 2. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) + const s2 = mod(s * s) // 1 + const u1 = mod(_1n + s2) // 2 + const u1sq = mod(u1 * u1) + const u2 = mod(u1sq - _4n * d * s2) // 3 + const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 + let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 + if (isNegativeLE(u3, P)) u3 = mod(-u3) + const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 + const y = mod((_1n - s2) * invsqrt * u1) // 7 + const t = mod(x * y) // 8 + if (!isValid) throw new Error(emsg) + return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) + } + static msm(points, scalars) { + const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) + return pippenger(DcfPoint, Fn, points, scalars) + } + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes() { + let { ex: x, ey: _y, ez: z, et: t } = this.ep + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const u1 = mod(mod(x + t) * mod(x - t)) // 1 + const x2 = mod(x * x) + const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 + let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 + if (isNegativeLE(ratio, P)) ratio = mod(-ratio) + const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 + let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 + if (isNegativeLE(s, P)) s = mod(-s) + return numberToBytesLE(s, 56) + } + toHex() { + return bytesToHex(this.toRawBytes()) + } + toString() { + return this.toHex() + } + // Compare one point to another. + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 + equals(other) { + assertDcfPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed448.CURVE.Fp.create + // (x1 * y2 == y1 * x2) + return mod(X1 * Y2) === mod(Y1 * X2) + } + add(other) { + assertDcfPoint(other) + return new DcfPoint(this.ep.add(other.ep)) + } + subtract(other) { + assertDcfPoint(other) + return new DcfPoint(this.ep.subtract(other.ep)) + } + multiply(scalar) { + return new DcfPoint(this.ep.multiply(scalar)) + } + multiplyUnsafe(scalar) { + return new DcfPoint(this.ep.multiplyUnsafe(scalar)) + } + double() { + return new DcfPoint(this.ep.double()) + } + negate() { + return new DcfPoint(this.ep.negate()) + } +} +export const DecafPoint = /* @__PURE__ */ (() => { + // decaf448 base point is ed448 base x 2 + // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 + if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) + if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) + return DcfPoint +})() +// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C +export const hashToDecaf448 = (msg, options) => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) + const P = DcfPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_decaf448 = hashToDecaf448 // legacy +//# sourceMappingURL=ed448.js.map diff --git a/packages/noble-curves/esm/ed448.js.map b/packages/noble-curves/esm/ed448.js.map new file mode 100644 index 00000000000..48dcd5c4cc7 --- /dev/null +++ b/packages/noble-curves/esm/ed448.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ed448.js","sourceRoot":"","sources":["../src/ed448.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/index.d.ts b/packages/noble-curves/esm/index.d.ts new file mode 100644 index 00000000000..727505f11c0 --- /dev/null +++ b/packages/noble-curves/esm/index.d.ts @@ -0,0 +1,2 @@ +export {} +//# sourceMappingURL=index.d.ts.map diff --git a/packages/noble-curves/esm/index.d.ts.map b/packages/noble-curves/esm/index.d.ts.map new file mode 100644 index 00000000000..535b86d2936 --- /dev/null +++ b/packages/noble-curves/esm/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/noble-curves/esm/index.js b/packages/noble-curves/esm/index.js new file mode 100644 index 00000000000..9ee11f62b17 --- /dev/null +++ b/packages/noble-curves/esm/index.js @@ -0,0 +1,19 @@ +/** + * Audited & minimal JS implementation of elliptic curve cryptography. + * @module + * @example +```js +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + */ +throw new Error('root module cannot be imported: import submodules instead. Check out README') +export {} +//# sourceMappingURL=index.js.map diff --git a/packages/noble-curves/esm/index.js.map b/packages/noble-curves/esm/index.js.map new file mode 100644 index 00000000000..0cbc97e2af5 --- /dev/null +++ b/packages/noble-curves/esm/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/jubjub.d.ts b/packages/noble-curves/esm/jubjub.d.ts new file mode 100644 index 00000000000..dbd19cd59c8 --- /dev/null +++ b/packages/noble-curves/esm/jubjub.d.ts @@ -0,0 +1,5 @@ +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +export declare const jubjub: CurveFn +export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType +export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType +//# sourceMappingURL=jubjub.d.ts.map diff --git a/packages/noble-curves/esm/jubjub.d.ts.map b/packages/noble-curves/esm/jubjub.d.ts.map new file mode 100644 index 00000000000..ec7dbea6e04 --- /dev/null +++ b/packages/noble-curves/esm/jubjub.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"jubjub.d.ts","sourceRoot":"","sources":["../src/jubjub.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AAGxF,eAAO,MAAM,MAAM,EAAE,OAgBV,CAAC;AAOZ,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAUpF;AAKD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAWtF"} \ No newline at end of file diff --git a/packages/noble-curves/esm/jubjub.js b/packages/noble-curves/esm/jubjub.js new file mode 100644 index 00000000000..41a9839b136 --- /dev/null +++ b/packages/noble-curves/esm/jubjub.js @@ -0,0 +1,60 @@ +/** + * jubjub Twisted Edwards curve. + * https://neuromancer.sk/std/other/JubJub + * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { blake2s } from '@noble/hashes/blake2s' +import { sha512 } from '@noble/hashes/sha512' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { twistedEdwards } from './abstract/edwards.js' +import { Field } from './abstract/modular.js' +export const jubjub = /* @__PURE__ */ twistedEdwards({ + // Params: a, d + a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), + d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), + // Finite field 𝔽p over which we'll do calculations + // Same value as bls12-381 Fr (not Fp) + Fp: Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')), + // Subgroup order: how many points curve has + n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), + // Cofactor + h: BigInt(8), + // Base point (x, y) aka generator point + Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), + Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), + hash: sha512, + randomBytes, +}) +const GH_FIRST_BLOCK = utf8ToBytes( + '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', +) +// Returns point at JubJub curve which is prime order and not zero +export function groupHash(tag, personalization) { + const h = blake2s.create({ personalization, dkLen: 32 }) + h.update(GH_FIRST_BLOCK) + h.update(tag) + // NOTE: returns ExtendedPoint, in case it will be multiplied later + let p = jubjub.ExtendedPoint.fromHex(h.digest()) + // NOTE: cannot replace with isSmallOrder, returns Point*8 + p = p.multiply(jubjub.CURVE.h) + if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') + return p +} +// No secret data is leaked here at all. +// It operates over public data: +// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); +export function findGroupHash(m, personalization) { + const tag = concatBytes(m, new Uint8Array([0])) + const hashes = [] + for (let i = 0; i < 256; i++) { + tag[tag.length - 1] = i + try { + hashes.push(groupHash(tag, personalization)) + } catch (e) {} + } + if (!hashes.length) throw new Error('findGroupHash tag overflow') + return hashes[0] +} +//# sourceMappingURL=jubjub.js.map diff --git a/packages/noble-curves/esm/jubjub.js.map b/packages/noble-curves/esm/jubjub.js.map new file mode 100644 index 00000000000..21d9ce5dcf2 --- /dev/null +++ b/packages/noble-curves/esm/jubjub.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jubjub.js","sourceRoot":"","sources":["../src/jubjub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAmC,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,MAAM,CAAC,MAAM,MAAM,GAAY,eAAe,CAAC,cAAc,CAAC;IAC5D,eAAe;IACf,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,oDAAoD;IACpD,sCAAsC;IACtC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC;IACvF,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC,mEAAmE,CAAC;IAC9E,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,IAAI,EAAE,MAAM;IACZ,WAAW;CACH,CAAC,CAAC;AAEZ,MAAM,cAAc,GAAG,WAAW,CAChC,kEAAkE,CACnE,CAAC;AAEF,kEAAkE;AAClE,MAAM,UAAU,SAAS,CAAC,GAAe,EAAE,eAA2B;IACpE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,mEAAmE;IACnE,IAAI,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wCAAwC;AACxC,gCAAgC;AAChC,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,CAAa,EAAE,eAA2B;IACtE,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p256.d.ts b/packages/noble-curves/esm/p256.d.ts new file mode 100644 index 00000000000..b3a570ce137 --- /dev/null +++ b/packages/noble-curves/esm/p256.d.ts @@ -0,0 +1,11 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** secp256r1 curve, ECDSA and ECDH methods. */ +export declare const p256: CurveFnWithCreate +/** Alias to p256. */ +export declare const secp256r1: CurveFnWithCreate +/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p256.d.ts.map diff --git a/packages/noble-curves/esm/p256.d.ts.map b/packages/noble-curves/esm/p256.d.ts.map new file mode 100644 index 00000000000..98dba5c5828 --- /dev/null +++ b/packages/noble-curves/esm/p256.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p256.d.ts","sourceRoot":"","sources":["../src/p256.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAQ3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p256.js b/packages/noble-curves/esm/p256.js new file mode 100644 index 00000000000..9231539b997 --- /dev/null +++ b/packages/noble-curves/esm/p256.js @@ -0,0 +1,54 @@ +/** + * NIST secp256r1 aka p256. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { createCurve } from './_shortw_utils.js' +import { createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' +const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) +const CURVE_A = Fp256.create(BigInt('-3')) +const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') +/** secp256r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +export const p256 = createCurve( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n + // Curve order, total count of valid points in the field + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + // Base (generator) point (x, y) + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, + }, + sha256, +) +/** Alias to p256. */ +export const secp256r1 = p256 +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp256, { + A: CURVE_A, + B: CURVE_B, + Z: Fp256.create(BigInt('-10')), + }))() +const htf = /* @__PURE__ */ (() => + createHasher(secp256r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { + DST: 'P256_XMD:SHA-256_SSWU_RO_', + encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', + p: Fp256.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }))() +/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +//# sourceMappingURL=p256.js.map diff --git a/packages/noble-curves/esm/p256.js.map b/packages/noble-curves/esm/p256.js.map new file mode 100644 index 00000000000..03220895061 --- /dev/null +++ b/packages/noble-curves/esm/p256.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p256.js","sourceRoot":"","sources":["../src/p256.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;AAClG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAE7F,+CAA+C;AAC/C,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,yDAAyD;IACpE,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,MAAM,CAAC,CAAC;AACpB,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p384.d.ts b/packages/noble-curves/esm/p384.d.ts new file mode 100644 index 00000000000..0021526b8cc --- /dev/null +++ b/packages/noble-curves/esm/p384.d.ts @@ -0,0 +1,11 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** secp384r1 curve, ECDSA and ECDH methods. */ +export declare const p384: CurveFnWithCreate +/** Alias to p384. */ +export declare const secp384r1: CurveFnWithCreate +/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p384.d.ts.map diff --git a/packages/noble-curves/esm/p384.d.ts.map b/packages/noble-curves/esm/p384.d.ts.map new file mode 100644 index 00000000000..4e4df4f1803 --- /dev/null +++ b/packages/noble-curves/esm/p384.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p384.d.ts","sourceRoot":"","sources":["../src/p384.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAY3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p384.js b/packages/noble-curves/esm/p384.js new file mode 100644 index 00000000000..3c2dacf9dcc --- /dev/null +++ b/packages/noble-curves/esm/p384.js @@ -0,0 +1,68 @@ +/** + * NIST secp384r1 aka p384. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha384 } from '@noble/hashes/sha512' +import { createCurve } from './_shortw_utils.js' +import { createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', +) +const Fp384 = Field(P) +const CURVE_A = Fp384.create(BigInt('-3')) +// prettier-ignore +const CURVE_B = BigInt( + '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', +) +/** secp384r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +export const p384 = createCurve( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n + // Curve order, total count of valid points in the field. + n: BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', + ), + // Base (generator) point (x, y) + Gx: BigInt( + '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', + ), + Gy: BigInt( + '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', + ), + h: BigInt(1), + lowS: false, + }, + sha384, +) +/** Alias to p384. */ +export const secp384r1 = p384 +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp384, { + A: CURVE_A, + B: CURVE_B, + Z: Fp384.create(BigInt('-12')), + }))() +const htf = /* @__PURE__ */ (() => + createHasher(secp384r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { + DST: 'P384_XMD:SHA-384_SSWU_RO_', + encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', + p: Fp384.ORDER, + m: 1, + k: 192, + expand: 'xmd', + hash: sha384, + }))() +/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +//# sourceMappingURL=p384.js.map diff --git a/packages/noble-curves/esm/p384.js.map b/packages/noble-curves/esm/p384.js.map new file mode 100644 index 00000000000..f878897358d --- /dev/null +++ b/packages/noble-curves/esm/p384.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p384.js","sourceRoot":"","sources":["../src/p384.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AACvH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AACvB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,kBAAkB;AAClB,MAAM,OAAO,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AAE7H,+CAA+C;AAC/C,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,sDAAsD;IACjE,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAC/G,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,MAAM,CAAC,CAAC;AACpB,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p521.d.ts b/packages/noble-curves/esm/p521.d.ts new file mode 100644 index 00000000000..fadd9aad215 --- /dev/null +++ b/packages/noble-curves/esm/p521.d.ts @@ -0,0 +1,12 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** + * NIST secp521r1 aka p521. + */ +export declare const p521: CurveFnWithCreate +export declare const secp521r1: CurveFnWithCreate +/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p521.d.ts.map diff --git a/packages/noble-curves/esm/p521.d.ts.map b/packages/noble-curves/esm/p521.d.ts.map new file mode 100644 index 00000000000..bf0336ad11c --- /dev/null +++ b/packages/noble-curves/esm/p521.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p521.d.ts","sourceRoot":"","sources":["../src/p521.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA2B3E;;GAEG;AAEH,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p521.js b/packages/noble-curves/esm/p521.js new file mode 100644 index 00000000000..7eeff3b69f2 --- /dev/null +++ b/packages/noble-curves/esm/p521.js @@ -0,0 +1,76 @@ +/** + * NIST secp521r1 aka p521. + * Note that it's 521, which differs from 512 of its hash function. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha512' +import { createCurve } from './_shortw_utils.js' +import { createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const Fp521 = Field(P) +const CURVE = { + a: Fp521.create(BigInt('-3')), + b: BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', + ), + Fp: Fp521, + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', + ), + h: BigInt(1), +} +/** + * NIST secp521r1 aka p521. + */ +// prettier-ignore +export const p521 = createCurve( + { + a: CURVE.a, // Equation params: a, b + b: CURVE.b, + Fp: Fp521, // Field: 2n**521n - 1n + // Curve order, total count of valid points in the field + n: CURVE.n, + Gx: CURVE.Gx, // Base point (x, y) aka generator point + Gy: CURVE.Gy, + h: CURVE.h, + lowS: false, + allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b + }, + sha512, +) +export const secp521r1 = p521 +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp521, { + A: CURVE.a, + B: CURVE.b, + Z: Fp521.create(BigInt('-4')), + }))() +const htf = /* @__PURE__ */ (() => + createHasher(secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { + DST: 'P521_XMD:SHA-512_SSWU_RO_', + encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', + p: Fp521.ORDER, + m: 1, + k: 256, + expand: 'xmd', + hash: sha512, + }))() +/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +//# sourceMappingURL=p521.js.map diff --git a/packages/noble-curves/esm/p521.js.map b/packages/noble-curves/esm/p521.js.map new file mode 100644 index 00000000000..30df15022e2 --- /dev/null +++ b/packages/noble-curves/esm/p521.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p521.js","sourceRoot":"","sources":["../src/p521.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,uIAAuI,CAAC,CAAC;AAC1J,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAEvB,MAAM,KAAK,GAAG;IACZ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,KAAK;IACT,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,wBAAwB;IACpC,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,EAAE,uBAAuB;IAClC,wDAAwD;IACxD,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,wCAAwC;IACtD,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,IAAI,EAAE,KAAK;IACX,wBAAwB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,mDAAmD;CACrF,EAAE,MAAM,CAAC,CAAC;AACpB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/package.json b/packages/noble-curves/esm/package.json new file mode 100644 index 00000000000..7f1fc33ddaa --- /dev/null +++ b/packages/noble-curves/esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "sideEffects": false +} diff --git a/packages/noble-curves/esm/pasta.d.ts b/packages/noble-curves/esm/pasta.d.ts new file mode 100644 index 00000000000..8e978183120 --- /dev/null +++ b/packages/noble-curves/esm/pasta.d.ts @@ -0,0 +1,8 @@ +import { type CurveFn } from './abstract/weierstrass.js' +export declare const p: bigint +export declare const q: bigint +/** https://neuromancer.sk/std/other/Pallas */ +export declare const pallas: CurveFn +/** https://neuromancer.sk/std/other/Vesta */ +export declare const vesta: CurveFn +//# sourceMappingURL=pasta.d.ts.map diff --git a/packages/noble-curves/esm/pasta.d.ts.map b/packages/noble-curves/esm/pasta.d.ts.map new file mode 100644 index 00000000000..e07599f2cd3 --- /dev/null +++ b/packages/noble-curves/esm/pasta.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pasta.d.ts","sourceRoot":"","sources":["../src/pasta.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAEtE,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AACF,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,MAAM,EAAE,OASnB,CAAC;AACH,6CAA6C;AAC7C,eAAO,MAAM,KAAK,EAAE,OASlB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/pasta.js b/packages/noble-curves/esm/pasta.js new file mode 100644 index 00000000000..25212dac733 --- /dev/null +++ b/packages/noble-curves/esm/pasta.js @@ -0,0 +1,34 @@ +/** + * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { getHash } from './_shortw_utils.js' +import { Field, mod } from './abstract/modular.js' +import { weierstrass } from './abstract/weierstrass.js' +export const p = BigInt('0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001') +export const q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001') +/** https://neuromancer.sk/std/other/Pallas */ +export const pallas = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(p), + n: q, + Gx: mod(BigInt(-1), p), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +/** https://neuromancer.sk/std/other/Vesta */ +export const vesta = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(q), + n: p, + Gx: mod(BigInt(-1), q), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +//# sourceMappingURL=pasta.js.map diff --git a/packages/noble-curves/esm/pasta.js.map b/packages/noble-curves/esm/pasta.js.map new file mode 100644 index 00000000000..e7841d6952f --- /dev/null +++ b/packages/noble-curves/esm/pasta.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pasta.js","sourceRoot":"","sources":["../src/pasta.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAgB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,CAAC,MAAM,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AACF,MAAM,CAAC,MAAM,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AAEF,8CAA8C;AAC9C,MAAM,CAAC,MAAM,MAAM,GAAY,WAAW,CAAC;IACzC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC;IACJ,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,OAAO,CAAC,MAAM,CAAC;CACnB,CAAC,CAAC;AACH,6CAA6C;AAC7C,MAAM,CAAC,MAAM,KAAK,GAAY,WAAW,CAAC;IACxC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC;IACJ,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,OAAO,CAAC,MAAM,CAAC;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/secp256k1.d.ts b/packages/noble-curves/esm/secp256k1.d.ts new file mode 100644 index 00000000000..0f5d0fdc4d9 --- /dev/null +++ b/packages/noble-curves/esm/secp256k1.d.ts @@ -0,0 +1,71 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +import { mod } from './abstract/modular.js' +import type { Hex, PrivKey } from './abstract/utils.js' +import { bytesToNumberBE, numberToBytesBE } from './abstract/utils.js' +import { type ProjPointType as PointType } from './abstract/weierstrass.js' +/** + * secp256k1 short weierstrass curve and ECDSA signatures over it. + * + * @example + * import { secp256k1 } from '@noble/curves/secp256k1'; + * + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + */ +export declare const secp256k1: CurveFnWithCreate +declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +declare function lift_x(x: bigint): PointType +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +declare function schnorrGetPublicKey(privateKey: Hex): Uint8Array +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +declare function schnorrSign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Uint8Array +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +declare function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean +export type SecpSchnorr = { + getPublicKey: typeof schnorrGetPublicKey + sign: typeof schnorrSign + verify: typeof schnorrVerify + utils: { + randomPrivateKey: () => Uint8Array + lift_x: typeof lift_x + pointToBytes: (point: PointType) => Uint8Array + numberToBytesBE: typeof numberToBytesBE + bytesToNumberBE: typeof bytesToNumberBE + taggedHash: typeof taggedHash + mod: typeof mod + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + */ +export declare const schnorr: SecpSchnorr +/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +export {} +//# sourceMappingURL=secp256k1.d.ts.map diff --git a/packages/noble-curves/esm/secp256k1.d.ts.map b/packages/noble-curves/esm/secp256k1.d.ts.map new file mode 100644 index 00000000000..7ed67065c2a --- /dev/null +++ b/packages/noble-curves/esm/secp256k1.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"secp256k1.d.ts","sourceRoot":"","sources":["../src/secp256k1.ts"],"names":[],"mappings":"AAeA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAc,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAS,GAAG,EAAQ,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAEL,eAAe,EAIf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAuB,KAAK,aAAa,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsCjG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,iBAsCvB,CAAC;AAOF,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAQtE;AAkBD;;;GAGG;AACH,iBAAS,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAS5C;AASD;;GAEG;AACH,iBAAS,mBAAmB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAExD;AAED;;;GAGG;AACH,iBAAS,WAAW,CAClB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,OAAO,EACnB,OAAO,GAAE,GAAqB,GAC7B,UAAU,CAgBZ;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAiB5E;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,OAAO,mBAAmB,CAAC;IACzC,IAAI,EAAE,OAAO,WAAW,CAAC;IACzB,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,UAAU,CAAC;QACnC,MAAM,EAAE,OAAO,MAAM,CAAC;QACtB,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC;QACvD,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC;QAC9B,GAAG,EAAE,OAAO,GAAG,CAAC;KACjB,CAAC;CACH,CAAC;AACF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,WAajB,CAAC;AA2DN,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AAExF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/secp256k1.js b/packages/noble-curves/esm/secp256k1.js new file mode 100644 index 00000000000..02ecf6ce265 --- /dev/null +++ b/packages/noble-curves/esm/secp256k1.js @@ -0,0 +1,299 @@ +/** + * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). + * + * Seems to be rigid (not backdoored) + * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). + * + * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. + * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. + * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. + * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { createCurve } from './_shortw_utils.js' +import { createHasher, isogenyMap } from './abstract/hash-to-curve.js' +import { Field, mod, pow2 } from './abstract/modular.js' +import { + aInRange, + bytesToNumberBE, + concatBytes, + ensureBytes, + inRange, + numberToBytesBE, +} from './abstract/utils.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' +const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') +const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') +const _1n = BigInt(1) +const _2n = BigInt(2) +const divNearest = (a, b) => (a + b / _2n) / b +/** + * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ +function sqrtMod(y) { + const P = secp256k1P + // prettier-ignore + const _3n = BigInt(3), + _6n = BigInt(6), + _11n = BigInt(11), + _22n = BigInt(22) + // prettier-ignore + const _23n = BigInt(23), + _44n = BigInt(44), + _88n = BigInt(88) + const b2 = (y * y * y) % P // x^3, 11 + const b3 = (b2 * b2 * y) % P // x^7 + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b223 = (pow2(b220, _3n, P) * b3) % P + const t1 = (pow2(b223, _23n, P) * b22) % P + const t2 = (pow2(t1, _6n, P) * b2) % P + const root = pow2(t2, _2n, P) + if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') + return root +} +const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) +/** + * secp256k1 short weierstrass curve and ECDSA signatures over it. + * + * @example + * import { secp256k1 } from '@noble/curves/secp256k1'; + * + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + */ +export const secp256k1 = createCurve( + { + a: BigInt(0), // equation params: a, b + b: BigInt(7), + Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n + n: secp256k1N, // Curve order, total count of valid points in the field + // Base point (x, y) aka generator point + Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), + Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + h: BigInt(1), // Cofactor + lowS: true, // Allow only low-S signatures by default in sign() and verify() + endo: { + // Endomorphism, see above + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + splitScalar: (k) => { + const n = secp256k1N + const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') + const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') + const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') + const b2 = a1 + const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) + const c1 = divNearest(b2 * k, n) + const c2 = divNearest(-b1 * k, n) + let k1 = mod(k - c1 * a1 - c2 * a2, n) + let k2 = mod(-c1 * b1 - c2 * b2, n) + const k1neg = k1 > POW_2_128 + const k2neg = k2 > POW_2_128 + if (k1neg) k1 = n - k1 + if (k2neg) k2 = n - k2 + if (k1 > POW_2_128 || k2 > POW_2_128) { + throw new Error('splitScalar: Endomorphism failed, k=' + k) + } + return { k1neg, k1, k2neg, k2 } + }, + }, + }, + sha256, +) +// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. +// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +const _0n = BigInt(0) +/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +const TAGGED_HASH_PREFIXES = {} +function taggedHash(tag, ...messages) { + let tagP = TAGGED_HASH_PREFIXES[tag] + if (tagP === undefined) { + const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) + tagP = concatBytes(tagH, tagH) + TAGGED_HASH_PREFIXES[tag] = tagP + } + return sha256(concatBytes(tagP, ...messages)) +} +// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 +const pointToBytes = (point) => point.toRawBytes(true).slice(1) +const numTo32b = (n) => numberToBytesBE(n, 32) +const modP = (x) => mod(x, secp256k1P) +const modN = (x) => mod(x, secp256k1N) +const Point = secp256k1.ProjectivePoint +const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b) +// Calculate point, scalar and bytes +function schnorrGetExtPubKey(priv) { + let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey + let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside + const scalar = p.hasEvenY() ? d_ : modN(-d_) + return { scalar: scalar, bytes: pointToBytes(p) } +} +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +function lift_x(x) { + aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. + const xx = modP(x * x) + const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. + let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. + if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and + const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. + p.assertValidity() + return p +} +const num = bytesToNumberBE +/** + * Create tagged hash, convert it to bigint, reduce modulo-n. + */ +function challenge(...args) { + return modN(num(taggedHash('BIP0340/challenge', ...args))) +} +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +function schnorrGetPublicKey(privateKey) { + return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) +} +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +function schnorrSign(message, privateKey, auxRand = randomBytes(32)) { + const m = ensureBytes('message', message) + const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder + const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array + const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) + const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) + const k_ = modN(num(rand)) // Let k' = int(rand) mod n + if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. + const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. + const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. + const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). + sig.set(rx, 0) + sig.set(numTo32b(modN(k + e * d)), 32) + // If Verify(bytes(P), m, sig) (see below) returns failure, abort + if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') + return sig +} +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +function schnorrVerify(signature, message, publicKey) { + const sig = ensureBytes('signature', signature, 64) + const m = ensureBytes('message', message) + const pub = ensureBytes('publicKey', publicKey, 32) + try { + const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails + const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. + if (!inRange(r, _1n, secp256k1P)) return false + const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. + if (!inRange(s, _1n, secp256k1N)) return false + const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n + const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P + if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P + return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. + } catch (error) { + return false + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + */ +export const schnorr = /* @__PURE__ */ (() => ({ + getPublicKey: schnorrGetPublicKey, + sign: schnorrSign, + verify: schnorrVerify, + utils: { + randomPrivateKey: secp256k1.utils.randomPrivateKey, + lift_x, + pointToBytes, + numberToBytesBE, + bytesToNumberBE, + taggedHash, + mod, + }, +}))() +const isoMap = /* @__PURE__ */ (() => + isogenyMap( + Fpk1, + [ + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))), + ))() +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fpk1, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fpk1.create(BigInt('-11')), + }))() +const htf = /* @__PURE__ */ (() => + createHasher( + secp256k1.ProjectivePoint, + (scalars) => { + const { x, y } = mapSWU(Fpk1.create(scalars[0])) + return isoMap(x, y) + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fpk1.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }, + ))() +/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() +//# sourceMappingURL=secp256k1.js.map diff --git a/packages/noble-curves/esm/secp256k1.js.map b/packages/noble-curves/esm/secp256k1.js.map new file mode 100644 index 00000000000..297e1c0040a --- /dev/null +++ b/packages/noble-curves/esm/secp256k1.js.map @@ -0,0 +1 @@ +{"version":3,"file":"secp256k1.js","sourceRoot":"","sources":["../src/secp256k1.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/index.d.ts b/packages/noble-curves/index.d.ts new file mode 100644 index 00000000000..a33fb2e99b0 --- /dev/null +++ b/packages/noble-curves/index.d.ts @@ -0,0 +1 @@ +//# sourceMappingURL=index.d.ts.map diff --git a/packages/noble-curves/index.d.ts.map b/packages/noble-curves/index.d.ts.map new file mode 100644 index 00000000000..4e8c5816b41 --- /dev/null +++ b/packages/noble-curves/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/noble-curves/index.js b/packages/noble-curves/index.js new file mode 100644 index 00000000000..59d4449d4fa --- /dev/null +++ b/packages/noble-curves/index.js @@ -0,0 +1,19 @@ +'use strict' +/** + * Audited & minimal JS implementation of elliptic curve cryptography. + * @module + * @example +```js +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + */ +throw new Error('root module cannot be imported: import submodules instead. Check out README') +//# sourceMappingURL=index.js.map diff --git a/packages/noble-curves/index.js.map b/packages/noble-curves/index.js.map new file mode 100644 index 00000000000..5517b0a0e33 --- /dev/null +++ b/packages/noble-curves/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/jubjub.d.ts b/packages/noble-curves/jubjub.d.ts new file mode 100644 index 00000000000..dbd19cd59c8 --- /dev/null +++ b/packages/noble-curves/jubjub.d.ts @@ -0,0 +1,5 @@ +import { type CurveFn, type ExtPointType } from './abstract/edwards.js' +export declare const jubjub: CurveFn +export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType +export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType +//# sourceMappingURL=jubjub.d.ts.map diff --git a/packages/noble-curves/jubjub.d.ts.map b/packages/noble-curves/jubjub.d.ts.map new file mode 100644 index 00000000000..ac68c847b50 --- /dev/null +++ b/packages/noble-curves/jubjub.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"jubjub.d.ts","sourceRoot":"","sources":["src/jubjub.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AAGxF,eAAO,MAAM,MAAM,EAAE,OAgBV,CAAC;AAOZ,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAUpF;AAKD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAWtF"} \ No newline at end of file diff --git a/packages/noble-curves/jubjub.js b/packages/noble-curves/jubjub.js new file mode 100644 index 00000000000..f241c576e90 --- /dev/null +++ b/packages/noble-curves/jubjub.js @@ -0,0 +1,67 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.jubjub = void 0 +exports.groupHash = groupHash +exports.findGroupHash = findGroupHash +/** + * jubjub Twisted Edwards curve. + * https://neuromancer.sk/std/other/JubJub + * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const blake2s_1 = require('@noble/hashes/blake2s') +const sha512_1 = require('@noble/hashes/sha512') +const utils_1 = require('@noble/hashes/utils') +const edwards_js_1 = require('./abstract/edwards.js') +const modular_js_1 = require('./abstract/modular.js') +exports.jubjub = (0, edwards_js_1.twistedEdwards)({ + // Params: a, d + a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), + d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), + // Finite field 𝔽p over which we'll do calculations + // Same value as bls12-381 Fr (not Fp) + Fp: (0, modular_js_1.Field)( + BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), + ), + // Subgroup order: how many points curve has + n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), + // Cofactor + h: BigInt(8), + // Base point (x, y) aka generator point + Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), + Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), + hash: sha512_1.sha512, + randomBytes: utils_1.randomBytes, +}) +const GH_FIRST_BLOCK = (0, utils_1.utf8ToBytes)( + '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', +) +// Returns point at JubJub curve which is prime order and not zero +function groupHash(tag, personalization) { + const h = blake2s_1.blake2s.create({ personalization, dkLen: 32 }) + h.update(GH_FIRST_BLOCK) + h.update(tag) + // NOTE: returns ExtendedPoint, in case it will be multiplied later + let p = exports.jubjub.ExtendedPoint.fromHex(h.digest()) + // NOTE: cannot replace with isSmallOrder, returns Point*8 + p = p.multiply(exports.jubjub.CURVE.h) + if (p.equals(exports.jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') + return p +} +// No secret data is leaked here at all. +// It operates over public data: +// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); +function findGroupHash(m, personalization) { + const tag = (0, utils_1.concatBytes)(m, new Uint8Array([0])) + const hashes = [] + for (let i = 0; i < 256; i++) { + tag[tag.length - 1] = i + try { + hashes.push(groupHash(tag, personalization)) + } catch (e) {} + } + if (!hashes.length) throw new Error('findGroupHash tag overflow') + return hashes[0] +} +//# sourceMappingURL=jubjub.js.map diff --git a/packages/noble-curves/jubjub.js.map b/packages/noble-curves/jubjub.js.map new file mode 100644 index 00000000000..e90880ca0a4 --- /dev/null +++ b/packages/noble-curves/jubjub.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jubjub.js","sourceRoot":"","sources":["src/jubjub.ts"],"names":[],"mappings":";;;AAoCA,8BAUC;AAKD,sCAWC;AA9DD;;;;;GAKG;AACH,sEAAsE;AACtE,mDAAgD;AAChD,iDAA8C;AAC9C,+CAA4E;AAC5E,sDAAwF;AACxF,sDAA8C;AAEjC,QAAA,MAAM,GAA4B,IAAA,2BAAc,EAAC;IAC5D,eAAe;IACf,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,oDAAoD;IACpD,sCAAsC;IACtC,EAAE,EAAE,IAAA,kBAAK,EAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC;IACvF,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC,mEAAmE,CAAC;IAC9E,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,IAAI,EAAE,eAAM;IACZ,WAAW,EAAX,mBAAW;CACH,CAAC,CAAC;AAEZ,MAAM,cAAc,GAAG,IAAA,mBAAW,EAChC,kEAAkE,CACnE,CAAC;AAEF,kEAAkE;AAClE,SAAgB,SAAS,CAAC,GAAe,EAAE,eAA2B;IACpE,MAAM,CAAC,GAAG,iBAAO,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,mEAAmE;IACnE,IAAI,CAAC,GAAG,cAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC,MAAM,CAAC,cAAM,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wCAAwC;AACxC,gCAAgC;AAChC,kFAAkF;AAClF,SAAgB,aAAa,CAAC,CAAa,EAAE,eAA2B;IACtE,MAAM,GAAG,GAAG,IAAA,mBAAW,EAAC,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p256.d.ts b/packages/noble-curves/p256.d.ts new file mode 100644 index 00000000000..b3a570ce137 --- /dev/null +++ b/packages/noble-curves/p256.d.ts @@ -0,0 +1,11 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** secp256r1 curve, ECDSA and ECDH methods. */ +export declare const p256: CurveFnWithCreate +/** Alias to p256. */ +export declare const secp256r1: CurveFnWithCreate +/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p256.d.ts.map diff --git a/packages/noble-curves/p256.d.ts.map b/packages/noble-curves/p256.d.ts.map new file mode 100644 index 00000000000..2f9b171f4d6 --- /dev/null +++ b/packages/noble-curves/p256.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p256.d.ts","sourceRoot":"","sources":["src/p256.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAQ3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p256.js b/packages/noble-curves/p256.js new file mode 100644 index 00000000000..da4a2954b9a --- /dev/null +++ b/packages/noble-curves/p256.js @@ -0,0 +1,63 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.encodeToCurve = exports.hashToCurve = exports.secp256r1 = exports.p256 = void 0 +/** + * NIST secp256r1 aka p256. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha256_1 = require('@noble/hashes/sha256') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +const Fp256 = (0, modular_js_1.Field)( + BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'), +) +const CURVE_A = Fp256.create(BigInt('-3')) +const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') +/** secp256r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +exports.p256 = (0, _shortw_utils_js_1.createCurve)( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n + // Curve order, total count of valid points in the field + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + // Base (generator) point (x, y) + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, + }, + sha256_1.sha256, +) +/** Alias to p256. */ +exports.secp256r1 = exports.p256 +const mapSWU = /* @__PURE__ */ (() => + (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp256, { + A: CURVE_A, + B: CURVE_B, + Z: Fp256.create(BigInt('-10')), + }))() +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.secp256r1.ProjectivePoint, + (scalars) => mapSWU(scalars[0]), + { + DST: 'P256_XMD:SHA-256_SSWU_RO_', + encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', + p: Fp256.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256_1.sha256, + }, + ))() +/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.hashToCurve = (() => htf.hashToCurve)() +/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.encodeToCurve = (() => htf.encodeToCurve)() +//# sourceMappingURL=p256.js.map diff --git a/packages/noble-curves/p256.js.map b/packages/noble-curves/p256.js.map new file mode 100644 index 00000000000..a406427fdf3 --- /dev/null +++ b/packages/noble-curves/p256.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p256.js","sourceRoot":"","sources":["src/p256.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;AAClG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAE7F,+CAA+C;AAC/C,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,yDAAyD;IACpE,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,eAAM,CAAC,CAAC;AACpB,qBAAqB;AACR,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p384.d.ts b/packages/noble-curves/p384.d.ts new file mode 100644 index 00000000000..0021526b8cc --- /dev/null +++ b/packages/noble-curves/p384.d.ts @@ -0,0 +1,11 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** secp384r1 curve, ECDSA and ECDH methods. */ +export declare const p384: CurveFnWithCreate +/** Alias to p384. */ +export declare const secp384r1: CurveFnWithCreate +/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p384.d.ts.map diff --git a/packages/noble-curves/p384.d.ts.map b/packages/noble-curves/p384.d.ts.map new file mode 100644 index 00000000000..b14531b1497 --- /dev/null +++ b/packages/noble-curves/p384.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p384.d.ts","sourceRoot":"","sources":["src/p384.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAY3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p384.js b/packages/noble-curves/p384.js new file mode 100644 index 00000000000..217a7dcc237 --- /dev/null +++ b/packages/noble-curves/p384.js @@ -0,0 +1,75 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.encodeToCurve = exports.hashToCurve = exports.secp384r1 = exports.p384 = void 0 +/** + * NIST secp384r1 aka p384. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha512_1 = require('@noble/hashes/sha512') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', +) +const Fp384 = (0, modular_js_1.Field)(P) +const CURVE_A = Fp384.create(BigInt('-3')) +// prettier-ignore +const CURVE_B = BigInt( + '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', +) +/** secp384r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +exports.p384 = (0, _shortw_utils_js_1.createCurve)( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n + // Curve order, total count of valid points in the field. + n: BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', + ), + // Base (generator) point (x, y) + Gx: BigInt( + '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', + ), + Gy: BigInt( + '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', + ), + h: BigInt(1), + lowS: false, + }, + sha512_1.sha384, +) +/** Alias to p384. */ +exports.secp384r1 = exports.p384 +const mapSWU = /* @__PURE__ */ (() => + (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp384, { + A: CURVE_A, + B: CURVE_B, + Z: Fp384.create(BigInt('-12')), + }))() +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.secp384r1.ProjectivePoint, + (scalars) => mapSWU(scalars[0]), + { + DST: 'P384_XMD:SHA-384_SSWU_RO_', + encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', + p: Fp384.ORDER, + m: 1, + k: 192, + expand: 'xmd', + hash: sha512_1.sha384, + }, + ))() +/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.hashToCurve = (() => htf.hashToCurve)() +/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.encodeToCurve = (() => htf.encodeToCurve)() +//# sourceMappingURL=p384.js.map diff --git a/packages/noble-curves/p384.js.map b/packages/noble-curves/p384.js.map new file mode 100644 index 00000000000..173153e2a82 --- /dev/null +++ b/packages/noble-curves/p384.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p384.js","sourceRoot":"","sources":["src/p384.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AACvH,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,CAAC,CAAC,CAAC;AACvB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,kBAAkB;AAClB,MAAM,OAAO,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AAE7H,+CAA+C;AAC/C,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,sDAAsD;IACjE,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAC/G,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,eAAM,CAAC,CAAC;AACpB,qBAAqB;AACR,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p521.d.ts b/packages/noble-curves/p521.d.ts new file mode 100644 index 00000000000..fadd9aad215 --- /dev/null +++ b/packages/noble-curves/p521.d.ts @@ -0,0 +1,12 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +/** + * NIST secp521r1 aka p521. + */ +export declare const p521: CurveFnWithCreate +export declare const secp521r1: CurveFnWithCreate +/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +//# sourceMappingURL=p521.d.ts.map diff --git a/packages/noble-curves/p521.d.ts.map b/packages/noble-curves/p521.d.ts.map new file mode 100644 index 00000000000..32fecfca8a3 --- /dev/null +++ b/packages/noble-curves/p521.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"p521.d.ts","sourceRoot":"","sources":["src/p521.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA2B3E;;GAEG;AAEH,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p521.js b/packages/noble-curves/p521.js new file mode 100644 index 00000000000..e5d9c45617d --- /dev/null +++ b/packages/noble-curves/p521.js @@ -0,0 +1,83 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.encodeToCurve = exports.hashToCurve = exports.secp521r1 = exports.p521 = void 0 +/** + * NIST secp521r1 aka p521. + * Note that it's 521, which differs from 512 of its hash function. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha512_1 = require('@noble/hashes/sha512') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const Fp521 = (0, modular_js_1.Field)(P) +const CURVE = { + a: Fp521.create(BigInt('-3')), + b: BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', + ), + Fp: Fp521, + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', + ), + h: BigInt(1), +} +/** + * NIST secp521r1 aka p521. + */ +// prettier-ignore +exports.p521 = (0, _shortw_utils_js_1.createCurve)( + { + a: CURVE.a, // Equation params: a, b + b: CURVE.b, + Fp: Fp521, // Field: 2n**521n - 1n + // Curve order, total count of valid points in the field + n: CURVE.n, + Gx: CURVE.Gx, // Base point (x, y) aka generator point + Gy: CURVE.Gy, + h: CURVE.h, + lowS: false, + allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b + }, + sha512_1.sha512, +) +exports.secp521r1 = exports.p521 +const mapSWU = /* @__PURE__ */ (() => + (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp521, { + A: CURVE.a, + B: CURVE.b, + Z: Fp521.create(BigInt('-4')), + }))() +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.secp521r1.ProjectivePoint, + (scalars) => mapSWU(scalars[0]), + { + DST: 'P521_XMD:SHA-512_SSWU_RO_', + encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', + p: Fp521.ORDER, + m: 1, + k: 256, + expand: 'xmd', + hash: sha512_1.sha512, + }, + ))() +/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.hashToCurve = (() => htf.hashToCurve)() +/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.encodeToCurve = (() => htf.encodeToCurve)() +//# sourceMappingURL=p521.js.map diff --git a/packages/noble-curves/p521.js.map b/packages/noble-curves/p521.js.map new file mode 100644 index 00000000000..44374ecdc57 --- /dev/null +++ b/packages/noble-curves/p521.js.map @@ -0,0 +1 @@ +{"version":3,"file":"p521.js","sourceRoot":"","sources":["src/p521.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,uIAAuI,CAAC,CAAC;AAC1J,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,CAAC,CAAC,CAAC;AAEvB,MAAM,KAAK,GAAG;IACZ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,KAAK;IACT,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,wBAAwB;IACpC,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,EAAE,uBAAuB;IAClC,wDAAwD;IACxD,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,wCAAwC;IACtD,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,IAAI,EAAE,KAAK;IACX,wBAAwB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,mDAAmD;CACrF,EAAE,eAAM,CAAC,CAAC;AACP,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/package.json b/packages/noble-curves/package.json new file mode 100644 index 00000000000..b8af4db465b --- /dev/null +++ b/packages/noble-curves/package.json @@ -0,0 +1,163 @@ +{ + "name": "@noble/curves", + "version": "1.8.1", + "description": "Audited & minimal JS implementation of elliptic curve cryptography", + "files": ["*.js", "*.js.map", "*.d.ts", "*.d.ts.map", "esm", "src", "abstract"], + "scripts": { + "bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js; node ristretto255.js; node decaf448.js", + "bench:install": "cd benchmark; npm install; npm install .. --install-links", + "build": "tsc && tsc -p tsconfig.cjs.json", + "build:release": "npx jsbt esbuild test/build", + "build:clean": "rm {.,esm,abstract,esm/abstract}/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null", + "lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'", + "format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'", + "test": "node test/index.js", + "test:bun": "bun test/index.js", + "test:deno": "deno --allow-env --allow-read test/index.js", + "test:coverage": "npm install --no-save c8@10.1.2 && npx c8 npm test" + }, + "author": "Paul Miller (https://paulmillr.com)", + "homepage": "https://paulmillr.com/noble/", + "repository": { + "type": "git", + "url": "git+https://github.com/paulmillr/noble-curves.git" + }, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "devDependencies": { + "@paulmillr/jsbt": "0.3.1", + "fast-check": "3.0.0", + "micro-bmark": "0.4.0", + "micro-should": "0.5.1", + "prettier": "3.3.2", + "typescript": "5.5.2" + }, + "sideEffects": false, + "main": "index.js", + "exports": { + ".": { + "import": "./esm/index.js", + "require": "./index.js" + }, + "./abstract/bls": { + "import": "./esm/abstract/bls.js", + "require": "./abstract/bls.js" + }, + "./abstract/curve": { + "import": "./esm/abstract/curve.js", + "require": "./abstract/curve.js" + }, + "./abstract/edwards": { + "import": "./esm/abstract/edwards.js", + "require": "./abstract/edwards.js" + }, + "./abstract/hash-to-curve": { + "import": "./esm/abstract/hash-to-curve.js", + "require": "./abstract/hash-to-curve.js" + }, + "./abstract/modular": { + "import": "./esm/abstract/modular.js", + "require": "./abstract/modular.js" + }, + "./abstract/montgomery": { + "import": "./esm/abstract/montgomery.js", + "require": "./abstract/montgomery.js" + }, + "./abstract/poseidon": { + "import": "./esm/abstract/poseidon.js", + "require": "./abstract/poseidon.js" + }, + "./abstract/tower": { + "import": "./esm/abstract/tower.js", + "require": "./abstract/tower.js" + }, + "./abstract/utils": { + "import": "./esm/abstract/utils.js", + "require": "./abstract/utils.js" + }, + "./abstract/weierstrass": { + "import": "./esm/abstract/weierstrass.js", + "require": "./abstract/weierstrass.js" + }, + "./_shortw_utils": { + "import": "./esm/_shortw_utils.js", + "require": "./_shortw_utils.js" + }, + "./bls12-381": { + "import": "./esm/bls12-381.js", + "require": "./bls12-381.js" + }, + "./bn254": { + "import": "./esm/bn254.js", + "require": "./bn254.js" + }, + "./ed25519": { + "import": "./esm/ed25519.js", + "require": "./ed25519.js" + }, + "./ed448": { + "import": "./esm/ed448.js", + "require": "./ed448.js" + }, + "./index": { + "import": "./esm/index.js", + "require": "./index.js" + }, + "./jubjub": { + "import": "./esm/jubjub.js", + "require": "./jubjub.js" + }, + "./p256": { + "import": "./esm/p256.js", + "require": "./p256.js" + }, + "./p384": { + "import": "./esm/p384.js", + "require": "./p384.js" + }, + "./p521": { + "import": "./esm/p521.js", + "require": "./p521.js" + }, + "./pasta": { + "import": "./esm/pasta.js", + "require": "./pasta.js" + }, + "./secp256k1": { + "import": "./esm/secp256k1.js", + "require": "./secp256k1.js" + } + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "keywords": [ + "elliptic", + "curve", + "cryptography", + "secp256k1", + "ed25519", + "p256", + "p384", + "p521", + "secp256r1", + "ed448", + "x25519", + "ed25519", + "bls12-381", + "bn254", + "alt_bn128", + "bls", + "noble", + "ecc", + "ecdsa", + "eddsa", + "weierstrass", + "montgomery", + "edwards", + "schnorr" + ], + "funding": "https://paulmillr.com/funding/" +} diff --git a/packages/noble-curves/pasta.d.ts b/packages/noble-curves/pasta.d.ts new file mode 100644 index 00000000000..8e978183120 --- /dev/null +++ b/packages/noble-curves/pasta.d.ts @@ -0,0 +1,8 @@ +import { type CurveFn } from './abstract/weierstrass.js' +export declare const p: bigint +export declare const q: bigint +/** https://neuromancer.sk/std/other/Pallas */ +export declare const pallas: CurveFn +/** https://neuromancer.sk/std/other/Vesta */ +export declare const vesta: CurveFn +//# sourceMappingURL=pasta.d.ts.map diff --git a/packages/noble-curves/pasta.d.ts.map b/packages/noble-curves/pasta.d.ts.map new file mode 100644 index 00000000000..4d8421c35a8 --- /dev/null +++ b/packages/noble-curves/pasta.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pasta.d.ts","sourceRoot":"","sources":["src/pasta.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAEtE,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AACF,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,MAAM,EAAE,OASnB,CAAC;AACH,6CAA6C;AAC7C,eAAO,MAAM,KAAK,EAAE,OASlB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/pasta.js b/packages/noble-curves/pasta.js new file mode 100644 index 00000000000..2e22a27d5f1 --- /dev/null +++ b/packages/noble-curves/pasta.js @@ -0,0 +1,37 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.vesta = exports.pallas = exports.q = exports.p = void 0 +/** + * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha256_1 = require('@noble/hashes/sha256') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const modular_js_1 = require('./abstract/modular.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +exports.p = BigInt('0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001') +exports.q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001') +/** https://neuromancer.sk/std/other/Pallas */ +exports.pallas = (0, weierstrass_js_1.weierstrass)({ + a: BigInt(0), + b: BigInt(5), + Fp: (0, modular_js_1.Field)(exports.p), + n: exports.q, + Gx: (0, modular_js_1.mod)(BigInt(-1), exports.p), + Gy: BigInt(2), + h: BigInt(1), + ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), +}) +/** https://neuromancer.sk/std/other/Vesta */ +exports.vesta = (0, weierstrass_js_1.weierstrass)({ + a: BigInt(0), + b: BigInt(5), + Fp: (0, modular_js_1.Field)(exports.q), + n: exports.p, + Gx: (0, modular_js_1.mod)(BigInt(-1), exports.q), + Gy: BigInt(2), + h: BigInt(1), + ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), +}) +//# sourceMappingURL=pasta.js.map diff --git a/packages/noble-curves/pasta.js.map b/packages/noble-curves/pasta.js.map new file mode 100644 index 00000000000..dc936d9e557 --- /dev/null +++ b/packages/noble-curves/pasta.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pasta.js","sourceRoot":"","sources":["src/pasta.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAA6C;AAC7C,sDAAmD;AACnD,8DAAsE;AAEzD,QAAA,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AACW,QAAA,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AAEF,8CAA8C;AACjC,QAAA,MAAM,GAAY,IAAA,4BAAW,EAAC;IACzC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,IAAA,kBAAK,EAAC,SAAC,CAAC;IACZ,CAAC,EAAE,SAAC;IACJ,EAAE,EAAE,IAAA,gBAAG,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,IAAA,0BAAO,EAAC,eAAM,CAAC;CACnB,CAAC,CAAC;AACH,6CAA6C;AAChC,QAAA,KAAK,GAAY,IAAA,4BAAW,EAAC;IACxC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,IAAA,kBAAK,EAAC,SAAC,CAAC;IACZ,CAAC,EAAE,SAAC;IACJ,EAAE,EAAE,IAAA,gBAAG,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,IAAA,0BAAO,EAAC,eAAM,CAAC;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/secp256k1.d.ts b/packages/noble-curves/secp256k1.d.ts new file mode 100644 index 00000000000..0f5d0fdc4d9 --- /dev/null +++ b/packages/noble-curves/secp256k1.d.ts @@ -0,0 +1,71 @@ +import { type CurveFnWithCreate } from './_shortw_utils.js' +import { type HTFMethod } from './abstract/hash-to-curve.js' +import { mod } from './abstract/modular.js' +import type { Hex, PrivKey } from './abstract/utils.js' +import { bytesToNumberBE, numberToBytesBE } from './abstract/utils.js' +import { type ProjPointType as PointType } from './abstract/weierstrass.js' +/** + * secp256k1 short weierstrass curve and ECDSA signatures over it. + * + * @example + * import { secp256k1 } from '@noble/curves/secp256k1'; + * + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + */ +export declare const secp256k1: CurveFnWithCreate +declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +declare function lift_x(x: bigint): PointType +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +declare function schnorrGetPublicKey(privateKey: Hex): Uint8Array +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +declare function schnorrSign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Uint8Array +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +declare function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean +export type SecpSchnorr = { + getPublicKey: typeof schnorrGetPublicKey + sign: typeof schnorrSign + verify: typeof schnorrVerify + utils: { + randomPrivateKey: () => Uint8Array + lift_x: typeof lift_x + pointToBytes: (point: PointType) => Uint8Array + numberToBytesBE: typeof numberToBytesBE + bytesToNumberBE: typeof bytesToNumberBE + taggedHash: typeof taggedHash + mod: typeof mod + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + */ +export declare const schnorr: SecpSchnorr +/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const hashToCurve: HTFMethod +/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export declare const encodeToCurve: HTFMethod +export {} +//# sourceMappingURL=secp256k1.d.ts.map diff --git a/packages/noble-curves/secp256k1.d.ts.map b/packages/noble-curves/secp256k1.d.ts.map new file mode 100644 index 00000000000..0615024d341 --- /dev/null +++ b/packages/noble-curves/secp256k1.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"secp256k1.d.ts","sourceRoot":"","sources":["src/secp256k1.ts"],"names":[],"mappings":"AAeA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAc,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAS,GAAG,EAAQ,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAEL,eAAe,EAIf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAuB,KAAK,aAAa,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsCjG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,iBAsCvB,CAAC;AAOF,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAQtE;AAkBD;;;GAGG;AACH,iBAAS,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAS5C;AASD;;GAEG;AACH,iBAAS,mBAAmB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAExD;AAED;;;GAGG;AACH,iBAAS,WAAW,CAClB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,OAAO,EACnB,OAAO,GAAE,GAAqB,GAC7B,UAAU,CAgBZ;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAiB5E;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,OAAO,mBAAmB,CAAC;IACzC,IAAI,EAAE,OAAO,WAAW,CAAC;IACzB,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,UAAU,CAAC;QACnC,MAAM,EAAE,OAAO,MAAM,CAAC;QACtB,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC;QACvD,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC;QAC9B,GAAG,EAAE,OAAO,GAAG,CAAC;KACjB,CAAC;CACH,CAAC;AACF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,WAajB,CAAC;AA2DN,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AAExF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/secp256k1.js b/packages/noble-curves/secp256k1.js new file mode 100644 index 00000000000..63cc0784f45 --- /dev/null +++ b/packages/noble-curves/secp256k1.js @@ -0,0 +1,295 @@ +'use strict' +Object.defineProperty(exports, '__esModule', { value: true }) +exports.encodeToCurve = exports.hashToCurve = exports.schnorr = exports.secp256k1 = void 0 +/** + * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). + * + * Seems to be rigid (not backdoored) + * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). + * + * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. + * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. + * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. + * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +const sha256_1 = require('@noble/hashes/sha256') +const utils_1 = require('@noble/hashes/utils') +const _shortw_utils_js_1 = require('./_shortw_utils.js') +const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') +const modular_js_1 = require('./abstract/modular.js') +const utils_js_1 = require('./abstract/utils.js') +const weierstrass_js_1 = require('./abstract/weierstrass.js') +const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') +const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') +const _1n = BigInt(1) +const _2n = BigInt(2) +const divNearest = (a, b) => (a + b / _2n) / b +/** + * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ +function sqrtMod(y) { + const P = secp256k1P + // prettier-ignore + const _3n = BigInt(3), + _6n = BigInt(6), + _11n = BigInt(11), + _22n = BigInt(22) + // prettier-ignore + const _23n = BigInt(23), + _44n = BigInt(44), + _88n = BigInt(88) + const b2 = (y * y * y) % P // x^3, 11 + const b3 = (b2 * b2 * y) % P // x^7 + const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P + const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P + const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P + const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P + const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P + const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P + const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P + const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P + const b223 = ((0, modular_js_1.pow2)(b220, _3n, P) * b3) % P + const t1 = ((0, modular_js_1.pow2)(b223, _23n, P) * b22) % P + const t2 = ((0, modular_js_1.pow2)(t1, _6n, P) * b2) % P + const root = (0, modular_js_1.pow2)(t2, _2n, P) + if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') + return root +} +const Fpk1 = (0, modular_js_1.Field)(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) +/** + * secp256k1 short weierstrass curve and ECDSA signatures over it. + * + * @example + * import { secp256k1 } from '@noble/curves/secp256k1'; + * + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + */ +exports.secp256k1 = (0, _shortw_utils_js_1.createCurve)( + { + a: BigInt(0), // equation params: a, b + b: BigInt(7), + Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n + n: secp256k1N, // Curve order, total count of valid points in the field + // Base point (x, y) aka generator point + Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), + Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + h: BigInt(1), // Cofactor + lowS: true, // Allow only low-S signatures by default in sign() and verify() + endo: { + // Endomorphism, see above + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + splitScalar: (k) => { + const n = secp256k1N + const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') + const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') + const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') + const b2 = a1 + const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) + const c1 = divNearest(b2 * k, n) + const c2 = divNearest(-b1 * k, n) + let k1 = (0, modular_js_1.mod)(k - c1 * a1 - c2 * a2, n) + let k2 = (0, modular_js_1.mod)(-c1 * b1 - c2 * b2, n) + const k1neg = k1 > POW_2_128 + const k2neg = k2 > POW_2_128 + if (k1neg) k1 = n - k1 + if (k2neg) k2 = n - k2 + if (k1 > POW_2_128 || k2 > POW_2_128) { + throw new Error('splitScalar: Endomorphism failed, k=' + k) + } + return { k1neg, k1, k2neg, k2 } + }, + }, + }, + sha256_1.sha256, +) +// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. +// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +const _0n = BigInt(0) +/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +const TAGGED_HASH_PREFIXES = {} +function taggedHash(tag, ...messages) { + let tagP = TAGGED_HASH_PREFIXES[tag] + if (tagP === undefined) { + const tagH = (0, sha256_1.sha256)(Uint8Array.from(tag, (c) => c.charCodeAt(0))) + tagP = (0, utils_js_1.concatBytes)(tagH, tagH) + TAGGED_HASH_PREFIXES[tag] = tagP + } + return (0, sha256_1.sha256)((0, utils_js_1.concatBytes)(tagP, ...messages)) +} +// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 +const pointToBytes = (point) => point.toRawBytes(true).slice(1) +const numTo32b = (n) => (0, utils_js_1.numberToBytesBE)(n, 32) +const modP = (x) => (0, modular_js_1.mod)(x, secp256k1P) +const modN = (x) => (0, modular_js_1.mod)(x, secp256k1N) +const Point = exports.secp256k1.ProjectivePoint +const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b) +// Calculate point, scalar and bytes +function schnorrGetExtPubKey(priv) { + let d_ = exports.secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey + let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside + const scalar = p.hasEvenY() ? d_ : modN(-d_) + return { scalar: scalar, bytes: pointToBytes(p) } +} +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +function lift_x(x) { + ;(0, utils_js_1.aInRange)('x', x, _1n, secp256k1P) // Fail if x ≥ p. + const xx = modP(x * x) + const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. + let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. + if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and + const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. + p.assertValidity() + return p +} +const num = utils_js_1.bytesToNumberBE +/** + * Create tagged hash, convert it to bigint, reduce modulo-n. + */ +function challenge(...args) { + return modN(num(taggedHash('BIP0340/challenge', ...args))) +} +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +function schnorrGetPublicKey(privateKey) { + return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) +} +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +function schnorrSign(message, privateKey, auxRand = (0, utils_1.randomBytes)(32)) { + const m = (0, utils_js_1.ensureBytes)('message', message) + const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder + const a = (0, utils_js_1.ensureBytes)('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array + const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) + const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) + const k_ = modN(num(rand)) // Let k' = int(rand) mod n + if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. + const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. + const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. + const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). + sig.set(rx, 0) + sig.set(numTo32b(modN(k + e * d)), 32) + // If Verify(bytes(P), m, sig) (see below) returns failure, abort + if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') + return sig +} +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +function schnorrVerify(signature, message, publicKey) { + const sig = (0, utils_js_1.ensureBytes)('signature', signature, 64) + const m = (0, utils_js_1.ensureBytes)('message', message) + const pub = (0, utils_js_1.ensureBytes)('publicKey', publicKey, 32) + try { + const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails + const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. + if (!(0, utils_js_1.inRange)(r, _1n, secp256k1P)) return false + const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. + if (!(0, utils_js_1.inRange)(s, _1n, secp256k1N)) return false + const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n + const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P + if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P + return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. + } catch (error) { + return false + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + */ +exports.schnorr = (() => ({ + getPublicKey: schnorrGetPublicKey, + sign: schnorrSign, + verify: schnorrVerify, + utils: { + randomPrivateKey: exports.secp256k1.utils.randomPrivateKey, + lift_x, + pointToBytes, + numberToBytesBE: utils_js_1.numberToBytesBE, + bytesToNumberBE: utils_js_1.bytesToNumberBE, + taggedHash, + mod: modular_js_1.mod, + }, +}))() +const isoMap = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.isogenyMap)( + Fpk1, + [ + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))), + ))() +const mapSWU = /* @__PURE__ */ (() => + (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fpk1, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fpk1.create(BigInt('-11')), + }))() +const htf = /* @__PURE__ */ (() => + (0, hash_to_curve_js_1.createHasher)( + exports.secp256k1.ProjectivePoint, + (scalars) => { + const { x, y } = mapSWU(Fpk1.create(scalars[0])) + return isoMap(x, y) + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fpk1.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256_1.sha256, + }, + ))() +/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.hashToCurve = (() => htf.hashToCurve)() +/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +exports.encodeToCurve = (() => htf.encodeToCurve)() +//# sourceMappingURL=secp256k1.js.map diff --git a/packages/noble-curves/secp256k1.js.map b/packages/noble-curves/secp256k1.js.map new file mode 100644 index 00000000000..e37b90ab9d9 --- /dev/null +++ b/packages/noble-curves/secp256k1.js.map @@ -0,0 +1 @@ +{"version":3,"file":"secp256k1.js","sourceRoot":"","sources":["src/secp256k1.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/src/_shortw_utils.ts b/packages/noble-curves/src/_shortw_utils.ts new file mode 100644 index 00000000000..9fe8d7f623c --- /dev/null +++ b/packages/noble-curves/src/_shortw_utils.ts @@ -0,0 +1,30 @@ +/** + * Utilities for short weierstrass curves, combined with noble-hashes. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { hmac } from '@noble/hashes/hmac' +import { concatBytes, randomBytes } from '@noble/hashes/utils' +import type { CHash } from './abstract/utils.js' +import { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.js' + +/** connects noble-curves to noble-hashes */ +export function getHash(hash: CHash): { + hash: CHash + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array + randomBytes: typeof randomBytes +} { + return { + hash, + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)), + randomBytes, + } +} +/** Same API as @noble/hashes, with ability to create curve with custom hash */ +export type CurveDef = Readonly> +export type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn } + +export function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate { + const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, ...getHash(hash) }) + return { ...create(defHash), create } +} diff --git a/packages/noble-curves/src/abstract/bls.ts b/packages/noble-curves/src/abstract/bls.ts new file mode 100644 index 00000000000..3b29c0bf3e5 --- /dev/null +++ b/packages/noble-curves/src/abstract/bls.ts @@ -0,0 +1,574 @@ +// prettier-ignore +import { + type H2CPointConstructor, + type Opts as HTFOpts, + type MapToCurve, + createHasher, + type htfBasicOpts, +} from './hash-to-curve.js' +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// TODO: import { AffinePoint } from './curve.js'; +import { type IField, getMinHashLength, mapHashToField } from './modular.js' +import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' +import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.js' +import { + type CurvePointsRes, + type CurvePointsType, + type ProjPointType, + weierstrassPoints, +} from './weierstrass.js' + +type Fp = bigint // Can be different field? + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +export type TwistType = 'multiplicative' | 'divisive' + +export type ShortSignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type SignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type PostPrecomputePointAddFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, +) => { Rx: Fp2; Ry: Fp2; Rz: Fp2 } +export type PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => void +export type CurveType = { + G1: Omit, 'n'> & { + ShortSignature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + G2: Omit, 'n'> & { + Signature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + fields: { + Fp: IField + Fr: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + } + params: { + // NOTE: MSB is always ignored and used as marker for length, + // otherwise leading zeros will be lost. + // Can be different from 'X' (seed) param! + ateLoopSize: bigint + xNegative: boolean + r: bigint + twistType: TwistType // BLS12-381: Multiplicative, BN254: Divisive + } + htfDefaults: HTFOpts + hash: CHash // Because we need outputLen for DRBG + randomBytes: (bytesLength?: number) => Uint8Array + // This is super ugly hack for untwist point in BN254 after miller loop + postPrecompute?: PostPrecomputeFn +} + +type PrecomputeSingle = [Fp2, Fp2, Fp2][] +type Precompute = PrecomputeSingle[] + +export type CurveFn = { + getPublicKey: (privateKey: PrivKey) => Uint8Array + getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array + sign: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + signShortSignature: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + verify: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyShortSignature: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyBatch: ( + signature: Hex | ProjPointType, + messages: (Hex | ProjPointType)[], + publicKeys: (Hex | ProjPointType)[], + htfOpts?: htfBasicOpts, + ) => boolean + aggregatePublicKeys: { + (publicKeys: Hex[]): Uint8Array + (publicKeys: ProjPointType[]): ProjPointType + } + aggregateSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + aggregateShortSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 + pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 + pairingBatch: ( + pairs: { g1: ProjPointType; g2: ProjPointType }[], + withFinalExponent?: boolean, + ) => Fp12 + G1: CurvePointsRes & ReturnType> + G2: CurvePointsRes & ReturnType> + Signature: SignatureCoder + ShortSignature: ShortSignatureCoder + params: { + ateLoopSize: bigint + r: bigint + G1b: bigint + G2b: Fp2 + } + fields: { + Fp: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + Fr: IField + } + utils: { + randomPrivateKey: () => Uint8Array + calcPairingPrecomputes: (p: ProjPointType) => Precompute + } +} + +// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. +function NAfDecomposition(a: bigint) { + const res = [] + // a>1 because of marker bit + for (; a > _1n; a >>= _1n) { + if ((a & _1n) === _0n) res.unshift(0) + else if ((a & _3n) === _3n) { + res.unshift(-1) + a += _1n + } else res.unshift(1) + } + return res +} + +export function bls(CURVE: CurveType): CurveFn { + // Fields are specific for curve, so for now we'll need to pass them with opts + const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields + const BLS_X_IS_NEGATIVE = CURVE.params.xNegative + const TWIST: TwistType = CURVE.params.twistType + // Point on G1 curve: (x, y) + const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) + const G1 = Object.assign( + G1_, + createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G1.htfDefaults, + }), + ) + // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) + const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) + const G2 = Object.assign( + G2_, + createHasher(G2_.ProjectivePoint as H2CPointConstructor, CURVE.G2.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G2.htfDefaults, + }), + ) + type G1 = typeof G1.ProjectivePoint.BASE + type G2 = typeof G2.ProjectivePoint.BASE + + // Applies sparse multiplication as line function + let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12 + if (TWIST === 'multiplicative') { + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) + } else if (TWIST === 'divisive') { + // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of + // precompute calculations. + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) + } else throw new Error('bls: unknown twist type') + + const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) + function pointDouble(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2) { + const t0 = Fp2.sqr(Ry) // Ry² + const t1 = Fp2.sqr(Rz) // Rz² + const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B + const t3 = Fp2.mul(t2, _3n) // 3 * T2 + const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 + const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) + const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² + const c2 = Fp2.neg(t4) // -T4 (-h) + + ell.push([c0, c1, c2]) + + Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 + Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² + Rz = Fp2.mul(t0, t4) // T0 * T4 + return { Rx, Ry, Rz } + } + function pointAdd(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) { + // Addition + const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz + const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz + const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy + const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry + const c2 = t1 // == Rx - Qx * Rz + + ell.push([c0, c1, c2]) + + const t2 = Fp2.sqr(t1) // T1² + const t3 = Fp2.mul(t2, t1) // T2 * T1 + const t4 = Fp2.mul(t2, Rx) // T2 * Rx + const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz + Rx = Fp2.mul(t1, t5) // T1 * T5 + Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry + Rz = Fp2.mul(Rz, t3) // Rz * T3 + return { Rx, Ry, Rz } + } + + // Pre-compute coefficients for sparse multiplication + // Point addition and point double calculations is reused for coefficients + // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine + // add + double in windowed precomputes here, otherwise it would be single op (since X is static) + const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) + + const calcPairingPrecomputes = memoized((point: G2) => { + const p = point + const { x, y } = p.toAffine() + // prettier-ignore + const Qx = x, + Qy = y, + negQy = Fp2.neg(y) + // prettier-ignore + let Rx = Qx, + Ry = Qy, + Rz = Fp2.ONE + const ell: Precompute = [] + for (const bit of ATE_NAF) { + const cur: PrecomputeSingle = [] + ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) + if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) + ell.push(cur) + } + if (CURVE.postPrecompute) { + const last = ell[ell.length - 1] + CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) + } + return ell + }) + + // Main pairing logic is here. Computes product of miller loops + final exponentiate + // Applies calculated precomputes + type MillerInput = [Precompute, Fp, Fp][] + function millerLoopBatch(pairs: MillerInput, withFinalExponent: boolean = false) { + let f12 = Fp12.ONE + if (pairs.length) { + const ellLen = pairs[0][0].length + for (let i = 0; i < ellLen; i++) { + f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings + // NOTE: we apply multiple pairings in parallel here + for (const [ell, Px, Py] of pairs) { + for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) + } + } + } + if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) + return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 + } + type PairingInput = { g1: G1; g2: G2 } + // Calculates product of multiple pairings + // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` + function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) { + const res: MillerInput = [] + // This cache precomputed toAffine for all points + G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) + G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) + for (const { g1, g2 } of pairs) { + if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) + throw new Error('pairing is not available for ZERO point') + // This uses toAffine inside + g1.assertValidity() + g2.assertValidity() + const Qa = g1.toAffine() + res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) + } + return millerLoopBatch(res, withFinalExponent) + } + // Calculates bilinear pairing + function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 { + return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) + } + + const utils = { + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(Fr.ORDER) + return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) + }, + calcPairingPrecomputes, + } + + const { ShortSignature } = CURVE.G1 + const { Signature } = CURVE.G2 + + type G1Hex = Hex | G1 + type G2Hex = Hex | G2 + function normP1(point: G1Hex): G1 { + return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point) + } + function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 { + return point instanceof G1.ProjectivePoint + ? point + : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1) + } + function normP2(point: G2Hex): G2 { + return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) + } + function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 { + return point instanceof G2.ProjectivePoint + ? point + : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2) + } + + // Multiplies generator (G1) by private key. + // P = pk x G + function getPublicKey(privateKey: PrivKey): Uint8Array { + return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Multiplies generator (G2) by private key. + // P = pk x G + function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array { + return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Executes `hashToCurve` on the message and then multiplies the result by private key. + // S = pk x H(m) + function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2 + function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 { + const msgPoint = normP2Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G2.ProjectivePoint) return sigPoint + return Signature.toRawBytes(sigPoint) + } + + function signShortSignature(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1 + function signShortSignature( + message: G1Hex, + privateKey: PrivKey, + htfOpts?: htfBasicOpts, + ): Uint8Array | G1 { + const msgPoint = normP1Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G1.ProjectivePoint) return sigPoint + return ShortSignature.toRawBytes(sigPoint) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(P, H(m)) == e(G, S) + function verify( + signature: G2Hex, + message: G2Hex, + publicKey: G1Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP1(publicKey) + const Hm = normP2Hash(message, htfOpts) + const G = G1.ProjectivePoint.BASE + const S = normP2(signature) + const exp = pairingBatch([ + { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); + { g1: G, g2: S }, // eGS = pairing(G, S, false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(S, G) == e(H(m), P) + function verifyShortSignature( + signature: G1Hex, + message: G1Hex, + publicKey: G2Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP2(publicKey) + const Hm = normP1Hash(message, htfOpts) + const G = G2.ProjectivePoint.BASE + const S = normP1(signature) + const exp = pairingBatch([ + { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); + { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + function aNonEmpty(arr: any[]) { + if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') + } + + // Adds a bunch of public key points together. + // pk1 + pk2 + pk3 = pkA + function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array + function aggregatePublicKeys(publicKeys: G1[]): G1 + function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 { + aNonEmpty(publicKeys) + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (publicKeys[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + // toRawBytes ensures point validity + return aggAffine.toRawBytes(true) + } + + // Adds a bunch of signature points together. + function aggregateSignatures(signatures: Hex[]): Uint8Array + function aggregateSignatures(signatures: G2[]): G2 + function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 { + aNonEmpty(signatures) + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G2.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return Signature.toRawBytes(aggAffine) + } + + // Adds a bunch of signature points together. + function aggregateShortSignatures(signatures: Hex[]): Uint8Array + function aggregateShortSignatures(signatures: G1[]): G1 + function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 { + aNonEmpty(signatures) + const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return ShortSignature.toRawBytes(aggAffine) + } + + // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 + // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) + function verifyBatch( + signature: G2Hex, + // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? + messages: G2Hex[], + publicKeys: G1Hex[], + htfOpts?: htfBasicOpts, + ): boolean { + aNonEmpty(messages) + if (publicKeys.length !== messages.length) + throw new Error('amount of public keys and messages should be equal') + const sig = normP2(signature) + const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) + const nPublicKeys = publicKeys.map(normP1) + // NOTE: this works only for exact same object + const messagePubKeyMap = new Map() + for (let i = 0; i < nPublicKeys.length; i++) { + const pub = nPublicKeys[i] + const msg = nMessages[i] + let keys = messagePubKeyMap.get(msg) + if (keys === undefined) { + keys = [] + messagePubKeyMap.set(msg, keys) + } + keys.push(pub) + } + const paired = [] + try { + for (const [msg, keys] of messagePubKeyMap) { + const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) + paired.push({ g1: groupPublicKey, g2: msg }) + } + paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) + return Fp12.eql(pairingBatch(paired), Fp12.ONE) + } catch { + return false + } + } + + G1.ProjectivePoint.BASE._setWindowSize(4) + + return { + getPublicKey, + getPublicKeyForShortSignatures, + sign, + signShortSignature, + verify, + verifyBatch, + verifyShortSignature, + aggregatePublicKeys, + aggregateSignatures, + aggregateShortSignatures, + millerLoopBatch, + pairing, + pairingBatch, + G1, + G2, + Signature, + ShortSignature, + fields: { + Fr, + Fp, + Fp2, + Fp6, + Fp12, + }, + params: { + ateLoopSize: CURVE.params.ateLoopSize, + r: CURVE.params.r, + G1b: CURVE.G1.b, + G2b: CURVE.G2.b, + }, + utils, + } +} diff --git a/packages/noble-curves/src/abstract/curve.ts b/packages/noble-curves/src/abstract/curve.ts new file mode 100644 index 00000000000..de1f49eaf6e --- /dev/null +++ b/packages/noble-curves/src/abstract/curve.ts @@ -0,0 +1,457 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField, nLength, validateField } from './modular.js' +import { bitLen, validateObject } from './utils.js' + +const _0n = BigInt(0) +const _1n = BigInt(1) + +export type AffinePoint = { + x: T + y: T +} & { z?: never; t?: never } + +export interface Group> { + double(): T + negate(): T + add(other: T): T + subtract(other: T): T + equals(other: T): boolean + multiply(scalar: bigint): T +} + +export type GroupConstructor = { + BASE: T + ZERO: T +} +export type Mapper = (i: T[]) => T[] + +function constTimeNegate>(condition: boolean, item: T): T { + const neg = item.negate() + return condition ? neg : item +} + +function validateW(W: number, bits: number) { + if (!Number.isSafeInteger(W) || W <= 0 || W > bits) + throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) +} + +function calcWOpts(W: number, bits: number) { + validateW(W, bits) + const windows = Math.ceil(bits / W) + 1 // +1, because + const windowSize = 2 ** (W - 1) // -1 because we skip zero + return { windows, windowSize } +} + +function validateMSMPoints(points: any[], c: any) { + if (!Array.isArray(points)) throw new Error('array expected') + points.forEach((p, i) => { + if (!(p instanceof c)) throw new Error('invalid point at index ' + i) + }) +} +function validateMSMScalars(scalars: any[], field: any) { + if (!Array.isArray(scalars)) throw new Error('array of scalars expected') + scalars.forEach((s, i) => { + if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) + }) +} + +// Since points in different groups cannot be equal (different object constructor), +// we can have single place to store precomputes +const pointPrecomputes = new WeakMap() +const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) + +function getW(P: any): number { + return pointWindowSizes.get(P) || 1 +} + +export type IWNAF> = { + constTimeNegate: >(condition: boolean, item: T) => T + hasPrecomputes(elm: T): boolean + unsafeLadder(elm: T, n: bigint, p?: T): T + precomputeWindow(elm: T, W: number): Group[] + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T + getPrecomputes(W: number, P: T, transform: Mapper): T[] + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T + setWindowSize(P: T, W: number): void +} + +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export function wNAF>(c: GroupConstructor, bits: number): IWNAF { + return { + constTimeNegate, + + hasPrecomputes(elm: T) { + return getW(elm) !== 1 + }, + + // non-const time multiplication ladder + unsafeLadder(elm: T, n: bigint, p = c.ZERO) { + let d: T = elm + while (n > _0n) { + if (n & _1n) p = p.add(d) + d = d.double() + n >>= _1n + } + return p + }, + + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param elm Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(elm: T, W: number): Group[] { + const { windows, windowSize } = calcWOpts(W, bits) + const points: T[] = [] + let p: T = elm + let base = p + for (let window = 0; window < windows; window++) { + base = p + points.push(base) + // =1, because we skip zero + for (let i = 1; i < windowSize; i++) { + base = base.add(p) + points.push(base) + } + p = base.double() + } + return points + }, + + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @returns real and fake (for const-time) points + */ + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } { + // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise + // But need to carefully remove other checks before wNAF. ORDER == bits here + const { windows, windowSize } = calcWOpts(W, bits) + + let p = c.ZERO + let f = c.BASE + + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + // Extract W bits. + let wbits = Number(n & mask) + + // Shift number by W bits. + n >>= shiftBy + + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + + // This code was first written with assumption that 'f' and 'p' will never be infinity point: + // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, + // there is negate now: it is possible that negated element from low value + // would be the same as high element, which will create carry into next window. + // It's not obvious how this can fail, but still worth investigating later. + + // Check if we're onto Zero point. + // Add random point inside current window to f. + const offset1 = offset + const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero + const cond1 = window % 2 !== 0 + const cond2 = wbits < 0 + if (wbits === 0) { + // The most important part for const-time getPublicKey + f = f.add(constTimeNegate(cond1, precomputes[offset1])) + } else { + p = p.add(constTimeNegate(cond2, precomputes[offset2])) + } + } + // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() + // Even if the variable is still unused, there are some checks which will + // throw an exception, so compiler needs to prove they won't happen, which is hard. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. + return { p, f } + }, + + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc: T = c.ZERO): T { + const { windows, windowSize } = calcWOpts(W, bits) + const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. + const maxNumber = 2 ** W + const shiftBy = BigInt(W) + for (let window = 0; window < windows; window++) { + const offset = window * windowSize + if (n === _0n) break // No need to go over empty scalar + // Extract W bits. + let wbits = Number(n & mask) + // Shift number by W bits. + n >>= shiftBy + // If the bits are bigger than max size, we'll split those. + // +224 => 256 - 32 + if (wbits > windowSize) { + wbits -= maxNumber + n += _1n + } + if (wbits === 0) continue + let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero + if (wbits < 0) curr = curr.negate() + // NOTE: by re-using acc, we can save a lot of additions in case of MSM + acc = acc.add(curr) + } + return acc + }, + + getPrecomputes(W: number, P: T, transform: Mapper): T[] { + // Calculate precomputes on a first run, reuse them after + let comp = pointPrecomputes.get(P) + if (!comp) { + comp = this.precomputeWindow(P, W) as T[] + if (W !== 1) pointPrecomputes.set(P, transform(comp)) + } + return comp + }, + + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } { + const W = getW(P) + return this.wNAF(W, this.getPrecomputes(W, P, transform), n) + }, + + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T { + const W = getW(P) + if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster + return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) + }, + + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + + setWindowSize(P: T, W: number) { + validateW(W, bits) + pointWindowSizes.set(P, W) + pointPrecomputes.delete(P) + }, + } +} + +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster with precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export function pippenger>( + c: GroupConstructor, + fieldN: IField, + points: T[], + scalars: bigint[], +): T { + // If we split scalars by some window (let's say 8 bits), every chunk will only + // take 256 buckets even if there are 4096 scalars, also re-uses double. + // TODO: + // - https://eprint.iacr.org/2024/750.pdf + // - https://tches.iacr.org/index.php/TCHES/article/view/10287 + // 0 is accepted in scalars + validateMSMPoints(points, c) + validateMSMScalars(scalars, fieldN) + if (points.length !== scalars.length) + throw new Error('arrays of points and scalars must have equal length') + const zero = c.ZERO + const wbits = bitLen(BigInt(points.length)) + const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits + const MASK = (1 << windowSize) - 1 + const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array + const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize + let sum = zero + for (let i = lastBits; i >= 0; i -= windowSize) { + buckets.fill(zero) + for (let j = 0; j < scalars.length; j++) { + const scalar = scalars[j] + const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) + buckets[wbits] = buckets[wbits].add(points[j]) + } + let resI = zero // not using this will do small speed-up, but will lose ct + // Skip first bucket, because it is zero + for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { + sumI = sumI.add(buckets[j]) + resI = resI.add(sumI) + } + sum = sum.add(resI) + if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() + } + return sum as T +} +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export function precomputeMSMUnsafe>( + c: GroupConstructor, + fieldN: IField, + points: T[], + windowSize: number, +): (scalars: bigint[]) => T { + /** + * Performance Analysis of Window-based Precomputation + * + * Base Case (256-bit scalar, 8-bit window): + * - Standard precomputation requires: + * - 31 additions per scalar × 256 scalars = 7,936 ops + * - Plus 255 summary additions = 8,191 total ops + * Note: Summary additions can be optimized via accumulator + * + * Chunked Precomputation Analysis: + * - Using 32 chunks requires: + * - 255 additions per chunk + * - 256 doublings + * - Total: (255 × 32) + 256 = 8,416 ops + * + * Memory Usage Comparison: + * Window Size | Standard Points | Chunked Points + * ------------|-----------------|--------------- + * 4-bit | 520 | 15 + * 8-bit | 4,224 | 255 + * 10-bit | 13,824 | 1,023 + * 16-bit | 557,056 | 65,535 + * + * Key Advantages: + * 1. Enables larger window sizes due to reduced memory overhead + * 2. More efficient for smaller scalar counts: + * - 16 chunks: (16 × 255) + 256 = 4,336 ops + * - ~2x faster than standard 8,191 ops + * + * Limitations: + * - Not suitable for plain precomputes (requires 256 constant doublings) + * - Performance degrades with larger scalar counts: + * - Optimal for ~256 scalars + * - Less efficient for 4096+ scalars (Pippenger preferred) + */ + validateW(windowSize, fieldN.BITS) + validateMSMPoints(points, c) + const zero = c.ZERO + const tableSize = 2 ** windowSize - 1 // table size (without zero) + const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item + const MASK = BigInt((1 << windowSize) - 1) + const tables = points.map((p: T) => { + const res = [] + for (let i = 0, acc = p; i < tableSize; i++) { + res.push(acc) + acc = acc.add(p) + } + return res + }) + return (scalars: bigint[]): T => { + validateMSMScalars(scalars, fieldN) + if (scalars.length > points.length) + throw new Error('array of scalars must be smaller than array of points') + let res = zero + for (let i = 0; i < chunks; i++) { + // No need to double if accumulator is still zero. + if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() + const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) + for (let j = 0; j < scalars.length; j++) { + const n = scalars[j] + const curr = Number((n >> shiftBy) & MASK) + if (!curr) continue // skip zero scalars chunks + res = res.add(tables[j][curr - 1]) + } + } + return res + } +} + +/** + * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. + * Though generator can be different (Fp2 / Fp6 for BLS). + */ +export type BasicCurve = { + Fp: IField // Field over which we'll do calculations (Fp) + n: bigint // Curve order, total count of valid points in the field + nBitLength?: number // bit length of curve order + nByteLength?: number // byte length of curve order + h: bigint // cofactor. we can assign default=1, but users will just ignore it w/o validation + hEff?: bigint // Number to multiply to clear cofactor + Gx: T // base point X coordinate + Gy: T // base point Y coordinate + allowInfinityPoint?: boolean // bls12-381 requires it. ZERO point is valid, but invalid pubkey +} + +export function validateBasic( + curve: BasicCurve & T, +): Readonly< + { + readonly nBitLength: number + readonly nByteLength: number + } & BasicCurve & + T & { + p: bigint + } +> { + validateField(curve.Fp) + validateObject( + curve, + { + n: 'bigint', + h: 'bigint', + Gx: 'field', + Gy: 'field', + }, + { + nBitLength: 'isSafeInteger', + nByteLength: 'isSafeInteger', + }, + ) + // Set defaults + return Object.freeze({ + ...nLength(curve.n, curve.nBitLength), + ...curve, + ...{ p: curve.Fp.ORDER }, + } as const) +} diff --git a/packages/noble-curves/src/abstract/edwards.ts b/packages/noble-curves/src/abstract/edwards.ts new file mode 100644 index 00000000000..4f0b7d0dceb --- /dev/null +++ b/packages/noble-curves/src/abstract/edwards.ts @@ -0,0 +1,565 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.js' +import { Field, mod } from './modular.js' +import * as ut from './utils.js' +import { type FHash, type Hex, abool, ensureBytes, memoized } from './utils.js' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _8n = BigInt(8) + +/** Edwards curves must declare params a & d. */ +export type CurveType = BasicCurve & { + a: bigint // curve param a + d: bigint // curve param d + hash: FHash // Hashing + randomBytes: (bytesLength?: number) => Uint8Array // CSPRNG + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array // clears bits to get valid field elemtn + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array // Used for hashing + uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint } // Ratio √(u/v) + prehash?: FHash // RFC 8032 pre-hashing of messages to sign() / verify() + mapToCurve?: (scalar: bigint[]) => AffinePoint // for hash-to-curve standard +} + +export type CurveTypeWithLength = Readonly + +// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: +const VERIFY_DEFAULT = { zip215: true } + +function validateOpts(curve: CurveType): CurveTypeWithLength { + const opts = validateBasic(curve) + ut.validateObject( + curve, + { + hash: 'function', + a: 'bigint', + d: 'bigint', + randomBytes: 'function', + }, + { + adjustScalarBytes: 'function', + domain: 'function', + uvRatio: 'function', + mapToCurve: 'function', + }, + ) + // Set defaults + return Object.freeze({ ...opts } as const) +} + +/** Instance of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointType extends Group { + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + get x(): bigint + get y(): bigint + assertValidity(): void + multiply(scalar: bigint): ExtPointType + multiplyUnsafe(scalar: bigint): ExtPointType + isSmallOrder(): boolean + isTorsionFree(): boolean + clearCofactor(): ExtPointType + toAffine(iz?: bigint): AffinePoint + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + _setWindowSize(windowSize: number): void +} +/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType + fromAffine(p: AffinePoint): ExtPointType + fromHex(hex: Hex): ExtPointType + fromPrivateKey(privateKey: Hex): ExtPointType + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType +} + +/** + * Edwards Curve interface. + * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. + */ +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: Hex) => Uint8Array + sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { context?: Hex; zip215: boolean }, + ) => boolean + ExtendedPoint: ExtPointConstructor + utils: { + randomPrivateKey: () => Uint8Array + getExtendedPublicKey: (key: Hex) => { + head: Uint8Array + prefix: Uint8Array + scalar: bigint + point: ExtPointType + pointBytes: Uint8Array + } + precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType + } +} + +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export function twistedEdwards(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { + Fp, + n: CURVE_ORDER, + prehash: prehash, + hash: cHash, + randomBytes, + nByteLength, + h: cofactor, + } = CURVE + // Important: + // There are some places where Fp.BYTES is used instead of nByteLength. + // So far, everything has been tested with curves of Fp.BYTES == nByteLength. + // TODO: test and find curves which behave otherwise. + const MASK = _2n << (BigInt(nByteLength * 8) - _1n) + const modP = Fp.create // Function overrides + const Fn = Field(CURVE.n, CURVE.nBitLength) + + // sqrt(u/v) + const uvRatio = + CURVE.uvRatio || + ((u: bigint, v: bigint) => { + try { + return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } + } catch (e) { + return { isValid: false, value: _0n } + } + }) + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) // NOOP + const domain = + CURVE.domain || + ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + abool('phflag', phflag) + if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') + return data + }) // NOOP + // 0 <= n < MASK + // Coordinates larger than Fp.ORDER are allowed for zip215 + function aCoordinate(title: string, n: bigint) { + ut.aInRange('coordinate ' + title, n, _0n, MASK) + } + + function assertPoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint => { + const { ex: x, ey: y, ez: z } = p + const is0 = p.is0() + if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint) // 8 was chosen arbitrarily + const ax = modP(x * iz) + const ay = modP(y * iz) + const zz = modP(z * iz) + if (is0) return { x: _0n, y: _1n } + if (zz !== _1n) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + const assertValidMemo = memoized((p: Point) => { + const { a, d } = CURVE + if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? + // Equation in affine coordinates: ax² + y² = 1 + dx²y² + // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² + const { ex: X, ey: Y, ez: Z, et: T } = p + const X2 = modP(X * X) // X² + const Y2 = modP(Y * Y) // Y² + const Z2 = modP(Z * Z) // Z² + const Z4 = modP(Z2 * Z2) // Z⁴ + const aX2 = modP(X2 * a) // aX² + const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² + const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² + if (left !== right) throw new Error('bad point: equation left != right (1)') + // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T + const XY = modP(X * Y) + const ZT = modP(Z * T) + if (XY !== ZT) throw new Error('bad point: equation left != right (2)') + return true + }) + + // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). + // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates + class Point implements ExtPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) + static readonly ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 + + constructor( + readonly ex: bigint, + readonly ey: bigint, + readonly ez: bigint, + readonly et: bigint, + ) { + aCoordinate('x', ex) + aCoordinate('y', ey) + aCoordinate('z', ez) + aCoordinate('t', et) + Object.freeze(this) + } + + get x(): bigint { + return this.toAffine().x + } + get y(): bigint { + return this.toAffine().y + } + + static fromAffine(p: AffinePoint): Point { + if (p instanceof Point) throw new Error('extended point not allowed') + const { x, y } = p || {} + aCoordinate('x', x) + aCoordinate('y', y) + return new Point(x, y, _1n, modP(x * y)) + } + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.ez)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + // Not required for fromHex(), which always creates valid points. + // Could be useful for fromAffine(). + assertValidity(): void { + assertValidMemo(this) + } + + // Compare one point to another. + equals(other: Point): boolean { + assertPoint(other) + const { ex: X1, ey: Y1, ez: Z1 } = this + const { ex: X2, ey: Y2, ez: Z2 } = other + const X1Z2 = modP(X1 * Z2) + const X2Z1 = modP(X2 * Z1) + const Y1Z2 = modP(Y1 * Z2) + const Y2Z1 = modP(Y2 * Z1) + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 + } + + is0(): boolean { + return this.equals(Point.ZERO) + } + + negate(): Point { + // Flips point sign to a negative one (-x, y in affine coords) + return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) + } + + // Fast algo for doubling Extended Point. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd + // Cost: 4M + 4S + 1*a + 6add + 1*2. + double(): Point { + const { a } = CURVE + const { ex: X1, ey: Y1, ez: Z1 } = this + const A = modP(X1 * X1) // A = X12 + const B = modP(Y1 * Y1) // B = Y12 + const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 + const D = modP(a * A) // D = a*A + const x1y1 = X1 + Y1 + const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B + const G = D + B // G = D+B + const F = G - C // F = G-C + const H = D - B // H = D-B + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + + // Fast algo for adding 2 Extended Points. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd + // Cost: 9M + 1*a + 1*d + 7add. + add(other: Point) { + assertPoint(other) + const { a, d } = CURVE + const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this + const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other + // Faster algo for adding 2 Extended Points when curve's a=-1. + // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 + // Cost: 8M + 8add + 2*2. + // Note: It does not check whether the `other` point is valid. + if (a === BigInt(-1)) { + const A = modP((Y1 - X1) * (Y2 + X2)) + const B = modP((Y1 + X1) * (Y2 - X2)) + const F = modP(B - A) + if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing + const C = modP(Z1 * _2n * T2) + const D = modP(T1 * _2n * Z2) + const E = D + C + const G = B + A + const H = D - C + const X3 = modP(E * F) + const Y3 = modP(G * H) + const T3 = modP(E * H) + const Z3 = modP(F * G) + return new Point(X3, Y3, Z3, T3) + } + const A = modP(X1 * X2) // A = X1*X2 + const B = modP(Y1 * Y2) // B = Y1*Y2 + const C = modP(T1 * d * T2) // C = T1*d*T2 + const D = modP(Z1 * Z2) // D = Z1*Z2 + const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B + const F = D - C // F = D-C + const G = D + C // G = D+C + const H = modP(B - a * A) // H = B-a*A + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + + return new Point(X3, Y3, Z3, T3) + } + + subtract(other: Point): Point { + return this.add(other.negate()) + } + + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + // Constant-time multiplication. + multiply(scalar: bigint): Point { + const n = scalar + ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L + const { p, f } = this.wNAF(n) + return Point.normalizeZ([p, f])[0] + } + + // Non-constant-time multiplication. Uses double-and-add algorithm. + // It's faster, but should only be used when you don't care about + // an exposed private key e.g. sig verification. + // Does NOT allow scalars higher than CURVE.n. + // Accepts optional accumulator to merge with multiply (important for sparse scalars) + multiplyUnsafe(scalar: bigint, acc = Point.ZERO): Point { + const n = scalar + ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L + if (n === _0n) return I + if (this.is0() || n === _1n) return this + return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) + } + + // Checks if point is of small order. + // If you add something to small order point, you will have "dirty" + // point with torsion component. + // Multiplies point by cofactor and checks if the result is 0. + isSmallOrder(): boolean { + return this.multiplyUnsafe(cofactor).is0() + } + + // Multiplies point by curve order and checks if the result is 0. + // Returns `false` is the point is dirty. + isTorsionFree(): boolean { + return wnaf.unsafeLadder(this, CURVE_ORDER).is0() + } + + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + toAffine(iz?: bigint): AffinePoint { + return toAffineMemo(this, iz) + } + + clearCofactor(): Point { + const { h: cofactor } = CURVE + if (cofactor === _1n) return this + return this.multiplyUnsafe(cofactor) + } + + // Converts hash string or Uint8Array to Point. + // Uses algo from RFC8032 5.1.3. + static fromHex(hex: Hex, zip215 = false): Point { + const { d, a } = CURVE + const len = Fp.BYTES + hex = ensureBytes('pointHex', hex, len) // copy hex to a new array + abool('zip215', zip215) + const normed = hex.slice() // copy again, we'll manipulate it + const lastByte = hex[len - 1] // select last byte + normed[len - 1] = lastByte & ~0x80 // clear last bit + const y = ut.bytesToNumberLE(normed) + + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // RFC8032 prohibits >= p, but ZIP215 doesn't + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + const max = zip215 ? MASK : Fp.ORDER + ut.aInRange('pointHex.y', y, _0n, max) + + // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: + // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) + const y2 = modP(y * y) // denominator is always non-0 mod p. + const u = modP(y2 - _1n) // u = y² - 1 + const v = modP(d * y2 - a) // v = d y² + 1. + let { isValid, value: x } = uvRatio(u, v) // √(u/v) + if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') + const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper + const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1') + if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x + return Point.fromAffine({ x, y }) + } + static fromPrivateKey(privKey: Hex) { + return getExtendedPublicKey(privKey).point + } + toRawBytes(): Uint8Array { + const { x, y } = this.toAffine() + const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) + bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y + return bytes // and use the last byte to encode sign of x + } + toHex(): string { + return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. + } + } + const { BASE: G, ZERO: I } = Point + const wnaf = wNAF(Point, nByteLength * 8) + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + // Little-endian SHA512 with modulo n + function modN_LE(hash: Uint8Array): bigint { + return modN(ut.bytesToNumberLE(hash)) + } + + /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ + function getExtendedPublicKey(key: Hex) { + const len = Fp.BYTES + key = ensureBytes('private key', key, len) + // Hash private key with curve's hash function to produce uniformingly random input + // Check byte lengths: ensure(64, h(ensure(32, key))) + const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) + const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE + const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) + const scalar = modN_LE(head) // The actual private scalar + const point = G.multiply(scalar) // Point on Edwards curve aka public key + const pointBytes = point.toRawBytes() // Uint8Array representation + return { head, prefix, scalar, point, pointBytes } + } + + // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared + function getPublicKey(privKey: Hex): Uint8Array { + return getExtendedPublicKey(privKey).pointBytes + } + + // int('LE', SHA512(dom2(F, C) || msgs)) mod N + function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) { + const msg = ut.concatBytes(...msgs) + return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) + } + + /** Signs message with privateKey. RFC8032 5.1.6 */ + function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array { + msg = ensureBytes('message', msg) + if (prehash) msg = prehash(msg) // for ed25519ph etc. + const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) + const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) + const R = G.multiply(r).toRawBytes() // R = rG + const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) + const s = modN(r + k * scalar) // S = (r + k * s) mod L + ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l + const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) + return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature + } + + const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT + + /** + * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + * An extended group equation is checked. + */ + function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean { + const { context, zip215 } = options + const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. + msg = ensureBytes('message', msg) + publicKey = ensureBytes('publicKey', publicKey, len) + if (zip215 !== undefined) abool('zip215', zip215) + if (prehash) msg = prehash(msg) // for ed25519ph, etc + + const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) + let A, R, SB + try { + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + A = Point.fromHex(publicKey, zip215) + R = Point.fromHex(sig.slice(0, len), zip215) + SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside + } catch (error) { + return false + } + if (!zip215 && A.isSmallOrder()) return false + + const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) + const RkA = R.add(A.multiplyUnsafe(k)) + // Extended group equation + // [8][S]B = [8]R + [8][k]A' + return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) + } + + G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. + + const utils = { + getExtendedPublicKey, + // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. + randomPrivateKey: (): Uint8Array => randomBytes(Fp.BYTES), + + /** + * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT + * values. This slows down first getPublicKey() by milliseconds (see Speed section), + * but allows to speed-up subsequent getPublicKey() calls up to 20x. + * @param windowSize 2, 4, 8, 16 + */ + precompute(windowSize = 8, point: ExtPointType = Point.BASE): ExtPointType { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) + return point + }, + } + + return { + CURVE, + getPublicKey, + sign, + verify, + ExtendedPoint: Point, + utils, + } +} diff --git a/packages/noble-curves/src/abstract/hash-to-curve.ts b/packages/noble-curves/src/abstract/hash-to-curve.ts new file mode 100644 index 00000000000..1ecedd0bf19 --- /dev/null +++ b/packages/noble-curves/src/abstract/hash-to-curve.ts @@ -0,0 +1,255 @@ +/** + * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import type { AffinePoint, Group, GroupConstructor } from './curve.js' +import { type IField, mod } from './modular.js' +import type { CHash } from './utils.js' +import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.js' + +export type UnicodeOrBytes = string | Uint8Array + +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +export type Opts = { + DST: UnicodeOrBytes + p: bigint + m: number + k: number + expand: 'xmd' | 'xof' + hash: CHash +} + +// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. +const os2ip = bytesToNumberBE + +// Integer to Octet Stream (numberToBytesBE) +function i2osp(value: number, length: number): Uint8Array { + anum(value) + anum(length) + if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) + const res = Array.from({ length }).fill(0) as number[] + for (let i = length - 1; i >= 0; i--) { + res[i] = value & 0xff + value >>>= 8 + } + return new Uint8Array(res) +} + +function strxor(a: Uint8Array, b: Uint8Array): Uint8Array { + const arr = new Uint8Array(a.length) + for (let i = 0; i < a.length; i++) { + arr[i] = a[i] ^ b[i] + } + return arr +} + +function anum(item: unknown): void { + if (!Number.isSafeInteger(item)) throw new Error('number expected') +} + +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) + const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H + const ell = Math.ceil(lenInBytes / b_in_bytes) + if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') + 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) // len_in_bytes_str + const b = new Array(ell) + const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) + b[0] = 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] = H(concatBytes(...args)) + } + const pseudo_random_bytes = concatBytes(...b) + return pseudo_random_bytes.slice(0, lenInBytes) +} + +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); + if (DST.length > 255) { + const dkLen = Math.ceil((2 * k) / 8) + DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() + } + if (lenInBytes > 65535 || DST.length > 255) + throw new Error('expand_message_xof: invalid lenInBytes') + return ( + H.create({ dkLen: lenInBytes }) + .update(msg) + .update(i2osp(lenInBytes, 2)) + // 2. DST_prime = DST || I2OSP(len(DST), 1) + .update(DST) + .update(i2osp(DST.length, 1)) + .digest() + ) +} + +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] { + validateObject(options, { + DST: 'stringOrUint8Array', + p: 'bigint', + m: 'isSafeInteger', + k: 'isSafeInteger', + hash: 'hash', + }) + const { p, k, m, hash, expand, DST: _DST } = options + abytes(msg) + anum(count) + const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST + const log2p = p.toString(2).length + const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above + const len_in_bytes = count * m * L + let prb // pseudo_random_bytes + if (expand === 'xmd') { + prb = expand_message_xmd(msg, DST, len_in_bytes, hash) + } else if (expand === 'xof') { + prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) + } else if (expand === '_internal_pass') { + // for internal tests only + prb = msg + } else { + throw new Error('expand must be "xmd" or "xof"') + } + const u = new Array(count) + for (let i = 0; i < count; i++) { + const e = new Array(m) + for (let j = 0; j < m; j++) { + const elm_offset = L * (j + i * m) + const tv = prb.subarray(elm_offset, elm_offset + L) + e[j] = mod(os2ip(tv), p) + } + u[i] = e + } + return u +} + +export type XY = ( + x: T, + y: T, +) => { + x: T + y: T +} +export function isogenyMap>(field: F, map: [T[], T[], T[], T[]]): XY { + // Make same order as in spec + const COEFF = map.map((i) => Array.from(i).reverse()) + return (x: T, y: T) => { + const [xNum, xDen, yNum, yDen] = COEFF.map((val) => + val.reduce((acc, i) => field.add(field.mul(acc, x), i)), + ) + x = field.div(xNum, xDen) // xNum / xDen + y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) + return { x: x, y: y } + } +} + +/** Point interface, which curves must implement to work correctly with the module. */ +export interface H2CPoint extends Group> { + add(rhs: H2CPoint): H2CPoint + toAffine(iz?: bigint): AffinePoint + clearCofactor(): H2CPoint + assertValidity(): void +} + +export interface H2CPointConstructor extends GroupConstructor> { + fromAffine(ap: AffinePoint): H2CPoint +} + +export type MapToCurve = (scalar: bigint[]) => AffinePoint + +// Separated from initialization opts, so users won't accidentally change per-curve parameters +// (changing DST is ok!) +export type htfBasicOpts = { DST: UnicodeOrBytes } +export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint +export type MapMethod = (scalars: bigint[]) => H2CPoint + +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export function createHasher( + Point: H2CPointConstructor, + mapToCurve: MapToCurve, + def: Opts & { encodeDST?: UnicodeOrBytes }, +): { + hashToCurve: HTFMethod + encodeToCurve: HTFMethod + mapToCurve: MapMethod +} { + if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') + return { + // Encodes byte string to elliptic curve. + // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + hashToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts) + const u0 = Point.fromAffine(mapToCurve(u[0])) + const u1 = Point.fromAffine(mapToCurve(u[1])) + const P = u0.add(u1).clearCofactor() + P.assertValidity() + return P + }, + + // Encodes byte string to elliptic curve. + // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts) + const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() + P.assertValidity() + return P + }, + // Same as encodeToCurve, but without hash + mapToCurve(scalars: bigint[]): H2CPoint { + if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') + for (const i of scalars) + if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') + const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() + P.assertValidity() + return P + }, + } +} diff --git a/packages/noble-curves/src/abstract/modular.ts b/packages/noble-curves/src/abstract/modular.ts new file mode 100644 index 00000000000..e36f68478d1 --- /dev/null +++ b/packages/noble-curves/src/abstract/modular.ts @@ -0,0 +1,555 @@ +/** + * Utils for modular division and finite fields. + * A finite field over 11 is integer number operations `mod 11`. + * There is no division: it is replaced by modular multiplicative inverse. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + bitMask, + bytesToNumberBE, + bytesToNumberLE, + ensureBytes, + numberToBytesBE, + numberToBytesLE, + validateObject, +} from './utils.js' + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = /* @__PURE__ */ BigInt(2), + _3n = /* @__PURE__ */ BigInt(3) +// prettier-ignore +const _4n = /* @__PURE__ */ BigInt(4), + _5n = /* @__PURE__ */ BigInt(5), + _8n = /* @__PURE__ */ BigInt(8) +// prettier-ignore +const _9n = /* @__PURE__ */ BigInt(9), + _16n = /* @__PURE__ */ BigInt(16) + +// Calculates a modulo b +export function mod(a: bigint, b: bigint): bigint { + const result = a % b + return result >= _0n ? result : b + result +} +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export function pow(num: bigint, power: bigint, modulo: bigint): bigint { + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (modulo <= _0n) throw new Error('invalid modulus') + 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 +} + +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export function pow2(x: bigint, power: bigint, modulo: bigint): bigint { + let res = x + while (power-- > _0n) { + res *= res + res %= modulo + } + return res +} + +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export function invert(number: bigint, modulo: bigint): bigint { + if (number === _0n) throw new Error('invert: expected non-zero number') + if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) + // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. + let a = mod(number, modulo) + let b = modulo + // prettier-ignore + let x = _0n, + y = _1n, + u = _1n, + v = _0n + while (a !== _0n) { + // JIT applies optimization if those two lines follow each other + const q = b / a + const r = b % a + const m = x - u * q + const n = y - v * q + // prettier-ignore + ;(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) +} + +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export function tonelliShanks(P: bigint): (Fp: IField, n: T) => T { + // Legendre constant: used to calculate Legendre symbol (a | p), + // which denotes the value of a^((p-1)/2) (mod p). + // (a | p) ≡ 1 if a is a square (mod p) + // (a | p) ≡ -1 if a is not a square (mod p) + // (a | p) ≡ 0 if a ≡ 0 (mod p) + const legendreC = (P - _1n) / _2n + + let Q: bigint, S: number, Z: bigint + // Step 1: By factoring out powers of 2 from p - 1, + // find q and s such that p - 1 = q*(2^s) with q odd + for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); + + // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq + for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { + // Crash instead of infinity loop, we cannot reasonable count until P. + if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') + } + + // Fast-path + if (S === 1) { + const p1div4 = (P + _1n) / _4n + return function tonelliFast(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Slow-path + const Q1div2 = (Q + _1n) / _2n + return function tonelliSlow(Fp: IField, n: T): T { + // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 + if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') + let r = S + // TODO: will fail at Fp2/etc + let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b + let x = Fp.pow(n, Q1div2) // first guess at the square root + let b = Fp.pow(n, Q) // first guess at the fudge factor + + while (!Fp.eql(b, Fp.ONE)) { + if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) + // Find m such b^(2^m)==1 + let m = 1 + for (let t2 = Fp.sqr(b); m < r; m++) { + if (Fp.eql(t2, Fp.ONE)) break + t2 = Fp.sqr(t2) // t2 *= t2 + } + // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow + const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) + g = Fp.sqr(ge) // g = ge * ge + x = Fp.mul(x, ge) // x *= ge + b = Fp.mul(b, g) // b *= g + r = m + } + return x + } +} + +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export function FpSqrt(P: bigint): (Fp: IField, n: T) => T { + // P ≡ 3 (mod 4) + // √n = n^((P+1)/4) + if (P % _4n === _3n) { + // Not all roots possible! + // const ORDER = + // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; + // const NUM = 72057594037927816n; + const p1div4 = (P + _1n) / _4n + return function sqrt3mod4(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + // Throw if root**2 != n + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) + if (P % _8n === _5n) { + const c1 = (P - _5n) / _8n + return function sqrt5mod8(Fp: IField, n: T) { + const n2 = Fp.mul(n, _2n) + const v = Fp.pow(n2, c1) + const nv = Fp.mul(n, v) + const i = Fp.mul(Fp.mul(nv, _2n), v) + const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // P ≡ 9 (mod 16) + if (P % _16n === _9n) { + // NOTE: tonelli is too slow for bls-Fp2 calculations even on start + // Means we cannot use sqrt for constants at all! + // + // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F + // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F + // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F + // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic + // sqrt = (x) => { + // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 + // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 + // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 + // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 + // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x + // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x + // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x + // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x + // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x + // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 + // } + } + // Other cases: Tonelli-Shanks algorithm + return tonelliShanks(P) +} + +// Little-endian check for first LE bit (last BE bit); +export const isNegativeLE = (num: bigint, modulo: bigint): boolean => + (mod(num, modulo) & _1n) === _1n + +/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ +export interface IField { + ORDER: bigint + isLE: boolean + BYTES: number + BITS: number + MASK: bigint + ZERO: T + ONE: T + // 1-arg + create: (num: T) => T + isValid: (num: T) => boolean + is0: (num: T) => boolean + neg(num: T): T + inv(num: T): T + sqrt(num: T): T + sqr(num: T): T + // 2-args + eql(lhs: T, rhs: T): boolean + add(lhs: T, rhs: T): T + sub(lhs: T, rhs: T): T + mul(lhs: T, rhs: T | bigint): T + pow(lhs: T, power: bigint): T + div(lhs: T, rhs: T | bigint): T + // N for NonNormalized (for now) + addN(lhs: T, rhs: T): T + subN(lhs: T, rhs: T): T + mulN(lhs: T, rhs: T | bigint): T + sqrN(num: T): T + + // Optional + // Should be same as sgn0 function in + // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1). + // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway. + isOdd?(num: T): boolean // Odd instead of even since we have it for Fp2 + // legendre?(num: T): T; + pow(lhs: T, power: bigint): T + invertBatch: (lst: T[]) => T[] + toBytes(num: T): Uint8Array + fromBytes(bytes: Uint8Array): T + // If c is False, CMOV returns a, otherwise it returns b. + cmov(a: T, b: T, c: boolean): T +} +// prettier-ignore +const FIELD_FIELDS = [ + 'create', + 'isValid', + 'is0', + 'neg', + 'inv', + 'sqrt', + 'sqr', + 'eql', + 'add', + 'sub', + 'mul', + 'pow', + 'div', + 'addN', + 'subN', + 'mulN', + 'sqrN', +] as const +export function validateField(field: IField): IField { + const initial = { + ORDER: 'bigint', + MASK: 'bigint', + BYTES: 'isSafeInteger', + BITS: 'isSafeInteger', + } as Record + const opts = FIELD_FIELDS.reduce((map, val: string) => { + map[val] = 'function' + return map + }, initial) + return validateObject(field, opts) +} + +// Generic field functions + +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export function FpPow(f: IField, num: T, power: bigint): T { + // Should have same speed as pow for bigints + // TODO: benchmark! + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (power === _0n) return f.ONE + if (power === _1n) return num + let p = f.ONE + let d = num + while (power > _0n) { + if (power & _1n) p = f.mul(p, d) + d = f.sqr(d) + power >>= _1n + } + return p +} + +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export function FpInvertBatch(f: IField, nums: T[]): T[] { + const tmp = new Array(nums.length) + // Walk from first to last, multiply them by each other MOD p + const lastMultiplied = nums.reduce((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = acc + return f.mul(acc, num) + }, f.ONE) + // Invert last element + const inverted = f.inv(lastMultiplied) + // Walk from last to first, multiply them by inverted each other MOD p + nums.reduceRight((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = f.mul(acc, tmp[i]) + return f.mul(acc, num) + }, inverted) + return tmp +} + +export function FpDiv(f: IField, lhs: T, rhs: T | bigint): T { + return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) +} + +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export function FpLegendre(order: bigint): (f: IField, x: T) => T { + const legendreConst = (order - _1n) / _2n // Integer arithmetic + return (f: IField, x: T): T => f.pow(x, legendreConst) +} + +// This function returns True whenever the value x is a square in the field F. +export function FpIsSquare(f: IField): (x: T) => boolean { + const legendre = FpLegendre(f.ORDER) + return (x: T): boolean => { + const p = legendre(f, x) + return f.eql(p, f.ZERO) || f.eql(p, f.ONE) + } +} + +// CURVE.n lengths +export function nLength( + n: bigint, + nBitLength?: number, +): { + nBitLength: number + nByteLength: number +} { + // Bit size, byte size of CURVE.n + const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length + const nByteLength = Math.ceil(_nBitLength / 8) + return { nBitLength: _nBitLength, nByteLength } +} + +type FpField = IField & Required, 'isOdd'>> +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export function Field( + ORDER: bigint, + bitLen?: number, + isLE = false, + redef: Partial> = {}, +): Readonly { + if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) + const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) + if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') + let sqrtP: ReturnType // cached sqrtP + const f: Readonly = Object.freeze({ + ORDER, + isLE, + BITS, + BYTES, + MASK: bitMask(BITS), + ZERO: _0n, + ONE: _1n, + create: (num) => mod(num, ORDER), + isValid: (num) => { + if (typeof num !== 'bigint') + throw new Error('invalid field element: expected bigint, got ' + typeof num) + return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible + }, + is0: (num) => num === _0n, + isOdd: (num) => (num & _1n) === _1n, + neg: (num) => mod(-num, ORDER), + eql: (lhs, rhs) => lhs === rhs, + + sqr: (num) => mod(num * num, ORDER), + add: (lhs, rhs) => mod(lhs + rhs, ORDER), + sub: (lhs, rhs) => mod(lhs - rhs, ORDER), + mul: (lhs, rhs) => mod(lhs * rhs, ORDER), + pow: (num, power) => FpPow(f, num, power), + div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + + // Same as above, but doesn't normalize + sqrN: (num) => num * num, + addN: (lhs, rhs) => lhs + rhs, + subN: (lhs, rhs) => lhs - rhs, + mulN: (lhs, rhs) => lhs * rhs, + + inv: (num) => invert(num, ORDER), + sqrt: + redef.sqrt || + ((n) => { + if (!sqrtP) sqrtP = FpSqrt(ORDER) + return sqrtP(f, n) + }), + invertBatch: (lst) => FpInvertBatch(f, lst), + // TODO: do we really need constant cmov? + // We don't have const-time bigints anyway, so probably will be not very useful + cmov: (a, b, c) => (c ? b : a), + toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), + fromBytes: (bytes) => { + if (bytes.length !== BYTES) + throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) + return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) + }, + } as FpField) + return Object.freeze(f) +} + +export function FpSqrtOdd(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? root : Fp.neg(root) +} + +export function FpSqrtEven(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? Fp.neg(root) : root +} + +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export function hashToPrivateScalar( + hash: string | Uint8Array, + groupOrder: bigint, + isLE = false, +): bigint { + hash = ensureBytes('privateHash', hash) + const hashLen = hash.length + const minLen = nLength(groupOrder).nByteLength + 8 + if (minLen < 24 || hashLen < minLen || hashLen > 1024) + throw new Error( + 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, + ) + const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) + return mod(num, groupOrder - _1n) + _1n +} + +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export function getFieldBytesLength(fieldOrder: bigint): number { + if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') + const bitLength = fieldOrder.toString(2).length + return Math.ceil(bitLength / 8) +} + +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export function getMinHashLength(fieldOrder: bigint): number { + const length = getFieldBytesLength(fieldOrder) + return length + Math.ceil(length / 2) +} + +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array { + const len = key.length + const fieldLen = getFieldBytesLength(fieldOrder) + const minLen = getMinHashLength(fieldOrder) + // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. + if (len < 16 || len < minLen || len > 1024) + throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) + const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) + // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 + const reduced = mod(num, fieldOrder - _1n) + _1n + return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) +} diff --git a/packages/noble-curves/src/abstract/montgomery.ts b/packages/noble-curves/src/abstract/montgomery.ts new file mode 100644 index 00000000000..106a0c1943b --- /dev/null +++ b/packages/noble-curves/src/abstract/montgomery.ts @@ -0,0 +1,190 @@ +/** + * Montgomery curve methods. It's not really whole montgomery curve, + * just bunch of very specific methods for X25519 / X448 from + * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { mod, pow } from './modular.js' +import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.js' + +const _0n = BigInt(0) +const _1n = BigInt(1) +type Hex = string | Uint8Array + +export type CurveType = { + P: bigint // finite field prime + nByteLength: number + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + a: bigint + montgomeryBits: number + powPminus2?: (x: bigint) => bigint + xyToU?: (x: bigint, y: bigint) => bigint + Gu: bigint + randomBytes?: (bytesLength?: number) => Uint8Array +} + +export type CurveFn = { + scalarMult: (scalar: Hex, u: Hex) => Uint8Array + scalarMultBase: (scalar: Hex) => Uint8Array + getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array + getPublicKey: (privateKey: Hex) => Uint8Array + utils: { randomPrivateKey: () => Uint8Array } + GuBytes: Uint8Array +} + +function validateOpts(curve: CurveType) { + validateObject( + curve, + { + a: 'bigint', + }, + { + montgomeryBits: 'isSafeInteger', + nByteLength: 'isSafeInteger', + adjustScalarBytes: 'function', + domain: 'function', + powPminus2: 'function', + Gu: 'bigint', + }, + ) + // Set defaults + return Object.freeze({ ...curve } as const) +} + +// Uses only one coordinate instead of two +export function montgomery(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) + const { P } = CURVE + const modP = (n: bigint) => mod(n, P) + const montgomeryBits = CURVE.montgomeryBits + const montgomeryBytes = Math.ceil(montgomeryBits / 8) + const fieldLen = CURVE.nByteLength + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) + const powPminus2 = CURVE.powPminus2 || ((x: bigint) => pow(x, P - BigInt(2), P)) + + // cswap from RFC7748. But it is not from RFC7748! + /* + cswap(swap, x_2, x_3): + dummy = mask(swap) AND (x_2 XOR x_3) + x_2 = x_2 XOR dummy + x_3 = x_3 XOR dummy + Return (x_2, x_3) + Where mask(swap) is the all-1 or all-0 word of the same length as x_2 + and x_3, computed, e.g., as mask(swap) = 0 - swap. + */ + function cswap(swap: bigint, x_2: bigint, x_3: bigint): [bigint, bigint] { + const dummy = modP(swap * (x_2 - x_3)) + x_2 = modP(x_2 - dummy) + x_3 = modP(x_3 + dummy) + return [x_2, x_3] + } + + // x25519 from 4 + // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 + const a24 = (CURVE.a - BigInt(2)) / BigInt(4) + /** + * + * @param pointU u coordinate (x) on Montgomery Curve 25519 + * @param scalar by which the point would be multiplied + * @returns new Point on Montgomery curve + */ + function montgomeryLadder(u: bigint, scalar: bigint): bigint { + aInRange('u', u, _0n, P) + aInRange('scalar', scalar, _0n, P) + // Section 5: Implementations MUST accept non-canonical values and process them as + // if they had been reduced modulo the field prime. + const k = scalar + const x_1 = u + let x_2 = _1n + let z_2 = _0n + let x_3 = u + let z_3 = _1n + let swap = _0n + let sw: [bigint, bigint] + for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { + const k_t = (k >> t) & _1n + swap ^= k_t + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + swap = k_t + + const A = x_2 + z_2 + const AA = modP(A * A) + const B = x_2 - z_2 + const BB = modP(B * B) + const E = AA - BB + const C = x_3 + z_3 + const D = x_3 - z_3 + const DA = modP(D * A) + const CB = modP(C * B) + const dacb = DA + CB + const da_cb = DA - CB + x_3 = modP(dacb * dacb) + z_3 = modP(x_1 * modP(da_cb * da_cb)) + x_2 = modP(AA * BB) + z_2 = modP(E * (AA + modP(a24 * E))) + } + // (x_2, x_3) = cswap(swap, x_2, x_3) + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + // (z_2, z_3) = cswap(swap, z_2, z_3) + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + // z_2^(p - 2) + const z2 = powPminus2(z_2) + // Return x_2 * (z_2^(p - 2)) + return modP(x_2 * z2) + } + + function encodeUCoordinate(u: bigint): Uint8Array { + return numberToBytesLE(modP(u), montgomeryBytes) + } + + function decodeUCoordinate(uEnc: Hex): bigint { + // Section 5: When receiving such an array, implementations of X25519 + // MUST mask the most significant bit in the final byte. + const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) + if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 + return bytesToNumberLE(u) + } + function decodeScalar(n: Hex): bigint { + const bytes = ensureBytes('scalar', n) + const len = bytes.length + if (len !== montgomeryBytes && len !== fieldLen) { + let valid = '' + montgomeryBytes + ' or ' + fieldLen + throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) + } + return bytesToNumberLE(adjustScalarBytes(bytes)) + } + function scalarMult(scalar: Hex, u: Hex): Uint8Array { + const pointU = decodeUCoordinate(u) + const _scalar = decodeScalar(scalar) + const pu = montgomeryLadder(pointU, _scalar) + // The result was not contributory + // https://cr.yp.to/ecdh.html#validate + if (pu === _0n) throw new Error('invalid private or public key received') + return encodeUCoordinate(pu) + } + // Computes public key from private. By doing scalar multiplication of base point. + const GuBytes = encodeUCoordinate(CURVE.Gu) + function scalarMultBase(scalar: Hex): Uint8Array { + return scalarMult(scalar, GuBytes) + } + + return { + scalarMult, + scalarMultBase, + getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey), + getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey), + utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) }, + GuBytes: GuBytes, + } +} diff --git a/packages/noble-curves/src/abstract/poseidon.ts b/packages/noble-curves/src/abstract/poseidon.ts new file mode 100644 index 00000000000..025f8d089f4 --- /dev/null +++ b/packages/noble-curves/src/abstract/poseidon.ts @@ -0,0 +1,136 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { FpPow, type IField, validateField } from './modular.js' + +export type PoseidonOpts = { + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark + mds: bigint[][] + roundConstants: bigint[][] +} + +export function validateOpts(opts: PoseidonOpts): Readonly<{ + rounds: number + sboxFn: (n: bigint) => bigint + roundConstants: bigint[][] + mds: bigint[][] + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark +}> { + const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts + const { roundsFull, roundsPartial, sboxPower, t } = opts + + validateField(Fp) + for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + + // MDS is TxT matrix + if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') + const _mds = mds.map((mdsRow) => { + if (!Array.isArray(mdsRow) || mdsRow.length !== t) + throw new Error('invalid MDS matrix row: ' + mdsRow) + return mdsRow.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) + return Fp.create(i) + }) + }) + + if (rev !== undefined && typeof rev !== 'boolean') + throw new Error('invalid param reversePartialPowIdx=' + rev) + + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) + const rounds = roundsFull + roundsPartial + + if (!Array.isArray(rc) || rc.length !== rounds) + throw new Error('Poseidon: invalid round constants') + const roundConstants = rc.map((rc) => { + if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') + return rc.map((i) => { + if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') + return Fp.create(i) + }) + }) + + if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') + const _sboxPower = BigInt(sboxPower) + let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower) + // Unwrapped sbox power for common cases (195->142μs) + if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(n), n) + else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) + + return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) +} + +export function splitConstants(rc: bigint[], t: number): bigint[][] { + if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') + if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') + const res = [] + let tmp = [] + for (let i = 0; i < rc.length; i++) { + tmp.push(rc[i]) + if (tmp.length === t) { + res.push(tmp) + tmp = [] + } + } + return res +} + +/** Poseidon NTT-friendly hash. */ +export function poseidon(opts: PoseidonOpts): { + (values: bigint[]): bigint[] + // For verification in tests + roundConstants: bigint[][] +} { + const _opts = validateOpts(opts) + const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts + const halfRoundsFull = _opts.roundsFull / 2 + const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 + const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => { + values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) + + if (isFull) values = values.map((i) => sboxFn(i)) + else values[partialIdx] = sboxFn(values[partialIdx]) + // Matrix multiplication + values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) + return values + } + const poseidonHash = function poseidonHash(values: bigint[]) { + if (!Array.isArray(values) || values.length !== t) + throw new Error('invalid values, expected array of bigints with length ' + t) + values = values.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) + return Fp.create(i) + }) + let lastRound = 0 + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + // Apply r_p partial rounds. + for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + + if (lastRound !== totalRounds) throw new Error('invalid number of rounds') + return values + } + // For verification in tests + poseidonHash.roundConstants = roundConstants + return poseidonHash +} diff --git a/packages/noble-curves/src/abstract/tower.ts b/packages/noble-curves/src/abstract/tower.ts new file mode 100644 index 00000000000..743da2f7b33 --- /dev/null +++ b/packages/noble-curves/src/abstract/tower.ts @@ -0,0 +1,664 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.js' +import { bitLen, bitMask, concatBytes, notImplemented } from './utils.js' +import type { ProjConstructor, ProjPointType } from './weierstrass.js' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +// Fp₂ over complex plane +export type BigintTuple = [bigint, bigint] +export type Fp = bigint +// Finite extension field over irreducible polynominal. +// Fp(u) / (u² - β) where β = -1 +export type Fp2 = { c0: bigint; c1: bigint } +export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] +export type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 } +export type Fp12 = { c0: Fp6; c1: Fp6 } // Fp₁₂ = Fp₆² => Fp₂³, Fp₆(w) / (w² - γ) where γ = v +// prettier-ignore +export type BigintTwelve = [ + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, +] + +export type Fp2Bls = mod.IField & { + reim: (num: Fp2) => { re: Fp; im: Fp } + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + fromBigTuple(num: [bigint, bigint]): Fp2 +} + +export type Fp12Bls = mod.IField & { + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + fromBigTwelve(num: BigintTwelve): Fp12 +} + +function calcFrobeniusCoefficients( + Fp: mod.IField, + nonResidue: T, + modulus: bigint, + degree: number, + num: number = 1, + divisor?: number, +) { + const _divisor = BigInt(divisor === undefined ? degree : divisor) + const towerModulus: any = modulus ** BigInt(degree) + const res: T[][] = [] + for (let i = 0; i < num; i++) { + const a = BigInt(i + 1) + const powers: T[] = [] + for (let j = 0, qPower = _1n; j < degree; j++) { + const power = ((a * qPower - a) / _divisor) % towerModulus + powers.push(Fp.pow(nonResidue, power)) + qPower *= modulus + } + res.push(powers) + } + return res +} + +// This works same at least for bls12-381, bn254 and bls12-377 +export function psiFrobenius( + Fp: mod.IField, + Fp2: Fp2Bls, + base: Fp2, +): { + psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] + psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] + G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType + G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType + PSI_X: Fp2 + PSI_Y: Fp2 + PSI2_X: Fp2 + PSI2_Y: Fp2 +} { + // Ψ endomorphism + const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) + const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) + function psi(x: Fp2, y: Fp2): [Fp2, Fp2] { + // This x10 faster than previous version in bls12-381 + const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) + const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) + return [x2, y2] + } + // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) + const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) + // This equals -1, which causes y to be Fp2.neg(y). + // But not sure if there are case when this is not true? + const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) + if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') + function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] { + return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] + } + // Map points + const mapAffine = + (fn: (x: T, y: T) => [T, T]) => + (c: ProjConstructor, P: ProjPointType) => { + const affine = P.toAffine() + const p = fn(affine.x, affine.y) + return c.fromAffine({ x: p[0], y: p[1] }) + } + const G2psi = mapAffine(psi) + const G2psi2 = mapAffine(psi2) + return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } +} + +export type Tower12Opts = { + ORDER: bigint + NONRESIDUE?: Fp + // Fp2 + FP2_NONRESIDUE: BigintTuple + Fp2sqrt?: (num: Fp2) => Fp2 + Fp2mulByB: (num: Fp2) => Fp2 + // Fp12 + Fp12cyclotomicSquare: (num: Fp12) => Fp12 + Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 + Fp12finalExponentiate: (num: Fp12) => Fp12 +} + +export function tower12(opts: Tower12Opts): { + Fp: Readonly & Required, 'isOdd'>>> + Fp2: mod.IField & { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + Fp6: mod.IField & { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 } + Fp12: mod.IField & { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } +} { + const { ORDER } = opts + // Fp + const Fp = mod.Field(ORDER) + const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) + const FpLegendre = mod.FpLegendre(ORDER) + const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 + + // Fp2 + const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] + const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.add(c0, r0), + c1: Fp.add(c1, r1), + }) + const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.sub(c0, r0), + c1: Fp.sub(c1, r1), + }) + const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => { + if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } + // (a+bi)(c+di) = (ac−bd) + (ad+bc)i + const { c0: r0, c1: r1 } = rhs + let t1 = Fp.mul(c0, r0) // c0 * o0 + let t2 = Fp.mul(c1, r1) // c1 * o1 + // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i + const o0 = Fp.sub(t1, t2) + const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) + return { c0: o0, c1: o1 } + } + const Fp2Square = ({ c0, c1 }: Fp2) => { + const a = Fp.add(c0, c1) + const b = Fp.sub(c0, c1) + const c = Fp.add(c0, c0) + return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } + } + type Fp2Utils = { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => { + if (tuple.length !== 2) throw new Error('invalid tuple') + const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp] + return { c0: fps[0], c1: fps[1] } + } + + const FP2_ORDER = ORDER * ORDER + const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) + const Fp2: mod.IField & Fp2Utils = { + ORDER: FP2_ORDER, + isLE: Fp.isLE, + NONRESIDUE: Fp2Nonresidue, + BITS: bitLen(FP2_ORDER), + BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), + MASK: bitMask(bitLen(FP2_ORDER)), + ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, + ONE: { c0: Fp.ONE, c1: Fp.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', + is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), + eql: ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => Fp.eql(c0, r0) && Fp.eql(c1, r1), + neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), + pow: (num, power) => mod.FpPow(Fp2, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), + // Normalized + add: Fp2Add, + sub: Fp2Subtract, + mul: Fp2Multiply, + sqr: Fp2Square, + // NonNormalized stuff + addN: Fp2Add, + subN: Fp2Subtract, + mulN: Fp2Multiply, + sqrN: Fp2Square, + // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? + div: (lhs, rhs) => + Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), + inv: ({ c0: a, c1: b }) => { + // We wish to find the multiplicative inverse of a nonzero + // element a + bu in Fp2. We leverage an identity + // + // (a + bu)(a - bu) = a² + b² + // + // which holds because u² = -1. This can be rewritten as + // + // (a + bu)(a - bu)/(a² + b²) = 1 + // + // because a² + b² = 0 has no nonzero solutions for (a, b). + // This gives that (a - bu)/(a² + b²) is the inverse + // of (a + bu). Importantly, this can be computing using + // only a single inversion in Fp. + const factor = Fp.inv(Fp.create(a * a + b * b)) + return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } + }, + sqrt: (num) => { + if (opts.Fp2sqrt) return opts.Fp2sqrt(num) + // This is generic for all quadratic extensions (Fp2) + const { c0, c1 } = num + if (Fp.is0(c1)) { + // if c0 is quadratic residue + if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) + else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) + } + const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) + let d = Fp.mul(Fp.add(a, c0), Fpdiv2) + const legendre = FpLegendre(Fp, d) + // -1, Quadratic non residue + if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) + const a0 = Fp.sqrt(d) + const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) + if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') + // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num + const x1 = candidateSqrt + const x2 = Fp2.neg(x1) + const { re: re1, im: im1 } = Fp2.reim(x1) + const { re: re2, im: im2 } = Fp2.reim(x2) + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 + return x2 + }, + // Same as sgn0_m_eq_2 in RFC 9380 + isOdd: (x: Fp2) => { + const { re: x0, im: x1 } = Fp2.reim(x) + const sign_0 = x0 % _2n + const zero_0 = x0 === _0n + const sign_1 = x1 % _2n + return BigInt(sign_0 || (zero_0 && sign_1)) == _1n + }, + // Bytes util + fromBytes(b: Uint8Array): Fp2 { + if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } + }, + toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp.cmov(c0, r0, c), + c1: Fp.cmov(c1, r1, c), + }), + reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), + // multiply by u + 1 + mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), + mulByB: opts.Fp2mulByB, + fromBigTuple: Fp2fromBigTuple, + frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({ + c0, + c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), + }), + } + // Fp6 + const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.add(c0, r0), + c1: Fp2.add(c1, r1), + c2: Fp2.add(c2, r2), + }) + const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.sub(c0, r0), + c1: Fp2.sub(c1, r1), + c2: Fp2.sub(c2, r2), + }) + const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => { + if (typeof rhs === 'bigint') { + return { + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + } + } + const { c0: r0, c1: r1, c2: r2 } = rhs + const t0 = Fp2.mul(c0, r0) // c0 * o0 + const t1 = Fp2.mul(c1, r1) // c1 * o1 + const t2 = Fp2.mul(c2, r2) // c2 * o2 + return { + // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) + c0: Fp2.add( + t0, + Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), + ), + // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) + c1: Fp2.add( + Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), + Fp2.mulByNonresidue(t2), + ), + // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 + c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), + } + } + const Fp6Square = ({ c0, c1, c2 }: Fp6) => { + let t0 = Fp2.sqr(c0) // c0² + let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 + let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 + let t4 = Fp2.sqr(c2) // c2² + return { + c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 + c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 + // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 + c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), + } + } + type Fp6Utils = { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + + const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 6, + 2, + 3, + ) + + const Fp6: mod.IField & Fp6Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp2.isLE, + BITS: 3 * Fp2.BITS, + BYTES: 3 * Fp2.BYTES, + MASK: bitMask(3 * Fp2.BITS), + ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, + ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, + create: (num) => num, + isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), + is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), + neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), + eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => + Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), + sqrt: notImplemented, + // Do we need division by bigint at all? Should be done via order: + div: (lhs, rhs) => + Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp6, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), + // Normalized + add: Fp6Add, + sub: Fp6Subtract, + mul: Fp6Multiply, + sqr: Fp6Square, + // NonNormalized stuff + addN: Fp6Add, + subN: Fp6Subtract, + mulN: Fp6Multiply, + sqrN: Fp6Square, + + inv: ({ c0, c1, c2 }) => { + let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) + let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 + let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 + // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) + let t4 = Fp2.inv( + Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), + ) + return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } + }, + // Bytes utils + fromBytes: (b: Uint8Array): Fp6 => { + if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), + c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), + c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), + } + }, + toBytes: ({ c0, c1, c2 }): Uint8Array => + concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), + cmov: ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6, c) => ({ + c0: Fp2.cmov(c0, r0, c), + c1: Fp2.cmov(c1, r1, c), + c2: Fp2.cmov(c2, r2, c), + }), + fromBigSix: (t: BigintSix): Fp6 => { + if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') + return { + c0: Fp2.fromBigTuple(t.slice(0, 2)), + c1: Fp2.fromBigTuple(t.slice(2, 4)), + c2: Fp2.fromBigTuple(t.slice(4, 6)), + } + }, + frobeniusMap: ({ c0, c1, c2 }, power: number) => ({ + c0: Fp2.frobeniusMap(c0, power), + c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + }), + mulByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({ + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + }), + mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), + // Sparse multiplication + mul1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({ + c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), + c1: Fp2.mul(c0, b1), + c2: Fp2.mul(c1, b1), + }), + // Sparse multiplication + mul01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 { + let t0 = Fp2.mul(c0, b0) // c0 * b0 + let t1 = Fp2.mul(c1, b1) // c1 * b1 + return { + // ((c1 + c2) * b1 - T1) * (u + 1) + T0 + c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), + // (b0 + b1) * (c0 + c1) - T0 - T1 + c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), + // (c0 + c2) * b0 - T0 + T1 + c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), + } + }, + } + + // Fp12 + const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 12, + 1, + 6, + )[0] + + const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.add(c0, r0), + c1: Fp6.add(c1, r1), + }) + const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.sub(c0, r0), + c1: Fp6.sub(c1, r1), + }) + const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => { + if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } + let { c0: r0, c1: r1 } = rhs + let t1 = Fp6.mul(c0, r0) // c0 * r0 + let t2 = Fp6.mul(c1, r1) // c1 * r1 + return { + c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v + // (c0 + c1) * (r0 + r1) - (T1 + T2) + c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), + } + } + const Fp12Square = ({ c0, c1 }: Fp12) => { + let ab = Fp6.mul(c0, c1) // c0 * c1 + return { + // (c1 * v + c0) * (c0 + c1) - AB - AB * v + c0: Fp6.sub( + Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), + Fp6.mulByNonresidue(ab), + ), + c1: Fp6.add(ab, ab), + } // AB + AB + } + function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } { + const a2 = Fp2.sqr(a) + const b2 = Fp2.sqr(b) + return { + first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² + second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² + } + } + type Fp12Utils = { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } + + const Fp12: mod.IField & Fp12Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp6.isLE, + BITS: 2 * Fp2.BITS, + BYTES: 2 * Fp2.BYTES, + MASK: bitMask(2 * Fp2.BITS), + ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, + ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), + is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), + neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), + sqrt: notImplemented, + inv: ({ c0, c1 }) => { + let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) + return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w + }, + div: (lhs, rhs) => + Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp12, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), + // Normalized + add: Fp12Add, + sub: Fp12Subtract, + mul: Fp12Multiply, + sqr: Fp12Square, + // NonNormalized stuff + addN: Fp12Add, + subN: Fp12Subtract, + mulN: Fp12Multiply, + sqrN: Fp12Square, + + // Bytes utils + fromBytes: (b: Uint8Array): Fp12 => { + if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), + c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), + } + }, + toBytes: ({ c0, c1 }): Uint8Array => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp6.cmov(c0, r0, c), + c1: Fp6.cmov(c1, r1, c), + }), + // Utils + // toString() { + // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); + // }, + // fromTuple(c: [Fp6, Fp6]) { + // return new Fp12(...c); + // } + fromBigTwelve: (t: BigintTwelve): Fp12 => ({ + c0: Fp6.fromBigSix(t.slice(0, 6) as BigintSix), + c1: Fp6.fromBigSix(t.slice(6, 12) as BigintSix), + }), + // Raises to q**i -th power + frobeniusMap(lhs, power: number) { + const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] + return { + c0: Fp6.frobeniusMap(lhs.c0, power), + c1: Fp6.create({ + c0: Fp2.mul(c0, coeff), + c1: Fp2.mul(c1, coeff), + c2: Fp2.mul(c2, coeff), + }), + } + }, + mulByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({ + c0: Fp6.mulByFp2(c0, rhs), + c1: Fp6.mulByFp2(c1, rhs), + }), + conjugate: ({ c0, c1 }): Fp12 => ({ c0, c1: Fp6.neg(c1) }), + // Sparse multiplication + mul014: ({ c0, c1 }, o0: Fp2, o1: Fp2, o4: Fp2) => { + let t0 = Fp6.mul01(c0, o0, o1) + let t1 = Fp6.mul1(c1, o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 + // (c1 + c0) * [o0, o1+o4] - T0 - T1 + c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), + } + }, + mul034: ({ c0, c1 }, o0: Fp2, o3: Fp2, o4: Fp2) => { + const a = Fp6.create({ + c0: Fp2.mul(c0.c0, o0), + c1: Fp2.mul(c0.c1, o0), + c2: Fp2.mul(c0.c2, o0), + }) + const b = Fp6.mul01(c1, o3, o4) + const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(b), a), + c1: Fp6.sub(e, Fp6.add(a, b)), + } + }, + + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + _cyclotomicSquare: opts.Fp12cyclotomicSquare, + _cyclotomicExp: opts.Fp12cyclotomicExp, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + finalExponentiate: opts.Fp12finalExponentiate, + } + + return { Fp, Fp2, Fp6, Fp4Square, Fp12 } +} diff --git a/packages/noble-curves/src/abstract/utils.ts b/packages/noble-curves/src/abstract/utils.ts new file mode 100644 index 00000000000..0ace81e2696 --- /dev/null +++ b/packages/noble-curves/src/abstract/utils.ts @@ -0,0 +1,367 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ + +// 100 lines of code in the file are duplicated from noble-hashes (utils). +// This is OK: `abstract` directory does not use noble-hashes. +// User may opt-in into using different hashing library. This way, noble-hashes +// won't be included into their bundle. +const _0n = /* @__PURE__ */ BigInt(0) +const _1n = /* @__PURE__ */ BigInt(1) +const _2n = /* @__PURE__ */ BigInt(2) +export type Hex = Uint8Array | string // hex strings are accepted for simplicity +export type PrivKey = Hex | bigint // bigints are accepted to ease learning curve +export type CHash = { + (message: Uint8Array | string): Uint8Array + blockLen: number + outputLen: number + create(opts?: { dkLen?: number }): any // For shake +} +export type FHash = (message: Uint8Array | string) => Uint8Array + +export function isBytes(a: unknown): a is Uint8Array { + return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') +} + +export function abytes(item: unknown): void { + if (!isBytes(item)) throw new Error('Uint8Array expected') +} + +export function abool(title: string, value: boolean): void { + if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) +} + +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) +/** + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export function bytesToHex(bytes: Uint8Array): string { + abytes(bytes) + // pre-caching improves the speed 6x + let hex = '' + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]] + } + return hex +} + +export function numberToHexUnpadded(num: number | bigint): string { + const hex = num.toString(16) + return hex.length & 1 ? '0' + hex : hex +} + +export function hexToNumber(hex: string): bigint { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian +} + +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const +function asciiToBase16(ch: number): number | undefined { + if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 + if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) + if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) + return +} + +/** + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export function hexToBytes(hex: string): Uint8Array { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + const hl = hex.length + const al = hl / 2 + if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) + const array = new Uint8Array(al) + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)) + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1] + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) + } + array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 + } + return array +} + +// BE: Big Endian, LE: Little Endian +export function bytesToNumberBE(bytes: Uint8Array): bigint { + return hexToNumber(bytesToHex(bytes)) +} +export function bytesToNumberLE(bytes: Uint8Array): bigint { + abytes(bytes) + return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) +} + +export function numberToBytesBE(n: number | bigint, len: number): Uint8Array { + return hexToBytes(n.toString(16).padStart(len * 2, '0')) +} +export function numberToBytesLE(n: number | bigint, len: number): Uint8Array { + return numberToBytesBE(n, len).reverse() +} +// Unpadded, rarely used +export function numberToVarBytesBE(n: number | bigint): Uint8Array { + return hexToBytes(numberToHexUnpadded(n)) +} + +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array { + let res: Uint8Array + if (typeof hex === 'string') { + try { + res = hexToBytes(hex) + } catch (e) { + throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) + } + } else if (isBytes(hex)) { + // Uint8Array.from() instead of hash.slice() because node.js Buffer + // is instance of Uint8Array, and its slice() creates **mutable** copy + res = Uint8Array.from(hex) + } else { + throw new Error(title + ' must be hex string or Uint8Array') + } + const len = res.length + if (typeof expectedLength === 'number' && len !== expectedLength) + throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) + return res +} + +/** + * Copies several Uint8Arrays into one. + */ +export function concatBytes(...arrays: Uint8Array[]): Uint8Array { + let sum = 0 + for (let i = 0; i < arrays.length; i++) { + const a = arrays[i] + abytes(a) + sum += a.length + } + const res = new Uint8Array(sum) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const a = arrays[i] + res.set(a, pad) + pad += a.length + } + return res +} + +// Compares 2 u8a-s in kinda constant time +export function equalBytes(a: Uint8Array, b: Uint8Array): boolean { + if (a.length !== b.length) return false + let diff = 0 + for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] + return diff === 0 +} + +// Global symbols in both browsers and Node.js since v11 +// See https://github.com/microsoft/TypeScript/issues/31535 +declare const TextEncoder: any + +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export function utf8ToBytes(str: string): Uint8Array { + if (typeof str !== 'string') throw new Error('string expected') + return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 +} + +// Is positive bigint +const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n + +export function inRange(n: bigint, min: bigint, max: bigint): boolean { + return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max +} + +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void { + // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? + // consider P=256n, min=0n, max=P + // - a for min=0 would require -1: `inRange('x', x, -1n, P)` + // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` + // - our way is the cleanest: `inRange('x', x, 0n, P) + if (!inRange(n, min, max)) + throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) +} + +// Bit operations + +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export function bitLen(n: bigint): number { + let len + for (len = 0; n > _0n; n >>= _1n, len += 1); + return len +} + +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export function bitGet(n: bigint, pos: number): bigint { + return (n >> BigInt(pos)) & _1n +} + +/** + * Sets single bit at position. + */ +export function bitSet(n: bigint, pos: number, value: boolean): bigint { + return n | ((value ? _1n : _0n) << BigInt(pos)) +} + +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export const bitMask = (n: number): bigint => (_2n << BigInt(n - 1)) - _1n + +// DRBG + +const u8n = (data?: any) => new Uint8Array(data) // creates Uint8Array +const u8fr = (arr: any) => Uint8Array.from(arr) // another shortcut +type Pred = (v: Uint8Array) => T | undefined +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export function createHmacDrbg( + hashLen: number, + qByteLen: number, + hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, +): (seed: Uint8Array, predicate: Pred) => T { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') + if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0 // Iterations counter, will throw when over 1000 + const reset = () => { + v.fill(1) + k.fill(0) + i = 0 + } + const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) + const reseed = (seed = u8n()) => { + // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) + v = h() // v = hmac(k || v) + if (seed.length === 0) return + k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) + v = h() // v = hmac(k || v) + } + const gen = () => { + // HMAC-DRBG generate() function + if (i++ >= 1000) throw new Error('drbg: tried 1000 values') + let len = 0 + const out: Uint8Array[] = [] + while (len < qByteLen) { + v = h() + const sl = v.slice() + out.push(sl) + len += v.length + } + return concatBytes(...out) + } + const genUntil = (seed: Uint8Array, pred: Pred): T => { + reset() + reseed(seed) // Steps D-G + let res: T | undefined = undefined // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed() + reset() + return res + } + return genUntil +} + +// Validating curves and fields + +const validatorFns = { + bigint: (val: any): boolean => typeof val === 'bigint', + function: (val: any): boolean => typeof val === 'function', + boolean: (val: any): boolean => typeof val === 'boolean', + string: (val: any): boolean => typeof val === 'string', + stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val), + isSafeInteger: (val: any): boolean => Number.isSafeInteger(val), + array: (val: any): boolean => Array.isArray(val), + field: (val: any, object: any): any => (object as any).Fp.isValid(val), + hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen), +} as const +type Validator = keyof typeof validatorFns +type ValMap> = { [K in keyof T]?: Validator } +// type Record = { [P in K]: T; } + +export function validateObject>( + object: T, + validators: ValMap, + optValidators: ValMap = {}, +): T { + const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => { + const checkVal = validatorFns[type] + if (typeof checkVal !== 'function') throw new Error('invalid validator function') + + const val = object[fieldName as keyof typeof object] + if (isOptional && val === undefined) return + if (!checkVal(val, object)) { + throw new Error( + 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, + ) + } + } + for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false) + for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true) + return object +} +// validate type tests +// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; +// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! +// // Should fail type-check +// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); +// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); +// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); +// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); + +/** + * throws not implemented error + */ +export const notImplemented = (): never => { + throw new Error('not implemented') +} + +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export function memoized( + fn: (arg: T, ...args: O) => R, +): (arg: T, ...args: O) => R { + const map = new WeakMap() + return (arg: T, ...args: O): R => { + const val = map.get(arg) + if (val !== undefined) return val + const computed = fn(arg, ...args) + map.set(arg, computed) + return computed + } +} diff --git a/packages/noble-curves/src/abstract/weierstrass.ts b/packages/noble-curves/src/abstract/weierstrass.ts new file mode 100644 index 00000000000..2b6d25fa3b8 --- /dev/null +++ b/packages/noble-curves/src/abstract/weierstrass.ts @@ -0,0 +1,1383 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.js' +import { + Field, + type IField, + getMinHashLength, + invert, + mapHashToField, + mod, + validateField, +} from './modular.js' +import * as ut from './utils.js' +import { type CHash, type Hex, type PrivKey, abool, ensureBytes, memoized } from './utils.js' + +export type { AffinePoint } +type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array +type EndomorphismOpts = { + beta: bigint + splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint } +} +export type BasicWCurve = BasicCurve & { + // Params: a, b + a: T + b: T + + // Optional params + allowedPrivateKeyLengths?: readonly number[] // for P521 + wrapPrivateKey?: boolean // bls12-381 requires mod(n) instead of rejecting keys >= n + endo?: EndomorphismOpts // Endomorphism options for Koblitz curves + // When a cofactor != 1, there can be an effective methods to: + // 1. Determine whether a point is torsion-free + isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean + // 2. Clear torsion component + clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType +} + +type Entropy = Hex | boolean +export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean } +export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined } + +function validateSigVerOpts(opts: SignOpts | VerOpts) { + if (opts.lowS !== undefined) abool('lowS', opts.lowS) + if (opts.prehash !== undefined) abool('prehash', opts.prehash) +} + +// Instance for 3d XYZ points +export interface ProjPointType extends Group> { + readonly px: T + readonly py: T + readonly pz: T + get x(): T + get y(): T + multiply(scalar: bigint): ProjPointType + toAffine(iz?: T): AffinePoint + isTorsionFree(): boolean + clearCofactor(): ProjPointType + assertValidity(): void + hasEvenY(): boolean + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + + multiplyUnsafe(scalar: bigint): ProjPointType + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined + _setWindowSize(windowSize: number): void +} +// Static methods for 3d XYZ points +export interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType + fromAffine(p: AffinePoint): ProjPointType + fromHex(hex: Hex): ProjPointType + fromPrivateKey(privateKey: PrivKey): ProjPointType + normalizeZ(points: ProjPointType[]): ProjPointType[] + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType +} + +export type CurvePointsType = BasicWCurve & { + // Bytes + fromBytes?: (bytes: Uint8Array) => AffinePoint + toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array +} + +export type CurvePointsTypeWithLength = Readonly< + CurvePointsType & { nByteLength: number; nBitLength: number } +> + +function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength { + const opts = validateBasic(curve) + ut.validateObject( + opts, + { + a: 'field', + b: 'field', + }, + { + allowedPrivateKeyLengths: 'array', + wrapPrivateKey: 'boolean', + isTorsionFree: 'function', + clearCofactor: 'function', + allowInfinityPoint: 'boolean', + fromBytes: 'function', + toBytes: 'function', + }, + ) + const { endo, Fp, a } = opts + if (endo) { + if (!Fp.eql(a, Fp.ZERO)) { + throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') + } + if ( + typeof endo !== 'object' || + typeof endo.beta !== 'bigint' || + typeof endo.splitScalar !== 'function' + ) { + throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') + } + } + return Object.freeze({ ...opts } as const) +} + +export type CurvePointsRes = { + CURVE: ReturnType> + ProjectivePoint: ProjConstructor + normPrivateKeyToScalar: (key: PrivKey) => bigint + weierstrassEquation: (x: T) => T + isWithinCurveOrder: (num: bigint) => boolean +} + +const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut + +export class DERErr extends Error { + constructor(m = '') { + super(m) + } +} +export type IDER = { + // asn.1 DER encoding utils + Err: typeof DERErr + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string) => string + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } + } + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string + decode(data: Uint8Array): bigint + } + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } + hexFromSig(sig: { r: bigint; s: bigint }): string +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export const DER: IDER = { + // asn.1 DER encoding utils + Err: DERErr, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string): string => { + const { Err: E } = DER + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length & 1) throw new E('tlv.encode: unpadded data') + const dataLen = data.length / 2 + const len = ut.numberToHexUnpadded(dataLen) + if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big') + // length of length with long form flag + const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '' + const t = ut.numberToHexUnpadded(tag) + return t + lenLen + len + data + }, + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } { + const { Err: E } = DER + let pos = 0 + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') + const first = data[pos++] + const isLong = !!(first & 0b1000_0000) // First bit of first length byte is flag for short/long form + let length = 0 + if (!isLong) length = first + else { + // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] + const lenLen = first & 0b0111_1111 + if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') + if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js + const lengthBytes = data.subarray(pos, pos + lenLen) + if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') + if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') + for (const b of lengthBytes) length = (length << 8) | b + pos += lenLen + if (length < 128) throw new E('tlv.decode(long): not minimal encoding') + } + const v = data.subarray(pos, pos + length) + if (v.length !== length) throw new E('tlv.decode: wrong value length') + return { v, l: data.subarray(pos + length) } + }, + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string { + const { Err: E } = DER + if (num < _0n) throw new E('integer: negative integers are not allowed') + let hex = ut.numberToHexUnpadded(num) + // Pad with zero byte if negative flag is present + if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex + if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') + return hex + }, + decode(data: Uint8Array): bigint { + const { Err: E } = DER + if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative') + if (data[0] === 0x00 && !(data[1] & 0b1000_0000)) + throw new E('invalid signature integer: unnecessary leading zero') + return b2n(data) + }, + }, + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { + // parse DER signature + const { Err: E, _int: int, _tlv: tlv } = DER + const data = typeof hex === 'string' ? h2b(hex) : hex + ut.abytes(data) + const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) + if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) + const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) + if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + return { r: int.decode(rBytes), s: int.decode(sBytes) } + }, + hexFromSig(sig: { r: bigint; s: bigint }): string { + const { _tlv: tlv, _int: int } = DER + const rs = tlv.encode(0x02, int.encode(sig.r)) + const ss = tlv.encode(0x02, int.encode(sig.s)) + const seq = rs + ss + return tlv.encode(0x30, seq) + }, +} + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +export function weierstrassPoints(opts: CurvePointsType): CurvePointsRes { + const CURVE = validatePointOpts(opts) + const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ + const Fn = Field(CURVE.n, CURVE.nBitLength) + + const toBytes = + CURVE.toBytes || + ((_c: ProjConstructor, point: ProjPointType, _isCompressed: boolean) => { + const a = point.toAffine() + return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) + }) + const fromBytes = + CURVE.fromBytes || + ((bytes: Uint8Array) => { + // const head = bytes[0]; + const tail = bytes.subarray(1) + // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + }) + + /** + * y² = x³ + ax + b: Short weierstrass curve formula + * @returns y² + */ + function weierstrassEquation(x: T): T { + const { a, b } = CURVE + const x2 = Fp.sqr(x) // x * x + const x3 = Fp.mul(x2, x) // x2 * x + return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b + } + // Validate whether the passed curve params are valid. + // We check if curve equation works for generator point. + // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. + // ProjectivePoint class has not been initialized yet. + if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) + throw new Error('bad generator point: equation left != right') + + // Valid group elements reside in range 1..n-1 + function isWithinCurveOrder(num: bigint): boolean { + return ut.inRange(num, _1n, CURVE.n) + } + // Validates if priv key is valid and converts it to bigint. + // Supports options allowedPrivateKeyLengths and wrapPrivateKey. + function normPrivateKeyToScalar(key: PrivKey): bigint { + const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE + if (lengths && typeof key !== 'bigint') { + if (ut.isBytes(key)) key = ut.bytesToHex(key) + // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes + if (typeof key !== 'string' || !lengths.includes(key.length)) + throw new Error('invalid private key') + key = key.padStart(nByteLength * 2, '0') + } + let num: bigint + try { + num = + typeof key === 'bigint' + ? key + : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength)) + } catch (error) { + throw new Error( + 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, + ) + } + if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS + ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] + return num + } + + function assertPrjPoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') + } + + // Memoized toAffine / validity check. They are heavy. Points are immutable. + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint => { + const { px: x, py: y, pz: z } = p + // Fast-path for normalized points + if (Fp.eql(z, Fp.ONE)) return { x, y } + const is0 = p.is0() + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 1. + if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) + const ax = Fp.mul(x, iz) + const ay = Fp.mul(y, iz) + const zz = Fp.mul(z, iz) + if (is0) return { x: Fp.ZERO, y: Fp.ZERO } + if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + // NOTE: on exception this will crash 'cached' and no value will be set. + // Otherwise true will be return + const assertValidMemo = memoized((p: Point) => { + if (p.is0()) { + // (0, 1, 0) aka ZERO is invalid in most contexts. + // In BLS, ZERO can be serialized, so we allow it. + // (0, 0, 0) is invalid representation of ZERO. + if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return + throw new Error('bad point: ZERO') + } + // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` + const { x, y } = p.toAffine() + // Check if x, y are valid field elements + if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') + const left = Fp.sqr(y) // y² + const right = weierstrassEquation(x) // x³ + ax + b + if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') + if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') + return true + }) + + /** + * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) + * Default Point works in 2d / affine coordinates: (x, y) + * We're doing calculations in projective, because its operations don't require costly inversion. + */ + class Point implements ProjPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) + static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) + + constructor( + readonly px: T, + readonly py: T, + readonly pz: T, + ) { + if (px == null || !Fp.isValid(px)) throw new Error('x required') + if (py == null || !Fp.isValid(py)) throw new Error('y required') + if (pz == null || !Fp.isValid(pz)) throw new Error('z required') + Object.freeze(this) + } + + // Does not validate if the point is on-curve. + // Use fromHex instead, or call assertValidity() later. + static fromAffine(p: AffinePoint): Point { + const { x, y } = p || {} + if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') + if (p instanceof Point) throw new Error('projective point not allowed') + const is0 = (i: T) => Fp.eql(i, Fp.ZERO) + // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) + if (is0(x) && is0(y)) return Point.ZERO + return new Point(x, y, Fp.ONE) + } + + get x(): T { + return this.toAffine().x + } + get y(): T { + return this.toAffine().y + } + + /** + * Takes a bunch of Projective Points but executes only one + * inversion on all of them. Inversion is very slow operation, + * so this improves performance massively. + * Optimization: converts a list of projective points to a list of identical points with Z=1. + */ + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.pz)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + + /** + * Converts hash string or Uint8Array to Point. + * @param hex short/long ECDSA hex + */ + static fromHex(hex: Hex): Point { + const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) + P.assertValidity() + return P + } + + // Multiplies generator point by privateKey. + static fromPrivateKey(privateKey: PrivKey) { + return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) + } + + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + + // A point on curve is valid if it conforms to equation. + assertValidity(): void { + assertValidMemo(this) + } + + hasEvenY(): boolean { + const { y } = this.toAffine() + if (Fp.isOdd) return !Fp.isOdd(y) + throw new Error("Field doesn't support isOdd") + } + + /** + * Compare one point to another. + */ + equals(other: Point): boolean { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) + const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) + return U1 && U2 + } + + /** + * Flips point to one corresponding to (x, -y) in Affine coordinates. + */ + negate(): Point { + return new Point(this.px, Fp.neg(this.py), this.pz) + } + + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a, b } = CURVE + const b3 = Fp.mul(b, _3n) + const { px: X1, py: Y1, pz: Z1 } = this + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + let t0 = Fp.mul(X1, X1) // step 1 + let t1 = Fp.mul(Y1, Y1) + let t2 = Fp.mul(Z1, Z1) + let t3 = Fp.mul(X1, Y1) + t3 = Fp.add(t3, t3) // step 5 + Z3 = Fp.mul(X1, Z1) + Z3 = Fp.add(Z3, Z3) + X3 = Fp.mul(a, Z3) + Y3 = Fp.mul(b3, t2) + Y3 = Fp.add(X3, Y3) // step 10 + X3 = Fp.sub(t1, Y3) + Y3 = Fp.add(t1, Y3) + Y3 = Fp.mul(X3, Y3) + X3 = Fp.mul(t3, X3) + Z3 = Fp.mul(b3, Z3) // step 15 + t2 = Fp.mul(a, t2) + t3 = Fp.sub(t0, t2) + t3 = Fp.mul(a, t3) + t3 = Fp.add(t3, Z3) + Z3 = Fp.add(t0, t0) // step 20 + t0 = Fp.add(Z3, t0) + t0 = Fp.add(t0, t2) + t0 = Fp.mul(t0, t3) + Y3 = Fp.add(Y3, t0) + t2 = Fp.mul(Y1, Z1) // step 25 + t2 = Fp.add(t2, t2) + t0 = Fp.mul(t2, t3) + X3 = Fp.sub(X3, t0) + Z3 = Fp.mul(t2, t1) + Z3 = Fp.add(Z3, Z3) // step 30 + Z3 = Fp.add(Z3, Z3) + return new Point(X3, Y3, Z3) + } + + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(other: Point): Point { + assertPrjPoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + const a = CURVE.a + const b3 = Fp.mul(CURVE.b, _3n) + let t0 = Fp.mul(X1, X2) // step 1 + let t1 = Fp.mul(Y1, Y2) + let t2 = Fp.mul(Z1, Z2) + let t3 = Fp.add(X1, Y1) + let t4 = Fp.add(X2, Y2) // step 5 + t3 = Fp.mul(t3, t4) + t4 = Fp.add(t0, t1) + t3 = Fp.sub(t3, t4) + t4 = Fp.add(X1, Z1) + let t5 = Fp.add(X2, Z2) // step 10 + t4 = Fp.mul(t4, t5) + t5 = Fp.add(t0, t2) + t4 = Fp.sub(t4, t5) + t5 = Fp.add(Y1, Z1) + X3 = Fp.add(Y2, Z2) // step 15 + t5 = Fp.mul(t5, X3) + X3 = Fp.add(t1, t2) + t5 = Fp.sub(t5, X3) + Z3 = Fp.mul(a, t4) + X3 = Fp.mul(b3, t2) // step 20 + Z3 = Fp.add(X3, Z3) + X3 = Fp.sub(t1, Z3) + Z3 = Fp.add(t1, Z3) + Y3 = Fp.mul(X3, Z3) + t1 = Fp.add(t0, t0) // step 25 + t1 = Fp.add(t1, t0) + t2 = Fp.mul(a, t2) + t4 = Fp.mul(b3, t4) + t1 = Fp.add(t1, t2) + t2 = Fp.sub(t0, t2) // step 30 + t2 = Fp.mul(a, t2) + t4 = Fp.add(t4, t2) + t0 = Fp.mul(t1, t4) + Y3 = Fp.add(Y3, t0) + t0 = Fp.mul(t5, t4) // step 35 + X3 = Fp.mul(t3, X3) + X3 = Fp.sub(X3, t0) + t0 = Fp.mul(t3, t1) + Z3 = Fp.mul(t5, Z3) + Z3 = Fp.add(Z3, t0) // step 40 + return new Point(X3, Y3, Z3) + } + + subtract(other: Point) { + return this.add(other.negate()) + } + + is0() { + return this.equals(Point.ZERO) + } + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed private key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(sc: bigint): Point { + const { endo, n: N } = CURVE + ut.aInRange('scalar', sc, _0n, N) + const I = Point.ZERO + if (sc === _0n) return I + if (this.is0() || sc === _1n) return this + + // Case a: no endomorphism. Case b: has precomputes. + if (!endo || wnaf.hasPrecomputes(this)) + return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) + + // Case c: endomorphism + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) + let k1p = I + let k2p = I + let d: Point = this + while (k1 > _0n || k2 > _0n) { + if (k1 & _1n) k1p = k1p.add(d) + if (k2 & _1n) k2p = k2p.add(d) + d = d.double() + k1 >>= _1n + k2 >>= _1n + } + if (k1neg) k1p = k1p.negate() + if (k2neg) k2p = k2p.negate() + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + return k1p.add(k2p) + } + + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(scalar: bigint): Point { + const { endo, n: N } = CURVE + ut.aInRange('scalar', scalar, _1n, N) + let point: Point, fake: Point // Fake point is used to const-time mult + if (endo) { + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) + let { p: k1p, f: f1p } = this.wNAF(k1) + let { p: k2p, f: f2p } = this.wNAF(k2) + k1p = wnaf.constTimeNegate(k1neg, k1p) + k2p = wnaf.constTimeNegate(k2neg, k2p) + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + point = k1p.add(k2p) + fake = f1p.add(f2p) + } else { + const { p, f } = this.wNAF(scalar) + point = p + fake = f + } + // Normalize `z` for both points, but return only real one + return Point.normalizeZ([point, fake])[0] + } + + /** + * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. + * Not using Strauss-Shamir trick: precomputation tables are faster. + * The trick could be useful if both P and Q are not G (not in our case). + * @returns non-zero affine point + */ + multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { + const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes + const mul = ( + P: Point, + a: bigint, // Select faster multiply() method + ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) + const sum = mul(this, a).add(mul(Q, b)) + return sum.is0() ? undefined : sum + } + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + toAffine(iz?: T): AffinePoint { + return toAffineMemo(this, iz) + } + isTorsionFree(): boolean { + const { h: cofactor, isTorsionFree } = CURVE + if (cofactor === _1n) return true // No subgroups, always torsion-free + if (isTorsionFree) return isTorsionFree(Point, this) + throw new Error('isTorsionFree() has not been declared for the elliptic curve') + } + clearCofactor(): Point { + const { h: cofactor, clearCofactor } = CURVE + if (cofactor === _1n) return this // Fast-path + if (clearCofactor) return clearCofactor(Point, this) as Point + return this.multiplyUnsafe(CURVE.h) + } + + toRawBytes(isCompressed = true): Uint8Array { + abool('isCompressed', isCompressed) + this.assertValidity() + return toBytes(Point, this, isCompressed) + } + + toHex(isCompressed = true): string { + abool('isCompressed', isCompressed) + return ut.bytesToHex(this.toRawBytes(isCompressed)) + } + } + const _bits = CURVE.nBitLength + const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) + // Validate if generator point is on curve + return { + CURVE, + ProjectivePoint: Point as ProjConstructor, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } +} + +// Instance +export interface SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + assertValidity(): void + addRecoveryBit(recovery: number): RecoveredSignatureType + hasHighS(): boolean + normalizeS(): SignatureType + recoverPublicKey(msgHash: Hex): ProjPointType + toCompactRawBytes(): Uint8Array + toCompactHex(): string + // DER-encoded + toDERRawBytes(isCompressed?: boolean): Uint8Array + toDERHex(isCompressed?: boolean): string +} +export type RecoveredSignatureType = SignatureType & { + readonly recovery: number +} +// Static methods +export type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType + fromCompact(hex: Hex): SignatureType + fromDER(hex: Hex): SignatureType +} +type SignatureLike = { r: bigint; s: bigint } + +export type PubKey = Hex | ProjPointType + +export type CurveType = BasicWCurve & { + hash: CHash // CHash not FHash because we need outputLen for DRBG + hmac: HmacFnSync + randomBytes: (bytesLength?: number) => Uint8Array + lowS?: boolean + bits2int?: (bytes: Uint8Array) => bigint + bits2int_modN?: (bytes: Uint8Array) => bigint +} + +function validateOpts( + curve: CurveType, +): Readonly { + const opts = validateBasic(curve) + ut.validateObject( + opts, + { + hash: 'hash', + hmac: 'function', + randomBytes: 'function', + }, + { + bits2int: 'function', + bits2int_modN: 'function', + lowS: 'boolean', + }, + ) + return Object.freeze({ lowS: true, ...opts } as const) +} + +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType + verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean + ProjectivePoint: ProjConstructor + Signature: SignatureConstructor + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint + isValidPrivateKey(privateKey: PrivKey): boolean + randomPrivateKey: () => Uint8Array + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType + } +} + +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export function weierstrass(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { Fp, n: CURVE_ORDER } = CURVE + const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 + const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + function invN(a: bigint) { + return invert(a, CURVE_ORDER) + } + + const { + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } = weierstrassPoints({ + ...CURVE, + toBytes(_c, point, isCompressed: boolean): Uint8Array { + const a = point.toAffine() + const x = Fp.toBytes(a.x) + const cat = ut.concatBytes + abool('isCompressed', isCompressed) + if (isCompressed) { + return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) + } else { + return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) + } + }, + fromBytes(bytes: Uint8Array) { + const len = bytes.length + const head = bytes[0] + const tail = bytes.subarray(1) + // this.assertValidity() is done inside of fromHex + if (len === compressedLen && (head === 0x02 || head === 0x03)) { + const x = ut.bytesToNumberBE(tail) + if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') + const y2 = weierstrassEquation(x) // y² = x³ + ax + b + let y: bigint + try { + y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 + } catch (sqrtError) { + const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' + throw new Error('Point is not on curve' + suffix) + } + const isYOdd = (y & _1n) === _1n + // ECDSA + const isHeadOdd = (head & 1) === 1 + if (isHeadOdd !== isYOdd) y = Fp.neg(y) + return { x, y } + } else if (len === uncompressedLen && head === 0x04) { + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + } else { + const cl = compressedLen + const ul = uncompressedLen + throw new Error( + 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, + ) + } + }, + }) + const numToNByteStr = (num: bigint): string => + ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) + + function isBiggerThanHalfOrder(number: bigint) { + const HALF = CURVE_ORDER >> _1n + return number > HALF + } + + function normalizeS(s: bigint) { + return isBiggerThanHalfOrder(s) ? modN(-s) : s + } + // slice bytes num + const slcNum = (b: Uint8Array, from: number, to: number) => ut.bytesToNumberBE(b.slice(from, to)) + + /** + * ECDSA signature with its (r, s) properties. Supports DER & compact representations. + */ + class Signature implements SignatureType { + constructor( + readonly r: bigint, + readonly s: bigint, + readonly recovery?: number, + ) { + this.assertValidity() + } + + // pair (bytes of r, bytes of s) + static fromCompact(hex: Hex) { + const l = CURVE.nByteLength + hex = ensureBytes('compactSignature', hex, l * 2) + return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) + } + + // DER encoded ECDSA signature + // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script + static fromDER(hex: Hex) { + const { r, s } = DER.toSig(ensureBytes('DER', hex)) + return new Signature(r, s) + } + + assertValidity(): void { + ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] + ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] + } + + addRecoveryBit(recovery: number): RecoveredSignature { + return new Signature(this.r, this.s, recovery) as RecoveredSignature + } + + recoverPublicKey(msgHash: Hex): typeof Point.BASE { + const { r, s, recovery: rec } = this + const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash + if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') + const radj = rec === 2 || rec === 3 ? r + CURVE.n : r + if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') + const prefix = (rec & 1) === 0 ? '02' : '03' + const R = Point.fromHex(prefix + numToNByteStr(radj)) + const ir = invN(radj) // r^-1 + const u1 = modN(-h * ir) // -hr^-1 + const u2 = modN(s * ir) // sr^-1 + const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) + if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked + Q.assertValidity() + return Q + } + + // Signatures should be low-s, to prevent malleability. + hasHighS(): boolean { + return isBiggerThanHalfOrder(this.s) + } + + normalizeS() { + return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this + } + + // DER-encoded + toDERRawBytes() { + return ut.hexToBytes(this.toDERHex()) + } + toDERHex() { + return DER.hexFromSig({ r: this.r, s: this.s }) + } + + // padded bytes of r, then padded bytes of s + toCompactRawBytes() { + return ut.hexToBytes(this.toCompactHex()) + } + toCompactHex() { + return numToNByteStr(this.r) + numToNByteStr(this.s) + } + } + type RecoveredSignature = Signature & { recovery: number } + + const utils = { + isValidPrivateKey(privateKey: PrivKey) { + try { + normPrivateKeyToScalar(privateKey) + return true + } catch (error) { + return false + } + }, + normPrivateKeyToScalar: normPrivateKeyToScalar, + + /** + * Produces cryptographically secure private key from random of size + * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. + */ + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(CURVE.n) + return mapHashToField(CURVE.randomBytes(length), CURVE.n) + }, + + /** + * Creates precompute table for an arbitrary EC point. Makes point "cached". + * Allows to massively speed-up `point.multiply(scalar)`. + * @returns cached point + * @example + * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); + * fast.multiply(privKey); // much faster ECDH now + */ + precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here + return point + }, + } + + /** + * Computes public key for a private key. Checks for validity of the private key. + * @param privateKey private key + * @param isCompressed whether to return compact (default), or full key + * @returns Public key, full when isCompressed=false; short when isCompressed=true + */ + function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array { + return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) + } + + /** + * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. + */ + function isProbPub(item: PrivKey | PubKey): boolean { + const arr = ut.isBytes(item) + const str = typeof item === 'string' + const len = (arr || str) && (item as Hex).length + if (arr) return len === compressedLen || len === uncompressedLen + if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen + if (item instanceof Point) return true + return false + } + + /** + * ECDH (Elliptic Curve Diffie Hellman). + * Computes shared public key from private key and public key. + * Checks: 1) private key validity 2) shared key is on-curve. + * Does NOT hash the result. + * @param privateA private key + * @param publicB different public key + * @param isCompressed whether to return compact (default), or full key + * @returns shared public key + */ + function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array { + if (isProbPub(privateA)) throw new Error('first arg must be private key') + if (!isProbPub(publicB)) throw new Error('second arg must be public key') + const b = Point.fromHex(publicB) // check for being on-curve + return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) + } + + // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. + // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. + // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. + // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors + const bits2int = + CURVE.bits2int || + function (bytes: Uint8Array): bigint { + // Our custom check "just in case" + if (bytes.length > 8192) throw new Error('input is too large') + // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) + // for some cases, since bytes.length * 8 is not actual bitLength. + const num = ut.bytesToNumberBE(bytes) // check for == u8 done here + const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits + return delta > 0 ? num >> BigInt(delta) : num + } + const bits2int_modN = + CURVE.bits2int_modN || + function (bytes: Uint8Array): bigint { + return modN(bits2int(bytes)) // can't use bytesToNumberBE here + } + // NOTE: pads output with zero as per spec + const ORDER_MASK = ut.bitMask(CURVE.nBitLength) + /** + * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. + */ + function int2octets(num: bigint): Uint8Array { + ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) + // works with order, can have different size than numToField! + return ut.numberToBytesBE(num, CURVE.nByteLength) + } + + // Steps A, D of RFC6979 3.2 + // Creates RFC6979 seed; converts msg/privKey to numbers. + // Used only in sign, not in verify. + // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, + // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 + function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) { + if (['recovered', 'canonical'].some((k) => k in opts)) + throw new Error('sign() legacy options not supported') + const { hash, randomBytes } = CURVE + let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default + if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash + msgHash = ensureBytes('msgHash', msgHash) + validateSigVerOpts(opts) + if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) + + // We can't later call bits2octets, since nested bits2int is broken for curves + // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. + // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) + const h1int = bits2int_modN(msgHash) + const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint + const seedArgs = [int2octets(d), int2octets(h1int)] + // extraEntropy. RFC6979 3.6: additional k' (optional). + if (ent != null && ent !== false) { + // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is + seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes + } + const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 + const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! + // Converts signature params into point w r/s, checks result for validity. + function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined { + // RFC 6979 Section 3.2, step 3: k = bits2int(T) + const k = bits2int(kBytes) // Cannot use fields methods, since it is group element + if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N + const ik = invN(k) // k^-1 mod n + const q = Point.BASE.multiply(k).toAffine() // q = Gk + const r = modN(q.x) // r = q.x mod n + if (r === _0n) return + // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to + // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: + // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT + const s = modN(ik * modN(m + r * d)) // Not using blinding here + if (s === _0n) return + let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) + let normS = s + if (lowS && isBiggerThanHalfOrder(s)) { + normS = normalizeS(s) // if lowS was passed, ensure s is always + recovery ^= 1 // // in the bottom half of N + } + return new Signature(r, normS, recovery) as RecoveredSignature // use normS, not s + } + return { seed, k2sig } + } + const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false } + const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false } + + /** + * Signs message hash with a private key. + * ``` + * sign(m, d, k) where + * (x, y) = G × k + * r = x mod n + * s = (m + dr)/k mod n + * ``` + * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. + * @param privKey private key + * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. + * @returns signature with recovery param + */ + function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature { + const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. + const C = CURVE + const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) + return drbg(seed, k2sig) // Steps B, C, D, E, F, G + } + + // Enable precomputes. Slows down first publicKey computation by 20ms. + Point.BASE._setWindowSize(8) + // utils.precompute(8, ProjectivePoint.BASE) + + /** + * Verifies a signature against message hash and public key. + * Rejects lowS signatures by default: to override, + * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: + * + * ``` + * verify(r, s, h, P) where + * U1 = hs^-1 mod n + * U2 = rs^-1 mod n + * R = U1⋅G - U2⋅P + * mod(R.x, n) == r + * ``` + */ + function verify( + signature: Hex | SignatureLike, + msgHash: Hex, + publicKey: Hex, + opts = defaultVerOpts, + ): boolean { + const sg = signature + msgHash = ensureBytes('msgHash', msgHash) + publicKey = ensureBytes('publicKey', publicKey) + const { lowS, prehash, format } = opts + + // Verify opts, deduce signature format + validateSigVerOpts(opts) + if ('strict' in opts) throw new Error('options.strict was renamed to lowS') + if (format !== undefined && format !== 'compact' && format !== 'der') + throw new Error('format must be compact or der') + const isHex = typeof sg === 'string' || ut.isBytes(sg) + const isObj = + !isHex && + !format && + typeof sg === 'object' && + sg !== null && + typeof sg.r === 'bigint' && + typeof sg.s === 'bigint' + if (!isHex && !isObj) + throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') + + let _sig: Signature | undefined = undefined + let P: ProjPointType + try { + if (isObj) _sig = new Signature(sg.r, sg.s) + if (isHex) { + // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). + // Since DER can also be 2*nByteLength bytes, we check for it first. + try { + if (format !== 'compact') _sig = Signature.fromDER(sg) + } catch (derError) { + if (!(derError instanceof DER.Err)) throw derError + } + if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) + } + P = Point.fromHex(publicKey) + } catch (error) { + return false + } + if (!_sig) return false + if (lowS && _sig.hasHighS()) return false + if (prehash) msgHash = CURVE.hash(msgHash) + const { r, s } = _sig + const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element + const is = invN(s) // s^-1 + const u1 = modN(h * is) // u1 = hs^-1 mod n + const u2 = modN(r * is) // u2 = rs^-1 mod n + const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P + if (!R) return false + const v = modN(R.x) + return v === r + } + return { + CURVE, + getPublicKey, + getSharedSecret, + sign, + verify, + ProjectivePoint: Point, + Signature, + utils, + } +} + +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export function SWUFpSqrtRatio( + Fp: IField, + Z: T, +): (u: T, v: T) => { isValid: boolean; value: T } { + // Generic implementation + const q = Fp.ORDER + let l = _0n + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n + const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. + // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. + // 2n ** c1 == 2n << (c1-1) + const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) + const _2n_pow_c1 = _2n_pow_c1_1 * _2n + const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 + const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) + let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { + let tv1 = c6 // 1. tv1 = c6 + let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 + let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 + tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v + let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 + tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 + tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 + tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v + tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u + let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 + tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 + let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 + tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 + tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) + // 17. for i in (c1, c1 - 1, ..., 2): + for (let i = c1; i > _1n; i--) { + let tv5 = i - _2n // 18. tv5 = i - 2 + tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 + let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 + const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 + tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 + tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 + tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) + } + return { isValid: isQR, value: tv3 } + } + if (Fp.ORDER % _4n === _3n) { + // sqrt_ratio_3mod4(u, v) + const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) + sqrtRatio = (u: T, v: T) => { + let tv1 = Fp.sqr(v) // 1. tv1 = v^2 + const tv2 = Fp.mul(u, v) // 2. tv2 = u * v + tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 + let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 + y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 + const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 + const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v + const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u + let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) + return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 + } + } + // No curves uses that + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 + return sqrtRatio +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export function mapToCurveSimpleSWU( + Fp: IField, + opts: { + A: T + B: T + Z: T + }, +): (u: T) => { x: T; y: T } { + validateField(Fp) + if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) + throw new Error('mapToCurveSimpleSWU: invalid opts') + const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) + if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') + // Input: u, an element of F. + // Output: (x, y), a point on E. + return (u: T): { x: T; y: T } => { + // prettier-ignore + let tv1, tv2, tv3, tv4, tv5, tv6, x, y + tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 + tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 + tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 + tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 + tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 + tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) + tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 + tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 + tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 + tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 + tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 + tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 + tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 + tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 + tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 + x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 + const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 + y = Fp.mul(y, value) // 20. y = y * y1 + x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) + y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) + const e1 = Fp.isOdd!(u) === Fp.isOdd!(y) // 23. e1 = sgn0(u) == sgn0(y) + y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) + x = Fp.div(x, tv4) // 25. x = x / tv4 + return { x, y } + } +} diff --git a/packages/noble-curves/src/bls12-381.ts b/packages/noble-curves/src/bls12-381.ts new file mode 100644 index 00000000000..422a2906ef0 --- /dev/null +++ b/packages/noble-curves/src/bls12-381.ts @@ -0,0 +1,774 @@ +/** + * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: + * * Construct zk-SNARKs at the ~120-bit security + * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: + * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr + * + * ### Summary + * 1. BLS Relies on Bilinear Pairing (expensive) + * 2. Private Keys: 32 bytes + * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. + * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. + * - The signature is a point on the G2 subgroup, which is defined over a finite field + * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the + * complex numbers). + * - We also support reversed 96-byte pubkeys & 48-byte short signatures. + * 5. The 12 stands for the Embedding degree. + * + * ### Formulas + * - `P = pk x G` - public keys + * - `S = pk x H(m)` - signing + * - `e(P, H(m)) == e(G, S)` - verification using pairings + * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation + * + * ### Compatibility and notes + * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. + * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. + * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". + * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) + * 4. Compatible with specs: + * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), + * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), + * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). + * + * ### Params + * To verify curve parameters, see + * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). + * Basic math is done over finite fields over p. + * More complicated math is done over polynominal extension fields. + * To simplify calculations in Fp12, we construct extension tower: + * + * Embedding degree (k): 12 + * Seed (X): -15132376222941642752 + * Fr: (x⁴-x²+1) + * Fp: ((x-1)² ⋅ r(x)/3+x) + * (E/Fp): Y²=X³+4 + * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) + * Ate loop size: X + * + * ### Towers + * - Fp₁₂ = Fp₆² => Fp₂³ + * - Fp(u) / (u² - β) where β = -1 + * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 + * - Fp₆(w) / (w² - γ) where γ = v + * - Fp²[u] = Fp/u²+1 + * - Fp⁶[v] = Fp²/v³-1-u + * - Fp¹²[w] = Fp⁶/w²-v + * + * @todo construct bls & bn fp/fr from seed. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFn, bls } from './abstract/bls.js' +// Types +import { isogenyMap } from './abstract/hash-to-curve.js' +import * as mod from './abstract/modular.js' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js' +import { psiFrobenius, tower12 } from './abstract/tower.js' +import { + type Hex, + bitGet, + bitLen, + bytesToHex, + bytesToNumberBE, + concatBytes as concatB, + ensureBytes, + numberToBytesBE, +} from './abstract/utils.js' +import { + type AffinePoint, + type ProjPointType, + mapToCurveSimpleSWU, +} from './abstract/weierstrass.js' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! +const BLS_X = BigInt('0xd201000000010000') +const BLS_X_LEN = bitLen(BLS_X) + +// CURVE FIELDS +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + // Order of Fp + ORDER: BigInt( + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', + ), + // Finite extension field over irreducible polynominal. + // Fp(u) / (u² - β) where β = -1 + FP2_NONRESIDUE: [_1n, _1n], + Fp2mulByB: ({ c0, c1 }) => { + const t0 = Fp.mul(c0, _4n) // 4 * c0 + const t1 = Fp.mul(c1, _4n) // 4 * c1 + // (T0-T1) + (T0+T1)*i + return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } + }, + // Fp12 + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const x = BLS_X + // this^(q⁶) / this + const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) + // t0^(q²) * t0 + const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) + const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) + const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) + const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) + const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) + const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) + const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) + const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) + const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) + const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) + const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) + // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 + return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) + }, +}) + +// Finite field over r. +// This particular field is not used anywhere in bls12-381, but it is still useful. +const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) + +// END OF CURVE FIELDS + +// HashToCurve + +// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 +const isogenyMapG2 = isogenyMap( + Fp2, + [ + // xNum + [ + [ + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + ], + [ + '0x0', + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', + ], + [ + '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', + '0x0', + ], + ], + // xDen + [ + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', + ], + [ + '0xc', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', + ], + ['0x1', '0x0'], // LAST 1 + ], + // yNum + [ + [ + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + ], + [ + '0x0', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', + ], + [ + '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', + '0x0', + ], + ], + // yDen + [ + [ + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + ], + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', + ], + [ + '0x12', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', + ], + ['0x1', '0x0'], // LAST 1 + ], + ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))) as [Fp2[], Fp2[], Fp2[], Fp2[]], +) +// 11-isogeny map from E' to E +const isogenyMapG1 = isogenyMap( + Fp, + [ + // xNum + [ + '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', + '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', + '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', + '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', + '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', + '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', + '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', + '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', + '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', + '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', + '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', + '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', + ], + // xDen + [ + '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', + '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', + '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', + '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', + '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', + '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', + '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', + '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', + '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', + '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', + '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', + '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', + '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', + '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', + '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', + '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', + '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', + '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', + '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', + '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', + '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', + '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', + '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', + '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', + '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', + ], + // yDen + [ + '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', + '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', + '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', + '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', + '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', + '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', + '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', + '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', + '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', + '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', + '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', + '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', + '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', + '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', + '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]], +) + +// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i +const G2_SWU = mapToCurveSimpleSWU(Fp2, { + A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I + B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) + Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) +}) +// Optimized SWU Map - Fp to G1 +const G1_SWU = mapToCurveSimpleSWU(Fp, { + A: Fp.create( + BigInt( + '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', + ), + ), + B: Fp.create( + BigInt( + '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', + ), + ), + Z: Fp.create(BigInt(11)), +}) + +// Endomorphisms (for fast cofactor clearing) +// Ψ(P) endomorphism +const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) + +// Default hash_to_field options are for hash to G2. +// +// Parameter definitions are in section 5.3 of the spec unless otherwise noted. +// Parameter values come from section 8.8.2 of the spec. +// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 +// +// Base field F is GF(p^m) +// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +// m = 2 (or 1 for G1 see section 8.8.1) +// k = 128 +const htfDefaults = Object.freeze({ + // DST: a domain separation tag + // defined in section 2.2.5 + // Use utils.getDSTLabel(), utils.setDSTLabel(value) + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + // p: the characteristic of F + // where F is a finite field of characteristic p and order q = p^m + p: Fp.ORDER, + // m: the extension degree of F, m >= 1 + // where F is a finite field of characteristic p and order q = p^m + m: 2, + // k: the target security level for the suite in bits + // defined in section 5.1 + k: 128, + // option to use a message that has already been processed by + // expand_message_xmd + expand: 'xmd', + // Hash functions for: expand_message_xmd is appropriate for use with a + // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. + // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 + hash: sha256, +} as const) + +// Encoding utils +// Point on G1 curve: (x, y) + +// Compressed point of infinity +const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits + +function parseMask(bytes: Uint8Array) { + // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. + bytes = bytes.slice() + const mask = bytes[0] & 0b1110_0000 + const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) + const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) + const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) + bytes[0] &= 0b0001_1111 // clear mask (zero first 3 bits) + return { compressed, infinity, sort, value: bytes } +} + +function setMask( + bytes: Uint8Array, + mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }, +) { + if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask') + if (mask.compressed) bytes[0] |= 0b1000_0000 + if (mask.infinity) bytes[0] |= 0b0100_0000 + if (mask.sort) bytes[0] |= 0b0010_0000 + return bytes +} + +function signatureG1ToRawBytes(point: ProjPointType) { + point.assertValidity() + const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) + const { x, y } = point.toAffine() + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) +} + +function signatureG2ToRawBytes(point: ProjPointType) { + // NOTE: by some reasons it was missed in bls12-381, looks like bug + point.assertValidity() + const len = Fp.BYTES + if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) + return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const { x, y } = point.toAffine() + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + const tmp = y1 > _0n ? y1 * _2n : y0 * _2n + const sort = Boolean((tmp / Fp.ORDER) & _1n) + const z2 = x0 + return concatB( + setMask(numberToBytesBE(x1, len), { sort, compressed: true }), + numberToBytesBE(z2, len), + ) +} + +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export const bls12_381: CurveFn = bls({ + // Fields + fields: { + Fp, + Fp2, + Fp6, + Fp12, + Fr, + }, + // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where + // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 + G1: { + Fp, + // cofactor; (z - 1)²/3 + h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), + // generator's coordinates + // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 + // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 + Gx: BigInt( + '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', + ), + Gy: BigInt( + '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', + ), + a: Fp.ZERO, + b: _4n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, point): boolean => { + // φ endomorphism + const cubicRootOfUnityModP = BigInt( + '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', + ) + const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) + + // todo: unroll + const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P + const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P + return u2P.equals(phi) + + // https://eprint.iacr.org/2019/814.pdf + // (z² − 1)/3 + // const c1 = BigInt('0x396c8c005555e1560000000055555555'); + // const P = this; + // const S = P.sigma(); + // const Q = S.double(); + // const S2 = S.sigma(); + // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O + // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); + // const C = left.subtract(S2); + // return C.isZero(); + }, + // Clear cofactor of G1 + // https://eprint.iacr.org/2019/403 + clearCofactor: (_c, point) => { + // return this.multiplyUnsafe(CURVE.h); + return point.multiplyUnsafe(BLS_X).add(point) // x*P + P + }, + mapToCurve: (scalars: bigint[]) => { + const { x, y } = G1_SWU(Fp.create(scalars[0])) + return isogenyMapG1(x, y) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if (value.length === 48 && compressed) { + // TODO: Fp.bytes + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + const x = Fp.create(compressedValue & Fp.MASK) + if (infinity) { + if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') + return { x: _0n, y: _0n } + } + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) + return { x: Fp.create(x), y: Fp.create(y) } + } else if (value.length === 96 && !compressed) { + // Check if the infinity flag is set + const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) + const y = bytesToNumberBE(value.subarray(Fp.BYTES)) + if (infinity) { + if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') + return bls12_381.G1.ProjectivePoint.ZERO.toAffine() + } + return { x: Fp.create(x), y: Fp.create(y) } + } else { + throw new Error('invalid point G1, expected 48/96 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) + } else { + if (isZero) { + // 2x PUBLIC_KEY_LENGTH + const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) + return x + } else { + return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) + } + } + }, + ShortSignature: { + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + if (infinity) return bls12_381.G1.ProjectivePoint.ZERO + const x = Fp.create(compressedValue & Fp.MASK) + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + const aflag = BigInt(sort) + if ((y * _2n) / P !== aflag) y = Fp.neg(y) + const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG1ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG1ToRawBytes(point)) + }, + }, + }, + // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), + // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where + // G² - 1 + // h2q + G2: { + Fp: Fp2, + // cofactor + h: BigInt( + '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', + ), + Gx: Fp2.fromBigTuple([ + BigInt( + '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', + ), + BigInt( + '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', + ), + ]), + // y = + // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, + // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + Gy: Fp2.fromBigTuple([ + BigInt( + '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', + ), + BigInt( + '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', + ), + ]), + a: Fp2.ZERO, + b: Fp2.fromBigTuple([_4n, _4n]), + hEff: BigInt( + '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', + ), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: (scalars: bigint[]) => { + const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) + return isogenyMapG2(x, y) + }, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, P): boolean => { + return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) + // Older version: https://eprint.iacr.org/2019/814.pdf + // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O + // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); + }, + // Maps the point into the prime-order subgroup G2. + // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 + // https://eprint.iacr.org/2017/419.pdf + // prettier-ignore + clearCofactor: (c, P) => { + const x = BLS_X + let t1 = P.multiplyUnsafe(x).negate() // [-x]P + let t2 = G2psi(c, P) // Ψ(P) + let t3 = P.double() // 2P + t3 = G2psi2(c, t3) // Ψ²(2P) + t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) + t2 = t1.add(t2) // [-x]P + Ψ(P) + t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) + t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P + const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P + return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if ( + (!compressed && !infinity && sort) || // 00100000 + (!compressed && infinity && sort) || // 01100000 + (sort && infinity && compressed) // 11100000 + ) { + throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000)) + } + const L = Fp.BYTES + const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to)) + if (value.length === 96 && compressed) { + const b = bls12_381.params.G2b + const P = Fp.ORDER + if (infinity) { + // check that all bytes are 0 + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid compressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x_1 = slc(value, 0, L) + const x_0 = slc(value, L, 2 * L) + const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) + const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b + let y = Fp2.sqrt(right) + const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n + y = sort && Y_bit > 0 ? y : Fp2.neg(y) + return { x, y } + } else if (value.length === 192 && !compressed) { + if (infinity) { + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid uncompressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x1 = slc(value, 0, L) + const x0 = slc(value, L, 2 * L) + const y1 = slc(value, 2 * L, 3 * L) + const y0 = slc(value, 3 * L, 4 * L) + return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } + } else { + throw new Error('invalid point G2, expected 96/192 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const { BYTES: len, ORDER: P } = Fp + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) + return concatB( + setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), + numberToBytesBE(x.c0, len), + ) + } else { + if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + return concatB( + numberToBytesBE(x1, len), + numberToBytesBE(x0, len), + numberToBytesBE(y1, len), + numberToBytesBE(y0, len), + ) + } + }, + Signature: { + // TODO: Optimize, it's very slow because of sqrt. + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) + const P = Fp.ORDER + const half = value.length / 2 + if (half !== 48 && half !== 96) + throw new Error('invalid compressed signature length, must be 96 or 192') + const z1 = bytesToNumberBE(value.slice(0, half)) + const z2 = bytesToNumberBE(value.slice(half)) + // Indicates the infinity point + if (infinity) return bls12_381.G2.ProjectivePoint.ZERO + const x1 = Fp.create(z1 & Fp.MASK) + const x2 = Fp.create(z2) + const x = Fp2.create({ c0: x2, c1: x1 }) + const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 + // The slow part + let y = Fp2.sqrt(y2) + if (!y) throw new Error('Failed to find a square root') + + // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 + // If y1 happens to be zero, then use the bit of y0 + const { re: y0, im: y1 } = Fp2.reim(y) + const aflag1 = BigInt(sort) + const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 + const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 + if (isGreater || isZero) y = Fp2.neg(y) + const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG2ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG2ToRawBytes(point)) + }, + }, + }, + params: { + ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 + r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves + xNegative: true, + twistType: 'multiplicative', + }, + htfDefaults, + hash: sha256, + randomBytes, +}) diff --git a/packages/noble-curves/src/bn254.ts b/packages/noble-curves/src/bn254.ts new file mode 100644 index 00000000000..54bf54022c9 --- /dev/null +++ b/packages/noble-curves/src/bn254.ts @@ -0,0 +1,254 @@ +/** + * bn254, previously known as alt_bn_128, when it had 128-bit security. + +Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, +so the naming has been adjusted to its prime bit count: +https://hal.science/hal-01534101/file/main.pdf. +Compatible with EIP-196 and EIP-197. + +There are huge compatibility issues in the ecosystem: + +1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". +2. libff has bn128, but it's a different curve with different G2: + https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 +3. halo2curves bn256 is also incompatible and returns different outputs + +The goal of our implementation is to support "Ethereum" variant of the curve, +because it at least has specs: + +- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM +- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings +- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 +- The existing implementations are bad. Some are deprecated: + - https://github.com/paritytech/bn (old version) + - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) + - https://github.com/zcash-hackworks/bn + - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs +- Python implementations use different towers and produce different Fp12 outputs: + - https://github.com/ethereum/py_pairing + - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py +- Points are encoded differently in different implementations + +### Params +Seed (X): 4965661367192848881 +Fr: (36x⁴+36x³+18x²+6x+1) +Fp: (36x⁴+36x³+24x²+6x+1) +(E / Fp ): Y² = X³+3 +(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) +Ate loop size: 6x+2 + +### Towers +- Fp²[u] = Fp/u²+1 +- Fp⁶[v] = Fp²/v³-9-u +- Fp¹²[w] = Fp⁶/w²-v + + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.js' +import { + type CurveFn as BLSCurveFn, + type PostPrecomputeFn, + type PostPrecomputePointAddFn, + bls, +} from './abstract/bls.js' +import { Field } from './abstract/modular.js' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js' +import { psiFrobenius, tower12 } from './abstract/tower.js' +import { bitGet, bitLen, notImplemented } from './abstract/utils.js' +import { type CurveFn, weierstrass } from './abstract/weierstrass.js' +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +const _6n = BigInt(6) + +const BN_X = BigInt('4965661367192848881') +const BN_X_LEN = bitLen(BN_X) +const SIX_X_SQUARED = _6n * BN_X ** _2n + +// Finite field over r. It's for convenience and is not used in the code below. +const Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) +// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) +const Fp2B = { + c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), + c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), +} + +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), + FP2_NONRESIDUE: [BigInt(9), _1n], + Fp2mulByB: (num) => Fp2.mul(num, Fp2B), + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BN_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) + const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) + const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) + const y1 = Fp12._cyclotomicSquare(powMinusX(r)) + const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) + const y4 = powMinusX(y2) + const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) + const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) + const y9 = Fp12.mul(y8, y1) + return Fp12.mul( + Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), + Fp12.mul( + Fp12.frobeniusMap(y8, 2), + Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), + ), + ) + }, +}) + +// END OF CURVE FIELDS +const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) + +/* +No hashToCurve for now (and signatures): + +- RFC 9380 doesn't mention bn254 and doesn't provide test vectors +- Overall seems like nobody is using BLS signatures on top of bn254 +- Seems like it can utilize SVDW, which is not implemented yet +*/ +const htfDefaults = Object.freeze({ + // DST: a domain separation tag defined in section 2.2.5 + DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + p: Fp.ORDER, + m: 2, + k: 128, + expand: 'xmd', + hash: sha256, +} as const) + +export const _postPrecompute: PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => { + const q = psi(Qx, Qy) + ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) + const q2 = psi(q[0], q[1]) + pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) +} + +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export const bn254: BLSCurveFn = bls({ + // Fields + fields: { Fp, Fp2, Fp6, Fp12, Fr }, + G1: { + Fp, + h: BigInt(1), + Gx: BigInt(1), + Gy: BigInt(2), + a: Fp.ZERO, + b: _3n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + ShortSignature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + G2: { + Fp: Fp2, + // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 + h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + Gx: Fp2.fromBigTuple([ + BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), + BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), + ]), + Gy: Fp2.fromBigTuple([ + BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), + BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), + ]), + a: Fp2.ZERO, + b: Fp2B, + hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + Signature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + params: { + ateLoopSize: BN_X * _6n + _2n, + r: Fr.ORDER, + xNegative: false, + twistType: 'divisive', + }, + htfDefaults, + hash: sha256, + randomBytes, + + postPrecompute: _postPrecompute, +}) + +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + */ +export const bn254_weierstrass: CurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(3), + Fp, + n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), + Gx: BigInt(1), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/noble-curves/src/ed25519.ts b/packages/noble-curves/src/ed25519.ts new file mode 100644 index 00000000000..f058758c38c --- /dev/null +++ b/packages/noble-curves/src/ed25519.ts @@ -0,0 +1,544 @@ +/** + * ed25519 Twisted Edwards curve with following addons: + * - X25519 ECDH + * - Ristretto cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha512' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { type AffinePoint, type Group, pippenger } from './abstract/curve.js' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' +import { + type HTFMethod, + createHasher, + expand_message_xmd, + type htfBasicOpts, +} from './abstract/hash-to-curve.js' +import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.js' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.js' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.js' + +const ED25519_P = BigInt( + '57896044618658097711785492504343953926634992332820282019728792003956564819949', +) +// √(-1) aka √(a) aka 2^((p-1)/4) +const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( + '19681161376707505956807079304988542015446066515923890162744021073123829784752', +) + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// prettier-ignore +const _5n = BigInt(5), + _8n = BigInt(8) + +function ed25519_pow_2_252_3(x: bigint) { + // prettier-ignore + const _10n = BigInt(10), + _20n = BigInt(20), + _40n = BigInt(40), + _80n = BigInt(80) + const P = ED25519_P + const x2 = (x * x) % P + const b2 = (x2 * x) % P // x^3, 11 + const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 + const b5 = (pow2(b4, _1n, P) * x) % P // x^31 + const b10 = (pow2(b5, _5n, P) * b5) % P + const b20 = (pow2(b10, _10n, P) * b10) % P + const b40 = (pow2(b20, _20n, P) * b20) % P + const b80 = (pow2(b40, _40n, P) * b40) % P + const b160 = (pow2(b80, _80n, P) * b80) % P + const b240 = (pow2(b160, _80n, P) * b80) % P + const b250 = (pow2(b240, _10n, P) * b10) % P + const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P + // ^ To pow to (p+3)/8, multiply it by x. + return { pow_p_5_8, b2 } +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, + // set the three least significant bits of the first byte + bytes[0] &= 248 // 0b1111_1000 + // and the most significant bit of the last to zero, + bytes[31] &= 127 // 0b0111_1111 + // set the second most significant bit of the last byte to 1 + bytes[31] |= 64 // 0b0100_0000 + return bytes +} + +// sqrt(u/v) +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ED25519_P + const v3 = mod(v * v * v, P) // v³ + const v7 = mod(v3 * v3 * v, P) // v⁷ + // (p+3)/8 and (p-5)/8 + const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 + let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 + const vx2 = mod(v * x * x, P) // vx² + const root1 = x // First root candidate + const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate + const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root + const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) + const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) + if (useRoot1) x = root1 + if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time + if (isNegativeLE(x, P)) x = mod(-x, P) + return { isValid: useRoot1 || useRoot2, value: x } +} + +// Just in case +export const ED25519_TORSION_SUBGROUP: string[] = [ + '0100000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', + '0000000000000000000000000000000000000000000000000000000000000080', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', + '0000000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', +] + +const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() + +const ed25519Defaults = /* @__PURE__ */ (() => + ({ + // Param: a + a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster + // d is equal to -121665/121666 over finite field. + // Negative number is P - number, and division is invert(number, P) + d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), + // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n + Fp, + // Subgroup order: how many points curve has + // 2n**252n + 27742317777372353535851937790883648493n; + n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), + // Cofactor + h: _8n, + // Base point (x, y) aka generator point + Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), + Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), + hash: sha512, + randomBytes, + adjustScalarBytes, + // dom2 + // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. + // Constant-time, u/√v + uvRatio, + }) as const)() + +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() + +function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) { + if (ctx.length > 255) throw new Error('Context is too big') + return concatBytes( + utf8ToBytes('SigEd25519 no Ed25519 collisions'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) +} + +export const ed25519ctx: CurveFn = /* @__PURE__ */ (() => + twistedEdwards({ + ...ed25519Defaults, + domain: ed25519_domain, + }))() +export const ed25519ph: CurveFn = /* @__PURE__ */ (() => + twistedEdwards( + Object.assign({}, ed25519Defaults, { + domain: ed25519_domain, + prehash: sha512, + }), + ))() + +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export const x25519: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x: bigint): bigint => { + const P = ED25519_P + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) + return mod(pow2(pow_p_5_8, _3n, P) * b2, P) + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array { + const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) +} +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated + +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array { + const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) + return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) +} + +// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) +// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since +// SageMath returns different root first and everything falls apart + +const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic +const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 +const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) + +// prettier-ignore +function map_to_curve_elligator2_curve25519(u: bigint) { + const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic + const ELL2_J = BigInt(486662) + + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 + let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not + let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) + let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 + tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 + tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 + tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 + tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 + let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) + y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) + let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 + tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 + tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd + let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 + let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt + let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd + let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u + y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 + let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 + let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) + tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 + tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 + let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt + tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd + let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 + let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) +} + +const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 +function map_to_curve_elligator2_edwards25519(u: bigint) { + const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = + // map_to_curve_elligator2_curve25519(u) + let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd + xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 + let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM + let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd + let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) + let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd + let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 + xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) + xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) + yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) + yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) + + const inv = Fp.invertBatch([xd, yd]) // batch division + return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) +} + +const htf = /* @__PURE__ */ (() => + createHasher( + ed25519.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512, + }, + ))() +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() + +function assertRstPoint(other: unknown) { + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') +} + +// √(-1) aka √(a) aka 2^((p-1)/4) +const SQRT_M1 = ED25519_SQRT_M1 +// √(ad - 1) +const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( + '25063068953384623474111414158702152701244531502492656460079210482610430750235', +) +// 1 / √(a-d) +const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( + '54469307008909316920995813868745141605393597292927456921205312896311721017578', +) +// 1-d² +const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( + '1159843021668779879193775521855586647937357759715417654439879720876111806838', +) +// (d-1)² +const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( + '40440834346308536858101042469323190826248399146238708352240133220865137265952', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_255B = /* @__PURE__ */ BigInt( + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes255ToNumberLE = (bytes: Uint8Array) => + ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Ristretto +// https://ristretto.group/formulas/elligator.html +function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { + const { d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const r = mod(SQRT_M1 * r0 * r0) // 1 + const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 + let c = BigInt(-1) // 3 + const D = mod((c - d * r) * mod(r + d)) // 4 + let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 + let s_ = mod(s * r0) // 6 + if (!isNegativeLE(s_, P)) s_ = mod(-s_) + if (!Ns_D_is_sq) s = s_ // 7 + if (!Ns_D_is_sq) c = r // 8 + const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 + const s2 = s * s + const W0 = mod((s + s) * D) // 10 + const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 + const W2 = mod(_1n - s2) // 12 + const W3 = mod(_1n + s2) // 13 + return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class RistPoint implements Group { + static BASE: RistPoint + static ZERO: RistPoint + // Private property to discourage combining ExtendedPoint + RistrettoPoint + // Always use Ristretto encoding/decoding instead. + constructor(private readonly ep: ExtendedPoint) {} + + static fromAffine(ap: AffinePoint): RistPoint { + return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHash', hex, 64) + const r1 = bytes255ToNumberLE(hex.slice(0, 32)) + const R1 = calcElligatorRistrettoMap(r1) + const r2 = bytes255ToNumberLE(hex.slice(32, 64)) + const R2 = calcElligatorRistrettoMap(r2) + return new RistPoint(R1.add(R2)) + } + + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHex', hex, 32) + const { a, d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' + const s = bytes255ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 3. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) + const s2 = mod(s * s) + const u1 = mod(_1n + a * s2) // 4 (a is -1) + const u2 = mod(_1n - a * s2) // 5 + const u1_2 = mod(u1 * u1) + const u2_2 = mod(u2 * u2) + const v = mod(a * d * u1_2 - u2_2) // 6 + const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 + const Dx = mod(I * u2) // 8 + const Dy = mod(I * Dx * v) // 9 + let x = mod((s + s) * Dx) // 10 + if (isNegativeLE(x, P)) x = mod(-x) // 10 + const y = mod(u1 * Dy) // 11 + const t = mod(x * y) // 12 + if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) + return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: RistPoint[], scalars: bigint[]): RistPoint { + const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) + return pippenger(RistPoint, Fn, points, scalars) + } + + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: y, ez: z, et: t } = this.ep + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const u1 = mod(mod(z + y) * mod(z - y)) // 1 + const u2 = mod(x * y) // 2 + // Square root always exists + const u2sq = mod(u2 * u2) + const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 + const D1 = mod(invsqrt * u1) // 4 + const D2 = mod(invsqrt * u2) // 5 + const zInv = mod(D1 * D2 * t) // 6 + let D: bigint // 7 + if (isNegativeLE(t * zInv, P)) { + let _x = mod(y * SQRT_M1) + let _y = mod(x * SQRT_M1) + x = _x + y = _y + D = mod(D1 * INVSQRT_A_MINUS_D) + } else { + D = D2 // 8 + } + if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 + let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) + if (isNegativeLE(s, P)) s = mod(-s) + return numberToBytesLE(s, 32) // 11 + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + equals(other: RistPoint): boolean { + assertRstPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed25519.CURVE.Fp.create + // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) + const one = mod(X1 * Y2) === mod(Y1 * X2) + const two = mod(Y1 * Y2) === mod(X1 * X2) + return one || two + } + + add(other: RistPoint): RistPoint { + assertRstPoint(other) + return new RistPoint(this.ep.add(other.ep)) + } + + subtract(other: RistPoint): RistPoint { + assertRstPoint(other) + return new RistPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): RistPoint { + return new RistPoint(this.ep.double()) + } + + negate(): RistPoint { + return new RistPoint(this.ep.negate()) + } +} +export const RistrettoPoint: typeof RistPoint = /* @__PURE__ */ (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) + return RistPoint +})() + +// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B +export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts): RistPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) + const P = RistPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint = + hashToRistretto255 // legacy diff --git a/packages/noble-curves/src/ed448.ts b/packages/noble-curves/src/ed448.ts new file mode 100644 index 00000000000..2b432735d0b --- /dev/null +++ b/packages/noble-curves/src/ed448.ts @@ -0,0 +1,514 @@ +/** + * Edwards448 (not Ed448-Goldilocks) curve with following addons: + * - X448 ECDH + * - Decaf cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { shake256 } from '@noble/hashes/sha3' +import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' +import type { AffinePoint, Group } from './abstract/curve.js' +import { pippenger } from './abstract/curve.js' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' +import { + type HTFMethod, + createHasher, + expand_message_xof, + type htfBasicOpts, +} from './abstract/hash-to-curve.js' +import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.js' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.js' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.js' + +const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) +const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) +const ed448P = BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', +) + +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4), + _11n = BigInt(11) +// prettier-ignore +const _22n = BigInt(22), + _44n = BigInt(44), + _88n = BigInt(88), + _223n = BigInt(223) + +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +// Used for efficient square root calculation. +// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] +function ed448_pow_Pminus3div4(x: bigint): bigint { + const P = ed448P + const b2 = (x * x * x) % P + const b3 = (b2 * b2 * x) % P + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b222 = (pow2(b220, _2n, P) * b2) % P + const b223 = (pow2(b222, _1n, P) * x) % P + return (pow2(b223, _223n, P) * b222) % P +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most + // significant bit of the last byte to 1. + bytes[0] &= 252 // 0b11111100 + // and the most significant bit of the last byte to 1. + bytes[55] |= 128 // 0b10000000 + // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) + bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) + return bytes +} + +// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. +// Uses algo from RFC8032 5.1.3. +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ed448P + // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 + // To compute the square root of (u/v), the first step is to compute the + // candidate root x = (u/v)^((p+1)/4). This can be done using the + // following trick, to use a single modular powering for both the + // inversion of v and the square root: + // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) + const u2v = mod(u * u * v, P) // u²v + const u3v = mod(u2v * u, P) // u³v + const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ + const root = ed448_pow_Pminus3div4(u5v3) + const x = mod(u3v * root, P) + // Verify that root is exists + const x2 = mod(x * x, P) // x² + // If vx² = u, the recovered x-coordinate is x. Otherwise, no + // square root exists, and the decoding fails. + return { isValid: mod(x2 * v, P) === u, value: x } +} + +const Fp = Field(ed448P, 456, true) + +const ED448_DEF = { + // Param: a + a: BigInt(1), + // -39081. Negative number is P - number + d: BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', + ), + // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n + Fp, + // Subgroup order: how many points curve has; + // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n + n: BigInt( + '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', + ), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + nBitLength: 456, + // Cofactor + h: BigInt(4), + // Base point (x, y) aka generator point + Gx: BigInt( + '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', + ), + Gy: BigInt( + '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', + ), + // SHAKE256(dom4(phflag,context)||x, 114) + hash: shake256_114, + randomBytes, + adjustScalarBytes, + // dom4 + domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) + return concatBytes( + utf8ToBytes('SigEd448'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) + }, + uvRatio, +} as const + +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export const ed448: CurveFn = /* @__PURE__ */ twistedEdwards(ED448_DEF) +// NOTE: there is no ed448ctx, since ed448 supports ctx by default +export const ed448ph: CurveFn = /* @__PURE__ */ twistedEdwards({ + ...ED448_DEF, + prehash: shake256_64, +}) + +/** + * ECDH using curve448 aka x448. + */ +export const x448: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + a: BigInt(156326), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + montgomeryBits: 448, + nByteLength: 56, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x: bigint): bigint => { + const P = ed448P + const Pminus3div4 = ed448_pow_Pminus3div4(x) + const Pminus3 = pow2(Pminus3div4, BigInt(2), P) + return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array { + const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) +} + +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated +// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version + +// Hash To Curve Elligator2 Map +const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic +const ELL2_J = BigInt(156326) + +function map_to_curve_elligator2_curve448(u: bigint) { + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 + tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 + let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 + let x1n = Fp.neg(ELL2_J) // 5. x1n = -J + let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 + tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd + tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 + let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) + y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) + let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd + let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u + y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) + tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 + let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) + return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) +} + +function map_to_curve_elligator2_edwards448(u: bigint) { + let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) + let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 + let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 + let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 + let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 + let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 + let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 + let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 + xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 + xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd + xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn + xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 + tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 + tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 + let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 + let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 + tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 + let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 + tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn + let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 + let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 + yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 + yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 + tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 + tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 + tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd + tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 + tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 + let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 + tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 + yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 + tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd + let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 + xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) + xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) + yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) + yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) + + const inv = Fp.invertBatch([xEd, yEd]) // batch division + return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) +} + +const htf = /* @__PURE__ */ (() => + createHasher( + ed448.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), + { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: shake256, + }, + ))() +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() + +function assertDcfPoint(other: unknown) { + if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') +} + +// 1-d +const ONE_MINUS_D = BigInt('39082') +// 1-2d +const ONE_MINUS_TWO_D = BigInt('78163') +// √(-d) +const SQRT_MINUS_D = BigInt( + '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', +) +// 1 / √(-d) +const INVSQRT_MINUS_D = BigInt( + '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_448B = BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes448ToNumberLE = (bytes: Uint8Array) => + ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Decaf +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 +function calcElligatorDecafMap(r0: bigint): ExtendedPoint { + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const r = mod(-(r0 * r0)) // 1 + const u0 = mod(d * (r - _1n)) // 2 + const u1 = mod((u0 + _1n) * (u0 - r)) // 3 + + const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 + + let v_prime = v // 5 + if (!was_square) v_prime = mod(r0 * v) + + let sgn = _1n // 6 + if (!was_square) sgn = mod(-_1n) + + const s = mod(v_prime * (r + _1n)) // 7 + let s_abs = s + if (isNegativeLE(s, P)) s_abs = mod(-s) + + const s2 = s * s + const W0 = mod(s_abs * _2n) // 8 + const W1 = mod(s2 + _1n) // 9 + const W2 = mod(s2 - _1n) // 10 + const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 + return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class DcfPoint implements Group { + static BASE: DcfPoint + static ZERO: DcfPoint + // Private property to discourage combining ExtendedPoint + DecafPoint + // Always use Decaf encoding/decoding instead. + constructor(private readonly ep: ExtendedPoint) {} + + static fromAffine(ap: AffinePoint): DcfPoint { + return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex: Hex): DcfPoint { + hex = ensureBytes('decafHash', hex, 112) + const r1 = bytes448ToNumberLE(hex.slice(0, 56)) + const R1 = calcElligatorDecafMap(r1) + const r2 = bytes448ToNumberLE(hex.slice(56, 112)) + const R2 = calcElligatorDecafMap(r2) + return new DcfPoint(R1.add(R2)) + } + + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex: Hex): DcfPoint { + hex = ensureBytes('decafHex', hex, 56) + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' + const s = bytes448ToNumberLE(hex) + + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 2. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) + + const s2 = mod(s * s) // 1 + const u1 = mod(_1n + s2) // 2 + const u1sq = mod(u1 * u1) + const u2 = mod(u1sq - _4n * d * s2) // 3 + + const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 + + let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 + if (isNegativeLE(u3, P)) u3 = mod(-u3) + + const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 + const y = mod((_1n - s2) * invsqrt * u1) // 7 + const t = mod(x * y) // 8 + + if (!isValid) throw new Error(emsg) + return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint { + const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) + return pippenger(DcfPoint, Fn, points, scalars) + } + + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: _y, ez: z, et: t } = this.ep + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const u1 = mod(mod(x + t) * mod(x - t)) // 1 + const x2 = mod(x * x) + const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 + + let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 + if (isNegativeLE(ratio, P)) ratio = mod(-ratio) + + const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 + + let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 + if (isNegativeLE(s, P)) s = mod(-s) + + return numberToBytesLE(s, 56) + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 + equals(other: DcfPoint): boolean { + assertDcfPoint(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed448.CURVE.Fp.create + // (x1 * y2 == y1 * x2) + return mod(X1 * Y2) === mod(Y1 * X2) + } + + add(other: DcfPoint): DcfPoint { + assertDcfPoint(other) + return new DcfPoint(this.ep.add(other.ep)) + } + + subtract(other: DcfPoint): DcfPoint { + assertDcfPoint(other) + return new DcfPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): DcfPoint { + return new DcfPoint(this.ep.double()) + } + + negate(): DcfPoint { + return new DcfPoint(this.ep.negate()) + } +} + +export const DecafPoint: typeof DcfPoint = /* @__PURE__ */ (() => { + // decaf448 base point is ed448 base x 2 + // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 + if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) + if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) + return DcfPoint +})() + +// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C +export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts): DcfPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) + const P = DcfPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_decaf448: typeof hashToDecaf448 = hashToDecaf448 // legacy diff --git a/packages/noble-curves/src/index.ts b/packages/noble-curves/src/index.ts new file mode 100644 index 00000000000..8b4ac3bb10f --- /dev/null +++ b/packages/noble-curves/src/index.ts @@ -0,0 +1,17 @@ +/** + * Audited & minimal JS implementation of elliptic curve cryptography. + * @module + * @example +```js +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + */ +throw new Error('root module cannot be imported: import submodules instead. Check out README') diff --git a/packages/noble-curves/src/jubjub.ts b/packages/noble-curves/src/jubjub.ts new file mode 100644 index 00000000000..50ce965df93 --- /dev/null +++ b/packages/noble-curves/src/jubjub.ts @@ -0,0 +1,63 @@ +/** + * jubjub Twisted Edwards curve. + * https://neuromancer.sk/std/other/JubJub + * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { blake2s } from '@noble/hashes/blake2s' +import { sha512 } from '@noble/hashes/sha512' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' +import { Field } from './abstract/modular.js' + +export const jubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ + // Params: a, d + a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), + d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), + // Finite field 𝔽p over which we'll do calculations + // Same value as bls12-381 Fr (not Fp) + Fp: Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')), + // Subgroup order: how many points curve has + n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), + // Cofactor + h: BigInt(8), + // Base point (x, y) aka generator point + Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), + Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), + hash: sha512, + randomBytes, +} as const) + +const GH_FIRST_BLOCK = utf8ToBytes( + '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', +) + +// Returns point at JubJub curve which is prime order and not zero +export function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType { + const h = blake2s.create({ personalization, dkLen: 32 }) + h.update(GH_FIRST_BLOCK) + h.update(tag) + // NOTE: returns ExtendedPoint, in case it will be multiplied later + let p = jubjub.ExtendedPoint.fromHex(h.digest()) + // NOTE: cannot replace with isSmallOrder, returns Point*8 + p = p.multiply(jubjub.CURVE.h) + if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') + return p +} + +// No secret data is leaked here at all. +// It operates over public data: +// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); +export function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType { + const tag = concatBytes(m, new Uint8Array([0])) + const hashes = [] + for (let i = 0; i < 256; i++) { + tag[tag.length - 1] = i + try { + hashes.push(groupHash(tag, personalization)) + } catch (e) {} + } + if (!hashes.length) throw new Error('findGroupHash tag overflow') + return hashes[0] +} diff --git a/packages/noble-curves/src/p256.ts b/packages/noble-curves/src/p256.ts new file mode 100644 index 00000000000..d5e2086ff99 --- /dev/null +++ b/packages/noble-curves/src/p256.ts @@ -0,0 +1,57 @@ +/** + * NIST secp256r1 aka p256. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' +import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' + +const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) +const CURVE_A = Fp256.create(BigInt('-3')) +const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') + +/** secp256r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +export const p256: CurveFnWithCreate = createCurve( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n + // Curve order, total count of valid points in the field + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + // Base (generator) point (x, y) + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, + } as const, + sha256, +) +/** Alias to p256. */ +export const secp256r1: CurveFnWithCreate = p256 + +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp256, { + A: CURVE_A, + B: CURVE_B, + Z: Fp256.create(BigInt('-10')), + }))() + +const htf = /* @__PURE__ */ (() => + createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { + DST: 'P256_XMD:SHA-256_SSWU_RO_', + encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', + p: Fp256.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }))() +/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/p384.ts b/packages/noble-curves/src/p384.ts new file mode 100644 index 00000000000..24f23e4c7e9 --- /dev/null +++ b/packages/noble-curves/src/p384.ts @@ -0,0 +1,71 @@ +/** + * NIST secp384r1 aka p384. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha384 } from '@noble/hashes/sha512' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' +import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' + +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', +) +const Fp384 = Field(P) +const CURVE_A = Fp384.create(BigInt('-3')) +// prettier-ignore +const CURVE_B = BigInt( + '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', +) + +/** secp384r1 curve, ECDSA and ECDH methods. */ +// prettier-ignore +export const p384: CurveFnWithCreate = createCurve( + { + a: CURVE_A, // Equation params: a, b + b: CURVE_B, + Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n + // Curve order, total count of valid points in the field. + n: BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', + ), + // Base (generator) point (x, y) + Gx: BigInt( + '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', + ), + Gy: BigInt( + '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', + ), + h: BigInt(1), + lowS: false, + } as const, + sha384, +) +/** Alias to p384. */ +export const secp384r1: CurveFnWithCreate = p384 + +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp384, { + A: CURVE_A, + B: CURVE_B, + Z: Fp384.create(BigInt('-12')), + }))() + +const htf = /* @__PURE__ */ (() => + createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { + DST: 'P384_XMD:SHA-384_SSWU_RO_', + encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', + p: Fp384.ORDER, + m: 1, + k: 192, + expand: 'xmd', + hash: sha384, + }))() +/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/p521.ts b/packages/noble-curves/src/p521.ts new file mode 100644 index 00000000000..f4e3df9ec63 --- /dev/null +++ b/packages/noble-curves/src/p521.ts @@ -0,0 +1,80 @@ +/** + * NIST secp521r1 aka p521. + * Note that it's 521, which differs from 512 of its hash function. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha512' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' +import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' +import { Field } from './abstract/modular.js' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' + +// Field over which we'll do calculations. +// prettier-ignore +const P = BigInt( + '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const Fp521 = Field(P) + +const CURVE = { + a: Fp521.create(BigInt('-3')), + b: BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', + ), + Fp: Fp521, + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', + ), + h: BigInt(1), +} + +/** + * NIST secp521r1 aka p521. + */ +// prettier-ignore +export const p521: CurveFnWithCreate = createCurve( + { + a: CURVE.a, // Equation params: a, b + b: CURVE.b, + Fp: Fp521, // Field: 2n**521n - 1n + // Curve order, total count of valid points in the field + n: CURVE.n, + Gx: CURVE.Gx, // Base point (x, y) aka generator point + Gy: CURVE.Gy, + h: CURVE.h, + lowS: false, + allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b + } as const, + sha512, +) +export const secp521r1: CurveFnWithCreate = p521 + +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp521, { + A: CURVE.a, + B: CURVE.b, + Z: Fp521.create(BigInt('-4')), + }))() + +const htf = /* @__PURE__ */ (() => + createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { + DST: 'P521_XMD:SHA-512_SSWU_RO_', + encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', + p: Fp521.ORDER, + m: 1, + k: 256, + expand: 'xmd', + hash: sha512, + }))() +/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() +/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/package.json b/packages/noble-curves/src/package.json new file mode 100644 index 00000000000..3dbc1ca591c --- /dev/null +++ b/packages/noble-curves/src/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/noble-curves/src/pasta.ts b/packages/noble-curves/src/pasta.ts new file mode 100644 index 00000000000..df1784d0d7f --- /dev/null +++ b/packages/noble-curves/src/pasta.ts @@ -0,0 +1,39 @@ +/** + * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { getHash } from './_shortw_utils.js' +import { Field, mod } from './abstract/modular.js' +import { type CurveFn, weierstrass } from './abstract/weierstrass.js' + +export const p: bigint = BigInt( + '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001', +) +export const q: bigint = BigInt( + '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001', +) + +/** https://neuromancer.sk/std/other/Pallas */ +export const pallas: CurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(p), + n: q, + Gx: mod(BigInt(-1), p), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +/** https://neuromancer.sk/std/other/Vesta */ +export const vesta: CurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(q), + n: p, + Gx: mod(BigInt(-1), q), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/noble-curves/src/secp256k1.ts b/packages/noble-curves/src/secp256k1.ts new file mode 100644 index 00000000000..ef45055b99c --- /dev/null +++ b/packages/noble-curves/src/secp256k1.ts @@ -0,0 +1,333 @@ +/** + * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). + * + * Seems to be rigid (not backdoored) + * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). + * + * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. + * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. + * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. + * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha256' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' +import { type HTFMethod, createHasher, isogenyMap } from './abstract/hash-to-curve.js' +import { Field, mod, pow2 } from './abstract/modular.js' +import type { Hex, PrivKey } from './abstract/utils.js' +import { + aInRange, + bytesToNumberBE, + concatBytes, + ensureBytes, + inRange, + numberToBytesBE, +} from './abstract/utils.js' +import { type ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js' + +const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') +const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') +const _1n = BigInt(1) +const _2n = BigInt(2) +const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b + +/** + * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ +function sqrtMod(y: bigint): bigint { + const P = secp256k1P + // prettier-ignore + const _3n = BigInt(3), + _6n = BigInt(6), + _11n = BigInt(11), + _22n = BigInt(22) + // prettier-ignore + const _23n = BigInt(23), + _44n = BigInt(44), + _88n = BigInt(88) + const b2 = (y * y * y) % P // x^3, 11 + const b3 = (b2 * b2 * y) % P // x^7 + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b223 = (pow2(b220, _3n, P) * b3) % P + const t1 = (pow2(b223, _23n, P) * b22) % P + const t2 = (pow2(t1, _6n, P) * b2) % P + const root = pow2(t2, _2n, P) + if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') + return root +} + +const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) + +/** + * secp256k1 short weierstrass curve and ECDSA signatures over it. + * + * @example + * import { secp256k1 } from '@noble/curves/secp256k1'; + * + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + */ +export const secp256k1: CurveFnWithCreate = createCurve( + { + a: BigInt(0), // equation params: a, b + b: BigInt(7), + Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n + n: secp256k1N, // Curve order, total count of valid points in the field + // Base point (x, y) aka generator point + Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), + Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + h: BigInt(1), // Cofactor + lowS: true, // Allow only low-S signatures by default in sign() and verify() + endo: { + // Endomorphism, see above + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + splitScalar: (k: bigint) => { + const n = secp256k1N + const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') + const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') + const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') + const b2 = a1 + const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) + + const c1 = divNearest(b2 * k, n) + const c2 = divNearest(-b1 * k, n) + let k1 = mod(k - c1 * a1 - c2 * a2, n) + let k2 = mod(-c1 * b1 - c2 * b2, n) + const k1neg = k1 > POW_2_128 + const k2neg = k2 > POW_2_128 + if (k1neg) k1 = n - k1 + if (k2neg) k2 = n - k2 + if (k1 > POW_2_128 || k2 > POW_2_128) { + throw new Error('splitScalar: Endomorphism failed, k=' + k) + } + return { k1neg, k1, k2neg, k2 } + }, + }, + }, + sha256, +) + +// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. +// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +const _0n = BigInt(0) +/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {} +function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array { + let tagP = TAGGED_HASH_PREFIXES[tag] + if (tagP === undefined) { + const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) + tagP = concatBytes(tagH, tagH) + TAGGED_HASH_PREFIXES[tag] = tagP + } + return sha256(concatBytes(tagP, ...messages)) +} + +// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 +const pointToBytes = (point: PointType) => point.toRawBytes(true).slice(1) +const numTo32b = (n: bigint) => numberToBytesBE(n, 32) +const modP = (x: bigint) => mod(x, secp256k1P) +const modN = (x: bigint) => mod(x, secp256k1N) +const Point = secp256k1.ProjectivePoint +const GmulAdd = (Q: PointType, a: bigint, b: bigint) => + Point.BASE.multiplyAndAddUnsafe(Q, a, b) + +// Calculate point, scalar and bytes +function schnorrGetExtPubKey(priv: PrivKey) { + let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey + let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside + const scalar = p.hasEvenY() ? d_ : modN(-d_) + return { scalar: scalar, bytes: pointToBytes(p) } +} +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +function lift_x(x: bigint): PointType { + aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. + const xx = modP(x * x) + const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. + let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. + if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and + const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. + p.assertValidity() + return p +} +const num = bytesToNumberBE +/** + * Create tagged hash, convert it to bigint, reduce modulo-n. + */ +function challenge(...args: Uint8Array[]): bigint { + return modN(num(taggedHash('BIP0340/challenge', ...args))) +} + +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +function schnorrGetPublicKey(privateKey: Hex): Uint8Array { + return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) +} + +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +function schnorrSign( + message: Hex, + privateKey: PrivKey, + auxRand: Hex = randomBytes(32), +): Uint8Array { + const m = ensureBytes('message', message) + const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder + const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array + const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) + const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) + const k_ = modN(num(rand)) // Let k' = int(rand) mod n + if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. + const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. + const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. + const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). + sig.set(rx, 0) + sig.set(numTo32b(modN(k + e * d)), 32) + // If Verify(bytes(P), m, sig) (see below) returns failure, abort + if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') + return sig +} + +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { + const sig = ensureBytes('signature', signature, 64) + const m = ensureBytes('message', message) + const pub = ensureBytes('publicKey', publicKey, 32) + try { + const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails + const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. + if (!inRange(r, _1n, secp256k1P)) return false + const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. + if (!inRange(s, _1n, secp256k1N)) return false + const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n + const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P + if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P + return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. + } catch (error) { + return false + } +} + +export type SecpSchnorr = { + getPublicKey: typeof schnorrGetPublicKey + sign: typeof schnorrSign + verify: typeof schnorrVerify + utils: { + randomPrivateKey: () => Uint8Array + lift_x: typeof lift_x + pointToBytes: (point: PointType) => Uint8Array + numberToBytesBE: typeof numberToBytesBE + bytesToNumberBE: typeof bytesToNumberBE + taggedHash: typeof taggedHash + mod: typeof mod + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + */ +export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => ({ + getPublicKey: schnorrGetPublicKey, + sign: schnorrSign, + verify: schnorrVerify, + utils: { + randomPrivateKey: secp256k1.utils.randomPrivateKey, + lift_x, + pointToBytes, + numberToBytesBE, + bytesToNumberBE, + taggedHash, + mod, + }, +}))() + +const isoMap = /* @__PURE__ */ (() => + isogenyMap( + Fpk1, + [ + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]], + ))() +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fpk1, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fpk1.create(BigInt('-11')), + }))() +const htf = /* @__PURE__ */ (() => + createHasher( + secp256k1.ProjectivePoint, + (scalars: bigint[]) => { + const { x, y } = mapSWU(Fpk1.create(scalars[0])) + return isoMap(x, y) + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fpk1.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }, + ))() + +/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() + +/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() From fbc743111f01821ed58206ba5b2fa64b1838cdb7 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 19 Apr 2025 04:37:44 +0200 Subject: [PATCH 05/10] load inner noble bls [no ci] --- packages/evm/src/precompiles/bls12_381/noble.ts | 2 +- packages/vm/vitest.config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/evm/src/precompiles/bls12_381/noble.ts b/packages/evm/src/precompiles/bls12_381/noble.ts index 7be334127e0..a8658c22920 100644 --- a/packages/evm/src/precompiles/bls12_381/noble.ts +++ b/packages/evm/src/precompiles/bls12_381/noble.ts @@ -6,7 +6,7 @@ import { equalsBytes, setLengthLeft, } from '@ethereumjs/util' -import { bls12_381 } from '@noble/curves/bls12-381' +import { bls12_381 } from '../../../../noble-curves/bls12-381.js' import { EVMError, EVMErrorMessages } from '../../errors.ts' diff --git a/packages/vm/vitest.config.ts b/packages/vm/vitest.config.ts index 2e389497bea..604f5586aaf 100644 --- a/packages/vm/vitest.config.ts +++ b/packages/vm/vitest.config.ts @@ -17,7 +17,7 @@ export default mergeConfig( coverage: { enabled: true, allowExternal: true, - include: ['**/packages/*/src/**/*.{ts,js}'], + include: ['**/packages/*/src/**/*.{ts,js}', '**/packages/noble-curves/**/*.{ts,js}'], exclude: ['**/packages/ethereum-tests'], reporter: ['text', 'html'], }, From 546251c1d7b8b031894619af11550a8fc2b543f0 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 22 Apr 2025 00:33:36 +0200 Subject: [PATCH 06/10] delete noble curves clone [no ci] --- packages/noble-curves/LICENSE | 21 - packages/noble-curves/README.md | 1113 ------------- packages/noble-curves/_shortw_utils.d.ts | 16 - packages/noble-curves/_shortw_utils.d.ts.map | 1 - packages/noble-curves/_shortw_utils.js | 25 - packages/noble-curves/_shortw_utils.js.map | 1 - packages/noble-curves/abstract/bls.d.ts | 165 -- packages/noble-curves/abstract/bls.d.ts.map | 1 - packages/noble-curves/abstract/bls.js | 360 ----- packages/noble-curves/abstract/bls.js.map | 1 - packages/noble-curves/abstract/curve.d.ts | 124 -- packages/noble-curves/abstract/curve.d.ts.map | 1 - packages/noble-curves/abstract/curve.js | 368 ----- packages/noble-curves/abstract/curve.js.map | 1 - packages/noble-curves/abstract/edwards.d.ts | 106 -- .../noble-curves/abstract/edwards.d.ts.map | 1 - packages/noble-curves/abstract/edwards.js | 448 ------ packages/noble-curves/abstract/edwards.js.map | 1 - .../noble-curves/abstract/hash-to-curve.d.ts | 99 -- .../abstract/hash-to-curve.d.ts.map | 1 - .../noble-curves/abstract/hash-to-curve.js | 184 --- .../abstract/hash-to-curve.js.map | 1 - packages/noble-curves/abstract/modular.d.ts | 168 -- .../noble-curves/abstract/modular.d.ts.map | 1 - packages/noble-curves/abstract/modular.js | 485 ------ packages/noble-curves/abstract/modular.js.map | 1 - .../noble-curves/abstract/montgomery.d.ts | 26 - .../noble-curves/abstract/montgomery.d.ts.map | 1 - packages/noble-curves/abstract/montgomery.js | 162 -- .../noble-curves/abstract/montgomery.js.map | 1 - packages/noble-curves/abstract/poseidon.d.ts | 39 - .../noble-curves/abstract/poseidon.d.ts.map | 1 - packages/noble-curves/abstract/poseidon.js | 104 -- .../noble-curves/abstract/poseidon.js.map | 1 - packages/noble-curves/abstract/tower.d.ts | 126 -- packages/noble-curves/abstract/tower.d.ts.map | 1 - packages/noble-curves/abstract/tower.js | 520 ------- packages/noble-curves/abstract/tower.js.map | 1 - packages/noble-curves/abstract/utils.d.ts | 126 -- packages/noble-curves/abstract/utils.d.ts.map | 1 - packages/noble-curves/abstract/utils.js | 340 ---- packages/noble-curves/abstract/utils.js.map | 1 - .../noble-curves/abstract/weierstrass.d.ts | 241 --- .../abstract/weierstrass.d.ts.map | 1 - packages/noble-curves/abstract/weierstrass.js | 1139 -------------- .../noble-curves/abstract/weierstrass.js.map | 1 - packages/noble-curves/bls12-381.d.ts | 14 - packages/noble-curves/bls12-381.d.ts.map | 1 - packages/noble-curves/bls12-381.js | 756 --------- packages/noble-curves/bls12-381.js.map | 1 - packages/noble-curves/bn254.d.ts | 15 - packages/noble-curves/bn254.d.ts.map | 1 - packages/noble-curves/bn254.js | 237 --- packages/noble-curves/bn254.js.map | 1 - packages/noble-curves/ed25519.d.ts | 101 -- packages/noble-curves/ed25519.d.ts.map | 1 - packages/noble-curves/ed25519.js | 510 ------ packages/noble-curves/ed25519.js.map | 1 - packages/noble-curves/ed448.d.ts | 82 - packages/noble-curves/ed448.d.ts.map | 1 - packages/noble-curves/ed448.js | 470 ------ packages/noble-curves/ed448.js.map | 1 - packages/noble-curves/esm/_shortw_utils.d.ts | 16 - .../noble-curves/esm/_shortw_utils.d.ts.map | 1 - packages/noble-curves/esm/_shortw_utils.js | 21 - .../noble-curves/esm/_shortw_utils.js.map | 1 - packages/noble-curves/esm/abstract/bls.d.ts | 165 -- .../noble-curves/esm/abstract/bls.d.ts.map | 1 - packages/noble-curves/esm/abstract/bls.js | 357 ----- packages/noble-curves/esm/abstract/bls.js.map | 1 - packages/noble-curves/esm/abstract/curve.d.ts | 124 -- .../noble-curves/esm/abstract/curve.d.ts.map | 1 - packages/noble-curves/esm/abstract/curve.js | 362 ----- .../noble-curves/esm/abstract/curve.js.map | 1 - .../noble-curves/esm/abstract/edwards.d.ts | 106 -- .../esm/abstract/edwards.d.ts.map | 1 - packages/noble-curves/esm/abstract/edwards.js | 445 ------ .../noble-curves/esm/abstract/edwards.js.map | 1 - .../esm/abstract/hash-to-curve.d.ts | 99 -- .../esm/abstract/hash-to-curve.d.ts.map | 1 - .../esm/abstract/hash-to-curve.js | 173 --- .../esm/abstract/hash-to-curve.js.map | 1 - .../noble-curves/esm/abstract/modular.d.ts | 168 -- .../esm/abstract/modular.d.ts.map | 1 - packages/noble-curves/esm/abstract/modular.js | 464 ------ .../noble-curves/esm/abstract/modular.js.map | 1 - .../noble-curves/esm/abstract/montgomery.d.ts | 26 - .../esm/abstract/montgomery.d.ts.map | 1 - .../noble-curves/esm/abstract/montgomery.js | 159 -- .../esm/abstract/montgomery.js.map | 1 - .../noble-curves/esm/abstract/poseidon.d.ts | 39 - .../esm/abstract/poseidon.d.ts.map | 1 - .../noble-curves/esm/abstract/poseidon.js | 99 -- .../noble-curves/esm/abstract/poseidon.js.map | 1 - packages/noble-curves/esm/abstract/tower.d.ts | 126 -- .../noble-curves/esm/abstract/tower.d.ts.map | 1 - packages/noble-curves/esm/abstract/tower.js | 515 ------ .../noble-curves/esm/abstract/tower.js.map | 1 - packages/noble-curves/esm/abstract/utils.d.ts | 126 -- .../noble-curves/esm/abstract/utils.d.ts.map | 1 - packages/noble-curves/esm/abstract/utils.js | 311 ---- .../noble-curves/esm/abstract/utils.js.map | 1 - .../esm/abstract/weierstrass.d.ts | 241 --- .../esm/abstract/weierstrass.d.ts.map | 1 - .../noble-curves/esm/abstract/weierstrass.js | 1131 -------------- .../esm/abstract/weierstrass.js.map | 1 - packages/noble-curves/esm/bls12-381.d.ts | 14 - packages/noble-curves/esm/bls12-381.d.ts.map | 1 - packages/noble-curves/esm/bls12-381.js | 747 --------- packages/noble-curves/esm/bls12-381.js.map | 1 - packages/noble-curves/esm/bn254.d.ts | 15 - packages/noble-curves/esm/bn254.d.ts.map | 1 - packages/noble-curves/esm/bn254.js | 233 --- packages/noble-curves/esm/bn254.js.map | 1 - packages/noble-curves/esm/ed25519.d.ts | 101 -- packages/noble-curves/esm/ed25519.d.ts.map | 1 - packages/noble-curves/esm/ed25519.js | 493 ------ packages/noble-curves/esm/ed25519.js.map | 1 - packages/noble-curves/esm/ed448.d.ts | 82 - packages/noble-curves/esm/ed448.d.ts.map | 1 - packages/noble-curves/esm/ed448.js | 447 ------ packages/noble-curves/esm/ed448.js.map | 1 - packages/noble-curves/esm/index.d.ts | 2 - packages/noble-curves/esm/index.d.ts.map | 1 - packages/noble-curves/esm/index.js | 19 - packages/noble-curves/esm/index.js.map | 1 - packages/noble-curves/esm/jubjub.d.ts | 5 - packages/noble-curves/esm/jubjub.d.ts.map | 1 - packages/noble-curves/esm/jubjub.js | 60 - packages/noble-curves/esm/jubjub.js.map | 1 - packages/noble-curves/esm/p256.d.ts | 11 - packages/noble-curves/esm/p256.d.ts.map | 1 - packages/noble-curves/esm/p256.js | 54 - packages/noble-curves/esm/p256.js.map | 1 - packages/noble-curves/esm/p384.d.ts | 11 - packages/noble-curves/esm/p384.d.ts.map | 1 - packages/noble-curves/esm/p384.js | 68 - packages/noble-curves/esm/p384.js.map | 1 - packages/noble-curves/esm/p521.d.ts | 12 - packages/noble-curves/esm/p521.d.ts.map | 1 - packages/noble-curves/esm/p521.js | 76 - packages/noble-curves/esm/p521.js.map | 1 - packages/noble-curves/esm/package.json | 4 - packages/noble-curves/esm/pasta.d.ts | 8 - packages/noble-curves/esm/pasta.d.ts.map | 1 - packages/noble-curves/esm/pasta.js | 34 - packages/noble-curves/esm/pasta.js.map | 1 - packages/noble-curves/esm/secp256k1.d.ts | 71 - packages/noble-curves/esm/secp256k1.d.ts.map | 1 - packages/noble-curves/esm/secp256k1.js | 299 ---- packages/noble-curves/esm/secp256k1.js.map | 1 - packages/noble-curves/index.d.ts | 1 - packages/noble-curves/index.d.ts.map | 1 - packages/noble-curves/index.js | 19 - packages/noble-curves/index.js.map | 1 - packages/noble-curves/jubjub.d.ts | 5 - packages/noble-curves/jubjub.d.ts.map | 1 - packages/noble-curves/jubjub.js | 67 - packages/noble-curves/jubjub.js.map | 1 - packages/noble-curves/p256.d.ts | 11 - packages/noble-curves/p256.d.ts.map | 1 - packages/noble-curves/p256.js | 63 - packages/noble-curves/p256.js.map | 1 - packages/noble-curves/p384.d.ts | 11 - packages/noble-curves/p384.d.ts.map | 1 - packages/noble-curves/p384.js | 75 - packages/noble-curves/p384.js.map | 1 - packages/noble-curves/p521.d.ts | 12 - packages/noble-curves/p521.d.ts.map | 1 - packages/noble-curves/p521.js | 83 - packages/noble-curves/p521.js.map | 1 - packages/noble-curves/package.json | 163 -- packages/noble-curves/pasta.d.ts | 8 - packages/noble-curves/pasta.d.ts.map | 1 - packages/noble-curves/pasta.js | 37 - packages/noble-curves/pasta.js.map | 1 - packages/noble-curves/secp256k1.d.ts | 71 - packages/noble-curves/secp256k1.d.ts.map | 1 - packages/noble-curves/secp256k1.js | 295 ---- packages/noble-curves/secp256k1.js.map | 1 - packages/noble-curves/src/_shortw_utils.ts | 30 - packages/noble-curves/src/abstract/bls.ts | 574 ------- packages/noble-curves/src/abstract/curve.ts | 457 ------ packages/noble-curves/src/abstract/edwards.ts | 565 ------- .../src/abstract/hash-to-curve.ts | 255 --- packages/noble-curves/src/abstract/modular.ts | 555 ------- .../noble-curves/src/abstract/montgomery.ts | 190 --- .../noble-curves/src/abstract/poseidon.ts | 136 -- packages/noble-curves/src/abstract/tower.ts | 664 -------- packages/noble-curves/src/abstract/utils.ts | 367 ----- .../noble-curves/src/abstract/weierstrass.ts | 1383 ----------------- packages/noble-curves/src/bls12-381.ts | 774 --------- packages/noble-curves/src/bn254.ts | 254 --- packages/noble-curves/src/ed25519.ts | 544 ------- packages/noble-curves/src/ed448.ts | 514 ------ packages/noble-curves/src/index.ts | 17 - packages/noble-curves/src/jubjub.ts | 63 - packages/noble-curves/src/p256.ts | 57 - packages/noble-curves/src/p384.ts | 71 - packages/noble-curves/src/p521.ts | 80 - packages/noble-curves/src/package.json | 3 - packages/noble-curves/src/pasta.ts | 39 - packages/noble-curves/src/secp256k1.ts | 333 ---- 203 files changed, 25763 deletions(-) delete mode 100644 packages/noble-curves/LICENSE delete mode 100644 packages/noble-curves/README.md delete mode 100644 packages/noble-curves/_shortw_utils.d.ts delete mode 100644 packages/noble-curves/_shortw_utils.d.ts.map delete mode 100644 packages/noble-curves/_shortw_utils.js delete mode 100644 packages/noble-curves/_shortw_utils.js.map delete mode 100644 packages/noble-curves/abstract/bls.d.ts delete mode 100644 packages/noble-curves/abstract/bls.d.ts.map delete mode 100644 packages/noble-curves/abstract/bls.js delete mode 100644 packages/noble-curves/abstract/bls.js.map delete mode 100644 packages/noble-curves/abstract/curve.d.ts delete mode 100644 packages/noble-curves/abstract/curve.d.ts.map delete mode 100644 packages/noble-curves/abstract/curve.js delete mode 100644 packages/noble-curves/abstract/curve.js.map delete mode 100644 packages/noble-curves/abstract/edwards.d.ts delete mode 100644 packages/noble-curves/abstract/edwards.d.ts.map delete mode 100644 packages/noble-curves/abstract/edwards.js delete mode 100644 packages/noble-curves/abstract/edwards.js.map delete mode 100644 packages/noble-curves/abstract/hash-to-curve.d.ts delete mode 100644 packages/noble-curves/abstract/hash-to-curve.d.ts.map delete mode 100644 packages/noble-curves/abstract/hash-to-curve.js delete mode 100644 packages/noble-curves/abstract/hash-to-curve.js.map delete mode 100644 packages/noble-curves/abstract/modular.d.ts delete mode 100644 packages/noble-curves/abstract/modular.d.ts.map delete mode 100644 packages/noble-curves/abstract/modular.js delete mode 100644 packages/noble-curves/abstract/modular.js.map delete mode 100644 packages/noble-curves/abstract/montgomery.d.ts delete mode 100644 packages/noble-curves/abstract/montgomery.d.ts.map delete mode 100644 packages/noble-curves/abstract/montgomery.js delete mode 100644 packages/noble-curves/abstract/montgomery.js.map delete mode 100644 packages/noble-curves/abstract/poseidon.d.ts delete mode 100644 packages/noble-curves/abstract/poseidon.d.ts.map delete mode 100644 packages/noble-curves/abstract/poseidon.js delete mode 100644 packages/noble-curves/abstract/poseidon.js.map delete mode 100644 packages/noble-curves/abstract/tower.d.ts delete mode 100644 packages/noble-curves/abstract/tower.d.ts.map delete mode 100644 packages/noble-curves/abstract/tower.js delete mode 100644 packages/noble-curves/abstract/tower.js.map delete mode 100644 packages/noble-curves/abstract/utils.d.ts delete mode 100644 packages/noble-curves/abstract/utils.d.ts.map delete mode 100644 packages/noble-curves/abstract/utils.js delete mode 100644 packages/noble-curves/abstract/utils.js.map delete mode 100644 packages/noble-curves/abstract/weierstrass.d.ts delete mode 100644 packages/noble-curves/abstract/weierstrass.d.ts.map delete mode 100644 packages/noble-curves/abstract/weierstrass.js delete mode 100644 packages/noble-curves/abstract/weierstrass.js.map delete mode 100644 packages/noble-curves/bls12-381.d.ts delete mode 100644 packages/noble-curves/bls12-381.d.ts.map delete mode 100644 packages/noble-curves/bls12-381.js delete mode 100644 packages/noble-curves/bls12-381.js.map delete mode 100644 packages/noble-curves/bn254.d.ts delete mode 100644 packages/noble-curves/bn254.d.ts.map delete mode 100644 packages/noble-curves/bn254.js delete mode 100644 packages/noble-curves/bn254.js.map delete mode 100644 packages/noble-curves/ed25519.d.ts delete mode 100644 packages/noble-curves/ed25519.d.ts.map delete mode 100644 packages/noble-curves/ed25519.js delete mode 100644 packages/noble-curves/ed25519.js.map delete mode 100644 packages/noble-curves/ed448.d.ts delete mode 100644 packages/noble-curves/ed448.d.ts.map delete mode 100644 packages/noble-curves/ed448.js delete mode 100644 packages/noble-curves/ed448.js.map delete mode 100644 packages/noble-curves/esm/_shortw_utils.d.ts delete mode 100644 packages/noble-curves/esm/_shortw_utils.d.ts.map delete mode 100644 packages/noble-curves/esm/_shortw_utils.js delete mode 100644 packages/noble-curves/esm/_shortw_utils.js.map delete mode 100644 packages/noble-curves/esm/abstract/bls.d.ts delete mode 100644 packages/noble-curves/esm/abstract/bls.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/bls.js delete mode 100644 packages/noble-curves/esm/abstract/bls.js.map delete mode 100644 packages/noble-curves/esm/abstract/curve.d.ts delete mode 100644 packages/noble-curves/esm/abstract/curve.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/curve.js delete mode 100644 packages/noble-curves/esm/abstract/curve.js.map delete mode 100644 packages/noble-curves/esm/abstract/edwards.d.ts delete mode 100644 packages/noble-curves/esm/abstract/edwards.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/edwards.js delete mode 100644 packages/noble-curves/esm/abstract/edwards.js.map delete mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.d.ts delete mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.js delete mode 100644 packages/noble-curves/esm/abstract/hash-to-curve.js.map delete mode 100644 packages/noble-curves/esm/abstract/modular.d.ts delete mode 100644 packages/noble-curves/esm/abstract/modular.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/modular.js delete mode 100644 packages/noble-curves/esm/abstract/modular.js.map delete mode 100644 packages/noble-curves/esm/abstract/montgomery.d.ts delete mode 100644 packages/noble-curves/esm/abstract/montgomery.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/montgomery.js delete mode 100644 packages/noble-curves/esm/abstract/montgomery.js.map delete mode 100644 packages/noble-curves/esm/abstract/poseidon.d.ts delete mode 100644 packages/noble-curves/esm/abstract/poseidon.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/poseidon.js delete mode 100644 packages/noble-curves/esm/abstract/poseidon.js.map delete mode 100644 packages/noble-curves/esm/abstract/tower.d.ts delete mode 100644 packages/noble-curves/esm/abstract/tower.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/tower.js delete mode 100644 packages/noble-curves/esm/abstract/tower.js.map delete mode 100644 packages/noble-curves/esm/abstract/utils.d.ts delete mode 100644 packages/noble-curves/esm/abstract/utils.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/utils.js delete mode 100644 packages/noble-curves/esm/abstract/utils.js.map delete mode 100644 packages/noble-curves/esm/abstract/weierstrass.d.ts delete mode 100644 packages/noble-curves/esm/abstract/weierstrass.d.ts.map delete mode 100644 packages/noble-curves/esm/abstract/weierstrass.js delete mode 100644 packages/noble-curves/esm/abstract/weierstrass.js.map delete mode 100644 packages/noble-curves/esm/bls12-381.d.ts delete mode 100644 packages/noble-curves/esm/bls12-381.d.ts.map delete mode 100644 packages/noble-curves/esm/bls12-381.js delete mode 100644 packages/noble-curves/esm/bls12-381.js.map delete mode 100644 packages/noble-curves/esm/bn254.d.ts delete mode 100644 packages/noble-curves/esm/bn254.d.ts.map delete mode 100644 packages/noble-curves/esm/bn254.js delete mode 100644 packages/noble-curves/esm/bn254.js.map delete mode 100644 packages/noble-curves/esm/ed25519.d.ts delete mode 100644 packages/noble-curves/esm/ed25519.d.ts.map delete mode 100644 packages/noble-curves/esm/ed25519.js delete mode 100644 packages/noble-curves/esm/ed25519.js.map delete mode 100644 packages/noble-curves/esm/ed448.d.ts delete mode 100644 packages/noble-curves/esm/ed448.d.ts.map delete mode 100644 packages/noble-curves/esm/ed448.js delete mode 100644 packages/noble-curves/esm/ed448.js.map delete mode 100644 packages/noble-curves/esm/index.d.ts delete mode 100644 packages/noble-curves/esm/index.d.ts.map delete mode 100644 packages/noble-curves/esm/index.js delete mode 100644 packages/noble-curves/esm/index.js.map delete mode 100644 packages/noble-curves/esm/jubjub.d.ts delete mode 100644 packages/noble-curves/esm/jubjub.d.ts.map delete mode 100644 packages/noble-curves/esm/jubjub.js delete mode 100644 packages/noble-curves/esm/jubjub.js.map delete mode 100644 packages/noble-curves/esm/p256.d.ts delete mode 100644 packages/noble-curves/esm/p256.d.ts.map delete mode 100644 packages/noble-curves/esm/p256.js delete mode 100644 packages/noble-curves/esm/p256.js.map delete mode 100644 packages/noble-curves/esm/p384.d.ts delete mode 100644 packages/noble-curves/esm/p384.d.ts.map delete mode 100644 packages/noble-curves/esm/p384.js delete mode 100644 packages/noble-curves/esm/p384.js.map delete mode 100644 packages/noble-curves/esm/p521.d.ts delete mode 100644 packages/noble-curves/esm/p521.d.ts.map delete mode 100644 packages/noble-curves/esm/p521.js delete mode 100644 packages/noble-curves/esm/p521.js.map delete mode 100644 packages/noble-curves/esm/package.json delete mode 100644 packages/noble-curves/esm/pasta.d.ts delete mode 100644 packages/noble-curves/esm/pasta.d.ts.map delete mode 100644 packages/noble-curves/esm/pasta.js delete mode 100644 packages/noble-curves/esm/pasta.js.map delete mode 100644 packages/noble-curves/esm/secp256k1.d.ts delete mode 100644 packages/noble-curves/esm/secp256k1.d.ts.map delete mode 100644 packages/noble-curves/esm/secp256k1.js delete mode 100644 packages/noble-curves/esm/secp256k1.js.map delete mode 100644 packages/noble-curves/index.d.ts delete mode 100644 packages/noble-curves/index.d.ts.map delete mode 100644 packages/noble-curves/index.js delete mode 100644 packages/noble-curves/index.js.map delete mode 100644 packages/noble-curves/jubjub.d.ts delete mode 100644 packages/noble-curves/jubjub.d.ts.map delete mode 100644 packages/noble-curves/jubjub.js delete mode 100644 packages/noble-curves/jubjub.js.map delete mode 100644 packages/noble-curves/p256.d.ts delete mode 100644 packages/noble-curves/p256.d.ts.map delete mode 100644 packages/noble-curves/p256.js delete mode 100644 packages/noble-curves/p256.js.map delete mode 100644 packages/noble-curves/p384.d.ts delete mode 100644 packages/noble-curves/p384.d.ts.map delete mode 100644 packages/noble-curves/p384.js delete mode 100644 packages/noble-curves/p384.js.map delete mode 100644 packages/noble-curves/p521.d.ts delete mode 100644 packages/noble-curves/p521.d.ts.map delete mode 100644 packages/noble-curves/p521.js delete mode 100644 packages/noble-curves/p521.js.map delete mode 100644 packages/noble-curves/package.json delete mode 100644 packages/noble-curves/pasta.d.ts delete mode 100644 packages/noble-curves/pasta.d.ts.map delete mode 100644 packages/noble-curves/pasta.js delete mode 100644 packages/noble-curves/pasta.js.map delete mode 100644 packages/noble-curves/secp256k1.d.ts delete mode 100644 packages/noble-curves/secp256k1.d.ts.map delete mode 100644 packages/noble-curves/secp256k1.js delete mode 100644 packages/noble-curves/secp256k1.js.map delete mode 100644 packages/noble-curves/src/_shortw_utils.ts delete mode 100644 packages/noble-curves/src/abstract/bls.ts delete mode 100644 packages/noble-curves/src/abstract/curve.ts delete mode 100644 packages/noble-curves/src/abstract/edwards.ts delete mode 100644 packages/noble-curves/src/abstract/hash-to-curve.ts delete mode 100644 packages/noble-curves/src/abstract/modular.ts delete mode 100644 packages/noble-curves/src/abstract/montgomery.ts delete mode 100644 packages/noble-curves/src/abstract/poseidon.ts delete mode 100644 packages/noble-curves/src/abstract/tower.ts delete mode 100644 packages/noble-curves/src/abstract/utils.ts delete mode 100644 packages/noble-curves/src/abstract/weierstrass.ts delete mode 100644 packages/noble-curves/src/bls12-381.ts delete mode 100644 packages/noble-curves/src/bn254.ts delete mode 100644 packages/noble-curves/src/ed25519.ts delete mode 100644 packages/noble-curves/src/ed448.ts delete mode 100644 packages/noble-curves/src/index.ts delete mode 100644 packages/noble-curves/src/jubjub.ts delete mode 100644 packages/noble-curves/src/p256.ts delete mode 100644 packages/noble-curves/src/p384.ts delete mode 100644 packages/noble-curves/src/p521.ts delete mode 100644 packages/noble-curves/src/package.json delete mode 100644 packages/noble-curves/src/pasta.ts delete mode 100644 packages/noble-curves/src/secp256k1.ts diff --git a/packages/noble-curves/LICENSE b/packages/noble-curves/LICENSE deleted file mode 100644 index 9297a046d01..00000000000 --- a/packages/noble-curves/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 Paul Miller (https://paulmillr.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the “Software”), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/packages/noble-curves/README.md b/packages/noble-curves/README.md deleted file mode 100644 index 02527331b9b..00000000000 --- a/packages/noble-curves/README.md +++ /dev/null @@ -1,1113 +0,0 @@ -# noble-curves - -Audited & minimal JS implementation of elliptic curve cryptography. - -- 🔒 [**Audited**](#security) by independent security firms -- 🔻 Tree-shakeable: unused code is excluded from your builds -- 🏎 Fast: hand-optimized for caveats of JS engines -- 🔍 Reliable: cross-library / wycheproof tests and fuzzing ensure correctness -- ➰ Short Weierstrass, Edwards, Montgomery curves -- ✍️ ECDSA, EdDSA, Schnorr, BLS, ECDH, hashing to curves, Poseidon ZK-friendly hash -- 🔖 SUF-CMA, SBS (non-repudiation), ZIP215 (consensus friendliness) features for ed25519 & ed448 -- 🪶 93KB for everything with hashes, 26KB (11KB gzipped) for single-curve build - -Curves have 4KB sister projects -[secp256k1](https://github.com/paulmillr/noble-secp256k1) & [ed25519](https://github.com/paulmillr/noble-ed25519). -They have smaller attack surface, but less features. - -Take a glance at [GitHub Discussions](https://github.com/paulmillr/noble-curves/discussions) for questions and support. - -### This library belongs to _noble_ cryptography - -> **noble cryptography** — high-security, easily auditable set of contained cryptographic libraries and tools. - -- Zero or minimal dependencies -- Highly readable TypeScript / JS code -- PGP-signed releases and transparent NPM builds -- All libraries: - [ciphers](https://github.com/paulmillr/noble-ciphers), - [curves](https://github.com/paulmillr/noble-curves), - [hashes](https://github.com/paulmillr/noble-hashes), - [post-quantum](https://github.com/paulmillr/noble-post-quantum), - 4kb [secp256k1](https://github.com/paulmillr/noble-secp256k1) / - [ed25519](https://github.com/paulmillr/noble-ed25519) -- [Check out homepage](https://paulmillr.com/noble/) - for reading resources, documentation and apps built with noble - -## Usage - -> `npm install @noble/curves` - -> `deno add jsr:@noble/curves` - -> `deno doc jsr:@noble/curves` # command-line documentation - -We support all major platforms and runtimes. -For React Native, you may need a [polyfill for getRandomValues](https://github.com/LinusU/react-native-get-random-values). -A standalone file [noble-curves.js](https://github.com/paulmillr/noble-curves/releases) is also available. - -```js -// import * from '@noble/curves'; // Error: use sub-imports, to ensure small app size -import { secp256k1 } from '@noble/curves/secp256k1'; // ESM and Common.js -// import { secp256k1 } from 'npm:@noble/curves@1.6.0/secp256k1'; // Deno -``` - -- [Implementations](#implementations) - - [ECDSA signatures over secp256k1 and others](#ecdsa-signatures-over-secp256k1-and-others) - - [ECDSA public key recovery & extra entropy](#ecdsa-public-key-recovery--extra-entropy) - - [ECDH: Elliptic Curve Diffie-Hellman](#ecdh-elliptic-curve-diffie-hellman) - - [Schnorr signatures over secp256k1, BIP340](#schnorr-signatures-over-secp256k1-bip340) - - [ed25519, X25519, ristretto255](#ed25519-x25519-ristretto255) - - [ed448, X448, decaf448](#ed448-x448-decaf448) - - [bls12-381](#bls12-381) - - [bn254 aka alt_bn128](#bn254-aka-alt_bn128) - - [Multi-scalar-multiplication](#multi-scalar-multiplication) - - [Accessing a curve's variables](#accessing-a-curves-variables) - - [All available imports](#all-available-imports) -- [Abstract API](#abstract-api) - - [weierstrass: Short Weierstrass curve](#weierstrass-short-weierstrass-curve) - - [edwards: Twisted Edwards curve](#edwards-twisted-edwards-curve) - - [montgomery: Montgomery curve](#montgomery-montgomery-curve) - - [bls: Barreto-Lynn-Scott curves](#bls-barreto-lynn-scott-curves) - - [hash-to-curve: Hashing strings to curve points](#hash-to-curve-hashing-strings-to-curve-points) - - [poseidon: Poseidon hash](#poseidon-poseidon-hash) - - [modular: Modular arithmetics utilities](#modular-modular-arithmetics-utilities) - - [Creating private keys from hashes](#creating-private-keys-from-hashes) - - [utils: Useful utilities](#utils-useful-utilities) -- [Security](#security) -- [Speed](#speed) -- [Upgrading](#upgrading) -- [Contributing & testing](#contributing--testing) -- [License](#license) - -### Implementations - -Implementations use [noble-hashes](https://github.com/paulmillr/noble-hashes). -If you want to use a different hashing library, [abstract API](#abstract-api) doesn't depend on them. - -#### ECDSA signatures over secp256k1 and others - -```ts -import { secp256k1 } from '@noble/curves/secp256k1'; -// import { p256 } from '@noble/curves/p256'; // or p384 / p521 - -const priv = secp256k1.utils.randomPrivateKey(); -const pub = secp256k1.getPublicKey(priv); -const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa -const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available -const isValid = secp256k1.verify(sig, msg, pub) === true; - -// hex strings are also supported besides Uint8Array-s: -const privHex = '46c930bc7bb4db7f55da20798697421b98c4175a52c630294d75a84b9c126236'; -const pub2 = secp256k1.getPublicKey(privHex); -``` - -The same code would work for NIST P256 (secp256r1), P384 (secp384r1) & P521 (secp521r1). - -#### ECDSA public key recovery & extra entropy - -```ts -// let sig = secp256k1.Signature.fromCompact(sigHex); // or .fromDER(sigDERHex) -// sig = sig.addRecoveryBit(bit); // bit is not serialized into compact / der format -sig.recoverPublicKey(msg).toRawBytes(); // === pub; // public key recovery - -// extraEntropy https://moderncrypto.org/mail-archive/curves/2017/000925.html -const sigImprovedSecurity = secp256k1.sign(msg, priv, { extraEntropy: true }); -``` - -#### ECDH: Elliptic Curve Diffie-Hellman - -```ts -// 1. The output includes parity byte. Strip it using shared.slice(1) -// 2. The output is not hashed. More secure way is sha256(shared) or hkdf(shared) -const someonesPub = secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey()); -const shared = secp256k1.getSharedSecret(priv, someonesPub); -``` - -#### Schnorr signatures over secp256k1 (BIP340) - -```ts -import { schnorr } from '@noble/curves/secp256k1'; -const priv = schnorr.utils.randomPrivateKey(); -const pub = schnorr.getPublicKey(priv); -const msg = new TextEncoder().encode('hello'); -const sig = schnorr.sign(msg, priv); -const isValid = schnorr.verify(sig, msg, pub); -``` - -#### ed25519, X25519, ristretto255 - -```ts -import { ed25519 } from '@noble/curves/ed25519'; -const priv = ed25519.utils.randomPrivateKey(); -const pub = ed25519.getPublicKey(priv); -const msg = new TextEncoder().encode('hello'); -const sig = ed25519.sign(msg, priv); -ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 -ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 -``` - -Default `verify` behavior follows [ZIP215](https://zips.z.cash/zip-0215) and -[can be used in consensus-critical applications](https://hdevalence.ca/blog/2020-10-04-its-25519am). -It has SUF-CMA (strong unforgeability under chosen message attacks). -`zip215: false` option switches verification criteria to strict -[RFC8032](https://www.rfc-editor.org/rfc/rfc8032) / [FIPS 186-5](https://csrc.nist.gov/publications/detail/fips/186/5/final) -and additionally provides [non-repudiation with SBS](#edwards-twisted-edwards-curve). - -X25519 follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748). - -```ts -// Variants from RFC8032: with context, prehashed -import { ed25519ctx, ed25519ph } from '@noble/curves/ed25519'; - -// ECDH using curve25519 aka x25519 -import { x25519 } from '@noble/curves/ed25519'; -const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; -const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; -x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases -x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); -x25519.getPublicKey(x25519.utils.randomPrivateKey()); - -// ed25519 => x25519 conversion -import { edwardsToMontgomeryPub, edwardsToMontgomeryPriv } from '@noble/curves/ed25519'; -edwardsToMontgomeryPub(ed25519.getPublicKey(ed25519.utils.randomPrivateKey())); -edwardsToMontgomeryPriv(ed25519.utils.randomPrivateKey()); -``` - -ristretto255 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448). - -```ts -// hash-to-curve, ristretto255 -import { utf8ToBytes } from '@noble/hashes/utils'; -import { sha512 } from '@noble/hashes/sha512'; -import { - hashToCurve, - encodeToCurve, - RistrettoPoint, - hashToRistretto255, -} from '@noble/curves/ed25519'; - -const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee'); -hashToCurve(msg); - -const rp = RistrettoPoint.fromHex( - '6a493210f7499cd17fecb510ae0cea23a110e8d5b901f8acadd3095c73a3b919' -); -RistrettoPoint.BASE.multiply(2n).add(rp).subtract(RistrettoPoint.BASE).toRawBytes(); -RistrettoPoint.ZERO.equals(dp) === false; -// pre-hashed hash-to-curve -RistrettoPoint.hashToCurve(sha512(msg)); -// full hash-to-curve including domain separation tag -hashToRistretto255(msg, { DST: 'ristretto255_XMD:SHA-512_R255MAP_RO_' }); -``` - -#### ed448, X448, decaf448 - -```ts -import { ed448 } from '@noble/curves/ed448'; -const priv = ed448.utils.randomPrivateKey(); -const pub = ed448.getPublicKey(priv); -const msg = new TextEncoder().encode('whatsup'); -const sig = ed448.sign(msg, priv); -ed448.verify(sig, msg, pub); - -// Variants from RFC8032: prehashed -import { ed448ph } from '@noble/curves/ed448'; -``` - -ECDH using Curve448 aka X448, follows [RFC7748](https://www.rfc-editor.org/rfc/rfc7748). - -```ts -import { x448 } from '@noble/curves/ed448'; -x448.getSharedSecret(priv, pub) === x448.scalarMult(priv, pub); // aliases -x448.getPublicKey(priv) === x448.scalarMultBase(priv); - -// ed448 => x448 conversion -import { edwardsToMontgomeryPub } from '@noble/curves/ed448'; -edwardsToMontgomeryPub(ed448.getPublicKey(ed448.utils.randomPrivateKey())); -``` - -decaf448 follows [irtf draft](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448). - -```ts -import { utf8ToBytes } from '@noble/hashes/utils'; -import { shake256 } from '@noble/hashes/sha3'; -import { hashToCurve, encodeToCurve, DecafPoint, hashToDecaf448 } from '@noble/curves/ed448'; - -const msg = utf8ToBytes('Ristretto is traditionally a short shot of espresso coffee'); -hashToCurve(msg); - -const dp = DecafPoint.fromHex( - 'c898eb4f87f97c564c6fd61fc7e49689314a1f818ec85eeb3bd5514ac816d38778f69ef347a89fca817e66defdedce178c7cc709b2116e75' -); -DecafPoint.BASE.multiply(2n).add(dp).subtract(DecafPoint.BASE).toRawBytes(); -DecafPoint.ZERO.equals(dp) === false; -// pre-hashed hash-to-curve -DecafPoint.hashToCurve(shake256(msg, { dkLen: 112 })); -// full hash-to-curve including domain separation tag -hashToDecaf448(msg, { DST: 'decaf448_XOF:SHAKE256_D448MAP_RO_' }); -``` - -Same RFC7748 / RFC8032 / IRTF draft are followed. - -#### bls12-381 - -```ts -import { bls12_381 as bls } from '@noble/curves/bls12-381'; - -// G1 keys, G2 signatures -const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; -const message = '64726e3da8'; -const publicKey = bls.getPublicKey(privateKey); -const signature = bls.sign(message, privateKey); -const isValid = bls.verify(signature, message, publicKey); -console.log({ publicKey, signature, isValid }); - -// G2 keys, G1 signatures -// getPublicKeyForShortSignatures(privateKey) -// signShortSignature(message, privateKey) -// verifyShortSignature(signature, message, publicKey) -// aggregateShortSignatures(signatures) - -// Custom DST -const htfEthereum = { DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_' }; -const signatureEth = bls.sign(message, privateKey, htfEthereum); -const isValidEth = bls.verify(signature, message, publicKey, htfEthereum); - -// Aggregation -const aggregatedKey = bls.aggregatePublicKeys([bls.utils.randomPrivateKey(), bls.utils.randomPrivateKey()]) -// const aggregatedSig = bls.aggregateSignatures(sigs) - -// Pairings, with and without final exponentiation -// bls.pairing(PointG1, PointG2); -// bls.pairing(PointG1, PointG2, false); -// bls.fields.Fp12.finalExponentiate(bls.fields.Fp12.mul(PointG1, PointG2)); - -// Others -// bls.G1.ProjectivePoint.BASE, bls.G2.ProjectivePoint.BASE; -// bls.fields.Fp, bls.fields.Fp2, bls.fields.Fp12, bls.fields.Fr; -``` - -See [abstract/bls](#bls-barreto-lynn-scott-curves). -For example usage, check out [the implementation of BLS EVM precompiles](https://github.com/ethereumjs/ethereumjs-monorepo/blob/361f4edbc239e795a411ac2da7e5567298b9e7e5/packages/evm/src/precompiles/bls12_381/noble.ts). - -#### bn254 aka alt_bn128 - -```ts -import { bn254 } from '@noble/curves/bn254'; - -console.log( - bn254.G1, - bn254.G2, - bn254.pairing -) -``` - -The API mirrors [BLS](#bls12-381). The curve was previously called alt_bn128. -The implementation is compatible with [EIP-196](https://eips.ethereum.org/EIPS/eip-196) and -[EIP-197](https://eips.ethereum.org/EIPS/eip-197). - -Keep in mind that we don't implement Point methods toHex / toRawBytes. It's because -different implementations of bn254 do it differently - there is no standard. Points of divergence: - -- Endianness: LE vs BE (byte-swapped) -- Flags as first hex bits (similar to BLS) vs no-flags -- Imaginary part last in G2 vs first (c0, c1 vs c1, c0) - -For example usage, check out [the implementation of bn254 EVM precompiles](https://github.com/paulmillr/noble-curves/blob/3ed792f8ad9932765b84d1064afea8663a255457/test/bn254.test.js#L697). - -#### Multi-scalar-multiplication - -```ts -import { secp256k1 } from '@noble/curves/secp256k1'; -const p = secp256k1.ProjectivePoint; -const points = [p.BASE, p.BASE.multiply(2n), p.BASE.multiply(4n), p.BASE.multiply(8n)]; -p.msm(points, [3n, 5n, 7n, 11n]).equals(p.BASE.multiply(129n)); // 129*G -``` - -Pippenger algorithm is used underneath. -Multi-scalar-multiplication (MSM) is basically `(Pa + Qb + Rc + ...)`. -It's 10-30x faster vs naive addition for large amount of points. - -#### Accessing a curve's variables - -```ts -import { secp256k1 } from '@noble/curves/secp256k1'; -// Every curve has `CURVE` object that contains its parameters, field, and others -console.log(secp256k1.CURVE.p); // field modulus -console.log(secp256k1.CURVE.n); // curve order -console.log(secp256k1.CURVE.a, secp256k1.CURVE.b); // equation params -console.log(secp256k1.CURVE.Gx, secp256k1.CURVE.Gy); // base point coordinates -``` - - -#### All available imports - -```typescript -import { secp256k1, schnorr } from '@noble/curves/secp256k1'; -import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; -import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; -import { p256 } from '@noble/curves/p256'; -import { p384 } from '@noble/curves/p384'; -import { p521 } from '@noble/curves/p521'; -import { pallas, vesta } from '@noble/curves/pasta'; -import { bls12_381 } from '@noble/curves/bls12-381'; -import { bn254 } from '@noble/curves/bn254'; // also known as alt_bn128 -import { jubjub } from '@noble/curves/jubjub'; -import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; -``` - -## Abstract API - -Abstract API allows to define custom curves. All arithmetics is done with JS -bigints over finite fields, which is defined from `modular` sub-module. For -scalar multiplication, we use -[precomputed tables with w-ary non-adjacent form (wNAF)](https://paulmillr.com/posts/noble-secp256k1-fast-ecc/). -Precomputes are enabled for weierstrass and edwards BASE points of a curve. You -could precompute any other point (e.g. for ECDH) using `utils.precompute()` -method: check out examples. - -### weierstrass: Short Weierstrass curve - -```ts -import { weierstrass } from '@noble/curves/abstract/weierstrass'; -import { Field } from '@noble/curves/abstract/modular'; // finite field for mod arithmetics -import { sha256 } from '@noble/hashes/sha256'; // 3rd-party sha256() of type utils.CHash -import { hmac } from '@noble/hashes/hmac'; // 3rd-party hmac() that will accept sha256() -import { concatBytes, randomBytes } from '@noble/hashes/utils'; // 3rd-party utilities - -const hmacSha256 = (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)); - -// secq256k1: cycle of secp256k1 with Fp/N flipped. -// https://personaelabs.org/posts/spartan-ecdsa -// https://zcash.github.io/halo2/background/curves.html#cycles-of-curves -const secq256k1 = weierstrass({ - // Curve equation params a, b - a: 0n, - b: 7n, - // Field over which we'll do calculations - Fp: Field(2n ** 256n - 432420386565659656852420866394968145599n), - // Curve order, total count of valid points in the field. - n: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n, - // Base point (x, y) aka generator point - Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n, - Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n, - - hash: sha256, - hmac: hmacSha256, - randomBytes, -}); - -// NIST secp192r1 aka p192 https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/secg/secp192r1 -const secp192r1 = weierstrass({ - a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffc'), - b: BigInt('0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1'), - Fp: Field(BigInt('0xfffffffffffffffffffffffffffffffeffffffffffffffff')), - n: BigInt('0xffffffffffffffffffffffff99def836146bc9b1b4d22831'), - Gx: BigInt('0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'), - Gy: BigInt('0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811'), - h: BigInt(1), - hash: sha256, - hmac: hmacSha256, - randomBytes, -}); - - -// Replace weierstrass() with weierstrassPoints() if you don't need ECDSA, hash, hmac, randomBytes -``` - -Short Weierstrass curve's formula is `y² = x³ + ax + b`. `weierstrass` -expects arguments `a`, `b`, field `Fp`, curve order `n`, cofactor `h` -and coordinates `Gx`, `Gy` of generator point. - -**`k` generation** is done deterministically, following -[RFC6979](https://www.rfc-editor.org/rfc/rfc6979). It is suggested to use `extraEntropy` -option, which incorporates randomness into signatures to increase their security. - -For k generation, specifying `hmac` & `hash` is required, -which in our implementations is done by noble-hashes. If -you're using different hashing library, make sure to wrap it in the following interface: - -```ts -type CHash = { - (message: Uint8Array): Uint8Array; - blockLen: number; - outputLen: number; - create(): any; -}; - -// example -function sha256(message: Uint8Array) { - return _internal_lowlvl(message); -} -sha256.outputLen = 32; // 32 bytes of output for sha2-256 -``` - -**Message hash** is expected instead of message itself: - -- `sign(msgHash, privKey)` is default behavior, assuming you pre-hash msg with sha2, or other hash -- `sign(msg, privKey, {prehash: true})` option can be used if you want to pass the message itself - -**Weierstrass points:** - -1. Exported as `ProjectivePoint` -2. Represented in projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) -3. Use complete exception-free formulas for addition and doubling -4. Can be decoded/encoded from/to Uint8Array / hex strings using - `ProjectivePoint.fromHex` and `ProjectivePoint#toRawBytes()` -5. Have `assertValidity()` which checks for being on-curve -6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates - -```ts -// `weierstrassPoints()` returns `CURVE` and `ProjectivePoint` -// `weierstrass()` returns `CurveFn` -type SignOpts = { lowS?: boolean; prehash?: boolean; extraEntropy: boolean | Uint8Array }; -type CurveFn = { - CURVE: ReturnType; - getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array; - getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array; - sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => SignatureType; - verify: ( - signature: Hex | SignatureType, - msgHash: Hex, - publicKey: Hex, - opts?: { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' } - ) => boolean; - ProjectivePoint: ProjectivePointConstructor; - Signature: SignatureConstructor; - utils: { - normPrivateKeyToScalar: (key: PrivKey) => bigint; - isValidPrivateKey(key: PrivKey): boolean; - randomPrivateKey: () => Uint8Array; - precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType; - }; -}; - -// T is usually bigint, but can be something else like complex numbers in BLS curves -interface ProjPointType extends Group> { - readonly px: T; - readonly py: T; - readonly pz: T; - get x(): bigint; - get y(): bigint; - multiply(scalar: bigint): ProjPointType; - multiplyUnsafe(scalar: bigint): ProjPointType; - multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined; - toAffine(iz?: T): AffinePoint; - isTorsionFree(): boolean; - clearCofactor(): ProjPointType; - assertValidity(): void; - hasEvenY(): boolean; - toRawBytes(isCompressed?: boolean): Uint8Array; - toHex(isCompressed?: boolean): string; -} -// Static methods for 3d XYZ points -interface ProjConstructor extends GroupConstructor> { - new (x: T, y: T, z: T): ProjPointType; - fromAffine(p: AffinePoint): ProjPointType; - fromHex(hex: Hex): ProjPointType; - fromPrivateKey(privateKey: PrivKey): ProjPointType; - msm(points: ProjPointType[], scalars: bigint[]): ProjPointType; -} -``` - -**ECDSA signatures** are represented by `Signature` instances and can be -described by the interface: - -```ts -interface SignatureType { - readonly r: bigint; - readonly s: bigint; - readonly recovery?: number; - assertValidity(): void; - addRecoveryBit(recovery: number): SignatureType; - hasHighS(): boolean; - normalizeS(): SignatureType; - recoverPublicKey(msgHash: Hex): ProjPointType; - toCompactRawBytes(): Uint8Array; - toCompactHex(): string; - // DER-encoded - toDERRawBytes(): Uint8Array; - toDERHex(): string; -} -type SignatureConstructor = { - new (r: bigint, s: bigint): SignatureType; - fromCompact(hex: Hex): SignatureType; - fromDER(hex: Hex): SignatureType; -}; -``` - -More examples: - -```typescript -// All curves expose same generic interface. -const priv = secq256k1.utils.randomPrivateKey(); -secq256k1.getPublicKey(priv); // Convert private key to public. -const sig = secq256k1.sign(msg, priv); // Sign msg with private key. -const sig2 = secq256k1.sign(msg, priv, { prehash: true }); // hash(msg) -secq256k1.verify(sig, msg, priv); // Verify if sig is correct. - -// Default behavior is "try DER, then try compact if fails". Can be explicit: -secq256k1.verify(sig.toCompactHex(), msg, priv, { format: 'compact' }); - -const Point = secq256k1.ProjectivePoint; -const point = Point.BASE; // Elliptic curve Point class and BASE point static var. -point.add(point).equals(point.double()); // add(), equals(), double() methods -point.subtract(point).equals(Point.ZERO); // subtract() method, ZERO static var -point.negate(); // Flips point over x/y coordinate. -point.multiply(31415n); // Multiplication of Point by scalar. - -point.assertValidity(); // Checks for being on-curve -point.toAffine(); // Converts to 2d affine xy coordinates - -secq256k1.CURVE.n; -secq256k1.CURVE.p; -secq256k1.CURVE.Fp.mod(); -secq256k1.CURVE.hash(); - -// precomputes -const fast = secq256k1.utils.precompute(8, Point.fromHex(someonesPubKey)); -fast.multiply(privKey); // much faster ECDH now -``` - -### edwards: Twisted Edwards curve - -```ts -import { twistedEdwards } from '@noble/curves/abstract/edwards'; -import { Field } from '@noble/curves/abstract/modular'; -import { sha512 } from '@noble/hashes/sha512'; -import { randomBytes } from '@noble/hashes/utils'; - -const Fp = Field(2n ** 255n - 19n); -const ed25519 = twistedEdwards({ - a: Fp.create(-1n), - d: Fp.div(-121665n, 121666n), // -121665n/121666n mod p - Fp: Fp, - n: 2n ** 252n + 27742317777372353535851937790883648493n, - h: 8n, - Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n, - Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n, - hash: sha512, - randomBytes, - adjustScalarBytes(bytes) { - // optional; but mandatory in ed25519 - bytes[0] &= 248; - bytes[31] &= 127; - bytes[31] |= 64; - return bytes; - }, -} as const); -``` - -Twisted Edwards curve's formula is `ax² + y² = 1 + dx²y²`. You must specify `a`, `d`, field `Fp`, order `n`, cofactor `h` -and coordinates `Gx`, `Gy` of generator point. - -For EdDSA signatures, `hash` param required. `adjustScalarBytes` which instructs how to change private scalars could be specified. - -We support [non-repudiation](https://eprint.iacr.org/2020/1244), which help in following scenarios: - -- Contract Signing: if A signed an agreement with B using key that allows repudiation, it can later claim that it signed a different contract -- E-voting: malicious voters may pick keys that allow repudiation in order to deny results -- Blockchains: transaction of amount X might also be valid for a different amount Y - -**Edwards points:** - -1. Exported as `ExtendedPoint` -2. Represented in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z) -3. Use complete exception-free formulas for addition and doubling -4. Can be decoded/encoded from/to Uint8Array / hex strings using `ExtendedPoint.fromHex` and `ExtendedPoint#toRawBytes()` -5. Have `assertValidity()` which checks for being on-curve -6. Have `toAffine()` and `x` / `y` getters which convert to 2d xy affine coordinates -7. Have `isTorsionFree()`, `clearCofactor()` and `isSmallOrder()` utilities to handle torsions - -```ts -// `twistedEdwards()` returns `CurveFn` of following type: -type CurveFn = { - CURVE: ReturnType; - getPublicKey: (privateKey: Hex) => Uint8Array; - sign: (message: Hex, privateKey: Hex, context?: Hex) => Uint8Array; - verify: (sig: SigType, message: Hex, publicKey: Hex, context?: Hex) => boolean; - ExtendedPoint: ExtPointConstructor; - utils: { - randomPrivateKey: () => Uint8Array; - getExtendedPublicKey: (key: PrivKey) => { - head: Uint8Array; - prefix: Uint8Array; - scalar: bigint; - point: PointType; - pointBytes: Uint8Array; - }; - }; -}; - -interface ExtPointType extends Group { - readonly ex: bigint; - readonly ey: bigint; - readonly ez: bigint; - readonly et: bigint; - get x(): bigint; - get y(): bigint; - assertValidity(): void; - multiply(scalar: bigint): ExtPointType; - multiplyUnsafe(scalar: bigint): ExtPointType; - isSmallOrder(): boolean; - isTorsionFree(): boolean; - clearCofactor(): ExtPointType; - toAffine(iz?: bigint): AffinePoint; - toRawBytes(isCompressed?: boolean): Uint8Array; - toHex(isCompressed?: boolean): string; -} -// Static methods of Extended Point with coordinates in X, Y, Z, T -interface ExtPointConstructor extends GroupConstructor { - new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType; - fromAffine(p: AffinePoint): ExtPointType; - fromHex(hex: Hex): ExtPointType; - fromPrivateKey(privateKey: Hex): ExtPointType; - msm(points: ExtPointType[], scalars: bigint[]): ExtPointType; -} -``` - -### montgomery: Montgomery curve - -```typescript -import { montgomery } from '@noble/curves/abstract/montgomery'; -import { Field } from '@noble/curves/abstract/modular'; - -const x25519 = montgomery({ - a: 486662n, - Gu: 9n, - P: 2n ** 255n - 19n, - montgomeryBits: 255, - nByteLength: 32, - // Optional param - adjustScalarBytes(bytes) { - bytes[0] &= 248; - bytes[31] &= 127; - bytes[31] |= 64; - return bytes; - }, -}); -``` - -The module contains methods for x-only ECDH on Curve25519 / Curve448 from RFC7748. -Proper Elliptic Curve Points are not implemented yet. - -You must specify curve params `Fp`, `a`, `Gu` coordinate of u, `montgomeryBits` and `nByteLength`. - -### bls: Barreto-Lynn-Scott curves - -The module abstracts BLS (Barreto-Lynn-Scott) pairing-friendly elliptic curve construction. -They allow to construct [zk-SNARKs](https://z.cash/technology/zksnarks/) and -use aggregated, batch-verifiable -[threshold signatures](https://medium.com/snigirev.stepan/bls-signatures-better-than-schnorr-5a7fe30ea716), -using Boneh-Lynn-Shacham signature scheme. - -The module doesn't expose `CURVE` property: use `G1.CURVE`, `G2.CURVE` instead. -Only BLS12-381 is currently implemented. -Defining BLS12-377 and BLS24 should be straightforward. - -The default BLS uses short public keys (with public keys in G1 and signatures in G2). -Short signatures (public keys in G2 and signatures in G1) are also supported. - -### hash-to-curve: Hashing strings to curve points - -The module allows to hash arbitrary strings to elliptic curve points. Implements [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - -Every curve has exported `hashToCurve` and `encodeToCurve` methods. You should always prefer `hashToCurve` for security: - -```ts -import { hashToCurve, encodeToCurve } from '@noble/curves/secp256k1'; -import { randomBytes } from '@noble/hashes/utils'; -hashToCurve('0102abcd'); -console.log(hashToCurve(randomBytes())); -console.log(encodeToCurve(randomBytes())); - -import { bls12_381 } from '@noble/curves/bls12-381'; -bls12_381.G1.hashToCurve(randomBytes(), { DST: 'another' }); -bls12_381.G2.hashToCurve(randomBytes(), { DST: 'custom' }); -``` - -Low-level methods from the spec: - -```ts -// produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. -function expand_message_xmd( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - H: CHash // For CHash see abstract/weierstrass docs section -): Uint8Array; -// produces a uniformly random byte string using an extendable-output function (XOF) H. -function expand_message_xof( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - k: number, - H: CHash -): Uint8Array; -// Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F -function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][]; - -/** - * * `DST` is a domain separation tag, defined in section 2.2.5 - * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m - * * `m` is extension degree (1 for prime fields) - * * `k` is the target security target in bits (e.g. 128), from section 5.1 - * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) - * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props - */ -type UnicodeOrBytes = string | Uint8Array; -type Opts = { - DST: UnicodeOrBytes; - p: bigint; - m: number; - k: number; - expand?: 'xmd' | 'xof'; - hash: CHash; -}; -``` - -### poseidon: Poseidon hash - -Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - -There are many poseidon variants with different constants. -We don't provide them: you should construct them manually. -Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - -```ts -import { poseidon } from '@noble/curves/abstract/poseidon'; - -type PoseidonOpts = { - Fp: Field; - t: number; - roundsFull: number; - roundsPartial: number; - sboxPower?: number; - reversePartialPowIdx?: boolean; - mds: bigint[][]; - roundConstants: bigint[][]; -}; -const instance = poseidon(opts: PoseidonOpts); -``` - -### modular: Modular arithmetics utilities - -```ts -import * as mod from '@noble/curves/abstract/modular'; - -// Finite Field utils -const fp = mod.Field(2n ** 255n - 19n); // Finite field over 2^255-19 -fp.mul(591n, 932n); // multiplication -fp.pow(481n, 11024858120n); // exponentiation -fp.div(5n, 17n); // division: 5/17 mod 2^255-19 == 5 * invert(17) -fp.inv(5n); // modular inverse -fp.sqrt(21n); // square root - -// Non-Field generic utils are also available -mod.mod(21n, 10n); // 21 mod 10 == 1n; fixed version of 21 % 10 -mod.invert(17n, 10n); // invert(17) mod 10; modular multiplicative inverse -mod.invertBatch([1n, 2n, 4n], 21n); // => [1n, 11n, 16n] in one inversion -``` - -Field operations are not constant-time: they are using JS bigints, see [security](#security). -The fact is mostly irrelevant, but the important method to keep in mind is `pow`, -which may leak exponent bits, when used naïvely. - -`mod.Field` is always **field over prime number**. Non-prime fields aren't supported for now. -We don't test for prime-ness for speed and because algorithms are probabilistic anyway. -Initializing a non-prime field could make your app suspectible to -DoS (infilite loop) on Tonelli-Shanks square root calculation. - -Unlike `mod.inv`, `mod.invertBatch` won't throw on `0`: make sure to throw an error yourself. - -#### Creating private keys from hashes - -You can't simply make a 32-byte private key from a 32-byte hash. -Doing so will make the key [biased](https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/). - -To make the bias negligible, we follow [FIPS 186-5 A.2](https://csrc.nist.gov/publications/detail/fips/186/5/final) -and [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). -This means, for 32-byte key, we would need 48-byte hash to get 2^-128 bias, which matches curve security level. - -`hashToPrivateScalar()` that hashes to **private key** was created for this purpose. -Use [abstract/hash-to-curve](#hash-to-curve-hashing-strings-to-curve-points) -if you need to hash to **public key**. - -```ts -import { p256 } from '@noble/curves/p256'; -import { sha256 } from '@noble/hashes/sha256'; -import { hkdf } from '@noble/hashes/hkdf'; -import * as mod from '@noble/curves/abstract/modular'; -const someKey = new Uint8Array(32).fill(2); // Needs to actually be random, not .fill(2) -const derived = hkdf(sha256, someKey, undefined, 'application', 48); // 48 bytes for 32-byte priv -const validPrivateKey = mod.hashToPrivateScalar(derived, p256.CURVE.n); -``` - -### utils: Useful utilities - -```ts -import * as utils from '@noble/curves/abstract/utils'; - -utils.bytesToHex(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); -utils.hexToBytes('deadbeef'); -utils.numberToHexUnpadded(123n); -utils.hexToNumber(); - -utils.bytesToNumberBE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); -utils.bytesToNumberLE(Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); -utils.numberToBytesBE(123n, 32); -utils.numberToBytesLE(123n, 64); - -utils.concatBytes(Uint8Array.from([0xde, 0xad]), Uint8Array.from([0xbe, 0xef])); -utils.nLength(255n); -utils.equalBytes(Uint8Array.from([0xde]), Uint8Array.from([0xde])); -``` - -## Security - -The library has been independently audited: - -- at version 1.6.0, in Sep 2024, by [Cure53](https://cure53.de) - - PDFs: [website](https://cure53.de/audit-report_noble-crypto-libs.pdf), [in-repo](./audit/2024-09-cure53-audit-nbl4.pdf) - - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.6.0..main) - - Scope: ed25519, ed448, their add-ons, bls12-381, bn254, - hash-to-curve, low-level primitives bls, tower, edwards, montgomery. - - The audit has been funded by [OpenSats](https://opensats.org) -- at version 1.2.0, in Sep 2023, by [Kudelski Security](https://kudelskisecurity.com) - - PDFs: [in-repo](./audit/2023-09-kudelski-audit-starknet.pdf) - - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/1.2.0..main) - - Scope: [scure-starknet](https://github.com/paulmillr/scure-starknet) and its related - abstract modules of noble-curves: `curve`, `modular`, `poseidon`, `weierstrass` - - The audit has been funded by [Starkware](https://starkware.co) -- at version 0.7.3, in Feb 2023, by [Trail of Bits](https://www.trailofbits.com) - - PDFs: [website](https://github.com/trailofbits/publications/blob/master/reviews/2023-01-ryanshea-noblecurveslibrary-securityreview.pdf), - [in-repo](./audit/2023-01-trailofbits-audit-curves.pdf) - - [Changes since audit](https://github.com/paulmillr/noble-curves/compare/0.7.3..main) - - Scope: abstract modules `curve`, `hash-to-curve`, `modular`, `poseidon`, `utils`, `weierstrass` and - top-level modules `_shortw_utils` and `secp256k1` - - The audit has been funded by [Ryan Shea](https://www.shea.io) - -It is tested against property-based, cross-library and Wycheproof vectors, -and has fuzzing by [Guido Vranken's cryptofuzz](https://github.com/guidovranken/cryptofuzz). - -If you see anything unusual: investigate and report. - -### Constant-timeness - -_JIT-compiler_ and _Garbage Collector_ make "constant time" extremely hard to -achieve [timing attack](https://en.wikipedia.org/wiki/Timing_attack) resistance -in a scripting language. Which means _any other JS library can't have -constant-timeness_. Even statically typed Rust, a language without GC, -[makes it harder to achieve constant-time](https://www.chosenplaintext.ca/open-source/rust-timing-shield/security) -for some cases. If your goal is absolute security, don't use any JS lib — including bindings to native ones. -Use low-level libraries & languages. Nonetheless we're targetting algorithmic constant time. - -### Supply chain security - -- **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures. -- **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs -- **Rare releasing** is followed to ensure less re-audit need for end-users -- **Dependencies** are minimized and locked-down: - - If your app has 500 dependencies, any dep could get hacked and you'll be downloading - malware with every install. We make sure to use as few dependencies as possible - - We prevent automatic dependency updates by locking-down version ranges. Every update is checked with `npm-diff` - - One dependency [noble-hashes](https://github.com/paulmillr/noble-hashes) is used, by the same author, to provide hashing functionality -- **Dev Dependencies** are only used if you want to contribute to the repo. They are disabled for end-users: - - scure-base, scure-bip32, scure-bip39, micro-bmark and micro-should are developed by the same author and follow identical security practices - - prettier (linter), fast-check (property-based testing) and typescript are used for code quality, vector generation and ts compilation. The packages are big, which makes it hard to audit their source code thoroughly and fully - -### Randomness - -We're deferring to built-in -[crypto.getRandomValues](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) -which is considered cryptographically secure (CSPRNG). - -In the past, browsers had bugs that made it weak: it may happen again. -Implementing a userspace CSPRNG to get resilient to the weakness -is even worse: there is no reliable userspace source of quality entropy. - -### Quantum computers - -Cryptographically relevant quantum computer, if built, will allow to -break elliptic curve cryptography (both ECDSA / EdDSA & ECDH) using Shor's algorithm. - -Consider switching to newer / hybrid algorithms, such as SPHINCS+. They are available in -[noble-post-quantum](https://github.com/paulmillr/noble-post-quantum). - -NIST prohibits classical cryptography (RSA, DSA, ECDSA, ECDH) [after 2035](https://nvlpubs.nist.gov/nistpubs/ir/2024/NIST.IR.8547.ipd.pdf). Australian ASD prohibits it [after 2030](https://www.cyber.gov.au/resources-business-and-government/essential-cyber-security/ism/cyber-security-guidelines/guidelines-cryptography). - -## Speed - -Benchmark results on Apple M2 with node v22: - -``` -secp256k1 -init x 68 ops/sec @ 14ms/op -getPublicKey x 6,839 ops/sec @ 146μs/op -sign x 5,226 ops/sec @ 191μs/op -verify x 893 ops/sec @ 1ms/op -getSharedSecret x 538 ops/sec @ 1ms/op -recoverPublicKey x 923 ops/sec @ 1ms/op -schnorr.sign x 700 ops/sec @ 1ms/op -schnorr.verify x 919 ops/sec @ 1ms/op - -ed25519 -init x 51 ops/sec @ 19ms/op -getPublicKey x 9,809 ops/sec @ 101μs/op -sign x 4,976 ops/sec @ 200μs/op -verify x 1,018 ops/sec @ 981μs/op - -ed448 -init x 19 ops/sec @ 50ms/op -getPublicKey x 3,723 ops/sec @ 268μs/op -sign x 1,759 ops/sec @ 568μs/op -verify x 344 ops/sec @ 2ms/op - -p256 -init x 39 ops/sec @ 25ms/op -getPublicKey x 6,518 ops/sec @ 153μs/op -sign x 5,148 ops/sec @ 194μs/op -verify x 609 ops/sec @ 1ms/op - -p384 -init x 17 ops/sec @ 57ms/op -getPublicKey x 2,933 ops/sec @ 340μs/op -sign x 2,327 ops/sec @ 429μs/op -verify x 244 ops/sec @ 4ms/op - -p521 -init x 8 ops/sec @ 112ms/op -getPublicKey x 1,484 ops/sec @ 673μs/op -sign x 1,264 ops/sec @ 790μs/op -verify x 124 ops/sec @ 8ms/op - -ristretto255 -add x 680,735 ops/sec @ 1μs/op -multiply x 10,766 ops/sec @ 92μs/op -encode x 15,835 ops/sec @ 63μs/op -decode x 15,972 ops/sec @ 62μs/op - -decaf448 -add x 345,303 ops/sec @ 2μs/op -multiply x 300 ops/sec @ 3ms/op -encode x 5,987 ops/sec @ 167μs/op -decode x 5,892 ops/sec @ 169μs/op - -ecdh -├─x25519 x 1,477 ops/sec @ 676μs/op -├─secp256k1 x 537 ops/sec @ 1ms/op -├─p256 x 512 ops/sec @ 1ms/op -├─p384 x 198 ops/sec @ 5ms/op -├─p521 x 99 ops/sec @ 10ms/op -└─x448 x 504 ops/sec @ 1ms/op - -bls12-381 -init x 36 ops/sec @ 27ms/op -getPublicKey x 960 ops/sec @ 1ms/op -sign x 60 ops/sec @ 16ms/op -verify x 47 ops/sec @ 21ms/op -pairing x 125 ops/sec @ 7ms/op -pairing10 x 40 ops/sec @ 24ms/op ± 23.27% (min: 21ms, max: 48ms) -MSM 4096 scalars x points x 0 ops/sec @ 4655ms/op -aggregatePublicKeys/8 x 129 ops/sec @ 7ms/op -aggregatePublicKeys/32 x 34 ops/sec @ 28ms/op -aggregatePublicKeys/128 x 8 ops/sec @ 113ms/op -aggregatePublicKeys/512 x 2 ops/sec @ 449ms/op -aggregatePublicKeys/2048 x 0 ops/sec @ 1792ms/op -aggregateSignatures/8 x 62 ops/sec @ 15ms/op -aggregateSignatures/32 x 16 ops/sec @ 60ms/op -aggregateSignatures/128 x 4 ops/sec @ 238ms/op -aggregateSignatures/512 x 1 ops/sec @ 946ms/op -aggregateSignatures/2048 x 0 ops/sec @ 3774ms/op - -hash-to-curve -hash_to_field x 91,600 ops/sec @ 10μs/op -secp256k1 x 2,373 ops/sec @ 421μs/op -p256 x 4,310 ops/sec @ 231μs/op -p384 x 1,664 ops/sec @ 600μs/op -p521 x 807 ops/sec @ 1ms/op -ed25519 x 3,088 ops/sec @ 323μs/op -ed448 x 1,247 ops/sec @ 801μs/op -``` - -## Upgrading - -Previously, the library was split into single-feature packages -[noble-secp256k1](https://github.com/paulmillr/noble-secp256k1), -[noble-ed25519](https://github.com/paulmillr/noble-ed25519) and -[noble-bls12-381](https://github.com/paulmillr/noble-bls12-381). - -Curves continue their original work. The single-feature packages changed their -direction towards providing minimal 4kb implementations of cryptography, -which means they have less features. - -Upgrading from noble-secp256k1 2.0 or noble-ed25519 2.0: no changes, libraries are compatible. - -Upgrading from noble-secp256k1 1.7: - -- `getPublicKey` - - now produce 33-byte compressed signatures by default - - to use old behavior, which produced 65-byte uncompressed keys, set - argument `isCompressed` to `false`: `getPublicKey(priv, false)` -- `sign` - - is now sync - - now returns `Signature` instance with `{ r, s, recovery }` properties - - `canonical` option was renamed to `lowS` - - `recovered` option has been removed because recovery bit is always returned now - - `der` option has been removed. There are 2 options: - 1. Use compact encoding: `fromCompact`, `toCompactRawBytes`, `toCompactHex`. - Compact encoding is simply a concatenation of 32-byte r and 32-byte s. - 2. If you must use DER encoding, switch to noble-curves (see above). -- `verify` - - is now sync - - `strict` option was renamed to `lowS` -- `getSharedSecret` - - now produce 33-byte compressed signatures by default - - to use old behavior, which produced 65-byte uncompressed keys, set - argument `isCompressed` to `false`: `getSharedSecret(a, b, false)` -- `recoverPublicKey(msg, sig, rec)` was changed to `sig.recoverPublicKey(msg)` -- `number` type for private keys have been removed: use `bigint` instead -- `Point` (2d xy) has been changed to `ProjectivePoint` (3d xyz) -- `utils` were split into `utils` (same api as in noble-curves) and - `etc` (`hmacSha256Sync` and others) - -Upgrading from [@noble/ed25519](https://github.com/paulmillr/noble-ed25519) 1.7: - -- Methods are now sync by default -- `bigint` is no longer allowed in `getPublicKey`, `sign`, `verify`. Reason: ed25519 is LE, can lead to bugs -- `Point` (2d xy) has been changed to `ExtendedPoint` (xyzt) -- `Signature` was removed: just use raw bytes or hex now -- `utils` were split into `utils` (same api as in noble-curves) and - `etc` (`sha512Sync` and others) -- `getSharedSecret` was moved to `x25519` module -- `toX25519` has been moved to `edwardsToMontgomeryPub` and `edwardsToMontgomeryPriv` methods - -Upgrading from [@noble/bls12-381](https://github.com/paulmillr/noble-bls12-381): - -- Methods and classes were renamed: - - PointG1 -> G1.Point, PointG2 -> G2.Point - - PointG2.fromSignature -> Signature.decode, PointG2.toSignature -> Signature.encode -- Fp2 ORDER was corrected - -## Contributing & testing - -* `npm install && npm run build && npm test` will build the code and run tests. -* `npm run lint` / `npm run format` will run linter / fix linter issues. -* `npm run bench` will run benchmarks, which may need their deps first (`npm run bench:install`) -* `cd build && npm install && npm run build:release` will build single file - -Check out [github.com/paulmillr/guidelines](https://github.com/paulmillr/guidelines) -for general coding practices and rules. - -See [paulmillr.com/noble](https://paulmillr.com/noble/) -for useful resources, articles, documentation and demos -related to the library. - -## License - -The MIT License (MIT) - -Copyright (c) 2022 Paul Miller [(https://paulmillr.com)](https://paulmillr.com) - -See LICENSE file. diff --git a/packages/noble-curves/_shortw_utils.d.ts b/packages/noble-curves/_shortw_utils.d.ts deleted file mode 100644 index 02064fbb558..00000000000 --- a/packages/noble-curves/_shortw_utils.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { randomBytes } from '@noble/hashes/utils' -import type { CHash } from './abstract/utils.js' -import { type CurveFn, type CurveType } from './abstract/weierstrass.js' -/** connects noble-curves to noble-hashes */ -export declare function getHash(hash: CHash): { - hash: CHash - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array - randomBytes: typeof randomBytes -} -/** Same API as @noble/hashes, with ability to create curve with custom hash */ -export type CurveDef = Readonly> -export type CurveFnWithCreate = CurveFn & { - create: (hash: CHash) => CurveFn -} -export declare function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate -//# sourceMappingURL=_shortw_utils.d.ts.map diff --git a/packages/noble-curves/_shortw_utils.d.ts.map b/packages/noble-curves/_shortw_utils.d.ts.map deleted file mode 100644 index e1caf75120a..00000000000 --- a/packages/noble-curves/_shortw_utils.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG;IACpC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,KAAK,UAAU,CAAC;IAC7D,WAAW,EAAE,OAAO,WAAW,CAAC;CACjC,CAMA;AACD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,GAAG,iBAAiB,CAGjF"} \ No newline at end of file diff --git a/packages/noble-curves/_shortw_utils.js b/packages/noble-curves/_shortw_utils.js deleted file mode 100644 index c0d0396660c..00000000000 --- a/packages/noble-curves/_shortw_utils.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.getHash = getHash -exports.createCurve = createCurve -/** - * Utilities for short weierstrass curves, combined with noble-hashes. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const hmac_1 = require('@noble/hashes/hmac') -const utils_1 = require('@noble/hashes/utils') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -/** connects noble-curves to noble-hashes */ -function getHash(hash) { - return { - hash, - hmac: (key, ...msgs) => (0, hmac_1.hmac)(hash, key, (0, utils_1.concatBytes)(...msgs)), - randomBytes: utils_1.randomBytes, - } -} -function createCurve(curveDef, defHash) { - const create = (hash) => (0, weierstrass_js_1.weierstrass)({ ...curveDef, ...getHash(hash) }) - return { ...create(defHash), create } -} -//# sourceMappingURL=_shortw_utils.js.map diff --git a/packages/noble-curves/_shortw_utils.js.map b/packages/noble-curves/_shortw_utils.js.map deleted file mode 100644 index 9b3bc4dc02e..00000000000 --- a/packages/noble-curves/_shortw_utils.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"_shortw_utils.js","sourceRoot":"","sources":["src/_shortw_utils.ts"],"names":[],"mappings":";;AAWA,0BAUC;AAKD,kCAGC;AA7BD;;;GAGG;AACH,sEAAsE;AACtE,6CAA0C;AAC1C,+CAA+D;AAE/D,8DAAsF;AAEtF,4CAA4C;AAC5C,SAAgB,OAAO,CAAC,IAAW;IAKjC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,CAAC,GAAe,EAAE,GAAG,IAAkB,EAAE,EAAE,CAAC,IAAA,WAAI,EAAC,IAAI,EAAE,GAAG,EAAE,IAAA,mBAAW,EAAC,GAAG,IAAI,CAAC,CAAC;QACvF,WAAW,EAAX,mBAAW;KACZ,CAAC;AACJ,CAAC;AAKD,SAAgB,WAAW,CAAC,QAAkB,EAAE,OAAc;IAC5D,MAAM,MAAM,GAAG,CAAC,IAAW,EAAW,EAAE,CAAC,IAAA,4BAAW,EAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/bls.d.ts b/packages/noble-curves/abstract/bls.d.ts deleted file mode 100644 index cc7aae5e409..00000000000 --- a/packages/noble-curves/abstract/bls.d.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { - type Opts as HTFOpts, - type MapToCurve, - createHasher, - type htfBasicOpts, -} from './hash-to-curve.js' -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' -import { type CHash, type Hex, type PrivKey } from './utils.js' -import { type CurvePointsRes, type CurvePointsType, type ProjPointType } from './weierstrass.js' -type Fp = bigint -export type TwistType = 'multiplicative' | 'divisive' -export type ShortSignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} -export type SignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} -export type PostPrecomputePointAddFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, -) => { - Rx: Fp2 - Ry: Fp2 - Rz: Fp2 -} -export type PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => void -export type CurveType = { - G1: Omit, 'n'> & { - ShortSignature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - G2: Omit, 'n'> & { - Signature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - fields: { - Fp: IField - Fr: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - } - params: { - ateLoopSize: bigint - xNegative: boolean - r: bigint - twistType: TwistType - } - htfDefaults: HTFOpts - hash: CHash - randomBytes: (bytesLength?: number) => Uint8Array - postPrecompute?: PostPrecomputeFn -} -type PrecomputeSingle = [Fp2, Fp2, Fp2][] -type Precompute = PrecomputeSingle[] -export type CurveFn = { - getPublicKey: (privateKey: PrivKey) => Uint8Array - getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array - sign: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - signShortSignature: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - verify: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyShortSignature: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyBatch: ( - signature: Hex | ProjPointType, - messages: (Hex | ProjPointType)[], - publicKeys: (Hex | ProjPointType)[], - htfOpts?: htfBasicOpts, - ) => boolean - aggregatePublicKeys: { - (publicKeys: Hex[]): Uint8Array - (publicKeys: ProjPointType[]): ProjPointType - } - aggregateSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - aggregateShortSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 - pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 - pairingBatch: ( - pairs: { - g1: ProjPointType - g2: ProjPointType - }[], - withFinalExponent?: boolean, - ) => Fp12 - G1: CurvePointsRes & ReturnType> - G2: CurvePointsRes & ReturnType> - Signature: SignatureCoder - ShortSignature: ShortSignatureCoder - params: { - ateLoopSize: bigint - r: bigint - G1b: bigint - G2b: Fp2 - } - fields: { - Fp: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - Fr: IField - } - utils: { - randomPrivateKey: () => Uint8Array - calcPairingPrecomputes: (p: ProjPointType) => Precompute - } -} -export declare function bls(CURVE: CurveType): CurveFn -export {} -//# sourceMappingURL=bls.d.ts.map diff --git a/packages/noble-curves/abstract/bls.d.ts.map b/packages/noble-curves/abstract/bls.d.ts.map deleted file mode 100644 index 9aaa0b4dfd0..00000000000 --- a/packages/noble-curves/abstract/bls.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls.d.ts","sourceRoot":"","sources":["../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/bls.js b/packages/noble-curves/abstract/bls.js deleted file mode 100644 index c544ee14cc6..00000000000 --- a/packages/noble-curves/abstract/bls.js +++ /dev/null @@ -1,360 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.bls = bls -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// TODO: import { AffinePoint } from './curve.js'; -const modular_js_1 = require('./modular.js') -const utils_js_1 = require('./utils.js') -// prettier-ignore -const hash_to_curve_js_1 = require('./hash-to-curve.js') -const weierstrass_js_1 = require('./weierstrass.js') -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. -function NAfDecomposition(a) { - const res = [] - // a>1 because of marker bit - for (; a > _1n; a >>= _1n) { - if ((a & _1n) === _0n) res.unshift(0) - else if ((a & _3n) === _3n) { - res.unshift(-1) - a += _1n - } else res.unshift(1) - } - return res -} -function bls(CURVE) { - // Fields are specific for curve, so for now we'll need to pass them with opts - const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields - const BLS_X_IS_NEGATIVE = CURVE.params.xNegative - const TWIST = CURVE.params.twistType - // Point on G1 curve: (x, y) - const G1_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G1 }) - const G1 = Object.assign( - G1_, - (0, hash_to_curve_js_1.createHasher)(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G1.htfDefaults, - }), - ) - // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) - const G2_ = (0, weierstrass_js_1.weierstrassPoints)({ n: Fr.ORDER, ...CURVE.G2 }) - const G2 = Object.assign( - G2_, - (0, hash_to_curve_js_1.createHasher)(G2_.ProjectivePoint, CURVE.G2.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G2.htfDefaults, - }), - ) - // Applies sparse multiplication as line function - let lineFunction - if (TWIST === 'multiplicative') { - lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) - } else if (TWIST === 'divisive') { - // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of - // precompute calculations. - lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) - } else throw new Error('bls: unknown twist type') - const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) - function pointDouble(ell, Rx, Ry, Rz) { - const t0 = Fp2.sqr(Ry) // Ry² - const t1 = Fp2.sqr(Rz) // Rz² - const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B - const t3 = Fp2.mul(t2, _3n) // 3 * T2 - const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 - const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) - const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² - const c2 = Fp2.neg(t4) // -T4 (-h) - ell.push([c0, c1, c2]) - Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 - Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² - Rz = Fp2.mul(t0, t4) // T0 * T4 - return { Rx, Ry, Rz } - } - function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) { - // Addition - const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz - const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz - const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy - const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry - const c2 = t1 // == Rx - Qx * Rz - ell.push([c0, c1, c2]) - const t2 = Fp2.sqr(t1) // T1² - const t3 = Fp2.mul(t2, t1) // T2 * T1 - const t4 = Fp2.mul(t2, Rx) // T2 * Rx - const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz - Rx = Fp2.mul(t1, t5) // T1 * T5 - Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry - Rz = Fp2.mul(Rz, t3) // Rz * T3 - return { Rx, Ry, Rz } - } - // Pre-compute coefficients for sparse multiplication - // Point addition and point double calculations is reused for coefficients - // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine - // add + double in windowed precomputes here, otherwise it would be single op (since X is static) - const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) - const calcPairingPrecomputes = (0, utils_js_1.memoized)((point) => { - const p = point - const { x, y } = p.toAffine() - // prettier-ignore - const Qx = x, - Qy = y, - negQy = Fp2.neg(y) - // prettier-ignore - let Rx = Qx, - Ry = Qy, - Rz = Fp2.ONE - const ell = [] - for (const bit of ATE_NAF) { - const cur = [] - ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) - if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) - ell.push(cur) - } - if (CURVE.postPrecompute) { - const last = ell[ell.length - 1] - CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) - } - return ell - }) - function millerLoopBatch(pairs, withFinalExponent = false) { - let f12 = Fp12.ONE - if (pairs.length) { - const ellLen = pairs[0][0].length - for (let i = 0; i < ellLen; i++) { - f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings - // NOTE: we apply multiple pairings in parallel here - for (const [ell, Px, Py] of pairs) { - for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) - } - } - } - if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) - return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 - } - // Calculates product of multiple pairings - // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` - function pairingBatch(pairs, withFinalExponent = true) { - const res = [] - // This cache precomputed toAffine for all points - G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) - G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) - for (const { g1, g2 } of pairs) { - if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) - throw new Error('pairing is not available for ZERO point') - // This uses toAffine inside - g1.assertValidity() - g2.assertValidity() - const Qa = g1.toAffine() - res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) - } - return millerLoopBatch(res, withFinalExponent) - } - // Calculates bilinear pairing - function pairing(Q, P, withFinalExponent = true) { - return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) - } - const utils = { - randomPrivateKey: () => { - const length = (0, modular_js_1.getMinHashLength)(Fr.ORDER) - return (0, modular_js_1.mapHashToField)(CURVE.randomBytes(length), Fr.ORDER) - }, - calcPairingPrecomputes, - } - const { ShortSignature } = CURVE.G1 - const { Signature } = CURVE.G2 - function normP1(point) { - return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point) - } - function normP1Hash(point, htfOpts) { - return point instanceof G1.ProjectivePoint - ? point - : G1.hashToCurve((0, utils_js_1.ensureBytes)('point', point), htfOpts) - } - function normP2(point) { - return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) - } - function normP2Hash(point, htfOpts) { - return point instanceof G2.ProjectivePoint - ? point - : G2.hashToCurve((0, utils_js_1.ensureBytes)('point', point), htfOpts) - } - // Multiplies generator (G1) by private key. - // P = pk x G - function getPublicKey(privateKey) { - return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - // Multiplies generator (G2) by private key. - // P = pk x G - function getPublicKeyForShortSignatures(privateKey) { - return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - function sign(message, privateKey, htfOpts) { - const msgPoint = normP2Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G2.ProjectivePoint) return sigPoint - return Signature.toRawBytes(sigPoint) - } - function signShortSignature(message, privateKey, htfOpts) { - const msgPoint = normP1Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G1.ProjectivePoint) return sigPoint - return ShortSignature.toRawBytes(sigPoint) - } - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(P, H(m)) == e(G, S) - function verify(signature, message, publicKey, htfOpts) { - const P = normP1(publicKey) - const Hm = normP2Hash(message, htfOpts) - const G = G1.ProjectivePoint.BASE - const S = normP2(signature) - const exp = pairingBatch([ - { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); - { g1: G, g2: S }, // eGS = pairing(G, S, false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(S, G) == e(H(m), P) - function verifyShortSignature(signature, message, publicKey, htfOpts) { - const P = normP2(publicKey) - const Hm = normP1Hash(message, htfOpts) - const G = G2.ProjectivePoint.BASE - const S = normP1(signature) - const exp = pairingBatch([ - { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); - { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - function aNonEmpty(arr) { - if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') - } - function aggregatePublicKeys(publicKeys) { - aNonEmpty(publicKeys) - const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (publicKeys[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - // toRawBytes ensures point validity - return aggAffine.toRawBytes(true) - } - function aggregateSignatures(signatures) { - aNonEmpty(signatures) - const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G2.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return Signature.toRawBytes(aggAffine) - } - function aggregateShortSignatures(signatures) { - aNonEmpty(signatures) - const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return ShortSignature.toRawBytes(aggAffine) - } - // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 - // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) - function verifyBatch( - signature, - // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? - messages, - publicKeys, - htfOpts, - ) { - aNonEmpty(messages) - if (publicKeys.length !== messages.length) - throw new Error('amount of public keys and messages should be equal') - const sig = normP2(signature) - const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) - const nPublicKeys = publicKeys.map(normP1) - // NOTE: this works only for exact same object - const messagePubKeyMap = new Map() - for (let i = 0; i < nPublicKeys.length; i++) { - const pub = nPublicKeys[i] - const msg = nMessages[i] - let keys = messagePubKeyMap.get(msg) - if (keys === undefined) { - keys = [] - messagePubKeyMap.set(msg, keys) - } - keys.push(pub) - } - const paired = [] - try { - for (const [msg, keys] of messagePubKeyMap) { - const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) - paired.push({ g1: groupPublicKey, g2: msg }) - } - paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) - return Fp12.eql(pairingBatch(paired), Fp12.ONE) - } catch { - return false - } - } - G1.ProjectivePoint.BASE._setWindowSize(4) - return { - getPublicKey, - getPublicKeyForShortSignatures, - sign, - signShortSignature, - verify, - verifyBatch, - verifyShortSignature, - aggregatePublicKeys, - aggregateSignatures, - aggregateShortSignatures, - millerLoopBatch, - pairing, - pairingBatch, - G1, - G2, - Signature, - ShortSignature, - fields: { - Fr, - Fp, - Fp2, - Fp6, - Fp12, - }, - params: { - ateLoopSize: CURVE.params.ateLoopSize, - r: CURVE.params.r, - G1b: CURVE.G1.b, - G2b: CURVE.G2.b, - }, - utils, - } -} -//# sourceMappingURL=bls.js.map diff --git a/packages/noble-curves/abstract/bls.js.map b/packages/noble-curves/abstract/bls.js.map deleted file mode 100644 index e6c9ece3311..00000000000 --- a/packages/noble-curves/abstract/bls.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls.js","sourceRoot":"","sources":["../src/abstract/bls.ts"],"names":[],"mappings":";;AA+LA,kBA0XC;AAzjBD;;;;;;;;;;;;;;;;IAgBI;AACJ,sEAAsE;AACtE,kDAAkD;AAClD,6CAA6E;AAC7E,yCAAuF;AACvF,kBAAkB;AAClB,yDAK4B;AAE5B,qDAK0B;AAI1B,kBAAkB;AAClB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AA0IzE,8EAA8E;AAC9E,SAAS,gBAAgB,CAAC,CAAS;IACjC,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,4BAA4B;IAC5B,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG;YAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;aACjC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;YAC3B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YAChB,CAAC,IAAI,GAAG,CAAC;QACX,CAAC;;YAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAgB,GAAG,CAAC,KAAgB;IAClC,8EAA8E;IAC9E,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IAChD,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;IACjD,MAAM,KAAK,GAAc,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;IAChD,4BAA4B;IAC5B,MAAM,GAAG,GAAG,IAAA,kCAAiB,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CACtB,GAAG,EACH,IAAA,+BAAY,EAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE;QACrD,GAAG,KAAK,CAAC,WAAW;QACpB,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW;KACxB,CAAC,CACH,CAAC;IACF,8DAA8D;IAC9D,MAAM,GAAG,GAAG,IAAA,kCAAiB,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CACtB,GAAG,EACH,IAAA,+BAAY,EAAC,GAAG,CAAC,eAA2C,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE;QACjF,GAAG,KAAK,CAAC,WAAW;QACpB,GAAG,KAAK,CAAC,EAAE,CAAC,WAAW;KACxB,CAAC,CACH,CAAC;IAIF,iDAAiD;IACjD,IAAI,YAA0E,CAAC;IAC/E,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;QAC/B,YAAY,GAAG,CAAC,EAAO,EAAE,EAAO,EAAE,EAAO,EAAE,CAAO,EAAE,EAAM,EAAE,EAAM,EAAE,EAAE,CACpE,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;SAAM,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,2FAA2F;QAC3F,2BAA2B;QAC3B,YAAY,GAAG,CAAC,EAAO,EAAE,EAAO,EAAE,EAAO,EAAE,CAAO,EAAE,EAAM,EAAE,EAAM,EAAE,EAAE,CACpE,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;;QAAM,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,SAAS,WAAW,CAAC,GAAqB,EAAE,EAAO,EAAE,EAAO,EAAE,EAAO;QACnE,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;QAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;QAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa;QACtD,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS;QACtC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,uBAAuB;QACtF,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc;QAC1C,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,UAAU;QAChD,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;QAEnC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEvB,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B;QAC9F,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,6BAA6B;QAClH,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QAChC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IACD,SAAS,QAAQ,CAAC,GAAqB,EAAE,EAAO,EAAE,EAAO,EAAE,EAAO,EAAE,EAAO,EAAE,EAAO;QAClF,WAAW;QACX,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe;QACxD,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe;QACxD,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,0CAA0C;QAChG,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,sBAAsB;QAC9C,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,kBAAkB;QAEjC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAEvB,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;QAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QACtC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QACtC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,yBAAyB;QACtG,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QAChC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,2BAA2B;QACxF,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;QAChC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IAED,qDAAqD;IACrD,0EAA0E;IAC1E,2FAA2F;IAC3F,iGAAiG;IACjG,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAE3D,MAAM,sBAAsB,GAAG,IAAA,mBAAQ,EAAC,CAAC,KAAS,EAAE,EAAE;QACpD,MAAM,CAAC,GAAG,KAAK,CAAC;QAChB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9B,kBAAkB;QAClB,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzC,kBAAkB;QAClB,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC;QACnC,MAAM,GAAG,GAAe,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAqB,EAAE,CAAC;YACjC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAChD,IAAI,GAAG;gBAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnF,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;QACD,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAKH,SAAS,eAAe,CAAC,KAAkB,EAAE,oBAA6B,KAAK;QAC7E,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACnB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,0DAA0D;gBAC/E,oDAAoD;gBACpD,KAAK,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;oBAClC,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;wBAAE,GAAG,GAAG,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACjF,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,iBAAiB;YAAE,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACjD,OAAO,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/D,CAAC;IAED,0CAA0C;IAC1C,qEAAqE;IACrE,SAAS,YAAY,CAAC,KAAqB,EAAE,oBAA6B,IAAI;QAC5E,MAAM,GAAG,GAAgB,EAAE,CAAC;QAC5B,iDAAiD;QACjD,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACzD,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACzD,KAAK,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,KAAK,EAAE,CAAC;YAC/B,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;gBAC1E,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC7D,4BAA4B;YAC5B,EAAE,CAAC,cAAc,EAAE,CAAC;YACpB,EAAE,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;YACzB,GAAG,CAAC,IAAI,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,eAAe,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IACjD,CAAC;IACD,8BAA8B;IAC9B,SAAS,OAAO,CAAC,CAAK,EAAE,CAAK,EAAE,oBAA6B,IAAI;QAC9D,OAAO,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,gBAAgB,EAAE,GAAe,EAAE;YACjC,MAAM,MAAM,GAAG,IAAA,6BAAgB,EAAC,EAAE,CAAC,KAAK,CAAC,CAAC;YAC1C,OAAO,IAAA,2BAAc,EAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC;QACD,sBAAsB;KACvB,CAAC;IAEF,MAAM,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IACpC,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IAI/B,SAAS,MAAM,CAAC,KAAY;QAC1B,OAAO,KAAK,YAAY,EAAE,CAAC,eAAe,CAAC,CAAC,CAAE,KAAY,CAAC,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACjG,CAAC;IACD,SAAS,UAAU,CAAC,KAAY,EAAE,OAAsB;QACtD,OAAO,KAAK,YAAY,EAAE,CAAC,eAAe;YACxC,CAAC,CAAC,KAAK;YACP,CAAC,CAAE,EAAE,CAAC,WAAW,CAAC,IAAA,sBAAW,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,CAAQ,CAAC;IACnE,CAAC;IACD,SAAS,MAAM,CAAC,KAAY;QAC1B,OAAO,KAAK,YAAY,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IACD,SAAS,UAAU,CAAC,KAAY,EAAE,OAAsB;QACtD,OAAO,KAAK,YAAY,EAAE,CAAC,eAAe;YACxC,CAAC,CAAC,KAAK;YACP,CAAC,CAAE,EAAE,CAAC,WAAW,CAAC,IAAA,sBAAW,EAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,CAAQ,CAAC;IACnE,CAAC;IAED,4CAA4C;IAC5C,aAAa;IACb,SAAS,YAAY,CAAC,UAAmB;QACvC,OAAO,EAAE,CAAC,eAAe,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,4CAA4C;IAC5C,aAAa;IACb,SAAS,8BAA8B,CAAC,UAAmB;QACzD,OAAO,EAAE,CAAC,eAAe,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;IAMD,SAAS,IAAI,CAAC,OAAc,EAAE,UAAmB,EAAE,OAAsB;QACvE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1E,IAAI,OAAO,YAAY,EAAE,CAAC,eAAe;YAAE,OAAO,QAAQ,CAAC;QAC3D,OAAO,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAQD,SAAS,kBAAkB,CACzB,OAAc,EACd,UAAmB,EACnB,OAAsB;QAEtB,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1E,IAAI,OAAO,YAAY,EAAE,CAAC,eAAe;YAAE,OAAO,QAAQ,CAAC;QAC3D,OAAO,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,uFAAuF;IACvF,wBAAwB;IACxB,SAAS,MAAM,CACb,SAAgB,EAChB,OAAc,EACd,SAAgB,EAChB,OAAsB;QAEtB,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,YAAY,CAAC;YACvB,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,yCAAyC;YACrE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,8BAA8B;SACjD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,uFAAuF;IACvF,wBAAwB;IACxB,SAAS,oBAAoB,CAC3B,SAAgB,EAChB,OAAc,EACd,SAAgB,EAChB,OAAsB;QAEtB,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,YAAY,CAAC;YACvB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,gCAAgC;YACnD,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,uCAAuC;SACnE,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,SAAS,SAAS,CAAC,GAAU;QAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC3F,CAAC;IAMD,SAAS,mBAAmB,CAAC,UAAmB;QAC9C,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC3F,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,cAAc;QACrC,IAAI,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,eAAe,EAAE,CAAC;YAChD,SAAS,CAAC,cAAc,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,oCAAoC;QACpC,OAAO,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAKD,SAAS,mBAAmB,CAAC,UAAmB;QAC9C,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC3F,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,cAAc;QACrC,IAAI,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,eAAe,EAAE,CAAC;YAChD,SAAS,CAAC,cAAc,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAKD,SAAS,wBAAwB,CAAC,UAAmB;QACnD,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC3F,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,cAAc;QACrC,IAAI,UAAU,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,eAAe,EAAE,CAAC;YAChD,SAAS,CAAC,cAAc,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED,2EAA2E;IAC3E,gDAAgD;IAChD,SAAS,WAAW,CAClB,SAAgB;IAChB,8DAA8D;IAC9D,QAAiB,EACjB,UAAmB,EACnB,OAAsB;QAEtB,SAAS,CAAC,QAAQ,CAAC,CAAC;QACpB,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;YACvC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3C,8CAA8C;QAC9C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAY,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,GAAG,EAAE,CAAC;gBACV,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,gBAAgB,EAAE,CAAC;gBAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC/D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAE1C,OAAO;QACL,YAAY;QACZ,8BAA8B;QAC9B,IAAI;QACJ,kBAAkB;QAClB,MAAM;QACN,WAAW;QACX,oBAAoB;QACpB,mBAAmB;QACnB,mBAAmB;QACnB,wBAAwB;QACxB,eAAe;QACf,OAAO;QACP,YAAY;QACZ,EAAE;QACF,EAAE;QACF,SAAS;QACT,cAAc;QACd,MAAM,EAAE;YACN,EAAE;YACF,EAAE;YACF,GAAG;YACH,GAAG;YACH,IAAI;SACL;QACD,MAAM,EAAE;YACN,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;YACrC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACjB,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACf,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;SAChB;QACD,KAAK;KACN,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/curve.d.ts b/packages/noble-curves/abstract/curve.d.ts deleted file mode 100644 index b4984cb067f..00000000000 --- a/packages/noble-curves/abstract/curve.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -export type AffinePoint = { - x: T - y: T -} & { - z?: never - t?: never -} -export interface Group> { - double(): T - negate(): T - add(other: T): T - subtract(other: T): T - equals(other: T): boolean - multiply(scalar: bigint): T -} -export type GroupConstructor = { - BASE: T - ZERO: T -} -export type Mapper = (i: T[]) => T[] -export type IWNAF> = { - constTimeNegate: >(condition: boolean, item: T) => T - hasPrecomputes(elm: T): boolean - unsafeLadder(elm: T, n: bigint, p?: T): T - precomputeWindow(elm: T, W: number): Group[] - wNAF( - W: number, - precomputes: T[], - n: bigint, - ): { - p: T - f: T - } - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T - getPrecomputes(W: number, P: T, transform: Mapper): T[] - wNAFCached( - P: T, - n: bigint, - transform: Mapper, - ): { - p: T - f: T - } - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T - setWindowSize(P: T, W: number): void -} -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -export declare function wNAF>(c: GroupConstructor, bits: number): IWNAF -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster with precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -export declare function pippenger>( - c: GroupConstructor, - fieldN: IField, - points: T[], - scalars: bigint[], -): T -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -export declare function precomputeMSMUnsafe>( - c: GroupConstructor, - fieldN: IField, - points: T[], - windowSize: number, -): (scalars: bigint[]) => T -/** - * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. - * Though generator can be different (Fp2 / Fp6 for BLS). - */ -export type BasicCurve = { - Fp: IField - n: bigint - nBitLength?: number - nByteLength?: number - h: bigint - hEff?: bigint - Gx: T - Gy: T - allowInfinityPoint?: boolean -} -export declare function validateBasic( - curve: BasicCurve & T, -): Readonly< - { - readonly nBitLength: number - readonly nByteLength: number - } & BasicCurve & - T & { - p: bigint - } -> -//# sourceMappingURL=curve.d.ts.map diff --git a/packages/noble-curves/abstract/curve.d.ts.map b/packages/noble-curves/abstract/curve.d.ts.map deleted file mode 100644 index cc9403631ef..00000000000 --- a/packages/noble-curves/abstract/curve.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/curve.js b/packages/noble-curves/abstract/curve.js deleted file mode 100644 index c93b3847bdf..00000000000 --- a/packages/noble-curves/abstract/curve.js +++ /dev/null @@ -1,368 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.wNAF = wNAF -exports.pippenger = pippenger -exports.precomputeMSMUnsafe = precomputeMSMUnsafe -exports.validateBasic = validateBasic -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const modular_js_1 = require('./modular.js') -const utils_js_1 = require('./utils.js') -const _0n = BigInt(0) -const _1n = BigInt(1) -function constTimeNegate(condition, item) { - const neg = item.negate() - return condition ? neg : item -} -function validateW(W, bits) { - if (!Number.isSafeInteger(W) || W <= 0 || W > bits) - throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) -} -function calcWOpts(W, bits) { - validateW(W, bits) - const windows = Math.ceil(bits / W) + 1 // +1, because - const windowSize = 2 ** (W - 1) // -1 because we skip zero - return { windows, windowSize } -} -function validateMSMPoints(points, c) { - if (!Array.isArray(points)) throw new Error('array expected') - points.forEach((p, i) => { - if (!(p instanceof c)) throw new Error('invalid point at index ' + i) - }) -} -function validateMSMScalars(scalars, field) { - if (!Array.isArray(scalars)) throw new Error('array of scalars expected') - scalars.forEach((s, i) => { - if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) - }) -} -// Since points in different groups cannot be equal (different object constructor), -// we can have single place to store precomputes -const pointPrecomputes = new WeakMap() -const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) -function getW(P) { - return pointWindowSizes.get(P) || 1 -} -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -function wNAF(c, bits) { - return { - constTimeNegate, - hasPrecomputes(elm) { - return getW(elm) !== 1 - }, - // non-const time multiplication ladder - unsafeLadder(elm, n, p = c.ZERO) { - let d = elm - while (n > _0n) { - if (n & _1n) p = p.add(d) - d = d.double() - n >>= _1n - } - return p - }, - /** - * Creates a wNAF precomputation window. Used for caching. - * Default window size is set by `utils.precompute()` and is equal to 8. - * Number of precomputed points depends on the curve size: - * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: - * - 𝑊 is the window size - * - 𝑛 is the bitlength of the curve order. - * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. - * @param elm Point instance - * @param W window size - * @returns precomputed point tables flattened to a single array - */ - precomputeWindow(elm, W) { - const { windows, windowSize } = calcWOpts(W, bits) - const points = [] - let p = elm - let base = p - for (let window = 0; window < windows; window++) { - base = p - points.push(base) - // =1, because we skip zero - for (let i = 1; i < windowSize; i++) { - base = base.add(p) - points.push(base) - } - p = base.double() - } - return points - }, - /** - * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @returns real and fake (for const-time) points - */ - wNAF(W, precomputes, n) { - // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise - // But need to carefully remove other checks before wNAF. ORDER == bits here - const { windows, windowSize } = calcWOpts(W, bits) - let p = c.ZERO - let f = c.BASE - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - // Extract W bits. - let wbits = Number(n & mask) - // Shift number by W bits. - n >>= shiftBy - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - // This code was first written with assumption that 'f' and 'p' will never be infinity point: - // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, - // there is negate now: it is possible that negated element from low value - // would be the same as high element, which will create carry into next window. - // It's not obvious how this can fail, but still worth investigating later. - // Check if we're onto Zero point. - // Add random point inside current window to f. - const offset1 = offset - const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero - const cond1 = window % 2 !== 0 - const cond2 = wbits < 0 - if (wbits === 0) { - // The most important part for const-time getPublicKey - f = f.add(constTimeNegate(cond1, precomputes[offset1])) - } else { - p = p.add(constTimeNegate(cond2, precomputes[offset2])) - } - } - // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() - // Even if the variable is still unused, there are some checks which will - // throw an exception, so compiler needs to prove they won't happen, which is hard. - // At this point there is a way to F be infinity-point even if p is not, - // which makes it less const-time: around 1 bigint multiply. - return { p, f } - }, - /** - * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @param acc accumulator point to add result of multiplication - * @returns point - */ - wNAFUnsafe(W, precomputes, n, acc = c.ZERO) { - const { windows, windowSize } = calcWOpts(W, bits) - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - if (n === _0n) break // No need to go over empty scalar - // Extract W bits. - let wbits = Number(n & mask) - // Shift number by W bits. - n >>= shiftBy - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - if (wbits === 0) continue - let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero - if (wbits < 0) curr = curr.negate() - // NOTE: by re-using acc, we can save a lot of additions in case of MSM - acc = acc.add(curr) - } - return acc - }, - getPrecomputes(W, P, transform) { - // Calculate precomputes on a first run, reuse them after - let comp = pointPrecomputes.get(P) - if (!comp) { - comp = this.precomputeWindow(P, W) - if (W !== 1) pointPrecomputes.set(P, transform(comp)) - } - return comp - }, - wNAFCached(P, n, transform) { - const W = getW(P) - return this.wNAF(W, this.getPrecomputes(W, P, transform), n) - }, - wNAFCachedUnsafe(P, n, transform, prev) { - const W = getW(P) - if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster - return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) - }, - // We calculate precomputes for elliptic curve point multiplication - // using windowed method. This specifies window size and - // stores precomputed values. Usually only base point would be precomputed. - setWindowSize(P, W) { - validateW(W, bits) - pointWindowSizes.set(P, W) - pointPrecomputes.delete(P) - }, - } -} -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster with precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -function pippenger(c, fieldN, points, scalars) { - // If we split scalars by some window (let's say 8 bits), every chunk will only - // take 256 buckets even if there are 4096 scalars, also re-uses double. - // TODO: - // - https://eprint.iacr.org/2024/750.pdf - // - https://tches.iacr.org/index.php/TCHES/article/view/10287 - // 0 is accepted in scalars - validateMSMPoints(points, c) - validateMSMScalars(scalars, fieldN) - if (points.length !== scalars.length) - throw new Error('arrays of points and scalars must have equal length') - const zero = c.ZERO - const wbits = (0, utils_js_1.bitLen)(BigInt(points.length)) - const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits - const MASK = (1 << windowSize) - 1 - const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array - const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize - let sum = zero - for (let i = lastBits; i >= 0; i -= windowSize) { - buckets.fill(zero) - for (let j = 0; j < scalars.length; j++) { - const scalar = scalars[j] - const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) - buckets[wbits] = buckets[wbits].add(points[j]) - } - let resI = zero // not using this will do small speed-up, but will lose ct - // Skip first bucket, because it is zero - for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { - sumI = sumI.add(buckets[j]) - resI = resI.add(sumI) - } - sum = sum.add(resI) - if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() - } - return sum -} -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -function precomputeMSMUnsafe(c, fieldN, points, windowSize) { - /** - * Performance Analysis of Window-based Precomputation - * - * Base Case (256-bit scalar, 8-bit window): - * - Standard precomputation requires: - * - 31 additions per scalar × 256 scalars = 7,936 ops - * - Plus 255 summary additions = 8,191 total ops - * Note: Summary additions can be optimized via accumulator - * - * Chunked Precomputation Analysis: - * - Using 32 chunks requires: - * - 255 additions per chunk - * - 256 doublings - * - Total: (255 × 32) + 256 = 8,416 ops - * - * Memory Usage Comparison: - * Window Size | Standard Points | Chunked Points - * ------------|-----------------|--------------- - * 4-bit | 520 | 15 - * 8-bit | 4,224 | 255 - * 10-bit | 13,824 | 1,023 - * 16-bit | 557,056 | 65,535 - * - * Key Advantages: - * 1. Enables larger window sizes due to reduced memory overhead - * 2. More efficient for smaller scalar counts: - * - 16 chunks: (16 × 255) + 256 = 4,336 ops - * - ~2x faster than standard 8,191 ops - * - * Limitations: - * - Not suitable for plain precomputes (requires 256 constant doublings) - * - Performance degrades with larger scalar counts: - * - Optimal for ~256 scalars - * - Less efficient for 4096+ scalars (Pippenger preferred) - */ - validateW(windowSize, fieldN.BITS) - validateMSMPoints(points, c) - const zero = c.ZERO - const tableSize = 2 ** windowSize - 1 // table size (without zero) - const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item - const MASK = BigInt((1 << windowSize) - 1) - const tables = points.map((p) => { - const res = [] - for (let i = 0, acc = p; i < tableSize; i++) { - res.push(acc) - acc = acc.add(p) - } - return res - }) - return (scalars) => { - validateMSMScalars(scalars, fieldN) - if (scalars.length > points.length) - throw new Error('array of scalars must be smaller than array of points') - let res = zero - for (let i = 0; i < chunks; i++) { - // No need to double if accumulator is still zero. - if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() - const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) - for (let j = 0; j < scalars.length; j++) { - const n = scalars[j] - const curr = Number((n >> shiftBy) & MASK) - if (!curr) continue // skip zero scalars chunks - res = res.add(tables[j][curr - 1]) - } - } - return res - } -} -function validateBasic(curve) { - ;(0, modular_js_1.validateField)(curve.Fp) - ;(0, utils_js_1.validateObject)( - curve, - { - n: 'bigint', - h: 'bigint', - Gx: 'field', - Gy: 'field', - }, - { - nBitLength: 'isSafeInteger', - nByteLength: 'isSafeInteger', - }, - ) - // Set defaults - return Object.freeze({ - ...(0, modular_js_1.nLength)(curve.n, curve.nBitLength), - ...curve, - ...{ p: curve.Fp.ORDER }, - }) -} -//# sourceMappingURL=curve.js.map diff --git a/packages/noble-curves/abstract/curve.js.map b/packages/noble-curves/abstract/curve.js.map deleted file mode 100644 index 1fe22d973a2..00000000000 --- a/packages/noble-curves/abstract/curve.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"curve.js","sourceRoot":"","sources":["../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/edwards.d.ts b/packages/noble-curves/abstract/edwards.d.ts deleted file mode 100644 index cfd6867cfb1..00000000000 --- a/packages/noble-curves/abstract/edwards.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' -import { type FHash, type Hex } from './utils.js' -/** Edwards curves must declare params a & d. */ -export type CurveType = BasicCurve & { - a: bigint - d: bigint - hash: FHash - randomBytes: (bytesLength?: number) => Uint8Array - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - uvRatio?: ( - u: bigint, - v: bigint, - ) => { - isValid: boolean - value: bigint - } - prehash?: FHash - mapToCurve?: (scalar: bigint[]) => AffinePoint -} -export type CurveTypeWithLength = Readonly< - CurveType & { - nByteLength: number - nBitLength: number - } -> -declare function validateOpts(curve: CurveType): CurveTypeWithLength -/** Instance of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointType extends Group { - readonly ex: bigint - readonly ey: bigint - readonly ez: bigint - readonly et: bigint - get x(): bigint - get y(): bigint - assertValidity(): void - multiply(scalar: bigint): ExtPointType - multiplyUnsafe(scalar: bigint): ExtPointType - isSmallOrder(): boolean - isTorsionFree(): boolean - clearCofactor(): ExtPointType - toAffine(iz?: bigint): AffinePoint - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - _setWindowSize(windowSize: number): void -} -/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointConstructor extends GroupConstructor { - new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType - fromAffine(p: AffinePoint): ExtPointType - fromHex(hex: Hex): ExtPointType - fromPrivateKey(privateKey: Hex): ExtPointType - msm(points: ExtPointType[], scalars: bigint[]): ExtPointType -} -/** - * Edwards Curve interface. - * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. - */ -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: Hex) => Uint8Array - sign: ( - message: Hex, - privateKey: Hex, - options?: { - context?: Hex - }, - ) => Uint8Array - verify: ( - sig: Hex, - message: Hex, - publicKey: Hex, - options?: { - context?: Hex - zip215: boolean - }, - ) => boolean - ExtendedPoint: ExtPointConstructor - utils: { - randomPrivateKey: () => Uint8Array - getExtendedPublicKey: (key: Hex) => { - head: Uint8Array - prefix: Uint8Array - scalar: bigint - point: ExtPointType - pointBytes: Uint8Array - } - precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType - } -} -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -export declare function twistedEdwards(curveDef: CurveType): CurveFn -export {} -//# sourceMappingURL=edwards.d.ts.map diff --git a/packages/noble-curves/abstract/edwards.d.ts.map b/packages/noble-curves/abstract/edwards.d.ts.map deleted file mode 100644 index 48de4faf5b9..00000000000 --- a/packages/noble-curves/abstract/edwards.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"edwards.d.ts","sourceRoot":"","sources":["../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/edwards.js b/packages/noble-curves/abstract/edwards.js deleted file mode 100644 index bca78b2e482..00000000000 --- a/packages/noble-curves/abstract/edwards.js +++ /dev/null @@ -1,448 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.twistedEdwards = twistedEdwards -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const curve_js_1 = require('./curve.js') -const modular_js_1 = require('./modular.js') -const ut = require('./utils.js') -const utils_js_1 = require('./utils.js') -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _8n = BigInt(8) -// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: -const VERIFY_DEFAULT = { zip215: true } -function validateOpts(curve) { - const opts = (0, curve_js_1.validateBasic)(curve) - ut.validateObject( - curve, - { - hash: 'function', - a: 'bigint', - d: 'bigint', - randomBytes: 'function', - }, - { - adjustScalarBytes: 'function', - domain: 'function', - uvRatio: 'function', - mapToCurve: 'function', - }, - ) - // Set defaults - return Object.freeze({ ...opts }) -} -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -function twistedEdwards(curveDef) { - const CURVE = validateOpts(curveDef) - const { - Fp, - n: CURVE_ORDER, - prehash: prehash, - hash: cHash, - randomBytes, - nByteLength, - h: cofactor, - } = CURVE - // Important: - // There are some places where Fp.BYTES is used instead of nByteLength. - // So far, everything has been tested with curves of Fp.BYTES == nByteLength. - // TODO: test and find curves which behave otherwise. - const MASK = _2n << (BigInt(nByteLength * 8) - _1n) - const modP = Fp.create // Function overrides - const Fn = (0, modular_js_1.Field)(CURVE.n, CURVE.nBitLength) - // sqrt(u/v) - const uvRatio = - CURVE.uvRatio || - ((u, v) => { - try { - return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } - } catch (e) { - return { isValid: false, value: _0n } - } - }) - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) // NOOP - const domain = - CURVE.domain || - ((data, ctx, phflag) => { - ;(0, utils_js_1.abool)('phflag', phflag) - if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') - return data - }) // NOOP - // 0 <= n < MASK - // Coordinates larger than Fp.ORDER are allowed for zip215 - function aCoordinate(title, n) { - ut.aInRange('coordinate ' + title, n, _0n, MASK) - } - function assertPoint(other) { - if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - const toAffineMemo = (0, utils_js_1.memoized)((p, iz) => { - const { ex: x, ey: y, ez: z } = p - const is0 = p.is0() - if (iz == null) iz = is0 ? _8n : Fp.inv(z) // 8 was chosen arbitrarily - const ax = modP(x * iz) - const ay = modP(y * iz) - const zz = modP(z * iz) - if (is0) return { x: _0n, y: _1n } - if (zz !== _1n) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - const assertValidMemo = (0, utils_js_1.memoized)((p) => { - const { a, d } = CURVE - if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? - // Equation in affine coordinates: ax² + y² = 1 + dx²y² - // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² - const { ex: X, ey: Y, ez: Z, et: T } = p - const X2 = modP(X * X) // X² - const Y2 = modP(Y * Y) // Y² - const Z2 = modP(Z * Z) // Z² - const Z4 = modP(Z2 * Z2) // Z⁴ - const aX2 = modP(X2 * a) // aX² - const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² - const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² - if (left !== right) throw new Error('bad point: equation left != right (1)') - // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T - const XY = modP(X * Y) - const ZT = modP(Z * T) - if (XY !== ZT) throw new Error('bad point: equation left != right (2)') - return true - }) - // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). - // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates - class Point { - constructor(ex, ey, ez, et) { - this.ex = ex - this.ey = ey - this.ez = ez - this.et = et - aCoordinate('x', ex) - aCoordinate('y', ey) - aCoordinate('z', ez) - aCoordinate('t', et) - Object.freeze(this) - } - get x() { - return this.toAffine().x - } - get y() { - return this.toAffine().y - } - static fromAffine(p) { - if (p instanceof Point) throw new Error('extended point not allowed') - const { x, y } = p || {} - aCoordinate('x', x) - aCoordinate('y', y) - return new Point(x, y, _1n, modP(x * y)) - } - static normalizeZ(points) { - const toInv = Fp.invertBatch(points.map((p) => p.ez)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - // Multiscalar Multiplication - static msm(points, scalars) { - return (0, curve_js_1.pippenger)(Point, Fn, points, scalars) - } - // "Private method", don't use it directly - _setWindowSize(windowSize) { - wnaf.setWindowSize(this, windowSize) - } - // Not required for fromHex(), which always creates valid points. - // Could be useful for fromAffine(). - assertValidity() { - assertValidMemo(this) - } - // Compare one point to another. - equals(other) { - assertPoint(other) - const { ex: X1, ey: Y1, ez: Z1 } = this - const { ex: X2, ey: Y2, ez: Z2 } = other - const X1Z2 = modP(X1 * Z2) - const X2Z1 = modP(X2 * Z1) - const Y1Z2 = modP(Y1 * Z2) - const Y2Z1 = modP(Y2 * Z1) - return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 - } - is0() { - return this.equals(Point.ZERO) - } - negate() { - // Flips point sign to a negative one (-x, y in affine coords) - return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) - } - // Fast algo for doubling Extended Point. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd - // Cost: 4M + 4S + 1*a + 6add + 1*2. - double() { - const { a } = CURVE - const { ex: X1, ey: Y1, ez: Z1 } = this - const A = modP(X1 * X1) // A = X12 - const B = modP(Y1 * Y1) // B = Y12 - const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 - const D = modP(a * A) // D = a*A - const x1y1 = X1 + Y1 - const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B - const G = D + B // G = D+B - const F = G - C // F = G-C - const H = D - B // H = D-B - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - // Fast algo for adding 2 Extended Points. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd - // Cost: 9M + 1*a + 1*d + 7add. - add(other) { - assertPoint(other) - const { a, d } = CURVE - const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this - const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other - // Faster algo for adding 2 Extended Points when curve's a=-1. - // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 - // Cost: 8M + 8add + 2*2. - // Note: It does not check whether the `other` point is valid. - if (a === BigInt(-1)) { - const A = modP((Y1 - X1) * (Y2 + X2)) - const B = modP((Y1 + X1) * (Y2 - X2)) - const F = modP(B - A) - if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing - const C = modP(Z1 * _2n * T2) - const D = modP(T1 * _2n * Z2) - const E = D + C - const G = B + A - const H = D - C - const X3 = modP(E * F) - const Y3 = modP(G * H) - const T3 = modP(E * H) - const Z3 = modP(F * G) - return new Point(X3, Y3, Z3, T3) - } - const A = modP(X1 * X2) // A = X1*X2 - const B = modP(Y1 * Y2) // B = Y1*Y2 - const C = modP(T1 * d * T2) // C = T1*d*T2 - const D = modP(Z1 * Z2) // D = Z1*Z2 - const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B - const F = D - C // F = D-C - const G = D + C // G = D+C - const H = modP(B - a * A) // H = B-a*A - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - subtract(other) { - return this.add(other.negate()) - } - wNAF(n) { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - // Constant-time multiplication. - multiply(scalar) { - const n = scalar - ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L - const { p, f } = this.wNAF(n) - return Point.normalizeZ([p, f])[0] - } - // Non-constant-time multiplication. Uses double-and-add algorithm. - // It's faster, but should only be used when you don't care about - // an exposed private key e.g. sig verification. - // Does NOT allow scalars higher than CURVE.n. - // Accepts optional accumulator to merge with multiply (important for sparse scalars) - multiplyUnsafe(scalar, acc = Point.ZERO) { - const n = scalar - ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L - if (n === _0n) return I - if (this.is0() || n === _1n) return this - return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) - } - // Checks if point is of small order. - // If you add something to small order point, you will have "dirty" - // point with torsion component. - // Multiplies point by cofactor and checks if the result is 0. - isSmallOrder() { - return this.multiplyUnsafe(cofactor).is0() - } - // Multiplies point by curve order and checks if the result is 0. - // Returns `false` is the point is dirty. - isTorsionFree() { - return wnaf.unsafeLadder(this, CURVE_ORDER).is0() - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - toAffine(iz) { - return toAffineMemo(this, iz) - } - clearCofactor() { - const { h: cofactor } = CURVE - if (cofactor === _1n) return this - return this.multiplyUnsafe(cofactor) - } - // Converts hash string or Uint8Array to Point. - // Uses algo from RFC8032 5.1.3. - static fromHex(hex, zip215 = false) { - const { d, a } = CURVE - const len = Fp.BYTES - hex = (0, utils_js_1.ensureBytes)('pointHex', hex, len) // copy hex to a new array - ;(0, utils_js_1.abool)('zip215', zip215) - const normed = hex.slice() // copy again, we'll manipulate it - const lastByte = hex[len - 1] // select last byte - normed[len - 1] = lastByte & ~0x80 // clear last bit - const y = ut.bytesToNumberLE(normed) - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // RFC8032 prohibits >= p, but ZIP215 doesn't - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - const max = zip215 ? MASK : Fp.ORDER - ut.aInRange('pointHex.y', y, _0n, max) - // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: - // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) - const y2 = modP(y * y) // denominator is always non-0 mod p. - const u = modP(y2 - _1n) // u = y² - 1 - const v = modP(d * y2 - a) // v = d y² + 1. - let { isValid, value: x } = uvRatio(u, v) // √(u/v) - if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') - const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper - const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit - if (!zip215 && x === _0n && isLastByteOdd) - // if x=0 and x_0 = 1, fail - throw new Error('Point.fromHex: x=0 and x_0=1') - if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x - return Point.fromAffine({ x, y }) - } - static fromPrivateKey(privKey) { - return getExtendedPublicKey(privKey).point - } - toRawBytes() { - const { x, y } = this.toAffine() - const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) - bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y - return bytes // and use the last byte to encode sign of x - } - toHex() { - return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. - } - } - Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) - Point.ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 - const { BASE: G, ZERO: I } = Point - const wnaf = (0, curve_js_1.wNAF)(Point, nByteLength * 8) - function modN(a) { - return (0, modular_js_1.mod)(a, CURVE_ORDER) - } - // Little-endian SHA512 with modulo n - function modN_LE(hash) { - return modN(ut.bytesToNumberLE(hash)) - } - /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ - function getExtendedPublicKey(key) { - const len = Fp.BYTES - key = (0, utils_js_1.ensureBytes)('private key', key, len) - // Hash private key with curve's hash function to produce uniformingly random input - // Check byte lengths: ensure(64, h(ensure(32, key))) - const hashed = (0, utils_js_1.ensureBytes)('hashed private key', cHash(key), 2 * len) - const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE - const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) - const scalar = modN_LE(head) // The actual private scalar - const point = G.multiply(scalar) // Point on Edwards curve aka public key - const pointBytes = point.toRawBytes() // Uint8Array representation - return { head, prefix, scalar, point, pointBytes } - } - // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared - function getPublicKey(privKey) { - return getExtendedPublicKey(privKey).pointBytes - } - // int('LE', SHA512(dom2(F, C) || msgs)) mod N - function hashDomainToScalar(context = new Uint8Array(), ...msgs) { - const msg = ut.concatBytes(...msgs) - return modN_LE(cHash(domain(msg, (0, utils_js_1.ensureBytes)('context', context), !!prehash))) - } - /** Signs message with privateKey. RFC8032 5.1.6 */ - function sign(msg, privKey, options = {}) { - msg = (0, utils_js_1.ensureBytes)('message', msg) - if (prehash) msg = prehash(msg) // for ed25519ph etc. - const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) - const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) - const R = G.multiply(r).toRawBytes() // R = rG - const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) - const s = modN(r + k * scalar) // S = (r + k * s) mod L - ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l - const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) - return (0, utils_js_1.ensureBytes)('result', res, Fp.BYTES * 2) // 64-byte signature - } - const verifyOpts = VERIFY_DEFAULT - /** - * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - * An extended group equation is checked. - */ - function verify(sig, msg, publicKey, options = verifyOpts) { - const { context, zip215 } = options - const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - sig = (0, utils_js_1.ensureBytes)('signature', sig, 2 * len) // An extended group equation is checked. - msg = (0, utils_js_1.ensureBytes)('message', msg) - publicKey = (0, utils_js_1.ensureBytes)('publicKey', publicKey, len) - if (zip215 !== undefined) (0, utils_js_1.abool)('zip215', zip215) - if (prehash) msg = prehash(msg) // for ed25519ph, etc - const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) - let A, R, SB - try { - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - A = Point.fromHex(publicKey, zip215) - R = Point.fromHex(sig.slice(0, len), zip215) - SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside - } catch (error) { - return false - } - if (!zip215 && A.isSmallOrder()) return false - const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) - const RkA = R.add(A.multiplyUnsafe(k)) - // Extended group equation - // [8][S]B = [8]R + [8][k]A' - return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) - } - G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. - const utils = { - getExtendedPublicKey, - // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. - randomPrivateKey: () => randomBytes(Fp.BYTES), - /** - * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT - * values. This slows down first getPublicKey() by milliseconds (see Speed section), - * but allows to speed-up subsequent getPublicKey() calls up to 20x. - * @param windowSize 2, 4, 8, 16 - */ - precompute(windowSize = 8, point = Point.BASE) { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) - return point - }, - } - return { - CURVE, - getPublicKey, - sign, - verify, - ExtendedPoint: Point, - utils, - } -} -//# sourceMappingURL=edwards.js.map diff --git a/packages/noble-curves/abstract/edwards.js.map b/packages/noble-curves/abstract/edwards.js.map deleted file mode 100644 index 91e38bbf020..00000000000 --- a/packages/noble-curves/abstract/edwards.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"edwards.js","sourceRoot":"","sources":["../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/hash-to-curve.d.ts b/packages/noble-curves/abstract/hash-to-curve.d.ts deleted file mode 100644 index 646647f9280..00000000000 --- a/packages/noble-curves/abstract/hash-to-curve.d.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import type { AffinePoint, Group, GroupConstructor } from './curve.js' -import { type IField } from './modular.js' -import type { CHash } from './utils.js' -export type UnicodeOrBytes = string | Uint8Array -/** - * * `DST` is a domain separation tag, defined in section 2.2.5 - * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m - * * `m` is extension degree (1 for prime fields) - * * `k` is the target security target in bits (e.g. 128), from section 5.1 - * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) - * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props - */ -export type Opts = { - DST: UnicodeOrBytes - p: bigint - m: number - k: number - expand: 'xmd' | 'xof' - hash: CHash -} -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -export declare function expand_message_xmd( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - H: CHash, -): Uint8Array -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -export declare function expand_message_xof( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - k: number, - H: CHash, -): Uint8Array -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -export declare function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] -export type XY = ( - x: T, - y: T, -) => { - x: T - y: T -} -export declare function isogenyMap>( - field: F, - map: [T[], T[], T[], T[]], -): XY -/** Point interface, which curves must implement to work correctly with the module. */ -export interface H2CPoint extends Group> { - add(rhs: H2CPoint): H2CPoint - toAffine(iz?: bigint): AffinePoint - clearCofactor(): H2CPoint - assertValidity(): void -} -export interface H2CPointConstructor extends GroupConstructor> { - fromAffine(ap: AffinePoint): H2CPoint -} -export type MapToCurve = (scalar: bigint[]) => AffinePoint -export type htfBasicOpts = { - DST: UnicodeOrBytes -} -export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint -export type MapMethod = (scalars: bigint[]) => H2CPoint -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -export declare function createHasher( - Point: H2CPointConstructor, - mapToCurve: MapToCurve, - def: Opts & { - encodeDST?: UnicodeOrBytes - }, -): { - hashToCurve: HTFMethod - encodeToCurve: HTFMethod - mapToCurve: MapMethod -} -//# sourceMappingURL=hash-to-curve.d.ts.map diff --git a/packages/noble-curves/abstract/hash-to-curve.d.ts.map b/packages/noble-curves/abstract/hash-to-curve.d.ts.map deleted file mode 100644 index cd7dda14a2d..00000000000 --- a/packages/noble-curves/abstract/hash-to-curve.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"hash-to-curve.d.ts","sourceRoot":"","sources":["../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/hash-to-curve.js b/packages/noble-curves/abstract/hash-to-curve.js deleted file mode 100644 index 8e48fcffc8a..00000000000 --- a/packages/noble-curves/abstract/hash-to-curve.js +++ /dev/null @@ -1,184 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.expand_message_xmd = expand_message_xmd -exports.expand_message_xof = expand_message_xof -exports.hash_to_field = hash_to_field -exports.isogenyMap = isogenyMap -exports.createHasher = createHasher -const modular_js_1 = require('./modular.js') -const utils_js_1 = require('./utils.js') -// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. -const os2ip = utils_js_1.bytesToNumberBE -// Integer to Octet Stream (numberToBytesBE) -function i2osp(value, length) { - anum(value) - anum(length) - if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) - 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 -} -function anum(item) { - if (!Number.isSafeInteger(item)) throw new Error('number expected') -} -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -function expand_message_xmd(msg, DST, lenInBytes, H) { - ;(0, utils_js_1.abytes)(msg) - ;(0, utils_js_1.abytes)(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - if (DST.length > 255) - DST = H((0, utils_js_1.concatBytes)((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-'), DST)) - const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H - const ell = Math.ceil(lenInBytes / b_in_bytes) - if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') - const DST_prime = (0, utils_js_1.concatBytes)(DST, i2osp(DST.length, 1)) - const Z_pad = i2osp(0, r_in_bytes) - const l_i_b_str = i2osp(lenInBytes, 2) // len_in_bytes_str - const b = new Array(ell) - const b_0 = H((0, utils_js_1.concatBytes)(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) - b[0] = H((0, utils_js_1.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] = H((0, utils_js_1.concatBytes)(...args)) - } - const pseudo_random_bytes = (0, utils_js_1.concatBytes)(...b) - return pseudo_random_bytes.slice(0, lenInBytes) -} -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -function expand_message_xof(msg, DST, lenInBytes, k, H) { - ;(0, utils_js_1.abytes)(msg) - ;(0, utils_js_1.abytes)(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); - if (DST.length > 255) { - const dkLen = Math.ceil((2 * k) / 8) - DST = H.create({ dkLen }) - .update((0, utils_js_1.utf8ToBytes)('H2C-OVERSIZE-DST-')) - .update(DST) - .digest() - } - if (lenInBytes > 65535 || DST.length > 255) - throw new Error('expand_message_xof: invalid lenInBytes') - return ( - H.create({ dkLen: lenInBytes }) - .update(msg) - .update(i2osp(lenInBytes, 2)) - // 2. DST_prime = DST || I2OSP(len(DST), 1) - .update(DST) - .update(i2osp(DST.length, 1)) - .digest() - ) -} -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -function hash_to_field(msg, count, options) { - ;(0, utils_js_1.validateObject)(options, { - DST: 'stringOrUint8Array', - p: 'bigint', - m: 'isSafeInteger', - k: 'isSafeInteger', - hash: 'hash', - }) - const { p, k, m, hash, expand, DST: _DST } = options - ;(0, utils_js_1.abytes)(msg) - anum(count) - const DST = typeof _DST === 'string' ? (0, utils_js_1.utf8ToBytes)(_DST) : _DST - const log2p = p.toString(2).length - const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above - const len_in_bytes = count * m * L - let prb // pseudo_random_bytes - if (expand === 'xmd') { - prb = expand_message_xmd(msg, DST, len_in_bytes, hash) - } else if (expand === 'xof') { - prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) - } else if (expand === '_internal_pass') { - // for internal tests only - prb = msg - } else { - throw new Error('expand must be "xmd" or "xof"') - } - const u = new Array(count) - for (let i = 0; i < count; i++) { - const e = new Array(m) - for (let j = 0; j < m; j++) { - const elm_offset = L * (j + i * m) - const tv = prb.subarray(elm_offset, elm_offset + L) - e[j] = (0, modular_js_1.mod)(os2ip(tv), p) - } - u[i] = e - } - return u -} -function isogenyMap(field, map) { - // Make same order as in spec - const COEFF = map.map((i) => Array.from(i).reverse()) - return (x, y) => { - const [xNum, xDen, yNum, yDen] = COEFF.map((val) => - val.reduce((acc, i) => field.add(field.mul(acc, x), i)), - ) - x = field.div(xNum, xDen) // xNum / xDen - y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) - return { x: x, y: y } - } -} -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -function createHasher(Point, mapToCurve, def) { - if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') - return { - // Encodes byte string to elliptic curve. - // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - hashToCurve(msg, options) { - const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options }) - const u0 = Point.fromAffine(mapToCurve(u[0])) - const u1 = Point.fromAffine(mapToCurve(u[1])) - const P = u0.add(u1).clearCofactor() - P.assertValidity() - return P - }, - // Encodes byte string to elliptic curve. - // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - encodeToCurve(msg, options) { - const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options }) - const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() - P.assertValidity() - return P - }, - // Same as encodeToCurve, but without hash - mapToCurve(scalars) { - if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') - for (const i of scalars) - if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') - const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() - P.assertValidity() - return P - }, - } -} -//# sourceMappingURL=hash-to-curve.js.map diff --git a/packages/noble-curves/abstract/hash-to-curve.js.map b/packages/noble-curves/abstract/hash-to-curve.js.map deleted file mode 100644 index e005e9630da..00000000000 --- a/packages/noble-curves/abstract/hash-to-curve.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"hash-to-curve.js","sourceRoot":"","sources":["../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/modular.d.ts b/packages/noble-curves/abstract/modular.d.ts deleted file mode 100644 index c95a932142e..00000000000 --- a/packages/noble-curves/abstract/modular.d.ts +++ /dev/null @@ -1,168 +0,0 @@ -export declare function mod(a: bigint, b: bigint): bigint -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -export declare function invert(number: bigint, modulo: bigint): bigint -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -export declare function tonelliShanks(P: bigint): (Fp: IField, n: T) => T -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -export declare function FpSqrt(P: bigint): (Fp: IField, n: T) => T -export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean -/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ -export interface IField { - ORDER: bigint - isLE: boolean - BYTES: number - BITS: number - MASK: bigint - ZERO: T - ONE: T - create: (num: T) => T - isValid: (num: T) => boolean - is0: (num: T) => boolean - neg(num: T): T - inv(num: T): T - sqrt(num: T): T - sqr(num: T): T - eql(lhs: T, rhs: T): boolean - add(lhs: T, rhs: T): T - sub(lhs: T, rhs: T): T - mul(lhs: T, rhs: T | bigint): T - pow(lhs: T, power: bigint): T - div(lhs: T, rhs: T | bigint): T - addN(lhs: T, rhs: T): T - subN(lhs: T, rhs: T): T - mulN(lhs: T, rhs: T | bigint): T - sqrN(num: T): T - isOdd?(num: T): boolean - pow(lhs: T, power: bigint): T - invertBatch: (lst: T[]) => T[] - toBytes(num: T): Uint8Array - fromBytes(bytes: Uint8Array): T - cmov(a: T, b: T, c: boolean): T -} -export declare function validateField(field: IField): IField -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -export declare function FpPow(f: IField, num: T, power: bigint): T -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -export declare function FpInvertBatch(f: IField, nums: T[]): T[] -export declare function FpDiv(f: IField, lhs: T, rhs: T | bigint): T -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -export declare function FpLegendre(order: bigint): (f: IField, x: T) => T -export declare function FpIsSquare(f: IField): (x: T) => boolean -export declare function nLength( - n: bigint, - nBitLength?: number, -): { - nBitLength: number - nByteLength: number -} -type FpField = IField & Required, 'isOdd'>> -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -export declare function Field( - ORDER: bigint, - bitLen?: number, - isLE?: boolean, - redef?: Partial>, -): Readonly -export declare function FpSqrtOdd(Fp: IField, elm: T): T -export declare function FpSqrtEven(Fp: IField, elm: T): T -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -export declare function hashToPrivateScalar( - hash: string | Uint8Array, - groupOrder: bigint, - isLE?: boolean, -): bigint -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -export declare function getFieldBytesLength(fieldOrder: bigint): number -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -export declare function getMinHashLength(fieldOrder: bigint): number -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -export declare function mapHashToField( - key: Uint8Array, - fieldOrder: bigint, - isLE?: boolean, -): Uint8Array -export {} -//# sourceMappingURL=modular.d.ts.map diff --git a/packages/noble-curves/abstract/modular.d.ts.map b/packages/noble-curves/abstract/modular.d.ts.map deleted file mode 100644 index d1a5311a14a..00000000000 --- a/packages/noble-curves/abstract/modular.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"modular.d.ts","sourceRoot":"","sources":["../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/modular.js b/packages/noble-curves/abstract/modular.js deleted file mode 100644 index 9f63624e1e7..00000000000 --- a/packages/noble-curves/abstract/modular.js +++ /dev/null @@ -1,485 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.isNegativeLE = void 0 -exports.mod = mod -exports.pow = pow -exports.pow2 = pow2 -exports.invert = invert -exports.tonelliShanks = tonelliShanks -exports.FpSqrt = FpSqrt -exports.validateField = validateField -exports.FpPow = FpPow -exports.FpInvertBatch = FpInvertBatch -exports.FpDiv = FpDiv -exports.FpLegendre = FpLegendre -exports.FpIsSquare = FpIsSquare -exports.nLength = nLength -exports.Field = Field -exports.FpSqrtOdd = FpSqrtOdd -exports.FpSqrtEven = FpSqrtEven -exports.hashToPrivateScalar = hashToPrivateScalar -exports.getFieldBytesLength = getFieldBytesLength -exports.getMinHashLength = getMinHashLength -exports.mapHashToField = mapHashToField -/** - * Utils for modular division and finite fields. - * A finite field over 11 is integer number operations `mod 11`. - * There is no division: it is replaced by modular multiplicative inverse. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const utils_js_1 = require('./utils.js') -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = /* @__PURE__ */ BigInt(2), - _3n = /* @__PURE__ */ BigInt(3) -// prettier-ignore -const _4n = /* @__PURE__ */ BigInt(4), - _5n = /* @__PURE__ */ BigInt(5), - _8n = /* @__PURE__ */ BigInt(8) -// prettier-ignore -const _9n = /* @__PURE__ */ BigInt(9), - _16n = /* @__PURE__ */ BigInt(16) -// Calculates a modulo b -function mod(a, b) { - const result = a % b - return result >= _0n ? result : b + result -} -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -function pow(num, power, modulo) { - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (modulo <= _0n) throw new Error('invalid modulus') - 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 -} -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -function pow2(x, power, modulo) { - let res = x - while (power-- > _0n) { - res *= res - res %= modulo - } - return res -} -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -function invert(number, modulo) { - if (number === _0n) throw new Error('invert: expected non-zero number') - if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) - // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. - let a = mod(number, modulo) - let b = modulo - // prettier-ignore - let x = _0n, - y = _1n, - u = _1n, - v = _0n - while (a !== _0n) { - // JIT applies optimization if those two lines follow each other - const q = b / a - const r = b % a - const m = x - u * q - const n = y - v * q - // prettier-ignore - ;(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) -} -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -function tonelliShanks(P) { - // Legendre constant: used to calculate Legendre symbol (a | p), - // which denotes the value of a^((p-1)/2) (mod p). - // (a | p) ≡ 1 if a is a square (mod p) - // (a | p) ≡ -1 if a is not a square (mod p) - // (a | p) ≡ 0 if a ≡ 0 (mod p) - const legendreC = (P - _1n) / _2n - let Q, S, Z - // Step 1: By factoring out powers of 2 from p - 1, - // find q and s such that p - 1 = q*(2^s) with q odd - for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); - // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq - for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { - // Crash instead of infinity loop, we cannot reasonable count until P. - if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') - } - // Fast-path - if (S === 1) { - const p1div4 = (P + _1n) / _4n - return function tonelliFast(Fp, n) { - const root = Fp.pow(n, p1div4) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // Slow-path - const Q1div2 = (Q + _1n) / _2n - return function tonelliSlow(Fp, n) { - // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 - if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') - let r = S - // TODO: will fail at Fp2/etc - let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b - let x = Fp.pow(n, Q1div2) // first guess at the square root - let b = Fp.pow(n, Q) // first guess at the fudge factor - while (!Fp.eql(b, Fp.ONE)) { - if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) - // Find m such b^(2^m)==1 - let m = 1 - for (let t2 = Fp.sqr(b); m < r; m++) { - if (Fp.eql(t2, Fp.ONE)) break - t2 = Fp.sqr(t2) // t2 *= t2 - } - // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow - const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) - g = Fp.sqr(ge) // g = ge * ge - x = Fp.mul(x, ge) // x *= ge - b = Fp.mul(b, g) // b *= g - r = m - } - return x - } -} -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -function FpSqrt(P) { - // P ≡ 3 (mod 4) - // √n = n^((P+1)/4) - if (P % _4n === _3n) { - // Not all roots possible! - // const ORDER = - // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; - // const NUM = 72057594037927816n; - const p1div4 = (P + _1n) / _4n - return function sqrt3mod4(Fp, n) { - const root = Fp.pow(n, p1div4) - // Throw if root**2 != n - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) - if (P % _8n === _5n) { - const c1 = (P - _5n) / _8n - return function sqrt5mod8(Fp, n) { - const n2 = Fp.mul(n, _2n) - const v = Fp.pow(n2, c1) - const nv = Fp.mul(n, v) - const i = Fp.mul(Fp.mul(nv, _2n), v) - const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // P ≡ 9 (mod 16) - if (P % _16n === _9n) { - // NOTE: tonelli is too slow for bls-Fp2 calculations even on start - // Means we cannot use sqrt for constants at all! - // - // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F - // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F - // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F - // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic - // sqrt = (x) => { - // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 - // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 - // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 - // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 - // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x - // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x - // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x - // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x - // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x - // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 - // } - } - // Other cases: Tonelli-Shanks algorithm - return tonelliShanks(P) -} -// Little-endian check for first LE bit (last BE bit); -const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n -exports.isNegativeLE = isNegativeLE -// prettier-ignore -const FIELD_FIELDS = [ - 'create', - 'isValid', - 'is0', - 'neg', - 'inv', - 'sqrt', - 'sqr', - 'eql', - 'add', - 'sub', - 'mul', - 'pow', - 'div', - 'addN', - 'subN', - 'mulN', - 'sqrN', -] -function validateField(field) { - const initial = { - ORDER: 'bigint', - MASK: 'bigint', - BYTES: 'isSafeInteger', - BITS: 'isSafeInteger', - } - const opts = FIELD_FIELDS.reduce((map, val) => { - map[val] = 'function' - return map - }, initial) - return (0, utils_js_1.validateObject)(field, opts) -} -// Generic field functions -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -function FpPow(f, num, power) { - // Should have same speed as pow for bigints - // TODO: benchmark! - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (power === _0n) return f.ONE - if (power === _1n) return num - let p = f.ONE - let d = num - while (power > _0n) { - if (power & _1n) p = f.mul(p, d) - d = f.sqr(d) - power >>= _1n - } - return p -} -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -function FpInvertBatch(f, nums) { - const tmp = new Array(nums.length) - // Walk from first to last, multiply them by each other MOD p - const lastMultiplied = nums.reduce((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = acc - return f.mul(acc, num) - }, f.ONE) - // Invert last element - const inverted = f.inv(lastMultiplied) - // Walk from last to first, multiply them by inverted each other MOD p - nums.reduceRight((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = f.mul(acc, tmp[i]) - return f.mul(acc, num) - }, inverted) - return tmp -} -function FpDiv(f, lhs, rhs) { - return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) -} -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -function FpLegendre(order) { - const legendreConst = (order - _1n) / _2n // Integer arithmetic - return (f, x) => f.pow(x, legendreConst) -} -// This function returns True whenever the value x is a square in the field F. -function FpIsSquare(f) { - const legendre = FpLegendre(f.ORDER) - return (x) => { - const p = legendre(f, x) - return f.eql(p, f.ZERO) || f.eql(p, f.ONE) - } -} -// CURVE.n lengths -function nLength(n, nBitLength) { - // Bit size, byte size of CURVE.n - const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length - const nByteLength = Math.ceil(_nBitLength / 8) - return { nBitLength: _nBitLength, nByteLength } -} -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -function Field(ORDER, bitLen, isLE = false, redef = {}) { - if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) - const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) - if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') - let sqrtP // cached sqrtP - const f = Object.freeze({ - ORDER, - isLE, - BITS, - BYTES, - MASK: (0, utils_js_1.bitMask)(BITS), - ZERO: _0n, - ONE: _1n, - create: (num) => mod(num, ORDER), - isValid: (num) => { - if (typeof num !== 'bigint') - throw new Error('invalid field element: expected bigint, got ' + typeof num) - return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible - }, - is0: (num) => num === _0n, - isOdd: (num) => (num & _1n) === _1n, - neg: (num) => mod(-num, ORDER), - eql: (lhs, rhs) => lhs === rhs, - sqr: (num) => mod(num * num, ORDER), - add: (lhs, rhs) => mod(lhs + rhs, ORDER), - sub: (lhs, rhs) => mod(lhs - rhs, ORDER), - mul: (lhs, rhs) => mod(lhs * rhs, ORDER), - pow: (num, power) => FpPow(f, num, power), - div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), - // Same as above, but doesn't normalize - sqrN: (num) => num * num, - addN: (lhs, rhs) => lhs + rhs, - subN: (lhs, rhs) => lhs - rhs, - mulN: (lhs, rhs) => lhs * rhs, - inv: (num) => invert(num, ORDER), - sqrt: - redef.sqrt || - ((n) => { - if (!sqrtP) sqrtP = FpSqrt(ORDER) - return sqrtP(f, n) - }), - invertBatch: (lst) => FpInvertBatch(f, lst), - // TODO: do we really need constant cmov? - // We don't have const-time bigints anyway, so probably will be not very useful - cmov: (a, b, c) => (c ? b : a), - toBytes: (num) => - isLE - ? (0, utils_js_1.numberToBytesLE)(num, BYTES) - : (0, utils_js_1.numberToBytesBE)(num, BYTES), - fromBytes: (bytes) => { - if (bytes.length !== BYTES) - throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) - return isLE ? (0, utils_js_1.bytesToNumberLE)(bytes) : (0, utils_js_1.bytesToNumberBE)(bytes) - }, - }) - return Object.freeze(f) -} -function FpSqrtOdd(Fp, elm) { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? root : Fp.neg(root) -} -function FpSqrtEven(Fp, elm) { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? Fp.neg(root) : root -} -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -function hashToPrivateScalar(hash, groupOrder, isLE = false) { - hash = (0, utils_js_1.ensureBytes)('privateHash', hash) - const hashLen = hash.length - const minLen = nLength(groupOrder).nByteLength + 8 - if (minLen < 24 || hashLen < minLen || hashLen > 1024) - throw new Error( - 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, - ) - const num = isLE ? (0, utils_js_1.bytesToNumberLE)(hash) : (0, utils_js_1.bytesToNumberBE)(hash) - return mod(num, groupOrder - _1n) + _1n -} -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -function getFieldBytesLength(fieldOrder) { - if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') - const bitLength = fieldOrder.toString(2).length - return Math.ceil(bitLength / 8) -} -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -function getMinHashLength(fieldOrder) { - const length = getFieldBytesLength(fieldOrder) - return length + Math.ceil(length / 2) -} -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -function mapHashToField(key, fieldOrder, isLE = false) { - const len = key.length - const fieldLen = getFieldBytesLength(fieldOrder) - const minLen = getMinHashLength(fieldOrder) - // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. - if (len < 16 || len < minLen || len > 1024) - throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) - const num = isLE ? (0, utils_js_1.bytesToNumberLE)(key) : (0, utils_js_1.bytesToNumberBE)(key) - // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 - const reduced = mod(num, fieldOrder - _1n) + _1n - return isLE - ? (0, utils_js_1.numberToBytesLE)(reduced, fieldLen) - : (0, utils_js_1.numberToBytesBE)(reduced, fieldLen) -} -//# sourceMappingURL=modular.js.map diff --git a/packages/noble-curves/abstract/modular.js.map b/packages/noble-curves/abstract/modular.js.map deleted file mode 100644 index 89e17765c36..00000000000 --- a/packages/noble-curves/abstract/modular.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"modular.js","sourceRoot":"","sources":["../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/montgomery.d.ts b/packages/noble-curves/abstract/montgomery.d.ts deleted file mode 100644 index 64a01ea5d1c..00000000000 --- a/packages/noble-curves/abstract/montgomery.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -type Hex = string | Uint8Array -export type CurveType = { - P: bigint - nByteLength: number - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - a: bigint - montgomeryBits: number - powPminus2?: (x: bigint) => bigint - xyToU?: (x: bigint, y: bigint) => bigint - Gu: bigint - randomBytes?: (bytesLength?: number) => Uint8Array -} -export type CurveFn = { - scalarMult: (scalar: Hex, u: Hex) => Uint8Array - scalarMultBase: (scalar: Hex) => Uint8Array - getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array - getPublicKey: (privateKey: Hex) => Uint8Array - utils: { - randomPrivateKey: () => Uint8Array - } - GuBytes: Uint8Array -} -export declare function montgomery(curveDef: CurveType): CurveFn -export {} -//# sourceMappingURL=montgomery.d.ts.map diff --git a/packages/noble-curves/abstract/montgomery.d.ts.map b/packages/noble-curves/abstract/montgomery.d.ts.map deleted file mode 100644 index 5b04dc83510..00000000000 --- a/packages/noble-curves/abstract/montgomery.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../src/abstract/montgomery.ts"],"names":[],"mappings":"AAkBA,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACtD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC;IAC5E,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IACnE,YAAY,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAC9C,KAAK,EAAE;QAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;KAAE,CAAC;IAC9C,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAsBF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAqIvD"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/montgomery.js b/packages/noble-curves/abstract/montgomery.js deleted file mode 100644 index 97e5d70ea11..00000000000 --- a/packages/noble-curves/abstract/montgomery.js +++ /dev/null @@ -1,162 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.montgomery = montgomery -/** - * Montgomery curve methods. It's not really whole montgomery curve, - * just bunch of very specific methods for X25519 / X448 from - * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const modular_js_1 = require('./modular.js') -const utils_js_1 = require('./utils.js') -const _0n = BigInt(0) -const _1n = BigInt(1) -function validateOpts(curve) { - ;(0, utils_js_1.validateObject)( - curve, - { - a: 'bigint', - }, - { - montgomeryBits: 'isSafeInteger', - nByteLength: 'isSafeInteger', - adjustScalarBytes: 'function', - domain: 'function', - powPminus2: 'function', - Gu: 'bigint', - }, - ) - // Set defaults - return Object.freeze({ ...curve }) -} -// Uses only one coordinate instead of two -function montgomery(curveDef) { - const CURVE = validateOpts(curveDef) - const { P } = CURVE - const modP = (n) => (0, modular_js_1.mod)(n, P) - const montgomeryBits = CURVE.montgomeryBits - const montgomeryBytes = Math.ceil(montgomeryBits / 8) - const fieldLen = CURVE.nByteLength - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) - const powPminus2 = CURVE.powPminus2 || ((x) => (0, modular_js_1.pow)(x, P - BigInt(2), P)) - // cswap from RFC7748. But it is not from RFC7748! - /* - cswap(swap, x_2, x_3): - dummy = mask(swap) AND (x_2 XOR x_3) - x_2 = x_2 XOR dummy - x_3 = x_3 XOR dummy - Return (x_2, x_3) - Where mask(swap) is the all-1 or all-0 word of the same length as x_2 - and x_3, computed, e.g., as mask(swap) = 0 - swap. - */ - function cswap(swap, x_2, x_3) { - const dummy = modP(swap * (x_2 - x_3)) - x_2 = modP(x_2 - dummy) - x_3 = modP(x_3 + dummy) - return [x_2, x_3] - } - // x25519 from 4 - // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 - const a24 = (CURVE.a - BigInt(2)) / BigInt(4) - /** - * - * @param pointU u coordinate (x) on Montgomery Curve 25519 - * @param scalar by which the point would be multiplied - * @returns new Point on Montgomery curve - */ - function montgomeryLadder(u, scalar) { - ;(0, utils_js_1.aInRange)('u', u, _0n, P) - ;(0, utils_js_1.aInRange)('scalar', scalar, _0n, P) - // Section 5: Implementations MUST accept non-canonical values and process them as - // if they had been reduced modulo the field prime. - const k = scalar - const x_1 = u - let x_2 = _1n - let z_2 = _0n - let x_3 = u - let z_3 = _1n - let swap = _0n - let sw - for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { - const k_t = (k >> t) & _1n - swap ^= k_t - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - swap = k_t - const A = x_2 + z_2 - const AA = modP(A * A) - const B = x_2 - z_2 - const BB = modP(B * B) - const E = AA - BB - const C = x_3 + z_3 - const D = x_3 - z_3 - const DA = modP(D * A) - const CB = modP(C * B) - const dacb = DA + CB - const da_cb = DA - CB - x_3 = modP(dacb * dacb) - z_3 = modP(x_1 * modP(da_cb * da_cb)) - x_2 = modP(AA * BB) - z_2 = modP(E * (AA + modP(a24 * E))) - } - // (x_2, x_3) = cswap(swap, x_2, x_3) - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - // (z_2, z_3) = cswap(swap, z_2, z_3) - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - // z_2^(p - 2) - const z2 = powPminus2(z_2) - // Return x_2 * (z_2^(p - 2)) - return modP(x_2 * z2) - } - function encodeUCoordinate(u) { - return (0, utils_js_1.numberToBytesLE)(modP(u), montgomeryBytes) - } - function decodeUCoordinate(uEnc) { - // Section 5: When receiving such an array, implementations of X25519 - // MUST mask the most significant bit in the final byte. - const u = (0, utils_js_1.ensureBytes)('u coordinate', uEnc, montgomeryBytes) - if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 - return (0, utils_js_1.bytesToNumberLE)(u) - } - function decodeScalar(n) { - const bytes = (0, utils_js_1.ensureBytes)('scalar', n) - const len = bytes.length - if (len !== montgomeryBytes && len !== fieldLen) { - let valid = '' + montgomeryBytes + ' or ' + fieldLen - throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) - } - return (0, utils_js_1.bytesToNumberLE)(adjustScalarBytes(bytes)) - } - function scalarMult(scalar, u) { - const pointU = decodeUCoordinate(u) - const _scalar = decodeScalar(scalar) - const pu = montgomeryLadder(pointU, _scalar) - // The result was not contributory - // https://cr.yp.to/ecdh.html#validate - if (pu === _0n) throw new Error('invalid private or public key received') - return encodeUCoordinate(pu) - } - // Computes public key from private. By doing scalar multiplication of base point. - const GuBytes = encodeUCoordinate(CURVE.Gu) - function scalarMultBase(scalar) { - return scalarMult(scalar, GuBytes) - } - return { - scalarMult, - scalarMultBase, - getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey), - getPublicKey: (privateKey) => scalarMultBase(privateKey), - utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) }, - GuBytes: GuBytes, - } -} -//# sourceMappingURL=montgomery.js.map diff --git a/packages/noble-curves/abstract/montgomery.js.map b/packages/noble-curves/abstract/montgomery.js.map deleted file mode 100644 index f7c44bbf434..00000000000 --- a/packages/noble-curves/abstract/montgomery.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"montgomery.js","sourceRoot":"","sources":["../src/abstract/montgomery.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/poseidon.d.ts b/packages/noble-curves/abstract/poseidon.d.ts deleted file mode 100644 index 37c473b1465..00000000000 --- a/packages/noble-curves/abstract/poseidon.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -export type PoseidonOpts = { - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean - mds: bigint[][] - roundConstants: bigint[][] -} -export declare function validateOpts(opts: PoseidonOpts): Readonly<{ - rounds: number - sboxFn: (n: bigint) => bigint - roundConstants: bigint[][] - mds: bigint[][] - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean -}> -export declare function splitConstants(rc: bigint[], t: number): bigint[][] -/** Poseidon NTT-friendly hash. */ -export declare function poseidon(opts: PoseidonOpts): { - (values: bigint[]): bigint[] - roundConstants: bigint[][] -} -//# sourceMappingURL=poseidon.d.ts.map diff --git a/packages/noble-curves/abstract/poseidon.d.ts.map b/packages/noble-curves/abstract/poseidon.d.ts.map deleted file mode 100644 index f984629539b..00000000000 --- a/packages/noble-curves/abstract/poseidon.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"poseidon.d.ts","sourceRoot":"","sources":["../src/abstract/poseidon.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sEAAsE;AACtE,OAAO,EAAS,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,CA6CD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAalE;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG;IAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAE7B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAmCA"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/poseidon.js b/packages/noble-curves/abstract/poseidon.js deleted file mode 100644 index 66b16492669..00000000000 --- a/packages/noble-curves/abstract/poseidon.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.validateOpts = validateOpts -exports.splitConstants = splitConstants -exports.poseidon = poseidon -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const modular_js_1 = require('./modular.js') -function validateOpts(opts) { - const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts - const { roundsFull, roundsPartial, sboxPower, t } = opts - ;(0, modular_js_1.validateField)(Fp) - for (const i of ['t', 'roundsFull', 'roundsPartial']) { - if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) - throw new Error('invalid number ' + i) - } - // MDS is TxT matrix - if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') - const _mds = mds.map((mdsRow) => { - if (!Array.isArray(mdsRow) || mdsRow.length !== t) - throw new Error('invalid MDS matrix row: ' + mdsRow) - return mdsRow.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) - return Fp.create(i) - }) - }) - if (rev !== undefined && typeof rev !== 'boolean') - throw new Error('invalid param reversePartialPowIdx=' + rev) - if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) - const rounds = roundsFull + roundsPartial - if (!Array.isArray(rc) || rc.length !== rounds) - throw new Error('Poseidon: invalid round constants') - const roundConstants = rc.map((rc) => { - if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') - return rc.map((i) => { - if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') - return Fp.create(i) - }) - }) - if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') - const _sboxPower = BigInt(sboxPower) - let sboxFn = (n) => (0, modular_js_1.FpPow)(Fp, n, _sboxPower) - // Unwrapped sbox power for common cases (195->142μs) - if (sboxPower === 3) sboxFn = (n) => Fp.mul(Fp.sqrN(n), n) - else if (sboxPower === 5) sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) - return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) -} -function splitConstants(rc, t) { - if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') - if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') - const res = [] - let tmp = [] - for (let i = 0; i < rc.length; i++) { - tmp.push(rc[i]) - if (tmp.length === t) { - res.push(tmp) - tmp = [] - } - } - return res -} -/** Poseidon NTT-friendly hash. */ -function poseidon(opts) { - const _opts = validateOpts(opts) - const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts - const halfRoundsFull = _opts.roundsFull / 2 - const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 - const poseidonRound = (values, isFull, idx) => { - values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) - if (isFull) values = values.map((i) => sboxFn(i)) - else values[partialIdx] = sboxFn(values[partialIdx]) - // Matrix multiplication - values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) - return values - } - const poseidonHash = function poseidonHash(values) { - if (!Array.isArray(values) || values.length !== t) - throw new Error('invalid values, expected array of bigints with length ' + t) - values = values.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) - return Fp.create(i) - }) - let lastRound = 0 - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - // Apply r_p partial rounds. - for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - if (lastRound !== totalRounds) throw new Error('invalid number of rounds') - return values - } - // For verification in tests - poseidonHash.roundConstants = roundConstants - return poseidonHash -} -//# sourceMappingURL=poseidon.js.map diff --git a/packages/noble-curves/abstract/poseidon.js.map b/packages/noble-curves/abstract/poseidon.js.map deleted file mode 100644 index eabe9f385c1..00000000000 --- a/packages/noble-curves/abstract/poseidon.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"poseidon.js","sourceRoot":"","sources":["../src/abstract/poseidon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/tower.d.ts b/packages/noble-curves/abstract/tower.d.ts deleted file mode 100644 index 34d68c39e3b..00000000000 --- a/packages/noble-curves/abstract/tower.d.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import * as mod from './modular.js' -import type { ProjConstructor, ProjPointType } from './weierstrass.js' -export type BigintTuple = [bigint, bigint] -export type Fp = bigint -export type Fp2 = { - c0: bigint - c1: bigint -} -export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] -export type Fp6 = { - c0: Fp2 - c1: Fp2 - c2: Fp2 -} -export type Fp12 = { - c0: Fp6 - c1: Fp6 -} -export type BigintTwelve = [ - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, -] -export type Fp2Bls = mod.IField & { - reim: (num: Fp2) => { - re: Fp - im: Fp - } - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - fromBigTuple(num: [bigint, bigint]): Fp2 -} -export type Fp12Bls = mod.IField & { - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - fromBigTwelve(num: BigintTwelve): Fp12 -} -export declare function psiFrobenius( - Fp: mod.IField, - Fp2: Fp2Bls, - base: Fp2, -): { - psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] - psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] - G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType - G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType - PSI_X: Fp2 - PSI_Y: Fp2 - PSI2_X: Fp2 - PSI2_Y: Fp2 -} -export type Tower12Opts = { - ORDER: bigint - NONRESIDUE?: Fp - FP2_NONRESIDUE: BigintTuple - Fp2sqrt?: (num: Fp2) => Fp2 - Fp2mulByB: (num: Fp2) => Fp2 - Fp12cyclotomicSquare: (num: Fp12) => Fp12 - Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 - Fp12finalExponentiate: (num: Fp12) => Fp12 -} -export declare function tower12(opts: Tower12Opts): { - Fp: Readonly & Required, 'isOdd'>>> - Fp2: mod.IField & { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { - re: bigint - im: bigint - } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - Fp6: mod.IField & { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - Fp4Square: ( - a: Fp2, - b: Fp2, - ) => { - first: Fp2 - second: Fp2 - } - Fp12: mod.IField & { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } -} -//# sourceMappingURL=tower.d.ts.map diff --git a/packages/noble-curves/abstract/tower.d.ts.map b/packages/noble-curves/abstract/tower.d.ts.map deleted file mode 100644 index 436e2fecb8d..00000000000 --- a/packages/noble-curves/abstract/tower.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"tower.d.ts","sourceRoot":"","sources":["../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/tower.js b/packages/noble-curves/abstract/tower.js deleted file mode 100644 index 0094e80cdcc..00000000000 --- a/packages/noble-curves/abstract/tower.js +++ /dev/null @@ -1,520 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.psiFrobenius = psiFrobenius -exports.tower12 = tower12 -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const mod = require('./modular.js') -const utils_js_1 = require('./utils.js') -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) { - const _divisor = BigInt(divisor === undefined ? degree : divisor) - const towerModulus = modulus ** BigInt(degree) - const res = [] - for (let i = 0; i < num; i++) { - const a = BigInt(i + 1) - const powers = [] - for (let j = 0, qPower = _1n; j < degree; j++) { - const power = ((a * qPower - a) / _divisor) % towerModulus - powers.push(Fp.pow(nonResidue, power)) - qPower *= modulus - } - res.push(powers) - } - return res -} -// This works same at least for bls12-381, bn254 and bls12-377 -function psiFrobenius(Fp, Fp2, base) { - // Ψ endomorphism - const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) - const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) - function psi(x, y) { - // This x10 faster than previous version in bls12-381 - const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) - const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) - return [x2, y2] - } - // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) - const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) - // This equals -1, which causes y to be Fp2.neg(y). - // But not sure if there are case when this is not true? - const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) - if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') - function psi2(x, y) { - return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] - } - // Map points - const mapAffine = (fn) => (c, P) => { - const affine = P.toAffine() - const p = fn(affine.x, affine.y) - return c.fromAffine({ x: p[0], y: p[1] }) - } - const G2psi = mapAffine(psi) - const G2psi2 = mapAffine(psi2) - return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } -} -function tower12(opts) { - const { ORDER } = opts - // Fp - const Fp = mod.Field(ORDER) - const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) - const FpLegendre = mod.FpLegendre(ORDER) - const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 - // Fp2 - const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] - const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp.add(c0, r0), - c1: Fp.add(c1, r1), - }) - const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp.sub(c0, r0), - c1: Fp.sub(c1, r1), - }) - const Fp2Multiply = ({ c0, c1 }, rhs) => { - if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } - // (a+bi)(c+di) = (ac−bd) + (ad+bc)i - const { c0: r0, c1: r1 } = rhs - let t1 = Fp.mul(c0, r0) // c0 * o0 - let t2 = Fp.mul(c1, r1) // c1 * o1 - // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i - const o0 = Fp.sub(t1, t2) - const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) - return { c0: o0, c1: o1 } - } - const Fp2Square = ({ c0, c1 }) => { - const a = Fp.add(c0, c1) - const b = Fp.sub(c0, c1) - const c = Fp.add(c0, c0) - return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } - } - const Fp2fromBigTuple = (tuple) => { - if (tuple.length !== 2) throw new Error('invalid tuple') - const fps = tuple.map((n) => Fp.create(n)) - return { c0: fps[0], c1: fps[1] } - } - const FP2_ORDER = ORDER * ORDER - const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) - const Fp2 = { - ORDER: FP2_ORDER, - isLE: Fp.isLE, - NONRESIDUE: Fp2Nonresidue, - BITS: (0, utils_js_1.bitLen)(FP2_ORDER), - BYTES: Math.ceil((0, utils_js_1.bitLen)(FP2_ORDER) / 8), - MASK: (0, utils_js_1.bitMask)((0, utils_js_1.bitLen)(FP2_ORDER)), - ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, - ONE: { c0: Fp.ONE, c1: Fp.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', - is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1), - neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), - pow: (num, power) => mod.FpPow(Fp2, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), - // Normalized - add: Fp2Add, - sub: Fp2Subtract, - mul: Fp2Multiply, - sqr: Fp2Square, - // NonNormalized stuff - addN: Fp2Add, - subN: Fp2Subtract, - mulN: Fp2Multiply, - sqrN: Fp2Square, - // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? - div: (lhs, rhs) => - Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), - inv: ({ c0: a, c1: b }) => { - // We wish to find the multiplicative inverse of a nonzero - // element a + bu in Fp2. We leverage an identity - // - // (a + bu)(a - bu) = a² + b² - // - // which holds because u² = -1. This can be rewritten as - // - // (a + bu)(a - bu)/(a² + b²) = 1 - // - // because a² + b² = 0 has no nonzero solutions for (a, b). - // This gives that (a - bu)/(a² + b²) is the inverse - // of (a + bu). Importantly, this can be computing using - // only a single inversion in Fp. - const factor = Fp.inv(Fp.create(a * a + b * b)) - return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } - }, - sqrt: (num) => { - if (opts.Fp2sqrt) return opts.Fp2sqrt(num) - // This is generic for all quadratic extensions (Fp2) - const { c0, c1 } = num - if (Fp.is0(c1)) { - // if c0 is quadratic residue - if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) - else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) - } - const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) - let d = Fp.mul(Fp.add(a, c0), Fpdiv2) - const legendre = FpLegendre(Fp, d) - // -1, Quadratic non residue - if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) - const a0 = Fp.sqrt(d) - const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) - if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') - // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num - const x1 = candidateSqrt - const x2 = Fp2.neg(x1) - const { re: re1, im: im1 } = Fp2.reim(x1) - const { re: re2, im: im2 } = Fp2.reim(x2) - if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 - return x2 - }, - // Same as sgn0_m_eq_2 in RFC 9380 - isOdd: (x) => { - const { re: x0, im: x1 } = Fp2.reim(x) - const sign_0 = x0 % _2n - const zero_0 = x0 === _0n - const sign_1 = x1 % _2n - return BigInt(sign_0 || (zero_0 && sign_1)) == _1n - }, - // Bytes util - fromBytes(b) { - if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } - }, - toBytes: ({ c0, c1 }) => (0, utils_js_1.concatBytes)(Fp.toBytes(c0), Fp.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp.cmov(c0, r0, c), - c1: Fp.cmov(c1, r1, c), - }), - reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), - // multiply by u + 1 - mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), - mulByB: opts.Fp2mulByB, - fromBigTuple: Fp2fromBigTuple, - frobeniusMap: ({ c0, c1 }, power) => ({ - c0, - c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), - }), - } - // Fp6 - const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ - c0: Fp2.add(c0, r0), - c1: Fp2.add(c1, r1), - c2: Fp2.add(c2, r2), - }) - const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ - c0: Fp2.sub(c0, r0), - c1: Fp2.sub(c1, r1), - c2: Fp2.sub(c2, r2), - }) - const Fp6Multiply = ({ c0, c1, c2 }, rhs) => { - if (typeof rhs === 'bigint') { - return { - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - } - } - const { c0: r0, c1: r1, c2: r2 } = rhs - const t0 = Fp2.mul(c0, r0) // c0 * o0 - const t1 = Fp2.mul(c1, r1) // c1 * o1 - const t2 = Fp2.mul(c2, r2) // c2 * o2 - return { - // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) - c0: Fp2.add( - t0, - Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), - ), - // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) - c1: Fp2.add( - Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), - Fp2.mulByNonresidue(t2), - ), - // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 - c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), - } - } - const Fp6Square = ({ c0, c1, c2 }) => { - let t0 = Fp2.sqr(c0) // c0² - let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 - let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 - let t4 = Fp2.sqr(c2) // c2² - return { - c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 - c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 - // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 - c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), - } - } - const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 6, - 2, - 3, - ) - const Fp6 = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp2.isLE, - BITS: 3 * Fp2.BITS, - BYTES: 3 * Fp2.BYTES, - MASK: (0, utils_js_1.bitMask)(3 * Fp2.BITS), - ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, - ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, - create: (num) => num, - isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), - is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), - neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), - eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => - Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), - sqrt: utils_js_1.notImplemented, - // Do we need division by bigint at all? Should be done via order: - div: (lhs, rhs) => - Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp6, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), - // Normalized - add: Fp6Add, - sub: Fp6Subtract, - mul: Fp6Multiply, - sqr: Fp6Square, - // NonNormalized stuff - addN: Fp6Add, - subN: Fp6Subtract, - mulN: Fp6Multiply, - sqrN: Fp6Square, - inv: ({ c0, c1, c2 }) => { - let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) - let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 - let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 - // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) - let t4 = Fp2.inv( - Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), - ) - return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } - }, - // Bytes utils - fromBytes: (b) => { - if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), - c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), - c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), - } - }, - toBytes: ({ c0, c1, c2 }) => - (0, utils_js_1.concatBytes)(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), - cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({ - c0: Fp2.cmov(c0, r0, c), - c1: Fp2.cmov(c1, r1, c), - c2: Fp2.cmov(c2, r2, c), - }), - fromBigSix: (t) => { - if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') - return { - c0: Fp2.fromBigTuple(t.slice(0, 2)), - c1: Fp2.fromBigTuple(t.slice(2, 4)), - c2: Fp2.fromBigTuple(t.slice(4, 6)), - } - }, - frobeniusMap: ({ c0, c1, c2 }, power) => ({ - c0: Fp2.frobeniusMap(c0, power), - c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), - c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), - }), - mulByFp2: ({ c0, c1, c2 }, rhs) => ({ - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - }), - mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), - // Sparse multiplication - mul1: ({ c0, c1, c2 }, b1) => ({ - c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), - c1: Fp2.mul(c0, b1), - c2: Fp2.mul(c1, b1), - }), - // Sparse multiplication - mul01({ c0, c1, c2 }, b0, b1) { - let t0 = Fp2.mul(c0, b0) // c0 * b0 - let t1 = Fp2.mul(c1, b1) // c1 * b1 - return { - // ((c1 + c2) * b1 - T1) * (u + 1) + T0 - c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), - // (b0 + b1) * (c0 + c1) - T0 - T1 - c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), - // (c0 + c2) * b0 - T0 + T1 - c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), - } - }, - } - // Fp12 - const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 12, - 1, - 6, - )[0] - const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp6.add(c0, r0), - c1: Fp6.add(c1, r1), - }) - const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp6.sub(c0, r0), - c1: Fp6.sub(c1, r1), - }) - const Fp12Multiply = ({ c0, c1 }, rhs) => { - if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } - let { c0: r0, c1: r1 } = rhs - let t1 = Fp6.mul(c0, r0) // c0 * r0 - let t2 = Fp6.mul(c1, r1) // c1 * r1 - return { - c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v - // (c0 + c1) * (r0 + r1) - (T1 + T2) - c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), - } - } - const Fp12Square = ({ c0, c1 }) => { - let ab = Fp6.mul(c0, c1) // c0 * c1 - return { - // (c1 * v + c0) * (c0 + c1) - AB - AB * v - c0: Fp6.sub( - Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), - Fp6.mulByNonresidue(ab), - ), - c1: Fp6.add(ab, ab), - } // AB + AB - } - function Fp4Square(a, b) { - const a2 = Fp2.sqr(a) - const b2 = Fp2.sqr(b) - return { - first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² - second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² - } - } - const Fp12 = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp6.isLE, - BITS: 2 * Fp2.BITS, - BYTES: 2 * Fp2.BYTES, - MASK: (0, utils_js_1.bitMask)(2 * Fp2.BITS), - ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, - ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), - is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), - neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), - sqrt: utils_js_1.notImplemented, - inv: ({ c0, c1 }) => { - let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) - return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w - }, - div: (lhs, rhs) => - Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp12, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), - // Normalized - add: Fp12Add, - sub: Fp12Subtract, - mul: Fp12Multiply, - sqr: Fp12Square, - // NonNormalized stuff - addN: Fp12Add, - subN: Fp12Subtract, - mulN: Fp12Multiply, - sqrN: Fp12Square, - // Bytes utils - fromBytes: (b) => { - if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), - c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), - } - }, - toBytes: ({ c0, c1 }) => (0, utils_js_1.concatBytes)(Fp6.toBytes(c0), Fp6.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp6.cmov(c0, r0, c), - c1: Fp6.cmov(c1, r1, c), - }), - // Utils - // toString() { - // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); - // }, - // fromTuple(c: [Fp6, Fp6]) { - // return new Fp12(...c); - // } - fromBigTwelve: (t) => ({ - c0: Fp6.fromBigSix(t.slice(0, 6)), - c1: Fp6.fromBigSix(t.slice(6, 12)), - }), - // Raises to q**i -th power - frobeniusMap(lhs, power) { - const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) - const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] - return { - c0: Fp6.frobeniusMap(lhs.c0, power), - c1: Fp6.create({ - c0: Fp2.mul(c0, coeff), - c1: Fp2.mul(c1, coeff), - c2: Fp2.mul(c2, coeff), - }), - } - }, - mulByFp2: ({ c0, c1 }, rhs) => ({ - c0: Fp6.mulByFp2(c0, rhs), - c1: Fp6.mulByFp2(c1, rhs), - }), - conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }), - // Sparse multiplication - mul014: ({ c0, c1 }, o0, o1, o4) => { - let t0 = Fp6.mul01(c0, o0, o1) - let t1 = Fp6.mul1(c1, o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 - // (c1 + c0) * [o0, o1+o4] - T0 - T1 - c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), - } - }, - mul034: ({ c0, c1 }, o0, o3, o4) => { - const a = Fp6.create({ - c0: Fp2.mul(c0.c0, o0), - c1: Fp2.mul(c0.c1, o0), - c2: Fp2.mul(c0.c2, o0), - }) - const b = Fp6.mul01(c1, o3, o4) - const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(b), a), - c1: Fp6.sub(e, Fp6.add(a, b)), - } - }, - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - _cyclotomicSquare: opts.Fp12cyclotomicSquare, - _cyclotomicExp: opts.Fp12cyclotomicExp, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - finalExponentiate: opts.Fp12finalExponentiate, - } - return { Fp, Fp2, Fp6, Fp4Square, Fp12 } -} -//# sourceMappingURL=tower.js.map diff --git a/packages/noble-curves/abstract/tower.js.map b/packages/noble-curves/abstract/tower.js.map deleted file mode 100644 index d148f00a2a9..00000000000 --- a/packages/noble-curves/abstract/tower.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"tower.js","sourceRoot":"","sources":["../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/utils.d.ts b/packages/noble-curves/abstract/utils.d.ts deleted file mode 100644 index 405e6bef69d..00000000000 --- a/packages/noble-curves/abstract/utils.d.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -export type Hex = Uint8Array | string -export type PrivKey = Hex | bigint -export type CHash = { - (message: Uint8Array | string): Uint8Array - blockLen: number - outputLen: number - create(opts?: { - dkLen?: number - }): any -} -export type FHash = (message: Uint8Array | string) => Uint8Array -export declare function isBytes(a: unknown): a is Uint8Array -export declare function abytes(item: unknown): void -export declare function abool(title: string, value: boolean): void -/** - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -export declare function bytesToHex(bytes: Uint8Array): string -export declare function numberToHexUnpadded(num: number | bigint): string -export declare function hexToNumber(hex: string): bigint -/** - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -export declare function hexToBytes(hex: string): Uint8Array -export declare function bytesToNumberBE(bytes: Uint8Array): bigint -export declare function bytesToNumberLE(bytes: Uint8Array): bigint -export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array -export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array -export declare function numberToVarBytesBE(n: number | bigint): Uint8Array -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -export declare function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array -/** - * Copies several Uint8Arrays into one. - */ -export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array -export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -export declare function utf8ToBytes(str: string): Uint8Array -export declare function inRange(n: bigint, min: bigint, max: bigint): boolean -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -export declare function aInRange(title: string, n: bigint, min: bigint, max: bigint): void -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -export declare function bitLen(n: bigint): number -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -export declare function bitGet(n: bigint, pos: number): bigint -/** - * Sets single bit at position. - */ -export declare function bitSet(n: bigint, pos: number, value: boolean): bigint -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -export declare const bitMask: (n: number) => bigint -type Pred = (v: Uint8Array) => T | undefined -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -export declare function createHmacDrbg( - hashLen: number, - qByteLen: number, - hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, -): (seed: Uint8Array, predicate: Pred) => T -declare const validatorFns: { - readonly bigint: (val: any) => boolean - readonly function: (val: any) => boolean - readonly boolean: (val: any) => boolean - readonly string: (val: any) => boolean - readonly stringOrUint8Array: (val: any) => boolean - readonly isSafeInteger: (val: any) => boolean - readonly array: (val: any) => boolean - readonly field: (val: any, object: any) => any - readonly hash: (val: any) => boolean -} -type Validator = keyof typeof validatorFns -type ValMap> = { - [K in keyof T]?: Validator -} -export declare function validateObject>( - object: T, - validators: ValMap, - optValidators?: ValMap, -): T -/** - * throws not implemented error - */ -export declare const notImplemented: () => never -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -export declare function memoized( - fn: (arg: T, ...args: O) => R, -): (arg: T, ...args: O) => R -export {} -//# sourceMappingURL=utils.d.ts.map diff --git a/packages/noble-curves/abstract/utils.d.ts.map b/packages/noble-curves/abstract/utils.d.ts.map deleted file mode 100644 index 350f5c0e2f0..00000000000 --- a/packages/noble-curves/abstract/utils.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/abstract/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AAStE,MAAM,MAAM,GAAG,GAAG,UAAU,GAAG,MAAM,CAAC;AACtC,MAAM,MAAM,OAAO,GAAG,GAAG,GAAG,MAAM,CAAC;AACnC,MAAM,MAAM,KAAK,GAAG;IAClB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,UAAU,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,GAAG,CAAC;CACxC,CAAC;AACF,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,KAAK,UAAU,CAAC;AAEjE,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,UAAU,CAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE1C;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAEzD;AAMD;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQpD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C;AAWD;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAgBlD;AAGD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEzD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGzD;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAE3E;AACD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAE3E;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAEjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,CAmBxF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,CAc/D;AAGD,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAKhE;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAGnD;AAKD,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAQjF;AAID;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxC;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,MAAO,MAAM,KAAG,MAAsC,CAAC;AAM3E,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,KAAK,CAAC,GAAG,SAAS,CAAC;AAChD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,KAAK,UAAU,GACjE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CA4C7C;AAID,QAAA,MAAM,YAAY;2BACF,GAAG,KAAG,OAAO;6BACX,GAAG,KAAG,OAAO;4BACd,GAAG,KAAG,OAAO;2BACd,GAAG,KAAG,OAAO;uCACD,GAAG,KAAG,OAAO;kCAClB,GAAG,KAAG,OAAO;0BACrB,GAAG,KAAG,OAAO;0BACb,GAAG,UAAU,GAAG,KAAG,GAAG;yBACvB,GAAG,KAAG,OAAO;CACjB,CAAC;AACX,KAAK,SAAS,GAAG,MAAM,OAAO,YAAY,CAAC;AAC3C,KAAK,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS;CAAE,CAAC;AAG5E,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1D,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EACrB,aAAa,GAAE,MAAM,CAAC,CAAC,CAAM,GAC5B,CAAC,CAgBH;AAUD;;GAEG;AACH,eAAO,MAAM,cAAc,QAAO,KAEjC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAC3D,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,GAC5B,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAS3B"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/utils.js b/packages/noble-curves/abstract/utils.js deleted file mode 100644 index 20607d42562..00000000000 --- a/packages/noble-curves/abstract/utils.js +++ /dev/null @@ -1,340 +0,0 @@ -'use strict' -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -Object.defineProperty(exports, '__esModule', { value: true }) -exports.notImplemented = exports.bitMask = void 0 -exports.isBytes = isBytes -exports.abytes = abytes -exports.abool = abool -exports.bytesToHex = bytesToHex -exports.numberToHexUnpadded = numberToHexUnpadded -exports.hexToNumber = hexToNumber -exports.hexToBytes = hexToBytes -exports.bytesToNumberBE = bytesToNumberBE -exports.bytesToNumberLE = bytesToNumberLE -exports.numberToBytesBE = numberToBytesBE -exports.numberToBytesLE = numberToBytesLE -exports.numberToVarBytesBE = numberToVarBytesBE -exports.ensureBytes = ensureBytes -exports.concatBytes = concatBytes -exports.equalBytes = equalBytes -exports.utf8ToBytes = utf8ToBytes -exports.inRange = inRange -exports.aInRange = aInRange -exports.bitLen = bitLen -exports.bitGet = bitGet -exports.bitSet = bitSet -exports.createHmacDrbg = createHmacDrbg -exports.validateObject = validateObject -exports.memoized = memoized -// 100 lines of code in the file are duplicated from noble-hashes (utils). -// This is OK: `abstract` directory does not use noble-hashes. -// User may opt-in into using different hashing library. This way, noble-hashes -// won't be included into their bundle. -const _0n = /* @__PURE__ */ BigInt(0) -const _1n = /* @__PURE__ */ BigInt(1) -const _2n = /* @__PURE__ */ BigInt(2) -function isBytes(a) { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') -} -function abytes(item) { - if (!isBytes(item)) throw new Error('Uint8Array expected') -} -function abool(title, value) { - if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) -} -// Array where index 0xf0 (240) is mapped to string 'f0' -const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) -/** - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -function bytesToHex(bytes) { - abytes(bytes) - // pre-caching improves the speed 6x - let hex = '' - for (let i = 0; i < bytes.length; i++) { - hex += hexes[bytes[i]] - } - return hex -} -function numberToHexUnpadded(num) { - const hex = num.toString(16) - return hex.length & 1 ? '0' + hex : hex -} -function hexToNumber(hex) { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian -} -// We use optimized technique to convert hex string to byte array -const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } -function asciiToBase16(ch) { - if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 - if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) - if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) - return -} -/** - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -function hexToBytes(hex) { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - const hl = hex.length - const al = hl / 2 - if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) - const array = new Uint8Array(al) - for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { - const n1 = asciiToBase16(hex.charCodeAt(hi)) - const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) - if (n1 === undefined || n2 === undefined) { - const char = hex[hi] + hex[hi + 1] - throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) - } - array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 - } - return array -} -// BE: Big Endian, LE: Little Endian -function bytesToNumberBE(bytes) { - return hexToNumber(bytesToHex(bytes)) -} -function bytesToNumberLE(bytes) { - abytes(bytes) - return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) -} -function numberToBytesBE(n, len) { - return hexToBytes(n.toString(16).padStart(len * 2, '0')) -} -function numberToBytesLE(n, len) { - return numberToBytesBE(n, len).reverse() -} -// Unpadded, rarely used -function numberToVarBytesBE(n) { - return hexToBytes(numberToHexUnpadded(n)) -} -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -function ensureBytes(title, hex, expectedLength) { - let res - if (typeof hex === 'string') { - try { - res = hexToBytes(hex) - } catch (e) { - throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) - } - } else if (isBytes(hex)) { - // Uint8Array.from() instead of hash.slice() because node.js Buffer - // is instance of Uint8Array, and its slice() creates **mutable** copy - res = Uint8Array.from(hex) - } else { - throw new Error(title + ' must be hex string or Uint8Array') - } - const len = res.length - if (typeof expectedLength === 'number' && len !== expectedLength) - throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) - return res -} -/** - * Copies several Uint8Arrays into one. - */ -function concatBytes(...arrays) { - let sum = 0 - for (let i = 0; i < arrays.length; i++) { - const a = arrays[i] - abytes(a) - sum += a.length - } - const res = new Uint8Array(sum) - for (let i = 0, pad = 0; i < arrays.length; i++) { - const a = arrays[i] - res.set(a, pad) - pad += a.length - } - return res -} -// Compares 2 u8a-s in kinda constant time -function equalBytes(a, b) { - if (a.length !== b.length) return false - let diff = 0 - for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] - return diff === 0 -} -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -function utf8ToBytes(str) { - if (typeof str !== 'string') throw new Error('string expected') - return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 -} -// Is positive bigint -const isPosBig = (n) => typeof n === 'bigint' && _0n <= n -function inRange(n, min, max) { - return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max -} -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -function aInRange(title, n, min, max) { - // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? - // consider P=256n, min=0n, max=P - // - a for min=0 would require -1: `inRange('x', x, -1n, P)` - // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` - // - our way is the cleanest: `inRange('x', x, 0n, P) - if (!inRange(n, min, max)) - throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) -} -// Bit operations -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -function bitLen(n) { - let len - for (len = 0; n > _0n; n >>= _1n, len += 1); - return len -} -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -function bitGet(n, pos) { - return (n >> BigInt(pos)) & _1n -} -/** - * Sets single bit at position. - */ -function bitSet(n, pos, value) { - return n | ((value ? _1n : _0n) << BigInt(pos)) -} -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n -exports.bitMask = bitMask -// DRBG -const u8n = (data) => new Uint8Array(data) // creates Uint8Array -const u8fr = (arr) => Uint8Array.from(arr) // another shortcut -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -function createHmacDrbg(hashLen, qByteLen, hmacFn) { - if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') - if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') - if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') - // Step B, Step C: set hashLen to 8*ceil(hlen/8) - let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same - let i = 0 // Iterations counter, will throw when over 1000 - const reset = () => { - v.fill(1) - k.fill(0) - i = 0 - } - const h = (...b) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) - const reseed = (seed = u8n()) => { - // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) - v = h() // v = hmac(k || v) - if (seed.length === 0) return - k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) - v = h() // v = hmac(k || v) - } - const gen = () => { - // HMAC-DRBG generate() function - if (i++ >= 1000) throw new Error('drbg: tried 1000 values') - let len = 0 - const out = [] - while (len < qByteLen) { - v = h() - const sl = v.slice() - out.push(sl) - len += v.length - } - return concatBytes(...out) - } - const genUntil = (seed, pred) => { - reset() - reseed(seed) // Steps D-G - let res = undefined // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed() - reset() - return res - } - return genUntil -} -// Validating curves and fields -const validatorFns = { - bigint: (val) => typeof val === 'bigint', - function: (val) => typeof val === 'function', - boolean: (val) => typeof val === 'boolean', - string: (val) => typeof val === 'string', - stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val), - isSafeInteger: (val) => Number.isSafeInteger(val), - array: (val) => Array.isArray(val), - field: (val, object) => object.Fp.isValid(val), - hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen), -} -// type Record = { [P in K]: T; } -function validateObject(object, validators, optValidators = {}) { - const checkField = (fieldName, type, isOptional) => { - const checkVal = validatorFns[type] - if (typeof checkVal !== 'function') throw new Error('invalid validator function') - const val = object[fieldName] - if (isOptional && val === undefined) return - if (!checkVal(val, object)) { - throw new Error( - 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, - ) - } - } - for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false) - for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true) - return object -} -// validate type tests -// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; -// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! -// // Should fail type-check -// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); -// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); -// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); -// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); -/** - * throws not implemented error - */ -const notImplemented = () => { - throw new Error('not implemented') -} -exports.notImplemented = notImplemented -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -function memoized(fn) { - const map = new WeakMap() - return (arg, ...args) => { - const val = map.get(arg) - if (val !== undefined) return val - const computed = fn(arg, ...args) - map.set(arg, computed) - return computed - } -} -//# sourceMappingURL=utils.js.map diff --git a/packages/noble-curves/abstract/utils.js.map b/packages/noble-curves/abstract/utils.js.map deleted file mode 100644 index 6f9fc1c881b..00000000000 --- a/packages/noble-curves/abstract/utils.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/weierstrass.d.ts b/packages/noble-curves/abstract/weierstrass.d.ts deleted file mode 100644 index f79b0c73b8e..00000000000 --- a/packages/noble-curves/abstract/weierstrass.d.ts +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' -import { type IField } from './modular.js' -import { type CHash, type Hex, type PrivKey } from './utils.js' -export type { AffinePoint } -type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array -type EndomorphismOpts = { - beta: bigint - splitScalar: (k: bigint) => { - k1neg: boolean - k1: bigint - k2neg: boolean - k2: bigint - } -} -export type BasicWCurve = BasicCurve & { - a: T - b: T - allowedPrivateKeyLengths?: readonly number[] - wrapPrivateKey?: boolean - endo?: EndomorphismOpts - isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean - clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType -} -type Entropy = Hex | boolean -export type SignOpts = { - lowS?: boolean - extraEntropy?: Entropy - prehash?: boolean -} -export type VerOpts = { - lowS?: boolean - prehash?: boolean - format?: 'compact' | 'der' | undefined -} -export interface ProjPointType extends Group> { - readonly px: T - readonly py: T - readonly pz: T - get x(): T - get y(): T - multiply(scalar: bigint): ProjPointType - toAffine(iz?: T): AffinePoint - isTorsionFree(): boolean - clearCofactor(): ProjPointType - assertValidity(): void - hasEvenY(): boolean - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - multiplyUnsafe(scalar: bigint): ProjPointType - multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined - _setWindowSize(windowSize: number): void -} -export interface ProjConstructor extends GroupConstructor> { - new (x: T, y: T, z: T): ProjPointType - fromAffine(p: AffinePoint): ProjPointType - fromHex(hex: Hex): ProjPointType - fromPrivateKey(privateKey: PrivKey): ProjPointType - normalizeZ(points: ProjPointType[]): ProjPointType[] - msm(points: ProjPointType[], scalars: bigint[]): ProjPointType -} -export type CurvePointsType = BasicWCurve & { - fromBytes?: (bytes: Uint8Array) => AffinePoint - toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array -} -export type CurvePointsTypeWithLength = Readonly< - CurvePointsType & { - nByteLength: number - nBitLength: number - } -> -declare function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength -export type CurvePointsRes = { - CURVE: ReturnType> - ProjectivePoint: ProjConstructor - normPrivateKeyToScalar: (key: PrivKey) => bigint - weierstrassEquation: (x: T) => T - isWithinCurveOrder: (num: bigint) => boolean -} -export declare class DERErr extends Error { - constructor(m?: string) -} -export type IDER = { - Err: typeof DERErr - _tlv: { - encode: (tag: number, data: string) => string - decode( - tag: number, - data: Uint8Array, - ): { - v: Uint8Array - l: Uint8Array - } - } - _int: { - encode(num: bigint): string - decode(data: Uint8Array): bigint - } - toSig(hex: string | Uint8Array): { - r: bigint - s: bigint - } - hexFromSig(sig: { - r: bigint - s: bigint - }): string -} -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -export declare const DER: IDER -export declare function weierstrassPoints(opts: CurvePointsType): CurvePointsRes -export interface SignatureType { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - assertValidity(): void - addRecoveryBit(recovery: number): RecoveredSignatureType - hasHighS(): boolean - normalizeS(): SignatureType - recoverPublicKey(msgHash: Hex): ProjPointType - toCompactRawBytes(): Uint8Array - toCompactHex(): string - toDERRawBytes(isCompressed?: boolean): Uint8Array - toDERHex(isCompressed?: boolean): string -} -export type RecoveredSignatureType = SignatureType & { - readonly recovery: number -} -export type SignatureConstructor = { - new (r: bigint, s: bigint): SignatureType - fromCompact(hex: Hex): SignatureType - fromDER(hex: Hex): SignatureType -} -type SignatureLike = { - r: bigint - s: bigint -} -export type PubKey = Hex | ProjPointType -export type CurveType = BasicWCurve & { - hash: CHash - hmac: HmacFnSync - randomBytes: (bytesLength?: number) => Uint8Array - lowS?: boolean - bits2int?: (bytes: Uint8Array) => bigint - bits2int_modN?: (bytes: Uint8Array) => bigint -} -declare function validateOpts(curve: CurveType): Readonly< - CurveType & { - nByteLength: number - nBitLength: number - } -> -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array - getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array - sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType - verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean - ProjectivePoint: ProjConstructor - Signature: SignatureConstructor - utils: { - normPrivateKeyToScalar: (key: PrivKey) => bigint - isValidPrivateKey(privateKey: PrivKey): boolean - randomPrivateKey: () => Uint8Array - precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType - } -} -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -export declare function weierstrass(curveDef: CurveType): CurveFn -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -export declare function SWUFpSqrtRatio( - Fp: IField, - Z: T, -): ( - u: T, - v: T, -) => { - isValid: boolean - value: T -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -export declare function mapToCurveSimpleSWU( - Fp: IField, - opts: { - A: T - B: T - Z: T - }, -): (u: T) => { - x: T - y: T -} -//# sourceMappingURL=weierstrass.d.ts.map diff --git a/packages/noble-curves/abstract/weierstrass.d.ts.map b/packages/noble-curves/abstract/weierstrass.d.ts.map deleted file mode 100644 index 8bf023e0581..00000000000 --- a/packages/noble-curves/abstract/weierstrass.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"weierstrass.d.ts","sourceRoot":"","sources":["../src/abstract/weierstrass.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/abstract/weierstrass.js b/packages/noble-curves/abstract/weierstrass.js deleted file mode 100644 index e7b0342dc1f..00000000000 --- a/packages/noble-curves/abstract/weierstrass.js +++ /dev/null @@ -1,1139 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.DER = exports.DERErr = void 0 -exports.weierstrassPoints = weierstrassPoints -exports.weierstrass = weierstrass -exports.SWUFpSqrtRatio = SWUFpSqrtRatio -exports.mapToCurveSimpleSWU = mapToCurveSimpleSWU -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const curve_js_1 = require('./curve.js') -const modular_js_1 = require('./modular.js') -const ut = require('./utils.js') -const utils_js_1 = require('./utils.js') -function validateSigVerOpts(opts) { - if (opts.lowS !== undefined) (0, utils_js_1.abool)('lowS', opts.lowS) - if (opts.prehash !== undefined) (0, utils_js_1.abool)('prehash', opts.prehash) -} -function validatePointOpts(curve) { - const opts = (0, curve_js_1.validateBasic)(curve) - ut.validateObject( - opts, - { - a: 'field', - b: 'field', - }, - { - allowedPrivateKeyLengths: 'array', - wrapPrivateKey: 'boolean', - isTorsionFree: 'function', - clearCofactor: 'function', - allowInfinityPoint: 'boolean', - fromBytes: 'function', - toBytes: 'function', - }, - ) - const { endo, Fp, a } = opts - if (endo) { - if (!Fp.eql(a, Fp.ZERO)) { - throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') - } - if ( - typeof endo !== 'object' || - typeof endo.beta !== 'bigint' || - typeof endo.splitScalar !== 'function' - ) { - throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') - } - } - return Object.freeze({ ...opts }) -} -const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut -class DERErr extends Error { - constructor(m = '') { - super(m) - } -} -exports.DERErr = DERErr -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -exports.DER = { - // asn.1 DER encoding utils - Err: DERErr, - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag, data) => { - const { Err: E } = exports.DER - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length & 1) throw new E('tlv.encode: unpadded data') - const dataLen = data.length / 2 - const len = ut.numberToHexUnpadded(dataLen) - if ((len.length / 2) & 128) throw new E('tlv.encode: long form length too big') - // length of length with long form flag - const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 128) : '' - const t = ut.numberToHexUnpadded(tag) - return t + lenLen + len + data - }, - // v - value, l - left bytes (unparsed) - decode(tag, data) { - const { Err: E } = exports.DER - let pos = 0 - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') - const first = data[pos++] - const isLong = !!(first & 128) // First bit of first length byte is flag for short/long form - let length = 0 - if (!isLong) length = first - else { - // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] - const lenLen = first & 127 - if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') - if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js - const lengthBytes = data.subarray(pos, pos + lenLen) - if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') - if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') - for (const b of lengthBytes) length = (length << 8) | b - pos += lenLen - if (length < 128) throw new E('tlv.decode(long): not minimal encoding') - } - const v = data.subarray(pos, pos + length) - if (v.length !== length) throw new E('tlv.decode: wrong value length') - return { v, l: data.subarray(pos + length) } - }, - }, - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num) { - const { Err: E } = exports.DER - if (num < _0n) throw new E('integer: negative integers are not allowed') - let hex = ut.numberToHexUnpadded(num) - // Pad with zero byte if negative flag is present - if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex - if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') - return hex - }, - decode(data) { - const { Err: E } = exports.DER - if (data[0] & 128) throw new E('invalid signature integer: negative') - if (data[0] === 0x00 && !(data[1] & 128)) - throw new E('invalid signature integer: unnecessary leading zero') - return b2n(data) - }, - }, - toSig(hex) { - // parse DER signature - const { Err: E, _int: int, _tlv: tlv } = exports.DER - const data = typeof hex === 'string' ? h2b(hex) : hex - ut.abytes(data) - const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) - if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) - const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) - if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - return { r: int.decode(rBytes), s: int.decode(sBytes) } - }, - hexFromSig(sig) { - const { _tlv: tlv, _int: int } = exports.DER - const rs = tlv.encode(0x02, int.encode(sig.r)) - const ss = tlv.encode(0x02, int.encode(sig.s)) - const seq = rs + ss - return tlv.encode(0x30, seq) - }, -} -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) -function weierstrassPoints(opts) { - const CURVE = validatePointOpts(opts) - const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ - const Fn = (0, modular_js_1.Field)(CURVE.n, CURVE.nBitLength) - const toBytes = - CURVE.toBytes || - ((_c, point, _isCompressed) => { - const a = point.toAffine() - return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) - }) - const fromBytes = - CURVE.fromBytes || - ((bytes) => { - // const head = bytes[0]; - const tail = bytes.subarray(1) - // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - }) - /** - * y² = x³ + ax + b: Short weierstrass curve formula - * @returns y² - */ - function weierstrassEquation(x) { - const { a, b } = CURVE - const x2 = Fp.sqr(x) // x * x - const x3 = Fp.mul(x2, x) // x2 * x - return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b - } - // Validate whether the passed curve params are valid. - // We check if curve equation works for generator point. - // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. - // ProjectivePoint class has not been initialized yet. - if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) - throw new Error('bad generator point: equation left != right') - // Valid group elements reside in range 1..n-1 - function isWithinCurveOrder(num) { - return ut.inRange(num, _1n, CURVE.n) - } - // Validates if priv key is valid and converts it to bigint. - // Supports options allowedPrivateKeyLengths and wrapPrivateKey. - function normPrivateKeyToScalar(key) { - const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE - if (lengths && typeof key !== 'bigint') { - if (ut.isBytes(key)) key = ut.bytesToHex(key) - // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes - if (typeof key !== 'string' || !lengths.includes(key.length)) - throw new Error('invalid private key') - key = key.padStart(nByteLength * 2, '0') - } - let num - try { - num = - typeof key === 'bigint' - ? key - : ut.bytesToNumberBE((0, utils_js_1.ensureBytes)('private key', key, nByteLength)) - } catch (error) { - throw new Error( - 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, - ) - } - if (wrapPrivateKey) num = (0, modular_js_1.mod)(num, N) // disabled by default, enabled for BLS - ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] - return num - } - function assertPrjPoint(other) { - if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') - } - // Memoized toAffine / validity check. They are heavy. Points are immutable. - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - const toAffineMemo = (0, utils_js_1.memoized)((p, iz) => { - const { px: x, py: y, pz: z } = p - // Fast-path for normalized points - if (Fp.eql(z, Fp.ONE)) return { x, y } - const is0 = p.is0() - // If invZ was 0, we return zero point. However we still want to execute - // all operations, so we replace invZ with a random number, 1. - if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) - const ax = Fp.mul(x, iz) - const ay = Fp.mul(y, iz) - const zz = Fp.mul(z, iz) - if (is0) return { x: Fp.ZERO, y: Fp.ZERO } - if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - // NOTE: on exception this will crash 'cached' and no value will be set. - // Otherwise true will be return - const assertValidMemo = (0, utils_js_1.memoized)((p) => { - if (p.is0()) { - // (0, 1, 0) aka ZERO is invalid in most contexts. - // In BLS, ZERO can be serialized, so we allow it. - // (0, 0, 0) is invalid representation of ZERO. - if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return - throw new Error('bad point: ZERO') - } - // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` - const { x, y } = p.toAffine() - // Check if x, y are valid field elements - if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') - const left = Fp.sqr(y) // y² - const right = weierstrassEquation(x) // x³ + ax + b - if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') - if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') - return true - }) - /** - * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) - * Default Point works in 2d / affine coordinates: (x, y) - * We're doing calculations in projective, because its operations don't require costly inversion. - */ - class Point { - constructor(px, py, pz) { - this.px = px - this.py = py - this.pz = pz - if (px == null || !Fp.isValid(px)) throw new Error('x required') - if (py == null || !Fp.isValid(py)) throw new Error('y required') - if (pz == null || !Fp.isValid(pz)) throw new Error('z required') - Object.freeze(this) - } - // Does not validate if the point is on-curve. - // Use fromHex instead, or call assertValidity() later. - static fromAffine(p) { - const { x, y } = p || {} - if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') - if (p instanceof Point) throw new Error('projective point not allowed') - const is0 = (i) => Fp.eql(i, Fp.ZERO) - // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) - if (is0(x) && is0(y)) return Point.ZERO - return new Point(x, y, Fp.ONE) - } - get x() { - return this.toAffine().x - } - get y() { - return this.toAffine().y - } - /** - * Takes a bunch of Projective Points but executes only one - * inversion on all of them. Inversion is very slow operation, - * so this improves performance massively. - * Optimization: converts a list of projective points to a list of identical points with Z=1. - */ - static normalizeZ(points) { - const toInv = Fp.invertBatch(points.map((p) => p.pz)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - /** - * Converts hash string or Uint8Array to Point. - * @param hex short/long ECDSA hex - */ - static fromHex(hex) { - const P = Point.fromAffine(fromBytes((0, utils_js_1.ensureBytes)('pointHex', hex))) - P.assertValidity() - return P - } - // Multiplies generator point by privateKey. - static fromPrivateKey(privateKey) { - return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) - } - // Multiscalar Multiplication - static msm(points, scalars) { - return (0, curve_js_1.pippenger)(Point, Fn, points, scalars) - } - // "Private method", don't use it directly - _setWindowSize(windowSize) { - wnaf.setWindowSize(this, windowSize) - } - // A point on curve is valid if it conforms to equation. - assertValidity() { - assertValidMemo(this) - } - hasEvenY() { - const { y } = this.toAffine() - if (Fp.isOdd) return !Fp.isOdd(y) - throw new Error("Field doesn't support isOdd") - } - /** - * Compare one point to another. - */ - equals(other) { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) - const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) - return U1 && U2 - } - /** - * Flips point to one corresponding to (x, -y) in Affine coordinates. - */ - negate() { - return new Point(this.px, Fp.neg(this.py), this.pz) - } - // Renes-Costello-Batina exception-free doubling formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 3 - // Cost: 8M + 3S + 3*a + 2*b3 + 15add. - double() { - const { a, b } = CURVE - const b3 = Fp.mul(b, _3n) - const { px: X1, py: Y1, pz: Z1 } = this - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - let t0 = Fp.mul(X1, X1) // step 1 - let t1 = Fp.mul(Y1, Y1) - let t2 = Fp.mul(Z1, Z1) - let t3 = Fp.mul(X1, Y1) - t3 = Fp.add(t3, t3) // step 5 - Z3 = Fp.mul(X1, Z1) - Z3 = Fp.add(Z3, Z3) - X3 = Fp.mul(a, Z3) - Y3 = Fp.mul(b3, t2) - Y3 = Fp.add(X3, Y3) // step 10 - X3 = Fp.sub(t1, Y3) - Y3 = Fp.add(t1, Y3) - Y3 = Fp.mul(X3, Y3) - X3 = Fp.mul(t3, X3) - Z3 = Fp.mul(b3, Z3) // step 15 - t2 = Fp.mul(a, t2) - t3 = Fp.sub(t0, t2) - t3 = Fp.mul(a, t3) - t3 = Fp.add(t3, Z3) - Z3 = Fp.add(t0, t0) // step 20 - t0 = Fp.add(Z3, t0) - t0 = Fp.add(t0, t2) - t0 = Fp.mul(t0, t3) - Y3 = Fp.add(Y3, t0) - t2 = Fp.mul(Y1, Z1) // step 25 - t2 = Fp.add(t2, t2) - t0 = Fp.mul(t2, t3) - X3 = Fp.sub(X3, t0) - Z3 = Fp.mul(t2, t1) - Z3 = Fp.add(Z3, Z3) // step 30 - Z3 = Fp.add(Z3, Z3) - return new Point(X3, Y3, Z3) - } - // Renes-Costello-Batina exception-free addition formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 1 - // Cost: 12M + 0S + 3*a + 3*b3 + 23add. - add(other) { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - const a = CURVE.a - const b3 = Fp.mul(CURVE.b, _3n) - let t0 = Fp.mul(X1, X2) // step 1 - let t1 = Fp.mul(Y1, Y2) - let t2 = Fp.mul(Z1, Z2) - let t3 = Fp.add(X1, Y1) - let t4 = Fp.add(X2, Y2) // step 5 - t3 = Fp.mul(t3, t4) - t4 = Fp.add(t0, t1) - t3 = Fp.sub(t3, t4) - t4 = Fp.add(X1, Z1) - let t5 = Fp.add(X2, Z2) // step 10 - t4 = Fp.mul(t4, t5) - t5 = Fp.add(t0, t2) - t4 = Fp.sub(t4, t5) - t5 = Fp.add(Y1, Z1) - X3 = Fp.add(Y2, Z2) // step 15 - t5 = Fp.mul(t5, X3) - X3 = Fp.add(t1, t2) - t5 = Fp.sub(t5, X3) - Z3 = Fp.mul(a, t4) - X3 = Fp.mul(b3, t2) // step 20 - Z3 = Fp.add(X3, Z3) - X3 = Fp.sub(t1, Z3) - Z3 = Fp.add(t1, Z3) - Y3 = Fp.mul(X3, Z3) - t1 = Fp.add(t0, t0) // step 25 - t1 = Fp.add(t1, t0) - t2 = Fp.mul(a, t2) - t4 = Fp.mul(b3, t4) - t1 = Fp.add(t1, t2) - t2 = Fp.sub(t0, t2) // step 30 - t2 = Fp.mul(a, t2) - t4 = Fp.add(t4, t2) - t0 = Fp.mul(t1, t4) - Y3 = Fp.add(Y3, t0) - t0 = Fp.mul(t5, t4) // step 35 - X3 = Fp.mul(t3, X3) - X3 = Fp.sub(X3, t0) - t0 = Fp.mul(t3, t1) - Z3 = Fp.mul(t5, Z3) - Z3 = Fp.add(Z3, t0) // step 40 - return new Point(X3, Y3, Z3) - } - subtract(other) { - return this.add(other.negate()) - } - is0() { - return this.equals(Point.ZERO) - } - wNAF(n) { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - /** - * Non-constant-time multiplication. Uses double-and-add algorithm. - * It's faster, but should only be used when you don't care about - * an exposed private key e.g. sig verification, which works over *public* keys. - */ - multiplyUnsafe(sc) { - const { endo, n: N } = CURVE - ut.aInRange('scalar', sc, _0n, N) - const I = Point.ZERO - if (sc === _0n) return I - if (this.is0() || sc === _1n) return this - // Case a: no endomorphism. Case b: has precomputes. - if (!endo || wnaf.hasPrecomputes(this)) - return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) - // Case c: endomorphism - let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) - let k1p = I - let k2p = I - let d = this - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) k1p = k1p.add(d) - if (k2 & _1n) k2p = k2p.add(d) - d = d.double() - k1 >>= _1n - k2 >>= _1n - } - if (k1neg) k1p = k1p.negate() - if (k2neg) k2p = k2p.negate() - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - return k1p.add(k2p) - } - /** - * Constant time multiplication. - * Uses wNAF method. Windowed method may be 10% faster, - * but takes 2x longer to generate and consumes 2x memory. - * Uses precomputes when available. - * Uses endomorphism for Koblitz curves. - * @param scalar by which the point would be multiplied - * @returns New point - */ - multiply(scalar) { - const { endo, n: N } = CURVE - ut.aInRange('scalar', scalar, _1n, N) - let point, fake // Fake point is used to const-time mult - if (endo) { - const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) - let { p: k1p, f: f1p } = this.wNAF(k1) - let { p: k2p, f: f2p } = this.wNAF(k2) - k1p = wnaf.constTimeNegate(k1neg, k1p) - k2p = wnaf.constTimeNegate(k2neg, k2p) - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - point = k1p.add(k2p) - fake = f1p.add(f2p) - } else { - const { p, f } = this.wNAF(scalar) - point = p - fake = f - } - // Normalize `z` for both points, but return only real one - return Point.normalizeZ([point, fake])[0] - } - /** - * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. - * Not using Strauss-Shamir trick: precomputation tables are faster. - * The trick could be useful if both P and Q are not G (not in our case). - * @returns non-zero affine point - */ - multiplyAndAddUnsafe(Q, a, b) { - const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes - const mul = ( - P, - a, // Select faster multiply() method - ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) - const sum = mul(this, a).add(mul(Q, b)) - return sum.is0() ? undefined : sum - } - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - toAffine(iz) { - return toAffineMemo(this, iz) - } - isTorsionFree() { - const { h: cofactor, isTorsionFree } = CURVE - if (cofactor === _1n) return true // No subgroups, always torsion-free - if (isTorsionFree) return isTorsionFree(Point, this) - throw new Error('isTorsionFree() has not been declared for the elliptic curve') - } - clearCofactor() { - const { h: cofactor, clearCofactor } = CURVE - if (cofactor === _1n) return this // Fast-path - if (clearCofactor) return clearCofactor(Point, this) - return this.multiplyUnsafe(CURVE.h) - } - toRawBytes(isCompressed = true) { - ;(0, utils_js_1.abool)('isCompressed', isCompressed) - this.assertValidity() - return toBytes(Point, this, isCompressed) - } - toHex(isCompressed = true) { - ;(0, utils_js_1.abool)('isCompressed', isCompressed) - return ut.bytesToHex(this.toRawBytes(isCompressed)) - } - } - Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) - Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) - const _bits = CURVE.nBitLength - const wnaf = (0, curve_js_1.wNAF)(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) - // Validate if generator point is on curve - return { - CURVE, - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } -} -function validateOpts(curve) { - const opts = (0, curve_js_1.validateBasic)(curve) - ut.validateObject( - opts, - { - hash: 'hash', - hmac: 'function', - randomBytes: 'function', - }, - { - bits2int: 'function', - bits2int_modN: 'function', - lowS: 'boolean', - }, - ) - return Object.freeze({ lowS: true, ...opts }) -} -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -function weierstrass(curveDef) { - const CURVE = validateOpts(curveDef) - const { Fp, n: CURVE_ORDER } = CURVE - const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 - const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 - function modN(a) { - return (0, modular_js_1.mod)(a, CURVE_ORDER) - } - function invN(a) { - return (0, modular_js_1.invert)(a, CURVE_ORDER) - } - const { - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } = weierstrassPoints({ - ...CURVE, - toBytes(_c, point, isCompressed) { - const a = point.toAffine() - const x = Fp.toBytes(a.x) - const cat = ut.concatBytes - ;(0, utils_js_1.abool)('isCompressed', isCompressed) - if (isCompressed) { - return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) - } else { - return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) - } - }, - fromBytes(bytes) { - const len = bytes.length - const head = bytes[0] - const tail = bytes.subarray(1) - // this.assertValidity() is done inside of fromHex - if (len === compressedLen && (head === 0x02 || head === 0x03)) { - const x = ut.bytesToNumberBE(tail) - if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') - const y2 = weierstrassEquation(x) // y² = x³ + ax + b - let y - try { - y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 - } catch (sqrtError) { - const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' - throw new Error('Point is not on curve' + suffix) - } - const isYOdd = (y & _1n) === _1n - // ECDSA - const isHeadOdd = (head & 1) === 1 - if (isHeadOdd !== isYOdd) y = Fp.neg(y) - return { x, y } - } else if (len === uncompressedLen && head === 0x04) { - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - } else { - const cl = compressedLen - const ul = uncompressedLen - throw new Error( - 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, - ) - } - }, - }) - const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) - function isBiggerThanHalfOrder(number) { - const HALF = CURVE_ORDER >> _1n - return number > HALF - } - function normalizeS(s) { - return isBiggerThanHalfOrder(s) ? modN(-s) : s - } - // slice bytes num - const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to)) - /** - * ECDSA signature with its (r, s) properties. Supports DER & compact representations. - */ - class Signature { - constructor(r, s, recovery) { - this.r = r - this.s = s - this.recovery = recovery - this.assertValidity() - } - // pair (bytes of r, bytes of s) - static fromCompact(hex) { - const l = CURVE.nByteLength - hex = (0, utils_js_1.ensureBytes)('compactSignature', hex, l * 2) - return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) - } - // DER encoded ECDSA signature - // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script - static fromDER(hex) { - const { r, s } = exports.DER.toSig((0, utils_js_1.ensureBytes)('DER', hex)) - return new Signature(r, s) - } - assertValidity() { - ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] - ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] - } - addRecoveryBit(recovery) { - return new Signature(this.r, this.s, recovery) - } - recoverPublicKey(msgHash) { - const { r, s, recovery: rec } = this - const h = bits2int_modN((0, utils_js_1.ensureBytes)('msgHash', msgHash)) // Truncate hash - if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') - const radj = rec === 2 || rec === 3 ? r + CURVE.n : r - if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') - const prefix = (rec & 1) === 0 ? '02' : '03' - const R = Point.fromHex(prefix + numToNByteStr(radj)) - const ir = invN(radj) // r^-1 - const u1 = modN(-h * ir) // -hr^-1 - const u2 = modN(s * ir) // sr^-1 - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) - if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked - Q.assertValidity() - return Q - } - // Signatures should be low-s, to prevent malleability. - hasHighS() { - return isBiggerThanHalfOrder(this.s) - } - normalizeS() { - return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this - } - // DER-encoded - toDERRawBytes() { - return ut.hexToBytes(this.toDERHex()) - } - toDERHex() { - return exports.DER.hexFromSig({ r: this.r, s: this.s }) - } - // padded bytes of r, then padded bytes of s - toCompactRawBytes() { - return ut.hexToBytes(this.toCompactHex()) - } - toCompactHex() { - return numToNByteStr(this.r) + numToNByteStr(this.s) - } - } - const utils = { - isValidPrivateKey(privateKey) { - try { - normPrivateKeyToScalar(privateKey) - return true - } catch (error) { - return false - } - }, - normPrivateKeyToScalar: normPrivateKeyToScalar, - /** - * Produces cryptographically secure private key from random of size - * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. - */ - randomPrivateKey: () => { - const length = (0, modular_js_1.getMinHashLength)(CURVE.n) - return (0, modular_js_1.mapHashToField)(CURVE.randomBytes(length), CURVE.n) - }, - /** - * Creates precompute table for an arbitrary EC point. Makes point "cached". - * Allows to massively speed-up `point.multiply(scalar)`. - * @returns cached point - * @example - * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); - * fast.multiply(privKey); // much faster ECDH now - */ - precompute(windowSize = 8, point = Point.BASE) { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here - return point - }, - } - /** - * Computes public key for a private key. Checks for validity of the private key. - * @param privateKey private key - * @param isCompressed whether to return compact (default), or full key - * @returns Public key, full when isCompressed=false; short when isCompressed=true - */ - function getPublicKey(privateKey, isCompressed = true) { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) - } - /** - * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. - */ - function isProbPub(item) { - const arr = ut.isBytes(item) - const str = typeof item === 'string' - const len = (arr || str) && item.length - if (arr) return len === compressedLen || len === uncompressedLen - if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen - if (item instanceof Point) return true - return false - } - /** - * ECDH (Elliptic Curve Diffie Hellman). - * Computes shared public key from private key and public key. - * Checks: 1) private key validity 2) shared key is on-curve. - * Does NOT hash the result. - * @param privateA private key - * @param publicB different public key - * @param isCompressed whether to return compact (default), or full key - * @returns shared public key - */ - function getSharedSecret(privateA, publicB, isCompressed = true) { - if (isProbPub(privateA)) throw new Error('first arg must be private key') - if (!isProbPub(publicB)) throw new Error('second arg must be public key') - const b = Point.fromHex(publicB) // check for being on-curve - return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) - } - // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. - // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. - // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. - // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors - const bits2int = - CURVE.bits2int || - function (bytes) { - // Our custom check "just in case" - if (bytes.length > 8192) throw new Error('input is too large') - // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) - // for some cases, since bytes.length * 8 is not actual bitLength. - const num = ut.bytesToNumberBE(bytes) // check for == u8 done here - const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits - return delta > 0 ? num >> BigInt(delta) : num - } - const bits2int_modN = - CURVE.bits2int_modN || - function (bytes) { - return modN(bits2int(bytes)) // can't use bytesToNumberBE here - } - // NOTE: pads output with zero as per spec - const ORDER_MASK = ut.bitMask(CURVE.nBitLength) - /** - * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. - */ - function int2octets(num) { - ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) - // works with order, can have different size than numToField! - return ut.numberToBytesBE(num, CURVE.nByteLength) - } - // Steps A, D of RFC6979 3.2 - // Creates RFC6979 seed; converts msg/privKey to numbers. - // Used only in sign, not in verify. - // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, - // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 - function prepSig(msgHash, privateKey, opts = defaultSigOpts) { - if (['recovered', 'canonical'].some((k) => k in opts)) - throw new Error('sign() legacy options not supported') - const { hash, randomBytes } = CURVE - let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default - if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash - msgHash = (0, utils_js_1.ensureBytes)('msgHash', msgHash) - validateSigVerOpts(opts) - if (prehash) msgHash = (0, utils_js_1.ensureBytes)('prehashed msgHash', hash(msgHash)) - // We can't later call bits2octets, since nested bits2int is broken for curves - // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. - // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) - const h1int = bits2int_modN(msgHash) - const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint - const seedArgs = [int2octets(d), int2octets(h1int)] - // extraEntropy. RFC6979 3.6: additional k' (optional). - if (ent != null && ent !== false) { - // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is - seedArgs.push((0, utils_js_1.ensureBytes)('extraEntropy', e)) // check for being bytes - } - const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 - const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! - // Converts signature params into point w r/s, checks result for validity. - function k2sig(kBytes) { - // RFC 6979 Section 3.2, step 3: k = bits2int(T) - const k = bits2int(kBytes) // Cannot use fields methods, since it is group element - if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N - const ik = invN(k) // k^-1 mod n - const q = Point.BASE.multiply(k).toAffine() // q = Gk - const r = modN(q.x) // r = q.x mod n - if (r === _0n) return - // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to - // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: - // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT - const s = modN(ik * modN(m + r * d)) // Not using blinding here - if (s === _0n) return - let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) - let normS = s - if (lowS && isBiggerThanHalfOrder(s)) { - normS = normalizeS(s) // if lowS was passed, ensure s is always - recovery ^= 1 // // in the bottom half of N - } - return new Signature(r, normS, recovery) // use normS, not s - } - return { seed, k2sig } - } - const defaultSigOpts = { lowS: CURVE.lowS, prehash: false } - const defaultVerOpts = { lowS: CURVE.lowS, prehash: false } - /** - * Signs message hash with a private key. - * ``` - * sign(m, d, k) where - * (x, y) = G × k - * r = x mod n - * s = (m + dr)/k mod n - * ``` - * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. - * @param privKey private key - * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. - * @returns signature with recovery param - */ - function sign(msgHash, privKey, opts = defaultSigOpts) { - const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. - const C = CURVE - const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) - return drbg(seed, k2sig) // Steps B, C, D, E, F, G - } - // Enable precomputes. Slows down first publicKey computation by 20ms. - Point.BASE._setWindowSize(8) - // utils.precompute(8, ProjectivePoint.BASE) - /** - * Verifies a signature against message hash and public key. - * Rejects lowS signatures by default: to override, - * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: - * - * ``` - * verify(r, s, h, P) where - * U1 = hs^-1 mod n - * U2 = rs^-1 mod n - * R = U1⋅G - U2⋅P - * mod(R.x, n) == r - * ``` - */ - function verify(signature, msgHash, publicKey, opts = defaultVerOpts) { - const sg = signature - msgHash = (0, utils_js_1.ensureBytes)('msgHash', msgHash) - publicKey = (0, utils_js_1.ensureBytes)('publicKey', publicKey) - const { lowS, prehash, format } = opts - // Verify opts, deduce signature format - validateSigVerOpts(opts) - if ('strict' in opts) throw new Error('options.strict was renamed to lowS') - if (format !== undefined && format !== 'compact' && format !== 'der') - throw new Error('format must be compact or der') - const isHex = typeof sg === 'string' || ut.isBytes(sg) - const isObj = - !isHex && - !format && - typeof sg === 'object' && - sg !== null && - typeof sg.r === 'bigint' && - typeof sg.s === 'bigint' - if (!isHex && !isObj) - throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') - let _sig = undefined - let P - try { - if (isObj) _sig = new Signature(sg.r, sg.s) - if (isHex) { - // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). - // Since DER can also be 2*nByteLength bytes, we check for it first. - try { - if (format !== 'compact') _sig = Signature.fromDER(sg) - } catch (derError) { - if (!(derError instanceof exports.DER.Err)) throw derError - } - if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) - } - P = Point.fromHex(publicKey) - } catch (error) { - return false - } - if (!_sig) return false - if (lowS && _sig.hasHighS()) return false - if (prehash) msgHash = CURVE.hash(msgHash) - const { r, s } = _sig - const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element - const is = invN(s) // s^-1 - const u1 = modN(h * is) // u1 = hs^-1 mod n - const u2 = modN(r * is) // u2 = rs^-1 mod n - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P - if (!R) return false - const v = modN(R.x) - return v === r - } - return { - CURVE, - getPublicKey, - getSharedSecret, - sign, - verify, - ProjectivePoint: Point, - Signature, - utils, - } -} -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -function SWUFpSqrtRatio(Fp, Z) { - // Generic implementation - const q = Fp.ORDER - let l = _0n - for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n - const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. - // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. - // 2n ** c1 == 2n << (c1-1) - const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) - const _2n_pow_c1 = _2n_pow_c1_1 * _2n - const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic - const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic - const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic - const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic - const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 - const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) - let sqrtRatio = (u, v) => { - let tv1 = c6 // 1. tv1 = c6 - let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 - let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 - tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v - let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 - tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 - tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 - tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v - tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u - let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 - tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 - let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 - tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 - tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) - // 17. for i in (c1, c1 - 1, ..., 2): - for (let i = c1; i > _1n; i--) { - let tv5 = i - _2n // 18. tv5 = i - 2 - tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 - let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 - const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 - tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 - tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 - tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) - } - return { isValid: isQR, value: tv3 } - } - if (Fp.ORDER % _4n === _3n) { - // sqrt_ratio_3mod4(u, v) - const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic - const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) - sqrtRatio = (u, v) => { - let tv1 = Fp.sqr(v) // 1. tv1 = v^2 - const tv2 = Fp.mul(u, v) // 2. tv2 = u * v - tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 - let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 - y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 - const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 - const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v - const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u - let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) - return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 - } - } - // No curves uses that - // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 - return sqrtRatio -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -function mapToCurveSimpleSWU(Fp, opts) { - ;(0, modular_js_1.validateField)(Fp) - if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) - throw new Error('mapToCurveSimpleSWU: invalid opts') - const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) - if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') - // Input: u, an element of F. - // Output: (x, y), a point on E. - return (u) => { - // prettier-ignore - let tv1, tv2, tv3, tv4, tv5, tv6, x, y - tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 - tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 - tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 - tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 - tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 - tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) - tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 - tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 - tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 - tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 - tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 - tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 - tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 - tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 - tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 - x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 - const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) - y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 - y = Fp.mul(y, value) // 20. y = y * y1 - x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) - y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) - const e1 = Fp.isOdd(u) === Fp.isOdd(y) // 23. e1 = sgn0(u) == sgn0(y) - y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) - x = Fp.div(x, tv4) // 25. x = x / tv4 - return { x, y } - } -} -//# sourceMappingURL=weierstrass.js.map diff --git a/packages/noble-curves/abstract/weierstrass.js.map b/packages/noble-curves/abstract/weierstrass.js.map deleted file mode 100644 index 1c741346840..00000000000 --- a/packages/noble-curves/abstract/weierstrass.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"weierstrass.js","sourceRoot":"","sources":["../src/abstract/weierstrass.ts"],"names":[],"mappings":"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,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,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"} \ No newline at end of file diff --git a/packages/noble-curves/bls12-381.d.ts b/packages/noble-curves/bls12-381.d.ts deleted file mode 100644 index 8de19050c1e..00000000000 --- a/packages/noble-curves/bls12-381.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type CurveFn } from './abstract/bls.js' -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -export declare const bls12_381: CurveFn -//# sourceMappingURL=bls12-381.d.ts.map diff --git a/packages/noble-curves/bls12-381.d.ts.map b/packages/noble-curves/bls12-381.d.ts.map deleted file mode 100644 index c7b4579f259..00000000000 --- a/packages/noble-curves/bls12-381.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls12-381.d.ts","sourceRoot":"","sources":["src/bls12-381.ts"],"names":[],"mappings":"AA+DA,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAkXtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,OAqUtB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/bls12-381.js b/packages/noble-curves/bls12-381.js deleted file mode 100644 index a8abbaf2682..00000000000 --- a/packages/noble-curves/bls12-381.js +++ /dev/null @@ -1,756 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.bls12_381 = void 0 -/** - * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: - * * Construct zk-SNARKs at the ~120-bit security - * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: - * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr - * - * ### Summary - * 1. BLS Relies on Bilinear Pairing (expensive) - * 2. Private Keys: 32 bytes - * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. - * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. - * - The signature is a point on the G2 subgroup, which is defined over a finite field - * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the - * complex numbers). - * - We also support reversed 96-byte pubkeys & 48-byte short signatures. - * 5. The 12 stands for the Embedding degree. - * - * ### Formulas - * - `P = pk x G` - public keys - * - `S = pk x H(m)` - signing - * - `e(P, H(m)) == e(G, S)` - verification using pairings - * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation - * - * ### Compatibility and notes - * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. - * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. - * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". - * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) - * 4. Compatible with specs: - * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), - * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), - * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * - * ### Params - * To verify curve parameters, see - * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). - * Basic math is done over finite fields over p. - * More complicated math is done over polynominal extension fields. - * To simplify calculations in Fp12, we construct extension tower: - * - * Embedding degree (k): 12 - * Seed (X): -15132376222941642752 - * Fr: (x⁴-x²+1) - * Fp: ((x-1)² ⋅ r(x)/3+x) - * (E/Fp): Y²=X³+4 - * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) - * Ate loop size: X - * - * ### Towers - * - Fp₁₂ = Fp₆² => Fp₂³ - * - Fp(u) / (u² - β) where β = -1 - * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 - * - Fp₆(w) / (w² - γ) where γ = v - * - Fp²[u] = Fp/u²+1 - * - Fp⁶[v] = Fp²/v³-1-u - * - Fp¹²[w] = Fp⁶/w²-v - * - * @todo construct bls & bn fp/fr from seed. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha256_1 = require('@noble/hashes/sha256') -const utils_1 = require('@noble/hashes/utils') -const bls_js_1 = require('./abstract/bls.js') -const mod = require('./abstract/modular.js') -const utils_js_1 = require('./abstract/utils.js') -// Types -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const tower_js_1 = require('./abstract/tower.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) -// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! -const BLS_X = BigInt('0xd201000000010000') -const BLS_X_LEN = (0, utils_js_1.bitLen)(BLS_X) -// CURVE FIELDS -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_js_1.tower12)({ - // Order of Fp - ORDER: BigInt( - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', - ), - // Finite extension field over irreducible polynominal. - // Fp(u) / (u² - β) where β = -1 - FP2_NONRESIDUE: [_1n, _1n], - Fp2mulByB: ({ c0, c1 }) => { - const t0 = Fp.mul(c0, _4n) // 4 * c0 - const t1 = Fp.mul(c1, _4n) // 4 * c1 - // (T0-T1) + (T0+T1)*i - return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } - }, - // Fp12 - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }) => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BLS_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if ((0, utils_js_1.bitGet)(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const x = BLS_X - // this^(q⁶) / this - const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) - // t0^(q²) * t0 - const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) - const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) - const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) - const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) - const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) - const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) - const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) - const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) - const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) - const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) - const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) - // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 - return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) - }, -}) -// Finite field over r. -// This particular field is not used anywhere in bls12-381, but it is still useful. -const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) -// END OF CURVE FIELDS -// HashToCurve -// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 -const isogenyMapG2 = (0, hash_to_curve_js_1.isogenyMap)( - Fp2, - [ - // xNum - [ - [ - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - ], - [ - '0x0', - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', - ], - [ - '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', - '0x0', - ], - ], - // xDen - [ - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', - ], - [ - '0xc', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', - ], - ['0x1', '0x0'], // LAST 1 - ], - // yNum - [ - [ - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - ], - [ - '0x0', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', - ], - [ - '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', - '0x0', - ], - ], - // yDen - [ - [ - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - ], - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', - ], - [ - '0x12', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', - ], - ['0x1', '0x0'], // LAST 1 - ], - ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))), -) -// 11-isogeny map from E' to E -const isogenyMapG1 = (0, hash_to_curve_js_1.isogenyMap)( - Fp, - [ - // xNum - [ - '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', - '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', - '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', - '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', - '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', - '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', - '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', - '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', - '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', - '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', - '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', - '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', - ], - // xDen - [ - '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', - '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', - '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', - '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', - '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', - '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', - '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', - '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', - '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', - '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', - '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', - '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', - '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', - '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', - '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', - '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', - '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', - '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', - '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', - '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', - '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', - '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', - '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', - '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', - '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', - ], - // yDen - [ - '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', - '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', - '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', - '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', - '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', - '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', - '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', - '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', - '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', - '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', - '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', - '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', - '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', - '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', - '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))), -) -// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i -const G2_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp2, { - A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I - B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) - Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) -}) -// Optimized SWU Map - Fp to G1 -const G1_SWU = (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp, { - A: Fp.create( - BigInt( - '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', - ), - ), - B: Fp.create( - BigInt( - '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', - ), - ), - Z: Fp.create(BigInt(11)), -}) -// Endomorphisms (for fast cofactor clearing) -// Ψ(P) endomorphism -const { G2psi, G2psi2 } = (0, tower_js_1.psiFrobenius)(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) -// Default hash_to_field options are for hash to G2. -// -// Parameter definitions are in section 5.3 of the spec unless otherwise noted. -// Parameter values come from section 8.8.2 of the spec. -// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 -// -// Base field F is GF(p^m) -// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab -// m = 2 (or 1 for G1 see section 8.8.1) -// k = 128 -const htfDefaults = Object.freeze({ - // DST: a domain separation tag - // defined in section 2.2.5 - // Use utils.getDSTLabel(), utils.setDSTLabel(value) - DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - // p: the characteristic of F - // where F is a finite field of characteristic p and order q = p^m - p: Fp.ORDER, - // m: the extension degree of F, m >= 1 - // where F is a finite field of characteristic p and order q = p^m - m: 2, - // k: the target security level for the suite in bits - // defined in section 5.1 - k: 128, - // option to use a message that has already been processed by - // expand_message_xmd - expand: 'xmd', - // Hash functions for: expand_message_xmd is appropriate for use with a - // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. - // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 - hash: sha256_1.sha256, -}) -// Encoding utils -// Point on G1 curve: (x, y) -// Compressed point of infinity -const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits -function parseMask(bytes) { - // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. - bytes = bytes.slice() - const mask = bytes[0] & 224 - const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) - const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) - const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) - bytes[0] &= 31 // clear mask (zero first 3 bits) - return { compressed, infinity, sort, value: bytes } -} -function setMask(bytes, mask) { - if (bytes[0] & 224) throw new Error('setMask: non-empty mask') - if (mask.compressed) bytes[0] |= 128 - if (mask.infinity) bytes[0] |= 64 - if (mask.sort) bytes[0] |= 32 - return bytes -} -function signatureG1ToRawBytes(point) { - point.assertValidity() - const isZero = point.equals(exports.bls12_381.G1.ProjectivePoint.ZERO) - const { x, y } = point.toAffine() - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort }) -} -function signatureG2ToRawBytes(point) { - // NOTE: by some reasons it was missed in bls12-381, looks like bug - point.assertValidity() - const len = Fp.BYTES - if (point.equals(exports.bls12_381.G2.ProjectivePoint.ZERO)) - return (0, utils_js_1.concatBytes)(COMPRESSED_ZERO, (0, utils_js_1.numberToBytesBE)(_0n, len)) - const { x, y } = point.toAffine() - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - const tmp = y1 > _0n ? y1 * _2n : y0 * _2n - const sort = Boolean((tmp / Fp.ORDER) & _1n) - const z2 = x0 - return (0, utils_js_1.concatBytes)( - setMask((0, utils_js_1.numberToBytesBE)(x1, len), { sort, compressed: true }), - (0, utils_js_1.numberToBytesBE)(z2, len), - ) -} -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -exports.bls12_381 = (0, bls_js_1.bls)({ - // Fields - fields: { - Fp, - Fp2, - Fp6, - Fp12, - Fr, - }, - // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where - // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 - G1: { - Fp, - // cofactor; (z - 1)²/3 - h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), - // generator's coordinates - // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 - // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 - Gx: BigInt( - '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', - ), - Gy: BigInt( - '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', - ), - a: Fp.ZERO, - b: _4n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, point) => { - // φ endomorphism - const cubicRootOfUnityModP = BigInt( - '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', - ) - const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) - // todo: unroll - const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P - const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P - return u2P.equals(phi) - // https://eprint.iacr.org/2019/814.pdf - // (z² − 1)/3 - // const c1 = BigInt('0x396c8c005555e1560000000055555555'); - // const P = this; - // const S = P.sigma(); - // const Q = S.double(); - // const S2 = S.sigma(); - // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O - // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); - // const C = left.subtract(S2); - // return C.isZero(); - }, - // Clear cofactor of G1 - // https://eprint.iacr.org/2019/403 - clearCofactor: (_c, point) => { - // return this.multiplyUnsafe(CURVE.h); - return point.multiplyUnsafe(BLS_X).add(point) // x*P + P - }, - mapToCurve: (scalars) => { - const { x, y } = G1_SWU(Fp.create(scalars[0])) - return isogenyMapG1(x, y) - }, - fromBytes: (bytes) => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if (value.length === 48 && compressed) { - // TODO: Fp.bytes - const P = Fp.ORDER - const compressedValue = (0, utils_js_1.bytesToNumberBE)(value) - // Zero - const x = Fp.create(compressedValue & Fp.MASK) - if (infinity) { - if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') - return { x: _0n, y: _0n } - } - const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) - return { x: Fp.create(x), y: Fp.create(y) } - } else if (value.length === 96 && !compressed) { - // Check if the infinity flag is set - const x = (0, utils_js_1.bytesToNumberBE)(value.subarray(0, Fp.BYTES)) - const y = (0, utils_js_1.bytesToNumberBE)(value.subarray(Fp.BYTES)) - if (infinity) { - if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') - return exports.bls12_381.G1.ProjectivePoint.ZERO.toAffine() - } - return { x: Fp.create(x), y: Fp.create(y) } - } else { - throw new Error('invalid point G1, expected 48/96 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask((0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), { compressed: true, sort }) - } else { - if (isZero) { - // 2x PUBLIC_KEY_LENGTH - const x = (0, utils_js_1.concatBytes)( - new Uint8Array([0x40]), - new Uint8Array(2 * Fp.BYTES - 1), - ) - return x - } else { - return (0, utils_js_1.concatBytes)( - (0, utils_js_1.numberToBytesBE)(x, Fp.BYTES), - (0, utils_js_1.numberToBytesBE)(y, Fp.BYTES), - ) - } - } - }, - ShortSignature: { - fromHex(hex) { - const { infinity, sort, value } = parseMask( - (0, utils_js_1.ensureBytes)('signatureHex', hex, 48), - ) - const P = Fp.ORDER - const compressedValue = (0, utils_js_1.bytesToNumberBE)(value) - // Zero - if (infinity) return exports.bls12_381.G1.ProjectivePoint.ZERO - const x = Fp.create(compressedValue & Fp.MASK) - const right = Fp.add(Fp.pow(x, _3n), Fp.create(exports.bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - const aflag = BigInt(sort) - if ((y * _2n) / P !== aflag) y = Fp.neg(y) - const point = exports.bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point) { - return signatureG1ToRawBytes(point) - }, - toHex(point) { - return (0, utils_js_1.bytesToHex)(signatureG1ToRawBytes(point)) - }, - }, - }, - // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), - // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where - // G² - 1 - // h2q - G2: { - Fp: Fp2, - // cofactor - h: BigInt( - '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', - ), - Gx: Fp2.fromBigTuple([ - BigInt( - '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', - ), - BigInt( - '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', - ), - ]), - // y = - // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, - // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 - Gy: Fp2.fromBigTuple([ - BigInt( - '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', - ), - BigInt( - '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', - ), - ]), - a: Fp2.ZERO, - b: Fp2.fromBigTuple([_4n, _4n]), - hEff: BigInt( - '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', - ), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: (scalars) => { - const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) - return isogenyMapG2(x, y) - }, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, P) => { - return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) - // Older version: https://eprint.iacr.org/2019/814.pdf - // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O - // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); - }, - // Maps the point into the prime-order subgroup G2. - // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 - // https://eprint.iacr.org/2017/419.pdf - // prettier-ignore - clearCofactor: (c, P) => { - const x = BLS_X - let t1 = P.multiplyUnsafe(x).negate() // [-x]P - let t2 = G2psi(c, P) // Ψ(P) - let t3 = P.double() // 2P - t3 = G2psi2(c, t3) // Ψ²(2P) - t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) - t2 = t1.add(t2) // [-x]P + Ψ(P) - t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) - t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) - t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P - return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) - }, - fromBytes: (bytes) => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if ( - (!compressed && !infinity && sort) || // 00100000 - (!compressed && infinity && sort) || // 01100000 - (sort && infinity && compressed) // 11100000 - ) { - throw new Error('invalid encoding flag: ' + (bytes[0] & 224)) - } - const L = Fp.BYTES - const slc = (b, from, to) => (0, utils_js_1.bytesToNumberBE)(b.slice(from, to)) - if (value.length === 96 && compressed) { - const b = exports.bls12_381.params.G2b - const P = Fp.ORDER - if (infinity) { - // check that all bytes are 0 - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid compressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x_1 = slc(value, 0, L) - const x_0 = slc(value, L, 2 * L) - const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) - const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b - let y = Fp2.sqrt(right) - const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n - y = sort && Y_bit > 0 ? y : Fp2.neg(y) - return { x, y } - } else if (value.length === 192 && !compressed) { - if (infinity) { - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid uncompressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x1 = slc(value, 0, L) - const x0 = slc(value, L, 2 * L) - const y1 = slc(value, 2 * L, 3 * L) - const y0 = slc(value, 3 * L, 4 * L) - return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } - } else { - throw new Error('invalid point G2, expected 96/192 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const { BYTES: len, ORDER: P } = Fp - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) - return (0, utils_js_1.concatBytes)( - COMPRESSED_ZERO, - (0, utils_js_1.numberToBytesBE)(_0n, len), - ) - const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) - return (0, utils_js_1.concatBytes)( - setMask((0, utils_js_1.numberToBytesBE)(x.c1, len), { compressed: true, sort: flag }), - (0, utils_js_1.numberToBytesBE)(x.c0, len), - ) - } else { - if (isZero) - return (0, utils_js_1.concatBytes)(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - return (0, utils_js_1.concatBytes)( - (0, utils_js_1.numberToBytesBE)(x1, len), - (0, utils_js_1.numberToBytesBE)(x0, len), - (0, utils_js_1.numberToBytesBE)(y1, len), - (0, utils_js_1.numberToBytesBE)(y0, len), - ) - } - }, - Signature: { - // TODO: Optimize, it's very slow because of sqrt. - fromHex(hex) { - const { infinity, sort, value } = parseMask( - (0, utils_js_1.ensureBytes)('signatureHex', hex), - ) - const P = Fp.ORDER - const half = value.length / 2 - if (half !== 48 && half !== 96) - throw new Error('invalid compressed signature length, must be 96 or 192') - const z1 = (0, utils_js_1.bytesToNumberBE)(value.slice(0, half)) - const z2 = (0, utils_js_1.bytesToNumberBE)(value.slice(half)) - // Indicates the infinity point - if (infinity) return exports.bls12_381.G2.ProjectivePoint.ZERO - const x1 = Fp.create(z1 & Fp.MASK) - const x2 = Fp.create(z2) - const x = Fp2.create({ c0: x2, c1: x1 }) - const y2 = Fp2.add(Fp2.pow(x, _3n), exports.bls12_381.params.G2b) // y² = x³ + 4 - // The slow part - let y = Fp2.sqrt(y2) - if (!y) throw new Error('Failed to find a square root') - // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 - // If y1 happens to be zero, then use the bit of y0 - const { re: y0, im: y1 } = Fp2.reim(y) - const aflag1 = BigInt(sort) - const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 - const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 - if (isGreater || isZero) y = Fp2.neg(y) - const point = exports.bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point) { - return signatureG2ToRawBytes(point) - }, - toHex(point) { - return (0, utils_js_1.bytesToHex)(signatureG2ToRawBytes(point)) - }, - }, - }, - params: { - ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 - r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves - xNegative: true, - twistType: 'multiplicative', - }, - htfDefaults, - hash: sha256_1.sha256, - randomBytes: utils_1.randomBytes, -}) -//# sourceMappingURL=bls12-381.js.map diff --git a/packages/noble-curves/bls12-381.js.map b/packages/noble-curves/bls12-381.js.map deleted file mode 100644 index d9c120ba5e6..00000000000 --- a/packages/noble-curves/bls12-381.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls12-381.js","sourceRoot":"","sources":["src/bls12-381.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/bn254.d.ts b/packages/noble-curves/bn254.d.ts deleted file mode 100644 index 94c05dba695..00000000000 --- a/packages/noble-curves/bn254.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type CurveFn as BLSCurveFn, type PostPrecomputeFn } from './abstract/bls.js' -import { type CurveFn } from './abstract/weierstrass.js' -export declare const _postPrecompute: PostPrecomputeFn -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -export declare const bn254: BLSCurveFn -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - */ -export declare const bn254_weierstrass: CurveFn -//# sourceMappingURL=bn254.d.ts.map diff --git a/packages/noble-curves/bn254.d.ts.map b/packages/noble-curves/bn254.d.ts.map deleted file mode 100644 index 478f468e6d2..00000000000 --- a/packages/noble-curves/bn254.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bn254.d.ts","sourceRoot":"","sources":["src/bn254.ts"],"names":[],"mappings":"AAkDA,OAAO,EAEL,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAgGtE,eAAO,MAAM,eAAe,EAAE,gBAY7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UA6DlB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAS9B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/bn254.js b/packages/noble-curves/bn254.js deleted file mode 100644 index 434d7ac7584..00000000000 --- a/packages/noble-curves/bn254.js +++ /dev/null @@ -1,237 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.bn254_weierstrass = exports.bn254 = exports._postPrecompute = void 0 -/** - * bn254, previously known as alt_bn_128, when it had 128-bit security. - -Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, -so the naming has been adjusted to its prime bit count: -https://hal.science/hal-01534101/file/main.pdf. -Compatible with EIP-196 and EIP-197. - -There are huge compatibility issues in the ecosystem: - -1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". -2. libff has bn128, but it's a different curve with different G2: - https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 -3. halo2curves bn256 is also incompatible and returns different outputs - -The goal of our implementation is to support "Ethereum" variant of the curve, -because it at least has specs: - -- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM -- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings -- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 -- The existing implementations are bad. Some are deprecated: - - https://github.com/paritytech/bn (old version) - - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) - - https://github.com/zcash-hackworks/bn - - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs -- Python implementations use different towers and produce different Fp12 outputs: - - https://github.com/ethereum/py_pairing - - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py -- Points are encoded differently in different implementations - -### Params -Seed (X): 4965661367192848881 -Fr: (36x⁴+36x³+18x²+6x+1) -Fp: (36x⁴+36x³+24x²+6x+1) -(E / Fp ): Y² = X³+3 -(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) -Ate loop size: 6x+2 - -### Towers -- Fp²[u] = Fp/u²+1 -- Fp⁶[v] = Fp²/v³-9-u -- Fp¹²[w] = Fp⁶/w²-v - - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha256_1 = require('@noble/hashes/sha256') -const utils_1 = require('@noble/hashes/utils') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const bls_js_1 = require('./abstract/bls.js') -const modular_js_1 = require('./abstract/modular.js') -const tower_js_1 = require('./abstract/tower.js') -const utils_js_1 = require('./abstract/utils.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -const _6n = BigInt(6) -const BN_X = BigInt('4965661367192848881') -const BN_X_LEN = (0, utils_js_1.bitLen)(BN_X) -const SIX_X_SQUARED = _6n * BN_X ** _2n -// Finite field over r. It's for convenience and is not used in the code below. -const Fr = (0, modular_js_1.Field)( - BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), -) -// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) -const Fp2B = { - c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), - c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), -} -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = (0, tower_js_1.tower12)({ - ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), - FP2_NONRESIDUE: [BigInt(9), _1n], - Fp2mulByB: (num) => Fp2.mul(num, Fp2B), - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }) => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BN_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if ((0, utils_js_1.bitGet)(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const powMinusX = (num) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) - const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) - const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) - const y1 = Fp12._cyclotomicSquare(powMinusX(r)) - const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) - const y4 = powMinusX(y2) - const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) - const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) - const y9 = Fp12.mul(y8, y1) - return Fp12.mul( - Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), - Fp12.mul( - Fp12.frobeniusMap(y8, 2), - Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), - ), - ) - }, -}) -// END OF CURVE FIELDS -const { G2psi, psi } = (0, tower_js_1.psiFrobenius)(Fp, Fp2, Fp2.NONRESIDUE) -/* -No hashToCurve for now (and signatures): - -- RFC 9380 doesn't mention bn254 and doesn't provide test vectors -- Overall seems like nobody is using BLS signatures on top of bn254 -- Seems like it can utilize SVDW, which is not implemented yet -*/ -const htfDefaults = Object.freeze({ - // DST: a domain separation tag defined in section 2.2.5 - DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - p: Fp.ORDER, - m: 2, - k: 128, - expand: 'xmd', - hash: sha256_1.sha256, -}) -const _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => { - const q = psi(Qx, Qy) - ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) - const q2 = psi(q[0], q[1]) - pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) -} -exports._postPrecompute = _postPrecompute -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -exports.bn254 = (0, bls_js_1.bls)({ - // Fields - fields: { Fp, Fp2, Fp6, Fp12, Fr }, - G1: { - Fp, - h: BigInt(1), - Gx: BigInt(1), - Gy: BigInt(2), - a: Fp.ZERO, - b: _3n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: utils_js_1.notImplemented, - fromBytes: utils_js_1.notImplemented, - toBytes: utils_js_1.notImplemented, - ShortSignature: { - fromHex: utils_js_1.notImplemented, - toRawBytes: utils_js_1.notImplemented, - toHex: utils_js_1.notImplemented, - }, - }, - G2: { - Fp: Fp2, - // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 - h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - Gx: Fp2.fromBigTuple([ - BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), - BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), - ]), - Gy: Fp2.fromBigTuple([ - BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), - BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), - ]), - a: Fp2.ZERO, - b: Fp2B, - hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P - mapToCurve: utils_js_1.notImplemented, - fromBytes: utils_js_1.notImplemented, - toBytes: utils_js_1.notImplemented, - Signature: { - fromHex: utils_js_1.notImplemented, - toRawBytes: utils_js_1.notImplemented, - toHex: utils_js_1.notImplemented, - }, - }, - params: { - ateLoopSize: BN_X * _6n + _2n, - r: Fr.ORDER, - xNegative: false, - twistType: 'divisive', - }, - htfDefaults, - hash: sha256_1.sha256, - randomBytes: utils_1.randomBytes, - postPrecompute: exports._postPrecompute, -}) -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - */ -exports.bn254_weierstrass = (0, weierstrass_js_1.weierstrass)({ - a: BigInt(0), - b: BigInt(3), - Fp, - n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), - Gx: BigInt(1), - Gy: BigInt(2), - h: BigInt(1), - ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), -}) -//# sourceMappingURL=bn254.js.map diff --git a/packages/noble-curves/bn254.js.map b/packages/noble-curves/bn254.js.map deleted file mode 100644 index 7d179f56e3b..00000000000 --- a/packages/noble-curves/bn254.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bn254.js","sourceRoot":"","sources":["src/bn254.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/ed25519.d.ts b/packages/noble-curves/ed25519.d.ts deleted file mode 100644 index b7f9565cc9a..00000000000 --- a/packages/noble-curves/ed25519.d.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { type AffinePoint, type Group } from './abstract/curve.js' -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' -import { type CurveFn as XCurveFn } from './abstract/montgomery.js' -import { type Hex } from './abstract/utils.js' -export declare const ED25519_TORSION_SUBGROUP: string[] -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -export declare const ed25519: CurveFn -export declare const ed25519ctx: CurveFn -export declare const ed25519ph: CurveFn -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -export declare const x25519: XCurveFn -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -export declare function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array -export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -export declare function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array -export declare const hashToCurve: HTFMethod -export declare const encodeToCurve: HTFMethod -type ExtendedPoint = ExtPointType -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -declare class RistPoint implements Group { - private readonly ep - static BASE: RistPoint - static ZERO: RistPoint - constructor(ep: ExtendedPoint) - static fromAffine(ap: AffinePoint): RistPoint - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex: Hex): RistPoint - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex: Hex): RistPoint - static msm(points: RistPoint[], scalars: bigint[]): RistPoint - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes(): Uint8Array - toHex(): string - toString(): string - equals(other: RistPoint): boolean - add(other: RistPoint): RistPoint - subtract(other: RistPoint): RistPoint - multiply(scalar: bigint): RistPoint - multiplyUnsafe(scalar: bigint): RistPoint - double(): RistPoint - negate(): RistPoint -} -export declare const RistrettoPoint: typeof RistPoint -export declare const hashToRistretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint -export declare const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint -export {} -//# sourceMappingURL=ed25519.d.ts.map diff --git a/packages/noble-curves/ed25519.d.ts.map b/packages/noble-curves/ed25519.d.ts.map deleted file mode 100644 index 3f6674549f0..00000000000 --- a/packages/noble-curves/ed25519.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["src/ed25519.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAa,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AAmE7B,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAS5C,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,OAAmE,CAAC;AAY1F,eAAO,MAAM,UAAU,EAAE,OAIlB,CAAC;AACR,eAAO,MAAM,SAAS,EAAE,OAMlB,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,EAAE,QAed,CAAC;AAER;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAIlE;AACD,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAG3E;AA0FD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AAiC5F,KAAK,aAAa,GAAG,YAAY,CAAC;AA0BlC;;;;;;GAMG;AACH,cAAM,SAAU,YAAW,KAAK,CAAC,SAAS,CAAC;IAK7B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;gBAGM,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS;IAIrD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IASvC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IA2BnC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;IAK7D;;;OAGG;IACH,UAAU,IAAI,UAAU;IA4BxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAKlB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAWjC,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKhC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAInC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAIzC,MAAM,IAAI,SAAS;IAInB,MAAM,IAAI,SAAS;CAGpB;AACD,eAAO,MAAM,cAAc,EAAE,OAAO,SAIhC,CAAC;AAGL,eAAO,MAAM,kBAAkB,QAAS,UAAU,WAAW,YAAY,KAAG,SAM3E,CAAC;AACF,eAAO,MAAM,oBAAoB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,KAAK,SAC3D,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/ed25519.js b/packages/noble-curves/ed25519.js deleted file mode 100644 index c585f99fa87..00000000000 --- a/packages/noble-curves/ed25519.js +++ /dev/null @@ -1,510 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.hash_to_ristretto255 = - exports.hashToRistretto255 = - exports.RistrettoPoint = - exports.encodeToCurve = - exports.hashToCurve = - exports.edwardsToMontgomery = - exports.x25519 = - exports.ed25519ph = - exports.ed25519ctx = - exports.ed25519 = - exports.ED25519_TORSION_SUBGROUP = - void 0 -exports.edwardsToMontgomeryPub = edwardsToMontgomeryPub -exports.edwardsToMontgomeryPriv = edwardsToMontgomeryPriv -/** - * ed25519 Twisted Edwards curve with following addons: - * - X25519 ECDH - * - Ristretto cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha512_1 = require('@noble/hashes/sha512') -const utils_1 = require('@noble/hashes/utils') -const curve_js_1 = require('./abstract/curve.js') -const edwards_js_1 = require('./abstract/edwards.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const montgomery_js_1 = require('./abstract/montgomery.js') -const utils_js_1 = require('./abstract/utils.js') -const ED25519_P = BigInt( - '57896044618658097711785492504343953926634992332820282019728792003956564819949', -) -// √(-1) aka √(a) aka 2^((p-1)/4) -const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( - '19681161376707505956807079304988542015446066515923890162744021073123829784752', -) -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// prettier-ignore -const _5n = BigInt(5), - _8n = BigInt(8) -function ed25519_pow_2_252_3(x) { - // prettier-ignore - const _10n = BigInt(10), - _20n = BigInt(20), - _40n = BigInt(40), - _80n = BigInt(80) - const P = ED25519_P - const x2 = (x * x) % P - const b2 = (x2 * x) % P // x^3, 11 - const b4 = ((0, modular_js_1.pow2)(b2, _2n, P) * b2) % P // x^15, 1111 - const b5 = ((0, modular_js_1.pow2)(b4, _1n, P) * x) % P // x^31 - const b10 = ((0, modular_js_1.pow2)(b5, _5n, P) * b5) % P - const b20 = ((0, modular_js_1.pow2)(b10, _10n, P) * b10) % P - const b40 = ((0, modular_js_1.pow2)(b20, _20n, P) * b20) % P - const b80 = ((0, modular_js_1.pow2)(b40, _40n, P) * b40) % P - const b160 = ((0, modular_js_1.pow2)(b80, _80n, P) * b80) % P - const b240 = ((0, modular_js_1.pow2)(b160, _80n, P) * b80) % P - const b250 = ((0, modular_js_1.pow2)(b240, _10n, P) * b10) % P - const pow_p_5_8 = ((0, modular_js_1.pow2)(b250, _2n, P) * x) % P - // ^ To pow to (p+3)/8, multiply it by x. - return { pow_p_5_8, b2 } -} -function adjustScalarBytes(bytes) { - // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, - // set the three least significant bits of the first byte - bytes[0] &= 248 // 0b1111_1000 - // and the most significant bit of the last to zero, - bytes[31] &= 127 // 0b0111_1111 - // set the second most significant bit of the last byte to 1 - bytes[31] |= 64 // 0b0100_0000 - return bytes -} -// sqrt(u/v) -function uvRatio(u, v) { - const P = ED25519_P - const v3 = (0, modular_js_1.mod)(v * v * v, P) // v³ - const v7 = (0, modular_js_1.mod)(v3 * v3 * v, P) // v⁷ - // (p+3)/8 and (p-5)/8 - const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 - let x = (0, modular_js_1.mod)(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 - const vx2 = (0, modular_js_1.mod)(v * x * x, P) // vx² - const root1 = x // First root candidate - const root2 = (0, modular_js_1.mod)(x * ED25519_SQRT_M1, P) // Second root candidate - const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root - const useRoot2 = vx2 === (0, modular_js_1.mod)(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) - const noRoot = vx2 === (0, modular_js_1.mod)(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) - if (useRoot1) x = root1 - if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time - if ((0, modular_js_1.isNegativeLE)(x, P)) x = (0, modular_js_1.mod)(-x, P) - return { isValid: useRoot1 || useRoot2, value: x } -} -// Just in case -exports.ED25519_TORSION_SUBGROUP = [ - '0100000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', - '0000000000000000000000000000000000000000000000000000000000000080', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', - 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', - '0000000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', -] -const Fp = /* @__PURE__ */ (() => (0, modular_js_1.Field)(ED25519_P, undefined, true))() -const ed25519Defaults = /* @__PURE__ */ (() => ({ - // Param: a - a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster - // d is equal to -121665/121666 over finite field. - // Negative number is P - number, and division is invert(number, P) - d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), - // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n - Fp, - // Subgroup order: how many points curve has - // 2n**252n + 27742317777372353535851937790883648493n; - n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), - // Cofactor - h: _8n, - // Base point (x, y) aka generator point - Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), - Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), - hash: sha512_1.sha512, - randomBytes: utils_1.randomBytes, - adjustScalarBytes, - // dom2 - // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. - // Constant-time, u/√v - uvRatio, -}))() -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -exports.ed25519 = (() => (0, edwards_js_1.twistedEdwards)(ed25519Defaults))() -function ed25519_domain(data, ctx, phflag) { - if (ctx.length > 255) throw new Error('Context is too big') - return (0, utils_1.concatBytes)( - (0, utils_1.utf8ToBytes)('SigEd25519 no Ed25519 collisions'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) -} -exports.ed25519ctx = (() => - (0, edwards_js_1.twistedEdwards)({ - ...ed25519Defaults, - domain: ed25519_domain, - }))() -exports.ed25519ph = (() => - (0, edwards_js_1.twistedEdwards)( - Object.assign({}, ed25519Defaults, { - domain: ed25519_domain, - prehash: sha512_1.sha512, - }), - ))() -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -exports.x25519 = (() => - (0, montgomery_js_1.montgomery)({ - P: ED25519_P, - a: BigInt(486662), - montgomeryBits: 255, // n is 253 bits - nByteLength: 32, - Gu: BigInt(9), - powPminus2: (x) => { - const P = ED25519_P - // x^(p-2) aka x^(2^255-21) - const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) - return (0, modular_js_1.mod)((0, modular_js_1.pow2)(pow_p_5_8, _3n, P) * b2, P) - }, - adjustScalarBytes, - randomBytes: utils_1.randomBytes, - }))() -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -function edwardsToMontgomeryPub(edwardsPub) { - const { y } = exports.ed25519.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) -} -exports.edwardsToMontgomery = edwardsToMontgomeryPub // deprecated -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -function edwardsToMontgomeryPriv(edwardsPriv) { - const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) - return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) -} -// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) -// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since -// SageMath returns different root first and everything falls apart -const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic -const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 -const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) -// prettier-ignore -function map_to_curve_elligator2_curve25519(u) { - const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic - const ELL2_J = BigInt(486662) - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 - let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not - let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) - let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 - tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 - tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 - tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 - tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 - let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) - y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) - let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 - tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 - tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd - let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 - let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt - let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd - let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u - y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 - let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 - let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) - tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 - tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 - let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt - tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd - let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 - let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) - return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) -} -const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => - (0, modular_js_1.FpSqrtEven)(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 -function map_to_curve_elligator2_edwards25519(u) { - const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = - // map_to_curve_elligator2_curve25519(u) - let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd - xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 - let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM - let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd - let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) - let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd - let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 - xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) - xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) - yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) - yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) - const inv = Fp.invertBatch([xd, yd]) // batch division - return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) -} -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.ed25519.ExtendedPoint, - (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), - { - DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', - encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha512_1.sha512, - }, - ))() -exports.hashToCurve = (() => htf.hashToCurve)() -exports.encodeToCurve = (() => htf.encodeToCurve)() -function assertRstPoint(other) { - if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') -} -// √(-1) aka √(a) aka 2^((p-1)/4) -const SQRT_M1 = ED25519_SQRT_M1 -// √(ad - 1) -const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( - '25063068953384623474111414158702152701244531502492656460079210482610430750235', -) -// 1 / √(a-d) -const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( - '54469307008909316920995813868745141605393597292927456921205312896311721017578', -) -// 1-d² -const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( - '1159843021668779879193775521855586647937357759715417654439879720876111806838', -) -// (d-1)² -const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( - '40440834346308536858101042469323190826248399146238708352240133220865137265952', -) -// Calculates 1/√(number) -const invertSqrt = (number) => uvRatio(_1n, number) -const MAX_255B = /* @__PURE__ */ BigInt( - '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes255ToNumberLE = (bytes) => - exports.ed25519.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_255B) -// Computes Elligator map for Ristretto -// https://ristretto.group/formulas/elligator.html -function calcElligatorRistrettoMap(r0) { - const { d } = exports.ed25519.CURVE - const P = exports.ed25519.CURVE.Fp.ORDER - const mod = exports.ed25519.CURVE.Fp.create - const r = mod(SQRT_M1 * r0 * r0) // 1 - const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 - let c = BigInt(-1) // 3 - const D = mod((c - d * r) * mod(r + d)) // 4 - let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 - let s_ = mod(s * r0) // 6 - if (!(0, modular_js_1.isNegativeLE)(s_, P)) s_ = mod(-s_) - if (!Ns_D_is_sq) s = s_ // 7 - if (!Ns_D_is_sq) c = r // 8 - const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 - const s2 = s * s - const W0 = mod((s + s) * D) // 10 - const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 - const W2 = mod(_1n - s2) // 12 - const W3 = mod(_1n + s2) // 13 - return new exports.ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class RistPoint { - // Private property to discourage combining ExtendedPoint + RistrettoPoint - // Always use Ristretto encoding/decoding instead. - constructor(ep) { - this.ep = ep - } - static fromAffine(ap) { - return new RistPoint(exports.ed25519.ExtendedPoint.fromAffine(ap)) - } - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex) { - hex = (0, utils_js_1.ensureBytes)('ristrettoHash', hex, 64) - const r1 = bytes255ToNumberLE(hex.slice(0, 32)) - const R1 = calcElligatorRistrettoMap(r1) - const r2 = bytes255ToNumberLE(hex.slice(32, 64)) - const R2 = calcElligatorRistrettoMap(r2) - return new RistPoint(R1.add(R2)) - } - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex) { - hex = (0, utils_js_1.ensureBytes)('ristrettoHex', hex, 32) - const { a, d } = exports.ed25519.CURVE - const P = exports.ed25519.CURVE.Fp.ORDER - const mod = exports.ed25519.CURVE.Fp.create - const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' - const s = bytes255ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 3. Check that s is non-negative, or else abort - if ( - !(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 32), hex) || - (0, modular_js_1.isNegativeLE)(s, P) - ) - throw new Error(emsg) - const s2 = mod(s * s) - const u1 = mod(_1n + a * s2) // 4 (a is -1) - const u2 = mod(_1n - a * s2) // 5 - const u1_2 = mod(u1 * u1) - const u2_2 = mod(u2 * u2) - const v = mod(a * d * u1_2 - u2_2) // 6 - const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 - const Dx = mod(I * u2) // 8 - const Dy = mod(I * Dx * v) // 9 - let x = mod((s + s) * Dx) // 10 - if ((0, modular_js_1.isNegativeLE)(x, P)) x = mod(-x) // 10 - const y = mod(u1 * Dy) // 11 - const t = mod(x * y) // 12 - if (!isValid || (0, modular_js_1.isNegativeLE)(t, P) || y === _0n) throw new Error(emsg) - return new RistPoint(new exports.ed25519.ExtendedPoint(x, y, _1n, t)) - } - static msm(points, scalars) { - const Fn = (0, modular_js_1.Field)(exports.ed25519.CURVE.n, exports.ed25519.CURVE.nBitLength) - return (0, curve_js_1.pippenger)(RistPoint, Fn, points, scalars) - } - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes() { - let { ex: x, ey: y, ez: z, et: t } = this.ep - const P = exports.ed25519.CURVE.Fp.ORDER - const mod = exports.ed25519.CURVE.Fp.create - const u1 = mod(mod(z + y) * mod(z - y)) // 1 - const u2 = mod(x * y) // 2 - // Square root always exists - const u2sq = mod(u2 * u2) - const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 - const D1 = mod(invsqrt * u1) // 4 - const D2 = mod(invsqrt * u2) // 5 - const zInv = mod(D1 * D2 * t) // 6 - let D // 7 - if ((0, modular_js_1.isNegativeLE)(t * zInv, P)) { - let _x = mod(y * SQRT_M1) - let _y = mod(x * SQRT_M1) - x = _x - y = _y - D = mod(D1 * INVSQRT_A_MINUS_D) - } else { - D = D2 // 8 - } - if ((0, modular_js_1.isNegativeLE)(x * zInv, P)) y = mod(-y) // 9 - let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) - if ((0, modular_js_1.isNegativeLE)(s, P)) s = mod(-s) - return (0, utils_js_1.numberToBytesLE)(s, 32) // 11 - } - toHex() { - return (0, utils_js_1.bytesToHex)(this.toRawBytes()) - } - toString() { - return this.toHex() - } - // Compare one point to another. - equals(other) { - assertRstPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = exports.ed25519.CURVE.Fp.create - // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) - const one = mod(X1 * Y2) === mod(Y1 * X2) - const two = mod(Y1 * Y2) === mod(X1 * X2) - return one || two - } - add(other) { - assertRstPoint(other) - return new RistPoint(this.ep.add(other.ep)) - } - subtract(other) { - assertRstPoint(other) - return new RistPoint(this.ep.subtract(other.ep)) - } - multiply(scalar) { - return new RistPoint(this.ep.multiply(scalar)) - } - multiplyUnsafe(scalar) { - return new RistPoint(this.ep.multiplyUnsafe(scalar)) - } - double() { - return new RistPoint(this.ep.double()) - } - negate() { - return new RistPoint(this.ep.negate()) - } -} -exports.RistrettoPoint = (() => { - if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(exports.ed25519.ExtendedPoint.BASE) - if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(exports.ed25519.ExtendedPoint.ZERO) - return RistPoint -})() -// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B -const hashToRistretto255 = (msg, options) => { - const d = options.DST - const DST = typeof d === 'string' ? (0, utils_1.utf8ToBytes)(d) : d - const uniform_bytes = (0, hash_to_curve_js_1.expand_message_xmd)(msg, DST, 64, sha512_1.sha512) - const P = RistPoint.hashToCurve(uniform_bytes) - return P -} -exports.hashToRistretto255 = hashToRistretto255 -exports.hash_to_ristretto255 = exports.hashToRistretto255 // legacy -//# sourceMappingURL=ed25519.js.map diff --git a/packages/noble-curves/ed25519.js.map b/packages/noble-curves/ed25519.js.map deleted file mode 100644 index 57fa3ea2c9b..00000000000 --- a/packages/noble-curves/ed25519.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["src/ed25519.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/ed448.d.ts b/packages/noble-curves/ed448.d.ts deleted file mode 100644 index 82ac0fb743e..00000000000 --- a/packages/noble-curves/ed448.d.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { AffinePoint, Group } from './abstract/curve.js' -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' -import { type CurveFn as XCurveFn } from './abstract/montgomery.js' -import { type Hex } from './abstract/utils.js' -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -export declare const ed448: CurveFn -export declare const ed448ph: CurveFn -/** - * ECDH using curve448 aka x448. - */ -export declare const x448: XCurveFn -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -export declare function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array -export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub -export declare const hashToCurve: HTFMethod -export declare const encodeToCurve: HTFMethod -type ExtendedPoint = ExtPointType -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -declare class DcfPoint implements Group { - private readonly ep - static BASE: DcfPoint - static ZERO: DcfPoint - constructor(ep: ExtendedPoint) - static fromAffine(ap: AffinePoint): DcfPoint - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex: Hex): DcfPoint - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex: Hex): DcfPoint - static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes(): Uint8Array - toHex(): string - toString(): string - equals(other: DcfPoint): boolean - add(other: DcfPoint): DcfPoint - subtract(other: DcfPoint): DcfPoint - multiply(scalar: bigint): DcfPoint - multiplyUnsafe(scalar: bigint): DcfPoint - double(): DcfPoint - negate(): DcfPoint -} -export declare const DecafPoint: typeof DcfPoint -export declare const hashToDecaf448: (msg: Uint8Array, options: htfBasicOpts) => DcfPoint -export declare const hash_to_decaf448: typeof hashToDecaf448 -export {} -//# sourceMappingURL=ed448.d.ts.map diff --git a/packages/noble-curves/ed448.d.ts.map b/packages/noble-curves/ed448.d.ts.map deleted file mode 100644 index c8d1f0ab571..00000000000 --- a/packages/noble-curves/ed448.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed448.d.ts","sourceRoot":"","sources":["src/ed448.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AA8G7B;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,EAAE,OAAmD,CAAC;AAExE,eAAO,MAAM,OAAO,EAAE,OAGpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,QAgBZ,CAAC;AAER;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAIlF;AAED,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AA8FzF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AA2B5F,KAAK,aAAa,GAAG,YAAY,CAAC;AAiClC;;;;;;GAMG;AACH,cAAM,QAAS,YAAW,KAAK,CAAC,QAAQ,CAAC;IAK3B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;IACtB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAGO,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,QAAQ;IAIpD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAStC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IA8BlC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ;IAK3D;;;OAGG;IACH,UAAU,IAAI,UAAU;IAoBxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAMlB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAShC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAK9B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIlC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIxC,MAAM,IAAI,QAAQ;IAIlB,MAAM,IAAI,QAAQ;CAGnB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,QAM5B,CAAC;AAGL,eAAO,MAAM,cAAc,QAAS,UAAU,WAAW,YAAY,KAAG,QAMvE,CAAC;AACF,eAAO,MAAM,gBAAgB,EAAE,OAAO,cAA+B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/ed448.js b/packages/noble-curves/ed448.js deleted file mode 100644 index 528f4d47d39..00000000000 --- a/packages/noble-curves/ed448.js +++ /dev/null @@ -1,470 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.hash_to_decaf448 = - exports.hashToDecaf448 = - exports.DecafPoint = - exports.encodeToCurve = - exports.hashToCurve = - exports.edwardsToMontgomery = - exports.x448 = - exports.ed448ph = - exports.ed448 = - void 0 -exports.edwardsToMontgomeryPub = edwardsToMontgomeryPub -/** - * Edwards448 (not Ed448-Goldilocks) curve with following addons: - * - X448 ECDH - * - Decaf cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha3_1 = require('@noble/hashes/sha3') -const utils_1 = require('@noble/hashes/utils') -const curve_js_1 = require('./abstract/curve.js') -const edwards_js_1 = require('./abstract/edwards.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const montgomery_js_1 = require('./abstract/montgomery.js') -const utils_js_1 = require('./abstract/utils.js') -const shake256_114 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 114 })) -const shake256_64 = (0, utils_1.wrapConstructor)(() => sha3_1.shake256.create({ dkLen: 64 })) -const ed448P = BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', -) -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4), - _11n = BigInt(11) -// prettier-ignore -const _22n = BigInt(22), - _44n = BigInt(44), - _88n = BigInt(88), - _223n = BigInt(223) -// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. -// Used for efficient square root calculation. -// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] -function ed448_pow_Pminus3div4(x) { - const P = ed448P - const b2 = (x * x * x) % P - const b3 = (b2 * b2 * x) % P - const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P - const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P - const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P - const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P - const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P - const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P - const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P - const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P - const b222 = ((0, modular_js_1.pow2)(b220, _2n, P) * b2) % P - const b223 = ((0, modular_js_1.pow2)(b222, _1n, P) * x) % P - return ((0, modular_js_1.pow2)(b223, _223n, P) * b222) % P -} -function adjustScalarBytes(bytes) { - // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most - // significant bit of the last byte to 1. - bytes[0] &= 252 // 0b11111100 - // and the most significant bit of the last byte to 1. - bytes[55] |= 128 // 0b10000000 - // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) - bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) - return bytes -} -// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. -// Uses algo from RFC8032 5.1.3. -function uvRatio(u, v) { - const P = ed448P - // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 - // To compute the square root of (u/v), the first step is to compute the - // candidate root x = (u/v)^((p+1)/4). This can be done using the - // following trick, to use a single modular powering for both the - // inversion of v and the square root: - // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) - const u2v = (0, modular_js_1.mod)(u * u * v, P) // u²v - const u3v = (0, modular_js_1.mod)(u2v * u, P) // u³v - const u5v3 = (0, modular_js_1.mod)(u3v * u2v * v, P) // u⁵v³ - const root = ed448_pow_Pminus3div4(u5v3) - const x = (0, modular_js_1.mod)(u3v * root, P) - // Verify that root is exists - const x2 = (0, modular_js_1.mod)(x * x, P) // x² - // If vx² = u, the recovered x-coordinate is x. Otherwise, no - // square root exists, and the decoding fails. - return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x } -} -const Fp = (0, modular_js_1.Field)(ed448P, 456, true) -const ED448_DEF = { - // Param: a - a: BigInt(1), - // -39081. Negative number is P - number - d: BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', - ), - // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n - Fp, - // Subgroup order: how many points curve has; - // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n - n: BigInt( - '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', - ), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - nBitLength: 456, - // Cofactor - h: BigInt(4), - // Base point (x, y) aka generator point - Gx: BigInt( - '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', - ), - Gy: BigInt( - '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', - ), - // SHAKE256(dom4(phflag,context)||x, 114) - hash: shake256_114, - randomBytes: utils_1.randomBytes, - adjustScalarBytes, - // dom4 - domain: (data, ctx, phflag) => { - if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) - return (0, utils_1.concatBytes)( - (0, utils_1.utf8ToBytes)('SigEd448'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) - }, - uvRatio, -} -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF) -// NOTE: there is no ed448ctx, since ed448 supports ctx by default -exports.ed448ph = (0, edwards_js_1.twistedEdwards)({ - ...ED448_DEF, - prehash: shake256_64, -}) -/** - * ECDH using curve448 aka x448. - */ -exports.x448 = (() => - (0, montgomery_js_1.montgomery)({ - a: BigInt(156326), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - montgomeryBits: 448, - nByteLength: 56, - P: ed448P, - Gu: BigInt(5), - powPminus2: (x) => { - const P = ed448P - const Pminus3div4 = ed448_pow_Pminus3div4(x) - const Pminus3 = (0, modular_js_1.pow2)(Pminus3div4, BigInt(2), P) - return (0, modular_js_1.mod)(Pminus3 * x, P) // Pminus3 * x = Pminus2 - }, - adjustScalarBytes, - randomBytes: utils_1.randomBytes, - }))() -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -function edwardsToMontgomeryPub(edwardsPub) { - const { y } = exports.ed448.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) -} -exports.edwardsToMontgomery = edwardsToMontgomeryPub // deprecated -// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version -// Hash To Curve Elligator2 Map -const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic -const ELL2_J = BigInt(156326) -function map_to_curve_elligator2_curve448(u) { - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 - tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 - let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 - let x1n = Fp.neg(ELL2_J) // 5. x1n = -J - let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 - tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd - tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 - let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) - y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) - let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd - let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u - y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) - tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 - let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) - return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) -} -function map_to_curve_elligator2_edwards448(u) { - let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) - let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 - let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 - let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 - let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 - let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 - let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 - let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 - xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 - xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd - xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn - xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 - tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 - tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 - let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 - let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 - tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 - let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 - tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn - let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 - let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 - yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 - yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 - tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 - tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 - tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd - tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 - tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 - let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 - tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 - yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 - tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd - let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 - xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) - xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) - yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) - yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) - const inv = Fp.invertBatch([xEd, yEd]) // batch division - return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) -} -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.ed448.ExtendedPoint, - (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), - { - DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', - encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 224, - expand: 'xof', - hash: sha3_1.shake256, - }, - ))() -exports.hashToCurve = (() => htf.hashToCurve)() -exports.encodeToCurve = (() => htf.encodeToCurve)() -function assertDcfPoint(other) { - if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') -} -// 1-d -const ONE_MINUS_D = BigInt('39082') -// 1-2d -const ONE_MINUS_TWO_D = BigInt('78163') -// √(-d) -const SQRT_MINUS_D = BigInt( - '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', -) -// 1 / √(-d) -const INVSQRT_MINUS_D = BigInt( - '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', -) -// Calculates 1/√(number) -const invertSqrt = (number) => uvRatio(_1n, number) -const MAX_448B = BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes448ToNumberLE = (bytes) => - exports.ed448.CURVE.Fp.create((0, utils_js_1.bytesToNumberLE)(bytes) & MAX_448B) -// Computes Elligator map for Decaf -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 -function calcElligatorDecafMap(r0) { - const { d } = exports.ed448.CURVE - const P = exports.ed448.CURVE.Fp.ORDER - const mod = exports.ed448.CURVE.Fp.create - const r = mod(-(r0 * r0)) // 1 - const u0 = mod(d * (r - _1n)) // 2 - const u1 = mod((u0 + _1n) * (u0 - r)) // 3 - const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 - let v_prime = v // 5 - if (!was_square) v_prime = mod(r0 * v) - let sgn = _1n // 6 - if (!was_square) sgn = mod(-_1n) - const s = mod(v_prime * (r + _1n)) // 7 - let s_abs = s - if ((0, modular_js_1.isNegativeLE)(s, P)) s_abs = mod(-s) - const s2 = s * s - const W0 = mod(s_abs * _2n) // 8 - const W1 = mod(s2 + _1n) // 9 - const W2 = mod(s2 - _1n) // 10 - const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 - return new exports.ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class DcfPoint { - // Private property to discourage combining ExtendedPoint + DecafPoint - // Always use Decaf encoding/decoding instead. - constructor(ep) { - this.ep = ep - } - static fromAffine(ap) { - return new DcfPoint(exports.ed448.ExtendedPoint.fromAffine(ap)) - } - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex) { - hex = (0, utils_js_1.ensureBytes)('decafHash', hex, 112) - const r1 = bytes448ToNumberLE(hex.slice(0, 56)) - const R1 = calcElligatorDecafMap(r1) - const r2 = bytes448ToNumberLE(hex.slice(56, 112)) - const R2 = calcElligatorDecafMap(r2) - return new DcfPoint(R1.add(R2)) - } - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex) { - hex = (0, utils_js_1.ensureBytes)('decafHex', hex, 56) - const { d } = exports.ed448.CURVE - const P = exports.ed448.CURVE.Fp.ORDER - const mod = exports.ed448.CURVE.Fp.create - const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' - const s = bytes448ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 2. Check that s is non-negative, or else abort - if ( - !(0, utils_js_1.equalBytes)((0, utils_js_1.numberToBytesLE)(s, 56), hex) || - (0, modular_js_1.isNegativeLE)(s, P) - ) - throw new Error(emsg) - const s2 = mod(s * s) // 1 - const u1 = mod(_1n + s2) // 2 - const u1sq = mod(u1 * u1) - const u2 = mod(u1sq - _4n * d * s2) // 3 - const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 - let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 - if ((0, modular_js_1.isNegativeLE)(u3, P)) u3 = mod(-u3) - const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 - const y = mod((_1n - s2) * invsqrt * u1) // 7 - const t = mod(x * y) // 8 - if (!isValid) throw new Error(emsg) - return new DcfPoint(new exports.ed448.ExtendedPoint(x, y, _1n, t)) - } - static msm(points, scalars) { - const Fn = (0, modular_js_1.Field)(exports.ed448.CURVE.n, exports.ed448.CURVE.nBitLength) - return (0, curve_js_1.pippenger)(DcfPoint, Fn, points, scalars) - } - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes() { - let { ex: x, ey: _y, ez: z, et: t } = this.ep - const P = exports.ed448.CURVE.Fp.ORDER - const mod = exports.ed448.CURVE.Fp.create - const u1 = mod(mod(x + t) * mod(x - t)) // 1 - const x2 = mod(x * x) - const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 - let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 - if ((0, modular_js_1.isNegativeLE)(ratio, P)) ratio = mod(-ratio) - const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 - let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 - if ((0, modular_js_1.isNegativeLE)(s, P)) s = mod(-s) - return (0, utils_js_1.numberToBytesLE)(s, 56) - } - toHex() { - return (0, utils_js_1.bytesToHex)(this.toRawBytes()) - } - toString() { - return this.toHex() - } - // Compare one point to another. - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 - equals(other) { - assertDcfPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = exports.ed448.CURVE.Fp.create - // (x1 * y2 == y1 * x2) - return mod(X1 * Y2) === mod(Y1 * X2) - } - add(other) { - assertDcfPoint(other) - return new DcfPoint(this.ep.add(other.ep)) - } - subtract(other) { - assertDcfPoint(other) - return new DcfPoint(this.ep.subtract(other.ep)) - } - multiply(scalar) { - return new DcfPoint(this.ep.multiply(scalar)) - } - multiplyUnsafe(scalar) { - return new DcfPoint(this.ep.multiplyUnsafe(scalar)) - } - double() { - return new DcfPoint(this.ep.double()) - } - negate() { - return new DcfPoint(this.ep.negate()) - } -} -exports.DecafPoint = (() => { - // decaf448 base point is ed448 base x 2 - // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 - if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(exports.ed448.ExtendedPoint.BASE).multiply(_2n) - if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(exports.ed448.ExtendedPoint.ZERO) - return DcfPoint -})() -// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C -const hashToDecaf448 = (msg, options) => { - const d = options.DST - const DST = typeof d === 'string' ? (0, utils_1.utf8ToBytes)(d) : d - const uniform_bytes = (0, hash_to_curve_js_1.expand_message_xof)( - msg, - DST, - 112, - 224, - sha3_1.shake256, - ) - const P = DcfPoint.hashToCurve(uniform_bytes) - return P -} -exports.hashToDecaf448 = hashToDecaf448 -exports.hash_to_decaf448 = exports.hashToDecaf448 // legacy -//# sourceMappingURL=ed448.js.map diff --git a/packages/noble-curves/ed448.js.map b/packages/noble-curves/ed448.js.map deleted file mode 100644 index 75d39454acb..00000000000 --- a/packages/noble-curves/ed448.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed448.js","sourceRoot":"","sources":["src/ed448.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/_shortw_utils.d.ts b/packages/noble-curves/esm/_shortw_utils.d.ts deleted file mode 100644 index 02064fbb558..00000000000 --- a/packages/noble-curves/esm/_shortw_utils.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { randomBytes } from '@noble/hashes/utils' -import type { CHash } from './abstract/utils.js' -import { type CurveFn, type CurveType } from './abstract/weierstrass.js' -/** connects noble-curves to noble-hashes */ -export declare function getHash(hash: CHash): { - hash: CHash - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array - randomBytes: typeof randomBytes -} -/** Same API as @noble/hashes, with ability to create curve with custom hash */ -export type CurveDef = Readonly> -export type CurveFnWithCreate = CurveFn & { - create: (hash: CHash) => CurveFn -} -export declare function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate -//# sourceMappingURL=_shortw_utils.d.ts.map diff --git a/packages/noble-curves/esm/_shortw_utils.d.ts.map b/packages/noble-curves/esm/_shortw_utils.d.ts.map deleted file mode 100644 index aed6a3c4299..00000000000 --- a/packages/noble-curves/esm/_shortw_utils.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"_shortw_utils.d.ts","sourceRoot":"","sources":["../src/_shortw_utils.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG;IACpC,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,KAAK,UAAU,CAAC;IAC7D,WAAW,EAAE,OAAO,WAAW,CAAC;CACjC,CAMA;AACD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAA;CAAE,CAAC;AAE/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,GAAG,iBAAiB,CAGjF"} \ No newline at end of file diff --git a/packages/noble-curves/esm/_shortw_utils.js b/packages/noble-curves/esm/_shortw_utils.js deleted file mode 100644 index c32dd38a6dc..00000000000 --- a/packages/noble-curves/esm/_shortw_utils.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Utilities for short weierstrass curves, combined with noble-hashes. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { hmac } from '@noble/hashes/hmac' -import { concatBytes, randomBytes } from '@noble/hashes/utils' -import { weierstrass } from './abstract/weierstrass.js' -/** connects noble-curves to noble-hashes */ -export function getHash(hash) { - return { - hash, - hmac: (key, ...msgs) => hmac(hash, key, concatBytes(...msgs)), - randomBytes, - } -} -export function createCurve(curveDef, defHash) { - const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) }) - return { ...create(defHash), create } -} -//# sourceMappingURL=_shortw_utils.js.map diff --git a/packages/noble-curves/esm/_shortw_utils.js.map b/packages/noble-curves/esm/_shortw_utils.js.map deleted file mode 100644 index 0f19fb0873e..00000000000 --- a/packages/noble-curves/esm/_shortw_utils.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"_shortw_utils.js","sourceRoot":"","sources":["../src/_shortw_utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAgC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEtF,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,IAAW;IAKjC,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,CAAC,GAAe,EAAE,GAAG,IAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;QACvF,WAAW;KACZ,CAAC;AACJ,CAAC;AAKD,MAAM,UAAU,WAAW,CAAC,QAAkB,EAAE,OAAc;IAC5D,MAAM,MAAM,GAAG,CAAC,IAAW,EAAW,EAAE,CAAC,WAAW,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;AACxC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/bls.d.ts b/packages/noble-curves/esm/abstract/bls.d.ts deleted file mode 100644 index cc7aae5e409..00000000000 --- a/packages/noble-curves/esm/abstract/bls.d.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { - type Opts as HTFOpts, - type MapToCurve, - createHasher, - type htfBasicOpts, -} from './hash-to-curve.js' -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' -import { type CHash, type Hex, type PrivKey } from './utils.js' -import { type CurvePointsRes, type CurvePointsType, type ProjPointType } from './weierstrass.js' -type Fp = bigint -export type TwistType = 'multiplicative' | 'divisive' -export type ShortSignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} -export type SignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} -export type PostPrecomputePointAddFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, -) => { - Rx: Fp2 - Ry: Fp2 - Rz: Fp2 -} -export type PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => void -export type CurveType = { - G1: Omit, 'n'> & { - ShortSignature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - G2: Omit, 'n'> & { - Signature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - fields: { - Fp: IField - Fr: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - } - params: { - ateLoopSize: bigint - xNegative: boolean - r: bigint - twistType: TwistType - } - htfDefaults: HTFOpts - hash: CHash - randomBytes: (bytesLength?: number) => Uint8Array - postPrecompute?: PostPrecomputeFn -} -type PrecomputeSingle = [Fp2, Fp2, Fp2][] -type Precompute = PrecomputeSingle[] -export type CurveFn = { - getPublicKey: (privateKey: PrivKey) => Uint8Array - getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array - sign: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - signShortSignature: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - verify: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyShortSignature: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyBatch: ( - signature: Hex | ProjPointType, - messages: (Hex | ProjPointType)[], - publicKeys: (Hex | ProjPointType)[], - htfOpts?: htfBasicOpts, - ) => boolean - aggregatePublicKeys: { - (publicKeys: Hex[]): Uint8Array - (publicKeys: ProjPointType[]): ProjPointType - } - aggregateSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - aggregateShortSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 - pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 - pairingBatch: ( - pairs: { - g1: ProjPointType - g2: ProjPointType - }[], - withFinalExponent?: boolean, - ) => Fp12 - G1: CurvePointsRes & ReturnType> - G2: CurvePointsRes & ReturnType> - Signature: SignatureCoder - ShortSignature: ShortSignatureCoder - params: { - ateLoopSize: bigint - r: bigint - G1b: bigint - G2b: Fp2 - } - fields: { - Fp: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - Fr: IField - } - utils: { - randomPrivateKey: () => Uint8Array - calcPairingPrecomputes: (p: ProjPointType) => Precompute - } -} -export declare function bls(CURVE: CurveType): CurveFn -export {} -//# sourceMappingURL=bls.d.ts.map diff --git a/packages/noble-curves/esm/abstract/bls.d.ts.map b/packages/noble-curves/esm/abstract/bls.d.ts.map deleted file mode 100644 index 5b282a96635..00000000000 --- a/packages/noble-curves/esm/abstract/bls.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls.d.ts","sourceRoot":"","sources":["../../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/bls.js b/packages/noble-curves/esm/abstract/bls.js deleted file mode 100644 index a132739adce..00000000000 --- a/packages/noble-curves/esm/abstract/bls.js +++ /dev/null @@ -1,357 +0,0 @@ -// prettier-ignore -import { createHasher } from './hash-to-curve.js' -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// TODO: import { AffinePoint } from './curve.js'; -import { getMinHashLength, mapHashToField } from './modular.js' -import { ensureBytes, memoized } from './utils.js' -import { weierstrassPoints } from './weierstrass.js' -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. -function NAfDecomposition(a) { - const res = [] - // a>1 because of marker bit - for (; a > _1n; a >>= _1n) { - if ((a & _1n) === _0n) res.unshift(0) - else if ((a & _3n) === _3n) { - res.unshift(-1) - a += _1n - } else res.unshift(1) - } - return res -} -export function bls(CURVE) { - // Fields are specific for curve, so for now we'll need to pass them with opts - const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields - const BLS_X_IS_NEGATIVE = CURVE.params.xNegative - const TWIST = CURVE.params.twistType - // Point on G1 curve: (x, y) - const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) - const G1 = Object.assign( - G1_, - createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G1.htfDefaults, - }), - ) - // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) - const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) - const G2 = Object.assign( - G2_, - createHasher(G2_.ProjectivePoint, CURVE.G2.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G2.htfDefaults, - }), - ) - // Applies sparse multiplication as line function - let lineFunction - if (TWIST === 'multiplicative') { - lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) - } else if (TWIST === 'divisive') { - // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of - // precompute calculations. - lineFunction = (c0, c1, c2, f, Px, Py) => Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) - } else throw new Error('bls: unknown twist type') - const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) - function pointDouble(ell, Rx, Ry, Rz) { - const t0 = Fp2.sqr(Ry) // Ry² - const t1 = Fp2.sqr(Rz) // Rz² - const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B - const t3 = Fp2.mul(t2, _3n) // 3 * T2 - const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 - const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) - const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² - const c2 = Fp2.neg(t4) // -T4 (-h) - ell.push([c0, c1, c2]) - Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 - Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² - Rz = Fp2.mul(t0, t4) // T0 * T4 - return { Rx, Ry, Rz } - } - function pointAdd(ell, Rx, Ry, Rz, Qx, Qy) { - // Addition - const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz - const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz - const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy - const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry - const c2 = t1 // == Rx - Qx * Rz - ell.push([c0, c1, c2]) - const t2 = Fp2.sqr(t1) // T1² - const t3 = Fp2.mul(t2, t1) // T2 * T1 - const t4 = Fp2.mul(t2, Rx) // T2 * Rx - const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz - Rx = Fp2.mul(t1, t5) // T1 * T5 - Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry - Rz = Fp2.mul(Rz, t3) // Rz * T3 - return { Rx, Ry, Rz } - } - // Pre-compute coefficients for sparse multiplication - // Point addition and point double calculations is reused for coefficients - // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine - // add + double in windowed precomputes here, otherwise it would be single op (since X is static) - const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) - const calcPairingPrecomputes = memoized((point) => { - const p = point - const { x, y } = p.toAffine() - // prettier-ignore - const Qx = x, - Qy = y, - negQy = Fp2.neg(y) - // prettier-ignore - let Rx = Qx, - Ry = Qy, - Rz = Fp2.ONE - const ell = [] - for (const bit of ATE_NAF) { - const cur = [] - ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) - if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) - ell.push(cur) - } - if (CURVE.postPrecompute) { - const last = ell[ell.length - 1] - CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) - } - return ell - }) - function millerLoopBatch(pairs, withFinalExponent = false) { - let f12 = Fp12.ONE - if (pairs.length) { - const ellLen = pairs[0][0].length - for (let i = 0; i < ellLen; i++) { - f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings - // NOTE: we apply multiple pairings in parallel here - for (const [ell, Px, Py] of pairs) { - for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) - } - } - } - if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) - return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 - } - // Calculates product of multiple pairings - // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` - function pairingBatch(pairs, withFinalExponent = true) { - const res = [] - // This cache precomputed toAffine for all points - G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) - G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) - for (const { g1, g2 } of pairs) { - if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) - throw new Error('pairing is not available for ZERO point') - // This uses toAffine inside - g1.assertValidity() - g2.assertValidity() - const Qa = g1.toAffine() - res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) - } - return millerLoopBatch(res, withFinalExponent) - } - // Calculates bilinear pairing - function pairing(Q, P, withFinalExponent = true) { - return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) - } - const utils = { - randomPrivateKey: () => { - const length = getMinHashLength(Fr.ORDER) - return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) - }, - calcPairingPrecomputes, - } - const { ShortSignature } = CURVE.G1 - const { Signature } = CURVE.G2 - function normP1(point) { - return point instanceof G1.ProjectivePoint ? point : G1.ProjectivePoint.fromHex(point) - } - function normP1Hash(point, htfOpts) { - return point instanceof G1.ProjectivePoint - ? point - : G1.hashToCurve(ensureBytes('point', point), htfOpts) - } - function normP2(point) { - return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) - } - function normP2Hash(point, htfOpts) { - return point instanceof G2.ProjectivePoint - ? point - : G2.hashToCurve(ensureBytes('point', point), htfOpts) - } - // Multiplies generator (G1) by private key. - // P = pk x G - function getPublicKey(privateKey) { - return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - // Multiplies generator (G2) by private key. - // P = pk x G - function getPublicKeyForShortSignatures(privateKey) { - return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - function sign(message, privateKey, htfOpts) { - const msgPoint = normP2Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G2.ProjectivePoint) return sigPoint - return Signature.toRawBytes(sigPoint) - } - function signShortSignature(message, privateKey, htfOpts) { - const msgPoint = normP1Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G1.ProjectivePoint) return sigPoint - return ShortSignature.toRawBytes(sigPoint) - } - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(P, H(m)) == e(G, S) - function verify(signature, message, publicKey, htfOpts) { - const P = normP1(publicKey) - const Hm = normP2Hash(message, htfOpts) - const G = G1.ProjectivePoint.BASE - const S = normP2(signature) - const exp = pairingBatch([ - { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); - { g1: G, g2: S }, // eGS = pairing(G, S, false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(S, G) == e(H(m), P) - function verifyShortSignature(signature, message, publicKey, htfOpts) { - const P = normP2(publicKey) - const Hm = normP1Hash(message, htfOpts) - const G = G2.ProjectivePoint.BASE - const S = normP1(signature) - const exp = pairingBatch([ - { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); - { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - function aNonEmpty(arr) { - if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') - } - function aggregatePublicKeys(publicKeys) { - aNonEmpty(publicKeys) - const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (publicKeys[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - // toRawBytes ensures point validity - return aggAffine.toRawBytes(true) - } - function aggregateSignatures(signatures) { - aNonEmpty(signatures) - const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G2.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return Signature.toRawBytes(aggAffine) - } - function aggregateShortSignatures(signatures) { - aNonEmpty(signatures) - const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return ShortSignature.toRawBytes(aggAffine) - } - // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 - // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) - function verifyBatch( - signature, - // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? - messages, - publicKeys, - htfOpts, - ) { - aNonEmpty(messages) - if (publicKeys.length !== messages.length) - throw new Error('amount of public keys and messages should be equal') - const sig = normP2(signature) - const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) - const nPublicKeys = publicKeys.map(normP1) - // NOTE: this works only for exact same object - const messagePubKeyMap = new Map() - for (let i = 0; i < nPublicKeys.length; i++) { - const pub = nPublicKeys[i] - const msg = nMessages[i] - let keys = messagePubKeyMap.get(msg) - if (keys === undefined) { - keys = [] - messagePubKeyMap.set(msg, keys) - } - keys.push(pub) - } - const paired = [] - try { - for (const [msg, keys] of messagePubKeyMap) { - const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) - paired.push({ g1: groupPublicKey, g2: msg }) - } - paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) - return Fp12.eql(pairingBatch(paired), Fp12.ONE) - } catch { - return false - } - } - G1.ProjectivePoint.BASE._setWindowSize(4) - return { - getPublicKey, - getPublicKeyForShortSignatures, - sign, - signShortSignature, - verify, - verifyBatch, - verifyShortSignature, - aggregatePublicKeys, - aggregateSignatures, - aggregateShortSignatures, - millerLoopBatch, - pairing, - pairingBatch, - G1, - G2, - Signature, - ShortSignature, - fields: { - Fr, - Fp, - Fp2, - Fp6, - Fp12, - }, - params: { - ateLoopSize: CURVE.params.ateLoopSize, - r: CURVE.params.r, - G1b: CURVE.G1.b, - G2b: CURVE.G2.b, - }, - utils, - } -} -//# sourceMappingURL=bls.js.map diff --git a/packages/noble-curves/esm/abstract/bls.js.map b/packages/noble-curves/esm/abstract/bls.js.map deleted file mode 100644 index 334a1bed9ff..00000000000 --- a/packages/noble-curves/esm/abstract/bls.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls.js","sourceRoot":"","sources":["../../src/abstract/bls.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/curve.d.ts b/packages/noble-curves/esm/abstract/curve.d.ts deleted file mode 100644 index b4984cb067f..00000000000 --- a/packages/noble-curves/esm/abstract/curve.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -export type AffinePoint = { - x: T - y: T -} & { - z?: never - t?: never -} -export interface Group> { - double(): T - negate(): T - add(other: T): T - subtract(other: T): T - equals(other: T): boolean - multiply(scalar: bigint): T -} -export type GroupConstructor = { - BASE: T - ZERO: T -} -export type Mapper = (i: T[]) => T[] -export type IWNAF> = { - constTimeNegate: >(condition: boolean, item: T) => T - hasPrecomputes(elm: T): boolean - unsafeLadder(elm: T, n: bigint, p?: T): T - precomputeWindow(elm: T, W: number): Group[] - wNAF( - W: number, - precomputes: T[], - n: bigint, - ): { - p: T - f: T - } - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T - getPrecomputes(W: number, P: T, transform: Mapper): T[] - wNAFCached( - P: T, - n: bigint, - transform: Mapper, - ): { - p: T - f: T - } - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T - setWindowSize(P: T, W: number): void -} -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -export declare function wNAF>(c: GroupConstructor, bits: number): IWNAF -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster with precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -export declare function pippenger>( - c: GroupConstructor, - fieldN: IField, - points: T[], - scalars: bigint[], -): T -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -export declare function precomputeMSMUnsafe>( - c: GroupConstructor, - fieldN: IField, - points: T[], - windowSize: number, -): (scalars: bigint[]) => T -/** - * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. - * Though generator can be different (Fp2 / Fp6 for BLS). - */ -export type BasicCurve = { - Fp: IField - n: bigint - nBitLength?: number - nByteLength?: number - h: bigint - hEff?: bigint - Gx: T - Gy: T - allowInfinityPoint?: boolean -} -export declare function validateBasic( - curve: BasicCurve & T, -): Readonly< - { - readonly nBitLength: number - readonly nByteLength: number - } & BasicCurve & - T & { - p: bigint - } -> -//# sourceMappingURL=curve.d.ts.map diff --git a/packages/noble-curves/esm/abstract/curve.d.ts.map b/packages/noble-curves/esm/abstract/curve.d.ts.map deleted file mode 100644 index 0f2da30ccc0..00000000000 --- a/packages/noble-curves/esm/abstract/curve.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"curve.d.ts","sourceRoot":"","sources":["../../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/curve.js b/packages/noble-curves/esm/abstract/curve.js deleted file mode 100644 index c59b639eafc..00000000000 --- a/packages/noble-curves/esm/abstract/curve.js +++ /dev/null @@ -1,362 +0,0 @@ -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { nLength, validateField } from './modular.js' -import { bitLen, validateObject } from './utils.js' -const _0n = BigInt(0) -const _1n = BigInt(1) -function constTimeNegate(condition, item) { - const neg = item.negate() - return condition ? neg : item -} -function validateW(W, bits) { - if (!Number.isSafeInteger(W) || W <= 0 || W > bits) - throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) -} -function calcWOpts(W, bits) { - validateW(W, bits) - const windows = Math.ceil(bits / W) + 1 // +1, because - const windowSize = 2 ** (W - 1) // -1 because we skip zero - return { windows, windowSize } -} -function validateMSMPoints(points, c) { - if (!Array.isArray(points)) throw new Error('array expected') - points.forEach((p, i) => { - if (!(p instanceof c)) throw new Error('invalid point at index ' + i) - }) -} -function validateMSMScalars(scalars, field) { - if (!Array.isArray(scalars)) throw new Error('array of scalars expected') - scalars.forEach((s, i) => { - if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) - }) -} -// Since points in different groups cannot be equal (different object constructor), -// we can have single place to store precomputes -const pointPrecomputes = new WeakMap() -const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) -function getW(P) { - return pointWindowSizes.get(P) || 1 -} -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -export function wNAF(c, bits) { - return { - constTimeNegate, - hasPrecomputes(elm) { - return getW(elm) !== 1 - }, - // non-const time multiplication ladder - unsafeLadder(elm, n, p = c.ZERO) { - let d = elm - while (n > _0n) { - if (n & _1n) p = p.add(d) - d = d.double() - n >>= _1n - } - return p - }, - /** - * Creates a wNAF precomputation window. Used for caching. - * Default window size is set by `utils.precompute()` and is equal to 8. - * Number of precomputed points depends on the curve size: - * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: - * - 𝑊 is the window size - * - 𝑛 is the bitlength of the curve order. - * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. - * @param elm Point instance - * @param W window size - * @returns precomputed point tables flattened to a single array - */ - precomputeWindow(elm, W) { - const { windows, windowSize } = calcWOpts(W, bits) - const points = [] - let p = elm - let base = p - for (let window = 0; window < windows; window++) { - base = p - points.push(base) - // =1, because we skip zero - for (let i = 1; i < windowSize; i++) { - base = base.add(p) - points.push(base) - } - p = base.double() - } - return points - }, - /** - * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @returns real and fake (for const-time) points - */ - wNAF(W, precomputes, n) { - // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise - // But need to carefully remove other checks before wNAF. ORDER == bits here - const { windows, windowSize } = calcWOpts(W, bits) - let p = c.ZERO - let f = c.BASE - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - // Extract W bits. - let wbits = Number(n & mask) - // Shift number by W bits. - n >>= shiftBy - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - // This code was first written with assumption that 'f' and 'p' will never be infinity point: - // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, - // there is negate now: it is possible that negated element from low value - // would be the same as high element, which will create carry into next window. - // It's not obvious how this can fail, but still worth investigating later. - // Check if we're onto Zero point. - // Add random point inside current window to f. - const offset1 = offset - const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero - const cond1 = window % 2 !== 0 - const cond2 = wbits < 0 - if (wbits === 0) { - // The most important part for const-time getPublicKey - f = f.add(constTimeNegate(cond1, precomputes[offset1])) - } else { - p = p.add(constTimeNegate(cond2, precomputes[offset2])) - } - } - // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() - // Even if the variable is still unused, there are some checks which will - // throw an exception, so compiler needs to prove they won't happen, which is hard. - // At this point there is a way to F be infinity-point even if p is not, - // which makes it less const-time: around 1 bigint multiply. - return { p, f } - }, - /** - * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @param acc accumulator point to add result of multiplication - * @returns point - */ - wNAFUnsafe(W, precomputes, n, acc = c.ZERO) { - const { windows, windowSize } = calcWOpts(W, bits) - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - if (n === _0n) break // No need to go over empty scalar - // Extract W bits. - let wbits = Number(n & mask) - // Shift number by W bits. - n >>= shiftBy - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - if (wbits === 0) continue - let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero - if (wbits < 0) curr = curr.negate() - // NOTE: by re-using acc, we can save a lot of additions in case of MSM - acc = acc.add(curr) - } - return acc - }, - getPrecomputes(W, P, transform) { - // Calculate precomputes on a first run, reuse them after - let comp = pointPrecomputes.get(P) - if (!comp) { - comp = this.precomputeWindow(P, W) - if (W !== 1) pointPrecomputes.set(P, transform(comp)) - } - return comp - }, - wNAFCached(P, n, transform) { - const W = getW(P) - return this.wNAF(W, this.getPrecomputes(W, P, transform), n) - }, - wNAFCachedUnsafe(P, n, transform, prev) { - const W = getW(P) - if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster - return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) - }, - // We calculate precomputes for elliptic curve point multiplication - // using windowed method. This specifies window size and - // stores precomputed values. Usually only base point would be precomputed. - setWindowSize(P, W) { - validateW(W, bits) - pointWindowSizes.set(P, W) - pointPrecomputes.delete(P) - }, - } -} -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster with precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -export function pippenger(c, fieldN, points, scalars) { - // If we split scalars by some window (let's say 8 bits), every chunk will only - // take 256 buckets even if there are 4096 scalars, also re-uses double. - // TODO: - // - https://eprint.iacr.org/2024/750.pdf - // - https://tches.iacr.org/index.php/TCHES/article/view/10287 - // 0 is accepted in scalars - validateMSMPoints(points, c) - validateMSMScalars(scalars, fieldN) - if (points.length !== scalars.length) - throw new Error('arrays of points and scalars must have equal length') - const zero = c.ZERO - const wbits = bitLen(BigInt(points.length)) - const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits - const MASK = (1 << windowSize) - 1 - const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array - const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize - let sum = zero - for (let i = lastBits; i >= 0; i -= windowSize) { - buckets.fill(zero) - for (let j = 0; j < scalars.length; j++) { - const scalar = scalars[j] - const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) - buckets[wbits] = buckets[wbits].add(points[j]) - } - let resI = zero // not using this will do small speed-up, but will lose ct - // Skip first bucket, because it is zero - for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { - sumI = sumI.add(buckets[j]) - resI = resI.add(sumI) - } - sum = sum.add(resI) - if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() - } - return sum -} -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -export function precomputeMSMUnsafe(c, fieldN, points, windowSize) { - /** - * Performance Analysis of Window-based Precomputation - * - * Base Case (256-bit scalar, 8-bit window): - * - Standard precomputation requires: - * - 31 additions per scalar × 256 scalars = 7,936 ops - * - Plus 255 summary additions = 8,191 total ops - * Note: Summary additions can be optimized via accumulator - * - * Chunked Precomputation Analysis: - * - Using 32 chunks requires: - * - 255 additions per chunk - * - 256 doublings - * - Total: (255 × 32) + 256 = 8,416 ops - * - * Memory Usage Comparison: - * Window Size | Standard Points | Chunked Points - * ------------|-----------------|--------------- - * 4-bit | 520 | 15 - * 8-bit | 4,224 | 255 - * 10-bit | 13,824 | 1,023 - * 16-bit | 557,056 | 65,535 - * - * Key Advantages: - * 1. Enables larger window sizes due to reduced memory overhead - * 2. More efficient for smaller scalar counts: - * - 16 chunks: (16 × 255) + 256 = 4,336 ops - * - ~2x faster than standard 8,191 ops - * - * Limitations: - * - Not suitable for plain precomputes (requires 256 constant doublings) - * - Performance degrades with larger scalar counts: - * - Optimal for ~256 scalars - * - Less efficient for 4096+ scalars (Pippenger preferred) - */ - validateW(windowSize, fieldN.BITS) - validateMSMPoints(points, c) - const zero = c.ZERO - const tableSize = 2 ** windowSize - 1 // table size (without zero) - const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item - const MASK = BigInt((1 << windowSize) - 1) - const tables = points.map((p) => { - const res = [] - for (let i = 0, acc = p; i < tableSize; i++) { - res.push(acc) - acc = acc.add(p) - } - return res - }) - return (scalars) => { - validateMSMScalars(scalars, fieldN) - if (scalars.length > points.length) - throw new Error('array of scalars must be smaller than array of points') - let res = zero - for (let i = 0; i < chunks; i++) { - // No need to double if accumulator is still zero. - if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() - const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) - for (let j = 0; j < scalars.length; j++) { - const n = scalars[j] - const curr = Number((n >> shiftBy) & MASK) - if (!curr) continue // skip zero scalars chunks - res = res.add(tables[j][curr - 1]) - } - } - return res - } -} -export function validateBasic(curve) { - validateField(curve.Fp) - validateObject( - curve, - { - n: 'bigint', - h: 'bigint', - Gx: 'field', - Gy: 'field', - }, - { - nBitLength: 'isSafeInteger', - nByteLength: 'isSafeInteger', - }, - ) - // Set defaults - return Object.freeze({ - ...nLength(curve.n, curve.nBitLength), - ...curve, - ...{ p: curve.Fp.ORDER }, - }) -} -//# sourceMappingURL=curve.js.map diff --git a/packages/noble-curves/esm/abstract/curve.js.map b/packages/noble-curves/esm/abstract/curve.js.map deleted file mode 100644 index 09e01508f2d..00000000000 --- a/packages/noble-curves/esm/abstract/curve.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"curve.js","sourceRoot":"","sources":["../../src/abstract/curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/edwards.d.ts b/packages/noble-curves/esm/abstract/edwards.d.ts deleted file mode 100644 index cfd6867cfb1..00000000000 --- a/packages/noble-curves/esm/abstract/edwards.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' -import { type FHash, type Hex } from './utils.js' -/** Edwards curves must declare params a & d. */ -export type CurveType = BasicCurve & { - a: bigint - d: bigint - hash: FHash - randomBytes: (bytesLength?: number) => Uint8Array - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - uvRatio?: ( - u: bigint, - v: bigint, - ) => { - isValid: boolean - value: bigint - } - prehash?: FHash - mapToCurve?: (scalar: bigint[]) => AffinePoint -} -export type CurveTypeWithLength = Readonly< - CurveType & { - nByteLength: number - nBitLength: number - } -> -declare function validateOpts(curve: CurveType): CurveTypeWithLength -/** Instance of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointType extends Group { - readonly ex: bigint - readonly ey: bigint - readonly ez: bigint - readonly et: bigint - get x(): bigint - get y(): bigint - assertValidity(): void - multiply(scalar: bigint): ExtPointType - multiplyUnsafe(scalar: bigint): ExtPointType - isSmallOrder(): boolean - isTorsionFree(): boolean - clearCofactor(): ExtPointType - toAffine(iz?: bigint): AffinePoint - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - _setWindowSize(windowSize: number): void -} -/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointConstructor extends GroupConstructor { - new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType - fromAffine(p: AffinePoint): ExtPointType - fromHex(hex: Hex): ExtPointType - fromPrivateKey(privateKey: Hex): ExtPointType - msm(points: ExtPointType[], scalars: bigint[]): ExtPointType -} -/** - * Edwards Curve interface. - * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. - */ -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: Hex) => Uint8Array - sign: ( - message: Hex, - privateKey: Hex, - options?: { - context?: Hex - }, - ) => Uint8Array - verify: ( - sig: Hex, - message: Hex, - publicKey: Hex, - options?: { - context?: Hex - zip215: boolean - }, - ) => boolean - ExtendedPoint: ExtPointConstructor - utils: { - randomPrivateKey: () => Uint8Array - getExtendedPublicKey: (key: Hex) => { - head: Uint8Array - prefix: Uint8Array - scalar: bigint - point: ExtPointType - pointBytes: Uint8Array - } - precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType - } -} -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -export declare function twistedEdwards(curveDef: CurveType): CurveFn -export {} -//# sourceMappingURL=edwards.d.ts.map diff --git a/packages/noble-curves/esm/abstract/edwards.d.ts.map b/packages/noble-curves/esm/abstract/edwards.d.ts.map deleted file mode 100644 index 7ba0ffa6390..00000000000 --- a/packages/noble-curves/esm/abstract/edwards.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"edwards.d.ts","sourceRoot":"","sources":["../../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/edwards.js b/packages/noble-curves/esm/abstract/edwards.js deleted file mode 100644 index 552735b0ecf..00000000000 --- a/packages/noble-curves/esm/abstract/edwards.js +++ /dev/null @@ -1,445 +0,0 @@ -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { pippenger, validateBasic, wNAF } from './curve.js' -import { Field, mod } from './modular.js' -import * as ut from './utils.js' -import { abool, ensureBytes, memoized } from './utils.js' -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _8n = BigInt(8) -// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: -const VERIFY_DEFAULT = { zip215: true } -function validateOpts(curve) { - const opts = validateBasic(curve) - ut.validateObject( - curve, - { - hash: 'function', - a: 'bigint', - d: 'bigint', - randomBytes: 'function', - }, - { - adjustScalarBytes: 'function', - domain: 'function', - uvRatio: 'function', - mapToCurve: 'function', - }, - ) - // Set defaults - return Object.freeze({ ...opts }) -} -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -export function twistedEdwards(curveDef) { - const CURVE = validateOpts(curveDef) - const { - Fp, - n: CURVE_ORDER, - prehash: prehash, - hash: cHash, - randomBytes, - nByteLength, - h: cofactor, - } = CURVE - // Important: - // There are some places where Fp.BYTES is used instead of nByteLength. - // So far, everything has been tested with curves of Fp.BYTES == nByteLength. - // TODO: test and find curves which behave otherwise. - const MASK = _2n << (BigInt(nByteLength * 8) - _1n) - const modP = Fp.create // Function overrides - const Fn = Field(CURVE.n, CURVE.nBitLength) - // sqrt(u/v) - const uvRatio = - CURVE.uvRatio || - ((u, v) => { - try { - return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } - } catch (e) { - return { isValid: false, value: _0n } - } - }) - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) // NOOP - const domain = - CURVE.domain || - ((data, ctx, phflag) => { - abool('phflag', phflag) - if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') - return data - }) // NOOP - // 0 <= n < MASK - // Coordinates larger than Fp.ORDER are allowed for zip215 - function aCoordinate(title, n) { - ut.aInRange('coordinate ' + title, n, _0n, MASK) - } - function assertPoint(other) { - if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - const toAffineMemo = memoized((p, iz) => { - const { ex: x, ey: y, ez: z } = p - const is0 = p.is0() - if (iz == null) iz = is0 ? _8n : Fp.inv(z) // 8 was chosen arbitrarily - const ax = modP(x * iz) - const ay = modP(y * iz) - const zz = modP(z * iz) - if (is0) return { x: _0n, y: _1n } - if (zz !== _1n) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - const assertValidMemo = memoized((p) => { - const { a, d } = CURVE - if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? - // Equation in affine coordinates: ax² + y² = 1 + dx²y² - // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² - const { ex: X, ey: Y, ez: Z, et: T } = p - const X2 = modP(X * X) // X² - const Y2 = modP(Y * Y) // Y² - const Z2 = modP(Z * Z) // Z² - const Z4 = modP(Z2 * Z2) // Z⁴ - const aX2 = modP(X2 * a) // aX² - const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² - const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² - if (left !== right) throw new Error('bad point: equation left != right (1)') - // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T - const XY = modP(X * Y) - const ZT = modP(Z * T) - if (XY !== ZT) throw new Error('bad point: equation left != right (2)') - return true - }) - // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). - // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates - class Point { - constructor(ex, ey, ez, et) { - this.ex = ex - this.ey = ey - this.ez = ez - this.et = et - aCoordinate('x', ex) - aCoordinate('y', ey) - aCoordinate('z', ez) - aCoordinate('t', et) - Object.freeze(this) - } - get x() { - return this.toAffine().x - } - get y() { - return this.toAffine().y - } - static fromAffine(p) { - if (p instanceof Point) throw new Error('extended point not allowed') - const { x, y } = p || {} - aCoordinate('x', x) - aCoordinate('y', y) - return new Point(x, y, _1n, modP(x * y)) - } - static normalizeZ(points) { - const toInv = Fp.invertBatch(points.map((p) => p.ez)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - // Multiscalar Multiplication - static msm(points, scalars) { - return pippenger(Point, Fn, points, scalars) - } - // "Private method", don't use it directly - _setWindowSize(windowSize) { - wnaf.setWindowSize(this, windowSize) - } - // Not required for fromHex(), which always creates valid points. - // Could be useful for fromAffine(). - assertValidity() { - assertValidMemo(this) - } - // Compare one point to another. - equals(other) { - assertPoint(other) - const { ex: X1, ey: Y1, ez: Z1 } = this - const { ex: X2, ey: Y2, ez: Z2 } = other - const X1Z2 = modP(X1 * Z2) - const X2Z1 = modP(X2 * Z1) - const Y1Z2 = modP(Y1 * Z2) - const Y2Z1 = modP(Y2 * Z1) - return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 - } - is0() { - return this.equals(Point.ZERO) - } - negate() { - // Flips point sign to a negative one (-x, y in affine coords) - return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) - } - // Fast algo for doubling Extended Point. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd - // Cost: 4M + 4S + 1*a + 6add + 1*2. - double() { - const { a } = CURVE - const { ex: X1, ey: Y1, ez: Z1 } = this - const A = modP(X1 * X1) // A = X12 - const B = modP(Y1 * Y1) // B = Y12 - const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 - const D = modP(a * A) // D = a*A - const x1y1 = X1 + Y1 - const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B - const G = D + B // G = D+B - const F = G - C // F = G-C - const H = D - B // H = D-B - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - // Fast algo for adding 2 Extended Points. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd - // Cost: 9M + 1*a + 1*d + 7add. - add(other) { - assertPoint(other) - const { a, d } = CURVE - const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this - const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other - // Faster algo for adding 2 Extended Points when curve's a=-1. - // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 - // Cost: 8M + 8add + 2*2. - // Note: It does not check whether the `other` point is valid. - if (a === BigInt(-1)) { - const A = modP((Y1 - X1) * (Y2 + X2)) - const B = modP((Y1 + X1) * (Y2 - X2)) - const F = modP(B - A) - if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing - const C = modP(Z1 * _2n * T2) - const D = modP(T1 * _2n * Z2) - const E = D + C - const G = B + A - const H = D - C - const X3 = modP(E * F) - const Y3 = modP(G * H) - const T3 = modP(E * H) - const Z3 = modP(F * G) - return new Point(X3, Y3, Z3, T3) - } - const A = modP(X1 * X2) // A = X1*X2 - const B = modP(Y1 * Y2) // B = Y1*Y2 - const C = modP(T1 * d * T2) // C = T1*d*T2 - const D = modP(Z1 * Z2) // D = Z1*Z2 - const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B - const F = D - C // F = D-C - const G = D + C // G = D+C - const H = modP(B - a * A) // H = B-a*A - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - subtract(other) { - return this.add(other.negate()) - } - wNAF(n) { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - // Constant-time multiplication. - multiply(scalar) { - const n = scalar - ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L - const { p, f } = this.wNAF(n) - return Point.normalizeZ([p, f])[0] - } - // Non-constant-time multiplication. Uses double-and-add algorithm. - // It's faster, but should only be used when you don't care about - // an exposed private key e.g. sig verification. - // Does NOT allow scalars higher than CURVE.n. - // Accepts optional accumulator to merge with multiply (important for sparse scalars) - multiplyUnsafe(scalar, acc = Point.ZERO) { - const n = scalar - ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L - if (n === _0n) return I - if (this.is0() || n === _1n) return this - return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) - } - // Checks if point is of small order. - // If you add something to small order point, you will have "dirty" - // point with torsion component. - // Multiplies point by cofactor and checks if the result is 0. - isSmallOrder() { - return this.multiplyUnsafe(cofactor).is0() - } - // Multiplies point by curve order and checks if the result is 0. - // Returns `false` is the point is dirty. - isTorsionFree() { - return wnaf.unsafeLadder(this, CURVE_ORDER).is0() - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - toAffine(iz) { - return toAffineMemo(this, iz) - } - clearCofactor() { - const { h: cofactor } = CURVE - if (cofactor === _1n) return this - return this.multiplyUnsafe(cofactor) - } - // Converts hash string or Uint8Array to Point. - // Uses algo from RFC8032 5.1.3. - static fromHex(hex, zip215 = false) { - const { d, a } = CURVE - const len = Fp.BYTES - hex = ensureBytes('pointHex', hex, len) // copy hex to a new array - abool('zip215', zip215) - const normed = hex.slice() // copy again, we'll manipulate it - const lastByte = hex[len - 1] // select last byte - normed[len - 1] = lastByte & ~0x80 // clear last bit - const y = ut.bytesToNumberLE(normed) - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // RFC8032 prohibits >= p, but ZIP215 doesn't - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - const max = zip215 ? MASK : Fp.ORDER - ut.aInRange('pointHex.y', y, _0n, max) - // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: - // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) - const y2 = modP(y * y) // denominator is always non-0 mod p. - const u = modP(y2 - _1n) // u = y² - 1 - const v = modP(d * y2 - a) // v = d y² + 1. - let { isValid, value: x } = uvRatio(u, v) // √(u/v) - if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') - const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper - const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit - if (!zip215 && x === _0n && isLastByteOdd) - // if x=0 and x_0 = 1, fail - throw new Error('Point.fromHex: x=0 and x_0=1') - if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x - return Point.fromAffine({ x, y }) - } - static fromPrivateKey(privKey) { - return getExtendedPublicKey(privKey).point - } - toRawBytes() { - const { x, y } = this.toAffine() - const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) - bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y - return bytes // and use the last byte to encode sign of x - } - toHex() { - return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. - } - } - Point.BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) - Point.ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 - const { BASE: G, ZERO: I } = Point - const wnaf = wNAF(Point, nByteLength * 8) - function modN(a) { - return mod(a, CURVE_ORDER) - } - // Little-endian SHA512 with modulo n - function modN_LE(hash) { - return modN(ut.bytesToNumberLE(hash)) - } - /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ - function getExtendedPublicKey(key) { - const len = Fp.BYTES - key = ensureBytes('private key', key, len) - // Hash private key with curve's hash function to produce uniformingly random input - // Check byte lengths: ensure(64, h(ensure(32, key))) - const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) - const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE - const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) - const scalar = modN_LE(head) // The actual private scalar - const point = G.multiply(scalar) // Point on Edwards curve aka public key - const pointBytes = point.toRawBytes() // Uint8Array representation - return { head, prefix, scalar, point, pointBytes } - } - // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared - function getPublicKey(privKey) { - return getExtendedPublicKey(privKey).pointBytes - } - // int('LE', SHA512(dom2(F, C) || msgs)) mod N - function hashDomainToScalar(context = new Uint8Array(), ...msgs) { - const msg = ut.concatBytes(...msgs) - return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) - } - /** Signs message with privateKey. RFC8032 5.1.6 */ - function sign(msg, privKey, options = {}) { - msg = ensureBytes('message', msg) - if (prehash) msg = prehash(msg) // for ed25519ph etc. - const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) - const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) - const R = G.multiply(r).toRawBytes() // R = rG - const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) - const s = modN(r + k * scalar) // S = (r + k * s) mod L - ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l - const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) - return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature - } - const verifyOpts = VERIFY_DEFAULT - /** - * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - * An extended group equation is checked. - */ - function verify(sig, msg, publicKey, options = verifyOpts) { - const { context, zip215 } = options - const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. - msg = ensureBytes('message', msg) - publicKey = ensureBytes('publicKey', publicKey, len) - if (zip215 !== undefined) abool('zip215', zip215) - if (prehash) msg = prehash(msg) // for ed25519ph, etc - const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) - let A, R, SB - try { - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - A = Point.fromHex(publicKey, zip215) - R = Point.fromHex(sig.slice(0, len), zip215) - SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside - } catch (error) { - return false - } - if (!zip215 && A.isSmallOrder()) return false - const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) - const RkA = R.add(A.multiplyUnsafe(k)) - // Extended group equation - // [8][S]B = [8]R + [8][k]A' - return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) - } - G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. - const utils = { - getExtendedPublicKey, - // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. - randomPrivateKey: () => randomBytes(Fp.BYTES), - /** - * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT - * values. This slows down first getPublicKey() by milliseconds (see Speed section), - * but allows to speed-up subsequent getPublicKey() calls up to 20x. - * @param windowSize 2, 4, 8, 16 - */ - precompute(windowSize = 8, point = Point.BASE) { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) - return point - }, - } - return { - CURVE, - getPublicKey, - sign, - verify, - ExtendedPoint: Point, - utils, - } -} -//# sourceMappingURL=edwards.js.map diff --git a/packages/noble-curves/esm/abstract/edwards.js.map b/packages/noble-curves/esm/abstract/edwards.js.map deleted file mode 100644 index 895922f39f0..00000000000 --- a/packages/noble-curves/esm/abstract/edwards.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"edwards.js","sourceRoot":"","sources":["../../src/abstract/edwards.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts deleted file mode 100644 index 646647f9280..00000000000 --- a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import type { AffinePoint, Group, GroupConstructor } from './curve.js' -import { type IField } from './modular.js' -import type { CHash } from './utils.js' -export type UnicodeOrBytes = string | Uint8Array -/** - * * `DST` is a domain separation tag, defined in section 2.2.5 - * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m - * * `m` is extension degree (1 for prime fields) - * * `k` is the target security target in bits (e.g. 128), from section 5.1 - * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) - * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props - */ -export type Opts = { - DST: UnicodeOrBytes - p: bigint - m: number - k: number - expand: 'xmd' | 'xof' - hash: CHash -} -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -export declare function expand_message_xmd( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - H: CHash, -): Uint8Array -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -export declare function expand_message_xof( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - k: number, - H: CHash, -): Uint8Array -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -export declare function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] -export type XY = ( - x: T, - y: T, -) => { - x: T - y: T -} -export declare function isogenyMap>( - field: F, - map: [T[], T[], T[], T[]], -): XY -/** Point interface, which curves must implement to work correctly with the module. */ -export interface H2CPoint extends Group> { - add(rhs: H2CPoint): H2CPoint - toAffine(iz?: bigint): AffinePoint - clearCofactor(): H2CPoint - assertValidity(): void -} -export interface H2CPointConstructor extends GroupConstructor> { - fromAffine(ap: AffinePoint): H2CPoint -} -export type MapToCurve = (scalar: bigint[]) => AffinePoint -export type htfBasicOpts = { - DST: UnicodeOrBytes -} -export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint -export type MapMethod = (scalars: bigint[]) => H2CPoint -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -export declare function createHasher( - Point: H2CPointConstructor, - mapToCurve: MapToCurve, - def: Opts & { - encodeDST?: UnicodeOrBytes - }, -): { - hashToCurve: HTFMethod - encodeToCurve: HTFMethod - mapToCurve: MapMethod -} -//# sourceMappingURL=hash-to-curve.d.ts.map diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map b/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map deleted file mode 100644 index ae9703b1822..00000000000 --- a/packages/noble-curves/esm/abstract/hash-to-curve.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"hash-to-curve.d.ts","sourceRoot":"","sources":["../../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,sEAAsE;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,KAAK,MAAM,EAAO,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AA8BF;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,MAAM,EAClB,CAAC,EAAE,KAAK,GACP,UAAU,CAqBZ;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,MAAM,EAClB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,KAAK,GACP,UAAU,CAqBZ;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,MAAM,EAAE,EAAE,CAqCvF;AAED,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CAClB,CAAC,EAAE,CAAC,EACJ,CAAC,EAAE,CAAC,KACD;IACH,CAAC,EAAE,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,CAAC;CACN,CAAC;AACF,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAW7F;AAED,sFAAsF;AACtF,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrD,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACtC,aAAa,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7B,cAAc,IAAI,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3E,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAIjE,MAAM,MAAM,YAAY,GAAG;IAAE,GAAG,EAAE,cAAc,CAAA;CAAE,CAAC;AACnD,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;AAE9D,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAC7B,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EACzB,GAAG,EAAE,IAAI,GAAG;IAAE,SAAS,CAAC,EAAE,cAAc,CAAA;CAAE,GACzC;IACD,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAC5B,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CAC1B,CAgCA"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.js b/packages/noble-curves/esm/abstract/hash-to-curve.js deleted file mode 100644 index 46e18205e77..00000000000 --- a/packages/noble-curves/esm/abstract/hash-to-curve.js +++ /dev/null @@ -1,173 +0,0 @@ -import { mod } from './modular.js' -import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.js' -// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. -const os2ip = bytesToNumberBE -// Integer to Octet Stream (numberToBytesBE) -function i2osp(value, length) { - anum(value) - anum(length) - if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) - 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 -} -function anum(item) { - if (!Number.isSafeInteger(item)) throw new Error('number expected') -} -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -export function expand_message_xmd(msg, DST, lenInBytes, H) { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) - const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H - const ell = Math.ceil(lenInBytes / b_in_bytes) - if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') - 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) // len_in_bytes_str - const b = new Array(ell) - const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) - b[0] = 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] = H(concatBytes(...args)) - } - const pseudo_random_bytes = concatBytes(...b) - return pseudo_random_bytes.slice(0, lenInBytes) -} -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -export function expand_message_xof(msg, DST, lenInBytes, k, H) { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); - if (DST.length > 255) { - const dkLen = Math.ceil((2 * k) / 8) - DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() - } - if (lenInBytes > 65535 || DST.length > 255) - throw new Error('expand_message_xof: invalid lenInBytes') - return ( - H.create({ dkLen: lenInBytes }) - .update(msg) - .update(i2osp(lenInBytes, 2)) - // 2. DST_prime = DST || I2OSP(len(DST), 1) - .update(DST) - .update(i2osp(DST.length, 1)) - .digest() - ) -} -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -export function hash_to_field(msg, count, options) { - validateObject(options, { - DST: 'stringOrUint8Array', - p: 'bigint', - m: 'isSafeInteger', - k: 'isSafeInteger', - hash: 'hash', - }) - const { p, k, m, hash, expand, DST: _DST } = options - abytes(msg) - anum(count) - const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST - const log2p = p.toString(2).length - const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above - const len_in_bytes = count * m * L - let prb // pseudo_random_bytes - if (expand === 'xmd') { - prb = expand_message_xmd(msg, DST, len_in_bytes, hash) - } else if (expand === 'xof') { - prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) - } else if (expand === '_internal_pass') { - // for internal tests only - prb = msg - } else { - throw new Error('expand must be "xmd" or "xof"') - } - const u = new Array(count) - for (let i = 0; i < count; i++) { - const e = new Array(m) - for (let j = 0; j < m; j++) { - const elm_offset = L * (j + i * m) - const tv = prb.subarray(elm_offset, elm_offset + L) - e[j] = mod(os2ip(tv), p) - } - u[i] = e - } - return u -} -export function isogenyMap(field, map) { - // Make same order as in spec - const COEFF = map.map((i) => Array.from(i).reverse()) - return (x, y) => { - const [xNum, xDen, yNum, yDen] = COEFF.map((val) => - val.reduce((acc, i) => field.add(field.mul(acc, x), i)), - ) - x = field.div(xNum, xDen) // xNum / xDen - y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) - return { x: x, y: y } - } -} -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -export function createHasher(Point, mapToCurve, def) { - if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') - return { - // Encodes byte string to elliptic curve. - // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - hashToCurve(msg, options) { - const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options }) - const u0 = Point.fromAffine(mapToCurve(u[0])) - const u1 = Point.fromAffine(mapToCurve(u[1])) - const P = u0.add(u1).clearCofactor() - P.assertValidity() - return P - }, - // Encodes byte string to elliptic curve. - // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - encodeToCurve(msg, options) { - const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options }) - const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() - P.assertValidity() - return P - }, - // Same as encodeToCurve, but without hash - mapToCurve(scalars) { - if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') - for (const i of scalars) - if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') - const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() - P.assertValidity() - return P - }, - } -} -//# sourceMappingURL=hash-to-curve.js.map diff --git a/packages/noble-curves/esm/abstract/hash-to-curve.js.map b/packages/noble-curves/esm/abstract/hash-to-curve.js.map deleted file mode 100644 index e0029c11254..00000000000 --- a/packages/noble-curves/esm/abstract/hash-to-curve.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"hash-to-curve.js","sourceRoot":"","sources":["../../src/abstract/hash-to-curve.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/modular.d.ts b/packages/noble-curves/esm/abstract/modular.d.ts deleted file mode 100644 index c95a932142e..00000000000 --- a/packages/noble-curves/esm/abstract/modular.d.ts +++ /dev/null @@ -1,168 +0,0 @@ -export declare function mod(a: bigint, b: bigint): bigint -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -export declare function pow(num: bigint, power: bigint, modulo: bigint): bigint -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -export declare function pow2(x: bigint, power: bigint, modulo: bigint): bigint -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -export declare function invert(number: bigint, modulo: bigint): bigint -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -export declare function tonelliShanks(P: bigint): (Fp: IField, n: T) => T -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -export declare function FpSqrt(P: bigint): (Fp: IField, n: T) => T -export declare const isNegativeLE: (num: bigint, modulo: bigint) => boolean -/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ -export interface IField { - ORDER: bigint - isLE: boolean - BYTES: number - BITS: number - MASK: bigint - ZERO: T - ONE: T - create: (num: T) => T - isValid: (num: T) => boolean - is0: (num: T) => boolean - neg(num: T): T - inv(num: T): T - sqrt(num: T): T - sqr(num: T): T - eql(lhs: T, rhs: T): boolean - add(lhs: T, rhs: T): T - sub(lhs: T, rhs: T): T - mul(lhs: T, rhs: T | bigint): T - pow(lhs: T, power: bigint): T - div(lhs: T, rhs: T | bigint): T - addN(lhs: T, rhs: T): T - subN(lhs: T, rhs: T): T - mulN(lhs: T, rhs: T | bigint): T - sqrN(num: T): T - isOdd?(num: T): boolean - pow(lhs: T, power: bigint): T - invertBatch: (lst: T[]) => T[] - toBytes(num: T): Uint8Array - fromBytes(bytes: Uint8Array): T - cmov(a: T, b: T, c: boolean): T -} -export declare function validateField(field: IField): IField -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -export declare function FpPow(f: IField, num: T, power: bigint): T -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -export declare function FpInvertBatch(f: IField, nums: T[]): T[] -export declare function FpDiv(f: IField, lhs: T, rhs: T | bigint): T -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -export declare function FpLegendre(order: bigint): (f: IField, x: T) => T -export declare function FpIsSquare(f: IField): (x: T) => boolean -export declare function nLength( - n: bigint, - nBitLength?: number, -): { - nBitLength: number - nByteLength: number -} -type FpField = IField & Required, 'isOdd'>> -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -export declare function Field( - ORDER: bigint, - bitLen?: number, - isLE?: boolean, - redef?: Partial>, -): Readonly -export declare function FpSqrtOdd(Fp: IField, elm: T): T -export declare function FpSqrtEven(Fp: IField, elm: T): T -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -export declare function hashToPrivateScalar( - hash: string | Uint8Array, - groupOrder: bigint, - isLE?: boolean, -): bigint -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -export declare function getFieldBytesLength(fieldOrder: bigint): number -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -export declare function getMinHashLength(fieldOrder: bigint): number -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -export declare function mapHashToField( - key: Uint8Array, - fieldOrder: bigint, - isLE?: boolean, -): Uint8Array -export {} -//# sourceMappingURL=modular.d.ts.map diff --git a/packages/noble-curves/esm/abstract/modular.d.ts.map b/packages/noble-curves/esm/abstract/modular.d.ts.map deleted file mode 100644 index 474d7bc0d0b..00000000000 --- a/packages/noble-curves/esm/abstract/modular.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"modular.d.ts","sourceRoot":"","sources":["../../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/modular.js b/packages/noble-curves/esm/abstract/modular.js deleted file mode 100644 index c0797abdde6..00000000000 --- a/packages/noble-curves/esm/abstract/modular.js +++ /dev/null @@ -1,464 +0,0 @@ -/** - * Utils for modular division and finite fields. - * A finite field over 11 is integer number operations `mod 11`. - * There is no division: it is replaced by modular multiplicative inverse. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - bitMask, - bytesToNumberBE, - bytesToNumberLE, - ensureBytes, - numberToBytesBE, - numberToBytesLE, - validateObject, -} from './utils.js' -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = /* @__PURE__ */ BigInt(2), - _3n = /* @__PURE__ */ BigInt(3) -// prettier-ignore -const _4n = /* @__PURE__ */ BigInt(4), - _5n = /* @__PURE__ */ BigInt(5), - _8n = /* @__PURE__ */ BigInt(8) -// prettier-ignore -const _9n = /* @__PURE__ */ BigInt(9), - _16n = /* @__PURE__ */ BigInt(16) -// Calculates a modulo b -export function mod(a, b) { - const result = a % b - return result >= _0n ? result : b + result -} -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -export function pow(num, power, modulo) { - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (modulo <= _0n) throw new Error('invalid modulus') - 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 -} -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -export function pow2(x, power, modulo) { - let res = x - while (power-- > _0n) { - res *= res - res %= modulo - } - return res -} -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -export function invert(number, modulo) { - if (number === _0n) throw new Error('invert: expected non-zero number') - if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) - // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. - let a = mod(number, modulo) - let b = modulo - // prettier-ignore - let x = _0n, - y = _1n, - u = _1n, - v = _0n - while (a !== _0n) { - // JIT applies optimization if those two lines follow each other - const q = b / a - const r = b % a - const m = x - u * q - const n = y - v * q - // prettier-ignore - ;(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) -} -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -export function tonelliShanks(P) { - // Legendre constant: used to calculate Legendre symbol (a | p), - // which denotes the value of a^((p-1)/2) (mod p). - // (a | p) ≡ 1 if a is a square (mod p) - // (a | p) ≡ -1 if a is not a square (mod p) - // (a | p) ≡ 0 if a ≡ 0 (mod p) - const legendreC = (P - _1n) / _2n - let Q, S, Z - // Step 1: By factoring out powers of 2 from p - 1, - // find q and s such that p - 1 = q*(2^s) with q odd - for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); - // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq - for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { - // Crash instead of infinity loop, we cannot reasonable count until P. - if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') - } - // Fast-path - if (S === 1) { - const p1div4 = (P + _1n) / _4n - return function tonelliFast(Fp, n) { - const root = Fp.pow(n, p1div4) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // Slow-path - const Q1div2 = (Q + _1n) / _2n - return function tonelliSlow(Fp, n) { - // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 - if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') - let r = S - // TODO: will fail at Fp2/etc - let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b - let x = Fp.pow(n, Q1div2) // first guess at the square root - let b = Fp.pow(n, Q) // first guess at the fudge factor - while (!Fp.eql(b, Fp.ONE)) { - if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) - // Find m such b^(2^m)==1 - let m = 1 - for (let t2 = Fp.sqr(b); m < r; m++) { - if (Fp.eql(t2, Fp.ONE)) break - t2 = Fp.sqr(t2) // t2 *= t2 - } - // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow - const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) - g = Fp.sqr(ge) // g = ge * ge - x = Fp.mul(x, ge) // x *= ge - b = Fp.mul(b, g) // b *= g - r = m - } - return x - } -} -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -export function FpSqrt(P) { - // P ≡ 3 (mod 4) - // √n = n^((P+1)/4) - if (P % _4n === _3n) { - // Not all roots possible! - // const ORDER = - // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; - // const NUM = 72057594037927816n; - const p1div4 = (P + _1n) / _4n - return function sqrt3mod4(Fp, n) { - const root = Fp.pow(n, p1div4) - // Throw if root**2 != n - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) - if (P % _8n === _5n) { - const c1 = (P - _5n) / _8n - return function sqrt5mod8(Fp, n) { - const n2 = Fp.mul(n, _2n) - const v = Fp.pow(n2, c1) - const nv = Fp.mul(n, v) - const i = Fp.mul(Fp.mul(nv, _2n), v) - const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - // P ≡ 9 (mod 16) - if (P % _16n === _9n) { - // NOTE: tonelli is too slow for bls-Fp2 calculations even on start - // Means we cannot use sqrt for constants at all! - // - // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F - // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F - // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F - // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic - // sqrt = (x) => { - // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 - // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 - // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 - // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 - // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x - // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x - // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x - // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x - // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x - // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 - // } - } - // Other cases: Tonelli-Shanks algorithm - return tonelliShanks(P) -} -// Little-endian check for first LE bit (last BE bit); -export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n -// prettier-ignore -const FIELD_FIELDS = [ - 'create', - 'isValid', - 'is0', - 'neg', - 'inv', - 'sqrt', - 'sqr', - 'eql', - 'add', - 'sub', - 'mul', - 'pow', - 'div', - 'addN', - 'subN', - 'mulN', - 'sqrN', -] -export function validateField(field) { - const initial = { - ORDER: 'bigint', - MASK: 'bigint', - BYTES: 'isSafeInteger', - BITS: 'isSafeInteger', - } - const opts = FIELD_FIELDS.reduce((map, val) => { - map[val] = 'function' - return map - }, initial) - return validateObject(field, opts) -} -// Generic field functions -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -export function FpPow(f, num, power) { - // Should have same speed as pow for bigints - // TODO: benchmark! - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (power === _0n) return f.ONE - if (power === _1n) return num - let p = f.ONE - let d = num - while (power > _0n) { - if (power & _1n) p = f.mul(p, d) - d = f.sqr(d) - power >>= _1n - } - return p -} -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -export function FpInvertBatch(f, nums) { - const tmp = new Array(nums.length) - // Walk from first to last, multiply them by each other MOD p - const lastMultiplied = nums.reduce((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = acc - return f.mul(acc, num) - }, f.ONE) - // Invert last element - const inverted = f.inv(lastMultiplied) - // Walk from last to first, multiply them by inverted each other MOD p - nums.reduceRight((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = f.mul(acc, tmp[i]) - return f.mul(acc, num) - }, inverted) - return tmp -} -export function FpDiv(f, lhs, rhs) { - return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) -} -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -export function FpLegendre(order) { - const legendreConst = (order - _1n) / _2n // Integer arithmetic - return (f, x) => f.pow(x, legendreConst) -} -// This function returns True whenever the value x is a square in the field F. -export function FpIsSquare(f) { - const legendre = FpLegendre(f.ORDER) - return (x) => { - const p = legendre(f, x) - return f.eql(p, f.ZERO) || f.eql(p, f.ONE) - } -} -// CURVE.n lengths -export function nLength(n, nBitLength) { - // Bit size, byte size of CURVE.n - const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length - const nByteLength = Math.ceil(_nBitLength / 8) - return { nBitLength: _nBitLength, nByteLength } -} -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -export function Field(ORDER, bitLen, isLE = false, redef = {}) { - if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) - const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) - if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') - let sqrtP // cached sqrtP - const f = Object.freeze({ - ORDER, - isLE, - BITS, - BYTES, - MASK: bitMask(BITS), - ZERO: _0n, - ONE: _1n, - create: (num) => mod(num, ORDER), - isValid: (num) => { - if (typeof num !== 'bigint') - throw new Error('invalid field element: expected bigint, got ' + typeof num) - return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible - }, - is0: (num) => num === _0n, - isOdd: (num) => (num & _1n) === _1n, - neg: (num) => mod(-num, ORDER), - eql: (lhs, rhs) => lhs === rhs, - sqr: (num) => mod(num * num, ORDER), - add: (lhs, rhs) => mod(lhs + rhs, ORDER), - sub: (lhs, rhs) => mod(lhs - rhs, ORDER), - mul: (lhs, rhs) => mod(lhs * rhs, ORDER), - pow: (num, power) => FpPow(f, num, power), - div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), - // Same as above, but doesn't normalize - sqrN: (num) => num * num, - addN: (lhs, rhs) => lhs + rhs, - subN: (lhs, rhs) => lhs - rhs, - mulN: (lhs, rhs) => lhs * rhs, - inv: (num) => invert(num, ORDER), - sqrt: - redef.sqrt || - ((n) => { - if (!sqrtP) sqrtP = FpSqrt(ORDER) - return sqrtP(f, n) - }), - invertBatch: (lst) => FpInvertBatch(f, lst), - // TODO: do we really need constant cmov? - // We don't have const-time bigints anyway, so probably will be not very useful - cmov: (a, b, c) => (c ? b : a), - toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), - fromBytes: (bytes) => { - if (bytes.length !== BYTES) - throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) - return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) - }, - }) - return Object.freeze(f) -} -export function FpSqrtOdd(Fp, elm) { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? root : Fp.neg(root) -} -export function FpSqrtEven(Fp, elm) { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? Fp.neg(root) : root -} -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -export function hashToPrivateScalar(hash, groupOrder, isLE = false) { - hash = ensureBytes('privateHash', hash) - const hashLen = hash.length - const minLen = nLength(groupOrder).nByteLength + 8 - if (minLen < 24 || hashLen < minLen || hashLen > 1024) - throw new Error( - 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, - ) - const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) - return mod(num, groupOrder - _1n) + _1n -} -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -export function getFieldBytesLength(fieldOrder) { - if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') - const bitLength = fieldOrder.toString(2).length - return Math.ceil(bitLength / 8) -} -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -export function getMinHashLength(fieldOrder) { - const length = getFieldBytesLength(fieldOrder) - return length + Math.ceil(length / 2) -} -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -export function mapHashToField(key, fieldOrder, isLE = false) { - const len = key.length - const fieldLen = getFieldBytesLength(fieldOrder) - const minLen = getMinHashLength(fieldOrder) - // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. - if (len < 16 || len < minLen || len > 1024) - throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) - const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) - // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 - const reduced = mod(num, fieldOrder - _1n) + _1n - return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) -} -//# sourceMappingURL=modular.js.map diff --git a/packages/noble-curves/esm/abstract/modular.js.map b/packages/noble-curves/esm/abstract/modular.js.map deleted file mode 100644 index 748f7405a2c..00000000000 --- a/packages/noble-curves/esm/abstract/modular.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"modular.js","sourceRoot":"","sources":["../../src/abstract/modular.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/montgomery.d.ts b/packages/noble-curves/esm/abstract/montgomery.d.ts deleted file mode 100644 index 64a01ea5d1c..00000000000 --- a/packages/noble-curves/esm/abstract/montgomery.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -type Hex = string | Uint8Array -export type CurveType = { - P: bigint - nByteLength: number - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - a: bigint - montgomeryBits: number - powPminus2?: (x: bigint) => bigint - xyToU?: (x: bigint, y: bigint) => bigint - Gu: bigint - randomBytes?: (bytesLength?: number) => Uint8Array -} -export type CurveFn = { - scalarMult: (scalar: Hex, u: Hex) => Uint8Array - scalarMultBase: (scalar: Hex) => Uint8Array - getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array - getPublicKey: (privateKey: Hex) => Uint8Array - utils: { - randomPrivateKey: () => Uint8Array - } - GuBytes: Uint8Array -} -export declare function montgomery(curveDef: CurveType): CurveFn -export {} -//# sourceMappingURL=montgomery.d.ts.map diff --git a/packages/noble-curves/esm/abstract/montgomery.d.ts.map b/packages/noble-curves/esm/abstract/montgomery.d.ts.map deleted file mode 100644 index 28cc704eb38..00000000000 --- a/packages/noble-curves/esm/abstract/montgomery.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"montgomery.d.ts","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"AAkBA,KAAK,GAAG,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IACtD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC;IAC5E,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,KAAK,UAAU,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,UAAU,CAAC;IAChD,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,UAAU,CAAC;IAC5C,eAAe,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IACnE,YAAY,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,UAAU,CAAC;IAC9C,KAAK,EAAE;QAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;KAAE,CAAC;IAC9C,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAsBF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAqIvD"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/montgomery.js b/packages/noble-curves/esm/abstract/montgomery.js deleted file mode 100644 index d08a39f1318..00000000000 --- a/packages/noble-curves/esm/abstract/montgomery.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Montgomery curve methods. It's not really whole montgomery curve, - * just bunch of very specific methods for X25519 / X448 from - * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { mod, pow } from './modular.js' -import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.js' -const _0n = BigInt(0) -const _1n = BigInt(1) -function validateOpts(curve) { - validateObject( - curve, - { - a: 'bigint', - }, - { - montgomeryBits: 'isSafeInteger', - nByteLength: 'isSafeInteger', - adjustScalarBytes: 'function', - domain: 'function', - powPminus2: 'function', - Gu: 'bigint', - }, - ) - // Set defaults - return Object.freeze({ ...curve }) -} -// Uses only one coordinate instead of two -export function montgomery(curveDef) { - const CURVE = validateOpts(curveDef) - const { P } = CURVE - const modP = (n) => mod(n, P) - const montgomeryBits = CURVE.montgomeryBits - const montgomeryBytes = Math.ceil(montgomeryBits / 8) - const fieldLen = CURVE.nByteLength - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes) => bytes) - const powPminus2 = CURVE.powPminus2 || ((x) => pow(x, P - BigInt(2), P)) - // cswap from RFC7748. But it is not from RFC7748! - /* - cswap(swap, x_2, x_3): - dummy = mask(swap) AND (x_2 XOR x_3) - x_2 = x_2 XOR dummy - x_3 = x_3 XOR dummy - Return (x_2, x_3) - Where mask(swap) is the all-1 or all-0 word of the same length as x_2 - and x_3, computed, e.g., as mask(swap) = 0 - swap. - */ - function cswap(swap, x_2, x_3) { - const dummy = modP(swap * (x_2 - x_3)) - x_2 = modP(x_2 - dummy) - x_3 = modP(x_3 + dummy) - return [x_2, x_3] - } - // x25519 from 4 - // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 - const a24 = (CURVE.a - BigInt(2)) / BigInt(4) - /** - * - * @param pointU u coordinate (x) on Montgomery Curve 25519 - * @param scalar by which the point would be multiplied - * @returns new Point on Montgomery curve - */ - function montgomeryLadder(u, scalar) { - aInRange('u', u, _0n, P) - aInRange('scalar', scalar, _0n, P) - // Section 5: Implementations MUST accept non-canonical values and process them as - // if they had been reduced modulo the field prime. - const k = scalar - const x_1 = u - let x_2 = _1n - let z_2 = _0n - let x_3 = u - let z_3 = _1n - let swap = _0n - let sw - for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { - const k_t = (k >> t) & _1n - swap ^= k_t - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - swap = k_t - const A = x_2 + z_2 - const AA = modP(A * A) - const B = x_2 - z_2 - const BB = modP(B * B) - const E = AA - BB - const C = x_3 + z_3 - const D = x_3 - z_3 - const DA = modP(D * A) - const CB = modP(C * B) - const dacb = DA + CB - const da_cb = DA - CB - x_3 = modP(dacb * dacb) - z_3 = modP(x_1 * modP(da_cb * da_cb)) - x_2 = modP(AA * BB) - z_2 = modP(E * (AA + modP(a24 * E))) - } - // (x_2, x_3) = cswap(swap, x_2, x_3) - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - // (z_2, z_3) = cswap(swap, z_2, z_3) - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - // z_2^(p - 2) - const z2 = powPminus2(z_2) - // Return x_2 * (z_2^(p - 2)) - return modP(x_2 * z2) - } - function encodeUCoordinate(u) { - return numberToBytesLE(modP(u), montgomeryBytes) - } - function decodeUCoordinate(uEnc) { - // Section 5: When receiving such an array, implementations of X25519 - // MUST mask the most significant bit in the final byte. - const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) - if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 - return bytesToNumberLE(u) - } - function decodeScalar(n) { - const bytes = ensureBytes('scalar', n) - const len = bytes.length - if (len !== montgomeryBytes && len !== fieldLen) { - let valid = '' + montgomeryBytes + ' or ' + fieldLen - throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) - } - return bytesToNumberLE(adjustScalarBytes(bytes)) - } - function scalarMult(scalar, u) { - const pointU = decodeUCoordinate(u) - const _scalar = decodeScalar(scalar) - const pu = montgomeryLadder(pointU, _scalar) - // The result was not contributory - // https://cr.yp.to/ecdh.html#validate - if (pu === _0n) throw new Error('invalid private or public key received') - return encodeUCoordinate(pu) - } - // Computes public key from private. By doing scalar multiplication of base point. - const GuBytes = encodeUCoordinate(CURVE.Gu) - function scalarMultBase(scalar) { - return scalarMult(scalar, GuBytes) - } - return { - scalarMult, - scalarMultBase, - getSharedSecret: (privateKey, publicKey) => scalarMult(privateKey, publicKey), - getPublicKey: (privateKey) => scalarMultBase(privateKey), - utils: { randomPrivateKey: () => CURVE.randomBytes(CURVE.nByteLength) }, - GuBytes: GuBytes, - } -} -//# sourceMappingURL=montgomery.js.map diff --git a/packages/noble-curves/esm/abstract/montgomery.js.map b/packages/noble-curves/esm/abstract/montgomery.js.map deleted file mode 100644 index 654013b6480..00000000000 --- a/packages/noble-curves/esm/abstract/montgomery.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"montgomery.js","sourceRoot":"","sources":["../../src/abstract/montgomery.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/poseidon.d.ts b/packages/noble-curves/esm/abstract/poseidon.d.ts deleted file mode 100644 index 37c473b1465..00000000000 --- a/packages/noble-curves/esm/abstract/poseidon.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField } from './modular.js' -export type PoseidonOpts = { - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean - mds: bigint[][] - roundConstants: bigint[][] -} -export declare function validateOpts(opts: PoseidonOpts): Readonly<{ - rounds: number - sboxFn: (n: bigint) => bigint - roundConstants: bigint[][] - mds: bigint[][] - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean -}> -export declare function splitConstants(rc: bigint[], t: number): bigint[][] -/** Poseidon NTT-friendly hash. */ -export declare function poseidon(opts: PoseidonOpts): { - (values: bigint[]): bigint[] - roundConstants: bigint[][] -} -//# sourceMappingURL=poseidon.d.ts.map diff --git a/packages/noble-curves/esm/abstract/poseidon.d.ts.map b/packages/noble-curves/esm/abstract/poseidon.d.ts.map deleted file mode 100644 index 50b61631c9a..00000000000 --- a/packages/noble-curves/esm/abstract/poseidon.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"poseidon.d.ts","sourceRoot":"","sources":["../../src/abstract/poseidon.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sEAAsE;AACtE,OAAO,EAAS,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAC;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;IAC3B,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC,CA6CD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAalE;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG;IAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAE7B,cAAc,EAAE,MAAM,EAAE,EAAE,CAAC;CAC5B,CAmCA"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/poseidon.js b/packages/noble-curves/esm/abstract/poseidon.js deleted file mode 100644 index b169136f07d..00000000000 --- a/packages/noble-curves/esm/abstract/poseidon.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { FpPow, validateField } from './modular.js' -export function validateOpts(opts) { - const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts - const { roundsFull, roundsPartial, sboxPower, t } = opts - validateField(Fp) - for (const i of ['t', 'roundsFull', 'roundsPartial']) { - if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) - throw new Error('invalid number ' + i) - } - // MDS is TxT matrix - if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') - const _mds = mds.map((mdsRow) => { - if (!Array.isArray(mdsRow) || mdsRow.length !== t) - throw new Error('invalid MDS matrix row: ' + mdsRow) - return mdsRow.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) - return Fp.create(i) - }) - }) - if (rev !== undefined && typeof rev !== 'boolean') - throw new Error('invalid param reversePartialPowIdx=' + rev) - if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) - const rounds = roundsFull + roundsPartial - if (!Array.isArray(rc) || rc.length !== rounds) - throw new Error('Poseidon: invalid round constants') - const roundConstants = rc.map((rc) => { - if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') - return rc.map((i) => { - if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') - return Fp.create(i) - }) - }) - if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') - const _sboxPower = BigInt(sboxPower) - let sboxFn = (n) => FpPow(Fp, n, _sboxPower) - // Unwrapped sbox power for common cases (195->142μs) - if (sboxPower === 3) sboxFn = (n) => Fp.mul(Fp.sqrN(n), n) - else if (sboxPower === 5) sboxFn = (n) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) - return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) -} -export function splitConstants(rc, t) { - if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') - if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') - const res = [] - let tmp = [] - for (let i = 0; i < rc.length; i++) { - tmp.push(rc[i]) - if (tmp.length === t) { - res.push(tmp) - tmp = [] - } - } - return res -} -/** Poseidon NTT-friendly hash. */ -export function poseidon(opts) { - const _opts = validateOpts(opts) - const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts - const halfRoundsFull = _opts.roundsFull / 2 - const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 - const poseidonRound = (values, isFull, idx) => { - values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) - if (isFull) values = values.map((i) => sboxFn(i)) - else values[partialIdx] = sboxFn(values[partialIdx]) - // Matrix multiplication - values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) - return values - } - const poseidonHash = function poseidonHash(values) { - if (!Array.isArray(values) || values.length !== t) - throw new Error('invalid values, expected array of bigints with length ' + t) - values = values.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) - return Fp.create(i) - }) - let lastRound = 0 - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - // Apply r_p partial rounds. - for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - if (lastRound !== totalRounds) throw new Error('invalid number of rounds') - return values - } - // For verification in tests - poseidonHash.roundConstants = roundConstants - return poseidonHash -} -//# sourceMappingURL=poseidon.js.map diff --git a/packages/noble-curves/esm/abstract/poseidon.js.map b/packages/noble-curves/esm/abstract/poseidon.js.map deleted file mode 100644 index 8292dcc8b08..00000000000 --- a/packages/noble-curves/esm/abstract/poseidon.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"poseidon.js","sourceRoot":"","sources":["../../src/abstract/poseidon.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/tower.d.ts b/packages/noble-curves/esm/abstract/tower.d.ts deleted file mode 100644 index 34d68c39e3b..00000000000 --- a/packages/noble-curves/esm/abstract/tower.d.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import * as mod from './modular.js' -import type { ProjConstructor, ProjPointType } from './weierstrass.js' -export type BigintTuple = [bigint, bigint] -export type Fp = bigint -export type Fp2 = { - c0: bigint - c1: bigint -} -export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] -export type Fp6 = { - c0: Fp2 - c1: Fp2 - c2: Fp2 -} -export type Fp12 = { - c0: Fp6 - c1: Fp6 -} -export type BigintTwelve = [ - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, -] -export type Fp2Bls = mod.IField & { - reim: (num: Fp2) => { - re: Fp - im: Fp - } - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - fromBigTuple(num: [bigint, bigint]): Fp2 -} -export type Fp12Bls = mod.IField & { - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - fromBigTwelve(num: BigintTwelve): Fp12 -} -export declare function psiFrobenius( - Fp: mod.IField, - Fp2: Fp2Bls, - base: Fp2, -): { - psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] - psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] - G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType - G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType - PSI_X: Fp2 - PSI_Y: Fp2 - PSI2_X: Fp2 - PSI2_Y: Fp2 -} -export type Tower12Opts = { - ORDER: bigint - NONRESIDUE?: Fp - FP2_NONRESIDUE: BigintTuple - Fp2sqrt?: (num: Fp2) => Fp2 - Fp2mulByB: (num: Fp2) => Fp2 - Fp12cyclotomicSquare: (num: Fp12) => Fp12 - Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 - Fp12finalExponentiate: (num: Fp12) => Fp12 -} -export declare function tower12(opts: Tower12Opts): { - Fp: Readonly & Required, 'isOdd'>>> - Fp2: mod.IField & { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { - re: bigint - im: bigint - } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - Fp6: mod.IField & { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - Fp4Square: ( - a: Fp2, - b: Fp2, - ) => { - first: Fp2 - second: Fp2 - } - Fp12: mod.IField & { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } -} -//# sourceMappingURL=tower.d.ts.map diff --git a/packages/noble-curves/esm/abstract/tower.d.ts.map b/packages/noble-curves/esm/abstract/tower.d.ts.map deleted file mode 100644 index 6d00d9f1c9b..00000000000 --- a/packages/noble-curves/esm/abstract/tower.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"tower.d.ts","sourceRoot":"","sources":["../../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/tower.js b/packages/noble-curves/esm/abstract/tower.js deleted file mode 100644 index b2eaa6f69f8..00000000000 --- a/packages/noble-curves/esm/abstract/tower.js +++ /dev/null @@ -1,515 +0,0 @@ -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import * as mod from './modular.js' -import { bitLen, bitMask, concatBytes, notImplemented } from './utils.js' -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -function calcFrobeniusCoefficients(Fp, nonResidue, modulus, degree, num = 1, divisor) { - const _divisor = BigInt(divisor === undefined ? degree : divisor) - const towerModulus = modulus ** BigInt(degree) - const res = [] - for (let i = 0; i < num; i++) { - const a = BigInt(i + 1) - const powers = [] - for (let j = 0, qPower = _1n; j < degree; j++) { - const power = ((a * qPower - a) / _divisor) % towerModulus - powers.push(Fp.pow(nonResidue, power)) - qPower *= modulus - } - res.push(powers) - } - return res -} -// This works same at least for bls12-381, bn254 and bls12-377 -export function psiFrobenius(Fp, Fp2, base) { - // Ψ endomorphism - const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) - const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) - function psi(x, y) { - // This x10 faster than previous version in bls12-381 - const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) - const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) - return [x2, y2] - } - // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) - const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) - // This equals -1, which causes y to be Fp2.neg(y). - // But not sure if there are case when this is not true? - const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) - if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') - function psi2(x, y) { - return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] - } - // Map points - const mapAffine = (fn) => (c, P) => { - const affine = P.toAffine() - const p = fn(affine.x, affine.y) - return c.fromAffine({ x: p[0], y: p[1] }) - } - const G2psi = mapAffine(psi) - const G2psi2 = mapAffine(psi2) - return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } -} -export function tower12(opts) { - const { ORDER } = opts - // Fp - const Fp = mod.Field(ORDER) - const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) - const FpLegendre = mod.FpLegendre(ORDER) - const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 - // Fp2 - const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] - const Fp2Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp.add(c0, r0), - c1: Fp.add(c1, r1), - }) - const Fp2Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp.sub(c0, r0), - c1: Fp.sub(c1, r1), - }) - const Fp2Multiply = ({ c0, c1 }, rhs) => { - if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } - // (a+bi)(c+di) = (ac−bd) + (ad+bc)i - const { c0: r0, c1: r1 } = rhs - let t1 = Fp.mul(c0, r0) // c0 * o0 - let t2 = Fp.mul(c1, r1) // c1 * o1 - // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i - const o0 = Fp.sub(t1, t2) - const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) - return { c0: o0, c1: o1 } - } - const Fp2Square = ({ c0, c1 }) => { - const a = Fp.add(c0, c1) - const b = Fp.sub(c0, c1) - const c = Fp.add(c0, c0) - return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } - } - const Fp2fromBigTuple = (tuple) => { - if (tuple.length !== 2) throw new Error('invalid tuple') - const fps = tuple.map((n) => Fp.create(n)) - return { c0: fps[0], c1: fps[1] } - } - const FP2_ORDER = ORDER * ORDER - const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) - const Fp2 = { - ORDER: FP2_ORDER, - isLE: Fp.isLE, - NONRESIDUE: Fp2Nonresidue, - BITS: bitLen(FP2_ORDER), - BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), - MASK: bitMask(bitLen(FP2_ORDER)), - ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, - ONE: { c0: Fp.ONE, c1: Fp.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', - is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp.eql(c0, r0) && Fp.eql(c1, r1), - neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), - pow: (num, power) => mod.FpPow(Fp2, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), - // Normalized - add: Fp2Add, - sub: Fp2Subtract, - mul: Fp2Multiply, - sqr: Fp2Square, - // NonNormalized stuff - addN: Fp2Add, - subN: Fp2Subtract, - mulN: Fp2Multiply, - sqrN: Fp2Square, - // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? - div: (lhs, rhs) => - Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), - inv: ({ c0: a, c1: b }) => { - // We wish to find the multiplicative inverse of a nonzero - // element a + bu in Fp2. We leverage an identity - // - // (a + bu)(a - bu) = a² + b² - // - // which holds because u² = -1. This can be rewritten as - // - // (a + bu)(a - bu)/(a² + b²) = 1 - // - // because a² + b² = 0 has no nonzero solutions for (a, b). - // This gives that (a - bu)/(a² + b²) is the inverse - // of (a + bu). Importantly, this can be computing using - // only a single inversion in Fp. - const factor = Fp.inv(Fp.create(a * a + b * b)) - return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } - }, - sqrt: (num) => { - if (opts.Fp2sqrt) return opts.Fp2sqrt(num) - // This is generic for all quadratic extensions (Fp2) - const { c0, c1 } = num - if (Fp.is0(c1)) { - // if c0 is quadratic residue - if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) - else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) - } - const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) - let d = Fp.mul(Fp.add(a, c0), Fpdiv2) - const legendre = FpLegendre(Fp, d) - // -1, Quadratic non residue - if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) - const a0 = Fp.sqrt(d) - const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) - if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') - // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num - const x1 = candidateSqrt - const x2 = Fp2.neg(x1) - const { re: re1, im: im1 } = Fp2.reim(x1) - const { re: re2, im: im2 } = Fp2.reim(x2) - if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 - return x2 - }, - // Same as sgn0_m_eq_2 in RFC 9380 - isOdd: (x) => { - const { re: x0, im: x1 } = Fp2.reim(x) - const sign_0 = x0 % _2n - const zero_0 = x0 === _0n - const sign_1 = x1 % _2n - return BigInt(sign_0 || (zero_0 && sign_1)) == _1n - }, - // Bytes util - fromBytes(b) { - if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } - }, - toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp.cmov(c0, r0, c), - c1: Fp.cmov(c1, r1, c), - }), - reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), - // multiply by u + 1 - mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), - mulByB: opts.Fp2mulByB, - fromBigTuple: Fp2fromBigTuple, - frobeniusMap: ({ c0, c1 }, power) => ({ - c0, - c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), - }), - } - // Fp6 - const Fp6Add = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ - c0: Fp2.add(c0, r0), - c1: Fp2.add(c1, r1), - c2: Fp2.add(c2, r2), - }) - const Fp6Subtract = ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => ({ - c0: Fp2.sub(c0, r0), - c1: Fp2.sub(c1, r1), - c2: Fp2.sub(c2, r2), - }) - const Fp6Multiply = ({ c0, c1, c2 }, rhs) => { - if (typeof rhs === 'bigint') { - return { - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - } - } - const { c0: r0, c1: r1, c2: r2 } = rhs - const t0 = Fp2.mul(c0, r0) // c0 * o0 - const t1 = Fp2.mul(c1, r1) // c1 * o1 - const t2 = Fp2.mul(c2, r2) // c2 * o2 - return { - // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) - c0: Fp2.add( - t0, - Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), - ), - // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) - c1: Fp2.add( - Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), - Fp2.mulByNonresidue(t2), - ), - // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 - c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), - } - } - const Fp6Square = ({ c0, c1, c2 }) => { - let t0 = Fp2.sqr(c0) // c0² - let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 - let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 - let t4 = Fp2.sqr(c2) // c2² - return { - c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 - c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 - // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 - c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), - } - } - const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 6, - 2, - 3, - ) - const Fp6 = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp2.isLE, - BITS: 3 * Fp2.BITS, - BYTES: 3 * Fp2.BYTES, - MASK: bitMask(3 * Fp2.BITS), - ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, - ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, - create: (num) => num, - isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), - is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), - neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), - eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => - Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), - sqrt: notImplemented, - // Do we need division by bigint at all? Should be done via order: - div: (lhs, rhs) => - Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp6, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), - // Normalized - add: Fp6Add, - sub: Fp6Subtract, - mul: Fp6Multiply, - sqr: Fp6Square, - // NonNormalized stuff - addN: Fp6Add, - subN: Fp6Subtract, - mulN: Fp6Multiply, - sqrN: Fp6Square, - inv: ({ c0, c1, c2 }) => { - let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) - let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 - let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 - // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) - let t4 = Fp2.inv( - Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), - ) - return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } - }, - // Bytes utils - fromBytes: (b) => { - if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), - c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), - c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), - } - }, - toBytes: ({ c0, c1, c2 }) => concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), - cmov: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }, c) => ({ - c0: Fp2.cmov(c0, r0, c), - c1: Fp2.cmov(c1, r1, c), - c2: Fp2.cmov(c2, r2, c), - }), - fromBigSix: (t) => { - if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') - return { - c0: Fp2.fromBigTuple(t.slice(0, 2)), - c1: Fp2.fromBigTuple(t.slice(2, 4)), - c2: Fp2.fromBigTuple(t.slice(4, 6)), - } - }, - frobeniusMap: ({ c0, c1, c2 }, power) => ({ - c0: Fp2.frobeniusMap(c0, power), - c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), - c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), - }), - mulByFp2: ({ c0, c1, c2 }, rhs) => ({ - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - }), - mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), - // Sparse multiplication - mul1: ({ c0, c1, c2 }, b1) => ({ - c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), - c1: Fp2.mul(c0, b1), - c2: Fp2.mul(c1, b1), - }), - // Sparse multiplication - mul01({ c0, c1, c2 }, b0, b1) { - let t0 = Fp2.mul(c0, b0) // c0 * b0 - let t1 = Fp2.mul(c1, b1) // c1 * b1 - return { - // ((c1 + c2) * b1 - T1) * (u + 1) + T0 - c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), - // (b0 + b1) * (c0 + c1) - T0 - T1 - c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), - // (c0 + c2) * b0 - T0 + T1 - c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), - } - }, - } - // Fp12 - const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 12, - 1, - 6, - )[0] - const Fp12Add = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp6.add(c0, r0), - c1: Fp6.add(c1, r1), - }) - const Fp12Subtract = ({ c0, c1 }, { c0: r0, c1: r1 }) => ({ - c0: Fp6.sub(c0, r0), - c1: Fp6.sub(c1, r1), - }) - const Fp12Multiply = ({ c0, c1 }, rhs) => { - if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } - let { c0: r0, c1: r1 } = rhs - let t1 = Fp6.mul(c0, r0) // c0 * r0 - let t2 = Fp6.mul(c1, r1) // c1 * r1 - return { - c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v - // (c0 + c1) * (r0 + r1) - (T1 + T2) - c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), - } - } - const Fp12Square = ({ c0, c1 }) => { - let ab = Fp6.mul(c0, c1) // c0 * c1 - return { - // (c1 * v + c0) * (c0 + c1) - AB - AB * v - c0: Fp6.sub( - Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), - Fp6.mulByNonresidue(ab), - ), - c1: Fp6.add(ab, ab), - } // AB + AB - } - function Fp4Square(a, b) { - const a2 = Fp2.sqr(a) - const b2 = Fp2.sqr(b) - return { - first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² - second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² - } - } - const Fp12 = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp6.isLE, - BITS: 2 * Fp2.BITS, - BYTES: 2 * Fp2.BYTES, - MASK: bitMask(2 * Fp2.BITS), - ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, - ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), - is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), - neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), - sqrt: notImplemented, - inv: ({ c0, c1 }) => { - let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) - return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w - }, - div: (lhs, rhs) => - Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp12, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), - // Normalized - add: Fp12Add, - sub: Fp12Subtract, - mul: Fp12Multiply, - sqr: Fp12Square, - // NonNormalized stuff - addN: Fp12Add, - subN: Fp12Subtract, - mulN: Fp12Multiply, - sqrN: Fp12Square, - // Bytes utils - fromBytes: (b) => { - if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), - c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), - } - }, - toBytes: ({ c0, c1 }) => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp6.cmov(c0, r0, c), - c1: Fp6.cmov(c1, r1, c), - }), - // Utils - // toString() { - // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); - // }, - // fromTuple(c: [Fp6, Fp6]) { - // return new Fp12(...c); - // } - fromBigTwelve: (t) => ({ - c0: Fp6.fromBigSix(t.slice(0, 6)), - c1: Fp6.fromBigSix(t.slice(6, 12)), - }), - // Raises to q**i -th power - frobeniusMap(lhs, power) { - const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) - const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] - return { - c0: Fp6.frobeniusMap(lhs.c0, power), - c1: Fp6.create({ - c0: Fp2.mul(c0, coeff), - c1: Fp2.mul(c1, coeff), - c2: Fp2.mul(c2, coeff), - }), - } - }, - mulByFp2: ({ c0, c1 }, rhs) => ({ - c0: Fp6.mulByFp2(c0, rhs), - c1: Fp6.mulByFp2(c1, rhs), - }), - conjugate: ({ c0, c1 }) => ({ c0, c1: Fp6.neg(c1) }), - // Sparse multiplication - mul014: ({ c0, c1 }, o0, o1, o4) => { - let t0 = Fp6.mul01(c0, o0, o1) - let t1 = Fp6.mul1(c1, o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 - // (c1 + c0) * [o0, o1+o4] - T0 - T1 - c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), - } - }, - mul034: ({ c0, c1 }, o0, o3, o4) => { - const a = Fp6.create({ - c0: Fp2.mul(c0.c0, o0), - c1: Fp2.mul(c0.c1, o0), - c2: Fp2.mul(c0.c2, o0), - }) - const b = Fp6.mul01(c1, o3, o4) - const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(b), a), - c1: Fp6.sub(e, Fp6.add(a, b)), - } - }, - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - _cyclotomicSquare: opts.Fp12cyclotomicSquare, - _cyclotomicExp: opts.Fp12cyclotomicExp, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - finalExponentiate: opts.Fp12finalExponentiate, - } - return { Fp, Fp2, Fp6, Fp4Square, Fp12 } -} -//# sourceMappingURL=tower.js.map diff --git a/packages/noble-curves/esm/abstract/tower.js.map b/packages/noble-curves/esm/abstract/tower.js.map deleted file mode 100644 index 54014b5bad4..00000000000 --- a/packages/noble-curves/esm/abstract/tower.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"tower.js","sourceRoot":"","sources":["../../src/abstract/tower.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/utils.d.ts b/packages/noble-curves/esm/abstract/utils.d.ts deleted file mode 100644 index 405e6bef69d..00000000000 --- a/packages/noble-curves/esm/abstract/utils.d.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -export type Hex = Uint8Array | string -export type PrivKey = Hex | bigint -export type CHash = { - (message: Uint8Array | string): Uint8Array - blockLen: number - outputLen: number - create(opts?: { - dkLen?: number - }): any -} -export type FHash = (message: Uint8Array | string) => Uint8Array -export declare function isBytes(a: unknown): a is Uint8Array -export declare function abytes(item: unknown): void -export declare function abool(title: string, value: boolean): void -/** - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -export declare function bytesToHex(bytes: Uint8Array): string -export declare function numberToHexUnpadded(num: number | bigint): string -export declare function hexToNumber(hex: string): bigint -/** - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -export declare function hexToBytes(hex: string): Uint8Array -export declare function bytesToNumberBE(bytes: Uint8Array): bigint -export declare function bytesToNumberLE(bytes: Uint8Array): bigint -export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array -export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array -export declare function numberToVarBytesBE(n: number | bigint): Uint8Array -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -export declare function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array -/** - * Copies several Uint8Arrays into one. - */ -export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array -export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -export declare function utf8ToBytes(str: string): Uint8Array -export declare function inRange(n: bigint, min: bigint, max: bigint): boolean -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -export declare function aInRange(title: string, n: bigint, min: bigint, max: bigint): void -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -export declare function bitLen(n: bigint): number -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -export declare function bitGet(n: bigint, pos: number): bigint -/** - * Sets single bit at position. - */ -export declare function bitSet(n: bigint, pos: number, value: boolean): bigint -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -export declare const bitMask: (n: number) => bigint -type Pred = (v: Uint8Array) => T | undefined -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -export declare function createHmacDrbg( - hashLen: number, - qByteLen: number, - hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, -): (seed: Uint8Array, predicate: Pred) => T -declare const validatorFns: { - readonly bigint: (val: any) => boolean - readonly function: (val: any) => boolean - readonly boolean: (val: any) => boolean - readonly string: (val: any) => boolean - readonly stringOrUint8Array: (val: any) => boolean - readonly isSafeInteger: (val: any) => boolean - readonly array: (val: any) => boolean - readonly field: (val: any, object: any) => any - readonly hash: (val: any) => boolean -} -type Validator = keyof typeof validatorFns -type ValMap> = { - [K in keyof T]?: Validator -} -export declare function validateObject>( - object: T, - validators: ValMap, - optValidators?: ValMap, -): T -/** - * throws not implemented error - */ -export declare const notImplemented: () => never -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -export declare function memoized( - fn: (arg: T, ...args: O) => R, -): (arg: T, ...args: O) => R -export {} -//# sourceMappingURL=utils.d.ts.map diff --git a/packages/noble-curves/esm/abstract/utils.d.ts.map b/packages/noble-curves/esm/abstract/utils.d.ts.map deleted file mode 100644 index f49a4144c3d..00000000000 --- a/packages/noble-curves/esm/abstract/utils.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/utils.js b/packages/noble-curves/esm/abstract/utils.js deleted file mode 100644 index 28f2f999afe..00000000000 --- a/packages/noble-curves/esm/abstract/utils.js +++ /dev/null @@ -1,311 +0,0 @@ -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// 100 lines of code in the file are duplicated from noble-hashes (utils). -// This is OK: `abstract` directory does not use noble-hashes. -// User may opt-in into using different hashing library. This way, noble-hashes -// won't be included into their bundle. -const _0n = /* @__PURE__ */ BigInt(0) -const _1n = /* @__PURE__ */ BigInt(1) -const _2n = /* @__PURE__ */ BigInt(2) -export function isBytes(a) { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') -} -export function abytes(item) { - if (!isBytes(item)) throw new Error('Uint8Array expected') -} -export function abool(title, value) { - if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) -} -// Array where index 0xf0 (240) is mapped to string 'f0' -const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) -/** - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -export function bytesToHex(bytes) { - abytes(bytes) - // pre-caching improves the speed 6x - let hex = '' - for (let i = 0; i < bytes.length; i++) { - hex += hexes[bytes[i]] - } - return hex -} -export function numberToHexUnpadded(num) { - const hex = num.toString(16) - return hex.length & 1 ? '0' + hex : hex -} -export function hexToNumber(hex) { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian -} -// We use optimized technique to convert hex string to byte array -const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } -function asciiToBase16(ch) { - if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 - if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) - if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) - return -} -/** - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -export function hexToBytes(hex) { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - const hl = hex.length - const al = hl / 2 - if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) - const array = new Uint8Array(al) - for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { - const n1 = asciiToBase16(hex.charCodeAt(hi)) - const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) - if (n1 === undefined || n2 === undefined) { - const char = hex[hi] + hex[hi + 1] - throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) - } - array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 - } - return array -} -// BE: Big Endian, LE: Little Endian -export function bytesToNumberBE(bytes) { - return hexToNumber(bytesToHex(bytes)) -} -export function bytesToNumberLE(bytes) { - abytes(bytes) - return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) -} -export function numberToBytesBE(n, len) { - return hexToBytes(n.toString(16).padStart(len * 2, '0')) -} -export function numberToBytesLE(n, len) { - return numberToBytesBE(n, len).reverse() -} -// Unpadded, rarely used -export function numberToVarBytesBE(n) { - return hexToBytes(numberToHexUnpadded(n)) -} -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -export function ensureBytes(title, hex, expectedLength) { - let res - if (typeof hex === 'string') { - try { - res = hexToBytes(hex) - } catch (e) { - throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) - } - } else if (isBytes(hex)) { - // Uint8Array.from() instead of hash.slice() because node.js Buffer - // is instance of Uint8Array, and its slice() creates **mutable** copy - res = Uint8Array.from(hex) - } else { - throw new Error(title + ' must be hex string or Uint8Array') - } - const len = res.length - if (typeof expectedLength === 'number' && len !== expectedLength) - throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) - return res -} -/** - * Copies several Uint8Arrays into one. - */ -export function concatBytes(...arrays) { - let sum = 0 - for (let i = 0; i < arrays.length; i++) { - const a = arrays[i] - abytes(a) - sum += a.length - } - const res = new Uint8Array(sum) - for (let i = 0, pad = 0; i < arrays.length; i++) { - const a = arrays[i] - res.set(a, pad) - pad += a.length - } - return res -} -// Compares 2 u8a-s in kinda constant time -export function equalBytes(a, b) { - if (a.length !== b.length) return false - let diff = 0 - for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] - return diff === 0 -} -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -export function utf8ToBytes(str) { - if (typeof str !== 'string') throw new Error('string expected') - return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 -} -// Is positive bigint -const isPosBig = (n) => typeof n === 'bigint' && _0n <= n -export function inRange(n, min, max) { - return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max -} -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -export function aInRange(title, n, min, max) { - // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? - // consider P=256n, min=0n, max=P - // - a for min=0 would require -1: `inRange('x', x, -1n, P)` - // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` - // - our way is the cleanest: `inRange('x', x, 0n, P) - if (!inRange(n, min, max)) - throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) -} -// Bit operations -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -export function bitLen(n) { - let len - for (len = 0; n > _0n; n >>= _1n, len += 1); - return len -} -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -export function bitGet(n, pos) { - return (n >> BigInt(pos)) & _1n -} -/** - * Sets single bit at position. - */ -export function bitSet(n, pos, value) { - return n | ((value ? _1n : _0n) << BigInt(pos)) -} -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -export const bitMask = (n) => (_2n << BigInt(n - 1)) - _1n -// DRBG -const u8n = (data) => new Uint8Array(data) // creates Uint8Array -const u8fr = (arr) => Uint8Array.from(arr) // another shortcut -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -export function createHmacDrbg(hashLen, qByteLen, hmacFn) { - if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') - if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') - if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') - // Step B, Step C: set hashLen to 8*ceil(hlen/8) - let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same - let i = 0 // Iterations counter, will throw when over 1000 - const reset = () => { - v.fill(1) - k.fill(0) - i = 0 - } - const h = (...b) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) - const reseed = (seed = u8n()) => { - // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) - v = h() // v = hmac(k || v) - if (seed.length === 0) return - k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) - v = h() // v = hmac(k || v) - } - const gen = () => { - // HMAC-DRBG generate() function - if (i++ >= 1000) throw new Error('drbg: tried 1000 values') - let len = 0 - const out = [] - while (len < qByteLen) { - v = h() - const sl = v.slice() - out.push(sl) - len += v.length - } - return concatBytes(...out) - } - const genUntil = (seed, pred) => { - reset() - reseed(seed) // Steps D-G - let res = undefined // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed() - reset() - return res - } - return genUntil -} -// Validating curves and fields -const validatorFns = { - bigint: (val) => typeof val === 'bigint', - function: (val) => typeof val === 'function', - boolean: (val) => typeof val === 'boolean', - string: (val) => typeof val === 'string', - stringOrUint8Array: (val) => typeof val === 'string' || isBytes(val), - isSafeInteger: (val) => Number.isSafeInteger(val), - array: (val) => Array.isArray(val), - field: (val, object) => object.Fp.isValid(val), - hash: (val) => typeof val === 'function' && Number.isSafeInteger(val.outputLen), -} -// type Record = { [P in K]: T; } -export function validateObject(object, validators, optValidators = {}) { - const checkField = (fieldName, type, isOptional) => { - const checkVal = validatorFns[type] - if (typeof checkVal !== 'function') throw new Error('invalid validator function') - const val = object[fieldName] - if (isOptional && val === undefined) return - if (!checkVal(val, object)) { - throw new Error( - 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, - ) - } - } - for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type, false) - for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type, true) - return object -} -// validate type tests -// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; -// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! -// // Should fail type-check -// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); -// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); -// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); -// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); -/** - * throws not implemented error - */ -export const notImplemented = () => { - throw new Error('not implemented') -} -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -export function memoized(fn) { - const map = new WeakMap() - return (arg, ...args) => { - const val = map.get(arg) - if (val !== undefined) return val - const computed = fn(arg, ...args) - map.set(arg, computed) - return computed - } -} -//# sourceMappingURL=utils.js.map diff --git a/packages/noble-curves/esm/abstract/utils.js.map b/packages/noble-curves/esm/abstract/utils.js.map deleted file mode 100644 index 2d06284c084..00000000000 --- a/packages/noble-curves/esm/abstract/utils.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/abstract/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/weierstrass.d.ts b/packages/noble-curves/esm/abstract/weierstrass.d.ts deleted file mode 100644 index f79b0c73b8e..00000000000 --- a/packages/noble-curves/esm/abstract/weierstrass.d.ts +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type AffinePoint, type BasicCurve, type Group, type GroupConstructor } from './curve.js' -import { type IField } from './modular.js' -import { type CHash, type Hex, type PrivKey } from './utils.js' -export type { AffinePoint } -type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array -type EndomorphismOpts = { - beta: bigint - splitScalar: (k: bigint) => { - k1neg: boolean - k1: bigint - k2neg: boolean - k2: bigint - } -} -export type BasicWCurve = BasicCurve & { - a: T - b: T - allowedPrivateKeyLengths?: readonly number[] - wrapPrivateKey?: boolean - endo?: EndomorphismOpts - isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean - clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType -} -type Entropy = Hex | boolean -export type SignOpts = { - lowS?: boolean - extraEntropy?: Entropy - prehash?: boolean -} -export type VerOpts = { - lowS?: boolean - prehash?: boolean - format?: 'compact' | 'der' | undefined -} -export interface ProjPointType extends Group> { - readonly px: T - readonly py: T - readonly pz: T - get x(): T - get y(): T - multiply(scalar: bigint): ProjPointType - toAffine(iz?: T): AffinePoint - isTorsionFree(): boolean - clearCofactor(): ProjPointType - assertValidity(): void - hasEvenY(): boolean - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - multiplyUnsafe(scalar: bigint): ProjPointType - multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined - _setWindowSize(windowSize: number): void -} -export interface ProjConstructor extends GroupConstructor> { - new (x: T, y: T, z: T): ProjPointType - fromAffine(p: AffinePoint): ProjPointType - fromHex(hex: Hex): ProjPointType - fromPrivateKey(privateKey: PrivKey): ProjPointType - normalizeZ(points: ProjPointType[]): ProjPointType[] - msm(points: ProjPointType[], scalars: bigint[]): ProjPointType -} -export type CurvePointsType = BasicWCurve & { - fromBytes?: (bytes: Uint8Array) => AffinePoint - toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array -} -export type CurvePointsTypeWithLength = Readonly< - CurvePointsType & { - nByteLength: number - nBitLength: number - } -> -declare function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength -export type CurvePointsRes = { - CURVE: ReturnType> - ProjectivePoint: ProjConstructor - normPrivateKeyToScalar: (key: PrivKey) => bigint - weierstrassEquation: (x: T) => T - isWithinCurveOrder: (num: bigint) => boolean -} -export declare class DERErr extends Error { - constructor(m?: string) -} -export type IDER = { - Err: typeof DERErr - _tlv: { - encode: (tag: number, data: string) => string - decode( - tag: number, - data: Uint8Array, - ): { - v: Uint8Array - l: Uint8Array - } - } - _int: { - encode(num: bigint): string - decode(data: Uint8Array): bigint - } - toSig(hex: string | Uint8Array): { - r: bigint - s: bigint - } - hexFromSig(sig: { - r: bigint - s: bigint - }): string -} -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -export declare const DER: IDER -export declare function weierstrassPoints(opts: CurvePointsType): CurvePointsRes -export interface SignatureType { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - assertValidity(): void - addRecoveryBit(recovery: number): RecoveredSignatureType - hasHighS(): boolean - normalizeS(): SignatureType - recoverPublicKey(msgHash: Hex): ProjPointType - toCompactRawBytes(): Uint8Array - toCompactHex(): string - toDERRawBytes(isCompressed?: boolean): Uint8Array - toDERHex(isCompressed?: boolean): string -} -export type RecoveredSignatureType = SignatureType & { - readonly recovery: number -} -export type SignatureConstructor = { - new (r: bigint, s: bigint): SignatureType - fromCompact(hex: Hex): SignatureType - fromDER(hex: Hex): SignatureType -} -type SignatureLike = { - r: bigint - s: bigint -} -export type PubKey = Hex | ProjPointType -export type CurveType = BasicWCurve & { - hash: CHash - hmac: HmacFnSync - randomBytes: (bytesLength?: number) => Uint8Array - lowS?: boolean - bits2int?: (bytes: Uint8Array) => bigint - bits2int_modN?: (bytes: Uint8Array) => bigint -} -declare function validateOpts(curve: CurveType): Readonly< - CurveType & { - nByteLength: number - nBitLength: number - } -> -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array - getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array - sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType - verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean - ProjectivePoint: ProjConstructor - Signature: SignatureConstructor - utils: { - normPrivateKeyToScalar: (key: PrivKey) => bigint - isValidPrivateKey(privateKey: PrivKey): boolean - randomPrivateKey: () => Uint8Array - precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType - } -} -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -export declare function weierstrass(curveDef: CurveType): CurveFn -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -export declare function SWUFpSqrtRatio( - Fp: IField, - Z: T, -): ( - u: T, - v: T, -) => { - isValid: boolean - value: T -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -export declare function mapToCurveSimpleSWU( - Fp: IField, - opts: { - A: T - B: T - Z: T - }, -): (u: T) => { - x: T - y: T -} -//# sourceMappingURL=weierstrass.d.ts.map diff --git a/packages/noble-curves/esm/abstract/weierstrass.d.ts.map b/packages/noble-curves/esm/abstract/weierstrass.d.ts.map deleted file mode 100644 index 1637197cd09..00000000000 --- a/packages/noble-curves/esm/abstract/weierstrass.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"weierstrass.d.ts","sourceRoot":"","sources":["../../src/abstract/weierstrass.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/abstract/weierstrass.js b/packages/noble-curves/esm/abstract/weierstrass.js deleted file mode 100644 index 54c6482d356..00000000000 --- a/packages/noble-curves/esm/abstract/weierstrass.js +++ /dev/null @@ -1,1131 +0,0 @@ -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { pippenger, validateBasic, wNAF } from './curve.js' -import { Field, getMinHashLength, invert, mapHashToField, mod, validateField } from './modular.js' -import * as ut from './utils.js' -import { abool, ensureBytes, memoized } from './utils.js' -function validateSigVerOpts(opts) { - if (opts.lowS !== undefined) abool('lowS', opts.lowS) - if (opts.prehash !== undefined) abool('prehash', opts.prehash) -} -function validatePointOpts(curve) { - const opts = validateBasic(curve) - ut.validateObject( - opts, - { - a: 'field', - b: 'field', - }, - { - allowedPrivateKeyLengths: 'array', - wrapPrivateKey: 'boolean', - isTorsionFree: 'function', - clearCofactor: 'function', - allowInfinityPoint: 'boolean', - fromBytes: 'function', - toBytes: 'function', - }, - ) - const { endo, Fp, a } = opts - if (endo) { - if (!Fp.eql(a, Fp.ZERO)) { - throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') - } - if ( - typeof endo !== 'object' || - typeof endo.beta !== 'bigint' || - typeof endo.splitScalar !== 'function' - ) { - throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') - } - } - return Object.freeze({ ...opts }) -} -const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut -export class DERErr extends Error { - constructor(m = '') { - super(m) - } -} -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -export const DER = { - // asn.1 DER encoding utils - Err: DERErr, - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag, data) => { - const { Err: E } = DER - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length & 1) throw new E('tlv.encode: unpadded data') - const dataLen = data.length / 2 - const len = ut.numberToHexUnpadded(dataLen) - if ((len.length / 2) & 128) throw new E('tlv.encode: long form length too big') - // length of length with long form flag - const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 128) : '' - const t = ut.numberToHexUnpadded(tag) - return t + lenLen + len + data - }, - // v - value, l - left bytes (unparsed) - decode(tag, data) { - const { Err: E } = DER - let pos = 0 - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') - const first = data[pos++] - const isLong = !!(first & 128) // First bit of first length byte is flag for short/long form - let length = 0 - if (!isLong) length = first - else { - // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] - const lenLen = first & 127 - if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') - if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js - const lengthBytes = data.subarray(pos, pos + lenLen) - if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') - if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') - for (const b of lengthBytes) length = (length << 8) | b - pos += lenLen - if (length < 128) throw new E('tlv.decode(long): not minimal encoding') - } - const v = data.subarray(pos, pos + length) - if (v.length !== length) throw new E('tlv.decode: wrong value length') - return { v, l: data.subarray(pos + length) } - }, - }, - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num) { - const { Err: E } = DER - if (num < _0n) throw new E('integer: negative integers are not allowed') - let hex = ut.numberToHexUnpadded(num) - // Pad with zero byte if negative flag is present - if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex - if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') - return hex - }, - decode(data) { - const { Err: E } = DER - if (data[0] & 128) throw new E('invalid signature integer: negative') - if (data[0] === 0x00 && !(data[1] & 128)) - throw new E('invalid signature integer: unnecessary leading zero') - return b2n(data) - }, - }, - toSig(hex) { - // parse DER signature - const { Err: E, _int: int, _tlv: tlv } = DER - const data = typeof hex === 'string' ? h2b(hex) : hex - ut.abytes(data) - const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) - if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) - const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) - if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - return { r: int.decode(rBytes), s: int.decode(sBytes) } - }, - hexFromSig(sig) { - const { _tlv: tlv, _int: int } = DER - const rs = tlv.encode(0x02, int.encode(sig.r)) - const ss = tlv.encode(0x02, int.encode(sig.s)) - const seq = rs + ss - return tlv.encode(0x30, seq) - }, -} -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) -export function weierstrassPoints(opts) { - const CURVE = validatePointOpts(opts) - const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ - const Fn = Field(CURVE.n, CURVE.nBitLength) - const toBytes = - CURVE.toBytes || - ((_c, point, _isCompressed) => { - const a = point.toAffine() - return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) - }) - const fromBytes = - CURVE.fromBytes || - ((bytes) => { - // const head = bytes[0]; - const tail = bytes.subarray(1) - // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - }) - /** - * y² = x³ + ax + b: Short weierstrass curve formula - * @returns y² - */ - function weierstrassEquation(x) { - const { a, b } = CURVE - const x2 = Fp.sqr(x) // x * x - const x3 = Fp.mul(x2, x) // x2 * x - return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b - } - // Validate whether the passed curve params are valid. - // We check if curve equation works for generator point. - // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. - // ProjectivePoint class has not been initialized yet. - if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) - throw new Error('bad generator point: equation left != right') - // Valid group elements reside in range 1..n-1 - function isWithinCurveOrder(num) { - return ut.inRange(num, _1n, CURVE.n) - } - // Validates if priv key is valid and converts it to bigint. - // Supports options allowedPrivateKeyLengths and wrapPrivateKey. - function normPrivateKeyToScalar(key) { - const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE - if (lengths && typeof key !== 'bigint') { - if (ut.isBytes(key)) key = ut.bytesToHex(key) - // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes - if (typeof key !== 'string' || !lengths.includes(key.length)) - throw new Error('invalid private key') - key = key.padStart(nByteLength * 2, '0') - } - let num - try { - num = - typeof key === 'bigint' - ? key - : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength)) - } catch (error) { - throw new Error( - 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, - ) - } - if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS - ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] - return num - } - function assertPrjPoint(other) { - if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') - } - // Memoized toAffine / validity check. They are heavy. Points are immutable. - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - const toAffineMemo = memoized((p, iz) => { - const { px: x, py: y, pz: z } = p - // Fast-path for normalized points - if (Fp.eql(z, Fp.ONE)) return { x, y } - const is0 = p.is0() - // If invZ was 0, we return zero point. However we still want to execute - // all operations, so we replace invZ with a random number, 1. - if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) - const ax = Fp.mul(x, iz) - const ay = Fp.mul(y, iz) - const zz = Fp.mul(z, iz) - if (is0) return { x: Fp.ZERO, y: Fp.ZERO } - if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - // NOTE: on exception this will crash 'cached' and no value will be set. - // Otherwise true will be return - const assertValidMemo = memoized((p) => { - if (p.is0()) { - // (0, 1, 0) aka ZERO is invalid in most contexts. - // In BLS, ZERO can be serialized, so we allow it. - // (0, 0, 0) is invalid representation of ZERO. - if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return - throw new Error('bad point: ZERO') - } - // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` - const { x, y } = p.toAffine() - // Check if x, y are valid field elements - if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') - const left = Fp.sqr(y) // y² - const right = weierstrassEquation(x) // x³ + ax + b - if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') - if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') - return true - }) - /** - * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) - * Default Point works in 2d / affine coordinates: (x, y) - * We're doing calculations in projective, because its operations don't require costly inversion. - */ - class Point { - constructor(px, py, pz) { - this.px = px - this.py = py - this.pz = pz - if (px == null || !Fp.isValid(px)) throw new Error('x required') - if (py == null || !Fp.isValid(py)) throw new Error('y required') - if (pz == null || !Fp.isValid(pz)) throw new Error('z required') - Object.freeze(this) - } - // Does not validate if the point is on-curve. - // Use fromHex instead, or call assertValidity() later. - static fromAffine(p) { - const { x, y } = p || {} - if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') - if (p instanceof Point) throw new Error('projective point not allowed') - const is0 = (i) => Fp.eql(i, Fp.ZERO) - // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) - if (is0(x) && is0(y)) return Point.ZERO - return new Point(x, y, Fp.ONE) - } - get x() { - return this.toAffine().x - } - get y() { - return this.toAffine().y - } - /** - * Takes a bunch of Projective Points but executes only one - * inversion on all of them. Inversion is very slow operation, - * so this improves performance massively. - * Optimization: converts a list of projective points to a list of identical points with Z=1. - */ - static normalizeZ(points) { - const toInv = Fp.invertBatch(points.map((p) => p.pz)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - /** - * Converts hash string or Uint8Array to Point. - * @param hex short/long ECDSA hex - */ - static fromHex(hex) { - const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) - P.assertValidity() - return P - } - // Multiplies generator point by privateKey. - static fromPrivateKey(privateKey) { - return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) - } - // Multiscalar Multiplication - static msm(points, scalars) { - return pippenger(Point, Fn, points, scalars) - } - // "Private method", don't use it directly - _setWindowSize(windowSize) { - wnaf.setWindowSize(this, windowSize) - } - // A point on curve is valid if it conforms to equation. - assertValidity() { - assertValidMemo(this) - } - hasEvenY() { - const { y } = this.toAffine() - if (Fp.isOdd) return !Fp.isOdd(y) - throw new Error("Field doesn't support isOdd") - } - /** - * Compare one point to another. - */ - equals(other) { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) - const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) - return U1 && U2 - } - /** - * Flips point to one corresponding to (x, -y) in Affine coordinates. - */ - negate() { - return new Point(this.px, Fp.neg(this.py), this.pz) - } - // Renes-Costello-Batina exception-free doubling formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 3 - // Cost: 8M + 3S + 3*a + 2*b3 + 15add. - double() { - const { a, b } = CURVE - const b3 = Fp.mul(b, _3n) - const { px: X1, py: Y1, pz: Z1 } = this - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - let t0 = Fp.mul(X1, X1) // step 1 - let t1 = Fp.mul(Y1, Y1) - let t2 = Fp.mul(Z1, Z1) - let t3 = Fp.mul(X1, Y1) - t3 = Fp.add(t3, t3) // step 5 - Z3 = Fp.mul(X1, Z1) - Z3 = Fp.add(Z3, Z3) - X3 = Fp.mul(a, Z3) - Y3 = Fp.mul(b3, t2) - Y3 = Fp.add(X3, Y3) // step 10 - X3 = Fp.sub(t1, Y3) - Y3 = Fp.add(t1, Y3) - Y3 = Fp.mul(X3, Y3) - X3 = Fp.mul(t3, X3) - Z3 = Fp.mul(b3, Z3) // step 15 - t2 = Fp.mul(a, t2) - t3 = Fp.sub(t0, t2) - t3 = Fp.mul(a, t3) - t3 = Fp.add(t3, Z3) - Z3 = Fp.add(t0, t0) // step 20 - t0 = Fp.add(Z3, t0) - t0 = Fp.add(t0, t2) - t0 = Fp.mul(t0, t3) - Y3 = Fp.add(Y3, t0) - t2 = Fp.mul(Y1, Z1) // step 25 - t2 = Fp.add(t2, t2) - t0 = Fp.mul(t2, t3) - X3 = Fp.sub(X3, t0) - Z3 = Fp.mul(t2, t1) - Z3 = Fp.add(Z3, Z3) // step 30 - Z3 = Fp.add(Z3, Z3) - return new Point(X3, Y3, Z3) - } - // Renes-Costello-Batina exception-free addition formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 1 - // Cost: 12M + 0S + 3*a + 3*b3 + 23add. - add(other) { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - const a = CURVE.a - const b3 = Fp.mul(CURVE.b, _3n) - let t0 = Fp.mul(X1, X2) // step 1 - let t1 = Fp.mul(Y1, Y2) - let t2 = Fp.mul(Z1, Z2) - let t3 = Fp.add(X1, Y1) - let t4 = Fp.add(X2, Y2) // step 5 - t3 = Fp.mul(t3, t4) - t4 = Fp.add(t0, t1) - t3 = Fp.sub(t3, t4) - t4 = Fp.add(X1, Z1) - let t5 = Fp.add(X2, Z2) // step 10 - t4 = Fp.mul(t4, t5) - t5 = Fp.add(t0, t2) - t4 = Fp.sub(t4, t5) - t5 = Fp.add(Y1, Z1) - X3 = Fp.add(Y2, Z2) // step 15 - t5 = Fp.mul(t5, X3) - X3 = Fp.add(t1, t2) - t5 = Fp.sub(t5, X3) - Z3 = Fp.mul(a, t4) - X3 = Fp.mul(b3, t2) // step 20 - Z3 = Fp.add(X3, Z3) - X3 = Fp.sub(t1, Z3) - Z3 = Fp.add(t1, Z3) - Y3 = Fp.mul(X3, Z3) - t1 = Fp.add(t0, t0) // step 25 - t1 = Fp.add(t1, t0) - t2 = Fp.mul(a, t2) - t4 = Fp.mul(b3, t4) - t1 = Fp.add(t1, t2) - t2 = Fp.sub(t0, t2) // step 30 - t2 = Fp.mul(a, t2) - t4 = Fp.add(t4, t2) - t0 = Fp.mul(t1, t4) - Y3 = Fp.add(Y3, t0) - t0 = Fp.mul(t5, t4) // step 35 - X3 = Fp.mul(t3, X3) - X3 = Fp.sub(X3, t0) - t0 = Fp.mul(t3, t1) - Z3 = Fp.mul(t5, Z3) - Z3 = Fp.add(Z3, t0) // step 40 - return new Point(X3, Y3, Z3) - } - subtract(other) { - return this.add(other.negate()) - } - is0() { - return this.equals(Point.ZERO) - } - wNAF(n) { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - /** - * Non-constant-time multiplication. Uses double-and-add algorithm. - * It's faster, but should only be used when you don't care about - * an exposed private key e.g. sig verification, which works over *public* keys. - */ - multiplyUnsafe(sc) { - const { endo, n: N } = CURVE - ut.aInRange('scalar', sc, _0n, N) - const I = Point.ZERO - if (sc === _0n) return I - if (this.is0() || sc === _1n) return this - // Case a: no endomorphism. Case b: has precomputes. - if (!endo || wnaf.hasPrecomputes(this)) - return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) - // Case c: endomorphism - let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) - let k1p = I - let k2p = I - let d = this - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) k1p = k1p.add(d) - if (k2 & _1n) k2p = k2p.add(d) - d = d.double() - k1 >>= _1n - k2 >>= _1n - } - if (k1neg) k1p = k1p.negate() - if (k2neg) k2p = k2p.negate() - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - return k1p.add(k2p) - } - /** - * Constant time multiplication. - * Uses wNAF method. Windowed method may be 10% faster, - * but takes 2x longer to generate and consumes 2x memory. - * Uses precomputes when available. - * Uses endomorphism for Koblitz curves. - * @param scalar by which the point would be multiplied - * @returns New point - */ - multiply(scalar) { - const { endo, n: N } = CURVE - ut.aInRange('scalar', scalar, _1n, N) - let point, fake // Fake point is used to const-time mult - if (endo) { - const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) - let { p: k1p, f: f1p } = this.wNAF(k1) - let { p: k2p, f: f2p } = this.wNAF(k2) - k1p = wnaf.constTimeNegate(k1neg, k1p) - k2p = wnaf.constTimeNegate(k2neg, k2p) - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - point = k1p.add(k2p) - fake = f1p.add(f2p) - } else { - const { p, f } = this.wNAF(scalar) - point = p - fake = f - } - // Normalize `z` for both points, but return only real one - return Point.normalizeZ([point, fake])[0] - } - /** - * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. - * Not using Strauss-Shamir trick: precomputation tables are faster. - * The trick could be useful if both P and Q are not G (not in our case). - * @returns non-zero affine point - */ - multiplyAndAddUnsafe(Q, a, b) { - const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes - const mul = ( - P, - a, // Select faster multiply() method - ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) - const sum = mul(this, a).add(mul(Q, b)) - return sum.is0() ? undefined : sum - } - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - toAffine(iz) { - return toAffineMemo(this, iz) - } - isTorsionFree() { - const { h: cofactor, isTorsionFree } = CURVE - if (cofactor === _1n) return true // No subgroups, always torsion-free - if (isTorsionFree) return isTorsionFree(Point, this) - throw new Error('isTorsionFree() has not been declared for the elliptic curve') - } - clearCofactor() { - const { h: cofactor, clearCofactor } = CURVE - if (cofactor === _1n) return this // Fast-path - if (clearCofactor) return clearCofactor(Point, this) - return this.multiplyUnsafe(CURVE.h) - } - toRawBytes(isCompressed = true) { - abool('isCompressed', isCompressed) - this.assertValidity() - return toBytes(Point, this, isCompressed) - } - toHex(isCompressed = true) { - abool('isCompressed', isCompressed) - return ut.bytesToHex(this.toRawBytes(isCompressed)) - } - } - Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) - Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) - const _bits = CURVE.nBitLength - const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) - // Validate if generator point is on curve - return { - CURVE, - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } -} -function validateOpts(curve) { - const opts = validateBasic(curve) - ut.validateObject( - opts, - { - hash: 'hash', - hmac: 'function', - randomBytes: 'function', - }, - { - bits2int: 'function', - bits2int_modN: 'function', - lowS: 'boolean', - }, - ) - return Object.freeze({ lowS: true, ...opts }) -} -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -export function weierstrass(curveDef) { - const CURVE = validateOpts(curveDef) - const { Fp, n: CURVE_ORDER } = CURVE - const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 - const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 - function modN(a) { - return mod(a, CURVE_ORDER) - } - function invN(a) { - return invert(a, CURVE_ORDER) - } - const { - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } = weierstrassPoints({ - ...CURVE, - toBytes(_c, point, isCompressed) { - const a = point.toAffine() - const x = Fp.toBytes(a.x) - const cat = ut.concatBytes - abool('isCompressed', isCompressed) - if (isCompressed) { - return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) - } else { - return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) - } - }, - fromBytes(bytes) { - const len = bytes.length - const head = bytes[0] - const tail = bytes.subarray(1) - // this.assertValidity() is done inside of fromHex - if (len === compressedLen && (head === 0x02 || head === 0x03)) { - const x = ut.bytesToNumberBE(tail) - if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') - const y2 = weierstrassEquation(x) // y² = x³ + ax + b - let y - try { - y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 - } catch (sqrtError) { - const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' - throw new Error('Point is not on curve' + suffix) - } - const isYOdd = (y & _1n) === _1n - // ECDSA - const isHeadOdd = (head & 1) === 1 - if (isHeadOdd !== isYOdd) y = Fp.neg(y) - return { x, y } - } else if (len === uncompressedLen && head === 0x04) { - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - } else { - const cl = compressedLen - const ul = uncompressedLen - throw new Error( - 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, - ) - } - }, - }) - const numToNByteStr = (num) => ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) - function isBiggerThanHalfOrder(number) { - const HALF = CURVE_ORDER >> _1n - return number > HALF - } - function normalizeS(s) { - return isBiggerThanHalfOrder(s) ? modN(-s) : s - } - // slice bytes num - const slcNum = (b, from, to) => ut.bytesToNumberBE(b.slice(from, to)) - /** - * ECDSA signature with its (r, s) properties. Supports DER & compact representations. - */ - class Signature { - constructor(r, s, recovery) { - this.r = r - this.s = s - this.recovery = recovery - this.assertValidity() - } - // pair (bytes of r, bytes of s) - static fromCompact(hex) { - const l = CURVE.nByteLength - hex = ensureBytes('compactSignature', hex, l * 2) - return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) - } - // DER encoded ECDSA signature - // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script - static fromDER(hex) { - const { r, s } = DER.toSig(ensureBytes('DER', hex)) - return new Signature(r, s) - } - assertValidity() { - ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] - ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] - } - addRecoveryBit(recovery) { - return new Signature(this.r, this.s, recovery) - } - recoverPublicKey(msgHash) { - const { r, s, recovery: rec } = this - const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash - if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') - const radj = rec === 2 || rec === 3 ? r + CURVE.n : r - if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') - const prefix = (rec & 1) === 0 ? '02' : '03' - const R = Point.fromHex(prefix + numToNByteStr(radj)) - const ir = invN(radj) // r^-1 - const u1 = modN(-h * ir) // -hr^-1 - const u2 = modN(s * ir) // sr^-1 - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) - if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked - Q.assertValidity() - return Q - } - // Signatures should be low-s, to prevent malleability. - hasHighS() { - return isBiggerThanHalfOrder(this.s) - } - normalizeS() { - return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this - } - // DER-encoded - toDERRawBytes() { - return ut.hexToBytes(this.toDERHex()) - } - toDERHex() { - return DER.hexFromSig({ r: this.r, s: this.s }) - } - // padded bytes of r, then padded bytes of s - toCompactRawBytes() { - return ut.hexToBytes(this.toCompactHex()) - } - toCompactHex() { - return numToNByteStr(this.r) + numToNByteStr(this.s) - } - } - const utils = { - isValidPrivateKey(privateKey) { - try { - normPrivateKeyToScalar(privateKey) - return true - } catch (error) { - return false - } - }, - normPrivateKeyToScalar: normPrivateKeyToScalar, - /** - * Produces cryptographically secure private key from random of size - * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. - */ - randomPrivateKey: () => { - const length = getMinHashLength(CURVE.n) - return mapHashToField(CURVE.randomBytes(length), CURVE.n) - }, - /** - * Creates precompute table for an arbitrary EC point. Makes point "cached". - * Allows to massively speed-up `point.multiply(scalar)`. - * @returns cached point - * @example - * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); - * fast.multiply(privKey); // much faster ECDH now - */ - precompute(windowSize = 8, point = Point.BASE) { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here - return point - }, - } - /** - * Computes public key for a private key. Checks for validity of the private key. - * @param privateKey private key - * @param isCompressed whether to return compact (default), or full key - * @returns Public key, full when isCompressed=false; short when isCompressed=true - */ - function getPublicKey(privateKey, isCompressed = true) { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) - } - /** - * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. - */ - function isProbPub(item) { - const arr = ut.isBytes(item) - const str = typeof item === 'string' - const len = (arr || str) && item.length - if (arr) return len === compressedLen || len === uncompressedLen - if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen - if (item instanceof Point) return true - return false - } - /** - * ECDH (Elliptic Curve Diffie Hellman). - * Computes shared public key from private key and public key. - * Checks: 1) private key validity 2) shared key is on-curve. - * Does NOT hash the result. - * @param privateA private key - * @param publicB different public key - * @param isCompressed whether to return compact (default), or full key - * @returns shared public key - */ - function getSharedSecret(privateA, publicB, isCompressed = true) { - if (isProbPub(privateA)) throw new Error('first arg must be private key') - if (!isProbPub(publicB)) throw new Error('second arg must be public key') - const b = Point.fromHex(publicB) // check for being on-curve - return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) - } - // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. - // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. - // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. - // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors - const bits2int = - CURVE.bits2int || - function (bytes) { - // Our custom check "just in case" - if (bytes.length > 8192) throw new Error('input is too large') - // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) - // for some cases, since bytes.length * 8 is not actual bitLength. - const num = ut.bytesToNumberBE(bytes) // check for == u8 done here - const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits - return delta > 0 ? num >> BigInt(delta) : num - } - const bits2int_modN = - CURVE.bits2int_modN || - function (bytes) { - return modN(bits2int(bytes)) // can't use bytesToNumberBE here - } - // NOTE: pads output with zero as per spec - const ORDER_MASK = ut.bitMask(CURVE.nBitLength) - /** - * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. - */ - function int2octets(num) { - ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) - // works with order, can have different size than numToField! - return ut.numberToBytesBE(num, CURVE.nByteLength) - } - // Steps A, D of RFC6979 3.2 - // Creates RFC6979 seed; converts msg/privKey to numbers. - // Used only in sign, not in verify. - // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, - // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 - function prepSig(msgHash, privateKey, opts = defaultSigOpts) { - if (['recovered', 'canonical'].some((k) => k in opts)) - throw new Error('sign() legacy options not supported') - const { hash, randomBytes } = CURVE - let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default - if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash - msgHash = ensureBytes('msgHash', msgHash) - validateSigVerOpts(opts) - if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) - // We can't later call bits2octets, since nested bits2int is broken for curves - // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. - // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) - const h1int = bits2int_modN(msgHash) - const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint - const seedArgs = [int2octets(d), int2octets(h1int)] - // extraEntropy. RFC6979 3.6: additional k' (optional). - if (ent != null && ent !== false) { - // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is - seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes - } - const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 - const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! - // Converts signature params into point w r/s, checks result for validity. - function k2sig(kBytes) { - // RFC 6979 Section 3.2, step 3: k = bits2int(T) - const k = bits2int(kBytes) // Cannot use fields methods, since it is group element - if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N - const ik = invN(k) // k^-1 mod n - const q = Point.BASE.multiply(k).toAffine() // q = Gk - const r = modN(q.x) // r = q.x mod n - if (r === _0n) return - // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to - // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: - // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT - const s = modN(ik * modN(m + r * d)) // Not using blinding here - if (s === _0n) return - let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) - let normS = s - if (lowS && isBiggerThanHalfOrder(s)) { - normS = normalizeS(s) // if lowS was passed, ensure s is always - recovery ^= 1 // // in the bottom half of N - } - return new Signature(r, normS, recovery) // use normS, not s - } - return { seed, k2sig } - } - const defaultSigOpts = { lowS: CURVE.lowS, prehash: false } - const defaultVerOpts = { lowS: CURVE.lowS, prehash: false } - /** - * Signs message hash with a private key. - * ``` - * sign(m, d, k) where - * (x, y) = G × k - * r = x mod n - * s = (m + dr)/k mod n - * ``` - * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. - * @param privKey private key - * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. - * @returns signature with recovery param - */ - function sign(msgHash, privKey, opts = defaultSigOpts) { - const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. - const C = CURVE - const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) - return drbg(seed, k2sig) // Steps B, C, D, E, F, G - } - // Enable precomputes. Slows down first publicKey computation by 20ms. - Point.BASE._setWindowSize(8) - // utils.precompute(8, ProjectivePoint.BASE) - /** - * Verifies a signature against message hash and public key. - * Rejects lowS signatures by default: to override, - * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: - * - * ``` - * verify(r, s, h, P) where - * U1 = hs^-1 mod n - * U2 = rs^-1 mod n - * R = U1⋅G - U2⋅P - * mod(R.x, n) == r - * ``` - */ - function verify(signature, msgHash, publicKey, opts = defaultVerOpts) { - const sg = signature - msgHash = ensureBytes('msgHash', msgHash) - publicKey = ensureBytes('publicKey', publicKey) - const { lowS, prehash, format } = opts - // Verify opts, deduce signature format - validateSigVerOpts(opts) - if ('strict' in opts) throw new Error('options.strict was renamed to lowS') - if (format !== undefined && format !== 'compact' && format !== 'der') - throw new Error('format must be compact or der') - const isHex = typeof sg === 'string' || ut.isBytes(sg) - const isObj = - !isHex && - !format && - typeof sg === 'object' && - sg !== null && - typeof sg.r === 'bigint' && - typeof sg.s === 'bigint' - if (!isHex && !isObj) - throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') - let _sig = undefined - let P - try { - if (isObj) _sig = new Signature(sg.r, sg.s) - if (isHex) { - // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). - // Since DER can also be 2*nByteLength bytes, we check for it first. - try { - if (format !== 'compact') _sig = Signature.fromDER(sg) - } catch (derError) { - if (!(derError instanceof DER.Err)) throw derError - } - if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) - } - P = Point.fromHex(publicKey) - } catch (error) { - return false - } - if (!_sig) return false - if (lowS && _sig.hasHighS()) return false - if (prehash) msgHash = CURVE.hash(msgHash) - const { r, s } = _sig - const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element - const is = invN(s) // s^-1 - const u1 = modN(h * is) // u1 = hs^-1 mod n - const u2 = modN(r * is) // u2 = rs^-1 mod n - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P - if (!R) return false - const v = modN(R.x) - return v === r - } - return { - CURVE, - getPublicKey, - getSharedSecret, - sign, - verify, - ProjectivePoint: Point, - Signature, - utils, - } -} -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -export function SWUFpSqrtRatio(Fp, Z) { - // Generic implementation - const q = Fp.ORDER - let l = _0n - for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n - const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. - // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. - // 2n ** c1 == 2n << (c1-1) - const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) - const _2n_pow_c1 = _2n_pow_c1_1 * _2n - const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic - const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic - const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic - const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic - const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 - const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) - let sqrtRatio = (u, v) => { - let tv1 = c6 // 1. tv1 = c6 - let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 - let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 - tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v - let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 - tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 - tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 - tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v - tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u - let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 - tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 - let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 - tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 - tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) - // 17. for i in (c1, c1 - 1, ..., 2): - for (let i = c1; i > _1n; i--) { - let tv5 = i - _2n // 18. tv5 = i - 2 - tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 - let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 - const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 - tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 - tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 - tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) - } - return { isValid: isQR, value: tv3 } - } - if (Fp.ORDER % _4n === _3n) { - // sqrt_ratio_3mod4(u, v) - const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic - const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) - sqrtRatio = (u, v) => { - let tv1 = Fp.sqr(v) // 1. tv1 = v^2 - const tv2 = Fp.mul(u, v) // 2. tv2 = u * v - tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 - let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 - y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 - const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 - const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v - const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u - let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) - return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 - } - } - // No curves uses that - // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 - return sqrtRatio -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -export function mapToCurveSimpleSWU(Fp, opts) { - validateField(Fp) - if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) - throw new Error('mapToCurveSimpleSWU: invalid opts') - const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) - if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') - // Input: u, an element of F. - // Output: (x, y), a point on E. - return (u) => { - // prettier-ignore - let tv1, tv2, tv3, tv4, tv5, tv6, x, y - tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 - tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 - tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 - tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 - tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 - tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) - tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 - tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 - tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 - tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 - tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 - tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 - tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 - tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 - tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 - x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 - const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) - y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 - y = Fp.mul(y, value) // 20. y = y * y1 - x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) - y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) - const e1 = Fp.isOdd(u) === Fp.isOdd(y) // 23. e1 = sgn0(u) == sgn0(y) - y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) - x = Fp.div(x, tv4) // 25. x = x / tv4 - return { x, y } - } -} -//# sourceMappingURL=weierstrass.js.map diff --git a/packages/noble-curves/esm/abstract/weierstrass.js.map b/packages/noble-curves/esm/abstract/weierstrass.js.map deleted file mode 100644 index b46193cd5b2..00000000000 --- a/packages/noble-curves/esm/abstract/weierstrass.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"weierstrass.js","sourceRoot":"","sources":["../../src/abstract/weierstrass.ts"],"names":[],"mappings":"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AAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;YAC/B,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,GA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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bls12-381.d.ts b/packages/noble-curves/esm/bls12-381.d.ts deleted file mode 100644 index 8de19050c1e..00000000000 --- a/packages/noble-curves/esm/bls12-381.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type CurveFn } from './abstract/bls.js' -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -export declare const bls12_381: CurveFn -//# sourceMappingURL=bls12-381.d.ts.map diff --git a/packages/noble-curves/esm/bls12-381.d.ts.map b/packages/noble-curves/esm/bls12-381.d.ts.map deleted file mode 100644 index 141ca4fe3aa..00000000000 --- a/packages/noble-curves/esm/bls12-381.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls12-381.d.ts","sourceRoot":"","sources":["../src/bls12-381.ts"],"names":[],"mappings":"AA+DA,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAkXtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,EAAE,OAqUtB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bls12-381.js b/packages/noble-curves/esm/bls12-381.js deleted file mode 100644 index 31c7d06e544..00000000000 --- a/packages/noble-curves/esm/bls12-381.js +++ /dev/null @@ -1,747 +0,0 @@ -/** - * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: - * * Construct zk-SNARKs at the ~120-bit security - * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: - * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr - * - * ### Summary - * 1. BLS Relies on Bilinear Pairing (expensive) - * 2. Private Keys: 32 bytes - * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. - * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. - * - The signature is a point on the G2 subgroup, which is defined over a finite field - * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the - * complex numbers). - * - We also support reversed 96-byte pubkeys & 48-byte short signatures. - * 5. The 12 stands for the Embedding degree. - * - * ### Formulas - * - `P = pk x G` - public keys - * - `S = pk x H(m)` - signing - * - `e(P, H(m)) == e(G, S)` - verification using pairings - * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation - * - * ### Compatibility and notes - * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. - * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. - * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". - * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) - * 4. Compatible with specs: - * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), - * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), - * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * - * ### Params - * To verify curve parameters, see - * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). - * Basic math is done over finite fields over p. - * More complicated math is done over polynominal extension fields. - * To simplify calculations in Fp12, we construct extension tower: - * - * Embedding degree (k): 12 - * Seed (X): -15132376222941642752 - * Fr: (x⁴-x²+1) - * Fp: ((x-1)² ⋅ r(x)/3+x) - * (E/Fp): Y²=X³+4 - * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) - * Ate loop size: X - * - * ### Towers - * - Fp₁₂ = Fp₆² => Fp₂³ - * - Fp(u) / (u² - β) where β = -1 - * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 - * - Fp₆(w) / (w² - γ) where γ = v - * - Fp²[u] = Fp/u²+1 - * - Fp⁶[v] = Fp²/v³-1-u - * - Fp¹²[w] = Fp⁶/w²-v - * - * @todo construct bls & bn fp/fr from seed. - * @module - */ -console.log('N NOBLE CURVEEEEEEEEEEEE') -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { bls } from './abstract/bls.js' -// Types -import { isogenyMap } from './abstract/hash-to-curve.js' -import * as mod from './abstract/modular.js' -import { psiFrobenius, tower12 } from './abstract/tower.js' -import { - bitGet, - bitLen, - bytesToHex, - bytesToNumberBE, - concatBytes as concatB, - ensureBytes, - numberToBytesBE, -} from './abstract/utils.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) -// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! -const BLS_X = BigInt('0xd201000000010000') -const BLS_X_LEN = bitLen(BLS_X) -// CURVE FIELDS -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - // Order of Fp - ORDER: BigInt( - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', - ), - // Finite extension field over irreducible polynominal. - // Fp(u) / (u² - β) where β = -1 - FP2_NONRESIDUE: [_1n, _1n], - Fp2mulByB: ({ c0, c1 }) => { - const t0 = Fp.mul(c0, _4n) // 4 * c0 - const t1 = Fp.mul(c1, _4n) // 4 * c1 - // (T0-T1) + (T0+T1)*i - return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } - }, - // Fp12 - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }) => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BLS_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const x = BLS_X - // this^(q⁶) / this - const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) - // t0^(q²) * t0 - const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) - const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) - const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) - const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) - const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) - const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) - const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) - const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) - const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) - const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) - const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) - // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 - return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) - }, -}) -// Finite field over r. -// This particular field is not used anywhere in bls12-381, but it is still useful. -const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) -// END OF CURVE FIELDS -// HashToCurve -// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 -const isogenyMapG2 = isogenyMap( - Fp2, - [ - // xNum - [ - [ - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - ], - [ - '0x0', - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', - ], - [ - '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', - '0x0', - ], - ], - // xDen - [ - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', - ], - [ - '0xc', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', - ], - ['0x1', '0x0'], // LAST 1 - ], - // yNum - [ - [ - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - ], - [ - '0x0', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', - ], - [ - '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', - '0x0', - ], - ], - // yDen - [ - [ - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - ], - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', - ], - [ - '0x12', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', - ], - ['0x1', '0x0'], // LAST 1 - ], - ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))), -) -// 11-isogeny map from E' to E -const isogenyMapG1 = isogenyMap( - Fp, - [ - // xNum - [ - '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', - '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', - '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', - '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', - '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', - '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', - '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', - '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', - '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', - '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', - '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', - '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', - ], - // xDen - [ - '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', - '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', - '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', - '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', - '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', - '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', - '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', - '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', - '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', - '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', - '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', - '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', - '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', - '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', - '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', - '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', - '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', - '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', - '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', - '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', - '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', - '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', - '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', - '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', - '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', - ], - // yDen - [ - '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', - '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', - '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', - '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', - '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', - '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', - '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', - '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', - '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', - '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', - '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', - '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', - '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', - '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', - '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))), -) -// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i -const G2_SWU = mapToCurveSimpleSWU(Fp2, { - A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I - B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) - Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) -}) -// Optimized SWU Map - Fp to G1 -const G1_SWU = mapToCurveSimpleSWU(Fp, { - A: Fp.create( - BigInt( - '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', - ), - ), - B: Fp.create( - BigInt( - '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', - ), - ), - Z: Fp.create(BigInt(11)), -}) -// Endomorphisms (for fast cofactor clearing) -// Ψ(P) endomorphism -const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) -// Default hash_to_field options are for hash to G2. -// -// Parameter definitions are in section 5.3 of the spec unless otherwise noted. -// Parameter values come from section 8.8.2 of the spec. -// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 -// -// Base field F is GF(p^m) -// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab -// m = 2 (or 1 for G1 see section 8.8.1) -// k = 128 -const htfDefaults = Object.freeze({ - // DST: a domain separation tag - // defined in section 2.2.5 - // Use utils.getDSTLabel(), utils.setDSTLabel(value) - DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - // p: the characteristic of F - // where F is a finite field of characteristic p and order q = p^m - p: Fp.ORDER, - // m: the extension degree of F, m >= 1 - // where F is a finite field of characteristic p and order q = p^m - m: 2, - // k: the target security level for the suite in bits - // defined in section 5.1 - k: 128, - // option to use a message that has already been processed by - // expand_message_xmd - expand: 'xmd', - // Hash functions for: expand_message_xmd is appropriate for use with a - // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. - // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 - hash: sha256, -}) -// Encoding utils -// Point on G1 curve: (x, y) -// Compressed point of infinity -const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits -function parseMask(bytes) { - // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. - bytes = bytes.slice() - const mask = bytes[0] & 224 - const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) - const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) - const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) - bytes[0] &= 31 // clear mask (zero first 3 bits) - return { compressed, infinity, sort, value: bytes } -} -function setMask(bytes, mask) { - if (bytes[0] & 224) throw new Error('setMask: non-empty mask') - if (mask.compressed) bytes[0] |= 128 - if (mask.infinity) bytes[0] |= 64 - if (mask.sort) bytes[0] |= 32 - return bytes -} -function signatureG1ToRawBytes(point) { - point.assertValidity() - const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) - const { x, y } = point.toAffine() - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) -} -function signatureG2ToRawBytes(point) { - // NOTE: by some reasons it was missed in bls12-381, looks like bug - point.assertValidity() - const len = Fp.BYTES - if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) - return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const { x, y } = point.toAffine() - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - const tmp = y1 > _0n ? y1 * _2n : y0 * _2n - const sort = Boolean((tmp / Fp.ORDER) & _1n) - const z2 = x0 - return concatB( - setMask(numberToBytesBE(x1, len), { sort, compressed: true }), - numberToBytesBE(z2, len), - ) -} -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -export const bls12_381 = bls({ - // Fields - fields: { - Fp, - Fp2, - Fp6, - Fp12, - Fr, - }, - // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where - // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 - G1: { - Fp, - // cofactor; (z - 1)²/3 - h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), - // generator's coordinates - // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 - // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 - Gx: BigInt( - '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', - ), - Gy: BigInt( - '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', - ), - a: Fp.ZERO, - b: _4n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, point) => { - // φ endomorphism - const cubicRootOfUnityModP = BigInt( - '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', - ) - const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) - // todo: unroll - const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P - const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P - return u2P.equals(phi) - // https://eprint.iacr.org/2019/814.pdf - // (z² − 1)/3 - // const c1 = BigInt('0x396c8c005555e1560000000055555555'); - // const P = this; - // const S = P.sigma(); - // const Q = S.double(); - // const S2 = S.sigma(); - // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O - // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); - // const C = left.subtract(S2); - // return C.isZero(); - }, - // Clear cofactor of G1 - // https://eprint.iacr.org/2019/403 - clearCofactor: (_c, point) => { - // return this.multiplyUnsafe(CURVE.h); - return point.multiplyUnsafe(BLS_X).add(point) // x*P + P - }, - mapToCurve: (scalars) => { - const { x, y } = G1_SWU(Fp.create(scalars[0])) - return isogenyMapG1(x, y) - }, - fromBytes: (bytes) => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if (value.length === 48 && compressed) { - // TODO: Fp.bytes - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - const x = Fp.create(compressedValue & Fp.MASK) - if (infinity) { - if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') - return { x: _0n, y: _0n } - } - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) - return { x: Fp.create(x), y: Fp.create(y) } - } else if (value.length === 96 && !compressed) { - // Check if the infinity flag is set - const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) - const y = bytesToNumberBE(value.subarray(Fp.BYTES)) - if (infinity) { - if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') - return bls12_381.G1.ProjectivePoint.ZERO.toAffine() - } - return { x: Fp.create(x), y: Fp.create(y) } - } else { - throw new Error('invalid point G1, expected 48/96 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) - } else { - if (isZero) { - // 2x PUBLIC_KEY_LENGTH - const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) - return x - } else { - return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) - } - } - }, - ShortSignature: { - fromHex(hex) { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - if (infinity) return bls12_381.G1.ProjectivePoint.ZERO - const x = Fp.create(compressedValue & Fp.MASK) - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - const aflag = BigInt(sort) - if ((y * _2n) / P !== aflag) y = Fp.neg(y) - const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point) { - return signatureG1ToRawBytes(point) - }, - toHex(point) { - return bytesToHex(signatureG1ToRawBytes(point)) - }, - }, - }, - // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), - // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where - // G² - 1 - // h2q - G2: { - Fp: Fp2, - // cofactor - h: BigInt( - '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', - ), - Gx: Fp2.fromBigTuple([ - BigInt( - '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', - ), - BigInt( - '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', - ), - ]), - // y = - // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, - // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 - Gy: Fp2.fromBigTuple([ - BigInt( - '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', - ), - BigInt( - '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', - ), - ]), - a: Fp2.ZERO, - b: Fp2.fromBigTuple([_4n, _4n]), - hEff: BigInt( - '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', - ), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: (scalars) => { - const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) - return isogenyMapG2(x, y) - }, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, P) => { - return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) - // Older version: https://eprint.iacr.org/2019/814.pdf - // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O - // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); - }, - // Maps the point into the prime-order subgroup G2. - // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 - // https://eprint.iacr.org/2017/419.pdf - // prettier-ignore - clearCofactor: (c, P) => { - const x = BLS_X - let t1 = P.multiplyUnsafe(x).negate() // [-x]P - let t2 = G2psi(c, P) // Ψ(P) - let t3 = P.double() // 2P - t3 = G2psi2(c, t3) // Ψ²(2P) - t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) - t2 = t1.add(t2) // [-x]P + Ψ(P) - t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) - t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) - t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P - return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) - }, - fromBytes: (bytes) => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if ( - (!compressed && !infinity && sort) || // 00100000 - (!compressed && infinity && sort) || // 01100000 - (sort && infinity && compressed) // 11100000 - ) { - throw new Error('invalid encoding flag: ' + (bytes[0] & 224)) - } - const L = Fp.BYTES - const slc = (b, from, to) => bytesToNumberBE(b.slice(from, to)) - if (value.length === 96 && compressed) { - const b = bls12_381.params.G2b - const P = Fp.ORDER - if (infinity) { - // check that all bytes are 0 - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid compressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x_1 = slc(value, 0, L) - const x_0 = slc(value, L, 2 * L) - const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) - const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b - let y = Fp2.sqrt(right) - const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n - y = sort && Y_bit > 0 ? y : Fp2.neg(y) - return { x, y } - } else if (value.length === 192 && !compressed) { - if (infinity) { - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid uncompressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x1 = slc(value, 0, L) - const x0 = slc(value, L, 2 * L) - const y1 = slc(value, 2 * L, 3 * L) - const y0 = slc(value, 3 * L, 4 * L) - return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } - } else { - throw new Error('invalid point G2, expected 96/192 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const { BYTES: len, ORDER: P } = Fp - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) - return concatB( - setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), - numberToBytesBE(x.c0, len), - ) - } else { - if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - return concatB( - numberToBytesBE(x1, len), - numberToBytesBE(x0, len), - numberToBytesBE(y1, len), - numberToBytesBE(y0, len), - ) - } - }, - Signature: { - // TODO: Optimize, it's very slow because of sqrt. - fromHex(hex) { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) - const P = Fp.ORDER - const half = value.length / 2 - if (half !== 48 && half !== 96) - throw new Error('invalid compressed signature length, must be 96 or 192') - const z1 = bytesToNumberBE(value.slice(0, half)) - const z2 = bytesToNumberBE(value.slice(half)) - // Indicates the infinity point - if (infinity) return bls12_381.G2.ProjectivePoint.ZERO - const x1 = Fp.create(z1 & Fp.MASK) - const x2 = Fp.create(z2) - const x = Fp2.create({ c0: x2, c1: x1 }) - const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 - // The slow part - let y = Fp2.sqrt(y2) - if (!y) throw new Error('Failed to find a square root') - // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 - // If y1 happens to be zero, then use the bit of y0 - const { re: y0, im: y1 } = Fp2.reim(y) - const aflag1 = BigInt(sort) - const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 - const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 - if (isGreater || isZero) y = Fp2.neg(y) - const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point) { - return signatureG2ToRawBytes(point) - }, - toHex(point) { - return bytesToHex(signatureG2ToRawBytes(point)) - }, - }, - }, - params: { - ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 - r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves - xNegative: true, - twistType: 'multiplicative', - }, - htfDefaults, - hash: sha256, - randomBytes, -}) -//# sourceMappingURL=bls12-381.js.map diff --git a/packages/noble-curves/esm/bls12-381.js.map b/packages/noble-curves/esm/bls12-381.js.map deleted file mode 100644 index e895207ab32..00000000000 --- a/packages/noble-curves/esm/bls12-381.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bls12-381.js","sourceRoot":"","sources":["../src/bls12-381.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bn254.d.ts b/packages/noble-curves/esm/bn254.d.ts deleted file mode 100644 index 94c05dba695..00000000000 --- a/packages/noble-curves/esm/bn254.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { type CurveFn as BLSCurveFn, type PostPrecomputeFn } from './abstract/bls.js' -import { type CurveFn } from './abstract/weierstrass.js' -export declare const _postPrecompute: PostPrecomputeFn -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -export declare const bn254: BLSCurveFn -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - */ -export declare const bn254_weierstrass: CurveFn -//# sourceMappingURL=bn254.d.ts.map diff --git a/packages/noble-curves/esm/bn254.d.ts.map b/packages/noble-curves/esm/bn254.d.ts.map deleted file mode 100644 index 390306a81dc..00000000000 --- a/packages/noble-curves/esm/bn254.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bn254.d.ts","sourceRoot":"","sources":["../src/bn254.ts"],"names":[],"mappings":"AAkDA,OAAO,EAEL,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAgGtE,eAAO,MAAM,eAAe,EAAE,gBAY7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,UA6DlB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAS9B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/bn254.js b/packages/noble-curves/esm/bn254.js deleted file mode 100644 index d883a68d504..00000000000 --- a/packages/noble-curves/esm/bn254.js +++ /dev/null @@ -1,233 +0,0 @@ -/** - * bn254, previously known as alt_bn_128, when it had 128-bit security. - -Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, -so the naming has been adjusted to its prime bit count: -https://hal.science/hal-01534101/file/main.pdf. -Compatible with EIP-196 and EIP-197. - -There are huge compatibility issues in the ecosystem: - -1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". -2. libff has bn128, but it's a different curve with different G2: - https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 -3. halo2curves bn256 is also incompatible and returns different outputs - -The goal of our implementation is to support "Ethereum" variant of the curve, -because it at least has specs: - -- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM -- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings -- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 -- The existing implementations are bad. Some are deprecated: - - https://github.com/paritytech/bn (old version) - - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) - - https://github.com/zcash-hackworks/bn - - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs -- Python implementations use different towers and produce different Fp12 outputs: - - https://github.com/ethereum/py_pairing - - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py -- Points are encoded differently in different implementations - -### Params -Seed (X): 4965661367192848881 -Fr: (36x⁴+36x³+18x²+6x+1) -Fp: (36x⁴+36x³+24x²+6x+1) -(E / Fp ): Y² = X³+3 -(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) -Ate loop size: 6x+2 - -### Towers -- Fp²[u] = Fp/u²+1 -- Fp⁶[v] = Fp²/v³-9-u -- Fp¹²[w] = Fp⁶/w²-v - - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { getHash } from './_shortw_utils.js' -import { bls } from './abstract/bls.js' -import { Field } from './abstract/modular.js' -import { psiFrobenius, tower12 } from './abstract/tower.js' -import { bitGet, bitLen, notImplemented } from './abstract/utils.js' -import { weierstrass } from './abstract/weierstrass.js' -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -const _6n = BigInt(6) -const BN_X = BigInt('4965661367192848881') -const BN_X_LEN = bitLen(BN_X) -const SIX_X_SQUARED = _6n * BN_X ** _2n -// Finite field over r. It's for convenience and is not used in the code below. -const Fr = Field( - BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), -) -// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) -const Fp2B = { - c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), - c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), -} -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), - FP2_NONRESIDUE: [BigInt(9), _1n], - Fp2mulByB: (num) => Fp2.mul(num, Fp2B), - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }) => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BN_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const powMinusX = (num) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) - const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) - const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) - const y1 = Fp12._cyclotomicSquare(powMinusX(r)) - const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) - const y4 = powMinusX(y2) - const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) - const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) - const y9 = Fp12.mul(y8, y1) - return Fp12.mul( - Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), - Fp12.mul( - Fp12.frobeniusMap(y8, 2), - Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), - ), - ) - }, -}) -// END OF CURVE FIELDS -const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) -/* -No hashToCurve for now (and signatures): - -- RFC 9380 doesn't mention bn254 and doesn't provide test vectors -- Overall seems like nobody is using BLS signatures on top of bn254 -- Seems like it can utilize SVDW, which is not implemented yet -*/ -const htfDefaults = Object.freeze({ - // DST: a domain separation tag defined in section 2.2.5 - DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - p: Fp.ORDER, - m: 2, - k: 128, - expand: 'xmd', - hash: sha256, -}) -export const _postPrecompute = (Rx, Ry, Rz, Qx, Qy, pointAdd) => { - const q = psi(Qx, Qy) - ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) - const q2 = psi(q[0], q[1]) - pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) -} -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -export const bn254 = bls({ - // Fields - fields: { Fp, Fp2, Fp6, Fp12, Fr }, - G1: { - Fp, - h: BigInt(1), - Gx: BigInt(1), - Gy: BigInt(2), - a: Fp.ZERO, - b: _3n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - ShortSignature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - G2: { - Fp: Fp2, - // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 - h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - Gx: Fp2.fromBigTuple([ - BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), - BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), - ]), - Gy: Fp2.fromBigTuple([ - BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), - BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), - ]), - a: Fp2.ZERO, - b: Fp2B, - hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - Signature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - params: { - ateLoopSize: BN_X * _6n + _2n, - r: Fr.ORDER, - xNegative: false, - twistType: 'divisive', - }, - htfDefaults, - hash: sha256, - randomBytes, - postPrecompute: _postPrecompute, -}) -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - */ -export const bn254_weierstrass = weierstrass({ - a: BigInt(0), - b: BigInt(3), - Fp, - n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), - Gx: BigInt(1), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) -//# sourceMappingURL=bn254.js.map diff --git a/packages/noble-curves/esm/bn254.js.map b/packages/noble-curves/esm/bn254.js.map deleted file mode 100644 index 2c0cdbfd3f1..00000000000 --- a/packages/noble-curves/esm/bn254.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"bn254.js","sourceRoot":"","sources":["../src/bn254.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed25519.d.ts b/packages/noble-curves/esm/ed25519.d.ts deleted file mode 100644 index b7f9565cc9a..00000000000 --- a/packages/noble-curves/esm/ed25519.d.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { type AffinePoint, type Group } from './abstract/curve.js' -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' -import { type CurveFn as XCurveFn } from './abstract/montgomery.js' -import { type Hex } from './abstract/utils.js' -export declare const ED25519_TORSION_SUBGROUP: string[] -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -export declare const ed25519: CurveFn -export declare const ed25519ctx: CurveFn -export declare const ed25519ph: CurveFn -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -export declare const x25519: XCurveFn -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -export declare function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array -export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -export declare function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array -export declare const hashToCurve: HTFMethod -export declare const encodeToCurve: HTFMethod -type ExtendedPoint = ExtPointType -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -declare class RistPoint implements Group { - private readonly ep - static BASE: RistPoint - static ZERO: RistPoint - constructor(ep: ExtendedPoint) - static fromAffine(ap: AffinePoint): RistPoint - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex: Hex): RistPoint - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex: Hex): RistPoint - static msm(points: RistPoint[], scalars: bigint[]): RistPoint - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes(): Uint8Array - toHex(): string - toString(): string - equals(other: RistPoint): boolean - add(other: RistPoint): RistPoint - subtract(other: RistPoint): RistPoint - multiply(scalar: bigint): RistPoint - multiplyUnsafe(scalar: bigint): RistPoint - double(): RistPoint - negate(): RistPoint -} -export declare const RistrettoPoint: typeof RistPoint -export declare const hashToRistretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint -export declare const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint -export {} -//# sourceMappingURL=ed25519.d.ts.map diff --git a/packages/noble-curves/esm/ed25519.d.ts.map b/packages/noble-curves/esm/ed25519.d.ts.map deleted file mode 100644 index 3784c84d890..00000000000 --- a/packages/noble-curves/esm/ed25519.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAa,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AAmE7B,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAS5C,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,OAAmE,CAAC;AAY1F,eAAO,MAAM,UAAU,EAAE,OAIlB,CAAC;AACR,eAAO,MAAM,SAAS,EAAE,OAMlB,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,EAAE,QAed,CAAC;AAER;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAIlE;AACD,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAG3E;AA0FD,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AAiC5F,KAAK,aAAa,GAAG,YAAY,CAAC;AA0BlC;;;;;;GAMG;AACH,cAAM,SAAU,YAAW,KAAK,CAAC,SAAS,CAAC;IAK7B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC;gBAGM,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS;IAIrD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IASvC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS;IA2BnC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAS;IAK7D;;;OAGG;IACH,UAAU,IAAI,UAAU;IA4BxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAKlB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAWjC,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKhC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAKrC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAInC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAIzC,MAAM,IAAI,SAAS;IAInB,MAAM,IAAI,SAAS;CAGpB;AACD,eAAO,MAAM,cAAc,EAAE,OAAO,SAIhC,CAAC;AAGL,eAAO,MAAM,kBAAkB,QAAS,UAAU,WAAW,YAAY,KAAG,SAM3E,CAAC;AACF,eAAO,MAAM,oBAAoB,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,KAAK,SAC3D,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed25519.js b/packages/noble-curves/esm/ed25519.js deleted file mode 100644 index a3747505544..00000000000 --- a/packages/noble-curves/esm/ed25519.js +++ /dev/null @@ -1,493 +0,0 @@ -/** - * ed25519 Twisted Edwards curve with following addons: - * - X25519 ECDH - * - Ristretto cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha512 } from '@noble/hashes/sha512' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { pippenger } from './abstract/curve.js' -import { twistedEdwards } from './abstract/edwards.js' -import { createHasher, expand_message_xmd } from './abstract/hash-to-curve.js' -import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.js' -import { montgomery } from './abstract/montgomery.js' -import { - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.js' -const ED25519_P = BigInt( - '57896044618658097711785492504343953926634992332820282019728792003956564819949', -) -// √(-1) aka √(a) aka 2^((p-1)/4) -const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( - '19681161376707505956807079304988542015446066515923890162744021073123829784752', -) -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// prettier-ignore -const _5n = BigInt(5), - _8n = BigInt(8) -function ed25519_pow_2_252_3(x) { - // prettier-ignore - const _10n = BigInt(10), - _20n = BigInt(20), - _40n = BigInt(40), - _80n = BigInt(80) - const P = ED25519_P - const x2 = (x * x) % P - const b2 = (x2 * x) % P // x^3, 11 - const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 - const b5 = (pow2(b4, _1n, P) * x) % P // x^31 - const b10 = (pow2(b5, _5n, P) * b5) % P - const b20 = (pow2(b10, _10n, P) * b10) % P - const b40 = (pow2(b20, _20n, P) * b20) % P - const b80 = (pow2(b40, _40n, P) * b40) % P - const b160 = (pow2(b80, _80n, P) * b80) % P - const b240 = (pow2(b160, _80n, P) * b80) % P - const b250 = (pow2(b240, _10n, P) * b10) % P - const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P - // ^ To pow to (p+3)/8, multiply it by x. - return { pow_p_5_8, b2 } -} -function adjustScalarBytes(bytes) { - // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, - // set the three least significant bits of the first byte - bytes[0] &= 248 // 0b1111_1000 - // and the most significant bit of the last to zero, - bytes[31] &= 127 // 0b0111_1111 - // set the second most significant bit of the last byte to 1 - bytes[31] |= 64 // 0b0100_0000 - return bytes -} -// sqrt(u/v) -function uvRatio(u, v) { - const P = ED25519_P - const v3 = mod(v * v * v, P) // v³ - const v7 = mod(v3 * v3 * v, P) // v⁷ - // (p+3)/8 and (p-5)/8 - const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 - let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 - const vx2 = mod(v * x * x, P) // vx² - const root1 = x // First root candidate - const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate - const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root - const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) - const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) - if (useRoot1) x = root1 - if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time - if (isNegativeLE(x, P)) x = mod(-x, P) - return { isValid: useRoot1 || useRoot2, value: x } -} -// Just in case -export const ED25519_TORSION_SUBGROUP = [ - '0100000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', - '0000000000000000000000000000000000000000000000000000000000000080', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', - 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', - '0000000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', -] -const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() -const ed25519Defaults = /* @__PURE__ */ (() => ({ - // Param: a - a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster - // d is equal to -121665/121666 over finite field. - // Negative number is P - number, and division is invert(number, P) - d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), - // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n - Fp, - // Subgroup order: how many points curve has - // 2n**252n + 27742317777372353535851937790883648493n; - n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), - // Cofactor - h: _8n, - // Base point (x, y) aka generator point - Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), - Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), - hash: sha512, - randomBytes, - adjustScalarBytes, - // dom2 - // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. - // Constant-time, u/√v - uvRatio, -}))() -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -export const ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() -function ed25519_domain(data, ctx, phflag) { - if (ctx.length > 255) throw new Error('Context is too big') - return concatBytes( - utf8ToBytes('SigEd25519 no Ed25519 collisions'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) -} -export const ed25519ctx = /* @__PURE__ */ (() => - twistedEdwards({ - ...ed25519Defaults, - domain: ed25519_domain, - }))() -export const ed25519ph = /* @__PURE__ */ (() => - twistedEdwards( - Object.assign({}, ed25519Defaults, { - domain: ed25519_domain, - prehash: sha512, - }), - ))() -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -export const x25519 = /* @__PURE__ */ (() => - montgomery({ - P: ED25519_P, - a: BigInt(486662), - montgomeryBits: 255, // n is 253 bits - nByteLength: 32, - Gu: BigInt(9), - powPminus2: (x) => { - const P = ED25519_P - // x^(p-2) aka x^(2^255-21) - const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) - return mod(pow2(pow_p_5_8, _3n, P) * b2, P) - }, - adjustScalarBytes, - randomBytes, - }))() -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub) { - const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) -} -export const edwardsToMontgomery = edwardsToMontgomeryPub // deprecated -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -export function edwardsToMontgomeryPriv(edwardsPriv) { - const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) - return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) -} -// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) -// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since -// SageMath returns different root first and everything falls apart -const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic -const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 -const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) -// prettier-ignore -function map_to_curve_elligator2_curve25519(u) { - const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic - const ELL2_J = BigInt(486662) - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 - let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not - let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) - let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 - tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 - tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 - tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 - tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 - let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) - y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) - let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 - tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 - tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd - let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 - let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt - let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd - let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u - y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 - let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 - let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) - tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 - tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 - let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt - tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd - let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 - let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) - return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) -} -const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 -function map_to_curve_elligator2_edwards25519(u) { - const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = - // map_to_curve_elligator2_curve25519(u) - let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd - xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 - let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM - let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd - let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) - let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd - let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 - xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) - xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) - yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) - yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) - const inv = Fp.invertBatch([xd, yd]) // batch division - return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) -} -const htf = /* @__PURE__ */ (() => - createHasher( - ed25519.ExtendedPoint, - (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]), - { - DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', - encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha512, - }, - ))() -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -function assertRstPoint(other) { - if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') -} -// √(-1) aka √(a) aka 2^((p-1)/4) -const SQRT_M1 = ED25519_SQRT_M1 -// √(ad - 1) -const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( - '25063068953384623474111414158702152701244531502492656460079210482610430750235', -) -// 1 / √(a-d) -const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( - '54469307008909316920995813868745141605393597292927456921205312896311721017578', -) -// 1-d² -const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( - '1159843021668779879193775521855586647937357759715417654439879720876111806838', -) -// (d-1)² -const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( - '40440834346308536858101042469323190826248399146238708352240133220865137265952', -) -// Calculates 1/√(number) -const invertSqrt = (number) => uvRatio(_1n, number) -const MAX_255B = /* @__PURE__ */ BigInt( - '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes255ToNumberLE = (bytes) => ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) -// Computes Elligator map for Ristretto -// https://ristretto.group/formulas/elligator.html -function calcElligatorRistrettoMap(r0) { - const { d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const r = mod(SQRT_M1 * r0 * r0) // 1 - const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 - let c = BigInt(-1) // 3 - const D = mod((c - d * r) * mod(r + d)) // 4 - let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 - let s_ = mod(s * r0) // 6 - if (!isNegativeLE(s_, P)) s_ = mod(-s_) - if (!Ns_D_is_sq) s = s_ // 7 - if (!Ns_D_is_sq) c = r // 8 - const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 - const s2 = s * s - const W0 = mod((s + s) * D) // 10 - const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 - const W2 = mod(_1n - s2) // 12 - const W3 = mod(_1n + s2) // 13 - return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class RistPoint { - // Private property to discourage combining ExtendedPoint + RistrettoPoint - // Always use Ristretto encoding/decoding instead. - constructor(ep) { - this.ep = ep - } - static fromAffine(ap) { - return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) - } - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex) { - hex = ensureBytes('ristrettoHash', hex, 64) - const r1 = bytes255ToNumberLE(hex.slice(0, 32)) - const R1 = calcElligatorRistrettoMap(r1) - const r2 = bytes255ToNumberLE(hex.slice(32, 64)) - const R2 = calcElligatorRistrettoMap(r2) - return new RistPoint(R1.add(R2)) - } - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex) { - hex = ensureBytes('ristrettoHex', hex, 32) - const { a, d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' - const s = bytes255ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 3. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) - const s2 = mod(s * s) - const u1 = mod(_1n + a * s2) // 4 (a is -1) - const u2 = mod(_1n - a * s2) // 5 - const u1_2 = mod(u1 * u1) - const u2_2 = mod(u2 * u2) - const v = mod(a * d * u1_2 - u2_2) // 6 - const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 - const Dx = mod(I * u2) // 8 - const Dy = mod(I * Dx * v) // 9 - let x = mod((s + s) * Dx) // 10 - if (isNegativeLE(x, P)) x = mod(-x) // 10 - const y = mod(u1 * Dy) // 11 - const t = mod(x * y) // 12 - if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) - return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) - } - static msm(points, scalars) { - const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) - return pippenger(RistPoint, Fn, points, scalars) - } - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes() { - let { ex: x, ey: y, ez: z, et: t } = this.ep - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const u1 = mod(mod(z + y) * mod(z - y)) // 1 - const u2 = mod(x * y) // 2 - // Square root always exists - const u2sq = mod(u2 * u2) - const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 - const D1 = mod(invsqrt * u1) // 4 - const D2 = mod(invsqrt * u2) // 5 - const zInv = mod(D1 * D2 * t) // 6 - let D // 7 - if (isNegativeLE(t * zInv, P)) { - let _x = mod(y * SQRT_M1) - let _y = mod(x * SQRT_M1) - x = _x - y = _y - D = mod(D1 * INVSQRT_A_MINUS_D) - } else { - D = D2 // 8 - } - if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 - let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) - if (isNegativeLE(s, P)) s = mod(-s) - return numberToBytesLE(s, 32) // 11 - } - toHex() { - return bytesToHex(this.toRawBytes()) - } - toString() { - return this.toHex() - } - // Compare one point to another. - equals(other) { - assertRstPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed25519.CURVE.Fp.create - // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) - const one = mod(X1 * Y2) === mod(Y1 * X2) - const two = mod(Y1 * Y2) === mod(X1 * X2) - return one || two - } - add(other) { - assertRstPoint(other) - return new RistPoint(this.ep.add(other.ep)) - } - subtract(other) { - assertRstPoint(other) - return new RistPoint(this.ep.subtract(other.ep)) - } - multiply(scalar) { - return new RistPoint(this.ep.multiply(scalar)) - } - multiplyUnsafe(scalar) { - return new RistPoint(this.ep.multiplyUnsafe(scalar)) - } - double() { - return new RistPoint(this.ep.double()) - } - negate() { - return new RistPoint(this.ep.negate()) - } -} -export const RistrettoPoint = /* @__PURE__ */ (() => { - if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) - if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) - return RistPoint -})() -// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B -export const hashToRistretto255 = (msg, options) => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) - const P = RistPoint.hashToCurve(uniform_bytes) - return P -} -export const hash_to_ristretto255 = hashToRistretto255 // legacy -//# sourceMappingURL=ed25519.js.map diff --git a/packages/noble-curves/esm/ed25519.js.map b/packages/noble-curves/esm/ed25519.js.map deleted file mode 100644 index 378cf93bb6a..00000000000 --- a/packages/noble-curves/esm/ed25519.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed448.d.ts b/packages/noble-curves/esm/ed448.d.ts deleted file mode 100644 index 82ac0fb743e..00000000000 --- a/packages/noble-curves/esm/ed448.d.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { AffinePoint, Group } from './abstract/curve.js' -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -import { type HTFMethod, type htfBasicOpts } from './abstract/hash-to-curve.js' -import { type CurveFn as XCurveFn } from './abstract/montgomery.js' -import { type Hex } from './abstract/utils.js' -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -export declare const ed448: CurveFn -export declare const ed448ph: CurveFn -/** - * ECDH using curve448 aka x448. - */ -export declare const x448: XCurveFn -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -export declare function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array -export declare const edwardsToMontgomery: typeof edwardsToMontgomeryPub -export declare const hashToCurve: HTFMethod -export declare const encodeToCurve: HTFMethod -type ExtendedPoint = ExtPointType -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -declare class DcfPoint implements Group { - private readonly ep - static BASE: DcfPoint - static ZERO: DcfPoint - constructor(ep: ExtendedPoint) - static fromAffine(ap: AffinePoint): DcfPoint - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex: Hex): DcfPoint - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex: Hex): DcfPoint - static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes(): Uint8Array - toHex(): string - toString(): string - equals(other: DcfPoint): boolean - add(other: DcfPoint): DcfPoint - subtract(other: DcfPoint): DcfPoint - multiply(scalar: bigint): DcfPoint - multiplyUnsafe(scalar: bigint): DcfPoint - double(): DcfPoint - negate(): DcfPoint -} -export declare const DecafPoint: typeof DcfPoint -export declare const hashToDecaf448: (msg: Uint8Array, options: htfBasicOpts) => DcfPoint -export declare const hash_to_decaf448: typeof hashToDecaf448 -export {} -//# sourceMappingURL=ed448.d.ts.map diff --git a/packages/noble-curves/esm/ed448.d.ts.map b/packages/noble-curves/esm/ed448.d.ts.map deleted file mode 100644 index 7272aeaf1a3..00000000000 --- a/packages/noble-curves/esm/ed448.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed448.d.ts","sourceRoot":"","sources":["../src/ed448.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAc,KAAK,OAAO,IAAI,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAKL,KAAK,GAAG,EAET,MAAM,qBAAqB,CAAC;AA8G7B;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,EAAE,OAAmD,CAAC;AAExE,eAAO,MAAM,OAAO,EAAE,OAGpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,QAgBZ,CAAC;AAER;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAIlF;AAED,eAAO,MAAM,mBAAmB,EAAE,OAAO,sBAA+C,CAAC;AA8FzF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC;AA2B5F,KAAK,aAAa,GAAG,YAAY,CAAC;AAiClC;;;;;;GAMG;AACH,cAAM,QAAS,YAAW,KAAK,CAAC,QAAQ,CAAC;IAK3B,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJ/B,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;IACtB,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAGO,EAAE,EAAE,aAAa;IAE9C,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,QAAQ;IAIpD;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IAStC;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,QAAQ;IA8BlC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,QAAQ;IAK3D;;;OAGG;IACH,UAAU,IAAI,UAAU;IAoBxB,KAAK,IAAI,MAAM;IAIf,QAAQ,IAAI,MAAM;IAMlB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAShC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAK9B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAKnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIlC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAIxC,MAAM,IAAI,QAAQ;IAIlB,MAAM,IAAI,QAAQ;CAGnB;AAED,eAAO,MAAM,UAAU,EAAE,OAAO,QAM5B,CAAC;AAGL,eAAO,MAAM,cAAc,QAAS,UAAU,WAAW,YAAY,KAAG,QAMvE,CAAC;AACF,eAAO,MAAM,gBAAgB,EAAE,OAAO,cAA+B,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/ed448.js b/packages/noble-curves/esm/ed448.js deleted file mode 100644 index 9fb0c3731a9..00000000000 --- a/packages/noble-curves/esm/ed448.js +++ /dev/null @@ -1,447 +0,0 @@ -/** - * Edwards448 (not Ed448-Goldilocks) curve with following addons: - * - X448 ECDH - * - Decaf cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { shake256 } from '@noble/hashes/sha3' -import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' -import { pippenger } from './abstract/curve.js' -import { twistedEdwards } from './abstract/edwards.js' -import { createHasher, expand_message_xof } from './abstract/hash-to-curve.js' -import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.js' -import { montgomery } from './abstract/montgomery.js' -import { - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.js' -const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) -const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) -const ed448P = BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', -) -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4), - _11n = BigInt(11) -// prettier-ignore -const _22n = BigInt(22), - _44n = BigInt(44), - _88n = BigInt(88), - _223n = BigInt(223) -// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. -// Used for efficient square root calculation. -// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] -function ed448_pow_Pminus3div4(x) { - const P = ed448P - const b2 = (x * x * x) % P - const b3 = (b2 * b2 * x) % P - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b222 = (pow2(b220, _2n, P) * b2) % P - const b223 = (pow2(b222, _1n, P) * x) % P - return (pow2(b223, _223n, P) * b222) % P -} -function adjustScalarBytes(bytes) { - // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most - // significant bit of the last byte to 1. - bytes[0] &= 252 // 0b11111100 - // and the most significant bit of the last byte to 1. - bytes[55] |= 128 // 0b10000000 - // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) - bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) - return bytes -} -// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. -// Uses algo from RFC8032 5.1.3. -function uvRatio(u, v) { - const P = ed448P - // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 - // To compute the square root of (u/v), the first step is to compute the - // candidate root x = (u/v)^((p+1)/4). This can be done using the - // following trick, to use a single modular powering for both the - // inversion of v and the square root: - // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) - const u2v = mod(u * u * v, P) // u²v - const u3v = mod(u2v * u, P) // u³v - const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ - const root = ed448_pow_Pminus3div4(u5v3) - const x = mod(u3v * root, P) - // Verify that root is exists - const x2 = mod(x * x, P) // x² - // If vx² = u, the recovered x-coordinate is x. Otherwise, no - // square root exists, and the decoding fails. - return { isValid: mod(x2 * v, P) === u, value: x } -} -const Fp = Field(ed448P, 456, true) -const ED448_DEF = { - // Param: a - a: BigInt(1), - // -39081. Negative number is P - number - d: BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', - ), - // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n - Fp, - // Subgroup order: how many points curve has; - // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n - n: BigInt( - '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', - ), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - nBitLength: 456, - // Cofactor - h: BigInt(4), - // Base point (x, y) aka generator point - Gx: BigInt( - '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', - ), - Gy: BigInt( - '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', - ), - // SHAKE256(dom4(phflag,context)||x, 114) - hash: shake256_114, - randomBytes, - adjustScalarBytes, - // dom4 - domain: (data, ctx, phflag) => { - if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) - return concatBytes( - utf8ToBytes('SigEd448'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) - }, - uvRatio, -} -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -export const ed448 = /* @__PURE__ */ twistedEdwards(ED448_DEF) -// NOTE: there is no ed448ctx, since ed448 supports ctx by default -export const ed448ph = /* @__PURE__ */ twistedEdwards({ - ...ED448_DEF, - prehash: shake256_64, -}) -/** - * ECDH using curve448 aka x448. - */ -export const x448 = /* @__PURE__ */ (() => - montgomery({ - a: BigInt(156326), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - montgomeryBits: 448, - nByteLength: 56, - P: ed448P, - Gu: BigInt(5), - powPminus2: (x) => { - const P = ed448P - const Pminus3div4 = ed448_pow_Pminus3div4(x) - const Pminus3 = pow2(Pminus3div4, BigInt(2), P) - return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 - }, - adjustScalarBytes, - randomBytes, - }))() -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub) { - const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) -} -export const edwardsToMontgomery = edwardsToMontgomeryPub // deprecated -// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version -// Hash To Curve Elligator2 Map -const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic -const ELL2_J = BigInt(156326) -function map_to_curve_elligator2_curve448(u) { - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 - tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 - let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 - let x1n = Fp.neg(ELL2_J) // 5. x1n = -J - let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 - tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd - tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 - let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) - y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) - let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd - let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u - y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) - tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 - let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) - return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) -} -function map_to_curve_elligator2_edwards448(u) { - let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) - let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 - let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 - let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 - let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 - let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 - let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 - let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 - xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 - xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd - xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn - xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 - tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 - tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 - let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 - let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 - tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 - let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 - tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn - let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 - let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 - yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 - yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 - tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 - tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 - tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd - tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 - tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 - let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 - tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 - yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 - tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd - let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 - xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) - xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) - yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) - yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) - const inv = Fp.invertBatch([xEd, yEd]) // batch division - return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) -} -const htf = /* @__PURE__ */ (() => - createHasher(ed448.ExtendedPoint, (scalars) => map_to_curve_elligator2_edwards448(scalars[0]), { - DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', - encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 224, - expand: 'xof', - hash: shake256, - }))() -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -function assertDcfPoint(other) { - if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') -} -// 1-d -const ONE_MINUS_D = BigInt('39082') -// 1-2d -const ONE_MINUS_TWO_D = BigInt('78163') -// √(-d) -const SQRT_MINUS_D = BigInt( - '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', -) -// 1 / √(-d) -const INVSQRT_MINUS_D = BigInt( - '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', -) -// Calculates 1/√(number) -const invertSqrt = (number) => uvRatio(_1n, number) -const MAX_448B = BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes448ToNumberLE = (bytes) => ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) -// Computes Elligator map for Decaf -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 -function calcElligatorDecafMap(r0) { - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - const r = mod(-(r0 * r0)) // 1 - const u0 = mod(d * (r - _1n)) // 2 - const u1 = mod((u0 + _1n) * (u0 - r)) // 3 - const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 - let v_prime = v // 5 - if (!was_square) v_prime = mod(r0 * v) - let sgn = _1n // 6 - if (!was_square) sgn = mod(-_1n) - const s = mod(v_prime * (r + _1n)) // 7 - let s_abs = s - if (isNegativeLE(s, P)) s_abs = mod(-s) - const s2 = s * s - const W0 = mod(s_abs * _2n) // 8 - const W1 = mod(s2 + _1n) // 9 - const W2 = mod(s2 - _1n) // 10 - const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 - return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class DcfPoint { - // Private property to discourage combining ExtendedPoint + DecafPoint - // Always use Decaf encoding/decoding instead. - constructor(ep) { - this.ep = ep - } - static fromAffine(ap) { - return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) - } - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex) { - hex = ensureBytes('decafHash', hex, 112) - const r1 = bytes448ToNumberLE(hex.slice(0, 56)) - const R1 = calcElligatorDecafMap(r1) - const r2 = bytes448ToNumberLE(hex.slice(56, 112)) - const R2 = calcElligatorDecafMap(r2) - return new DcfPoint(R1.add(R2)) - } - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex) { - hex = ensureBytes('decafHex', hex, 56) - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' - const s = bytes448ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 2. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) - const s2 = mod(s * s) // 1 - const u1 = mod(_1n + s2) // 2 - const u1sq = mod(u1 * u1) - const u2 = mod(u1sq - _4n * d * s2) // 3 - const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 - let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 - if (isNegativeLE(u3, P)) u3 = mod(-u3) - const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 - const y = mod((_1n - s2) * invsqrt * u1) // 7 - const t = mod(x * y) // 8 - if (!isValid) throw new Error(emsg) - return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) - } - static msm(points, scalars) { - const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) - return pippenger(DcfPoint, Fn, points, scalars) - } - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes() { - let { ex: x, ey: _y, ez: z, et: t } = this.ep - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - const u1 = mod(mod(x + t) * mod(x - t)) // 1 - const x2 = mod(x * x) - const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 - let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 - if (isNegativeLE(ratio, P)) ratio = mod(-ratio) - const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 - let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 - if (isNegativeLE(s, P)) s = mod(-s) - return numberToBytesLE(s, 56) - } - toHex() { - return bytesToHex(this.toRawBytes()) - } - toString() { - return this.toHex() - } - // Compare one point to another. - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 - equals(other) { - assertDcfPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed448.CURVE.Fp.create - // (x1 * y2 == y1 * x2) - return mod(X1 * Y2) === mod(Y1 * X2) - } - add(other) { - assertDcfPoint(other) - return new DcfPoint(this.ep.add(other.ep)) - } - subtract(other) { - assertDcfPoint(other) - return new DcfPoint(this.ep.subtract(other.ep)) - } - multiply(scalar) { - return new DcfPoint(this.ep.multiply(scalar)) - } - multiplyUnsafe(scalar) { - return new DcfPoint(this.ep.multiplyUnsafe(scalar)) - } - double() { - return new DcfPoint(this.ep.double()) - } - negate() { - return new DcfPoint(this.ep.negate()) - } -} -export const DecafPoint = /* @__PURE__ */ (() => { - // decaf448 base point is ed448 base x 2 - // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 - if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) - if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) - return DcfPoint -})() -// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C -export const hashToDecaf448 = (msg, options) => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) - const P = DcfPoint.hashToCurve(uniform_bytes) - return P -} -export const hash_to_decaf448 = hashToDecaf448 // legacy -//# sourceMappingURL=ed448.js.map diff --git a/packages/noble-curves/esm/ed448.js.map b/packages/noble-curves/esm/ed448.js.map deleted file mode 100644 index 48dcd5c4cc7..00000000000 --- a/packages/noble-curves/esm/ed448.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ed448.js","sourceRoot":"","sources":["../src/ed448.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/esm/index.d.ts b/packages/noble-curves/esm/index.d.ts deleted file mode 100644 index 727505f11c0..00000000000 --- a/packages/noble-curves/esm/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {} -//# sourceMappingURL=index.d.ts.map diff --git a/packages/noble-curves/esm/index.d.ts.map b/packages/noble-curves/esm/index.d.ts.map deleted file mode 100644 index 535b86d2936..00000000000 --- a/packages/noble-curves/esm/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/noble-curves/esm/index.js b/packages/noble-curves/esm/index.js deleted file mode 100644 index 9ee11f62b17..00000000000 --- a/packages/noble-curves/esm/index.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Audited & minimal JS implementation of elliptic curve cryptography. - * @module - * @example -```js -import { secp256k1, schnorr } from '@noble/curves/secp256k1'; -import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; -import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; -import { p256 } from '@noble/curves/p256'; -import { p384 } from '@noble/curves/p384'; -import { p521 } from '@noble/curves/p521'; -import { bls12_381 } from '@noble/curves/bls12-381'; -import { bn254 } from '@noble/curves/bn254'; -import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; -``` - */ -throw new Error('root module cannot be imported: import submodules instead. Check out README') -export {} -//# sourceMappingURL=index.js.map diff --git a/packages/noble-curves/esm/index.js.map b/packages/noble-curves/esm/index.js.map deleted file mode 100644 index 0cbc97e2af5..00000000000 --- a/packages/noble-curves/esm/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/jubjub.d.ts b/packages/noble-curves/esm/jubjub.d.ts deleted file mode 100644 index dbd19cd59c8..00000000000 --- a/packages/noble-curves/esm/jubjub.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -export declare const jubjub: CurveFn -export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType -export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType -//# sourceMappingURL=jubjub.d.ts.map diff --git a/packages/noble-curves/esm/jubjub.d.ts.map b/packages/noble-curves/esm/jubjub.d.ts.map deleted file mode 100644 index ec7dbea6e04..00000000000 --- a/packages/noble-curves/esm/jubjub.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jubjub.d.ts","sourceRoot":"","sources":["../src/jubjub.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AAGxF,eAAO,MAAM,MAAM,EAAE,OAgBV,CAAC;AAOZ,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAUpF;AAKD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAWtF"} \ No newline at end of file diff --git a/packages/noble-curves/esm/jubjub.js b/packages/noble-curves/esm/jubjub.js deleted file mode 100644 index 41a9839b136..00000000000 --- a/packages/noble-curves/esm/jubjub.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * jubjub Twisted Edwards curve. - * https://neuromancer.sk/std/other/JubJub - * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { blake2s } from '@noble/hashes/blake2s' -import { sha512 } from '@noble/hashes/sha512' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { twistedEdwards } from './abstract/edwards.js' -import { Field } from './abstract/modular.js' -export const jubjub = /* @__PURE__ */ twistedEdwards({ - // Params: a, d - a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), - d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), - // Finite field 𝔽p over which we'll do calculations - // Same value as bls12-381 Fr (not Fp) - Fp: Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')), - // Subgroup order: how many points curve has - n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), - // Cofactor - h: BigInt(8), - // Base point (x, y) aka generator point - Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), - Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), - hash: sha512, - randomBytes, -}) -const GH_FIRST_BLOCK = utf8ToBytes( - '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', -) -// Returns point at JubJub curve which is prime order and not zero -export function groupHash(tag, personalization) { - const h = blake2s.create({ personalization, dkLen: 32 }) - h.update(GH_FIRST_BLOCK) - h.update(tag) - // NOTE: returns ExtendedPoint, in case it will be multiplied later - let p = jubjub.ExtendedPoint.fromHex(h.digest()) - // NOTE: cannot replace with isSmallOrder, returns Point*8 - p = p.multiply(jubjub.CURVE.h) - if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') - return p -} -// No secret data is leaked here at all. -// It operates over public data: -// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); -export function findGroupHash(m, personalization) { - const tag = concatBytes(m, new Uint8Array([0])) - const hashes = [] - for (let i = 0; i < 256; i++) { - tag[tag.length - 1] = i - try { - hashes.push(groupHash(tag, personalization)) - } catch (e) {} - } - if (!hashes.length) throw new Error('findGroupHash tag overflow') - return hashes[0] -} -//# sourceMappingURL=jubjub.js.map diff --git a/packages/noble-curves/esm/jubjub.js.map b/packages/noble-curves/esm/jubjub.js.map deleted file mode 100644 index 21d9ce5dcf2..00000000000 --- a/packages/noble-curves/esm/jubjub.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jubjub.js","sourceRoot":"","sources":["../src/jubjub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAmC,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,MAAM,CAAC,MAAM,MAAM,GAAY,eAAe,CAAC,cAAc,CAAC;IAC5D,eAAe;IACf,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,oDAAoD;IACpD,sCAAsC;IACtC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC;IACvF,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC,mEAAmE,CAAC;IAC9E,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,IAAI,EAAE,MAAM;IACZ,WAAW;CACH,CAAC,CAAC;AAEZ,MAAM,cAAc,GAAG,WAAW,CAChC,kEAAkE,CACnE,CAAC;AAEF,kEAAkE;AAClE,MAAM,UAAU,SAAS,CAAC,GAAe,EAAE,eAA2B;IACpE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,mEAAmE;IACnE,IAAI,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wCAAwC;AACxC,gCAAgC;AAChC,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,CAAa,EAAE,eAA2B;IACtE,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p256.d.ts b/packages/noble-curves/esm/p256.d.ts deleted file mode 100644 index b3a570ce137..00000000000 --- a/packages/noble-curves/esm/p256.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** secp256r1 curve, ECDSA and ECDH methods. */ -export declare const p256: CurveFnWithCreate -/** Alias to p256. */ -export declare const secp256r1: CurveFnWithCreate -/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p256.d.ts.map diff --git a/packages/noble-curves/esm/p256.d.ts.map b/packages/noble-curves/esm/p256.d.ts.map deleted file mode 100644 index 98dba5c5828..00000000000 --- a/packages/noble-curves/esm/p256.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p256.d.ts","sourceRoot":"","sources":["../src/p256.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAQ3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p256.js b/packages/noble-curves/esm/p256.js deleted file mode 100644 index 9231539b997..00000000000 --- a/packages/noble-curves/esm/p256.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * NIST secp256r1 aka p256. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { createCurve } from './_shortw_utils.js' -import { createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' -const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) -const CURVE_A = Fp256.create(BigInt('-3')) -const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') -/** secp256r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -export const p256 = createCurve( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n - // Curve order, total count of valid points in the field - n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), - // Base (generator) point (x, y) - Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), - Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), - h: BigInt(1), - lowS: false, - }, - sha256, -) -/** Alias to p256. */ -export const secp256r1 = p256 -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp256, { - A: CURVE_A, - B: CURVE_B, - Z: Fp256.create(BigInt('-10')), - }))() -const htf = /* @__PURE__ */ (() => - createHasher(secp256r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { - DST: 'P256_XMD:SHA-256_SSWU_RO_', - encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', - p: Fp256.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - }))() -/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -//# sourceMappingURL=p256.js.map diff --git a/packages/noble-curves/esm/p256.js.map b/packages/noble-curves/esm/p256.js.map deleted file mode 100644 index 03220895061..00000000000 --- a/packages/noble-curves/esm/p256.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p256.js","sourceRoot":"","sources":["../src/p256.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;AAClG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAE7F,+CAA+C;AAC/C,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,yDAAyD;IACpE,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,MAAM,CAAC,CAAC;AACpB,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p384.d.ts b/packages/noble-curves/esm/p384.d.ts deleted file mode 100644 index 0021526b8cc..00000000000 --- a/packages/noble-curves/esm/p384.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** secp384r1 curve, ECDSA and ECDH methods. */ -export declare const p384: CurveFnWithCreate -/** Alias to p384. */ -export declare const secp384r1: CurveFnWithCreate -/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p384.d.ts.map diff --git a/packages/noble-curves/esm/p384.d.ts.map b/packages/noble-curves/esm/p384.d.ts.map deleted file mode 100644 index 4e4df4f1803..00000000000 --- a/packages/noble-curves/esm/p384.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p384.d.ts","sourceRoot":"","sources":["../src/p384.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAY3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p384.js b/packages/noble-curves/esm/p384.js deleted file mode 100644 index 3c2dacf9dcc..00000000000 --- a/packages/noble-curves/esm/p384.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * NIST secp384r1 aka p384. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha384 } from '@noble/hashes/sha512' -import { createCurve } from './_shortw_utils.js' -import { createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', -) -const Fp384 = Field(P) -const CURVE_A = Fp384.create(BigInt('-3')) -// prettier-ignore -const CURVE_B = BigInt( - '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', -) -/** secp384r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -export const p384 = createCurve( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n - // Curve order, total count of valid points in the field. - n: BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', - ), - // Base (generator) point (x, y) - Gx: BigInt( - '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', - ), - Gy: BigInt( - '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', - ), - h: BigInt(1), - lowS: false, - }, - sha384, -) -/** Alias to p384. */ -export const secp384r1 = p384 -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp384, { - A: CURVE_A, - B: CURVE_B, - Z: Fp384.create(BigInt('-12')), - }))() -const htf = /* @__PURE__ */ (() => - createHasher(secp384r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { - DST: 'P384_XMD:SHA-384_SSWU_RO_', - encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', - p: Fp384.ORDER, - m: 1, - k: 192, - expand: 'xmd', - hash: sha384, - }))() -/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -//# sourceMappingURL=p384.js.map diff --git a/packages/noble-curves/esm/p384.js.map b/packages/noble-curves/esm/p384.js.map deleted file mode 100644 index f878897358d..00000000000 --- a/packages/noble-curves/esm/p384.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p384.js","sourceRoot":"","sources":["../src/p384.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AACvH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AACvB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,kBAAkB;AAClB,MAAM,OAAO,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AAE7H,+CAA+C;AAC/C,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,sDAAsD;IACjE,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAC/G,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,MAAM,CAAC,CAAC;AACpB,qBAAqB;AACrB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p521.d.ts b/packages/noble-curves/esm/p521.d.ts deleted file mode 100644 index fadd9aad215..00000000000 --- a/packages/noble-curves/esm/p521.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** - * NIST secp521r1 aka p521. - */ -export declare const p521: CurveFnWithCreate -export declare const secp521r1: CurveFnWithCreate -/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p521.d.ts.map diff --git a/packages/noble-curves/esm/p521.d.ts.map b/packages/noble-curves/esm/p521.d.ts.map deleted file mode 100644 index bf0336ad11c..00000000000 --- a/packages/noble-curves/esm/p521.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p521.d.ts","sourceRoot":"","sources":["../src/p521.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA2B3E;;GAEG;AAEH,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/p521.js b/packages/noble-curves/esm/p521.js deleted file mode 100644 index 7eeff3b69f2..00000000000 --- a/packages/noble-curves/esm/p521.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * NIST secp521r1 aka p521. - * Note that it's 521, which differs from 512 of its hash function. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha512 } from '@noble/hashes/sha512' -import { createCurve } from './_shortw_utils.js' -import { createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const Fp521 = Field(P) -const CURVE = { - a: Fp521.create(BigInt('-3')), - b: BigInt( - '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', - ), - Fp: Fp521, - n: BigInt( - '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', - ), - Gx: BigInt( - '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', - ), - Gy: BigInt( - '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', - ), - h: BigInt(1), -} -/** - * NIST secp521r1 aka p521. - */ -// prettier-ignore -export const p521 = createCurve( - { - a: CURVE.a, // Equation params: a, b - b: CURVE.b, - Fp: Fp521, // Field: 2n**521n - 1n - // Curve order, total count of valid points in the field - n: CURVE.n, - Gx: CURVE.Gx, // Base point (x, y) aka generator point - Gy: CURVE.Gy, - h: CURVE.h, - lowS: false, - allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b - }, - sha512, -) -export const secp521r1 = p521 -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp521, { - A: CURVE.a, - B: CURVE.b, - Z: Fp521.create(BigInt('-4')), - }))() -const htf = /* @__PURE__ */ (() => - createHasher(secp521r1.ProjectivePoint, (scalars) => mapSWU(scalars[0]), { - DST: 'P521_XMD:SHA-512_SSWU_RO_', - encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', - p: Fp521.ORDER, - m: 1, - k: 256, - expand: 'xmd', - hash: sha512, - }))() -/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -//# sourceMappingURL=p521.js.map diff --git a/packages/noble-curves/esm/p521.js.map b/packages/noble-curves/esm/p521.js.map deleted file mode 100644 index 30df15022e2..00000000000 --- a/packages/noble-curves/esm/p521.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p521.js","sourceRoot":"","sources":["../src/p521.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAkB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,uIAAuI,CAAC,CAAC;AAC1J,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAEvB,MAAM,KAAK,GAAG;IACZ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,KAAK;IACT,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,kBAAkB;AAClB,MAAM,CAAC,MAAM,IAAI,GAAsB,WAAW,CAAC;IACjD,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,wBAAwB;IACpC,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,EAAE,uBAAuB;IAClC,wDAAwD;IACxD,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,wCAAwC;IACtD,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,IAAI,EAAE,KAAK;IACX,wBAAwB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,mDAAmD;CACrF,EAAE,MAAM,CAAC,CAAC;AACpB,MAAM,CAAC,MAAM,SAAS,GAAsB,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,mBAAmB,CAAC,KAAK,EAAE;IACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,YAAY,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,MAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AACvF,MAAM,CAAC,MAAM,WAAW,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAsB,eAAe,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/package.json b/packages/noble-curves/esm/package.json deleted file mode 100644 index 7f1fc33ddaa..00000000000 --- a/packages/noble-curves/esm/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "module", - "sideEffects": false -} diff --git a/packages/noble-curves/esm/pasta.d.ts b/packages/noble-curves/esm/pasta.d.ts deleted file mode 100644 index 8e978183120..00000000000 --- a/packages/noble-curves/esm/pasta.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type CurveFn } from './abstract/weierstrass.js' -export declare const p: bigint -export declare const q: bigint -/** https://neuromancer.sk/std/other/Pallas */ -export declare const pallas: CurveFn -/** https://neuromancer.sk/std/other/Vesta */ -export declare const vesta: CurveFn -//# sourceMappingURL=pasta.d.ts.map diff --git a/packages/noble-curves/esm/pasta.d.ts.map b/packages/noble-curves/esm/pasta.d.ts.map deleted file mode 100644 index e07599f2cd3..00000000000 --- a/packages/noble-curves/esm/pasta.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pasta.d.ts","sourceRoot":"","sources":["../src/pasta.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAEtE,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AACF,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,MAAM,EAAE,OASnB,CAAC;AACH,6CAA6C;AAC7C,eAAO,MAAM,KAAK,EAAE,OASlB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/pasta.js b/packages/noble-curves/esm/pasta.js deleted file mode 100644 index 25212dac733..00000000000 --- a/packages/noble-curves/esm/pasta.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { getHash } from './_shortw_utils.js' -import { Field, mod } from './abstract/modular.js' -import { weierstrass } from './abstract/weierstrass.js' -export const p = BigInt('0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001') -export const q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001') -/** https://neuromancer.sk/std/other/Pallas */ -export const pallas = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(p), - n: q, - Gx: mod(BigInt(-1), p), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) -/** https://neuromancer.sk/std/other/Vesta */ -export const vesta = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(q), - n: p, - Gx: mod(BigInt(-1), q), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) -//# sourceMappingURL=pasta.js.map diff --git a/packages/noble-curves/esm/pasta.js.map b/packages/noble-curves/esm/pasta.js.map deleted file mode 100644 index e7841d6952f..00000000000 --- a/packages/noble-curves/esm/pasta.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pasta.js","sourceRoot":"","sources":["../src/pasta.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,sEAAsE;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAgB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,CAAC,MAAM,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AACF,MAAM,CAAC,MAAM,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AAEF,8CAA8C;AAC9C,MAAM,CAAC,MAAM,MAAM,GAAY,WAAW,CAAC;IACzC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC;IACJ,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,OAAO,CAAC,MAAM,CAAC;CACnB,CAAC,CAAC;AACH,6CAA6C;AAC7C,MAAM,CAAC,MAAM,KAAK,GAAY,WAAW,CAAC;IACxC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC;IACJ,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,OAAO,CAAC,MAAM,CAAC;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/secp256k1.d.ts b/packages/noble-curves/esm/secp256k1.d.ts deleted file mode 100644 index 0f5d0fdc4d9..00000000000 --- a/packages/noble-curves/esm/secp256k1.d.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -import { mod } from './abstract/modular.js' -import type { Hex, PrivKey } from './abstract/utils.js' -import { bytesToNumberBE, numberToBytesBE } from './abstract/utils.js' -import { type ProjPointType as PointType } from './abstract/weierstrass.js' -/** - * secp256k1 short weierstrass curve and ECDSA signatures over it. - * - * @example - * import { secp256k1 } from '@noble/curves/secp256k1'; - * - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - */ -export declare const secp256k1: CurveFnWithCreate -declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -declare function lift_x(x: bigint): PointType -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -declare function schnorrGetPublicKey(privateKey: Hex): Uint8Array -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -declare function schnorrSign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Uint8Array -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -declare function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean -export type SecpSchnorr = { - getPublicKey: typeof schnorrGetPublicKey - sign: typeof schnorrSign - verify: typeof schnorrVerify - utils: { - randomPrivateKey: () => Uint8Array - lift_x: typeof lift_x - pointToBytes: (point: PointType) => Uint8Array - numberToBytesBE: typeof numberToBytesBE - bytesToNumberBE: typeof bytesToNumberBE - taggedHash: typeof taggedHash - mod: typeof mod - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - */ -export declare const schnorr: SecpSchnorr -/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -export {} -//# sourceMappingURL=secp256k1.d.ts.map diff --git a/packages/noble-curves/esm/secp256k1.d.ts.map b/packages/noble-curves/esm/secp256k1.d.ts.map deleted file mode 100644 index 7ed67065c2a..00000000000 --- a/packages/noble-curves/esm/secp256k1.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"secp256k1.d.ts","sourceRoot":"","sources":["../src/secp256k1.ts"],"names":[],"mappings":"AAeA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAc,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAS,GAAG,EAAQ,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAEL,eAAe,EAIf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAuB,KAAK,aAAa,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsCjG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,iBAsCvB,CAAC;AAOF,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAQtE;AAkBD;;;GAGG;AACH,iBAAS,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAS5C;AASD;;GAEG;AACH,iBAAS,mBAAmB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAExD;AAED;;;GAGG;AACH,iBAAS,WAAW,CAClB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,OAAO,EACnB,OAAO,GAAE,GAAqB,GAC7B,UAAU,CAgBZ;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAiB5E;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,OAAO,mBAAmB,CAAC;IACzC,IAAI,EAAE,OAAO,WAAW,CAAC;IACzB,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,UAAU,CAAC;QACnC,MAAM,EAAE,OAAO,MAAM,CAAC;QACtB,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC;QACvD,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC;QAC9B,GAAG,EAAE,OAAO,GAAG,CAAC;KACjB,CAAC;CACH,CAAC;AACF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,WAajB,CAAC;AA2DN,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AAExF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/esm/secp256k1.js b/packages/noble-curves/esm/secp256k1.js deleted file mode 100644 index 02ecf6ce265..00000000000 --- a/packages/noble-curves/esm/secp256k1.js +++ /dev/null @@ -1,299 +0,0 @@ -/** - * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). - * - * Seems to be rigid (not backdoored) - * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). - * - * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. - * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. - * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. - * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { createCurve } from './_shortw_utils.js' -import { createHasher, isogenyMap } from './abstract/hash-to-curve.js' -import { Field, mod, pow2 } from './abstract/modular.js' -import { - aInRange, - bytesToNumberBE, - concatBytes, - ensureBytes, - inRange, - numberToBytesBE, -} from './abstract/utils.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' -const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') -const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') -const _1n = BigInt(1) -const _2n = BigInt(2) -const divNearest = (a, b) => (a + b / _2n) / b -/** - * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. - * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] - */ -function sqrtMod(y) { - const P = secp256k1P - // prettier-ignore - const _3n = BigInt(3), - _6n = BigInt(6), - _11n = BigInt(11), - _22n = BigInt(22) - // prettier-ignore - const _23n = BigInt(23), - _44n = BigInt(44), - _88n = BigInt(88) - const b2 = (y * y * y) % P // x^3, 11 - const b3 = (b2 * b2 * y) % P // x^7 - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b223 = (pow2(b220, _3n, P) * b3) % P - const t1 = (pow2(b223, _23n, P) * b22) % P - const t2 = (pow2(t1, _6n, P) * b2) % P - const root = pow2(t2, _2n, P) - if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') - return root -} -const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) -/** - * secp256k1 short weierstrass curve and ECDSA signatures over it. - * - * @example - * import { secp256k1 } from '@noble/curves/secp256k1'; - * - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - */ -export const secp256k1 = createCurve( - { - a: BigInt(0), // equation params: a, b - b: BigInt(7), - Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n - n: secp256k1N, // Curve order, total count of valid points in the field - // Base point (x, y) aka generator point - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - h: BigInt(1), // Cofactor - lowS: true, // Allow only low-S signatures by default in sign() and verify() - endo: { - // Endomorphism, see above - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - splitScalar: (k) => { - const n = secp256k1N - const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') - const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') - const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') - const b2 = a1 - const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) - const c1 = divNearest(b2 * k, n) - const c2 = divNearest(-b1 * k, n) - let k1 = mod(k - c1 * a1 - c2 * a2, n) - let k2 = mod(-c1 * b1 - c2 * b2, n) - const k1neg = k1 > POW_2_128 - const k2neg = k2 > POW_2_128 - if (k1neg) k1 = n - k1 - if (k2neg) k2 = n - k2 - if (k1 > POW_2_128 || k2 > POW_2_128) { - throw new Error('splitScalar: Endomorphism failed, k=' + k) - } - return { k1neg, k1, k2neg, k2 } - }, - }, - }, - sha256, -) -// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. -// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki -const _0n = BigInt(0) -/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ -const TAGGED_HASH_PREFIXES = {} -function taggedHash(tag, ...messages) { - let tagP = TAGGED_HASH_PREFIXES[tag] - if (tagP === undefined) { - const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) - tagP = concatBytes(tagH, tagH) - TAGGED_HASH_PREFIXES[tag] = tagP - } - return sha256(concatBytes(tagP, ...messages)) -} -// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 -const pointToBytes = (point) => point.toRawBytes(true).slice(1) -const numTo32b = (n) => numberToBytesBE(n, 32) -const modP = (x) => mod(x, secp256k1P) -const modN = (x) => mod(x, secp256k1N) -const Point = secp256k1.ProjectivePoint -const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b) -// Calculate point, scalar and bytes -function schnorrGetExtPubKey(priv) { - let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey - let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside - const scalar = p.hasEvenY() ? d_ : modN(-d_) - return { scalar: scalar, bytes: pointToBytes(p) } -} -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -function lift_x(x) { - aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. - const xx = modP(x * x) - const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. - let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. - if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and - const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. - p.assertValidity() - return p -} -const num = bytesToNumberBE -/** - * Create tagged hash, convert it to bigint, reduce modulo-n. - */ -function challenge(...args) { - return modN(num(taggedHash('BIP0340/challenge', ...args))) -} -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -function schnorrGetPublicKey(privateKey) { - return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) -} -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -function schnorrSign(message, privateKey, auxRand = randomBytes(32)) { - const m = ensureBytes('message', message) - const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder - const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array - const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) - const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) - const k_ = modN(num(rand)) // Let k' = int(rand) mod n - if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. - const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. - const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. - const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). - sig.set(rx, 0) - sig.set(numTo32b(modN(k + e * d)), 32) - // If Verify(bytes(P), m, sig) (see below) returns failure, abort - if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') - return sig -} -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -function schnorrVerify(signature, message, publicKey) { - const sig = ensureBytes('signature', signature, 64) - const m = ensureBytes('message', message) - const pub = ensureBytes('publicKey', publicKey, 32) - try { - const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails - const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. - if (!inRange(r, _1n, secp256k1P)) return false - const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. - if (!inRange(s, _1n, secp256k1N)) return false - const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n - const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P - if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P - return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. - } catch (error) { - return false - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - */ -export const schnorr = /* @__PURE__ */ (() => ({ - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - utils: { - randomPrivateKey: secp256k1.utils.randomPrivateKey, - lift_x, - pointToBytes, - numberToBytesBE, - bytesToNumberBE, - taggedHash, - mod, - }, -}))() -const isoMap = /* @__PURE__ */ (() => - isogenyMap( - Fpk1, - [ - // xNum - [ - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', - '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', - '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', - ], - // xDen - [ - '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', - '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', - '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', - '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', - '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', - ], - // yDen - [ - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', - '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', - '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))), - ))() -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fpk1, { - A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), - B: BigInt('1771'), - Z: Fpk1.create(BigInt('-11')), - }))() -const htf = /* @__PURE__ */ (() => - createHasher( - secp256k1.ProjectivePoint, - (scalars) => { - const { x, y } = mapSWU(Fpk1.create(scalars[0])) - return isoMap(x, y) - }, - { - DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', - encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', - p: Fpk1.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - }, - ))() -/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve = /* @__PURE__ */ (() => htf.encodeToCurve)() -//# sourceMappingURL=secp256k1.js.map diff --git a/packages/noble-curves/esm/secp256k1.js.map b/packages/noble-curves/esm/secp256k1.js.map deleted file mode 100644 index 297e1c0040a..00000000000 --- a/packages/noble-curves/esm/secp256k1.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"secp256k1.js","sourceRoot":"","sources":["../src/secp256k1.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/noble-curves/index.d.ts b/packages/noble-curves/index.d.ts deleted file mode 100644 index a33fb2e99b0..00000000000 --- a/packages/noble-curves/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -//# sourceMappingURL=index.d.ts.map diff --git a/packages/noble-curves/index.d.ts.map b/packages/noble-curves/index.d.ts.map deleted file mode 100644 index 4e8c5816b41..00000000000 --- a/packages/noble-curves/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/packages/noble-curves/index.js b/packages/noble-curves/index.js deleted file mode 100644 index 59d4449d4fa..00000000000 --- a/packages/noble-curves/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' -/** - * Audited & minimal JS implementation of elliptic curve cryptography. - * @module - * @example -```js -import { secp256k1, schnorr } from '@noble/curves/secp256k1'; -import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; -import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; -import { p256 } from '@noble/curves/p256'; -import { p384 } from '@noble/curves/p384'; -import { p521 } from '@noble/curves/p521'; -import { bls12_381 } from '@noble/curves/bls12-381'; -import { bn254 } from '@noble/curves/bn254'; -import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; -``` - */ -throw new Error('root module cannot be imported: import submodules instead. Check out README') -//# sourceMappingURL=index.js.map diff --git a/packages/noble-curves/index.js.map b/packages/noble-curves/index.js.map deleted file mode 100644 index 5517b0a0e33..00000000000 --- a/packages/noble-curves/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/jubjub.d.ts b/packages/noble-curves/jubjub.d.ts deleted file mode 100644 index dbd19cd59c8..00000000000 --- a/packages/noble-curves/jubjub.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { type CurveFn, type ExtPointType } from './abstract/edwards.js' -export declare const jubjub: CurveFn -export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType -export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType -//# sourceMappingURL=jubjub.d.ts.map diff --git a/packages/noble-curves/jubjub.d.ts.map b/packages/noble-curves/jubjub.d.ts.map deleted file mode 100644 index ac68c847b50..00000000000 --- a/packages/noble-curves/jubjub.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jubjub.d.ts","sourceRoot":"","sources":["src/jubjub.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AAGxF,eAAO,MAAM,MAAM,EAAE,OAgBV,CAAC;AAOZ,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAUpF;AAKD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,GAAG,YAAY,CAWtF"} \ No newline at end of file diff --git a/packages/noble-curves/jubjub.js b/packages/noble-curves/jubjub.js deleted file mode 100644 index f241c576e90..00000000000 --- a/packages/noble-curves/jubjub.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.jubjub = void 0 -exports.groupHash = groupHash -exports.findGroupHash = findGroupHash -/** - * jubjub Twisted Edwards curve. - * https://neuromancer.sk/std/other/JubJub - * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const blake2s_1 = require('@noble/hashes/blake2s') -const sha512_1 = require('@noble/hashes/sha512') -const utils_1 = require('@noble/hashes/utils') -const edwards_js_1 = require('./abstract/edwards.js') -const modular_js_1 = require('./abstract/modular.js') -exports.jubjub = (0, edwards_js_1.twistedEdwards)({ - // Params: a, d - a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), - d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), - // Finite field 𝔽p over which we'll do calculations - // Same value as bls12-381 Fr (not Fp) - Fp: (0, modular_js_1.Field)( - BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), - ), - // Subgroup order: how many points curve has - n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), - // Cofactor - h: BigInt(8), - // Base point (x, y) aka generator point - Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), - Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), - hash: sha512_1.sha512, - randomBytes: utils_1.randomBytes, -}) -const GH_FIRST_BLOCK = (0, utils_1.utf8ToBytes)( - '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', -) -// Returns point at JubJub curve which is prime order and not zero -function groupHash(tag, personalization) { - const h = blake2s_1.blake2s.create({ personalization, dkLen: 32 }) - h.update(GH_FIRST_BLOCK) - h.update(tag) - // NOTE: returns ExtendedPoint, in case it will be multiplied later - let p = exports.jubjub.ExtendedPoint.fromHex(h.digest()) - // NOTE: cannot replace with isSmallOrder, returns Point*8 - p = p.multiply(exports.jubjub.CURVE.h) - if (p.equals(exports.jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') - return p -} -// No secret data is leaked here at all. -// It operates over public data: -// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); -function findGroupHash(m, personalization) { - const tag = (0, utils_1.concatBytes)(m, new Uint8Array([0])) - const hashes = [] - for (let i = 0; i < 256; i++) { - tag[tag.length - 1] = i - try { - hashes.push(groupHash(tag, personalization)) - } catch (e) {} - } - if (!hashes.length) throw new Error('findGroupHash tag overflow') - return hashes[0] -} -//# sourceMappingURL=jubjub.js.map diff --git a/packages/noble-curves/jubjub.js.map b/packages/noble-curves/jubjub.js.map deleted file mode 100644 index e90880ca0a4..00000000000 --- a/packages/noble-curves/jubjub.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"jubjub.js","sourceRoot":"","sources":["src/jubjub.ts"],"names":[],"mappings":";;;AAoCA,8BAUC;AAKD,sCAWC;AA9DD;;;;;GAKG;AACH,sEAAsE;AACtE,mDAAgD;AAChD,iDAA8C;AAC9C,+CAA4E;AAC5E,sDAAwF;AACxF,sDAA8C;AAEjC,QAAA,MAAM,GAA4B,IAAA,2BAAc,EAAC;IAC5D,eAAe;IACf,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,oDAAoD;IACpD,sCAAsC;IACtC,EAAE,EAAE,IAAA,kBAAK,EAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC;IACvF,4CAA4C;IAC5C,CAAC,EAAE,MAAM,CAAC,mEAAmE,CAAC;IAC9E,WAAW;IACX,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,IAAI,EAAE,eAAM;IACZ,WAAW,EAAX,mBAAW;CACH,CAAC,CAAC;AAEZ,MAAM,cAAc,GAAG,IAAA,mBAAW,EAChC,kEAAkE,CACnE,CAAC;AAEF,kEAAkE;AAClE,SAAgB,SAAS,CAAC,GAAe,EAAE,eAA2B;IACpE,MAAM,CAAC,GAAG,iBAAO,CAAC,MAAM,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACd,mEAAmE;IACnE,IAAI,CAAC,GAAG,cAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACjD,0DAA0D;IAC1D,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC,MAAM,CAAC,cAAM,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,wCAAwC;AACxC,gCAAgC;AAChC,kFAAkF;AAClF,SAAgB,aAAa,CAAC,CAAa,EAAE,eAA2B;IACtE,MAAM,GAAG,GAAG,IAAA,mBAAW,EAAC,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p256.d.ts b/packages/noble-curves/p256.d.ts deleted file mode 100644 index b3a570ce137..00000000000 --- a/packages/noble-curves/p256.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** secp256r1 curve, ECDSA and ECDH methods. */ -export declare const p256: CurveFnWithCreate -/** Alias to p256. */ -export declare const secp256r1: CurveFnWithCreate -/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p256.d.ts.map diff --git a/packages/noble-curves/p256.d.ts.map b/packages/noble-curves/p256.d.ts.map deleted file mode 100644 index 2f9b171f4d6..00000000000 --- a/packages/noble-curves/p256.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p256.d.ts","sourceRoot":"","sources":["src/p256.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAQ3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p256.js b/packages/noble-curves/p256.js deleted file mode 100644 index da4a2954b9a..00000000000 --- a/packages/noble-curves/p256.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.encodeToCurve = exports.hashToCurve = exports.secp256r1 = exports.p256 = void 0 -/** - * NIST secp256r1 aka p256. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha256_1 = require('@noble/hashes/sha256') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -const Fp256 = (0, modular_js_1.Field)( - BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'), -) -const CURVE_A = Fp256.create(BigInt('-3')) -const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') -/** secp256r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -exports.p256 = (0, _shortw_utils_js_1.createCurve)( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n - // Curve order, total count of valid points in the field - n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), - // Base (generator) point (x, y) - Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), - Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), - h: BigInt(1), - lowS: false, - }, - sha256_1.sha256, -) -/** Alias to p256. */ -exports.secp256r1 = exports.p256 -const mapSWU = /* @__PURE__ */ (() => - (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp256, { - A: CURVE_A, - B: CURVE_B, - Z: Fp256.create(BigInt('-10')), - }))() -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.secp256r1.ProjectivePoint, - (scalars) => mapSWU(scalars[0]), - { - DST: 'P256_XMD:SHA-256_SSWU_RO_', - encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', - p: Fp256.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256_1.sha256, - }, - ))() -/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.hashToCurve = (() => htf.hashToCurve)() -/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.encodeToCurve = (() => htf.encodeToCurve)() -//# sourceMappingURL=p256.js.map diff --git a/packages/noble-curves/p256.js.map b/packages/noble-curves/p256.js.map deleted file mode 100644 index a406427fdf3..00000000000 --- a/packages/noble-curves/p256.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p256.js","sourceRoot":"","sources":["src/p256.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;AAClG,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAE7F,+CAA+C;AAC/C,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,yDAAyD;IACpE,wDAAwD;IACxD,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,eAAM,CAAC,CAAC;AACpB,qBAAqB;AACR,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p384.d.ts b/packages/noble-curves/p384.d.ts deleted file mode 100644 index 0021526b8cc..00000000000 --- a/packages/noble-curves/p384.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** secp384r1 curve, ECDSA and ECDH methods. */ -export declare const p384: CurveFnWithCreate -/** Alias to p384. */ -export declare const secp384r1: CurveFnWithCreate -/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p384.d.ts.map diff --git a/packages/noble-curves/p384.d.ts.map b/packages/noble-curves/p384.d.ts.map deleted file mode 100644 index b14531b1497..00000000000 --- a/packages/noble-curves/p384.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p384.d.ts","sourceRoot":"","sources":["src/p384.ts"],"names":[],"mappings":"AAOA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAY3E,+CAA+C;AAE/C,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,qBAAqB;AACrB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p384.js b/packages/noble-curves/p384.js deleted file mode 100644 index 217a7dcc237..00000000000 --- a/packages/noble-curves/p384.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.encodeToCurve = exports.hashToCurve = exports.secp384r1 = exports.p384 = void 0 -/** - * NIST secp384r1 aka p384. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha512_1 = require('@noble/hashes/sha512') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', -) -const Fp384 = (0, modular_js_1.Field)(P) -const CURVE_A = Fp384.create(BigInt('-3')) -// prettier-ignore -const CURVE_B = BigInt( - '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', -) -/** secp384r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -exports.p384 = (0, _shortw_utils_js_1.createCurve)( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n - // Curve order, total count of valid points in the field. - n: BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', - ), - // Base (generator) point (x, y) - Gx: BigInt( - '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', - ), - Gy: BigInt( - '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', - ), - h: BigInt(1), - lowS: false, - }, - sha512_1.sha384, -) -/** Alias to p384. */ -exports.secp384r1 = exports.p384 -const mapSWU = /* @__PURE__ */ (() => - (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp384, { - A: CURVE_A, - B: CURVE_B, - Z: Fp384.create(BigInt('-12')), - }))() -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.secp384r1.ProjectivePoint, - (scalars) => mapSWU(scalars[0]), - { - DST: 'P384_XMD:SHA-384_SSWU_RO_', - encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', - p: Fp384.ORDER, - m: 1, - k: 192, - expand: 'xmd', - hash: sha512_1.sha384, - }, - ))() -/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.hashToCurve = (() => htf.hashToCurve)() -/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.encodeToCurve = (() => htf.encodeToCurve)() -//# sourceMappingURL=p384.js.map diff --git a/packages/noble-curves/p384.js.map b/packages/noble-curves/p384.js.map deleted file mode 100644 index 173153e2a82..00000000000 --- a/packages/noble-curves/p384.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p384.js","sourceRoot":"","sources":["src/p384.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AACvH,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,CAAC,CAAC,CAAC;AACvB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,kBAAkB;AAClB,MAAM,OAAO,GAAG,MAAM,CAAC,oGAAoG,CAAC,CAAC;AAE7H,+CAA+C;AAC/C,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,OAAO,EAAE,wBAAwB;IACpC,CAAC,EAAE,OAAO;IACV,EAAE,EAAE,KAAK,EAAE,sDAAsD;IACjE,yDAAyD;IACzD,CAAC,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAC/G,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,EAAE,EAAE,MAAM,CAAC,oGAAoG,CAAC;IAChH,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,IAAI,EAAE,KAAK;CACH,EAAE,eAAM,CAAC,CAAC;AACpB,qBAAqB;AACR,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC/B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p521.d.ts b/packages/noble-curves/p521.d.ts deleted file mode 100644 index fadd9aad215..00000000000 --- a/packages/noble-curves/p521.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -/** - * NIST secp521r1 aka p521. - */ -export declare const p521: CurveFnWithCreate -export declare const secp521r1: CurveFnWithCreate -/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -//# sourceMappingURL=p521.d.ts.map diff --git a/packages/noble-curves/p521.d.ts.map b/packages/noble-curves/p521.d.ts.map deleted file mode 100644 index 32fecfca8a3..00000000000 --- a/packages/noble-curves/p521.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p521.d.ts","sourceRoot":"","sources":["src/p521.ts"],"names":[],"mappings":"AAQA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AA2B3E;;GAEG;AAEH,eAAO,MAAM,IAAI,EAAE,iBAWA,CAAC;AACpB,eAAO,MAAM,SAAS,EAAE,iBAAwB,CAAC;AAmBjD,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/p521.js b/packages/noble-curves/p521.js deleted file mode 100644 index e5d9c45617d..00000000000 --- a/packages/noble-curves/p521.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.encodeToCurve = exports.hashToCurve = exports.secp521r1 = exports.p521 = void 0 -/** - * NIST secp521r1 aka p521. - * Note that it's 521, which differs from 512 of its hash function. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha512_1 = require('@noble/hashes/sha512') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const Fp521 = (0, modular_js_1.Field)(P) -const CURVE = { - a: Fp521.create(BigInt('-3')), - b: BigInt( - '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', - ), - Fp: Fp521, - n: BigInt( - '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', - ), - Gx: BigInt( - '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', - ), - Gy: BigInt( - '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', - ), - h: BigInt(1), -} -/** - * NIST secp521r1 aka p521. - */ -// prettier-ignore -exports.p521 = (0, _shortw_utils_js_1.createCurve)( - { - a: CURVE.a, // Equation params: a, b - b: CURVE.b, - Fp: Fp521, // Field: 2n**521n - 1n - // Curve order, total count of valid points in the field - n: CURVE.n, - Gx: CURVE.Gx, // Base point (x, y) aka generator point - Gy: CURVE.Gy, - h: CURVE.h, - lowS: false, - allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b - }, - sha512_1.sha512, -) -exports.secp521r1 = exports.p521 -const mapSWU = /* @__PURE__ */ (() => - (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fp521, { - A: CURVE.a, - B: CURVE.b, - Z: Fp521.create(BigInt('-4')), - }))() -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.secp521r1.ProjectivePoint, - (scalars) => mapSWU(scalars[0]), - { - DST: 'P521_XMD:SHA-512_SSWU_RO_', - encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', - p: Fp521.ORDER, - m: 1, - k: 256, - expand: 'xmd', - hash: sha512_1.sha512, - }, - ))() -/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.hashToCurve = (() => htf.hashToCurve)() -/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.encodeToCurve = (() => htf.encodeToCurve)() -//# sourceMappingURL=p521.js.map diff --git a/packages/noble-curves/p521.js.map b/packages/noble-curves/p521.js.map deleted file mode 100644 index 44374ecdc57..00000000000 --- a/packages/noble-curves/p521.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"p521.js","sourceRoot":"","sources":["src/p521.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAAgE;AAEhE,0CAA0C;AAC1C,kBAAkB;AAClB,MAAM,CAAC,GAAG,MAAM,CAAC,uIAAuI,CAAC,CAAC;AAC1J,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,CAAC,CAAC,CAAC;AAEvB,MAAM,KAAK,GAAG;IACZ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,KAAK;IACT,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,kBAAkB;AACL,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAAC;IACjD,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,wBAAwB;IACpC,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,EAAE,uBAAuB;IAClC,wDAAwD;IACxD,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,wCAAwC;IACtD,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,IAAI,EAAE,KAAK;IACX,wBAAwB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,mDAAmD;CACrF,EAAE,eAAM,CAAC,CAAC;AACP,QAAA,SAAS,GAAsB,YAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,KAAK,EAAE;IACzB,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAAC,EAAE,CAAC;AAER,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EAAC,iBAAS,CAAC,eAAe,EAAE,CAAC,OAAiB,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;IACjF,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,2BAA2B;IACtC,CAAC,EAAE,KAAK,CAAC,KAAK;IACd,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CAAC,CAAC,EAAE,CAAC;AACR,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AACxF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/package.json b/packages/noble-curves/package.json deleted file mode 100644 index b8af4db465b..00000000000 --- a/packages/noble-curves/package.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "name": "@noble/curves", - "version": "1.8.1", - "description": "Audited & minimal JS implementation of elliptic curve cryptography", - "files": ["*.js", "*.js.map", "*.d.ts", "*.d.ts.map", "esm", "src", "abstract"], - "scripts": { - "bench": "cd benchmark; node secp256k1.js; node curves.js; node ecdh.js; node hash-to-curve.js; node modular.js; node bls.js; node ristretto255.js; node decaf448.js", - "bench:install": "cd benchmark; npm install; npm install .. --install-links", - "build": "tsc && tsc -p tsconfig.cjs.json", - "build:release": "npx jsbt esbuild test/build", - "build:clean": "rm {.,esm,abstract,esm/abstract}/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null", - "lint": "prettier --check 'src/**/*.{js,ts}' 'test/*.js'", - "format": "prettier --write 'src/**/*.{js,ts}' 'test/*.js'", - "test": "node test/index.js", - "test:bun": "bun test/index.js", - "test:deno": "deno --allow-env --allow-read test/index.js", - "test:coverage": "npm install --no-save c8@10.1.2 && npx c8 npm test" - }, - "author": "Paul Miller (https://paulmillr.com)", - "homepage": "https://paulmillr.com/noble/", - "repository": { - "type": "git", - "url": "git+https://github.com/paulmillr/noble-curves.git" - }, - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.1" - }, - "devDependencies": { - "@paulmillr/jsbt": "0.3.1", - "fast-check": "3.0.0", - "micro-bmark": "0.4.0", - "micro-should": "0.5.1", - "prettier": "3.3.2", - "typescript": "5.5.2" - }, - "sideEffects": false, - "main": "index.js", - "exports": { - ".": { - "import": "./esm/index.js", - "require": "./index.js" - }, - "./abstract/bls": { - "import": "./esm/abstract/bls.js", - "require": "./abstract/bls.js" - }, - "./abstract/curve": { - "import": "./esm/abstract/curve.js", - "require": "./abstract/curve.js" - }, - "./abstract/edwards": { - "import": "./esm/abstract/edwards.js", - "require": "./abstract/edwards.js" - }, - "./abstract/hash-to-curve": { - "import": "./esm/abstract/hash-to-curve.js", - "require": "./abstract/hash-to-curve.js" - }, - "./abstract/modular": { - "import": "./esm/abstract/modular.js", - "require": "./abstract/modular.js" - }, - "./abstract/montgomery": { - "import": "./esm/abstract/montgomery.js", - "require": "./abstract/montgomery.js" - }, - "./abstract/poseidon": { - "import": "./esm/abstract/poseidon.js", - "require": "./abstract/poseidon.js" - }, - "./abstract/tower": { - "import": "./esm/abstract/tower.js", - "require": "./abstract/tower.js" - }, - "./abstract/utils": { - "import": "./esm/abstract/utils.js", - "require": "./abstract/utils.js" - }, - "./abstract/weierstrass": { - "import": "./esm/abstract/weierstrass.js", - "require": "./abstract/weierstrass.js" - }, - "./_shortw_utils": { - "import": "./esm/_shortw_utils.js", - "require": "./_shortw_utils.js" - }, - "./bls12-381": { - "import": "./esm/bls12-381.js", - "require": "./bls12-381.js" - }, - "./bn254": { - "import": "./esm/bn254.js", - "require": "./bn254.js" - }, - "./ed25519": { - "import": "./esm/ed25519.js", - "require": "./ed25519.js" - }, - "./ed448": { - "import": "./esm/ed448.js", - "require": "./ed448.js" - }, - "./index": { - "import": "./esm/index.js", - "require": "./index.js" - }, - "./jubjub": { - "import": "./esm/jubjub.js", - "require": "./jubjub.js" - }, - "./p256": { - "import": "./esm/p256.js", - "require": "./p256.js" - }, - "./p384": { - "import": "./esm/p384.js", - "require": "./p384.js" - }, - "./p521": { - "import": "./esm/p521.js", - "require": "./p521.js" - }, - "./pasta": { - "import": "./esm/pasta.js", - "require": "./pasta.js" - }, - "./secp256k1": { - "import": "./esm/secp256k1.js", - "require": "./secp256k1.js" - } - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "keywords": [ - "elliptic", - "curve", - "cryptography", - "secp256k1", - "ed25519", - "p256", - "p384", - "p521", - "secp256r1", - "ed448", - "x25519", - "ed25519", - "bls12-381", - "bn254", - "alt_bn128", - "bls", - "noble", - "ecc", - "ecdsa", - "eddsa", - "weierstrass", - "montgomery", - "edwards", - "schnorr" - ], - "funding": "https://paulmillr.com/funding/" -} diff --git a/packages/noble-curves/pasta.d.ts b/packages/noble-curves/pasta.d.ts deleted file mode 100644 index 8e978183120..00000000000 --- a/packages/noble-curves/pasta.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type CurveFn } from './abstract/weierstrass.js' -export declare const p: bigint -export declare const q: bigint -/** https://neuromancer.sk/std/other/Pallas */ -export declare const pallas: CurveFn -/** https://neuromancer.sk/std/other/Vesta */ -export declare const vesta: CurveFn -//# sourceMappingURL=pasta.d.ts.map diff --git a/packages/noble-curves/pasta.d.ts.map b/packages/noble-curves/pasta.d.ts.map deleted file mode 100644 index 4d8421c35a8..00000000000 --- a/packages/noble-curves/pasta.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pasta.d.ts","sourceRoot":"","sources":["src/pasta.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAEtE,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AACF,eAAO,MAAM,CAAC,EAAE,MAEf,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,MAAM,EAAE,OASnB,CAAC;AACH,6CAA6C;AAC7C,eAAO,MAAM,KAAK,EAAE,OASlB,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/pasta.js b/packages/noble-curves/pasta.js deleted file mode 100644 index 2e22a27d5f1..00000000000 --- a/packages/noble-curves/pasta.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.vesta = exports.pallas = exports.q = exports.p = void 0 -/** - * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha256_1 = require('@noble/hashes/sha256') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const modular_js_1 = require('./abstract/modular.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -exports.p = BigInt('0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001') -exports.q = BigInt('0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001') -/** https://neuromancer.sk/std/other/Pallas */ -exports.pallas = (0, weierstrass_js_1.weierstrass)({ - a: BigInt(0), - b: BigInt(5), - Fp: (0, modular_js_1.Field)(exports.p), - n: exports.q, - Gx: (0, modular_js_1.mod)(BigInt(-1), exports.p), - Gy: BigInt(2), - h: BigInt(1), - ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), -}) -/** https://neuromancer.sk/std/other/Vesta */ -exports.vesta = (0, weierstrass_js_1.weierstrass)({ - a: BigInt(0), - b: BigInt(5), - Fp: (0, modular_js_1.Field)(exports.q), - n: exports.p, - Gx: (0, modular_js_1.mod)(BigInt(-1), exports.q), - Gy: BigInt(2), - h: BigInt(1), - ...(0, _shortw_utils_js_1.getHash)(sha256_1.sha256), -}) -//# sourceMappingURL=pasta.js.map diff --git a/packages/noble-curves/pasta.js.map b/packages/noble-curves/pasta.js.map deleted file mode 100644 index dc936d9e557..00000000000 --- a/packages/noble-curves/pasta.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"pasta.js","sourceRoot":"","sources":["src/pasta.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,yDAA6C;AAC7C,sDAAmD;AACnD,8DAAsE;AAEzD,QAAA,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AACW,QAAA,CAAC,GAAW,MAAM,CAC7B,oEAAoE,CACrE,CAAC;AAEF,8CAA8C;AACjC,QAAA,MAAM,GAAY,IAAA,4BAAW,EAAC;IACzC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,IAAA,kBAAK,EAAC,SAAC,CAAC;IACZ,CAAC,EAAE,SAAC;IACJ,EAAE,EAAE,IAAA,gBAAG,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,IAAA,0BAAO,EAAC,eAAM,CAAC;CACnB,CAAC,CAAC;AACH,6CAA6C;AAChC,QAAA,KAAK,GAAY,IAAA,4BAAW,EAAC;IACxC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,IAAA,kBAAK,EAAC,SAAC,CAAC;IACZ,CAAC,EAAE,SAAC;IACJ,EAAE,EAAE,IAAA,gBAAG,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAC,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACb,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,GAAG,IAAA,0BAAO,EAAC,eAAM,CAAC;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/secp256k1.d.ts b/packages/noble-curves/secp256k1.d.ts deleted file mode 100644 index 0f5d0fdc4d9..00000000000 --- a/packages/noble-curves/secp256k1.d.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { type CurveFnWithCreate } from './_shortw_utils.js' -import { type HTFMethod } from './abstract/hash-to-curve.js' -import { mod } from './abstract/modular.js' -import type { Hex, PrivKey } from './abstract/utils.js' -import { bytesToNumberBE, numberToBytesBE } from './abstract/utils.js' -import { type ProjPointType as PointType } from './abstract/weierstrass.js' -/** - * secp256k1 short weierstrass curve and ECDSA signatures over it. - * - * @example - * import { secp256k1 } from '@noble/curves/secp256k1'; - * - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - */ -export declare const secp256k1: CurveFnWithCreate -declare function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -declare function lift_x(x: bigint): PointType -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -declare function schnorrGetPublicKey(privateKey: Hex): Uint8Array -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -declare function schnorrSign(message: Hex, privateKey: PrivKey, auxRand?: Hex): Uint8Array -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -declare function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean -export type SecpSchnorr = { - getPublicKey: typeof schnorrGetPublicKey - sign: typeof schnorrSign - verify: typeof schnorrVerify - utils: { - randomPrivateKey: () => Uint8Array - lift_x: typeof lift_x - pointToBytes: (point: PointType) => Uint8Array - numberToBytesBE: typeof numberToBytesBE - bytesToNumberBE: typeof bytesToNumberBE - taggedHash: typeof taggedHash - mod: typeof mod - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - */ -export declare const schnorr: SecpSchnorr -/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const hashToCurve: HTFMethod -/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export declare const encodeToCurve: HTFMethod -export {} -//# sourceMappingURL=secp256k1.d.ts.map diff --git a/packages/noble-curves/secp256k1.d.ts.map b/packages/noble-curves/secp256k1.d.ts.map deleted file mode 100644 index 0615024d341..00000000000 --- a/packages/noble-curves/secp256k1.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"secp256k1.d.ts","sourceRoot":"","sources":["src/secp256k1.ts"],"names":[],"mappings":"AAeA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAgB,KAAK,SAAS,EAAc,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAS,GAAG,EAAQ,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAEL,eAAe,EAIf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAuB,KAAK,aAAa,IAAI,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsCjG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,iBAsCvB,CAAC;AAOF,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,UAAU,CAQtE;AAkBD;;;GAGG;AACH,iBAAS,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAS5C;AASD;;GAEG;AACH,iBAAS,mBAAmB,CAAC,UAAU,EAAE,GAAG,GAAG,UAAU,CAExD;AAED;;;GAGG;AACH,iBAAS,WAAW,CAClB,OAAO,EAAE,GAAG,EACZ,UAAU,EAAE,OAAO,EACnB,OAAO,GAAE,GAAqB,GAC7B,UAAU,CAgBZ;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAiB5E;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,OAAO,mBAAmB,CAAC;IACzC,IAAI,EAAE,OAAO,WAAW,CAAC;IACzB,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,KAAK,EAAE;QACL,gBAAgB,EAAE,MAAM,UAAU,CAAC;QACnC,MAAM,EAAE,OAAO,MAAM,CAAC;QACtB,YAAY,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC;QACvD,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,eAAe,EAAE,OAAO,eAAe,CAAC;QACxC,UAAU,EAAE,OAAO,UAAU,CAAC;QAC9B,GAAG,EAAE,OAAO,GAAG,CAAC;KACjB,CAAC;CACH,CAAC;AACF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,EAAE,WAajB,CAAC;AA2DN,uFAAuF;AACvF,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,MAAM,CAA6C,CAAC;AAExF,yFAAyF;AACzF,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,MAAM,CAA+C,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/secp256k1.js b/packages/noble-curves/secp256k1.js deleted file mode 100644 index 63cc0784f45..00000000000 --- a/packages/noble-curves/secp256k1.js +++ /dev/null @@ -1,295 +0,0 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.encodeToCurve = exports.hashToCurve = exports.schnorr = exports.secp256k1 = void 0 -/** - * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). - * - * Seems to be rigid (not backdoored) - * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). - * - * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. - * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. - * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. - * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -const sha256_1 = require('@noble/hashes/sha256') -const utils_1 = require('@noble/hashes/utils') -const _shortw_utils_js_1 = require('./_shortw_utils.js') -const hash_to_curve_js_1 = require('./abstract/hash-to-curve.js') -const modular_js_1 = require('./abstract/modular.js') -const utils_js_1 = require('./abstract/utils.js') -const weierstrass_js_1 = require('./abstract/weierstrass.js') -const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') -const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') -const _1n = BigInt(1) -const _2n = BigInt(2) -const divNearest = (a, b) => (a + b / _2n) / b -/** - * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. - * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] - */ -function sqrtMod(y) { - const P = secp256k1P - // prettier-ignore - const _3n = BigInt(3), - _6n = BigInt(6), - _11n = BigInt(11), - _22n = BigInt(22) - // prettier-ignore - const _23n = BigInt(23), - _44n = BigInt(44), - _88n = BigInt(88) - const b2 = (y * y * y) % P // x^3, 11 - const b3 = (b2 * b2 * y) % P // x^7 - const b6 = ((0, modular_js_1.pow2)(b3, _3n, P) * b3) % P - const b9 = ((0, modular_js_1.pow2)(b6, _3n, P) * b3) % P - const b11 = ((0, modular_js_1.pow2)(b9, _2n, P) * b2) % P - const b22 = ((0, modular_js_1.pow2)(b11, _11n, P) * b11) % P - const b44 = ((0, modular_js_1.pow2)(b22, _22n, P) * b22) % P - const b88 = ((0, modular_js_1.pow2)(b44, _44n, P) * b44) % P - const b176 = ((0, modular_js_1.pow2)(b88, _88n, P) * b88) % P - const b220 = ((0, modular_js_1.pow2)(b176, _44n, P) * b44) % P - const b223 = ((0, modular_js_1.pow2)(b220, _3n, P) * b3) % P - const t1 = ((0, modular_js_1.pow2)(b223, _23n, P) * b22) % P - const t2 = ((0, modular_js_1.pow2)(t1, _6n, P) * b2) % P - const root = (0, modular_js_1.pow2)(t2, _2n, P) - if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') - return root -} -const Fpk1 = (0, modular_js_1.Field)(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) -/** - * secp256k1 short weierstrass curve and ECDSA signatures over it. - * - * @example - * import { secp256k1 } from '@noble/curves/secp256k1'; - * - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - */ -exports.secp256k1 = (0, _shortw_utils_js_1.createCurve)( - { - a: BigInt(0), // equation params: a, b - b: BigInt(7), - Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n - n: secp256k1N, // Curve order, total count of valid points in the field - // Base point (x, y) aka generator point - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - h: BigInt(1), // Cofactor - lowS: true, // Allow only low-S signatures by default in sign() and verify() - endo: { - // Endomorphism, see above - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - splitScalar: (k) => { - const n = secp256k1N - const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') - const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') - const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') - const b2 = a1 - const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) - const c1 = divNearest(b2 * k, n) - const c2 = divNearest(-b1 * k, n) - let k1 = (0, modular_js_1.mod)(k - c1 * a1 - c2 * a2, n) - let k2 = (0, modular_js_1.mod)(-c1 * b1 - c2 * b2, n) - const k1neg = k1 > POW_2_128 - const k2neg = k2 > POW_2_128 - if (k1neg) k1 = n - k1 - if (k2neg) k2 = n - k2 - if (k1 > POW_2_128 || k2 > POW_2_128) { - throw new Error('splitScalar: Endomorphism failed, k=' + k) - } - return { k1neg, k1, k2neg, k2 } - }, - }, - }, - sha256_1.sha256, -) -// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. -// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki -const _0n = BigInt(0) -/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ -const TAGGED_HASH_PREFIXES = {} -function taggedHash(tag, ...messages) { - let tagP = TAGGED_HASH_PREFIXES[tag] - if (tagP === undefined) { - const tagH = (0, sha256_1.sha256)(Uint8Array.from(tag, (c) => c.charCodeAt(0))) - tagP = (0, utils_js_1.concatBytes)(tagH, tagH) - TAGGED_HASH_PREFIXES[tag] = tagP - } - return (0, sha256_1.sha256)((0, utils_js_1.concatBytes)(tagP, ...messages)) -} -// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 -const pointToBytes = (point) => point.toRawBytes(true).slice(1) -const numTo32b = (n) => (0, utils_js_1.numberToBytesBE)(n, 32) -const modP = (x) => (0, modular_js_1.mod)(x, secp256k1P) -const modN = (x) => (0, modular_js_1.mod)(x, secp256k1N) -const Point = exports.secp256k1.ProjectivePoint -const GmulAdd = (Q, a, b) => Point.BASE.multiplyAndAddUnsafe(Q, a, b) -// Calculate point, scalar and bytes -function schnorrGetExtPubKey(priv) { - let d_ = exports.secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey - let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside - const scalar = p.hasEvenY() ? d_ : modN(-d_) - return { scalar: scalar, bytes: pointToBytes(p) } -} -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -function lift_x(x) { - ;(0, utils_js_1.aInRange)('x', x, _1n, secp256k1P) // Fail if x ≥ p. - const xx = modP(x * x) - const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. - let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. - if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and - const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. - p.assertValidity() - return p -} -const num = utils_js_1.bytesToNumberBE -/** - * Create tagged hash, convert it to bigint, reduce modulo-n. - */ -function challenge(...args) { - return modN(num(taggedHash('BIP0340/challenge', ...args))) -} -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -function schnorrGetPublicKey(privateKey) { - return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) -} -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -function schnorrSign(message, privateKey, auxRand = (0, utils_1.randomBytes)(32)) { - const m = (0, utils_js_1.ensureBytes)('message', message) - const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder - const a = (0, utils_js_1.ensureBytes)('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array - const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) - const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) - const k_ = modN(num(rand)) // Let k' = int(rand) mod n - if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. - const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. - const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. - const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). - sig.set(rx, 0) - sig.set(numTo32b(modN(k + e * d)), 32) - // If Verify(bytes(P), m, sig) (see below) returns failure, abort - if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') - return sig -} -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -function schnorrVerify(signature, message, publicKey) { - const sig = (0, utils_js_1.ensureBytes)('signature', signature, 64) - const m = (0, utils_js_1.ensureBytes)('message', message) - const pub = (0, utils_js_1.ensureBytes)('publicKey', publicKey, 32) - try { - const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails - const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. - if (!(0, utils_js_1.inRange)(r, _1n, secp256k1P)) return false - const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. - if (!(0, utils_js_1.inRange)(s, _1n, secp256k1N)) return false - const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n - const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P - if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P - return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. - } catch (error) { - return false - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - */ -exports.schnorr = (() => ({ - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - utils: { - randomPrivateKey: exports.secp256k1.utils.randomPrivateKey, - lift_x, - pointToBytes, - numberToBytesBE: utils_js_1.numberToBytesBE, - bytesToNumberBE: utils_js_1.bytesToNumberBE, - taggedHash, - mod: modular_js_1.mod, - }, -}))() -const isoMap = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.isogenyMap)( - Fpk1, - [ - // xNum - [ - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', - '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', - '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', - ], - // xDen - [ - '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', - '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', - '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', - '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', - '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', - ], - // yDen - [ - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', - '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', - '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))), - ))() -const mapSWU = /* @__PURE__ */ (() => - (0, weierstrass_js_1.mapToCurveSimpleSWU)(Fpk1, { - A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), - B: BigInt('1771'), - Z: Fpk1.create(BigInt('-11')), - }))() -const htf = /* @__PURE__ */ (() => - (0, hash_to_curve_js_1.createHasher)( - exports.secp256k1.ProjectivePoint, - (scalars) => { - const { x, y } = mapSWU(Fpk1.create(scalars[0])) - return isoMap(x, y) - }, - { - DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', - encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', - p: Fpk1.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256_1.sha256, - }, - ))() -/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.hashToCurve = (() => htf.hashToCurve)() -/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -exports.encodeToCurve = (() => htf.encodeToCurve)() -//# sourceMappingURL=secp256k1.js.map diff --git a/packages/noble-curves/secp256k1.js.map b/packages/noble-curves/secp256k1.js.map deleted file mode 100644 index e37b90ab9d9..00000000000 --- a/packages/noble-curves/secp256k1.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"secp256k1.js","sourceRoot":"","sources":["src/secp256k1.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;GAWG;AACH,sEAAsE;AACtE,iDAA8C;AAC9C,+CAAkD;AAClD,yDAAyE;AACzE,kEAAuF;AACvF,sDAAyD;AAEzD,kDAO6B;AAC7B,8DAAiG;AAEjG,MAAM,UAAU,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAChG,MAAM,UAAU,GAAG,MAAM,CAAC,oEAAoE,CAAC,CAAC;AAChG,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AAE/D;;;GAGG;AACH,SAAS,OAAO,CAAC,CAAS;IACxB,MAAM,CAAC,GAAG,UAAU,CAAC;IACrB,kBAAkB;IAClB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAC7E,kBAAkB;IAClB,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAC9D,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU;IACtC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM;IACpC,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,CAAC,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAA,iBAAI,EAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,IAAI,GAAG,IAAA,kBAAK,EAAC,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAExE;;;;;;;;;;;GAWG;AACU,QAAA,SAAS,GAAsB,IAAA,8BAAW,EACrD;IACE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,wBAAwB;IACtC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,EAAE,EAAE,IAAI,EAAE,sFAAsF;IAChG,CAAC,EAAE,UAAU,EAAE,wDAAwD;IACvE,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC,+EAA+E,CAAC;IAC3F,EAAE,EAAE,MAAM,CAAC,+EAA+E,CAAC;IAC3F,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW;IACzB,IAAI,EAAE,IAAI,EAAE,gEAAgE;IAC5E,IAAI,EAAE;QACJ,0BAA0B;QAC1B,IAAI,EAAE,MAAM,CAAC,oEAAoE,CAAC;QAClF,WAAW,EAAE,CAAC,CAAS,EAAE,EAAE;YACzB,MAAM,CAAC,GAAG,UAAU,CAAC;YACrB,MAAM,EAAE,GAAG,MAAM,CAAC,oCAAoC,CAAC,CAAC;YACxD,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,oCAAoC,CAAC,CAAC;YAC/D,MAAM,EAAE,GAAG,MAAM,CAAC,qCAAqC,CAAC,CAAC;YACzD,MAAM,EAAE,GAAG,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,MAAM,CAAC,qCAAqC,CAAC,CAAC,CAAC,0BAA0B;YAE3F,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACjC,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAClC,IAAI,EAAE,GAAG,IAAA,gBAAG,EAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,EAAE,GAAG,IAAA,gBAAG,EAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YACpC,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,CAAC;YAC7B,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,CAAC;YAC7B,IAAI,KAAK;gBAAE,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,KAAK;gBAAE,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,EAAE,GAAG,SAAS,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAClC,CAAC;KACF;CACF,EACD,eAAM,CACP,CAAC;AAEF,+FAA+F;AAC/F,iEAAiE;AACjE,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,wFAAwF;AACxF,MAAM,oBAAoB,GAAkC,EAAE,CAAC;AAC/D,SAAS,UAAU,CAAC,GAAW,EAAE,GAAG,QAAsB;IACxD,IAAI,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAA,eAAM,EAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,GAAG,IAAA,sBAAW,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/B,oBAAoB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACnC,CAAC;IACD,OAAO,IAAA,eAAM,EAAC,IAAA,sBAAW,EAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,oFAAoF;AACpF,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnF,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAA,0BAAe,EAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACvD,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAA,gBAAG,EAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/C,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAA,gBAAG,EAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAC/C,MAAM,KAAK,GAAG,iBAAS,CAAC,eAAe,CAAC;AACxC,MAAM,OAAO,GAAG,CAAC,CAAoB,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE,CAC7D,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAE3C,oCAAoC;AACpC,SAAS,mBAAmB,CAAC,IAAa;IACxC,IAAI,EAAE,GAAG,iBAAS,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,yCAAyC;IAChG,IAAI,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,4CAA4C;IAC9E,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;AACpD,CAAC;AACD;;;GAGG;AACH,SAAS,MAAM,CAAC,CAAS;IACvB,IAAA,mBAAQ,EAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,iBAAiB;IACpD,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;IAC5D,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B;IAC/C,IAAI,CAAC,GAAG,GAAG,KAAK,GAAG;QAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mDAAmD;IACtF,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,mDAAmD;IACnF,CAAC,CAAC,cAAc,EAAE,CAAC;IACnB,OAAO,CAAC,CAAC;AACX,CAAC;AACD,MAAM,GAAG,GAAG,0BAAe,CAAC;AAC5B;;GAEG;AACH,SAAS,SAAS,CAAC,GAAG,IAAkB;IACtC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,UAAe;IAC1C,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,oDAAoD;AACpG,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAClB,OAAY,EACZ,UAAmB,EACnB,UAAe,IAAA,mBAAW,EAAC,EAAE,CAAC;IAE9B,MAAM,CAAC,GAAG,IAAA,sBAAW,EAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,gCAAgC;IAClG,MAAM,CAAC,GAAG,IAAA,sBAAW,EAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,2CAA2C;IAC1F,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,yDAAyD;IACpH,MAAM,IAAI,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,4CAA4C;IAChG,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,2BAA2B;IACvD,IAAI,EAAE,KAAK,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,kBAAkB;IAC7E,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB;IAC1E,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,gEAAgE;IAChG,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,+CAA+C;IAC/E,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACf,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvC,iEAAiE;IACjE,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACpF,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,SAAc,EAAE,OAAY,EAAE,SAAc;IACjE,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,WAAW,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,IAAA,sBAAW,EAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,WAAW,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,0CAA0C;QACtE,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,yCAAyC;QAC7E,IAAI,CAAC,IAAA,kBAAO,EAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,0CAA0C;QAC/E,IAAI,CAAC,IAAA,kBAAO,EAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,0CAA0C;QAChG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB;QACnD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,gBAAgB;QAC/E,OAAO,IAAI,CAAC,CAAC,yDAAyD;IACxE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAgBD;;;;;;;;;;GAUG;AACU,QAAA,OAAO,GAAgC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1D,YAAY,EAAE,mBAAmB;IACjC,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,aAAa;IACrB,KAAK,EAAE;QACL,gBAAgB,EAAE,iBAAS,CAAC,KAAK,CAAC,gBAAgB;QAClD,MAAM;QACN,YAAY;QACZ,eAAe,EAAf,0BAAe;QACf,eAAe,EAAf,0BAAe;QACf,UAAU;QACV,GAAG,EAAH,gBAAG;KACJ;CACF,CAAC,CAAC,EAAE,CAAC;AAEN,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,6BAAU,EACR,IAAI,EACJ;IACE,OAAO;IACP;QACE,oEAAoE;QACpE,mEAAmE;QACnE,oEAAoE;QACpE,oEAAoE;KACrE;IACD,OAAO;IACP;QACE,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE,EAAE,SAAS;KAChF;IACD,OAAO;IACP;QACE,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE;KACrE;IACD,OAAO;IACP;QACE,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE,EAAE,SAAS;KAChF;CACF,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAA6C,CAClF,CAAC,EAAE,CAAC;AACP,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CACnC,IAAA,oCAAmB,EAAC,IAAI,EAAE;IACxB,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC;IACjB,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;CAC9B,CAAC,CAAC,EAAE,CAAC;AACR,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,GAAG,EAAE,CAChC,IAAA,+BAAY,EACV,iBAAS,CAAC,eAAe,EACzB,CAAC,OAAiB,EAAE,EAAE;IACpB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtB,CAAC,EACD;IACE,GAAG,EAAE,gCAAgC;IACrC,SAAS,EAAE,gCAAgC;IAC3C,CAAC,EAAE,IAAI,CAAC,KAAK;IACb,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,GAAG;IACN,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,eAAM;CACb,CACF,CAAC,EAAE,CAAC;AAEP,uFAAuF;AAC1E,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;AAExF,yFAAyF;AAC5E,QAAA,aAAa,GAAsC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/packages/noble-curves/src/_shortw_utils.ts b/packages/noble-curves/src/_shortw_utils.ts deleted file mode 100644 index 9fe8d7f623c..00000000000 --- a/packages/noble-curves/src/_shortw_utils.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Utilities for short weierstrass curves, combined with noble-hashes. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { hmac } from '@noble/hashes/hmac' -import { concatBytes, randomBytes } from '@noble/hashes/utils' -import type { CHash } from './abstract/utils.js' -import { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.js' - -/** connects noble-curves to noble-hashes */ -export function getHash(hash: CHash): { - hash: CHash - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array - randomBytes: typeof randomBytes -} { - return { - hash, - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)), - randomBytes, - } -} -/** Same API as @noble/hashes, with ability to create curve with custom hash */ -export type CurveDef = Readonly> -export type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn } - -export function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate { - const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, ...getHash(hash) }) - return { ...create(defHash), create } -} diff --git a/packages/noble-curves/src/abstract/bls.ts b/packages/noble-curves/src/abstract/bls.ts deleted file mode 100644 index 3b29c0bf3e5..00000000000 --- a/packages/noble-curves/src/abstract/bls.ts +++ /dev/null @@ -1,574 +0,0 @@ -// prettier-ignore -import { - type H2CPointConstructor, - type Opts as HTFOpts, - type MapToCurve, - createHasher, - type htfBasicOpts, -} from './hash-to-curve.js' -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// TODO: import { AffinePoint } from './curve.js'; -import { type IField, getMinHashLength, mapHashToField } from './modular.js' -import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.js' -import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.js' -import { - type CurvePointsRes, - type CurvePointsType, - type ProjPointType, - weierstrassPoints, -} from './weierstrass.js' - -type Fp = bigint // Can be different field? - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) - -export type TwistType = 'multiplicative' | 'divisive' - -export type ShortSignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} - -export type SignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} - -export type PostPrecomputePointAddFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, -) => { Rx: Fp2; Ry: Fp2; Rz: Fp2 } -export type PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => void -export type CurveType = { - G1: Omit, 'n'> & { - ShortSignature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - G2: Omit, 'n'> & { - Signature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - fields: { - Fp: IField - Fr: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - } - params: { - // NOTE: MSB is always ignored and used as marker for length, - // otherwise leading zeros will be lost. - // Can be different from 'X' (seed) param! - ateLoopSize: bigint - xNegative: boolean - r: bigint - twistType: TwistType // BLS12-381: Multiplicative, BN254: Divisive - } - htfDefaults: HTFOpts - hash: CHash // Because we need outputLen for DRBG - randomBytes: (bytesLength?: number) => Uint8Array - // This is super ugly hack for untwist point in BN254 after miller loop - postPrecompute?: PostPrecomputeFn -} - -type PrecomputeSingle = [Fp2, Fp2, Fp2][] -type Precompute = PrecomputeSingle[] - -export type CurveFn = { - getPublicKey: (privateKey: PrivKey) => Uint8Array - getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array - sign: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - signShortSignature: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - verify: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyShortSignature: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyBatch: ( - signature: Hex | ProjPointType, - messages: (Hex | ProjPointType)[], - publicKeys: (Hex | ProjPointType)[], - htfOpts?: htfBasicOpts, - ) => boolean - aggregatePublicKeys: { - (publicKeys: Hex[]): Uint8Array - (publicKeys: ProjPointType[]): ProjPointType - } - aggregateSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - aggregateShortSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 - pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 - pairingBatch: ( - pairs: { g1: ProjPointType; g2: ProjPointType }[], - withFinalExponent?: boolean, - ) => Fp12 - G1: CurvePointsRes & ReturnType> - G2: CurvePointsRes & ReturnType> - Signature: SignatureCoder - ShortSignature: ShortSignatureCoder - params: { - ateLoopSize: bigint - r: bigint - G1b: bigint - G2b: Fp2 - } - fields: { - Fp: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - Fr: IField - } - utils: { - randomPrivateKey: () => Uint8Array - calcPairingPrecomputes: (p: ProjPointType) => Precompute - } -} - -// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. -function NAfDecomposition(a: bigint) { - const res = [] - // a>1 because of marker bit - for (; a > _1n; a >>= _1n) { - if ((a & _1n) === _0n) res.unshift(0) - else if ((a & _3n) === _3n) { - res.unshift(-1) - a += _1n - } else res.unshift(1) - } - return res -} - -export function bls(CURVE: CurveType): CurveFn { - // Fields are specific for curve, so for now we'll need to pass them with opts - const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields - const BLS_X_IS_NEGATIVE = CURVE.params.xNegative - const TWIST: TwistType = CURVE.params.twistType - // Point on G1 curve: (x, y) - const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) - const G1 = Object.assign( - G1_, - createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G1.htfDefaults, - }), - ) - // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) - const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) - const G2 = Object.assign( - G2_, - createHasher(G2_.ProjectivePoint as H2CPointConstructor, CURVE.G2.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G2.htfDefaults, - }), - ) - type G1 = typeof G1.ProjectivePoint.BASE - type G2 = typeof G2.ProjectivePoint.BASE - - // Applies sparse multiplication as line function - let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12 - if (TWIST === 'multiplicative') { - lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => - Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) - } else if (TWIST === 'divisive') { - // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of - // precompute calculations. - lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => - Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) - } else throw new Error('bls: unknown twist type') - - const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) - function pointDouble(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2) { - const t0 = Fp2.sqr(Ry) // Ry² - const t1 = Fp2.sqr(Rz) // Rz² - const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B - const t3 = Fp2.mul(t2, _3n) // 3 * T2 - const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 - const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) - const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² - const c2 = Fp2.neg(t4) // -T4 (-h) - - ell.push([c0, c1, c2]) - - Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 - Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² - Rz = Fp2.mul(t0, t4) // T0 * T4 - return { Rx, Ry, Rz } - } - function pointAdd(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) { - // Addition - const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz - const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz - const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy - const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry - const c2 = t1 // == Rx - Qx * Rz - - ell.push([c0, c1, c2]) - - const t2 = Fp2.sqr(t1) // T1² - const t3 = Fp2.mul(t2, t1) // T2 * T1 - const t4 = Fp2.mul(t2, Rx) // T2 * Rx - const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz - Rx = Fp2.mul(t1, t5) // T1 * T5 - Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry - Rz = Fp2.mul(Rz, t3) // Rz * T3 - return { Rx, Ry, Rz } - } - - // Pre-compute coefficients for sparse multiplication - // Point addition and point double calculations is reused for coefficients - // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine - // add + double in windowed precomputes here, otherwise it would be single op (since X is static) - const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) - - const calcPairingPrecomputes = memoized((point: G2) => { - const p = point - const { x, y } = p.toAffine() - // prettier-ignore - const Qx = x, - Qy = y, - negQy = Fp2.neg(y) - // prettier-ignore - let Rx = Qx, - Ry = Qy, - Rz = Fp2.ONE - const ell: Precompute = [] - for (const bit of ATE_NAF) { - const cur: PrecomputeSingle = [] - ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) - if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) - ell.push(cur) - } - if (CURVE.postPrecompute) { - const last = ell[ell.length - 1] - CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) - } - return ell - }) - - // Main pairing logic is here. Computes product of miller loops + final exponentiate - // Applies calculated precomputes - type MillerInput = [Precompute, Fp, Fp][] - function millerLoopBatch(pairs: MillerInput, withFinalExponent: boolean = false) { - let f12 = Fp12.ONE - if (pairs.length) { - const ellLen = pairs[0][0].length - for (let i = 0; i < ellLen; i++) { - f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings - // NOTE: we apply multiple pairings in parallel here - for (const [ell, Px, Py] of pairs) { - for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) - } - } - } - if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) - return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 - } - type PairingInput = { g1: G1; g2: G2 } - // Calculates product of multiple pairings - // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` - function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) { - const res: MillerInput = [] - // This cache precomputed toAffine for all points - G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) - G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) - for (const { g1, g2 } of pairs) { - if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) - throw new Error('pairing is not available for ZERO point') - // This uses toAffine inside - g1.assertValidity() - g2.assertValidity() - const Qa = g1.toAffine() - res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) - } - return millerLoopBatch(res, withFinalExponent) - } - // Calculates bilinear pairing - function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 { - return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) - } - - const utils = { - randomPrivateKey: (): Uint8Array => { - const length = getMinHashLength(Fr.ORDER) - return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) - }, - calcPairingPrecomputes, - } - - const { ShortSignature } = CURVE.G1 - const { Signature } = CURVE.G2 - - type G1Hex = Hex | G1 - type G2Hex = Hex | G2 - function normP1(point: G1Hex): G1 { - return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point) - } - function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 { - return point instanceof G1.ProjectivePoint - ? point - : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1) - } - function normP2(point: G2Hex): G2 { - return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) - } - function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 { - return point instanceof G2.ProjectivePoint - ? point - : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2) - } - - // Multiplies generator (G1) by private key. - // P = pk x G - function getPublicKey(privateKey: PrivKey): Uint8Array { - return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - - // Multiplies generator (G2) by private key. - // P = pk x G - function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array { - return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - - // Executes `hashToCurve` on the message and then multiplies the result by private key. - // S = pk x H(m) - function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2 - function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 { - const msgPoint = normP2Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G2.ProjectivePoint) return sigPoint - return Signature.toRawBytes(sigPoint) - } - - function signShortSignature(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1 - function signShortSignature( - message: G1Hex, - privateKey: PrivKey, - htfOpts?: htfBasicOpts, - ): Uint8Array | G1 { - const msgPoint = normP1Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G1.ProjectivePoint) return sigPoint - return ShortSignature.toRawBytes(sigPoint) - } - - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(P, H(m)) == e(G, S) - function verify( - signature: G2Hex, - message: G2Hex, - publicKey: G1Hex, - htfOpts?: htfBasicOpts, - ): boolean { - const P = normP1(publicKey) - const Hm = normP2Hash(message, htfOpts) - const G = G1.ProjectivePoint.BASE - const S = normP2(signature) - const exp = pairingBatch([ - { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); - { g1: G, g2: S }, // eGS = pairing(G, S, false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(S, G) == e(H(m), P) - function verifyShortSignature( - signature: G1Hex, - message: G1Hex, - publicKey: G2Hex, - htfOpts?: htfBasicOpts, - ): boolean { - const P = normP2(publicKey) - const Hm = normP1Hash(message, htfOpts) - const G = G2.ProjectivePoint.BASE - const S = normP1(signature) - const exp = pairingBatch([ - { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); - { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - - function aNonEmpty(arr: any[]) { - if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') - } - - // Adds a bunch of public key points together. - // pk1 + pk2 + pk3 = pkA - function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array - function aggregatePublicKeys(publicKeys: G1[]): G1 - function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 { - aNonEmpty(publicKeys) - const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (publicKeys[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - // toRawBytes ensures point validity - return aggAffine.toRawBytes(true) - } - - // Adds a bunch of signature points together. - function aggregateSignatures(signatures: Hex[]): Uint8Array - function aggregateSignatures(signatures: G2[]): G2 - function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 { - aNonEmpty(signatures) - const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G2.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return Signature.toRawBytes(aggAffine) - } - - // Adds a bunch of signature points together. - function aggregateShortSignatures(signatures: Hex[]): Uint8Array - function aggregateShortSignatures(signatures: G1[]): G1 - function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 { - aNonEmpty(signatures) - const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return ShortSignature.toRawBytes(aggAffine) - } - - // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 - // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) - function verifyBatch( - signature: G2Hex, - // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? - messages: G2Hex[], - publicKeys: G1Hex[], - htfOpts?: htfBasicOpts, - ): boolean { - aNonEmpty(messages) - if (publicKeys.length !== messages.length) - throw new Error('amount of public keys and messages should be equal') - const sig = normP2(signature) - const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) - const nPublicKeys = publicKeys.map(normP1) - // NOTE: this works only for exact same object - const messagePubKeyMap = new Map() - for (let i = 0; i < nPublicKeys.length; i++) { - const pub = nPublicKeys[i] - const msg = nMessages[i] - let keys = messagePubKeyMap.get(msg) - if (keys === undefined) { - keys = [] - messagePubKeyMap.set(msg, keys) - } - keys.push(pub) - } - const paired = [] - try { - for (const [msg, keys] of messagePubKeyMap) { - const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) - paired.push({ g1: groupPublicKey, g2: msg }) - } - paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) - return Fp12.eql(pairingBatch(paired), Fp12.ONE) - } catch { - return false - } - } - - G1.ProjectivePoint.BASE._setWindowSize(4) - - return { - getPublicKey, - getPublicKeyForShortSignatures, - sign, - signShortSignature, - verify, - verifyBatch, - verifyShortSignature, - aggregatePublicKeys, - aggregateSignatures, - aggregateShortSignatures, - millerLoopBatch, - pairing, - pairingBatch, - G1, - G2, - Signature, - ShortSignature, - fields: { - Fr, - Fp, - Fp2, - Fp6, - Fp12, - }, - params: { - ateLoopSize: CURVE.params.ateLoopSize, - r: CURVE.params.r, - G1b: CURVE.G1.b, - G2b: CURVE.G2.b, - }, - utils, - } -} diff --git a/packages/noble-curves/src/abstract/curve.ts b/packages/noble-curves/src/abstract/curve.ts deleted file mode 100644 index de1f49eaf6e..00000000000 --- a/packages/noble-curves/src/abstract/curve.ts +++ /dev/null @@ -1,457 +0,0 @@ -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField, nLength, validateField } from './modular.js' -import { bitLen, validateObject } from './utils.js' - -const _0n = BigInt(0) -const _1n = BigInt(1) - -export type AffinePoint = { - x: T - y: T -} & { z?: never; t?: never } - -export interface Group> { - double(): T - negate(): T - add(other: T): T - subtract(other: T): T - equals(other: T): boolean - multiply(scalar: bigint): T -} - -export type GroupConstructor = { - BASE: T - ZERO: T -} -export type Mapper = (i: T[]) => T[] - -function constTimeNegate>(condition: boolean, item: T): T { - const neg = item.negate() - return condition ? neg : item -} - -function validateW(W: number, bits: number) { - if (!Number.isSafeInteger(W) || W <= 0 || W > bits) - throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) -} - -function calcWOpts(W: number, bits: number) { - validateW(W, bits) - const windows = Math.ceil(bits / W) + 1 // +1, because - const windowSize = 2 ** (W - 1) // -1 because we skip zero - return { windows, windowSize } -} - -function validateMSMPoints(points: any[], c: any) { - if (!Array.isArray(points)) throw new Error('array expected') - points.forEach((p, i) => { - if (!(p instanceof c)) throw new Error('invalid point at index ' + i) - }) -} -function validateMSMScalars(scalars: any[], field: any) { - if (!Array.isArray(scalars)) throw new Error('array of scalars expected') - scalars.forEach((s, i) => { - if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) - }) -} - -// Since points in different groups cannot be equal (different object constructor), -// we can have single place to store precomputes -const pointPrecomputes = new WeakMap() -const pointWindowSizes = new WeakMap() // This allows use make points immutable (nothing changes inside) - -function getW(P: any): number { - return pointWindowSizes.get(P) || 1 -} - -export type IWNAF> = { - constTimeNegate: >(condition: boolean, item: T) => T - hasPrecomputes(elm: T): boolean - unsafeLadder(elm: T, n: bigint, p?: T): T - precomputeWindow(elm: T, W: number): Group[] - wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T - getPrecomputes(W: number, P: T, transform: Mapper): T[] - wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T - setWindowSize(P: T, W: number): void -} - -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -export function wNAF>(c: GroupConstructor, bits: number): IWNAF { - return { - constTimeNegate, - - hasPrecomputes(elm: T) { - return getW(elm) !== 1 - }, - - // non-const time multiplication ladder - unsafeLadder(elm: T, n: bigint, p = c.ZERO) { - let d: T = elm - while (n > _0n) { - if (n & _1n) p = p.add(d) - d = d.double() - n >>= _1n - } - return p - }, - - /** - * Creates a wNAF precomputation window. Used for caching. - * Default window size is set by `utils.precompute()` and is equal to 8. - * Number of precomputed points depends on the curve size: - * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: - * - 𝑊 is the window size - * - 𝑛 is the bitlength of the curve order. - * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. - * @param elm Point instance - * @param W window size - * @returns precomputed point tables flattened to a single array - */ - precomputeWindow(elm: T, W: number): Group[] { - const { windows, windowSize } = calcWOpts(W, bits) - const points: T[] = [] - let p: T = elm - let base = p - for (let window = 0; window < windows; window++) { - base = p - points.push(base) - // =1, because we skip zero - for (let i = 1; i < windowSize; i++) { - base = base.add(p) - points.push(base) - } - p = base.double() - } - return points - }, - - /** - * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @returns real and fake (for const-time) points - */ - wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } { - // TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise - // But need to carefully remove other checks before wNAF. ORDER == bits here - const { windows, windowSize } = calcWOpts(W, bits) - - let p = c.ZERO - let f = c.BASE - - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - // Extract W bits. - let wbits = Number(n & mask) - - // Shift number by W bits. - n >>= shiftBy - - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - - // This code was first written with assumption that 'f' and 'p' will never be infinity point: - // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, - // there is negate now: it is possible that negated element from low value - // would be the same as high element, which will create carry into next window. - // It's not obvious how this can fail, but still worth investigating later. - - // Check if we're onto Zero point. - // Add random point inside current window to f. - const offset1 = offset - const offset2 = offset + Math.abs(wbits) - 1 // -1 because we skip zero - const cond1 = window % 2 !== 0 - const cond2 = wbits < 0 - if (wbits === 0) { - // The most important part for const-time getPublicKey - f = f.add(constTimeNegate(cond1, precomputes[offset1])) - } else { - p = p.add(constTimeNegate(cond2, precomputes[offset2])) - } - } - // JIT-compiler should not eliminate f here, since it will later be used in normalizeZ() - // Even if the variable is still unused, there are some checks which will - // throw an exception, so compiler needs to prove they won't happen, which is hard. - // At this point there is a way to F be infinity-point even if p is not, - // which makes it less const-time: around 1 bigint multiply. - return { p, f } - }, - - /** - * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @param acc accumulator point to add result of multiplication - * @returns point - */ - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc: T = c.ZERO): T { - const { windows, windowSize } = calcWOpts(W, bits) - const mask = BigInt(2 ** W - 1) // Create mask with W ones: 0b1111 for W=4 etc. - const maxNumber = 2 ** W - const shiftBy = BigInt(W) - for (let window = 0; window < windows; window++) { - const offset = window * windowSize - if (n === _0n) break // No need to go over empty scalar - // Extract W bits. - let wbits = Number(n & mask) - // Shift number by W bits. - n >>= shiftBy - // If the bits are bigger than max size, we'll split those. - // +224 => 256 - 32 - if (wbits > windowSize) { - wbits -= maxNumber - n += _1n - } - if (wbits === 0) continue - let curr = precomputes[offset + Math.abs(wbits) - 1] // -1 because we skip zero - if (wbits < 0) curr = curr.negate() - // NOTE: by re-using acc, we can save a lot of additions in case of MSM - acc = acc.add(curr) - } - return acc - }, - - getPrecomputes(W: number, P: T, transform: Mapper): T[] { - // Calculate precomputes on a first run, reuse them after - let comp = pointPrecomputes.get(P) - if (!comp) { - comp = this.precomputeWindow(P, W) as T[] - if (W !== 1) pointPrecomputes.set(P, transform(comp)) - } - return comp - }, - - wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } { - const W = getW(P) - return this.wNAF(W, this.getPrecomputes(W, P, transform), n) - }, - - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T { - const W = getW(P) - if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster - return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) - }, - - // We calculate precomputes for elliptic curve point multiplication - // using windowed method. This specifies window size and - // stores precomputed values. Usually only base point would be precomputed. - - setWindowSize(P: T, W: number) { - validateW(W, bits) - pointWindowSizes.set(P, W) - pointPrecomputes.delete(P) - }, - } -} - -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster with precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -export function pippenger>( - c: GroupConstructor, - fieldN: IField, - points: T[], - scalars: bigint[], -): T { - // If we split scalars by some window (let's say 8 bits), every chunk will only - // take 256 buckets even if there are 4096 scalars, also re-uses double. - // TODO: - // - https://eprint.iacr.org/2024/750.pdf - // - https://tches.iacr.org/index.php/TCHES/article/view/10287 - // 0 is accepted in scalars - validateMSMPoints(points, c) - validateMSMScalars(scalars, fieldN) - if (points.length !== scalars.length) - throw new Error('arrays of points and scalars must have equal length') - const zero = c.ZERO - const wbits = bitLen(BigInt(points.length)) - const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits - const MASK = (1 << windowSize) - 1 - const buckets = new Array(MASK + 1).fill(zero) // +1 for zero array - const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize - let sum = zero - for (let i = lastBits; i >= 0; i -= windowSize) { - buckets.fill(zero) - for (let j = 0; j < scalars.length; j++) { - const scalar = scalars[j] - const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK)) - buckets[wbits] = buckets[wbits].add(points[j]) - } - let resI = zero // not using this will do small speed-up, but will lose ct - // Skip first bucket, because it is zero - for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { - sumI = sumI.add(buckets[j]) - resI = resI.add(sumI) - } - sum = sum.add(resI) - if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() - } - return sum as T -} -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -export function precomputeMSMUnsafe>( - c: GroupConstructor, - fieldN: IField, - points: T[], - windowSize: number, -): (scalars: bigint[]) => T { - /** - * Performance Analysis of Window-based Precomputation - * - * Base Case (256-bit scalar, 8-bit window): - * - Standard precomputation requires: - * - 31 additions per scalar × 256 scalars = 7,936 ops - * - Plus 255 summary additions = 8,191 total ops - * Note: Summary additions can be optimized via accumulator - * - * Chunked Precomputation Analysis: - * - Using 32 chunks requires: - * - 255 additions per chunk - * - 256 doublings - * - Total: (255 × 32) + 256 = 8,416 ops - * - * Memory Usage Comparison: - * Window Size | Standard Points | Chunked Points - * ------------|-----------------|--------------- - * 4-bit | 520 | 15 - * 8-bit | 4,224 | 255 - * 10-bit | 13,824 | 1,023 - * 16-bit | 557,056 | 65,535 - * - * Key Advantages: - * 1. Enables larger window sizes due to reduced memory overhead - * 2. More efficient for smaller scalar counts: - * - 16 chunks: (16 × 255) + 256 = 4,336 ops - * - ~2x faster than standard 8,191 ops - * - * Limitations: - * - Not suitable for plain precomputes (requires 256 constant doublings) - * - Performance degrades with larger scalar counts: - * - Optimal for ~256 scalars - * - Less efficient for 4096+ scalars (Pippenger preferred) - */ - validateW(windowSize, fieldN.BITS) - validateMSMPoints(points, c) - const zero = c.ZERO - const tableSize = 2 ** windowSize - 1 // table size (without zero) - const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item - const MASK = BigInt((1 << windowSize) - 1) - const tables = points.map((p: T) => { - const res = [] - for (let i = 0, acc = p; i < tableSize; i++) { - res.push(acc) - acc = acc.add(p) - } - return res - }) - return (scalars: bigint[]): T => { - validateMSMScalars(scalars, fieldN) - if (scalars.length > points.length) - throw new Error('array of scalars must be smaller than array of points') - let res = zero - for (let i = 0; i < chunks; i++) { - // No need to double if accumulator is still zero. - if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() - const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) - for (let j = 0; j < scalars.length; j++) { - const n = scalars[j] - const curr = Number((n >> shiftBy) & MASK) - if (!curr) continue // skip zero scalars chunks - res = res.add(tables[j][curr - 1]) - } - } - return res - } -} - -/** - * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. - * Though generator can be different (Fp2 / Fp6 for BLS). - */ -export type BasicCurve = { - Fp: IField // Field over which we'll do calculations (Fp) - n: bigint // Curve order, total count of valid points in the field - nBitLength?: number // bit length of curve order - nByteLength?: number // byte length of curve order - h: bigint // cofactor. we can assign default=1, but users will just ignore it w/o validation - hEff?: bigint // Number to multiply to clear cofactor - Gx: T // base point X coordinate - Gy: T // base point Y coordinate - allowInfinityPoint?: boolean // bls12-381 requires it. ZERO point is valid, but invalid pubkey -} - -export function validateBasic( - curve: BasicCurve & T, -): Readonly< - { - readonly nBitLength: number - readonly nByteLength: number - } & BasicCurve & - T & { - p: bigint - } -> { - validateField(curve.Fp) - validateObject( - curve, - { - n: 'bigint', - h: 'bigint', - Gx: 'field', - Gy: 'field', - }, - { - nBitLength: 'isSafeInteger', - nByteLength: 'isSafeInteger', - }, - ) - // Set defaults - return Object.freeze({ - ...nLength(curve.n, curve.nBitLength), - ...curve, - ...{ p: curve.Fp.ORDER }, - } as const) -} diff --git a/packages/noble-curves/src/abstract/edwards.ts b/packages/noble-curves/src/abstract/edwards.ts deleted file mode 100644 index 4f0b7d0dceb..00000000000 --- a/packages/noble-curves/src/abstract/edwards.ts +++ /dev/null @@ -1,565 +0,0 @@ -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - type AffinePoint, - type BasicCurve, - type Group, - type GroupConstructor, - pippenger, - validateBasic, - wNAF, -} from './curve.js' -import { Field, mod } from './modular.js' -import * as ut from './utils.js' -import { type FHash, type Hex, abool, ensureBytes, memoized } from './utils.js' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _8n = BigInt(8) - -/** Edwards curves must declare params a & d. */ -export type CurveType = BasicCurve & { - a: bigint // curve param a - d: bigint // curve param d - hash: FHash // Hashing - randomBytes: (bytesLength?: number) => Uint8Array // CSPRNG - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array // clears bits to get valid field elemtn - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array // Used for hashing - uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint } // Ratio √(u/v) - prehash?: FHash // RFC 8032 pre-hashing of messages to sign() / verify() - mapToCurve?: (scalar: bigint[]) => AffinePoint // for hash-to-curve standard -} - -export type CurveTypeWithLength = Readonly - -// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: -const VERIFY_DEFAULT = { zip215: true } - -function validateOpts(curve: CurveType): CurveTypeWithLength { - const opts = validateBasic(curve) - ut.validateObject( - curve, - { - hash: 'function', - a: 'bigint', - d: 'bigint', - randomBytes: 'function', - }, - { - adjustScalarBytes: 'function', - domain: 'function', - uvRatio: 'function', - mapToCurve: 'function', - }, - ) - // Set defaults - return Object.freeze({ ...opts } as const) -} - -/** Instance of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointType extends Group { - readonly ex: bigint - readonly ey: bigint - readonly ez: bigint - readonly et: bigint - get x(): bigint - get y(): bigint - assertValidity(): void - multiply(scalar: bigint): ExtPointType - multiplyUnsafe(scalar: bigint): ExtPointType - isSmallOrder(): boolean - isTorsionFree(): boolean - clearCofactor(): ExtPointType - toAffine(iz?: bigint): AffinePoint - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - _setWindowSize(windowSize: number): void -} -/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointConstructor extends GroupConstructor { - new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType - fromAffine(p: AffinePoint): ExtPointType - fromHex(hex: Hex): ExtPointType - fromPrivateKey(privateKey: Hex): ExtPointType - msm(points: ExtPointType[], scalars: bigint[]): ExtPointType -} - -/** - * Edwards Curve interface. - * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. - */ -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: Hex) => Uint8Array - sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array - verify: ( - sig: Hex, - message: Hex, - publicKey: Hex, - options?: { context?: Hex; zip215: boolean }, - ) => boolean - ExtendedPoint: ExtPointConstructor - utils: { - randomPrivateKey: () => Uint8Array - getExtendedPublicKey: (key: Hex) => { - head: Uint8Array - prefix: Uint8Array - scalar: bigint - point: ExtPointType - pointBytes: Uint8Array - } - precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType - } -} - -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -export function twistedEdwards(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) as ReturnType - const { - Fp, - n: CURVE_ORDER, - prehash: prehash, - hash: cHash, - randomBytes, - nByteLength, - h: cofactor, - } = CURVE - // Important: - // There are some places where Fp.BYTES is used instead of nByteLength. - // So far, everything has been tested with curves of Fp.BYTES == nByteLength. - // TODO: test and find curves which behave otherwise. - const MASK = _2n << (BigInt(nByteLength * 8) - _1n) - const modP = Fp.create // Function overrides - const Fn = Field(CURVE.n, CURVE.nBitLength) - - // sqrt(u/v) - const uvRatio = - CURVE.uvRatio || - ((u: bigint, v: bigint) => { - try { - return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } - } catch (e) { - return { isValid: false, value: _0n } - } - }) - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) // NOOP - const domain = - CURVE.domain || - ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { - abool('phflag', phflag) - if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') - return data - }) // NOOP - // 0 <= n < MASK - // Coordinates larger than Fp.ORDER are allowed for zip215 - function aCoordinate(title: string, n: bigint) { - ut.aInRange('coordinate ' + title, n, _0n, MASK) - } - - function assertPoint(other: unknown) { - if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint => { - const { ex: x, ey: y, ez: z } = p - const is0 = p.is0() - if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint) // 8 was chosen arbitrarily - const ax = modP(x * iz) - const ay = modP(y * iz) - const zz = modP(z * iz) - if (is0) return { x: _0n, y: _1n } - if (zz !== _1n) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - const assertValidMemo = memoized((p: Point) => { - const { a, d } = CURVE - if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? - // Equation in affine coordinates: ax² + y² = 1 + dx²y² - // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² - const { ex: X, ey: Y, ez: Z, et: T } = p - const X2 = modP(X * X) // X² - const Y2 = modP(Y * Y) // Y² - const Z2 = modP(Z * Z) // Z² - const Z4 = modP(Z2 * Z2) // Z⁴ - const aX2 = modP(X2 * a) // aX² - const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² - const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² - if (left !== right) throw new Error('bad point: equation left != right (1)') - // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T - const XY = modP(X * Y) - const ZT = modP(Z * T) - if (XY !== ZT) throw new Error('bad point: equation left != right (2)') - return true - }) - - // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). - // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates - class Point implements ExtPointType { - static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) - static readonly ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 - - constructor( - readonly ex: bigint, - readonly ey: bigint, - readonly ez: bigint, - readonly et: bigint, - ) { - aCoordinate('x', ex) - aCoordinate('y', ey) - aCoordinate('z', ez) - aCoordinate('t', et) - Object.freeze(this) - } - - get x(): bigint { - return this.toAffine().x - } - get y(): bigint { - return this.toAffine().y - } - - static fromAffine(p: AffinePoint): Point { - if (p instanceof Point) throw new Error('extended point not allowed') - const { x, y } = p || {} - aCoordinate('x', x) - aCoordinate('y', y) - return new Point(x, y, _1n, modP(x * y)) - } - static normalizeZ(points: Point[]): Point[] { - const toInv = Fp.invertBatch(points.map((p) => p.ez)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - // Multiscalar Multiplication - static msm(points: Point[], scalars: bigint[]): Point { - return pippenger(Point, Fn, points, scalars) - } - - // "Private method", don't use it directly - _setWindowSize(windowSize: number) { - wnaf.setWindowSize(this, windowSize) - } - // Not required for fromHex(), which always creates valid points. - // Could be useful for fromAffine(). - assertValidity(): void { - assertValidMemo(this) - } - - // Compare one point to another. - equals(other: Point): boolean { - assertPoint(other) - const { ex: X1, ey: Y1, ez: Z1 } = this - const { ex: X2, ey: Y2, ez: Z2 } = other - const X1Z2 = modP(X1 * Z2) - const X2Z1 = modP(X2 * Z1) - const Y1Z2 = modP(Y1 * Z2) - const Y2Z1 = modP(Y2 * Z1) - return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 - } - - is0(): boolean { - return this.equals(Point.ZERO) - } - - negate(): Point { - // Flips point sign to a negative one (-x, y in affine coords) - return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) - } - - // Fast algo for doubling Extended Point. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd - // Cost: 4M + 4S + 1*a + 6add + 1*2. - double(): Point { - const { a } = CURVE - const { ex: X1, ey: Y1, ez: Z1 } = this - const A = modP(X1 * X1) // A = X12 - const B = modP(Y1 * Y1) // B = Y12 - const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 - const D = modP(a * A) // D = a*A - const x1y1 = X1 + Y1 - const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B - const G = D + B // G = D+B - const F = G - C // F = G-C - const H = D - B // H = D-B - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - - // Fast algo for adding 2 Extended Points. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd - // Cost: 9M + 1*a + 1*d + 7add. - add(other: Point) { - assertPoint(other) - const { a, d } = CURVE - const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this - const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other - // Faster algo for adding 2 Extended Points when curve's a=-1. - // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-4 - // Cost: 8M + 8add + 2*2. - // Note: It does not check whether the `other` point is valid. - if (a === BigInt(-1)) { - const A = modP((Y1 - X1) * (Y2 + X2)) - const B = modP((Y1 + X1) * (Y2 - X2)) - const F = modP(B - A) - if (F === _0n) return this.double() // Same point. Tests say it doesn't affect timing - const C = modP(Z1 * _2n * T2) - const D = modP(T1 * _2n * Z2) - const E = D + C - const G = B + A - const H = D - C - const X3 = modP(E * F) - const Y3 = modP(G * H) - const T3 = modP(E * H) - const Z3 = modP(F * G) - return new Point(X3, Y3, Z3, T3) - } - const A = modP(X1 * X2) // A = X1*X2 - const B = modP(Y1 * Y2) // B = Y1*Y2 - const C = modP(T1 * d * T2) // C = T1*d*T2 - const D = modP(Z1 * Z2) // D = Z1*Z2 - const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B - const F = D - C // F = D-C - const G = D + C // G = D+C - const H = modP(B - a * A) // H = B-a*A - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - - return new Point(X3, Y3, Z3, T3) - } - - subtract(other: Point): Point { - return this.add(other.negate()) - } - - private wNAF(n: bigint): { p: Point; f: Point } { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - - // Constant-time multiplication. - multiply(scalar: bigint): Point { - const n = scalar - ut.aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L - const { p, f } = this.wNAF(n) - return Point.normalizeZ([p, f])[0] - } - - // Non-constant-time multiplication. Uses double-and-add algorithm. - // It's faster, but should only be used when you don't care about - // an exposed private key e.g. sig verification. - // Does NOT allow scalars higher than CURVE.n. - // Accepts optional accumulator to merge with multiply (important for sparse scalars) - multiplyUnsafe(scalar: bigint, acc = Point.ZERO): Point { - const n = scalar - ut.aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L - if (n === _0n) return I - if (this.is0() || n === _1n) return this - return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) - } - - // Checks if point is of small order. - // If you add something to small order point, you will have "dirty" - // point with torsion component. - // Multiplies point by cofactor and checks if the result is 0. - isSmallOrder(): boolean { - return this.multiplyUnsafe(cofactor).is0() - } - - // Multiplies point by curve order and checks if the result is 0. - // Returns `false` is the point is dirty. - isTorsionFree(): boolean { - return wnaf.unsafeLadder(this, CURVE_ORDER).is0() - } - - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - toAffine(iz?: bigint): AffinePoint { - return toAffineMemo(this, iz) - } - - clearCofactor(): Point { - const { h: cofactor } = CURVE - if (cofactor === _1n) return this - return this.multiplyUnsafe(cofactor) - } - - // Converts hash string or Uint8Array to Point. - // Uses algo from RFC8032 5.1.3. - static fromHex(hex: Hex, zip215 = false): Point { - const { d, a } = CURVE - const len = Fp.BYTES - hex = ensureBytes('pointHex', hex, len) // copy hex to a new array - abool('zip215', zip215) - const normed = hex.slice() // copy again, we'll manipulate it - const lastByte = hex[len - 1] // select last byte - normed[len - 1] = lastByte & ~0x80 // clear last bit - const y = ut.bytesToNumberLE(normed) - - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // RFC8032 prohibits >= p, but ZIP215 doesn't - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - const max = zip215 ? MASK : Fp.ORDER - ut.aInRange('pointHex.y', y, _0n, max) - - // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: - // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) - const y2 = modP(y * y) // denominator is always non-0 mod p. - const u = modP(y2 - _1n) // u = y² - 1 - const v = modP(d * y2 - a) // v = d y² + 1. - let { isValid, value: x } = uvRatio(u, v) // √(u/v) - if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') - const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper - const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit - if (!zip215 && x === _0n && isLastByteOdd) - // if x=0 and x_0 = 1, fail - throw new Error('Point.fromHex: x=0 and x_0=1') - if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x - return Point.fromAffine({ x, y }) - } - static fromPrivateKey(privKey: Hex) { - return getExtendedPublicKey(privKey).point - } - toRawBytes(): Uint8Array { - const { x, y } = this.toAffine() - const bytes = ut.numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) - bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y - return bytes // and use the last byte to encode sign of x - } - toHex(): string { - return ut.bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. - } - } - const { BASE: G, ZERO: I } = Point - const wnaf = wNAF(Point, nByteLength * 8) - - function modN(a: bigint) { - return mod(a, CURVE_ORDER) - } - // Little-endian SHA512 with modulo n - function modN_LE(hash: Uint8Array): bigint { - return modN(ut.bytesToNumberLE(hash)) - } - - /** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */ - function getExtendedPublicKey(key: Hex) { - const len = Fp.BYTES - key = ensureBytes('private key', key, len) - // Hash private key with curve's hash function to produce uniformingly random input - // Check byte lengths: ensure(64, h(ensure(32, key))) - const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) - const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE - const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) - const scalar = modN_LE(head) // The actual private scalar - const point = G.multiply(scalar) // Point on Edwards curve aka public key - const pointBytes = point.toRawBytes() // Uint8Array representation - return { head, prefix, scalar, point, pointBytes } - } - - // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared - function getPublicKey(privKey: Hex): Uint8Array { - return getExtendedPublicKey(privKey).pointBytes - } - - // int('LE', SHA512(dom2(F, C) || msgs)) mod N - function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) { - const msg = ut.concatBytes(...msgs) - return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) - } - - /** Signs message with privateKey. RFC8032 5.1.6 */ - function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array { - msg = ensureBytes('message', msg) - if (prehash) msg = prehash(msg) // for ed25519ph etc. - const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) - const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) - const R = G.multiply(r).toRawBytes() // R = rG - const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) - const s = modN(r + k * scalar) // S = (r + k * s) mod L - ut.aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l - const res = ut.concatBytes(R, ut.numberToBytesLE(s, Fp.BYTES)) - return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature - } - - const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT - - /** - * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - * An extended group equation is checked. - */ - function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean { - const { context, zip215 } = options - const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. - msg = ensureBytes('message', msg) - publicKey = ensureBytes('publicKey', publicKey, len) - if (zip215 !== undefined) abool('zip215', zip215) - if (prehash) msg = prehash(msg) // for ed25519ph, etc - - const s = ut.bytesToNumberLE(sig.slice(len, 2 * len)) - let A, R, SB - try { - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - A = Point.fromHex(publicKey, zip215) - R = Point.fromHex(sig.slice(0, len), zip215) - SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside - } catch (error) { - return false - } - if (!zip215 && A.isSmallOrder()) return false - - const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) - const RkA = R.add(A.multiplyUnsafe(k)) - // Extended group equation - // [8][S]B = [8]R + [8][k]A' - return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) - } - - G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. - - const utils = { - getExtendedPublicKey, - // ed25519 private keys are uniform 32b. No need to check for modulo bias, like in secp256k1. - randomPrivateKey: (): Uint8Array => randomBytes(Fp.BYTES), - - /** - * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT - * values. This slows down first getPublicKey() by milliseconds (see Speed section), - * but allows to speed-up subsequent getPublicKey() calls up to 20x. - * @param windowSize 2, 4, 8, 16 - */ - precompute(windowSize = 8, point: ExtPointType = Point.BASE): ExtPointType { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) - return point - }, - } - - return { - CURVE, - getPublicKey, - sign, - verify, - ExtendedPoint: Point, - utils, - } -} diff --git a/packages/noble-curves/src/abstract/hash-to-curve.ts b/packages/noble-curves/src/abstract/hash-to-curve.ts deleted file mode 100644 index 1ecedd0bf19..00000000000 --- a/packages/noble-curves/src/abstract/hash-to-curve.ts +++ /dev/null @@ -1,255 +0,0 @@ -/** - * hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import type { AffinePoint, Group, GroupConstructor } from './curve.js' -import { type IField, mod } from './modular.js' -import type { CHash } from './utils.js' -import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.js' - -export type UnicodeOrBytes = string | Uint8Array - -/** - * * `DST` is a domain separation tag, defined in section 2.2.5 - * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m - * * `m` is extension degree (1 for prime fields) - * * `k` is the target security target in bits (e.g. 128), from section 5.1 - * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) - * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props - */ -export type Opts = { - DST: UnicodeOrBytes - p: bigint - m: number - k: number - expand: 'xmd' | 'xof' - hash: CHash -} - -// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. -const os2ip = bytesToNumberBE - -// Integer to Octet Stream (numberToBytesBE) -function i2osp(value: number, length: number): Uint8Array { - anum(value) - anum(length) - if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) - const res = Array.from({ length }).fill(0) as number[] - for (let i = length - 1; i >= 0; i--) { - res[i] = value & 0xff - value >>>= 8 - } - return new Uint8Array(res) -} - -function strxor(a: Uint8Array, b: Uint8Array): Uint8Array { - const arr = new Uint8Array(a.length) - for (let i = 0; i < a.length; i++) { - arr[i] = a[i] ^ b[i] - } - return arr -} - -function anum(item: unknown): void { - if (!Number.isSafeInteger(item)) throw new Error('number expected') -} - -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -export function expand_message_xmd( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - H: CHash, -): Uint8Array { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) - const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H - const ell = Math.ceil(lenInBytes / b_in_bytes) - if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') - 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) // len_in_bytes_str - const b = new Array(ell) - const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) - b[0] = 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] = H(concatBytes(...args)) - } - const pseudo_random_bytes = concatBytes(...b) - return pseudo_random_bytes.slice(0, lenInBytes) -} - -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -export function expand_message_xof( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - k: number, - H: CHash, -): Uint8Array { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); - if (DST.length > 255) { - const dkLen = Math.ceil((2 * k) / 8) - DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() - } - if (lenInBytes > 65535 || DST.length > 255) - throw new Error('expand_message_xof: invalid lenInBytes') - return ( - H.create({ dkLen: lenInBytes }) - .update(msg) - .update(i2osp(lenInBytes, 2)) - // 2. DST_prime = DST || I2OSP(len(DST), 1) - .update(DST) - .update(i2osp(DST.length, 1)) - .digest() - ) -} - -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] { - validateObject(options, { - DST: 'stringOrUint8Array', - p: 'bigint', - m: 'isSafeInteger', - k: 'isSafeInteger', - hash: 'hash', - }) - const { p, k, m, hash, expand, DST: _DST } = options - abytes(msg) - anum(count) - const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST - const log2p = p.toString(2).length - const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above - const len_in_bytes = count * m * L - let prb // pseudo_random_bytes - if (expand === 'xmd') { - prb = expand_message_xmd(msg, DST, len_in_bytes, hash) - } else if (expand === 'xof') { - prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) - } else if (expand === '_internal_pass') { - // for internal tests only - prb = msg - } else { - throw new Error('expand must be "xmd" or "xof"') - } - const u = new Array(count) - for (let i = 0; i < count; i++) { - const e = new Array(m) - for (let j = 0; j < m; j++) { - const elm_offset = L * (j + i * m) - const tv = prb.subarray(elm_offset, elm_offset + L) - e[j] = mod(os2ip(tv), p) - } - u[i] = e - } - return u -} - -export type XY = ( - x: T, - y: T, -) => { - x: T - y: T -} -export function isogenyMap>(field: F, map: [T[], T[], T[], T[]]): XY { - // Make same order as in spec - const COEFF = map.map((i) => Array.from(i).reverse()) - return (x: T, y: T) => { - const [xNum, xDen, yNum, yDen] = COEFF.map((val) => - val.reduce((acc, i) => field.add(field.mul(acc, x), i)), - ) - x = field.div(xNum, xDen) // xNum / xDen - y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) - return { x: x, y: y } - } -} - -/** Point interface, which curves must implement to work correctly with the module. */ -export interface H2CPoint extends Group> { - add(rhs: H2CPoint): H2CPoint - toAffine(iz?: bigint): AffinePoint - clearCofactor(): H2CPoint - assertValidity(): void -} - -export interface H2CPointConstructor extends GroupConstructor> { - fromAffine(ap: AffinePoint): H2CPoint -} - -export type MapToCurve = (scalar: bigint[]) => AffinePoint - -// Separated from initialization opts, so users won't accidentally change per-curve parameters -// (changing DST is ok!) -export type htfBasicOpts = { DST: UnicodeOrBytes } -export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint -export type MapMethod = (scalars: bigint[]) => H2CPoint - -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -export function createHasher( - Point: H2CPointConstructor, - mapToCurve: MapToCurve, - def: Opts & { encodeDST?: UnicodeOrBytes }, -): { - hashToCurve: HTFMethod - encodeToCurve: HTFMethod - mapToCurve: MapMethod -} { - if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') - return { - // Encodes byte string to elliptic curve. - // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - hashToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { - const u = hash_to_field(msg, 2, { ...def, DST: def.DST, ...options } as Opts) - const u0 = Point.fromAffine(mapToCurve(u[0])) - const u1 = Point.fromAffine(mapToCurve(u[1])) - const P = u0.add(u1).clearCofactor() - P.assertValidity() - return P - }, - - // Encodes byte string to elliptic curve. - // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { - const u = hash_to_field(msg, 1, { ...def, DST: def.encodeDST, ...options } as Opts) - const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() - P.assertValidity() - return P - }, - // Same as encodeToCurve, but without hash - mapToCurve(scalars: bigint[]): H2CPoint { - if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') - for (const i of scalars) - if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') - const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() - P.assertValidity() - return P - }, - } -} diff --git a/packages/noble-curves/src/abstract/modular.ts b/packages/noble-curves/src/abstract/modular.ts deleted file mode 100644 index e36f68478d1..00000000000 --- a/packages/noble-curves/src/abstract/modular.ts +++ /dev/null @@ -1,555 +0,0 @@ -/** - * Utils for modular division and finite fields. - * A finite field over 11 is integer number operations `mod 11`. - * There is no division: it is replaced by modular multiplicative inverse. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - bitMask, - bytesToNumberBE, - bytesToNumberLE, - ensureBytes, - numberToBytesBE, - numberToBytesLE, - validateObject, -} from './utils.js' - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = /* @__PURE__ */ BigInt(2), - _3n = /* @__PURE__ */ BigInt(3) -// prettier-ignore -const _4n = /* @__PURE__ */ BigInt(4), - _5n = /* @__PURE__ */ BigInt(5), - _8n = /* @__PURE__ */ BigInt(8) -// prettier-ignore -const _9n = /* @__PURE__ */ BigInt(9), - _16n = /* @__PURE__ */ BigInt(16) - -// Calculates a modulo b -export function mod(a: bigint, b: bigint): bigint { - const result = a % b - return result >= _0n ? result : b + result -} -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -export function pow(num: bigint, power: bigint, modulo: bigint): bigint { - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (modulo <= _0n) throw new Error('invalid modulus') - 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 -} - -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -export function pow2(x: bigint, power: bigint, modulo: bigint): bigint { - let res = x - while (power-- > _0n) { - res *= res - res %= modulo - } - return res -} - -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -export function invert(number: bigint, modulo: bigint): bigint { - if (number === _0n) throw new Error('invert: expected non-zero number') - if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) - // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. - let a = mod(number, modulo) - let b = modulo - // prettier-ignore - let x = _0n, - y = _1n, - u = _1n, - v = _0n - while (a !== _0n) { - // JIT applies optimization if those two lines follow each other - const q = b / a - const r = b % a - const m = x - u * q - const n = y - v * q - // prettier-ignore - ;(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) -} - -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -export function tonelliShanks(P: bigint): (Fp: IField, n: T) => T { - // Legendre constant: used to calculate Legendre symbol (a | p), - // which denotes the value of a^((p-1)/2) (mod p). - // (a | p) ≡ 1 if a is a square (mod p) - // (a | p) ≡ -1 if a is not a square (mod p) - // (a | p) ≡ 0 if a ≡ 0 (mod p) - const legendreC = (P - _1n) / _2n - - let Q: bigint, S: number, Z: bigint - // Step 1: By factoring out powers of 2 from p - 1, - // find q and s such that p - 1 = q*(2^s) with q odd - for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); - - // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq - for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { - // Crash instead of infinity loop, we cannot reasonable count until P. - if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') - } - - // Fast-path - if (S === 1) { - const p1div4 = (P + _1n) / _4n - return function tonelliFast(Fp: IField, n: T) { - const root = Fp.pow(n, p1div4) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // Slow-path - const Q1div2 = (Q + _1n) / _2n - return function tonelliSlow(Fp: IField, n: T): T { - // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 - if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') - let r = S - // TODO: will fail at Fp2/etc - let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b - let x = Fp.pow(n, Q1div2) // first guess at the square root - let b = Fp.pow(n, Q) // first guess at the fudge factor - - while (!Fp.eql(b, Fp.ONE)) { - if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) - // Find m such b^(2^m)==1 - let m = 1 - for (let t2 = Fp.sqr(b); m < r; m++) { - if (Fp.eql(t2, Fp.ONE)) break - t2 = Fp.sqr(t2) // t2 *= t2 - } - // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow - const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) - g = Fp.sqr(ge) // g = ge * ge - x = Fp.mul(x, ge) // x *= ge - b = Fp.mul(b, g) // b *= g - r = m - } - return x - } -} - -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -export function FpSqrt(P: bigint): (Fp: IField, n: T) => T { - // P ≡ 3 (mod 4) - // √n = n^((P+1)/4) - if (P % _4n === _3n) { - // Not all roots possible! - // const ORDER = - // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; - // const NUM = 72057594037927816n; - const p1div4 = (P + _1n) / _4n - return function sqrt3mod4(Fp: IField, n: T) { - const root = Fp.pow(n, p1div4) - // Throw if root**2 != n - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) - if (P % _8n === _5n) { - const c1 = (P - _5n) / _8n - return function sqrt5mod8(Fp: IField, n: T) { - const n2 = Fp.mul(n, _2n) - const v = Fp.pow(n2, c1) - const nv = Fp.mul(n, v) - const i = Fp.mul(Fp.mul(nv, _2n), v) - const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // P ≡ 9 (mod 16) - if (P % _16n === _9n) { - // NOTE: tonelli is too slow for bls-Fp2 calculations even on start - // Means we cannot use sqrt for constants at all! - // - // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F - // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F - // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F - // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic - // sqrt = (x) => { - // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 - // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 - // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 - // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 - // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x - // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x - // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x - // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x - // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x - // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 - // } - } - // Other cases: Tonelli-Shanks algorithm - return tonelliShanks(P) -} - -// Little-endian check for first LE bit (last BE bit); -export const isNegativeLE = (num: bigint, modulo: bigint): boolean => - (mod(num, modulo) & _1n) === _1n - -/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ -export interface IField { - ORDER: bigint - isLE: boolean - BYTES: number - BITS: number - MASK: bigint - ZERO: T - ONE: T - // 1-arg - create: (num: T) => T - isValid: (num: T) => boolean - is0: (num: T) => boolean - neg(num: T): T - inv(num: T): T - sqrt(num: T): T - sqr(num: T): T - // 2-args - eql(lhs: T, rhs: T): boolean - add(lhs: T, rhs: T): T - sub(lhs: T, rhs: T): T - mul(lhs: T, rhs: T | bigint): T - pow(lhs: T, power: bigint): T - div(lhs: T, rhs: T | bigint): T - // N for NonNormalized (for now) - addN(lhs: T, rhs: T): T - subN(lhs: T, rhs: T): T - mulN(lhs: T, rhs: T | bigint): T - sqrN(num: T): T - - // Optional - // Should be same as sgn0 function in - // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1). - // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway. - isOdd?(num: T): boolean // Odd instead of even since we have it for Fp2 - // legendre?(num: T): T; - pow(lhs: T, power: bigint): T - invertBatch: (lst: T[]) => T[] - toBytes(num: T): Uint8Array - fromBytes(bytes: Uint8Array): T - // If c is False, CMOV returns a, otherwise it returns b. - cmov(a: T, b: T, c: boolean): T -} -// prettier-ignore -const FIELD_FIELDS = [ - 'create', - 'isValid', - 'is0', - 'neg', - 'inv', - 'sqrt', - 'sqr', - 'eql', - 'add', - 'sub', - 'mul', - 'pow', - 'div', - 'addN', - 'subN', - 'mulN', - 'sqrN', -] as const -export function validateField(field: IField): IField { - const initial = { - ORDER: 'bigint', - MASK: 'bigint', - BYTES: 'isSafeInteger', - BITS: 'isSafeInteger', - } as Record - const opts = FIELD_FIELDS.reduce((map, val: string) => { - map[val] = 'function' - return map - }, initial) - return validateObject(field, opts) -} - -// Generic field functions - -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -export function FpPow(f: IField, num: T, power: bigint): T { - // Should have same speed as pow for bigints - // TODO: benchmark! - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (power === _0n) return f.ONE - if (power === _1n) return num - let p = f.ONE - let d = num - while (power > _0n) { - if (power & _1n) p = f.mul(p, d) - d = f.sqr(d) - power >>= _1n - } - return p -} - -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -export function FpInvertBatch(f: IField, nums: T[]): T[] { - const tmp = new Array(nums.length) - // Walk from first to last, multiply them by each other MOD p - const lastMultiplied = nums.reduce((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = acc - return f.mul(acc, num) - }, f.ONE) - // Invert last element - const inverted = f.inv(lastMultiplied) - // Walk from last to first, multiply them by inverted each other MOD p - nums.reduceRight((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = f.mul(acc, tmp[i]) - return f.mul(acc, num) - }, inverted) - return tmp -} - -export function FpDiv(f: IField, lhs: T, rhs: T | bigint): T { - return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) -} - -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -export function FpLegendre(order: bigint): (f: IField, x: T) => T { - const legendreConst = (order - _1n) / _2n // Integer arithmetic - return (f: IField, x: T): T => f.pow(x, legendreConst) -} - -// This function returns True whenever the value x is a square in the field F. -export function FpIsSquare(f: IField): (x: T) => boolean { - const legendre = FpLegendre(f.ORDER) - return (x: T): boolean => { - const p = legendre(f, x) - return f.eql(p, f.ZERO) || f.eql(p, f.ONE) - } -} - -// CURVE.n lengths -export function nLength( - n: bigint, - nBitLength?: number, -): { - nBitLength: number - nByteLength: number -} { - // Bit size, byte size of CURVE.n - const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length - const nByteLength = Math.ceil(_nBitLength / 8) - return { nBitLength: _nBitLength, nByteLength } -} - -type FpField = IField & Required, 'isOdd'>> -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -export function Field( - ORDER: bigint, - bitLen?: number, - isLE = false, - redef: Partial> = {}, -): Readonly { - if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) - const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) - if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') - let sqrtP: ReturnType // cached sqrtP - const f: Readonly = Object.freeze({ - ORDER, - isLE, - BITS, - BYTES, - MASK: bitMask(BITS), - ZERO: _0n, - ONE: _1n, - create: (num) => mod(num, ORDER), - isValid: (num) => { - if (typeof num !== 'bigint') - throw new Error('invalid field element: expected bigint, got ' + typeof num) - return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible - }, - is0: (num) => num === _0n, - isOdd: (num) => (num & _1n) === _1n, - neg: (num) => mod(-num, ORDER), - eql: (lhs, rhs) => lhs === rhs, - - sqr: (num) => mod(num * num, ORDER), - add: (lhs, rhs) => mod(lhs + rhs, ORDER), - sub: (lhs, rhs) => mod(lhs - rhs, ORDER), - mul: (lhs, rhs) => mod(lhs * rhs, ORDER), - pow: (num, power) => FpPow(f, num, power), - div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), - - // Same as above, but doesn't normalize - sqrN: (num) => num * num, - addN: (lhs, rhs) => lhs + rhs, - subN: (lhs, rhs) => lhs - rhs, - mulN: (lhs, rhs) => lhs * rhs, - - inv: (num) => invert(num, ORDER), - sqrt: - redef.sqrt || - ((n) => { - if (!sqrtP) sqrtP = FpSqrt(ORDER) - return sqrtP(f, n) - }), - invertBatch: (lst) => FpInvertBatch(f, lst), - // TODO: do we really need constant cmov? - // We don't have const-time bigints anyway, so probably will be not very useful - cmov: (a, b, c) => (c ? b : a), - toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), - fromBytes: (bytes) => { - if (bytes.length !== BYTES) - throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) - return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) - }, - } as FpField) - return Object.freeze(f) -} - -export function FpSqrtOdd(Fp: IField, elm: T): T { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? root : Fp.neg(root) -} - -export function FpSqrtEven(Fp: IField, elm: T): T { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? Fp.neg(root) : root -} - -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -export function hashToPrivateScalar( - hash: string | Uint8Array, - groupOrder: bigint, - isLE = false, -): bigint { - hash = ensureBytes('privateHash', hash) - const hashLen = hash.length - const minLen = nLength(groupOrder).nByteLength + 8 - if (minLen < 24 || hashLen < minLen || hashLen > 1024) - throw new Error( - 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, - ) - const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) - return mod(num, groupOrder - _1n) + _1n -} - -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -export function getFieldBytesLength(fieldOrder: bigint): number { - if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') - const bitLength = fieldOrder.toString(2).length - return Math.ceil(bitLength / 8) -} - -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -export function getMinHashLength(fieldOrder: bigint): number { - const length = getFieldBytesLength(fieldOrder) - return length + Math.ceil(length / 2) -} - -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array { - const len = key.length - const fieldLen = getFieldBytesLength(fieldOrder) - const minLen = getMinHashLength(fieldOrder) - // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. - if (len < 16 || len < minLen || len > 1024) - throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) - const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) - // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 - const reduced = mod(num, fieldOrder - _1n) + _1n - return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) -} diff --git a/packages/noble-curves/src/abstract/montgomery.ts b/packages/noble-curves/src/abstract/montgomery.ts deleted file mode 100644 index 106a0c1943b..00000000000 --- a/packages/noble-curves/src/abstract/montgomery.ts +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Montgomery curve methods. It's not really whole montgomery curve, - * just bunch of very specific methods for X25519 / X448 from - * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { mod, pow } from './modular.js' -import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.js' - -const _0n = BigInt(0) -const _1n = BigInt(1) -type Hex = string | Uint8Array - -export type CurveType = { - P: bigint // finite field prime - nByteLength: number - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - a: bigint - montgomeryBits: number - powPminus2?: (x: bigint) => bigint - xyToU?: (x: bigint, y: bigint) => bigint - Gu: bigint - randomBytes?: (bytesLength?: number) => Uint8Array -} - -export type CurveFn = { - scalarMult: (scalar: Hex, u: Hex) => Uint8Array - scalarMultBase: (scalar: Hex) => Uint8Array - getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array - getPublicKey: (privateKey: Hex) => Uint8Array - utils: { randomPrivateKey: () => Uint8Array } - GuBytes: Uint8Array -} - -function validateOpts(curve: CurveType) { - validateObject( - curve, - { - a: 'bigint', - }, - { - montgomeryBits: 'isSafeInteger', - nByteLength: 'isSafeInteger', - adjustScalarBytes: 'function', - domain: 'function', - powPminus2: 'function', - Gu: 'bigint', - }, - ) - // Set defaults - return Object.freeze({ ...curve } as const) -} - -// Uses only one coordinate instead of two -export function montgomery(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) - const { P } = CURVE - const modP = (n: bigint) => mod(n, P) - const montgomeryBits = CURVE.montgomeryBits - const montgomeryBytes = Math.ceil(montgomeryBits / 8) - const fieldLen = CURVE.nByteLength - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) - const powPminus2 = CURVE.powPminus2 || ((x: bigint) => pow(x, P - BigInt(2), P)) - - // cswap from RFC7748. But it is not from RFC7748! - /* - cswap(swap, x_2, x_3): - dummy = mask(swap) AND (x_2 XOR x_3) - x_2 = x_2 XOR dummy - x_3 = x_3 XOR dummy - Return (x_2, x_3) - Where mask(swap) is the all-1 or all-0 word of the same length as x_2 - and x_3, computed, e.g., as mask(swap) = 0 - swap. - */ - function cswap(swap: bigint, x_2: bigint, x_3: bigint): [bigint, bigint] { - const dummy = modP(swap * (x_2 - x_3)) - x_2 = modP(x_2 - dummy) - x_3 = modP(x_3 + dummy) - return [x_2, x_3] - } - - // x25519 from 4 - // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 - const a24 = (CURVE.a - BigInt(2)) / BigInt(4) - /** - * - * @param pointU u coordinate (x) on Montgomery Curve 25519 - * @param scalar by which the point would be multiplied - * @returns new Point on Montgomery curve - */ - function montgomeryLadder(u: bigint, scalar: bigint): bigint { - aInRange('u', u, _0n, P) - aInRange('scalar', scalar, _0n, P) - // Section 5: Implementations MUST accept non-canonical values and process them as - // if they had been reduced modulo the field prime. - const k = scalar - const x_1 = u - let x_2 = _1n - let z_2 = _0n - let x_3 = u - let z_3 = _1n - let swap = _0n - let sw: [bigint, bigint] - for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { - const k_t = (k >> t) & _1n - swap ^= k_t - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - swap = k_t - - const A = x_2 + z_2 - const AA = modP(A * A) - const B = x_2 - z_2 - const BB = modP(B * B) - const E = AA - BB - const C = x_3 + z_3 - const D = x_3 - z_3 - const DA = modP(D * A) - const CB = modP(C * B) - const dacb = DA + CB - const da_cb = DA - CB - x_3 = modP(dacb * dacb) - z_3 = modP(x_1 * modP(da_cb * da_cb)) - x_2 = modP(AA * BB) - z_2 = modP(E * (AA + modP(a24 * E))) - } - // (x_2, x_3) = cswap(swap, x_2, x_3) - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - // (z_2, z_3) = cswap(swap, z_2, z_3) - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - // z_2^(p - 2) - const z2 = powPminus2(z_2) - // Return x_2 * (z_2^(p - 2)) - return modP(x_2 * z2) - } - - function encodeUCoordinate(u: bigint): Uint8Array { - return numberToBytesLE(modP(u), montgomeryBytes) - } - - function decodeUCoordinate(uEnc: Hex): bigint { - // Section 5: When receiving such an array, implementations of X25519 - // MUST mask the most significant bit in the final byte. - const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) - if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 - return bytesToNumberLE(u) - } - function decodeScalar(n: Hex): bigint { - const bytes = ensureBytes('scalar', n) - const len = bytes.length - if (len !== montgomeryBytes && len !== fieldLen) { - let valid = '' + montgomeryBytes + ' or ' + fieldLen - throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) - } - return bytesToNumberLE(adjustScalarBytes(bytes)) - } - function scalarMult(scalar: Hex, u: Hex): Uint8Array { - const pointU = decodeUCoordinate(u) - const _scalar = decodeScalar(scalar) - const pu = montgomeryLadder(pointU, _scalar) - // The result was not contributory - // https://cr.yp.to/ecdh.html#validate - if (pu === _0n) throw new Error('invalid private or public key received') - return encodeUCoordinate(pu) - } - // Computes public key from private. By doing scalar multiplication of base point. - const GuBytes = encodeUCoordinate(CURVE.Gu) - function scalarMultBase(scalar: Hex): Uint8Array { - return scalarMult(scalar, GuBytes) - } - - return { - scalarMult, - scalarMultBase, - getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey), - getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey), - utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) }, - GuBytes: GuBytes, - } -} diff --git a/packages/noble-curves/src/abstract/poseidon.ts b/packages/noble-curves/src/abstract/poseidon.ts deleted file mode 100644 index 025f8d089f4..00000000000 --- a/packages/noble-curves/src/abstract/poseidon.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { FpPow, type IField, validateField } from './modular.js' - -export type PoseidonOpts = { - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean // Hack for stark - mds: bigint[][] - roundConstants: bigint[][] -} - -export function validateOpts(opts: PoseidonOpts): Readonly<{ - rounds: number - sboxFn: (n: bigint) => bigint - roundConstants: bigint[][] - mds: bigint[][] - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean // Hack for stark -}> { - const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts - const { roundsFull, roundsPartial, sboxPower, t } = opts - - validateField(Fp) - for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) { - if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) - throw new Error('invalid number ' + i) - } - - // MDS is TxT matrix - if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') - const _mds = mds.map((mdsRow) => { - if (!Array.isArray(mdsRow) || mdsRow.length !== t) - throw new Error('invalid MDS matrix row: ' + mdsRow) - return mdsRow.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) - return Fp.create(i) - }) - }) - - if (rev !== undefined && typeof rev !== 'boolean') - throw new Error('invalid param reversePartialPowIdx=' + rev) - - if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) - const rounds = roundsFull + roundsPartial - - if (!Array.isArray(rc) || rc.length !== rounds) - throw new Error('Poseidon: invalid round constants') - const roundConstants = rc.map((rc) => { - if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') - return rc.map((i) => { - if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') - return Fp.create(i) - }) - }) - - if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower') - const _sboxPower = BigInt(sboxPower) - let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower) - // Unwrapped sbox power for common cases (195->142μs) - if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(n), n) - else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) - - return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) -} - -export function splitConstants(rc: bigint[], t: number): bigint[][] { - if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') - if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') - const res = [] - let tmp = [] - for (let i = 0; i < rc.length; i++) { - tmp.push(rc[i]) - if (tmp.length === t) { - res.push(tmp) - tmp = [] - } - } - return res -} - -/** Poseidon NTT-friendly hash. */ -export function poseidon(opts: PoseidonOpts): { - (values: bigint[]): bigint[] - // For verification in tests - roundConstants: bigint[][] -} { - const _opts = validateOpts(opts) - const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts - const halfRoundsFull = _opts.roundsFull / 2 - const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 - const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => { - values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) - - if (isFull) values = values.map((i) => sboxFn(i)) - else values[partialIdx] = sboxFn(values[partialIdx]) - // Matrix multiplication - values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) - return values - } - const poseidonHash = function poseidonHash(values: bigint[]) { - if (!Array.isArray(values) || values.length !== t) - throw new Error('invalid values, expected array of bigints with length ' + t) - values = values.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) - return Fp.create(i) - }) - let lastRound = 0 - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - // Apply r_p partial rounds. - for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - - if (lastRound !== totalRounds) throw new Error('invalid number of rounds') - return values - } - // For verification in tests - poseidonHash.roundConstants = roundConstants - return poseidonHash -} diff --git a/packages/noble-curves/src/abstract/tower.ts b/packages/noble-curves/src/abstract/tower.ts deleted file mode 100644 index 743da2f7b33..00000000000 --- a/packages/noble-curves/src/abstract/tower.ts +++ /dev/null @@ -1,664 +0,0 @@ -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import * as mod from './modular.js' -import { bitLen, bitMask, concatBytes, notImplemented } from './utils.js' -import type { ProjConstructor, ProjPointType } from './weierstrass.js' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) - -// Fp₂ over complex plane -export type BigintTuple = [bigint, bigint] -export type Fp = bigint -// Finite extension field over irreducible polynominal. -// Fp(u) / (u² - β) where β = -1 -export type Fp2 = { c0: bigint; c1: bigint } -export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] -export type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 } -export type Fp12 = { c0: Fp6; c1: Fp6 } // Fp₁₂ = Fp₆² => Fp₂³, Fp₆(w) / (w² - γ) where γ = v -// prettier-ignore -export type BigintTwelve = [ - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, -] - -export type Fp2Bls = mod.IField & { - reim: (num: Fp2) => { re: Fp; im: Fp } - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - fromBigTuple(num: [bigint, bigint]): Fp2 -} - -export type Fp12Bls = mod.IField & { - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - fromBigTwelve(num: BigintTwelve): Fp12 -} - -function calcFrobeniusCoefficients( - Fp: mod.IField, - nonResidue: T, - modulus: bigint, - degree: number, - num: number = 1, - divisor?: number, -) { - const _divisor = BigInt(divisor === undefined ? degree : divisor) - const towerModulus: any = modulus ** BigInt(degree) - const res: T[][] = [] - for (let i = 0; i < num; i++) { - const a = BigInt(i + 1) - const powers: T[] = [] - for (let j = 0, qPower = _1n; j < degree; j++) { - const power = ((a * qPower - a) / _divisor) % towerModulus - powers.push(Fp.pow(nonResidue, power)) - qPower *= modulus - } - res.push(powers) - } - return res -} - -// This works same at least for bls12-381, bn254 and bls12-377 -export function psiFrobenius( - Fp: mod.IField, - Fp2: Fp2Bls, - base: Fp2, -): { - psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] - psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] - G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType - G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType - PSI_X: Fp2 - PSI_Y: Fp2 - PSI2_X: Fp2 - PSI2_Y: Fp2 -} { - // Ψ endomorphism - const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) - const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) - function psi(x: Fp2, y: Fp2): [Fp2, Fp2] { - // This x10 faster than previous version in bls12-381 - const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) - const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) - return [x2, y2] - } - // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) - const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) - // This equals -1, which causes y to be Fp2.neg(y). - // But not sure if there are case when this is not true? - const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) - if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') - function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] { - return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] - } - // Map points - const mapAffine = - (fn: (x: T, y: T) => [T, T]) => - (c: ProjConstructor, P: ProjPointType) => { - const affine = P.toAffine() - const p = fn(affine.x, affine.y) - return c.fromAffine({ x: p[0], y: p[1] }) - } - const G2psi = mapAffine(psi) - const G2psi2 = mapAffine(psi2) - return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } -} - -export type Tower12Opts = { - ORDER: bigint - NONRESIDUE?: Fp - // Fp2 - FP2_NONRESIDUE: BigintTuple - Fp2sqrt?: (num: Fp2) => Fp2 - Fp2mulByB: (num: Fp2) => Fp2 - // Fp12 - Fp12cyclotomicSquare: (num: Fp12) => Fp12 - Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 - Fp12finalExponentiate: (num: Fp12) => Fp12 -} - -export function tower12(opts: Tower12Opts): { - Fp: Readonly & Required, 'isOdd'>>> - Fp2: mod.IField & { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { re: bigint; im: bigint } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - Fp6: mod.IField & { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 } - Fp12: mod.IField & { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } -} { - const { ORDER } = opts - // Fp - const Fp = mod.Field(ORDER) - const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) - const FpLegendre = mod.FpLegendre(ORDER) - const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 - - // Fp2 - const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] - const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ - c0: Fp.add(c0, r0), - c1: Fp.add(c1, r1), - }) - const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ - c0: Fp.sub(c0, r0), - c1: Fp.sub(c1, r1), - }) - const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => { - if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } - // (a+bi)(c+di) = (ac−bd) + (ad+bc)i - const { c0: r0, c1: r1 } = rhs - let t1 = Fp.mul(c0, r0) // c0 * o0 - let t2 = Fp.mul(c1, r1) // c1 * o1 - // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i - const o0 = Fp.sub(t1, t2) - const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) - return { c0: o0, c1: o1 } - } - const Fp2Square = ({ c0, c1 }: Fp2) => { - const a = Fp.add(c0, c1) - const b = Fp.sub(c0, c1) - const c = Fp.add(c0, c0) - return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } - } - type Fp2Utils = { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { re: bigint; im: bigint } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => { - if (tuple.length !== 2) throw new Error('invalid tuple') - const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp] - return { c0: fps[0], c1: fps[1] } - } - - const FP2_ORDER = ORDER * ORDER - const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) - const Fp2: mod.IField & Fp2Utils = { - ORDER: FP2_ORDER, - isLE: Fp.isLE, - NONRESIDUE: Fp2Nonresidue, - BITS: bitLen(FP2_ORDER), - BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), - MASK: bitMask(bitLen(FP2_ORDER)), - ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, - ONE: { c0: Fp.ONE, c1: Fp.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', - is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), - eql: ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => Fp.eql(c0, r0) && Fp.eql(c1, r1), - neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), - pow: (num, power) => mod.FpPow(Fp2, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), - // Normalized - add: Fp2Add, - sub: Fp2Subtract, - mul: Fp2Multiply, - sqr: Fp2Square, - // NonNormalized stuff - addN: Fp2Add, - subN: Fp2Subtract, - mulN: Fp2Multiply, - sqrN: Fp2Square, - // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? - div: (lhs, rhs) => - Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), - inv: ({ c0: a, c1: b }) => { - // We wish to find the multiplicative inverse of a nonzero - // element a + bu in Fp2. We leverage an identity - // - // (a + bu)(a - bu) = a² + b² - // - // which holds because u² = -1. This can be rewritten as - // - // (a + bu)(a - bu)/(a² + b²) = 1 - // - // because a² + b² = 0 has no nonzero solutions for (a, b). - // This gives that (a - bu)/(a² + b²) is the inverse - // of (a + bu). Importantly, this can be computing using - // only a single inversion in Fp. - const factor = Fp.inv(Fp.create(a * a + b * b)) - return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } - }, - sqrt: (num) => { - if (opts.Fp2sqrt) return opts.Fp2sqrt(num) - // This is generic for all quadratic extensions (Fp2) - const { c0, c1 } = num - if (Fp.is0(c1)) { - // if c0 is quadratic residue - if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) - else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) - } - const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) - let d = Fp.mul(Fp.add(a, c0), Fpdiv2) - const legendre = FpLegendre(Fp, d) - // -1, Quadratic non residue - if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) - const a0 = Fp.sqrt(d) - const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) - if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') - // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num - const x1 = candidateSqrt - const x2 = Fp2.neg(x1) - const { re: re1, im: im1 } = Fp2.reim(x1) - const { re: re2, im: im2 } = Fp2.reim(x2) - if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 - return x2 - }, - // Same as sgn0_m_eq_2 in RFC 9380 - isOdd: (x: Fp2) => { - const { re: x0, im: x1 } = Fp2.reim(x) - const sign_0 = x0 % _2n - const zero_0 = x0 === _0n - const sign_1 = x1 % _2n - return BigInt(sign_0 || (zero_0 && sign_1)) == _1n - }, - // Bytes util - fromBytes(b: Uint8Array): Fp2 { - if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } - }, - toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp.cmov(c0, r0, c), - c1: Fp.cmov(c1, r1, c), - }), - reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), - // multiply by u + 1 - mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), - mulByB: opts.Fp2mulByB, - fromBigTuple: Fp2fromBigTuple, - frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({ - c0, - c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), - }), - } - // Fp6 - const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ - c0: Fp2.add(c0, r0), - c1: Fp2.add(c1, r1), - c2: Fp2.add(c2, r2), - }) - const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ - c0: Fp2.sub(c0, r0), - c1: Fp2.sub(c1, r1), - c2: Fp2.sub(c2, r2), - }) - const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => { - if (typeof rhs === 'bigint') { - return { - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - } - } - const { c0: r0, c1: r1, c2: r2 } = rhs - const t0 = Fp2.mul(c0, r0) // c0 * o0 - const t1 = Fp2.mul(c1, r1) // c1 * o1 - const t2 = Fp2.mul(c2, r2) // c2 * o2 - return { - // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) - c0: Fp2.add( - t0, - Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), - ), - // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) - c1: Fp2.add( - Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), - Fp2.mulByNonresidue(t2), - ), - // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 - c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), - } - } - const Fp6Square = ({ c0, c1, c2 }: Fp6) => { - let t0 = Fp2.sqr(c0) // c0² - let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 - let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 - let t4 = Fp2.sqr(c2) // c2² - return { - c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 - c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 - // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 - c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), - } - } - type Fp6Utils = { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - - const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 6, - 2, - 3, - ) - - const Fp6: mod.IField & Fp6Utils = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp2.isLE, - BITS: 3 * Fp2.BITS, - BYTES: 3 * Fp2.BYTES, - MASK: bitMask(3 * Fp2.BITS), - ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, - ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, - create: (num) => num, - isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), - is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), - neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), - eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => - Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), - sqrt: notImplemented, - // Do we need division by bigint at all? Should be done via order: - div: (lhs, rhs) => - Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp6, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), - // Normalized - add: Fp6Add, - sub: Fp6Subtract, - mul: Fp6Multiply, - sqr: Fp6Square, - // NonNormalized stuff - addN: Fp6Add, - subN: Fp6Subtract, - mulN: Fp6Multiply, - sqrN: Fp6Square, - - inv: ({ c0, c1, c2 }) => { - let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) - let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 - let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 - // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) - let t4 = Fp2.inv( - Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), - ) - return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } - }, - // Bytes utils - fromBytes: (b: Uint8Array): Fp6 => { - if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), - c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), - c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), - } - }, - toBytes: ({ c0, c1, c2 }): Uint8Array => - concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), - cmov: ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6, c) => ({ - c0: Fp2.cmov(c0, r0, c), - c1: Fp2.cmov(c1, r1, c), - c2: Fp2.cmov(c2, r2, c), - }), - fromBigSix: (t: BigintSix): Fp6 => { - if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') - return { - c0: Fp2.fromBigTuple(t.slice(0, 2)), - c1: Fp2.fromBigTuple(t.slice(2, 4)), - c2: Fp2.fromBigTuple(t.slice(4, 6)), - } - }, - frobeniusMap: ({ c0, c1, c2 }, power: number) => ({ - c0: Fp2.frobeniusMap(c0, power), - c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), - c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), - }), - mulByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({ - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - }), - mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), - // Sparse multiplication - mul1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({ - c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), - c1: Fp2.mul(c0, b1), - c2: Fp2.mul(c1, b1), - }), - // Sparse multiplication - mul01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 { - let t0 = Fp2.mul(c0, b0) // c0 * b0 - let t1 = Fp2.mul(c1, b1) // c1 * b1 - return { - // ((c1 + c2) * b1 - T1) * (u + 1) + T0 - c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), - // (b0 + b1) * (c0 + c1) - T0 - T1 - c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), - // (c0 + c2) * b0 - T0 + T1 - c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), - } - }, - } - - // Fp12 - const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 12, - 1, - 6, - )[0] - - const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ - c0: Fp6.add(c0, r0), - c1: Fp6.add(c1, r1), - }) - const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ - c0: Fp6.sub(c0, r0), - c1: Fp6.sub(c1, r1), - }) - const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => { - if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } - let { c0: r0, c1: r1 } = rhs - let t1 = Fp6.mul(c0, r0) // c0 * r0 - let t2 = Fp6.mul(c1, r1) // c1 * r1 - return { - c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v - // (c0 + c1) * (r0 + r1) - (T1 + T2) - c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), - } - } - const Fp12Square = ({ c0, c1 }: Fp12) => { - let ab = Fp6.mul(c0, c1) // c0 * c1 - return { - // (c1 * v + c0) * (c0 + c1) - AB - AB * v - c0: Fp6.sub( - Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), - Fp6.mulByNonresidue(ab), - ), - c1: Fp6.add(ab, ab), - } // AB + AB - } - function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } { - const a2 = Fp2.sqr(a) - const b2 = Fp2.sqr(b) - return { - first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² - second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² - } - } - type Fp12Utils = { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } - - const Fp12: mod.IField & Fp12Utils = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp6.isLE, - BITS: 2 * Fp2.BITS, - BYTES: 2 * Fp2.BYTES, - MASK: bitMask(2 * Fp2.BITS), - ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, - ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), - is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), - neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), - sqrt: notImplemented, - inv: ({ c0, c1 }) => { - let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) - return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w - }, - div: (lhs, rhs) => - Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp12, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), - // Normalized - add: Fp12Add, - sub: Fp12Subtract, - mul: Fp12Multiply, - sqr: Fp12Square, - // NonNormalized stuff - addN: Fp12Add, - subN: Fp12Subtract, - mulN: Fp12Multiply, - sqrN: Fp12Square, - - // Bytes utils - fromBytes: (b: Uint8Array): Fp12 => { - if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), - c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), - } - }, - toBytes: ({ c0, c1 }): Uint8Array => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp6.cmov(c0, r0, c), - c1: Fp6.cmov(c1, r1, c), - }), - // Utils - // toString() { - // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); - // }, - // fromTuple(c: [Fp6, Fp6]) { - // return new Fp12(...c); - // } - fromBigTwelve: (t: BigintTwelve): Fp12 => ({ - c0: Fp6.fromBigSix(t.slice(0, 6) as BigintSix), - c1: Fp6.fromBigSix(t.slice(6, 12) as BigintSix), - }), - // Raises to q**i -th power - frobeniusMap(lhs, power: number) { - const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) - const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] - return { - c0: Fp6.frobeniusMap(lhs.c0, power), - c1: Fp6.create({ - c0: Fp2.mul(c0, coeff), - c1: Fp2.mul(c1, coeff), - c2: Fp2.mul(c2, coeff), - }), - } - }, - mulByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({ - c0: Fp6.mulByFp2(c0, rhs), - c1: Fp6.mulByFp2(c1, rhs), - }), - conjugate: ({ c0, c1 }): Fp12 => ({ c0, c1: Fp6.neg(c1) }), - // Sparse multiplication - mul014: ({ c0, c1 }, o0: Fp2, o1: Fp2, o4: Fp2) => { - let t0 = Fp6.mul01(c0, o0, o1) - let t1 = Fp6.mul1(c1, o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 - // (c1 + c0) * [o0, o1+o4] - T0 - T1 - c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), - } - }, - mul034: ({ c0, c1 }, o0: Fp2, o3: Fp2, o4: Fp2) => { - const a = Fp6.create({ - c0: Fp2.mul(c0.c0, o0), - c1: Fp2.mul(c0.c1, o0), - c2: Fp2.mul(c0.c2, o0), - }) - const b = Fp6.mul01(c1, o3, o4) - const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(b), a), - c1: Fp6.sub(e, Fp6.add(a, b)), - } - }, - - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - _cyclotomicSquare: opts.Fp12cyclotomicSquare, - _cyclotomicExp: opts.Fp12cyclotomicExp, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - finalExponentiate: opts.Fp12finalExponentiate, - } - - return { Fp, Fp2, Fp6, Fp4Square, Fp12 } -} diff --git a/packages/noble-curves/src/abstract/utils.ts b/packages/noble-curves/src/abstract/utils.ts deleted file mode 100644 index 0ace81e2696..00000000000 --- a/packages/noble-curves/src/abstract/utils.ts +++ /dev/null @@ -1,367 +0,0 @@ -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ - -// 100 lines of code in the file are duplicated from noble-hashes (utils). -// This is OK: `abstract` directory does not use noble-hashes. -// User may opt-in into using different hashing library. This way, noble-hashes -// won't be included into their bundle. -const _0n = /* @__PURE__ */ BigInt(0) -const _1n = /* @__PURE__ */ BigInt(1) -const _2n = /* @__PURE__ */ BigInt(2) -export type Hex = Uint8Array | string // hex strings are accepted for simplicity -export type PrivKey = Hex | bigint // bigints are accepted to ease learning curve -export type CHash = { - (message: Uint8Array | string): Uint8Array - blockLen: number - outputLen: number - create(opts?: { dkLen?: number }): any // For shake -} -export type FHash = (message: Uint8Array | string) => Uint8Array - -export function isBytes(a: unknown): a is Uint8Array { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') -} - -export function abytes(item: unknown): void { - if (!isBytes(item)) throw new Error('Uint8Array expected') -} - -export function abool(title: string, value: boolean): void { - if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) -} - -// Array where index 0xf0 (240) is mapped to string 'f0' -const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) -/** - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -export function bytesToHex(bytes: Uint8Array): string { - abytes(bytes) - // pre-caching improves the speed 6x - let hex = '' - for (let i = 0; i < bytes.length; i++) { - hex += hexes[bytes[i]] - } - return hex -} - -export function numberToHexUnpadded(num: number | bigint): string { - const hex = num.toString(16) - return hex.length & 1 ? '0' + hex : hex -} - -export function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian -} - -// We use optimized technique to convert hex string to byte array -const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const -function asciiToBase16(ch: number): number | undefined { - if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 - if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) - if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) - return -} - -/** - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -export function hexToBytes(hex: string): Uint8Array { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - const hl = hex.length - const al = hl / 2 - if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) - const array = new Uint8Array(al) - for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { - const n1 = asciiToBase16(hex.charCodeAt(hi)) - const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) - if (n1 === undefined || n2 === undefined) { - const char = hex[hi] + hex[hi + 1] - throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) - } - array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 - } - return array -} - -// BE: Big Endian, LE: Little Endian -export function bytesToNumberBE(bytes: Uint8Array): bigint { - return hexToNumber(bytesToHex(bytes)) -} -export function bytesToNumberLE(bytes: Uint8Array): bigint { - abytes(bytes) - return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) -} - -export function numberToBytesBE(n: number | bigint, len: number): Uint8Array { - return hexToBytes(n.toString(16).padStart(len * 2, '0')) -} -export function numberToBytesLE(n: number | bigint, len: number): Uint8Array { - return numberToBytesBE(n, len).reverse() -} -// Unpadded, rarely used -export function numberToVarBytesBE(n: number | bigint): Uint8Array { - return hexToBytes(numberToHexUnpadded(n)) -} - -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array { - let res: Uint8Array - if (typeof hex === 'string') { - try { - res = hexToBytes(hex) - } catch (e) { - throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) - } - } else if (isBytes(hex)) { - // Uint8Array.from() instead of hash.slice() because node.js Buffer - // is instance of Uint8Array, and its slice() creates **mutable** copy - res = Uint8Array.from(hex) - } else { - throw new Error(title + ' must be hex string or Uint8Array') - } - const len = res.length - if (typeof expectedLength === 'number' && len !== expectedLength) - throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) - return res -} - -/** - * Copies several Uint8Arrays into one. - */ -export function concatBytes(...arrays: Uint8Array[]): Uint8Array { - let sum = 0 - for (let i = 0; i < arrays.length; i++) { - const a = arrays[i] - abytes(a) - sum += a.length - } - const res = new Uint8Array(sum) - for (let i = 0, pad = 0; i < arrays.length; i++) { - const a = arrays[i] - res.set(a, pad) - pad += a.length - } - return res -} - -// Compares 2 u8a-s in kinda constant time -export function equalBytes(a: Uint8Array, b: Uint8Array): boolean { - if (a.length !== b.length) return false - let diff = 0 - for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] - return diff === 0 -} - -// Global symbols in both browsers and Node.js since v11 -// See https://github.com/microsoft/TypeScript/issues/31535 -declare const TextEncoder: any - -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -export function utf8ToBytes(str: string): Uint8Array { - if (typeof str !== 'string') throw new Error('string expected') - return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 -} - -// Is positive bigint -const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n - -export function inRange(n: bigint, min: bigint, max: bigint): boolean { - return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max -} - -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void { - // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? - // consider P=256n, min=0n, max=P - // - a for min=0 would require -1: `inRange('x', x, -1n, P)` - // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` - // - our way is the cleanest: `inRange('x', x, 0n, P) - if (!inRange(n, min, max)) - throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) -} - -// Bit operations - -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -export function bitLen(n: bigint): number { - let len - for (len = 0; n > _0n; n >>= _1n, len += 1); - return len -} - -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -export function bitGet(n: bigint, pos: number): bigint { - return (n >> BigInt(pos)) & _1n -} - -/** - * Sets single bit at position. - */ -export function bitSet(n: bigint, pos: number, value: boolean): bigint { - return n | ((value ? _1n : _0n) << BigInt(pos)) -} - -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -export const bitMask = (n: number): bigint => (_2n << BigInt(n - 1)) - _1n - -// DRBG - -const u8n = (data?: any) => new Uint8Array(data) // creates Uint8Array -const u8fr = (arr: any) => Uint8Array.from(arr) // another shortcut -type Pred = (v: Uint8Array) => T | undefined -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -export function createHmacDrbg( - hashLen: number, - qByteLen: number, - hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, -): (seed: Uint8Array, predicate: Pred) => T { - if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') - if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') - if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') - // Step B, Step C: set hashLen to 8*ceil(hlen/8) - let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same - let i = 0 // Iterations counter, will throw when over 1000 - const reset = () => { - v.fill(1) - k.fill(0) - i = 0 - } - const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) - const reseed = (seed = u8n()) => { - // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) - v = h() // v = hmac(k || v) - if (seed.length === 0) return - k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) - v = h() // v = hmac(k || v) - } - const gen = () => { - // HMAC-DRBG generate() function - if (i++ >= 1000) throw new Error('drbg: tried 1000 values') - let len = 0 - const out: Uint8Array[] = [] - while (len < qByteLen) { - v = h() - const sl = v.slice() - out.push(sl) - len += v.length - } - return concatBytes(...out) - } - const genUntil = (seed: Uint8Array, pred: Pred): T => { - reset() - reseed(seed) // Steps D-G - let res: T | undefined = undefined // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed() - reset() - return res - } - return genUntil -} - -// Validating curves and fields - -const validatorFns = { - bigint: (val: any): boolean => typeof val === 'bigint', - function: (val: any): boolean => typeof val === 'function', - boolean: (val: any): boolean => typeof val === 'boolean', - string: (val: any): boolean => typeof val === 'string', - stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val), - isSafeInteger: (val: any): boolean => Number.isSafeInteger(val), - array: (val: any): boolean => Array.isArray(val), - field: (val: any, object: any): any => (object as any).Fp.isValid(val), - hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen), -} as const -type Validator = keyof typeof validatorFns -type ValMap> = { [K in keyof T]?: Validator } -// type Record = { [P in K]: T; } - -export function validateObject>( - object: T, - validators: ValMap, - optValidators: ValMap = {}, -): T { - const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => { - const checkVal = validatorFns[type] - if (typeof checkVal !== 'function') throw new Error('invalid validator function') - - const val = object[fieldName as keyof typeof object] - if (isOptional && val === undefined) return - if (!checkVal(val, object)) { - throw new Error( - 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, - ) - } - } - for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false) - for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true) - return object -} -// validate type tests -// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; -// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! -// // Should fail type-check -// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); -// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); -// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); -// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); - -/** - * throws not implemented error - */ -export const notImplemented = (): never => { - throw new Error('not implemented') -} - -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -export function memoized( - fn: (arg: T, ...args: O) => R, -): (arg: T, ...args: O) => R { - const map = new WeakMap() - return (arg: T, ...args: O): R => { - const val = map.get(arg) - if (val !== undefined) return val - const computed = fn(arg, ...args) - map.set(arg, computed) - return computed - } -} diff --git a/packages/noble-curves/src/abstract/weierstrass.ts b/packages/noble-curves/src/abstract/weierstrass.ts deleted file mode 100644 index 2b6d25fa3b8..00000000000 --- a/packages/noble-curves/src/abstract/weierstrass.ts +++ /dev/null @@ -1,1383 +0,0 @@ -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - type AffinePoint, - type BasicCurve, - type Group, - type GroupConstructor, - pippenger, - validateBasic, - wNAF, -} from './curve.js' -import { - Field, - type IField, - getMinHashLength, - invert, - mapHashToField, - mod, - validateField, -} from './modular.js' -import * as ut from './utils.js' -import { type CHash, type Hex, type PrivKey, abool, ensureBytes, memoized } from './utils.js' - -export type { AffinePoint } -type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array -type EndomorphismOpts = { - beta: bigint - splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint } -} -export type BasicWCurve = BasicCurve & { - // Params: a, b - a: T - b: T - - // Optional params - allowedPrivateKeyLengths?: readonly number[] // for P521 - wrapPrivateKey?: boolean // bls12-381 requires mod(n) instead of rejecting keys >= n - endo?: EndomorphismOpts // Endomorphism options for Koblitz curves - // When a cofactor != 1, there can be an effective methods to: - // 1. Determine whether a point is torsion-free - isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean - // 2. Clear torsion component - clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType -} - -type Entropy = Hex | boolean -export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean } -export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined } - -function validateSigVerOpts(opts: SignOpts | VerOpts) { - if (opts.lowS !== undefined) abool('lowS', opts.lowS) - if (opts.prehash !== undefined) abool('prehash', opts.prehash) -} - -// Instance for 3d XYZ points -export interface ProjPointType extends Group> { - readonly px: T - readonly py: T - readonly pz: T - get x(): T - get y(): T - multiply(scalar: bigint): ProjPointType - toAffine(iz?: T): AffinePoint - isTorsionFree(): boolean - clearCofactor(): ProjPointType - assertValidity(): void - hasEvenY(): boolean - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - - multiplyUnsafe(scalar: bigint): ProjPointType - multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined - _setWindowSize(windowSize: number): void -} -// Static methods for 3d XYZ points -export interface ProjConstructor extends GroupConstructor> { - new (x: T, y: T, z: T): ProjPointType - fromAffine(p: AffinePoint): ProjPointType - fromHex(hex: Hex): ProjPointType - fromPrivateKey(privateKey: PrivKey): ProjPointType - normalizeZ(points: ProjPointType[]): ProjPointType[] - msm(points: ProjPointType[], scalars: bigint[]): ProjPointType -} - -export type CurvePointsType = BasicWCurve & { - // Bytes - fromBytes?: (bytes: Uint8Array) => AffinePoint - toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array -} - -export type CurvePointsTypeWithLength = Readonly< - CurvePointsType & { nByteLength: number; nBitLength: number } -> - -function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength { - const opts = validateBasic(curve) - ut.validateObject( - opts, - { - a: 'field', - b: 'field', - }, - { - allowedPrivateKeyLengths: 'array', - wrapPrivateKey: 'boolean', - isTorsionFree: 'function', - clearCofactor: 'function', - allowInfinityPoint: 'boolean', - fromBytes: 'function', - toBytes: 'function', - }, - ) - const { endo, Fp, a } = opts - if (endo) { - if (!Fp.eql(a, Fp.ZERO)) { - throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') - } - if ( - typeof endo !== 'object' || - typeof endo.beta !== 'bigint' || - typeof endo.splitScalar !== 'function' - ) { - throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') - } - } - return Object.freeze({ ...opts } as const) -} - -export type CurvePointsRes = { - CURVE: ReturnType> - ProjectivePoint: ProjConstructor - normPrivateKeyToScalar: (key: PrivKey) => bigint - weierstrassEquation: (x: T) => T - isWithinCurveOrder: (num: bigint) => boolean -} - -const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut - -export class DERErr extends Error { - constructor(m = '') { - super(m) - } -} -export type IDER = { - // asn.1 DER encoding utils - Err: typeof DERErr - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag: number, data: string) => string - // v - value, l - left bytes (unparsed) - decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } - } - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num: bigint): string - decode(data: Uint8Array): bigint - } - toSig(hex: string | Uint8Array): { r: bigint; s: bigint } - hexFromSig(sig: { r: bigint; s: bigint }): string -} -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -export const DER: IDER = { - // asn.1 DER encoding utils - Err: DERErr, - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag: number, data: string): string => { - const { Err: E } = DER - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length & 1) throw new E('tlv.encode: unpadded data') - const dataLen = data.length / 2 - const len = ut.numberToHexUnpadded(dataLen) - if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big') - // length of length with long form flag - const lenLen = dataLen > 127 ? ut.numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '' - const t = ut.numberToHexUnpadded(tag) - return t + lenLen + len + data - }, - // v - value, l - left bytes (unparsed) - decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } { - const { Err: E } = DER - let pos = 0 - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') - const first = data[pos++] - const isLong = !!(first & 0b1000_0000) // First bit of first length byte is flag for short/long form - let length = 0 - if (!isLong) length = first - else { - // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] - const lenLen = first & 0b0111_1111 - if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') - if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js - const lengthBytes = data.subarray(pos, pos + lenLen) - if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') - if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') - for (const b of lengthBytes) length = (length << 8) | b - pos += lenLen - if (length < 128) throw new E('tlv.decode(long): not minimal encoding') - } - const v = data.subarray(pos, pos + length) - if (v.length !== length) throw new E('tlv.decode: wrong value length') - return { v, l: data.subarray(pos + length) } - }, - }, - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num: bigint): string { - const { Err: E } = DER - if (num < _0n) throw new E('integer: negative integers are not allowed') - let hex = ut.numberToHexUnpadded(num) - // Pad with zero byte if negative flag is present - if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex - if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') - return hex - }, - decode(data: Uint8Array): bigint { - const { Err: E } = DER - if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative') - if (data[0] === 0x00 && !(data[1] & 0b1000_0000)) - throw new E('invalid signature integer: unnecessary leading zero') - return b2n(data) - }, - }, - toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { - // parse DER signature - const { Err: E, _int: int, _tlv: tlv } = DER - const data = typeof hex === 'string' ? h2b(hex) : hex - ut.abytes(data) - const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) - if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) - const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) - if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - return { r: int.decode(rBytes), s: int.decode(sBytes) } - }, - hexFromSig(sig: { r: bigint; s: bigint }): string { - const { _tlv: tlv, _int: int } = DER - const rs = tlv.encode(0x02, int.encode(sig.r)) - const ss = tlv.encode(0x02, int.encode(sig.s)) - const seq = rs + ss - return tlv.encode(0x30, seq) - }, -} - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) - -export function weierstrassPoints(opts: CurvePointsType): CurvePointsRes { - const CURVE = validatePointOpts(opts) - const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ - const Fn = Field(CURVE.n, CURVE.nBitLength) - - const toBytes = - CURVE.toBytes || - ((_c: ProjConstructor, point: ProjPointType, _isCompressed: boolean) => { - const a = point.toAffine() - return ut.concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) - }) - const fromBytes = - CURVE.fromBytes || - ((bytes: Uint8Array) => { - // const head = bytes[0]; - const tail = bytes.subarray(1) - // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - }) - - /** - * y² = x³ + ax + b: Short weierstrass curve formula - * @returns y² - */ - function weierstrassEquation(x: T): T { - const { a, b } = CURVE - const x2 = Fp.sqr(x) // x * x - const x3 = Fp.mul(x2, x) // x2 * x - return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b - } - // Validate whether the passed curve params are valid. - // We check if curve equation works for generator point. - // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. - // ProjectivePoint class has not been initialized yet. - if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) - throw new Error('bad generator point: equation left != right') - - // Valid group elements reside in range 1..n-1 - function isWithinCurveOrder(num: bigint): boolean { - return ut.inRange(num, _1n, CURVE.n) - } - // Validates if priv key is valid and converts it to bigint. - // Supports options allowedPrivateKeyLengths and wrapPrivateKey. - function normPrivateKeyToScalar(key: PrivKey): bigint { - const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE - if (lengths && typeof key !== 'bigint') { - if (ut.isBytes(key)) key = ut.bytesToHex(key) - // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes - if (typeof key !== 'string' || !lengths.includes(key.length)) - throw new Error('invalid private key') - key = key.padStart(nByteLength * 2, '0') - } - let num: bigint - try { - num = - typeof key === 'bigint' - ? key - : ut.bytesToNumberBE(ensureBytes('private key', key, nByteLength)) - } catch (error) { - throw new Error( - 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, - ) - } - if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS - ut.aInRange('private key', num, _1n, N) // num in range [1..N-1] - return num - } - - function assertPrjPoint(other: unknown) { - if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') - } - - // Memoized toAffine / validity check. They are heavy. Points are immutable. - - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint => { - const { px: x, py: y, pz: z } = p - // Fast-path for normalized points - if (Fp.eql(z, Fp.ONE)) return { x, y } - const is0 = p.is0() - // If invZ was 0, we return zero point. However we still want to execute - // all operations, so we replace invZ with a random number, 1. - if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) - const ax = Fp.mul(x, iz) - const ay = Fp.mul(y, iz) - const zz = Fp.mul(z, iz) - if (is0) return { x: Fp.ZERO, y: Fp.ZERO } - if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - // NOTE: on exception this will crash 'cached' and no value will be set. - // Otherwise true will be return - const assertValidMemo = memoized((p: Point) => { - if (p.is0()) { - // (0, 1, 0) aka ZERO is invalid in most contexts. - // In BLS, ZERO can be serialized, so we allow it. - // (0, 0, 0) is invalid representation of ZERO. - if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return - throw new Error('bad point: ZERO') - } - // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` - const { x, y } = p.toAffine() - // Check if x, y are valid field elements - if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') - const left = Fp.sqr(y) // y² - const right = weierstrassEquation(x) // x³ + ax + b - if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') - if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') - return true - }) - - /** - * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) - * Default Point works in 2d / affine coordinates: (x, y) - * We're doing calculations in projective, because its operations don't require costly inversion. - */ - class Point implements ProjPointType { - static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) - static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) - - constructor( - readonly px: T, - readonly py: T, - readonly pz: T, - ) { - if (px == null || !Fp.isValid(px)) throw new Error('x required') - if (py == null || !Fp.isValid(py)) throw new Error('y required') - if (pz == null || !Fp.isValid(pz)) throw new Error('z required') - Object.freeze(this) - } - - // Does not validate if the point is on-curve. - // Use fromHex instead, or call assertValidity() later. - static fromAffine(p: AffinePoint): Point { - const { x, y } = p || {} - if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') - if (p instanceof Point) throw new Error('projective point not allowed') - const is0 = (i: T) => Fp.eql(i, Fp.ZERO) - // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) - if (is0(x) && is0(y)) return Point.ZERO - return new Point(x, y, Fp.ONE) - } - - get x(): T { - return this.toAffine().x - } - get y(): T { - return this.toAffine().y - } - - /** - * Takes a bunch of Projective Points but executes only one - * inversion on all of them. Inversion is very slow operation, - * so this improves performance massively. - * Optimization: converts a list of projective points to a list of identical points with Z=1. - */ - static normalizeZ(points: Point[]): Point[] { - const toInv = Fp.invertBatch(points.map((p) => p.pz)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - - /** - * Converts hash string or Uint8Array to Point. - * @param hex short/long ECDSA hex - */ - static fromHex(hex: Hex): Point { - const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) - P.assertValidity() - return P - } - - // Multiplies generator point by privateKey. - static fromPrivateKey(privateKey: PrivKey) { - return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) - } - - // Multiscalar Multiplication - static msm(points: Point[], scalars: bigint[]): Point { - return pippenger(Point, Fn, points, scalars) - } - - // "Private method", don't use it directly - _setWindowSize(windowSize: number) { - wnaf.setWindowSize(this, windowSize) - } - - // A point on curve is valid if it conforms to equation. - assertValidity(): void { - assertValidMemo(this) - } - - hasEvenY(): boolean { - const { y } = this.toAffine() - if (Fp.isOdd) return !Fp.isOdd(y) - throw new Error("Field doesn't support isOdd") - } - - /** - * Compare one point to another. - */ - equals(other: Point): boolean { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) - const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) - return U1 && U2 - } - - /** - * Flips point to one corresponding to (x, -y) in Affine coordinates. - */ - negate(): Point { - return new Point(this.px, Fp.neg(this.py), this.pz) - } - - // Renes-Costello-Batina exception-free doubling formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 3 - // Cost: 8M + 3S + 3*a + 2*b3 + 15add. - double() { - const { a, b } = CURVE - const b3 = Fp.mul(b, _3n) - const { px: X1, py: Y1, pz: Z1 } = this - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - let t0 = Fp.mul(X1, X1) // step 1 - let t1 = Fp.mul(Y1, Y1) - let t2 = Fp.mul(Z1, Z1) - let t3 = Fp.mul(X1, Y1) - t3 = Fp.add(t3, t3) // step 5 - Z3 = Fp.mul(X1, Z1) - Z3 = Fp.add(Z3, Z3) - X3 = Fp.mul(a, Z3) - Y3 = Fp.mul(b3, t2) - Y3 = Fp.add(X3, Y3) // step 10 - X3 = Fp.sub(t1, Y3) - Y3 = Fp.add(t1, Y3) - Y3 = Fp.mul(X3, Y3) - X3 = Fp.mul(t3, X3) - Z3 = Fp.mul(b3, Z3) // step 15 - t2 = Fp.mul(a, t2) - t3 = Fp.sub(t0, t2) - t3 = Fp.mul(a, t3) - t3 = Fp.add(t3, Z3) - Z3 = Fp.add(t0, t0) // step 20 - t0 = Fp.add(Z3, t0) - t0 = Fp.add(t0, t2) - t0 = Fp.mul(t0, t3) - Y3 = Fp.add(Y3, t0) - t2 = Fp.mul(Y1, Z1) // step 25 - t2 = Fp.add(t2, t2) - t0 = Fp.mul(t2, t3) - X3 = Fp.sub(X3, t0) - Z3 = Fp.mul(t2, t1) - Z3 = Fp.add(Z3, Z3) // step 30 - Z3 = Fp.add(Z3, Z3) - return new Point(X3, Y3, Z3) - } - - // Renes-Costello-Batina exception-free addition formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 1 - // Cost: 12M + 0S + 3*a + 3*b3 + 23add. - add(other: Point): Point { - assertPrjPoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - const a = CURVE.a - const b3 = Fp.mul(CURVE.b, _3n) - let t0 = Fp.mul(X1, X2) // step 1 - let t1 = Fp.mul(Y1, Y2) - let t2 = Fp.mul(Z1, Z2) - let t3 = Fp.add(X1, Y1) - let t4 = Fp.add(X2, Y2) // step 5 - t3 = Fp.mul(t3, t4) - t4 = Fp.add(t0, t1) - t3 = Fp.sub(t3, t4) - t4 = Fp.add(X1, Z1) - let t5 = Fp.add(X2, Z2) // step 10 - t4 = Fp.mul(t4, t5) - t5 = Fp.add(t0, t2) - t4 = Fp.sub(t4, t5) - t5 = Fp.add(Y1, Z1) - X3 = Fp.add(Y2, Z2) // step 15 - t5 = Fp.mul(t5, X3) - X3 = Fp.add(t1, t2) - t5 = Fp.sub(t5, X3) - Z3 = Fp.mul(a, t4) - X3 = Fp.mul(b3, t2) // step 20 - Z3 = Fp.add(X3, Z3) - X3 = Fp.sub(t1, Z3) - Z3 = Fp.add(t1, Z3) - Y3 = Fp.mul(X3, Z3) - t1 = Fp.add(t0, t0) // step 25 - t1 = Fp.add(t1, t0) - t2 = Fp.mul(a, t2) - t4 = Fp.mul(b3, t4) - t1 = Fp.add(t1, t2) - t2 = Fp.sub(t0, t2) // step 30 - t2 = Fp.mul(a, t2) - t4 = Fp.add(t4, t2) - t0 = Fp.mul(t1, t4) - Y3 = Fp.add(Y3, t0) - t0 = Fp.mul(t5, t4) // step 35 - X3 = Fp.mul(t3, X3) - X3 = Fp.sub(X3, t0) - t0 = Fp.mul(t3, t1) - Z3 = Fp.mul(t5, Z3) - Z3 = Fp.add(Z3, t0) // step 40 - return new Point(X3, Y3, Z3) - } - - subtract(other: Point) { - return this.add(other.negate()) - } - - is0() { - return this.equals(Point.ZERO) - } - private wNAF(n: bigint): { p: Point; f: Point } { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - - /** - * Non-constant-time multiplication. Uses double-and-add algorithm. - * It's faster, but should only be used when you don't care about - * an exposed private key e.g. sig verification, which works over *public* keys. - */ - multiplyUnsafe(sc: bigint): Point { - const { endo, n: N } = CURVE - ut.aInRange('scalar', sc, _0n, N) - const I = Point.ZERO - if (sc === _0n) return I - if (this.is0() || sc === _1n) return this - - // Case a: no endomorphism. Case b: has precomputes. - if (!endo || wnaf.hasPrecomputes(this)) - return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) - - // Case c: endomorphism - let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) - let k1p = I - let k2p = I - let d: Point = this - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) k1p = k1p.add(d) - if (k2 & _1n) k2p = k2p.add(d) - d = d.double() - k1 >>= _1n - k2 >>= _1n - } - if (k1neg) k1p = k1p.negate() - if (k2neg) k2p = k2p.negate() - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - return k1p.add(k2p) - } - - /** - * Constant time multiplication. - * Uses wNAF method. Windowed method may be 10% faster, - * but takes 2x longer to generate and consumes 2x memory. - * Uses precomputes when available. - * Uses endomorphism for Koblitz curves. - * @param scalar by which the point would be multiplied - * @returns New point - */ - multiply(scalar: bigint): Point { - const { endo, n: N } = CURVE - ut.aInRange('scalar', scalar, _1n, N) - let point: Point, fake: Point // Fake point is used to const-time mult - if (endo) { - const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) - let { p: k1p, f: f1p } = this.wNAF(k1) - let { p: k2p, f: f2p } = this.wNAF(k2) - k1p = wnaf.constTimeNegate(k1neg, k1p) - k2p = wnaf.constTimeNegate(k2neg, k2p) - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - point = k1p.add(k2p) - fake = f1p.add(f2p) - } else { - const { p, f } = this.wNAF(scalar) - point = p - fake = f - } - // Normalize `z` for both points, but return only real one - return Point.normalizeZ([point, fake])[0] - } - - /** - * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. - * Not using Strauss-Shamir trick: precomputation tables are faster. - * The trick could be useful if both P and Q are not G (not in our case). - * @returns non-zero affine point - */ - multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { - const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes - const mul = ( - P: Point, - a: bigint, // Select faster multiply() method - ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) - const sum = mul(this, a).add(mul(Q, b)) - return sum.is0() ? undefined : sum - } - - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - toAffine(iz?: T): AffinePoint { - return toAffineMemo(this, iz) - } - isTorsionFree(): boolean { - const { h: cofactor, isTorsionFree } = CURVE - if (cofactor === _1n) return true // No subgroups, always torsion-free - if (isTorsionFree) return isTorsionFree(Point, this) - throw new Error('isTorsionFree() has not been declared for the elliptic curve') - } - clearCofactor(): Point { - const { h: cofactor, clearCofactor } = CURVE - if (cofactor === _1n) return this // Fast-path - if (clearCofactor) return clearCofactor(Point, this) as Point - return this.multiplyUnsafe(CURVE.h) - } - - toRawBytes(isCompressed = true): Uint8Array { - abool('isCompressed', isCompressed) - this.assertValidity() - return toBytes(Point, this, isCompressed) - } - - toHex(isCompressed = true): string { - abool('isCompressed', isCompressed) - return ut.bytesToHex(this.toRawBytes(isCompressed)) - } - } - const _bits = CURVE.nBitLength - const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) - // Validate if generator point is on curve - return { - CURVE, - ProjectivePoint: Point as ProjConstructor, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } -} - -// Instance -export interface SignatureType { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - assertValidity(): void - addRecoveryBit(recovery: number): RecoveredSignatureType - hasHighS(): boolean - normalizeS(): SignatureType - recoverPublicKey(msgHash: Hex): ProjPointType - toCompactRawBytes(): Uint8Array - toCompactHex(): string - // DER-encoded - toDERRawBytes(isCompressed?: boolean): Uint8Array - toDERHex(isCompressed?: boolean): string -} -export type RecoveredSignatureType = SignatureType & { - readonly recovery: number -} -// Static methods -export type SignatureConstructor = { - new (r: bigint, s: bigint): SignatureType - fromCompact(hex: Hex): SignatureType - fromDER(hex: Hex): SignatureType -} -type SignatureLike = { r: bigint; s: bigint } - -export type PubKey = Hex | ProjPointType - -export type CurveType = BasicWCurve & { - hash: CHash // CHash not FHash because we need outputLen for DRBG - hmac: HmacFnSync - randomBytes: (bytesLength?: number) => Uint8Array - lowS?: boolean - bits2int?: (bytes: Uint8Array) => bigint - bits2int_modN?: (bytes: Uint8Array) => bigint -} - -function validateOpts( - curve: CurveType, -): Readonly { - const opts = validateBasic(curve) - ut.validateObject( - opts, - { - hash: 'hash', - hmac: 'function', - randomBytes: 'function', - }, - { - bits2int: 'function', - bits2int_modN: 'function', - lowS: 'boolean', - }, - ) - return Object.freeze({ lowS: true, ...opts } as const) -} - -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array - getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array - sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType - verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean - ProjectivePoint: ProjConstructor - Signature: SignatureConstructor - utils: { - normPrivateKeyToScalar: (key: PrivKey) => bigint - isValidPrivateKey(privateKey: PrivKey): boolean - randomPrivateKey: () => Uint8Array - precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType - } -} - -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -export function weierstrass(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) as ReturnType - const { Fp, n: CURVE_ORDER } = CURVE - const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 - const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 - - function modN(a: bigint) { - return mod(a, CURVE_ORDER) - } - function invN(a: bigint) { - return invert(a, CURVE_ORDER) - } - - const { - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } = weierstrassPoints({ - ...CURVE, - toBytes(_c, point, isCompressed: boolean): Uint8Array { - const a = point.toAffine() - const x = Fp.toBytes(a.x) - const cat = ut.concatBytes - abool('isCompressed', isCompressed) - if (isCompressed) { - return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) - } else { - return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) - } - }, - fromBytes(bytes: Uint8Array) { - const len = bytes.length - const head = bytes[0] - const tail = bytes.subarray(1) - // this.assertValidity() is done inside of fromHex - if (len === compressedLen && (head === 0x02 || head === 0x03)) { - const x = ut.bytesToNumberBE(tail) - if (!ut.inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') - const y2 = weierstrassEquation(x) // y² = x³ + ax + b - let y: bigint - try { - y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 - } catch (sqrtError) { - const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' - throw new Error('Point is not on curve' + suffix) - } - const isYOdd = (y & _1n) === _1n - // ECDSA - const isHeadOdd = (head & 1) === 1 - if (isHeadOdd !== isYOdd) y = Fp.neg(y) - return { x, y } - } else if (len === uncompressedLen && head === 0x04) { - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - } else { - const cl = compressedLen - const ul = uncompressedLen - throw new Error( - 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, - ) - } - }, - }) - const numToNByteStr = (num: bigint): string => - ut.bytesToHex(ut.numberToBytesBE(num, CURVE.nByteLength)) - - function isBiggerThanHalfOrder(number: bigint) { - const HALF = CURVE_ORDER >> _1n - return number > HALF - } - - function normalizeS(s: bigint) { - return isBiggerThanHalfOrder(s) ? modN(-s) : s - } - // slice bytes num - const slcNum = (b: Uint8Array, from: number, to: number) => ut.bytesToNumberBE(b.slice(from, to)) - - /** - * ECDSA signature with its (r, s) properties. Supports DER & compact representations. - */ - class Signature implements SignatureType { - constructor( - readonly r: bigint, - readonly s: bigint, - readonly recovery?: number, - ) { - this.assertValidity() - } - - // pair (bytes of r, bytes of s) - static fromCompact(hex: Hex) { - const l = CURVE.nByteLength - hex = ensureBytes('compactSignature', hex, l * 2) - return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) - } - - // DER encoded ECDSA signature - // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script - static fromDER(hex: Hex) { - const { r, s } = DER.toSig(ensureBytes('DER', hex)) - return new Signature(r, s) - } - - assertValidity(): void { - ut.aInRange('r', this.r, _1n, CURVE_ORDER) // r in [1..N] - ut.aInRange('s', this.s, _1n, CURVE_ORDER) // s in [1..N] - } - - addRecoveryBit(recovery: number): RecoveredSignature { - return new Signature(this.r, this.s, recovery) as RecoveredSignature - } - - recoverPublicKey(msgHash: Hex): typeof Point.BASE { - const { r, s, recovery: rec } = this - const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash - if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') - const radj = rec === 2 || rec === 3 ? r + CURVE.n : r - if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') - const prefix = (rec & 1) === 0 ? '02' : '03' - const R = Point.fromHex(prefix + numToNByteStr(radj)) - const ir = invN(radj) // r^-1 - const u1 = modN(-h * ir) // -hr^-1 - const u2 = modN(s * ir) // sr^-1 - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) - if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked - Q.assertValidity() - return Q - } - - // Signatures should be low-s, to prevent malleability. - hasHighS(): boolean { - return isBiggerThanHalfOrder(this.s) - } - - normalizeS() { - return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this - } - - // DER-encoded - toDERRawBytes() { - return ut.hexToBytes(this.toDERHex()) - } - toDERHex() { - return DER.hexFromSig({ r: this.r, s: this.s }) - } - - // padded bytes of r, then padded bytes of s - toCompactRawBytes() { - return ut.hexToBytes(this.toCompactHex()) - } - toCompactHex() { - return numToNByteStr(this.r) + numToNByteStr(this.s) - } - } - type RecoveredSignature = Signature & { recovery: number } - - const utils = { - isValidPrivateKey(privateKey: PrivKey) { - try { - normPrivateKeyToScalar(privateKey) - return true - } catch (error) { - return false - } - }, - normPrivateKeyToScalar: normPrivateKeyToScalar, - - /** - * Produces cryptographically secure private key from random of size - * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. - */ - randomPrivateKey: (): Uint8Array => { - const length = getMinHashLength(CURVE.n) - return mapHashToField(CURVE.randomBytes(length), CURVE.n) - }, - - /** - * Creates precompute table for an arbitrary EC point. Makes point "cached". - * Allows to massively speed-up `point.multiply(scalar)`. - * @returns cached point - * @example - * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); - * fast.multiply(privKey); // much faster ECDH now - */ - precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here - return point - }, - } - - /** - * Computes public key for a private key. Checks for validity of the private key. - * @param privateKey private key - * @param isCompressed whether to return compact (default), or full key - * @returns Public key, full when isCompressed=false; short when isCompressed=true - */ - function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) - } - - /** - * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. - */ - function isProbPub(item: PrivKey | PubKey): boolean { - const arr = ut.isBytes(item) - const str = typeof item === 'string' - const len = (arr || str) && (item as Hex).length - if (arr) return len === compressedLen || len === uncompressedLen - if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen - if (item instanceof Point) return true - return false - } - - /** - * ECDH (Elliptic Curve Diffie Hellman). - * Computes shared public key from private key and public key. - * Checks: 1) private key validity 2) shared key is on-curve. - * Does NOT hash the result. - * @param privateA private key - * @param publicB different public key - * @param isCompressed whether to return compact (default), or full key - * @returns shared public key - */ - function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array { - if (isProbPub(privateA)) throw new Error('first arg must be private key') - if (!isProbPub(publicB)) throw new Error('second arg must be public key') - const b = Point.fromHex(publicB) // check for being on-curve - return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) - } - - // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. - // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. - // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. - // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors - const bits2int = - CURVE.bits2int || - function (bytes: Uint8Array): bigint { - // Our custom check "just in case" - if (bytes.length > 8192) throw new Error('input is too large') - // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) - // for some cases, since bytes.length * 8 is not actual bitLength. - const num = ut.bytesToNumberBE(bytes) // check for == u8 done here - const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits - return delta > 0 ? num >> BigInt(delta) : num - } - const bits2int_modN = - CURVE.bits2int_modN || - function (bytes: Uint8Array): bigint { - return modN(bits2int(bytes)) // can't use bytesToNumberBE here - } - // NOTE: pads output with zero as per spec - const ORDER_MASK = ut.bitMask(CURVE.nBitLength) - /** - * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. - */ - function int2octets(num: bigint): Uint8Array { - ut.aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) - // works with order, can have different size than numToField! - return ut.numberToBytesBE(num, CURVE.nByteLength) - } - - // Steps A, D of RFC6979 3.2 - // Creates RFC6979 seed; converts msg/privKey to numbers. - // Used only in sign, not in verify. - // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, - // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 - function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) { - if (['recovered', 'canonical'].some((k) => k in opts)) - throw new Error('sign() legacy options not supported') - const { hash, randomBytes } = CURVE - let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default - if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash - msgHash = ensureBytes('msgHash', msgHash) - validateSigVerOpts(opts) - if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) - - // We can't later call bits2octets, since nested bits2int is broken for curves - // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. - // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) - const h1int = bits2int_modN(msgHash) - const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint - const seedArgs = [int2octets(d), int2octets(h1int)] - // extraEntropy. RFC6979 3.6: additional k' (optional). - if (ent != null && ent !== false) { - // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is - seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes - } - const seed = ut.concatBytes(...seedArgs) // Step D of RFC6979 3.2 - const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! - // Converts signature params into point w r/s, checks result for validity. - function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined { - // RFC 6979 Section 3.2, step 3: k = bits2int(T) - const k = bits2int(kBytes) // Cannot use fields methods, since it is group element - if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N - const ik = invN(k) // k^-1 mod n - const q = Point.BASE.multiply(k).toAffine() // q = Gk - const r = modN(q.x) // r = q.x mod n - if (r === _0n) return - // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to - // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: - // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT - const s = modN(ik * modN(m + r * d)) // Not using blinding here - if (s === _0n) return - let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) - let normS = s - if (lowS && isBiggerThanHalfOrder(s)) { - normS = normalizeS(s) // if lowS was passed, ensure s is always - recovery ^= 1 // // in the bottom half of N - } - return new Signature(r, normS, recovery) as RecoveredSignature // use normS, not s - } - return { seed, k2sig } - } - const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false } - const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false } - - /** - * Signs message hash with a private key. - * ``` - * sign(m, d, k) where - * (x, y) = G × k - * r = x mod n - * s = (m + dr)/k mod n - * ``` - * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. - * @param privKey private key - * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. - * @returns signature with recovery param - */ - function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature { - const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. - const C = CURVE - const drbg = ut.createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) - return drbg(seed, k2sig) // Steps B, C, D, E, F, G - } - - // Enable precomputes. Slows down first publicKey computation by 20ms. - Point.BASE._setWindowSize(8) - // utils.precompute(8, ProjectivePoint.BASE) - - /** - * Verifies a signature against message hash and public key. - * Rejects lowS signatures by default: to override, - * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: - * - * ``` - * verify(r, s, h, P) where - * U1 = hs^-1 mod n - * U2 = rs^-1 mod n - * R = U1⋅G - U2⋅P - * mod(R.x, n) == r - * ``` - */ - function verify( - signature: Hex | SignatureLike, - msgHash: Hex, - publicKey: Hex, - opts = defaultVerOpts, - ): boolean { - const sg = signature - msgHash = ensureBytes('msgHash', msgHash) - publicKey = ensureBytes('publicKey', publicKey) - const { lowS, prehash, format } = opts - - // Verify opts, deduce signature format - validateSigVerOpts(opts) - if ('strict' in opts) throw new Error('options.strict was renamed to lowS') - if (format !== undefined && format !== 'compact' && format !== 'der') - throw new Error('format must be compact or der') - const isHex = typeof sg === 'string' || ut.isBytes(sg) - const isObj = - !isHex && - !format && - typeof sg === 'object' && - sg !== null && - typeof sg.r === 'bigint' && - typeof sg.s === 'bigint' - if (!isHex && !isObj) - throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') - - let _sig: Signature | undefined = undefined - let P: ProjPointType - try { - if (isObj) _sig = new Signature(sg.r, sg.s) - if (isHex) { - // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). - // Since DER can also be 2*nByteLength bytes, we check for it first. - try { - if (format !== 'compact') _sig = Signature.fromDER(sg) - } catch (derError) { - if (!(derError instanceof DER.Err)) throw derError - } - if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) - } - P = Point.fromHex(publicKey) - } catch (error) { - return false - } - if (!_sig) return false - if (lowS && _sig.hasHighS()) return false - if (prehash) msgHash = CURVE.hash(msgHash) - const { r, s } = _sig - const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element - const is = invN(s) // s^-1 - const u1 = modN(h * is) // u1 = hs^-1 mod n - const u2 = modN(r * is) // u2 = rs^-1 mod n - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P - if (!R) return false - const v = modN(R.x) - return v === r - } - return { - CURVE, - getPublicKey, - getSharedSecret, - sign, - verify, - ProjectivePoint: Point, - Signature, - utils, - } -} - -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -export function SWUFpSqrtRatio( - Fp: IField, - Z: T, -): (u: T, v: T) => { isValid: boolean; value: T } { - // Generic implementation - const q = Fp.ORDER - let l = _0n - for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n - const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. - // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. - // 2n ** c1 == 2n << (c1-1) - const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) - const _2n_pow_c1 = _2n_pow_c1_1 * _2n - const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic - const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic - const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic - const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic - const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 - const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) - let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { - let tv1 = c6 // 1. tv1 = c6 - let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 - let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 - tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v - let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 - tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 - tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 - tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v - tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u - let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 - tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 - let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 - tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 - tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) - // 17. for i in (c1, c1 - 1, ..., 2): - for (let i = c1; i > _1n; i--) { - let tv5 = i - _2n // 18. tv5 = i - 2 - tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 - let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 - const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 - tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 - tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 - tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) - } - return { isValid: isQR, value: tv3 } - } - if (Fp.ORDER % _4n === _3n) { - // sqrt_ratio_3mod4(u, v) - const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic - const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) - sqrtRatio = (u: T, v: T) => { - let tv1 = Fp.sqr(v) // 1. tv1 = v^2 - const tv2 = Fp.mul(u, v) // 2. tv2 = u * v - tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 - let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 - y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 - const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 - const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v - const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u - let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) - return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 - } - } - // No curves uses that - // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 - return sqrtRatio -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -export function mapToCurveSimpleSWU( - Fp: IField, - opts: { - A: T - B: T - Z: T - }, -): (u: T) => { x: T; y: T } { - validateField(Fp) - if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) - throw new Error('mapToCurveSimpleSWU: invalid opts') - const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) - if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') - // Input: u, an element of F. - // Output: (x, y), a point on E. - return (u: T): { x: T; y: T } => { - // prettier-ignore - let tv1, tv2, tv3, tv4, tv5, tv6, x, y - tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 - tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 - tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 - tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 - tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 - tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) - tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 - tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 - tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 - tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 - tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 - tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 - tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 - tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 - tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 - x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 - const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) - y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 - y = Fp.mul(y, value) // 20. y = y * y1 - x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) - y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) - const e1 = Fp.isOdd!(u) === Fp.isOdd!(y) // 23. e1 = sgn0(u) == sgn0(y) - y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) - x = Fp.div(x, tv4) // 25. x = x / tv4 - return { x, y } - } -} diff --git a/packages/noble-curves/src/bls12-381.ts b/packages/noble-curves/src/bls12-381.ts deleted file mode 100644 index 422a2906ef0..00000000000 --- a/packages/noble-curves/src/bls12-381.ts +++ /dev/null @@ -1,774 +0,0 @@ -/** - * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: - * * Construct zk-SNARKs at the ~120-bit security - * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: - * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr - * - * ### Summary - * 1. BLS Relies on Bilinear Pairing (expensive) - * 2. Private Keys: 32 bytes - * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. - * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. - * - The signature is a point on the G2 subgroup, which is defined over a finite field - * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the - * complex numbers). - * - We also support reversed 96-byte pubkeys & 48-byte short signatures. - * 5. The 12 stands for the Embedding degree. - * - * ### Formulas - * - `P = pk x G` - public keys - * - `S = pk x H(m)` - signing - * - `e(P, H(m)) == e(G, S)` - verification using pairings - * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation - * - * ### Compatibility and notes - * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. - * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. - * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". - * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) - * 4. Compatible with specs: - * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), - * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), - * [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). - * - * ### Params - * To verify curve parameters, see - * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). - * Basic math is done over finite fields over p. - * More complicated math is done over polynominal extension fields. - * To simplify calculations in Fp12, we construct extension tower: - * - * Embedding degree (k): 12 - * Seed (X): -15132376222941642752 - * Fr: (x⁴-x²+1) - * Fp: ((x-1)² ⋅ r(x)/3+x) - * (E/Fp): Y²=X³+4 - * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) - * Ate loop size: X - * - * ### Towers - * - Fp₁₂ = Fp₆² => Fp₂³ - * - Fp(u) / (u² - β) where β = -1 - * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 - * - Fp₆(w) / (w² - γ) where γ = v - * - Fp²[u] = Fp/u²+1 - * - Fp⁶[v] = Fp²/v³-1-u - * - Fp¹²[w] = Fp⁶/w²-v - * - * @todo construct bls & bn fp/fr from seed. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { type CurveFn, bls } from './abstract/bls.js' -// Types -import { isogenyMap } from './abstract/hash-to-curve.js' -import * as mod from './abstract/modular.js' -import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js' -import { psiFrobenius, tower12 } from './abstract/tower.js' -import { - type Hex, - bitGet, - bitLen, - bytesToHex, - bytesToNumberBE, - concatBytes as concatB, - ensureBytes, - numberToBytesBE, -} from './abstract/utils.js' -import { - type AffinePoint, - type ProjPointType, - mapToCurveSimpleSWU, -} from './abstract/weierstrass.js' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) - -// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! -const BLS_X = BigInt('0xd201000000010000') -const BLS_X_LEN = bitLen(BLS_X) - -// CURVE FIELDS -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - // Order of Fp - ORDER: BigInt( - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', - ), - // Finite extension field over irreducible polynominal. - // Fp(u) / (u² - β) where β = -1 - FP2_NONRESIDUE: [_1n, _1n], - Fp2mulByB: ({ c0, c1 }) => { - const t0 = Fp.mul(c0, _4n) // 4 * c0 - const t1 = Fp.mul(c1, _4n) // 4 * c1 - // (T0-T1) + (T0+T1)*i - return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } - }, - // Fp12 - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BLS_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const x = BLS_X - // this^(q⁶) / this - const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) - // t0^(q²) * t0 - const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) - const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) - const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) - const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) - const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) - const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) - const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) - const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) - const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) - const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) - const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) - // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 - return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) - }, -}) - -// Finite field over r. -// This particular field is not used anywhere in bls12-381, but it is still useful. -const Fr = mod.Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) - -// END OF CURVE FIELDS - -// HashToCurve - -// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 -const isogenyMapG2 = isogenyMap( - Fp2, - [ - // xNum - [ - [ - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - ], - [ - '0x0', - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', - ], - [ - '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', - '0x0', - ], - ], - // xDen - [ - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', - ], - [ - '0xc', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', - ], - ['0x1', '0x0'], // LAST 1 - ], - // yNum - [ - [ - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - ], - [ - '0x0', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', - ], - [ - '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', - '0x0', - ], - ], - // yDen - [ - [ - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - ], - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', - ], - [ - '0x12', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', - ], - ['0x1', '0x0'], // LAST 1 - ], - ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))) as [Fp2[], Fp2[], Fp2[], Fp2[]], -) -// 11-isogeny map from E' to E -const isogenyMapG1 = isogenyMap( - Fp, - [ - // xNum - [ - '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', - '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', - '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', - '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', - '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', - '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', - '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', - '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', - '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', - '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', - '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', - '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', - ], - // xDen - [ - '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', - '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', - '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', - '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', - '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', - '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', - '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', - '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', - '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', - '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', - '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', - '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', - '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', - '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', - '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', - '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', - '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', - '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', - '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', - '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', - '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', - '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', - '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', - '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', - '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', - ], - // yDen - [ - '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', - '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', - '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', - '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', - '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', - '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', - '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', - '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', - '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', - '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', - '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', - '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', - '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', - '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', - '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]], -) - -// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i -const G2_SWU = mapToCurveSimpleSWU(Fp2, { - A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I - B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) - Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) -}) -// Optimized SWU Map - Fp to G1 -const G1_SWU = mapToCurveSimpleSWU(Fp, { - A: Fp.create( - BigInt( - '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', - ), - ), - B: Fp.create( - BigInt( - '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', - ), - ), - Z: Fp.create(BigInt(11)), -}) - -// Endomorphisms (for fast cofactor clearing) -// Ψ(P) endomorphism -const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) - -// Default hash_to_field options are for hash to G2. -// -// Parameter definitions are in section 5.3 of the spec unless otherwise noted. -// Parameter values come from section 8.8.2 of the spec. -// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 -// -// Base field F is GF(p^m) -// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab -// m = 2 (or 1 for G1 see section 8.8.1) -// k = 128 -const htfDefaults = Object.freeze({ - // DST: a domain separation tag - // defined in section 2.2.5 - // Use utils.getDSTLabel(), utils.setDSTLabel(value) - DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - // p: the characteristic of F - // where F is a finite field of characteristic p and order q = p^m - p: Fp.ORDER, - // m: the extension degree of F, m >= 1 - // where F is a finite field of characteristic p and order q = p^m - m: 2, - // k: the target security level for the suite in bits - // defined in section 5.1 - k: 128, - // option to use a message that has already been processed by - // expand_message_xmd - expand: 'xmd', - // Hash functions for: expand_message_xmd is appropriate for use with a - // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. - // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 - hash: sha256, -} as const) - -// Encoding utils -// Point on G1 curve: (x, y) - -// Compressed point of infinity -const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits - -function parseMask(bytes: Uint8Array) { - // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. - bytes = bytes.slice() - const mask = bytes[0] & 0b1110_0000 - const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) - const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) - const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) - bytes[0] &= 0b0001_1111 // clear mask (zero first 3 bits) - return { compressed, infinity, sort, value: bytes } -} - -function setMask( - bytes: Uint8Array, - mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }, -) { - if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask') - if (mask.compressed) bytes[0] |= 0b1000_0000 - if (mask.infinity) bytes[0] |= 0b0100_0000 - if (mask.sort) bytes[0] |= 0b0010_0000 - return bytes -} - -function signatureG1ToRawBytes(point: ProjPointType) { - point.assertValidity() - const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) - const { x, y } = point.toAffine() - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) -} - -function signatureG2ToRawBytes(point: ProjPointType) { - // NOTE: by some reasons it was missed in bls12-381, looks like bug - point.assertValidity() - const len = Fp.BYTES - if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) - return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const { x, y } = point.toAffine() - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - const tmp = y1 > _0n ? y1 * _2n : y0 * _2n - const sort = Boolean((tmp / Fp.ORDER) & _1n) - const z2 = x0 - return concatB( - setMask(numberToBytesBE(x1, len), { sort, compressed: true }), - numberToBytesBE(z2, len), - ) -} - -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -export const bls12_381: CurveFn = bls({ - // Fields - fields: { - Fp, - Fp2, - Fp6, - Fp12, - Fr, - }, - // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where - // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 - G1: { - Fp, - // cofactor; (z - 1)²/3 - h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), - // generator's coordinates - // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 - // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 - Gx: BigInt( - '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', - ), - Gy: BigInt( - '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', - ), - a: Fp.ZERO, - b: _4n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, point): boolean => { - // φ endomorphism - const cubicRootOfUnityModP = BigInt( - '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', - ) - const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) - - // todo: unroll - const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P - const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P - return u2P.equals(phi) - - // https://eprint.iacr.org/2019/814.pdf - // (z² − 1)/3 - // const c1 = BigInt('0x396c8c005555e1560000000055555555'); - // const P = this; - // const S = P.sigma(); - // const Q = S.double(); - // const S2 = S.sigma(); - // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O - // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); - // const C = left.subtract(S2); - // return C.isZero(); - }, - // Clear cofactor of G1 - // https://eprint.iacr.org/2019/403 - clearCofactor: (_c, point) => { - // return this.multiplyUnsafe(CURVE.h); - return point.multiplyUnsafe(BLS_X).add(point) // x*P + P - }, - mapToCurve: (scalars: bigint[]) => { - const { x, y } = G1_SWU(Fp.create(scalars[0])) - return isogenyMapG1(x, y) - }, - fromBytes: (bytes: Uint8Array): AffinePoint => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if (value.length === 48 && compressed) { - // TODO: Fp.bytes - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - const x = Fp.create(compressedValue & Fp.MASK) - if (infinity) { - if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') - return { x: _0n, y: _0n } - } - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) - return { x: Fp.create(x), y: Fp.create(y) } - } else if (value.length === 96 && !compressed) { - // Check if the infinity flag is set - const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) - const y = bytesToNumberBE(value.subarray(Fp.BYTES)) - if (infinity) { - if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') - return bls12_381.G1.ProjectivePoint.ZERO.toAffine() - } - return { x: Fp.create(x), y: Fp.create(y) } - } else { - throw new Error('invalid point G1, expected 48/96 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) - } else { - if (isZero) { - // 2x PUBLIC_KEY_LENGTH - const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) - return x - } else { - return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) - } - } - }, - ShortSignature: { - fromHex(hex: Hex): ProjPointType { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - if (infinity) return bls12_381.G1.ProjectivePoint.ZERO - const x = Fp.create(compressedValue & Fp.MASK) - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - const aflag = BigInt(sort) - if ((y * _2n) / P !== aflag) y = Fp.neg(y) - const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point: ProjPointType) { - return signatureG1ToRawBytes(point) - }, - toHex(point: ProjPointType) { - return bytesToHex(signatureG1ToRawBytes(point)) - }, - }, - }, - // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), - // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where - // G² - 1 - // h2q - G2: { - Fp: Fp2, - // cofactor - h: BigInt( - '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', - ), - Gx: Fp2.fromBigTuple([ - BigInt( - '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', - ), - BigInt( - '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', - ), - ]), - // y = - // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, - // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 - Gy: Fp2.fromBigTuple([ - BigInt( - '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', - ), - BigInt( - '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', - ), - ]), - a: Fp2.ZERO, - b: Fp2.fromBigTuple([_4n, _4n]), - hEff: BigInt( - '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', - ), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: (scalars: bigint[]) => { - const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) - return isogenyMapG2(x, y) - }, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, P): boolean => { - return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) - // Older version: https://eprint.iacr.org/2019/814.pdf - // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O - // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); - }, - // Maps the point into the prime-order subgroup G2. - // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 - // https://eprint.iacr.org/2017/419.pdf - // prettier-ignore - clearCofactor: (c, P) => { - const x = BLS_X - let t1 = P.multiplyUnsafe(x).negate() // [-x]P - let t2 = G2psi(c, P) // Ψ(P) - let t3 = P.double() // 2P - t3 = G2psi2(c, t3) // Ψ²(2P) - t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) - t2 = t1.add(t2) // [-x]P + Ψ(P) - t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) - t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) - t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P - return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) - }, - fromBytes: (bytes: Uint8Array): AffinePoint => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if ( - (!compressed && !infinity && sort) || // 00100000 - (!compressed && infinity && sort) || // 01100000 - (sort && infinity && compressed) // 11100000 - ) { - throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000)) - } - const L = Fp.BYTES - const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to)) - if (value.length === 96 && compressed) { - const b = bls12_381.params.G2b - const P = Fp.ORDER - if (infinity) { - // check that all bytes are 0 - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid compressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x_1 = slc(value, 0, L) - const x_0 = slc(value, L, 2 * L) - const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) - const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b - let y = Fp2.sqrt(right) - const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n - y = sort && Y_bit > 0 ? y : Fp2.neg(y) - return { x, y } - } else if (value.length === 192 && !compressed) { - if (infinity) { - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid uncompressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x1 = slc(value, 0, L) - const x0 = slc(value, L, 2 * L) - const y1 = slc(value, 2 * L, 3 * L) - const y0 = slc(value, 3 * L, 4 * L) - return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } - } else { - throw new Error('invalid point G2, expected 96/192 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const { BYTES: len, ORDER: P } = Fp - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) - return concatB( - setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), - numberToBytesBE(x.c0, len), - ) - } else { - if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - return concatB( - numberToBytesBE(x1, len), - numberToBytesBE(x0, len), - numberToBytesBE(y1, len), - numberToBytesBE(y0, len), - ) - } - }, - Signature: { - // TODO: Optimize, it's very slow because of sqrt. - fromHex(hex: Hex): ProjPointType { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) - const P = Fp.ORDER - const half = value.length / 2 - if (half !== 48 && half !== 96) - throw new Error('invalid compressed signature length, must be 96 or 192') - const z1 = bytesToNumberBE(value.slice(0, half)) - const z2 = bytesToNumberBE(value.slice(half)) - // Indicates the infinity point - if (infinity) return bls12_381.G2.ProjectivePoint.ZERO - const x1 = Fp.create(z1 & Fp.MASK) - const x2 = Fp.create(z2) - const x = Fp2.create({ c0: x2, c1: x1 }) - const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 - // The slow part - let y = Fp2.sqrt(y2) - if (!y) throw new Error('Failed to find a square root') - - // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 - // If y1 happens to be zero, then use the bit of y0 - const { re: y0, im: y1 } = Fp2.reim(y) - const aflag1 = BigInt(sort) - const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 - const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 - if (isGreater || isZero) y = Fp2.neg(y) - const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point: ProjPointType) { - return signatureG2ToRawBytes(point) - }, - toHex(point: ProjPointType) { - return bytesToHex(signatureG2ToRawBytes(point)) - }, - }, - }, - params: { - ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 - r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves - xNegative: true, - twistType: 'multiplicative', - }, - htfDefaults, - hash: sha256, - randomBytes, -}) diff --git a/packages/noble-curves/src/bn254.ts b/packages/noble-curves/src/bn254.ts deleted file mode 100644 index 54bf54022c9..00000000000 --- a/packages/noble-curves/src/bn254.ts +++ /dev/null @@ -1,254 +0,0 @@ -/** - * bn254, previously known as alt_bn_128, when it had 128-bit security. - -Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, -so the naming has been adjusted to its prime bit count: -https://hal.science/hal-01534101/file/main.pdf. -Compatible with EIP-196 and EIP-197. - -There are huge compatibility issues in the ecosystem: - -1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". -2. libff has bn128, but it's a different curve with different G2: - https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 -3. halo2curves bn256 is also incompatible and returns different outputs - -The goal of our implementation is to support "Ethereum" variant of the curve, -because it at least has specs: - -- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM -- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings -- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 -- The existing implementations are bad. Some are deprecated: - - https://github.com/paritytech/bn (old version) - - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) - - https://github.com/zcash-hackworks/bn - - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs -- Python implementations use different towers and produce different Fp12 outputs: - - https://github.com/ethereum/py_pairing - - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py -- Points are encoded differently in different implementations - -### Params -Seed (X): 4965661367192848881 -Fr: (36x⁴+36x³+18x²+6x+1) -Fp: (36x⁴+36x³+24x²+6x+1) -(E / Fp ): Y² = X³+3 -(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) -Ate loop size: 6x+2 - -### Towers -- Fp²[u] = Fp/u²+1 -- Fp⁶[v] = Fp²/v³-9-u -- Fp¹²[w] = Fp⁶/w²-v - - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { getHash } from './_shortw_utils.js' -import { - type CurveFn as BLSCurveFn, - type PostPrecomputeFn, - type PostPrecomputePointAddFn, - bls, -} from './abstract/bls.js' -import { Field } from './abstract/modular.js' -import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.js' -import { psiFrobenius, tower12 } from './abstract/tower.js' -import { bitGet, bitLen, notImplemented } from './abstract/utils.js' -import { type CurveFn, weierstrass } from './abstract/weierstrass.js' -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -const _6n = BigInt(6) - -const BN_X = BigInt('4965661367192848881') -const BN_X_LEN = bitLen(BN_X) -const SIX_X_SQUARED = _6n * BN_X ** _2n - -// Finite field over r. It's for convenience and is not used in the code below. -const Fr = Field( - BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), -) -// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) -const Fp2B = { - c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), - c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), -} - -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), - FP2_NONRESIDUE: [BigInt(9), _1n], - Fp2mulByB: (num) => Fp2.mul(num, Fp2B), - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BN_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) - const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) - const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) - const y1 = Fp12._cyclotomicSquare(powMinusX(r)) - const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) - const y4 = powMinusX(y2) - const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) - const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) - const y9 = Fp12.mul(y8, y1) - return Fp12.mul( - Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), - Fp12.mul( - Fp12.frobeniusMap(y8, 2), - Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), - ), - ) - }, -}) - -// END OF CURVE FIELDS -const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) - -/* -No hashToCurve for now (and signatures): - -- RFC 9380 doesn't mention bn254 and doesn't provide test vectors -- Overall seems like nobody is using BLS signatures on top of bn254 -- Seems like it can utilize SVDW, which is not implemented yet -*/ -const htfDefaults = Object.freeze({ - // DST: a domain separation tag defined in section 2.2.5 - DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - p: Fp.ORDER, - m: 2, - k: 128, - expand: 'xmd', - hash: sha256, -} as const) - -export const _postPrecompute: PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => { - const q = psi(Qx, Qy) - ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) - const q2 = psi(q[0], q[1]) - pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) -} - -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -export const bn254: BLSCurveFn = bls({ - // Fields - fields: { Fp, Fp2, Fp6, Fp12, Fr }, - G1: { - Fp, - h: BigInt(1), - Gx: BigInt(1), - Gy: BigInt(2), - a: Fp.ZERO, - b: _3n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - ShortSignature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - G2: { - Fp: Fp2, - // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 - h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - Gx: Fp2.fromBigTuple([ - BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), - BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), - ]), - Gy: Fp2.fromBigTuple([ - BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), - BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), - ]), - a: Fp2.ZERO, - b: Fp2B, - hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - Signature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - params: { - ateLoopSize: BN_X * _6n + _2n, - r: Fr.ORDER, - xNegative: false, - twistType: 'divisive', - }, - htfDefaults, - hash: sha256, - randomBytes, - - postPrecompute: _postPrecompute, -}) - -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - */ -export const bn254_weierstrass: CurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(3), - Fp, - n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), - Gx: BigInt(1), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) diff --git a/packages/noble-curves/src/ed25519.ts b/packages/noble-curves/src/ed25519.ts deleted file mode 100644 index f058758c38c..00000000000 --- a/packages/noble-curves/src/ed25519.ts +++ /dev/null @@ -1,544 +0,0 @@ -/** - * ed25519 Twisted Edwards curve with following addons: - * - X25519 ECDH - * - Ristretto cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha512 } from '@noble/hashes/sha512' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { type AffinePoint, type Group, pippenger } from './abstract/curve.js' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' -import { - type HTFMethod, - createHasher, - expand_message_xmd, - type htfBasicOpts, -} from './abstract/hash-to-curve.js' -import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.js' -import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.js' -import { - type Hex, - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.js' - -const ED25519_P = BigInt( - '57896044618658097711785492504343953926634992332820282019728792003956564819949', -) -// √(-1) aka √(a) aka 2^((p-1)/4) -const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( - '19681161376707505956807079304988542015446066515923890162744021073123829784752', -) - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// prettier-ignore -const _5n = BigInt(5), - _8n = BigInt(8) - -function ed25519_pow_2_252_3(x: bigint) { - // prettier-ignore - const _10n = BigInt(10), - _20n = BigInt(20), - _40n = BigInt(40), - _80n = BigInt(80) - const P = ED25519_P - const x2 = (x * x) % P - const b2 = (x2 * x) % P // x^3, 11 - const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 - const b5 = (pow2(b4, _1n, P) * x) % P // x^31 - const b10 = (pow2(b5, _5n, P) * b5) % P - const b20 = (pow2(b10, _10n, P) * b10) % P - const b40 = (pow2(b20, _20n, P) * b20) % P - const b80 = (pow2(b40, _40n, P) * b40) % P - const b160 = (pow2(b80, _80n, P) * b80) % P - const b240 = (pow2(b160, _80n, P) * b80) % P - const b250 = (pow2(b240, _10n, P) * b10) % P - const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P - // ^ To pow to (p+3)/8, multiply it by x. - return { pow_p_5_8, b2 } -} - -function adjustScalarBytes(bytes: Uint8Array): Uint8Array { - // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, - // set the three least significant bits of the first byte - bytes[0] &= 248 // 0b1111_1000 - // and the most significant bit of the last to zero, - bytes[31] &= 127 // 0b0111_1111 - // set the second most significant bit of the last byte to 1 - bytes[31] |= 64 // 0b0100_0000 - return bytes -} - -// sqrt(u/v) -function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { - const P = ED25519_P - const v3 = mod(v * v * v, P) // v³ - const v7 = mod(v3 * v3 * v, P) // v⁷ - // (p+3)/8 and (p-5)/8 - const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 - let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 - const vx2 = mod(v * x * x, P) // vx² - const root1 = x // First root candidate - const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate - const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root - const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) - const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) - if (useRoot1) x = root1 - if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time - if (isNegativeLE(x, P)) x = mod(-x, P) - return { isValid: useRoot1 || useRoot2, value: x } -} - -// Just in case -export const ED25519_TORSION_SUBGROUP: string[] = [ - '0100000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', - '0000000000000000000000000000000000000000000000000000000000000080', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', - 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', - '0000000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', -] - -const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() - -const ed25519Defaults = /* @__PURE__ */ (() => - ({ - // Param: a - a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster - // d is equal to -121665/121666 over finite field. - // Negative number is P - number, and division is invert(number, P) - d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), - // Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n - Fp, - // Subgroup order: how many points curve has - // 2n**252n + 27742317777372353535851937790883648493n; - n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), - // Cofactor - h: _8n, - // Base point (x, y) aka generator point - Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), - Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), - hash: sha512, - randomBytes, - adjustScalarBytes, - // dom2 - // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. - // Constant-time, u/√v - uvRatio, - }) as const)() - -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() - -function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) { - if (ctx.length > 255) throw new Error('Context is too big') - return concatBytes( - utf8ToBytes('SigEd25519 no Ed25519 collisions'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) -} - -export const ed25519ctx: CurveFn = /* @__PURE__ */ (() => - twistedEdwards({ - ...ed25519Defaults, - domain: ed25519_domain, - }))() -export const ed25519ph: CurveFn = /* @__PURE__ */ (() => - twistedEdwards( - Object.assign({}, ed25519Defaults, { - domain: ed25519_domain, - prehash: sha512, - }), - ))() - -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -export const x25519: XCurveFn = /* @__PURE__ */ (() => - montgomery({ - P: ED25519_P, - a: BigInt(486662), - montgomeryBits: 255, // n is 253 bits - nByteLength: 32, - Gu: BigInt(9), - powPminus2: (x: bigint): bigint => { - const P = ED25519_P - // x^(p-2) aka x^(2^255-21) - const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) - return mod(pow2(pow_p_5_8, _3n, P) * b2, P) - }, - adjustScalarBytes, - randomBytes, - }))() - -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array { - const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) -} -export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated - -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array { - const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) - return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) -} - -// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) -// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since -// SageMath returns different root first and everything falls apart - -const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic -const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 -const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) - -// prettier-ignore -function map_to_curve_elligator2_curve25519(u: bigint) { - const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic - const ELL2_J = BigInt(486662) - - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 - let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not - let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) - let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 - tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 - tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 - tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 - tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 - let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) - y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) - let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 - tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 - tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd - let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 - let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt - let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd - let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u - y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 - let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 - let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) - tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 - tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 - let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt - tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd - let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 - let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) - return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) -} - -const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 -function map_to_curve_elligator2_edwards25519(u: bigint) { - const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = - // map_to_curve_elligator2_curve25519(u) - let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd - xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 - let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM - let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd - let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) - let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd - let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 - xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) - xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) - yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) - yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) - - const inv = Fp.invertBatch([xd, yd]) // batch division - return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) -} - -const htf = /* @__PURE__ */ (() => - createHasher( - ed25519.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), - { - DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', - encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha512, - }, - ))() -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() - -function assertRstPoint(other: unknown) { - if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') -} - -// √(-1) aka √(a) aka 2^((p-1)/4) -const SQRT_M1 = ED25519_SQRT_M1 -// √(ad - 1) -const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( - '25063068953384623474111414158702152701244531502492656460079210482610430750235', -) -// 1 / √(a-d) -const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( - '54469307008909316920995813868745141605393597292927456921205312896311721017578', -) -// 1-d² -const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( - '1159843021668779879193775521855586647937357759715417654439879720876111806838', -) -// (d-1)² -const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( - '40440834346308536858101042469323190826248399146238708352240133220865137265952', -) -// Calculates 1/√(number) -const invertSqrt = (number: bigint) => uvRatio(_1n, number) - -const MAX_255B = /* @__PURE__ */ BigInt( - '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes255ToNumberLE = (bytes: Uint8Array) => - ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) - -type ExtendedPoint = ExtPointType - -// Computes Elligator map for Ristretto -// https://ristretto.group/formulas/elligator.html -function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { - const { d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const r = mod(SQRT_M1 * r0 * r0) // 1 - const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 - let c = BigInt(-1) // 3 - const D = mod((c - d * r) * mod(r + d)) // 4 - let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 - let s_ = mod(s * r0) // 6 - if (!isNegativeLE(s_, P)) s_ = mod(-s_) - if (!Ns_D_is_sq) s = s_ // 7 - if (!Ns_D_is_sq) c = r // 8 - const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 - const s2 = s * s - const W0 = mod((s + s) * D) // 10 - const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 - const W2 = mod(_1n - s2) // 12 - const W3 = mod(_1n + s2) // 13 - return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} - -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class RistPoint implements Group { - static BASE: RistPoint - static ZERO: RistPoint - // Private property to discourage combining ExtendedPoint + RistrettoPoint - // Always use Ristretto encoding/decoding instead. - constructor(private readonly ep: ExtendedPoint) {} - - static fromAffine(ap: AffinePoint): RistPoint { - return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) - } - - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex: Hex): RistPoint { - hex = ensureBytes('ristrettoHash', hex, 64) - const r1 = bytes255ToNumberLE(hex.slice(0, 32)) - const R1 = calcElligatorRistrettoMap(r1) - const r2 = bytes255ToNumberLE(hex.slice(32, 64)) - const R2 = calcElligatorRistrettoMap(r2) - return new RistPoint(R1.add(R2)) - } - - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex: Hex): RistPoint { - hex = ensureBytes('ristrettoHex', hex, 32) - const { a, d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' - const s = bytes255ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 3. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) - const s2 = mod(s * s) - const u1 = mod(_1n + a * s2) // 4 (a is -1) - const u2 = mod(_1n - a * s2) // 5 - const u1_2 = mod(u1 * u1) - const u2_2 = mod(u2 * u2) - const v = mod(a * d * u1_2 - u2_2) // 6 - const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 - const Dx = mod(I * u2) // 8 - const Dy = mod(I * Dx * v) // 9 - let x = mod((s + s) * Dx) // 10 - if (isNegativeLE(x, P)) x = mod(-x) // 10 - const y = mod(u1 * Dy) // 11 - const t = mod(x * y) // 12 - if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) - return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) - } - - static msm(points: RistPoint[], scalars: bigint[]): RistPoint { - const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) - return pippenger(RistPoint, Fn, points, scalars) - } - - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes(): Uint8Array { - let { ex: x, ey: y, ez: z, et: t } = this.ep - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const u1 = mod(mod(z + y) * mod(z - y)) // 1 - const u2 = mod(x * y) // 2 - // Square root always exists - const u2sq = mod(u2 * u2) - const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 - const D1 = mod(invsqrt * u1) // 4 - const D2 = mod(invsqrt * u2) // 5 - const zInv = mod(D1 * D2 * t) // 6 - let D: bigint // 7 - if (isNegativeLE(t * zInv, P)) { - let _x = mod(y * SQRT_M1) - let _y = mod(x * SQRT_M1) - x = _x - y = _y - D = mod(D1 * INVSQRT_A_MINUS_D) - } else { - D = D2 // 8 - } - if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 - let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) - if (isNegativeLE(s, P)) s = mod(-s) - return numberToBytesLE(s, 32) // 11 - } - - toHex(): string { - return bytesToHex(this.toRawBytes()) - } - - toString(): string { - return this.toHex() - } - - // Compare one point to another. - equals(other: RistPoint): boolean { - assertRstPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed25519.CURVE.Fp.create - // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) - const one = mod(X1 * Y2) === mod(Y1 * X2) - const two = mod(Y1 * Y2) === mod(X1 * X2) - return one || two - } - - add(other: RistPoint): RistPoint { - assertRstPoint(other) - return new RistPoint(this.ep.add(other.ep)) - } - - subtract(other: RistPoint): RistPoint { - assertRstPoint(other) - return new RistPoint(this.ep.subtract(other.ep)) - } - - multiply(scalar: bigint): RistPoint { - return new RistPoint(this.ep.multiply(scalar)) - } - - multiplyUnsafe(scalar: bigint): RistPoint { - return new RistPoint(this.ep.multiplyUnsafe(scalar)) - } - - double(): RistPoint { - return new RistPoint(this.ep.double()) - } - - negate(): RistPoint { - return new RistPoint(this.ep.negate()) - } -} -export const RistrettoPoint: typeof RistPoint = /* @__PURE__ */ (() => { - if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) - if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) - return RistPoint -})() - -// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B -export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts): RistPoint => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) - const P = RistPoint.hashToCurve(uniform_bytes) - return P -} -export const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint = - hashToRistretto255 // legacy diff --git a/packages/noble-curves/src/ed448.ts b/packages/noble-curves/src/ed448.ts deleted file mode 100644 index 2b432735d0b..00000000000 --- a/packages/noble-curves/src/ed448.ts +++ /dev/null @@ -1,514 +0,0 @@ -/** - * Edwards448 (not Ed448-Goldilocks) curve with following addons: - * - X448 ECDH - * - Decaf cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { shake256 } from '@noble/hashes/sha3' -import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' -import type { AffinePoint, Group } from './abstract/curve.js' -import { pippenger } from './abstract/curve.js' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' -import { - type HTFMethod, - createHasher, - expand_message_xof, - type htfBasicOpts, -} from './abstract/hash-to-curve.js' -import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.js' -import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.js' -import { - type Hex, - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.js' - -const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) -const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) -const ed448P = BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', -) - -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4), - _11n = BigInt(11) -// prettier-ignore -const _22n = BigInt(22), - _44n = BigInt(44), - _88n = BigInt(88), - _223n = BigInt(223) - -// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. -// Used for efficient square root calculation. -// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] -function ed448_pow_Pminus3div4(x: bigint): bigint { - const P = ed448P - const b2 = (x * x * x) % P - const b3 = (b2 * b2 * x) % P - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b222 = (pow2(b220, _2n, P) * b2) % P - const b223 = (pow2(b222, _1n, P) * x) % P - return (pow2(b223, _223n, P) * b222) % P -} - -function adjustScalarBytes(bytes: Uint8Array): Uint8Array { - // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most - // significant bit of the last byte to 1. - bytes[0] &= 252 // 0b11111100 - // and the most significant bit of the last byte to 1. - bytes[55] |= 128 // 0b10000000 - // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) - bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) - return bytes -} - -// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. -// Uses algo from RFC8032 5.1.3. -function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { - const P = ed448P - // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 - // To compute the square root of (u/v), the first step is to compute the - // candidate root x = (u/v)^((p+1)/4). This can be done using the - // following trick, to use a single modular powering for both the - // inversion of v and the square root: - // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) - const u2v = mod(u * u * v, P) // u²v - const u3v = mod(u2v * u, P) // u³v - const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ - const root = ed448_pow_Pminus3div4(u5v3) - const x = mod(u3v * root, P) - // Verify that root is exists - const x2 = mod(x * x, P) // x² - // If vx² = u, the recovered x-coordinate is x. Otherwise, no - // square root exists, and the decoding fails. - return { isValid: mod(x2 * v, P) === u, value: x } -} - -const Fp = Field(ed448P, 456, true) - -const ED448_DEF = { - // Param: a - a: BigInt(1), - // -39081. Negative number is P - number - d: BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', - ), - // Finite field 𝔽p over which we'll do calculations; 2n**448n - 2n**224n - 1n - Fp, - // Subgroup order: how many points curve has; - // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n - n: BigInt( - '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', - ), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - nBitLength: 456, - // Cofactor - h: BigInt(4), - // Base point (x, y) aka generator point - Gx: BigInt( - '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', - ), - Gy: BigInt( - '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', - ), - // SHAKE256(dom4(phflag,context)||x, 114) - hash: shake256_114, - randomBytes, - adjustScalarBytes, - // dom4 - domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { - if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) - return concatBytes( - utf8ToBytes('SigEd448'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) - }, - uvRatio, -} as const - -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -export const ed448: CurveFn = /* @__PURE__ */ twistedEdwards(ED448_DEF) -// NOTE: there is no ed448ctx, since ed448 supports ctx by default -export const ed448ph: CurveFn = /* @__PURE__ */ twistedEdwards({ - ...ED448_DEF, - prehash: shake256_64, -}) - -/** - * ECDH using curve448 aka x448. - */ -export const x448: XCurveFn = /* @__PURE__ */ (() => - montgomery({ - a: BigInt(156326), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - montgomeryBits: 448, - nByteLength: 56, - P: ed448P, - Gu: BigInt(5), - powPminus2: (x: bigint): bigint => { - const P = ed448P - const Pminus3div4 = ed448_pow_Pminus3div4(x) - const Pminus3 = pow2(Pminus3div4, BigInt(2), P) - return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 - }, - adjustScalarBytes, - randomBytes, - }))() - -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array { - const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) -} - -export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated -// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version - -// Hash To Curve Elligator2 Map -const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic -const ELL2_J = BigInt(156326) - -function map_to_curve_elligator2_curve448(u: bigint) { - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 - tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 - let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 - let x1n = Fp.neg(ELL2_J) // 5. x1n = -J - let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 - tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd - tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 - let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) - y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) - let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd - let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u - y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) - tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 - let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) - return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) -} - -function map_to_curve_elligator2_edwards448(u: bigint) { - let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) - let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 - let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 - let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 - let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 - let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 - let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 - let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 - xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 - xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd - xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn - xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 - tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 - tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 - let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 - let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 - tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 - let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 - tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn - let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 - let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 - yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 - yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 - tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 - tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 - tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd - tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 - tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 - let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 - tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 - yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 - tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd - let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 - xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) - xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) - yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) - yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) - - const inv = Fp.invertBatch([xEd, yEd]) // batch division - return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) -} - -const htf = /* @__PURE__ */ (() => - createHasher( - ed448.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), - { - DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', - encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 224, - expand: 'xof', - hash: shake256, - }, - ))() -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() - -function assertDcfPoint(other: unknown) { - if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') -} - -// 1-d -const ONE_MINUS_D = BigInt('39082') -// 1-2d -const ONE_MINUS_TWO_D = BigInt('78163') -// √(-d) -const SQRT_MINUS_D = BigInt( - '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', -) -// 1 / √(-d) -const INVSQRT_MINUS_D = BigInt( - '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', -) -// Calculates 1/√(number) -const invertSqrt = (number: bigint) => uvRatio(_1n, number) - -const MAX_448B = BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes448ToNumberLE = (bytes: Uint8Array) => - ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) - -type ExtendedPoint = ExtPointType - -// Computes Elligator map for Decaf -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 -function calcElligatorDecafMap(r0: bigint): ExtendedPoint { - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - - const r = mod(-(r0 * r0)) // 1 - const u0 = mod(d * (r - _1n)) // 2 - const u1 = mod((u0 + _1n) * (u0 - r)) // 3 - - const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 - - let v_prime = v // 5 - if (!was_square) v_prime = mod(r0 * v) - - let sgn = _1n // 6 - if (!was_square) sgn = mod(-_1n) - - const s = mod(v_prime * (r + _1n)) // 7 - let s_abs = s - if (isNegativeLE(s, P)) s_abs = mod(-s) - - const s2 = s * s - const W0 = mod(s_abs * _2n) // 8 - const W1 = mod(s2 + _1n) // 9 - const W2 = mod(s2 - _1n) // 10 - const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 - return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} - -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class DcfPoint implements Group { - static BASE: DcfPoint - static ZERO: DcfPoint - // Private property to discourage combining ExtendedPoint + DecafPoint - // Always use Decaf encoding/decoding instead. - constructor(private readonly ep: ExtendedPoint) {} - - static fromAffine(ap: AffinePoint): DcfPoint { - return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) - } - - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex: Hex): DcfPoint { - hex = ensureBytes('decafHash', hex, 112) - const r1 = bytes448ToNumberLE(hex.slice(0, 56)) - const R1 = calcElligatorDecafMap(r1) - const r2 = bytes448ToNumberLE(hex.slice(56, 112)) - const R2 = calcElligatorDecafMap(r2) - return new DcfPoint(R1.add(R2)) - } - - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex: Hex): DcfPoint { - hex = ensureBytes('decafHex', hex, 56) - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' - const s = bytes448ToNumberLE(hex) - - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 2. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) - - const s2 = mod(s * s) // 1 - const u1 = mod(_1n + s2) // 2 - const u1sq = mod(u1 * u1) - const u2 = mod(u1sq - _4n * d * s2) // 3 - - const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 - - let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 - if (isNegativeLE(u3, P)) u3 = mod(-u3) - - const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 - const y = mod((_1n - s2) * invsqrt * u1) // 7 - const t = mod(x * y) // 8 - - if (!isValid) throw new Error(emsg) - return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) - } - - static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint { - const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) - return pippenger(DcfPoint, Fn, points, scalars) - } - - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes(): Uint8Array { - let { ex: x, ey: _y, ez: z, et: t } = this.ep - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - - const u1 = mod(mod(x + t) * mod(x - t)) // 1 - const x2 = mod(x * x) - const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 - - let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 - if (isNegativeLE(ratio, P)) ratio = mod(-ratio) - - const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 - - let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 - if (isNegativeLE(s, P)) s = mod(-s) - - return numberToBytesLE(s, 56) - } - - toHex(): string { - return bytesToHex(this.toRawBytes()) - } - - toString(): string { - return this.toHex() - } - - // Compare one point to another. - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 - equals(other: DcfPoint): boolean { - assertDcfPoint(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed448.CURVE.Fp.create - // (x1 * y2 == y1 * x2) - return mod(X1 * Y2) === mod(Y1 * X2) - } - - add(other: DcfPoint): DcfPoint { - assertDcfPoint(other) - return new DcfPoint(this.ep.add(other.ep)) - } - - subtract(other: DcfPoint): DcfPoint { - assertDcfPoint(other) - return new DcfPoint(this.ep.subtract(other.ep)) - } - - multiply(scalar: bigint): DcfPoint { - return new DcfPoint(this.ep.multiply(scalar)) - } - - multiplyUnsafe(scalar: bigint): DcfPoint { - return new DcfPoint(this.ep.multiplyUnsafe(scalar)) - } - - double(): DcfPoint { - return new DcfPoint(this.ep.double()) - } - - negate(): DcfPoint { - return new DcfPoint(this.ep.negate()) - } -} - -export const DecafPoint: typeof DcfPoint = /* @__PURE__ */ (() => { - // decaf448 base point is ed448 base x 2 - // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 - if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) - if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) - return DcfPoint -})() - -// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C -export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts): DcfPoint => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) - const P = DcfPoint.hashToCurve(uniform_bytes) - return P -} -export const hash_to_decaf448: typeof hashToDecaf448 = hashToDecaf448 // legacy diff --git a/packages/noble-curves/src/index.ts b/packages/noble-curves/src/index.ts deleted file mode 100644 index 8b4ac3bb10f..00000000000 --- a/packages/noble-curves/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Audited & minimal JS implementation of elliptic curve cryptography. - * @module - * @example -```js -import { secp256k1, schnorr } from '@noble/curves/secp256k1'; -import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; -import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; -import { p256 } from '@noble/curves/p256'; -import { p384 } from '@noble/curves/p384'; -import { p521 } from '@noble/curves/p521'; -import { bls12_381 } from '@noble/curves/bls12-381'; -import { bn254 } from '@noble/curves/bn254'; -import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; -``` - */ -throw new Error('root module cannot be imported: import submodules instead. Check out README') diff --git a/packages/noble-curves/src/jubjub.ts b/packages/noble-curves/src/jubjub.ts deleted file mode 100644 index 50ce965df93..00000000000 --- a/packages/noble-curves/src/jubjub.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * jubjub Twisted Edwards curve. - * https://neuromancer.sk/std/other/JubJub - * jubjub does not use EdDSA, so `hash`/sha512 params are passed because interface expects them. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { blake2s } from '@noble/hashes/blake2s' -import { sha512 } from '@noble/hashes/sha512' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.js' -import { Field } from './abstract/modular.js' - -export const jubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ - // Params: a, d - a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), - d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), - // Finite field 𝔽p over which we'll do calculations - // Same value as bls12-381 Fr (not Fp) - Fp: Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')), - // Subgroup order: how many points curve has - n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), - // Cofactor - h: BigInt(8), - // Base point (x, y) aka generator point - Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), - Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), - hash: sha512, - randomBytes, -} as const) - -const GH_FIRST_BLOCK = utf8ToBytes( - '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', -) - -// Returns point at JubJub curve which is prime order and not zero -export function groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType { - const h = blake2s.create({ personalization, dkLen: 32 }) - h.update(GH_FIRST_BLOCK) - h.update(tag) - // NOTE: returns ExtendedPoint, in case it will be multiplied later - let p = jubjub.ExtendedPoint.fromHex(h.digest()) - // NOTE: cannot replace with isSmallOrder, returns Point*8 - p = p.multiply(jubjub.CURVE.h) - if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') - return p -} - -// No secret data is leaked here at all. -// It operates over public data: -// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); -export function findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType { - const tag = concatBytes(m, new Uint8Array([0])) - const hashes = [] - for (let i = 0; i < 256; i++) { - tag[tag.length - 1] = i - try { - hashes.push(groupHash(tag, personalization)) - } catch (e) {} - } - if (!hashes.length) throw new Error('findGroupHash tag overflow') - return hashes[0] -} diff --git a/packages/noble-curves/src/p256.ts b/packages/noble-curves/src/p256.ts deleted file mode 100644 index d5e2086ff99..00000000000 --- a/packages/noble-curves/src/p256.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * NIST secp256r1 aka p256. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' -import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' - -const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) -const CURVE_A = Fp256.create(BigInt('-3')) -const CURVE_B = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') - -/** secp256r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -export const p256: CurveFnWithCreate = createCurve( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp256, // Field: 2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n - // Curve order, total count of valid points in the field - n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), - // Base (generator) point (x, y) - Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), - Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), - h: BigInt(1), - lowS: false, - } as const, - sha256, -) -/** Alias to p256. */ -export const secp256r1: CurveFnWithCreate = p256 - -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp256, { - A: CURVE_A, - B: CURVE_B, - Z: Fp256.create(BigInt('-10')), - }))() - -const htf = /* @__PURE__ */ (() => - createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { - DST: 'P256_XMD:SHA-256_SSWU_RO_', - encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', - p: Fp256.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - }))() -/** secp256r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp256r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/p384.ts b/packages/noble-curves/src/p384.ts deleted file mode 100644 index 24f23e4c7e9..00000000000 --- a/packages/noble-curves/src/p384.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * NIST secp384r1 aka p384. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-384 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha384 } from '@noble/hashes/sha512' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' -import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' - -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', -) -const Fp384 = Field(P) -const CURVE_A = Fp384.create(BigInt('-3')) -// prettier-ignore -const CURVE_B = BigInt( - '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', -) - -/** secp384r1 curve, ECDSA and ECDH methods. */ -// prettier-ignore -export const p384: CurveFnWithCreate = createCurve( - { - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp: Fp384, // Field: 2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n - // Curve order, total count of valid points in the field. - n: BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', - ), - // Base (generator) point (x, y) - Gx: BigInt( - '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', - ), - Gy: BigInt( - '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', - ), - h: BigInt(1), - lowS: false, - } as const, - sha384, -) -/** Alias to p384. */ -export const secp384r1: CurveFnWithCreate = p384 - -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp384, { - A: CURVE_A, - B: CURVE_B, - Z: Fp384.create(BigInt('-12')), - }))() - -const htf = /* @__PURE__ */ (() => - createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { - DST: 'P384_XMD:SHA-384_SSWU_RO_', - encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', - p: Fp384.ORDER, - m: 1, - k: 192, - expand: 'xmd', - hash: sha384, - }))() -/** secp384r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp384r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/p521.ts b/packages/noble-curves/src/p521.ts deleted file mode 100644 index f4e3df9ec63..00000000000 --- a/packages/noble-curves/src/p521.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * NIST secp521r1 aka p521. - * Note that it's 521, which differs from 512 of its hash function. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-521 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha512 } from '@noble/hashes/sha512' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' -import { type HTFMethod, createHasher } from './abstract/hash-to-curve.js' -import { Field } from './abstract/modular.js' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.js' - -// Field over which we'll do calculations. -// prettier-ignore -const P = BigInt( - '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const Fp521 = Field(P) - -const CURVE = { - a: Fp521.create(BigInt('-3')), - b: BigInt( - '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', - ), - Fp: Fp521, - n: BigInt( - '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', - ), - Gx: BigInt( - '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', - ), - Gy: BigInt( - '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', - ), - h: BigInt(1), -} - -/** - * NIST secp521r1 aka p521. - */ -// prettier-ignore -export const p521: CurveFnWithCreate = createCurve( - { - a: CURVE.a, // Equation params: a, b - b: CURVE.b, - Fp: Fp521, // Field: 2n**521n - 1n - // Curve order, total count of valid points in the field - n: CURVE.n, - Gx: CURVE.Gx, // Base point (x, y) aka generator point - Gy: CURVE.Gy, - h: CURVE.h, - lowS: false, - allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b - } as const, - sha512, -) -export const secp521r1: CurveFnWithCreate = p521 - -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp521, { - A: CURVE.a, - B: CURVE.b, - Z: Fp521.create(BigInt('-4')), - }))() - -const htf = /* @__PURE__ */ (() => - createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => mapSWU(scalars[0]), { - DST: 'P521_XMD:SHA-512_SSWU_RO_', - encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', - p: Fp521.ORDER, - m: 1, - k: 256, - expand: 'xmd', - hash: sha512, - }))() -/** secp521r1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() -/** secp521r1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() diff --git a/packages/noble-curves/src/package.json b/packages/noble-curves/src/package.json deleted file mode 100644 index 3dbc1ca591c..00000000000 --- a/packages/noble-curves/src/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/packages/noble-curves/src/pasta.ts b/packages/noble-curves/src/pasta.ts deleted file mode 100644 index df1784d0d7f..00000000000 --- a/packages/noble-curves/src/pasta.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { getHash } from './_shortw_utils.js' -import { Field, mod } from './abstract/modular.js' -import { type CurveFn, weierstrass } from './abstract/weierstrass.js' - -export const p: bigint = BigInt( - '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001', -) -export const q: bigint = BigInt( - '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001', -) - -/** https://neuromancer.sk/std/other/Pallas */ -export const pallas: CurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(p), - n: q, - Gx: mod(BigInt(-1), p), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) -/** https://neuromancer.sk/std/other/Vesta */ -export const vesta: CurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(q), - n: p, - Gx: mod(BigInt(-1), q), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) diff --git a/packages/noble-curves/src/secp256k1.ts b/packages/noble-curves/src/secp256k1.ts deleted file mode 100644 index ef45055b99c..00000000000 --- a/packages/noble-curves/src/secp256k1.ts +++ /dev/null @@ -1,333 +0,0 @@ -/** - * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). - * - * Seems to be rigid (not backdoored) - * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). - * - * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. - * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. - * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. - * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha256' -import { randomBytes } from '@noble/hashes/utils' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.js' -import { type HTFMethod, createHasher, isogenyMap } from './abstract/hash-to-curve.js' -import { Field, mod, pow2 } from './abstract/modular.js' -import type { Hex, PrivKey } from './abstract/utils.js' -import { - aInRange, - bytesToNumberBE, - concatBytes, - ensureBytes, - inRange, - numberToBytesBE, -} from './abstract/utils.js' -import { type ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.js' - -const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') -const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') -const _1n = BigInt(1) -const _2n = BigInt(2) -const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b - -/** - * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. - * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] - */ -function sqrtMod(y: bigint): bigint { - const P = secp256k1P - // prettier-ignore - const _3n = BigInt(3), - _6n = BigInt(6), - _11n = BigInt(11), - _22n = BigInt(22) - // prettier-ignore - const _23n = BigInt(23), - _44n = BigInt(44), - _88n = BigInt(88) - const b2 = (y * y * y) % P // x^3, 11 - const b3 = (b2 * b2 * y) % P // x^7 - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b223 = (pow2(b220, _3n, P) * b3) % P - const t1 = (pow2(b223, _23n, P) * b22) % P - const t2 = (pow2(t1, _6n, P) * b2) % P - const root = pow2(t2, _2n, P) - if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') - return root -} - -const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) - -/** - * secp256k1 short weierstrass curve and ECDSA signatures over it. - * - * @example - * import { secp256k1 } from '@noble/curves/secp256k1'; - * - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - */ -export const secp256k1: CurveFnWithCreate = createCurve( - { - a: BigInt(0), // equation params: a, b - b: BigInt(7), - Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n - n: secp256k1N, // Curve order, total count of valid points in the field - // Base point (x, y) aka generator point - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - h: BigInt(1), // Cofactor - lowS: true, // Allow only low-S signatures by default in sign() and verify() - endo: { - // Endomorphism, see above - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - splitScalar: (k: bigint) => { - const n = secp256k1N - const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') - const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') - const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') - const b2 = a1 - const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) - - const c1 = divNearest(b2 * k, n) - const c2 = divNearest(-b1 * k, n) - let k1 = mod(k - c1 * a1 - c2 * a2, n) - let k2 = mod(-c1 * b1 - c2 * b2, n) - const k1neg = k1 > POW_2_128 - const k2neg = k2 > POW_2_128 - if (k1neg) k1 = n - k1 - if (k2neg) k2 = n - k2 - if (k1 > POW_2_128 || k2 > POW_2_128) { - throw new Error('splitScalar: Endomorphism failed, k=' + k) - } - return { k1neg, k1, k2neg, k2 } - }, - }, - }, - sha256, -) - -// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. -// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki -const _0n = BigInt(0) -/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ -const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {} -function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array { - let tagP = TAGGED_HASH_PREFIXES[tag] - if (tagP === undefined) { - const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) - tagP = concatBytes(tagH, tagH) - TAGGED_HASH_PREFIXES[tag] = tagP - } - return sha256(concatBytes(tagP, ...messages)) -} - -// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 -const pointToBytes = (point: PointType) => point.toRawBytes(true).slice(1) -const numTo32b = (n: bigint) => numberToBytesBE(n, 32) -const modP = (x: bigint) => mod(x, secp256k1P) -const modN = (x: bigint) => mod(x, secp256k1N) -const Point = secp256k1.ProjectivePoint -const GmulAdd = (Q: PointType, a: bigint, b: bigint) => - Point.BASE.multiplyAndAddUnsafe(Q, a, b) - -// Calculate point, scalar and bytes -function schnorrGetExtPubKey(priv: PrivKey) { - let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey - let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside - const scalar = p.hasEvenY() ? d_ : modN(-d_) - return { scalar: scalar, bytes: pointToBytes(p) } -} -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -function lift_x(x: bigint): PointType { - aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. - const xx = modP(x * x) - const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. - let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. - if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and - const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. - p.assertValidity() - return p -} -const num = bytesToNumberBE -/** - * Create tagged hash, convert it to bigint, reduce modulo-n. - */ -function challenge(...args: Uint8Array[]): bigint { - return modN(num(taggedHash('BIP0340/challenge', ...args))) -} - -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -function schnorrGetPublicKey(privateKey: Hex): Uint8Array { - return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) -} - -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -function schnorrSign( - message: Hex, - privateKey: PrivKey, - auxRand: Hex = randomBytes(32), -): Uint8Array { - const m = ensureBytes('message', message) - const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder - const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array - const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) - const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) - const k_ = modN(num(rand)) // Let k' = int(rand) mod n - if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. - const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. - const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. - const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). - sig.set(rx, 0) - sig.set(numTo32b(modN(k + e * d)), 32) - // If Verify(bytes(P), m, sig) (see below) returns failure, abort - if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') - return sig -} - -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { - const sig = ensureBytes('signature', signature, 64) - const m = ensureBytes('message', message) - const pub = ensureBytes('publicKey', publicKey, 32) - try { - const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails - const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. - if (!inRange(r, _1n, secp256k1P)) return false - const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. - if (!inRange(s, _1n, secp256k1N)) return false - const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n - const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P - if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P - return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. - } catch (error) { - return false - } -} - -export type SecpSchnorr = { - getPublicKey: typeof schnorrGetPublicKey - sign: typeof schnorrSign - verify: typeof schnorrVerify - utils: { - randomPrivateKey: () => Uint8Array - lift_x: typeof lift_x - pointToBytes: (point: PointType) => Uint8Array - numberToBytesBE: typeof numberToBytesBE - bytesToNumberBE: typeof bytesToNumberBE - taggedHash: typeof taggedHash - mod: typeof mod - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - */ -export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => ({ - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - utils: { - randomPrivateKey: secp256k1.utils.randomPrivateKey, - lift_x, - pointToBytes, - numberToBytesBE, - bytesToNumberBE, - taggedHash, - mod, - }, -}))() - -const isoMap = /* @__PURE__ */ (() => - isogenyMap( - Fpk1, - [ - // xNum - [ - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', - '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', - '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', - ], - // xDen - [ - '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', - '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', - '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', - '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', - '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', - ], - // yDen - [ - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', - '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', - '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]], - ))() -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fpk1, { - A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), - B: BigInt('1771'), - Z: Fpk1.create(BigInt('-11')), - }))() -const htf = /* @__PURE__ */ (() => - createHasher( - secp256k1.ProjectivePoint, - (scalars: bigint[]) => { - const { x, y } = mapSWU(Fpk1.create(scalars[0])) - return isoMap(x, y) - }, - { - DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', - encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', - p: Fpk1.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - }, - ))() - -/** secp256k1 hash-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => htf.hashToCurve)() - -/** secp256k1 encode-to-curve from [RFC 9380](https://www.rfc-editor.org/rfc/rfc9380). */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => htf.encodeToCurve)() From 15896a98a9f5aca1e55d00fc7c12107f17fd9114 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 22 Apr 2025 00:53:32 +0200 Subject: [PATCH 07/10] tmp: add noble-curves-tmp pkg [no ci] --- packages/noble-curves-tmp/.c8rc.json | 4 + packages/noble-curves-tmp/.gitignore | 1 + packages/noble-curves-tmp/CHANGELOG.md | 19 + packages/noble-curves-tmp/LICENSE | 22 + packages/noble-curves-tmp/README.md | 114 ++ packages/noble-curves-tmp/eslint.config.mjs | 19 + packages/noble-curves-tmp/package.json | 63 + .../noble-curves-tmp/src/_shortw_utils.ts | 30 + packages/noble-curves-tmp/src/abstract/bls.ts | 573 +++++++ .../noble-curves-tmp/src/abstract/curve.ts | 466 ++++++ .../noble-curves-tmp/src/abstract/edwards.ts | 567 +++++++ .../src/abstract/hash-to-curve.ts | 265 +++ .../noble-curves-tmp/src/abstract/modular.ts | 555 +++++++ .../src/abstract/montgomery.ts | 190 +++ .../noble-curves-tmp/src/abstract/poseidon.ts | 329 ++++ .../noble-curves-tmp/src/abstract/tower.ts | 664 ++++++++ .../noble-curves-tmp/src/abstract/utils.ts | 378 +++++ .../src/abstract/weierstrass.ts | 1419 +++++++++++++++++ packages/noble-curves-tmp/src/bls12-381.ts | 774 +++++++++ packages/noble-curves-tmp/src/bn254.ts | 255 +++ packages/noble-curves-tmp/src/ed25519.ts | 554 +++++++ packages/noble-curves-tmp/src/ed448.ts | 522 ++++++ packages/noble-curves-tmp/src/index.ts | 17 + packages/noble-curves-tmp/src/jubjub.ts | 5 + packages/noble-curves-tmp/src/misc.ts | 117 ++ packages/noble-curves-tmp/src/nist.ts | 171 ++ packages/noble-curves-tmp/src/p256.ts | 23 + packages/noble-curves-tmp/src/p384.ts | 23 + packages/noble-curves-tmp/src/p521.ts | 23 + packages/noble-curves-tmp/src/package.json | 3 + packages/noble-curves-tmp/src/pasta.ts | 1 + packages/noble-curves-tmp/src/secp256k1.ts | 343 ++++ packages/noble-curves-tmp/tsconfig.json | 7 + packages/noble-curves-tmp/tsconfig.lint.json | 3 + .../noble-curves-tmp/tsconfig.prod.cjs.json | 9 + .../noble-curves-tmp/tsconfig.prod.esm.json | 13 + packages/noble-curves-tmp/typedoc.cjs | 6 + 37 files changed, 8547 insertions(+) create mode 100644 packages/noble-curves-tmp/.c8rc.json create mode 100644 packages/noble-curves-tmp/.gitignore create mode 100644 packages/noble-curves-tmp/CHANGELOG.md create mode 100644 packages/noble-curves-tmp/LICENSE create mode 100644 packages/noble-curves-tmp/README.md create mode 100644 packages/noble-curves-tmp/eslint.config.mjs create mode 100644 packages/noble-curves-tmp/package.json create mode 100644 packages/noble-curves-tmp/src/_shortw_utils.ts create mode 100644 packages/noble-curves-tmp/src/abstract/bls.ts create mode 100644 packages/noble-curves-tmp/src/abstract/curve.ts create mode 100644 packages/noble-curves-tmp/src/abstract/edwards.ts create mode 100644 packages/noble-curves-tmp/src/abstract/hash-to-curve.ts create mode 100644 packages/noble-curves-tmp/src/abstract/modular.ts create mode 100644 packages/noble-curves-tmp/src/abstract/montgomery.ts create mode 100644 packages/noble-curves-tmp/src/abstract/poseidon.ts create mode 100644 packages/noble-curves-tmp/src/abstract/tower.ts create mode 100644 packages/noble-curves-tmp/src/abstract/utils.ts create mode 100644 packages/noble-curves-tmp/src/abstract/weierstrass.ts create mode 100644 packages/noble-curves-tmp/src/bls12-381.ts create mode 100644 packages/noble-curves-tmp/src/bn254.ts create mode 100644 packages/noble-curves-tmp/src/ed25519.ts create mode 100644 packages/noble-curves-tmp/src/ed448.ts create mode 100644 packages/noble-curves-tmp/src/index.ts create mode 100644 packages/noble-curves-tmp/src/jubjub.ts create mode 100644 packages/noble-curves-tmp/src/misc.ts create mode 100644 packages/noble-curves-tmp/src/nist.ts create mode 100644 packages/noble-curves-tmp/src/p256.ts create mode 100644 packages/noble-curves-tmp/src/p384.ts create mode 100644 packages/noble-curves-tmp/src/p521.ts create mode 100644 packages/noble-curves-tmp/src/package.json create mode 100644 packages/noble-curves-tmp/src/pasta.ts create mode 100644 packages/noble-curves-tmp/src/secp256k1.ts create mode 100644 packages/noble-curves-tmp/tsconfig.json create mode 100644 packages/noble-curves-tmp/tsconfig.lint.json create mode 100644 packages/noble-curves-tmp/tsconfig.prod.cjs.json create mode 100644 packages/noble-curves-tmp/tsconfig.prod.esm.json create mode 100644 packages/noble-curves-tmp/typedoc.cjs diff --git a/packages/noble-curves-tmp/.c8rc.json b/packages/noble-curves-tmp/.c8rc.json new file mode 100644 index 00000000000..52eb43c23b8 --- /dev/null +++ b/packages/noble-curves-tmp/.c8rc.json @@ -0,0 +1,4 @@ +{ + "extends": "../../config/.c8rc.json", + "include": ["src/**/*.ts"] +} diff --git a/packages/noble-curves-tmp/.gitignore b/packages/noble-curves-tmp/.gitignore new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/packages/noble-curves-tmp/.gitignore @@ -0,0 +1 @@ + diff --git a/packages/noble-curves-tmp/CHANGELOG.md b/packages/noble-curves-tmp/CHANGELOG.md new file mode 100644 index 00000000000..796d8e1acff --- /dev/null +++ b/packages/noble-curves-tmp/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +(modification: no type change headlines) and this project adheres to +[Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## 10.0.0-dev-rc.1 - 2025-03-24 + +Initial development release + +Features: + +- Export history data as Era1 +- Read Era1 files which store pre-merge execution layer block history in 8192 block increments (i.e. eras) +- Read Era files which store SSZ encoded signed beacon blocks by era (8192 blocks) + +Note: This library is still **experimental** and the API might change along minor release versions! \ No newline at end of file diff --git a/packages/noble-curves-tmp/LICENSE b/packages/noble-curves-tmp/LICENSE new file mode 100644 index 00000000000..4a5293bea8d --- /dev/null +++ b/packages/noble-curves-tmp/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2025 EthereumJS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/packages/noble-curves-tmp/README.md b/packages/noble-curves-tmp/README.md new file mode 100644 index 00000000000..9c62e0c14ae --- /dev/null +++ b/packages/noble-curves-tmp/README.md @@ -0,0 +1,114 @@ +# @ethereumjs/era + +[![NPM Package][era-npm-badge]][era-npm-link] +[![GitHub Issues][era-issues-badge]][era-issues-link] +[![Actions Status][era-actions-badge]][era-actions-link] +[![Code Coverage][era-coverage-badge]][era-coverage-link] +[![Discord][discord-badge]][discord-link] + +| A collection of utility functions for Ethereum. | +| ----------------------------------------------- | + +## Installation + +To obtain the latest version, simply require the project using `npm`: + +```shell +npm install @ethereumjs/era +``` + +## Usage + +All helpers are re-exported from the root level and deep imports are not necessary. So an import can be done like this: + +```ts +import { formatEntry } from "@ethereumjs/era"; +``` + +### Export History as Era1 + +Export history in epochs of 8192 blocks as Era1 files + +```ts +import { exportEpochAsEra1 } from "@ethereumjs/era"; + +const dataDir = PATH_TO_ETHEREUMJS_CLIENT_DB; +const epoch = 0; + +// generates ${dataDir}/era1/epoch-0.era1 +await exportEpochAsEra1(epoch, dataDir); +``` + +### Read Era1 file + +`readERA1` returns an async iterator of block tuples (header + body + receipts + totalDifficulty) + +```ts +import { + readBinaryFile, + validateERA1, + readERA1, + parseBlockTuple, + blockFromTuple, + getHeaderRecords, + EpochAccumulator, +} from "@ethereumjs/era"; + +const era1File = readBinaryFile(PATH_TO_ERA1_FILE); + +// validate era1 file +const isValid = validateERA1(era1File); + +// read blocks from era1 file +const blocks = readERA1(era1File); + +for await (const blockTuple of blocks) { + const { header, body, receipts } = await parseBlockTuple(blockTuple); + const block = blockFromTuple({ header, body }); + console.log(block.header.number); +} + +// reconstruct epoch accumulator +const headerRecords = await getHeaderRecords(era1File); +const epochAccumulator = EpochAccumulator.encode(headerRecords); +const epochAccumulatorRoot = EpochAccumulator.merkleRoot(headerRecords); +``` + +### Read Era file + +```ts +import { readBeaconState } from "@ethereumjs/era"; + +const eraFile = readBinaryFile(PATH_TO_ERA_FILE); + +// Extract BeaconState +const state = await readBeaconState(eraFile); +console.log(state.slot) + +// Read Beacon Blocks from era file +let count = 0 +for await (const block of readBlocksFromEra(eraFile)) { + console.log(block.message.slot) + count++ + if (count > 10) break +} +``` + +## EthereumJS + +See our organizational [documentation](https://ethereumjs.readthedocs.io) for an introduction to `EthereumJS` as well as information on current standards and best practices. If you want to join for work or carry out improvements on the libraries, please review our [contribution guidelines](https://ethereumjs.readthedocs.io/en/latest/contributing.html) first. + +## License + +[MPL-2.0]() + +[era-npm-badge]: https://img.shields.io/npm/v/@ethereumjs/era.svg +[era-npm-link]: https://www.npmjs.org/package/@ethereumjs/era +[era-issues-badge]: https://img.shields.io/github/issues/ethereumjs/ethereumjs-monorepo/package:%20era?label=issues +[era-issues-link]: https://github.com/ethereumjs/ethereumjs-monorepo/issues?q=is%3Aopen+is%3Aissue+label%3A"package%3A+era" +[era-actions-badge]: https://github.com/ethereumjs/ethereumjs-monorepo/workflows/Era/badge.svg +[era-actions-link]: https://github.com/ethereumjs/ethereumjs-monorepo/actions?query=workflow%3A%22Era%22 +[era-coverage-badge]: https://codecov.io/gh/ethereumjs/ethereumjs-monorepo/branch/master/graph/badge.svg?flag=era +[era-coverage-link]: https://codecov.io/gh/ethereumjs/ethereumjs-monorepo/tree/master/packages/era +[discord-badge]: https://img.shields.io/static/v1?logo=discord&label=discord&message=Join&color=blue +[discord-link]: https://discord.gg/TNwARpR diff --git a/packages/noble-curves-tmp/eslint.config.mjs b/packages/noble-curves-tmp/eslint.config.mjs new file mode 100644 index 00000000000..a6ffefbcaed --- /dev/null +++ b/packages/noble-curves-tmp/eslint.config.mjs @@ -0,0 +1,19 @@ +import rootConfig from '../../config/eslint.config.mjs' + +export default [ + ...rootConfig, + { + languageOptions: { + parserOptions: { + project: ['./tsconfig.lint.json'], + }, + }, + }, + { + files: ['examples/**/*'], + rules: { + 'no-console': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, +] diff --git a/packages/noble-curves-tmp/package.json b/packages/noble-curves-tmp/package.json new file mode 100644 index 00000000000..ceb38a78dd8 --- /dev/null +++ b/packages/noble-curves-tmp/package.json @@ -0,0 +1,63 @@ +{ + "name": "@ethereumjs/nbl-curves-tmp", + "version": "10.0.0-dev-rc.1", + "description": "Era file support for EthereumJS", + "keywords": ["ethereum", "era", "era1"], + "homepage": "https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/era#readme", + "bugs": { + "url": "https://github.com/ethereumjs/ethereumjs-monorepo/issues?q=is%3Aissue+label%3A%22package%3A+era%22" + }, + "repository": { + "type": "git", + "url": "https://github.com/ethereumjs/ethereumjs-monorepo.git" + }, + "license": "MIT", + "author": "EthereumJS Team", + "contributors": [ + { + "name": "ScottyPoi", + "url": "https://github.com/scottypoi" + } + ], + "type": "module", + "sideEffects": false, + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "exports": { + ".": { + "import": { + "typescript": "./src/index.ts", + "default": "./dist/esm/index.js" + }, + "require": "./dist/cjs/index.js" + } + }, + "files": ["dist", "src"], + "scripts": { + "biome": "npx @biomejs/biome check", + "biome:fix": "npx @biomejs/biome check --write", + "build": "../../config/cli/ts-build.sh", + "clean": "../../config/cli/clean-package.sh", + "coverage": "DEBUG=ethjs npx vitest run -c ../../config/vitest.config.coverage.mts", + "coverage:istanbul": "DEBUG=ethjs npx vitest run -c ../../config/vitest.config.coverage.istanbul.mts", + "docs:build": "npx typedoc --options typedoc.cjs", + "examples": "tsx ../../scripts/examples-runner.ts -- util", + "examples:build": "npx embedme README.md", + "lint": "npm run biome && eslint --config ./eslint.config.mjs .", + "lint:fix": "npm run biome:fix && eslint --fix --config ./eslint.config.mjs .", + "prepublishOnly": "../../config/cli/prepublish.sh", + "sc": "npm run spellcheck", + "spellcheck": "npm run spellcheck:ts && npm run spellcheck:md", + "spellcheck:ts": "npx cspell --gitignore -c ../../config/cspell-ts.json \"./**/*.ts\" --cache --show-suggestions --show-context", + "spellcheck:md": "npx cspell --gitignore -c ../../config/cspell-md.json \"**.md\" --cache --show-suggestions --show-context", + "test": "npm run test:node", + "test:node": "npx vitest run -c ../../config/vitest.config.mts", + "tsc": "../../config/cli/ts-compile.sh" + }, + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": ">=18" + } +} diff --git a/packages/noble-curves-tmp/src/_shortw_utils.ts b/packages/noble-curves-tmp/src/_shortw_utils.ts new file mode 100644 index 00000000000..d5bc2717d58 --- /dev/null +++ b/packages/noble-curves-tmp/src/_shortw_utils.ts @@ -0,0 +1,30 @@ +/** + * Utilities for short weierstrass curves, combined with noble-hashes. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { hmac } from '@noble/hashes/hmac' +import { concatBytes, randomBytes } from '@noble/hashes/utils' +import type { CHash } from './abstract/utils.ts' +import { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.ts' + +/** connects noble-curves to noble-hashes */ +export function getHash(hash: CHash): { + hash: CHash + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array + randomBytes: typeof randomBytes +} { + return { + hash, + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)), + randomBytes, + } +} +/** Same API as @noble/hashes, with ability to create curve with custom hash */ +export type CurveDef = Readonly> +export type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn } + +export function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate { + const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, ...getHash(hash) }) + return { ...create(defHash), create } +} diff --git a/packages/noble-curves-tmp/src/abstract/bls.ts b/packages/noble-curves-tmp/src/abstract/bls.ts new file mode 100644 index 00000000000..37e8eead962 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/bls.ts @@ -0,0 +1,573 @@ +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// TODO: import { AffinePoint } from './curve.ts'; +import { + type H2CPointConstructor, + type Opts as HTFOpts, + type MapToCurve, + createHasher, + type htfBasicOpts, +} from './hash-to-curve.ts' +import { type IField, getMinHashLength, mapHashToField } from './modular.ts' +import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.ts' +import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.ts' +import { + type CurvePointsRes, + type CurvePointsType, + type ProjPointType, + weierstrassPoints, +} from './weierstrass.ts' + +type Fp = bigint // Can be different field? + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +export type TwistType = 'multiplicative' | 'divisive' + +export type ShortSignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type SignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type PostPrecomputePointAddFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, +) => { Rx: Fp2; Ry: Fp2; Rz: Fp2 } +export type PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => void +export type CurveType = { + G1: Omit, 'n'> & { + ShortSignature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + G2: Omit, 'n'> & { + Signature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + fields: { + Fp: IField + Fr: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + } + params: { + // NOTE: MSB is always ignored and used as marker for length, + // otherwise leading zeros will be lost. + // Can be different from 'X' (seed) param! + ateLoopSize: bigint + xNegative: boolean + r: bigint + twistType: TwistType // BLS12-381: Multiplicative, BN254: Divisive + } + htfDefaults: HTFOpts + hash: CHash // Because we need outputLen for DRBG + randomBytes: (bytesLength?: number) => Uint8Array + // This is super ugly hack for untwist point in BN254 after miller loop + postPrecompute?: PostPrecomputeFn +} + +type PrecomputeSingle = [Fp2, Fp2, Fp2][] +type Precompute = PrecomputeSingle[] + +export type CurveFn = { + getPublicKey: (privateKey: PrivKey) => Uint8Array + getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array + sign: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + signShortSignature: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + verify: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyShortSignature: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyBatch: ( + signature: Hex | ProjPointType, + messages: (Hex | ProjPointType)[], + publicKeys: (Hex | ProjPointType)[], + htfOpts?: htfBasicOpts, + ) => boolean + aggregatePublicKeys: { + (publicKeys: Hex[]): Uint8Array + (publicKeys: ProjPointType[]): ProjPointType + } + aggregateSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + aggregateShortSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 + pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 + pairingBatch: ( + pairs: { g1: ProjPointType; g2: ProjPointType }[], + withFinalExponent?: boolean, + ) => Fp12 + G1: CurvePointsRes & ReturnType> + G2: CurvePointsRes & ReturnType> + Signature: SignatureCoder + ShortSignature: ShortSignatureCoder + params: { + ateLoopSize: bigint + r: bigint + G1b: bigint + G2b: Fp2 + } + fields: { + Fp: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + Fr: IField + } + utils: { + randomPrivateKey: () => Uint8Array + calcPairingPrecomputes: (p: ProjPointType) => Precompute + } +} + +// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. +function NAfDecomposition(a: bigint) { + const res = [] + // a>1 because of marker bit + for (; a > _1n; a >>= _1n) { + if ((a & _1n) === _0n) res.unshift(0) + else if ((a & _3n) === _3n) { + res.unshift(-1) + a += _1n + } else res.unshift(1) + } + return res +} + +export function bls(CURVE: CurveType): CurveFn { + // Fields are specific for curve, so for now we'll need to pass them with opts + const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields + const BLS_X_IS_NEGATIVE = CURVE.params.xNegative + const TWIST: TwistType = CURVE.params.twistType + // Point on G1 curve: (x, y) + const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) + const G1 = Object.assign( + G1_, + createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G1.htfDefaults, + }), + ) + // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) + const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) + const G2 = Object.assign( + G2_, + createHasher(G2_.ProjectivePoint as H2CPointConstructor, CURVE.G2.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G2.htfDefaults, + }), + ) + type G1 = typeof G1.ProjectivePoint.BASE + type G2 = typeof G2.ProjectivePoint.BASE + + // Applies sparse multiplication as line function + let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12 + if (TWIST === 'multiplicative') { + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) + } else if (TWIST === 'divisive') { + // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of + // precompute calculations. + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) + } else throw new Error('bls: unknown twist type') + + const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) + function pointDouble(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2) { + const t0 = Fp2.sqr(Ry) // Ry² + const t1 = Fp2.sqr(Rz) // Rz² + const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B + const t3 = Fp2.mul(t2, _3n) // 3 * T2 + const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 + const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) + const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² + const c2 = Fp2.neg(t4) // -T4 (-h) + + ell.push([c0, c1, c2]) + + Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 + Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² + Rz = Fp2.mul(t0, t4) // T0 * T4 + return { Rx, Ry, Rz } + } + function pointAdd(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) { + // Addition + const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz + const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz + const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy + const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry + const c2 = t1 // == Rx - Qx * Rz + + ell.push([c0, c1, c2]) + + const t2 = Fp2.sqr(t1) // T1² + const t3 = Fp2.mul(t2, t1) // T2 * T1 + const t4 = Fp2.mul(t2, Rx) // T2 * Rx + const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz + Rx = Fp2.mul(t1, t5) // T1 * T5 + Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry + Rz = Fp2.mul(Rz, t3) // Rz * T3 + return { Rx, Ry, Rz } + } + + // Pre-compute coefficients for sparse multiplication + // Point addition and point double calculations is reused for coefficients + // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine + // add + double in windowed precomputes here, otherwise it would be single op (since X is static) + const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) + + const calcPairingPrecomputes = memoized((point: G2) => { + const p = point + const { x, y } = p.toAffine() + // prettier-ignore + const Qx = x, + Qy = y, + negQy = Fp2.neg(y) + // prettier-ignore + let Rx = Qx, + Ry = Qy, + Rz = Fp2.ONE + const ell: Precompute = [] + for (const bit of ATE_NAF) { + const cur: PrecomputeSingle = [] + ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) + if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) + ell.push(cur) + } + if (CURVE.postPrecompute) { + const last = ell[ell.length - 1] + CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) + } + return ell + }) + + // Main pairing logic is here. Computes product of miller loops + final exponentiate + // Applies calculated precomputes + type MillerInput = [Precompute, Fp, Fp][] + function millerLoopBatch(pairs: MillerInput, withFinalExponent: boolean = false) { + let f12 = Fp12.ONE + if (pairs.length) { + const ellLen = pairs[0][0].length + for (let i = 0; i < ellLen; i++) { + f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings + // NOTE: we apply multiple pairings in parallel here + for (const [ell, Px, Py] of pairs) { + for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) + } + } + } + if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) + return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 + } + type PairingInput = { g1: G1; g2: G2 } + // Calculates product of multiple pairings + // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` + function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) { + const res: MillerInput = [] + // This cache precomputed toAffine for all points + G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) + G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) + for (const { g1, g2 } of pairs) { + if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) + throw new Error('pairing is not available for ZERO point') + // This uses toAffine inside + g1.assertValidity() + g2.assertValidity() + const Qa = g1.toAffine() + res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) + } + return millerLoopBatch(res, withFinalExponent) + } + // Calculates bilinear pairing + function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 { + return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) + } + + const utils = { + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(Fr.ORDER) + return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) + }, + calcPairingPrecomputes, + } + + const { ShortSignature } = CURVE.G1 + const { Signature } = CURVE.G2 + + type G1Hex = Hex | G1 + type G2Hex = Hex | G2 + function normP1(point: G1Hex): G1 { + return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point) + } + function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 { + return point instanceof G1.ProjectivePoint + ? point + : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1) + } + function normP2(point: G2Hex): G2 { + return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) + } + function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 { + return point instanceof G2.ProjectivePoint + ? point + : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2) + } + + // Multiplies generator (G1) by private key. + // P = pk x G + function getPublicKey(privateKey: PrivKey): Uint8Array { + return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Multiplies generator (G2) by private key. + // P = pk x G + function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array { + return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Executes `hashToCurve` on the message and then multiplies the result by private key. + // S = pk x H(m) + function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2 + function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 { + const msgPoint = normP2Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G2.ProjectivePoint) return sigPoint + return Signature.toRawBytes(sigPoint) + } + + function signShortSignature(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1 + function signShortSignature( + message: G1Hex, + privateKey: PrivKey, + htfOpts?: htfBasicOpts, + ): Uint8Array | G1 { + const msgPoint = normP1Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G1.ProjectivePoint) return sigPoint + return ShortSignature.toRawBytes(sigPoint) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(P, H(m)) == e(G, S) + function verify( + signature: G2Hex, + message: G2Hex, + publicKey: G1Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP1(publicKey) + const Hm = normP2Hash(message, htfOpts) + const G = G1.ProjectivePoint.BASE + const S = normP2(signature) + const exp = pairingBatch([ + { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); + { g1: G, g2: S }, // eGS = pairing(G, S, false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(S, G) == e(H(m), P) + function verifyShortSignature( + signature: G1Hex, + message: G1Hex, + publicKey: G2Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP2(publicKey) + const Hm = normP1Hash(message, htfOpts) + const G = G2.ProjectivePoint.BASE + const S = normP1(signature) + const exp = pairingBatch([ + { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); + { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + function aNonEmpty(arr: any[]) { + if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') + } + + // Adds a bunch of public key points together. + // pk1 + pk2 + pk3 = pkA + function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array + function aggregatePublicKeys(publicKeys: G1[]): G1 + function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 { + aNonEmpty(publicKeys) + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (publicKeys[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + // toRawBytes ensures point validity + return aggAffine.toRawBytes(true) + } + + // Adds a bunch of signature points together. + function aggregateSignatures(signatures: Hex[]): Uint8Array + function aggregateSignatures(signatures: G2[]): G2 + function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 { + aNonEmpty(signatures) + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G2.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return Signature.toRawBytes(aggAffine) + } + + // Adds a bunch of signature points together. + function aggregateShortSignatures(signatures: Hex[]): Uint8Array + function aggregateShortSignatures(signatures: G1[]): G1 + function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 { + aNonEmpty(signatures) + const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return ShortSignature.toRawBytes(aggAffine) + } + + // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 + // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) + function verifyBatch( + signature: G2Hex, + // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? + messages: G2Hex[], + publicKeys: G1Hex[], + htfOpts?: htfBasicOpts, + ): boolean { + aNonEmpty(messages) + if (publicKeys.length !== messages.length) + throw new Error('amount of public keys and messages should be equal') + const sig = normP2(signature) + const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) + const nPublicKeys = publicKeys.map(normP1) + // NOTE: this works only for exact same object + const messagePubKeyMap = new Map() + for (let i = 0; i < nPublicKeys.length; i++) { + const pub = nPublicKeys[i] + const msg = nMessages[i] + let keys = messagePubKeyMap.get(msg) + if (keys === undefined) { + keys = [] + messagePubKeyMap.set(msg, keys) + } + keys.push(pub) + } + const paired = [] + try { + for (const [msg, keys] of messagePubKeyMap) { + const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) + paired.push({ g1: groupPublicKey, g2: msg }) + } + paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) + return Fp12.eql(pairingBatch(paired), Fp12.ONE) + } catch { + return false + } + } + + G1.ProjectivePoint.BASE._setWindowSize(4) + + return { + getPublicKey, + getPublicKeyForShortSignatures, + sign, + signShortSignature, + verify, + verifyBatch, + verifyShortSignature, + aggregatePublicKeys, + aggregateSignatures, + aggregateShortSignatures, + millerLoopBatch, + pairing, + pairingBatch, + G1, + G2, + Signature, + ShortSignature, + fields: { + Fr, + Fp, + Fp2, + Fp6, + Fp12, + }, + params: { + ateLoopSize: CURVE.params.ateLoopSize, + r: CURVE.params.r, + G1b: CURVE.G1.b, + G2b: CURVE.G2.b, + }, + utils, + } +} diff --git a/packages/noble-curves-tmp/src/abstract/curve.ts b/packages/noble-curves-tmp/src/abstract/curve.ts new file mode 100644 index 00000000000..6a7830a1970 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/curve.ts @@ -0,0 +1,466 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField, nLength, validateField } from './modular.ts' +import { bitLen, bitMask, validateObject } from './utils.ts' + +const _0n = BigInt(0) +const _1n = BigInt(1) + +export type AffinePoint = { + x: T + y: T +} & { z?: never; t?: never } + +export interface Group> { + double(): T + negate(): T + add(other: T): T + subtract(other: T): T + equals(other: T): boolean + multiply(scalar: bigint): T +} + +export type GroupConstructor = { + BASE: T + ZERO: T +} +export type Mapper = (i: T[]) => T[] + +function constTimeNegate>(condition: boolean, item: T): T { + const neg = item.negate() + return condition ? neg : item +} + +function validateW(W: number, bits: number) { + if (!Number.isSafeInteger(W) || W <= 0 || W > bits) + throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) +} + +/** Internal wNAF opts for specific W and scalarBits */ +export type WOpts = { + windows: number + windowSize: number + mask: bigint + maxNumber: number + shiftBy: bigint +} + +function calcWOpts(W: number, scalarBits: number): WOpts { + validateW(W, scalarBits) + const windows = Math.ceil(scalarBits / W) + 1 // W=8 33. Not 32, because we skip zero + const windowSize = 2 ** (W - 1) // W=8 128. Not 256, because we skip zero + const maxNumber = 2 ** W // W=8 256 + const mask = bitMask(W) // W=8 255 == mask 0b11111111 + const shiftBy = BigInt(W) // W=8 8 + return { windows, windowSize, mask, maxNumber, shiftBy } +} + +function calcOffsets(n: bigint, window: number, wOpts: WOpts) { + const { windowSize, mask, maxNumber, shiftBy } = wOpts + let wbits = Number(n & mask) // extract W bits. + let nextN = n >> shiftBy // shift number by W bits. + + // What actually happens here: + // const highestBit = Number(mask ^ (mask >> 1n)); + // let wbits2 = wbits - 1; // skip zero + // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~); + + // split if bits > max: +224 => 256-32 + if (wbits > windowSize) { + // we skip zero, which means instead of `>= size-1`, we do `> size` + wbits -= maxNumber // -32, can be maxNumber - wbits, but then we need to set isNeg here. + nextN += _1n // +256 (carry) + } + const offsetStart = window * windowSize + const offset = offsetStart + Math.abs(wbits) - 1 // -1 because we skip zero + const isZero = wbits === 0 // is current window slice a 0? + const isNeg = wbits < 0 // is current window slice negative? + const isNegF = window % 2 !== 0 // fake random statement for noise + const offsetF = offsetStart // fake offset for noise + return { nextN, offset, isZero, isNeg, isNegF, offsetF } +} + +function validateMSMPoints(points: any[], c: any) { + if (!Array.isArray(points)) throw new Error('array expected') + points.forEach((p, i) => { + if (!(p instanceof c)) throw new Error('invalid point at index ' + i) + }) +} +function validateMSMScalars(scalars: any[], field: any) { + if (!Array.isArray(scalars)) throw new Error('array of scalars expected') + scalars.forEach((s, i) => { + if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) + }) +} + +// Since points in different groups cannot be equal (different object constructor), +// we can have single place to store precomputes. +// Allows to make points frozen / immutable. +const pointPrecomputes = new WeakMap() +const pointWindowSizes = new WeakMap() + +function getW(P: any): number { + return pointWindowSizes.get(P) || 1 +} + +export type IWNAF> = { + constTimeNegate: >(condition: boolean, item: T) => T + hasPrecomputes(elm: T): boolean + unsafeLadder(elm: T, n: bigint, p?: T): T + precomputeWindow(elm: T, W: number): Group[] + getPrecomputes(W: number, P: T, transform: Mapper): T[] + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T + setWindowSize(P: T, W: number): void +} + +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export function wNAF>(c: GroupConstructor, bits: number): IWNAF { + return { + constTimeNegate, + + hasPrecomputes(elm: T) { + return getW(elm) !== 1 + }, + + // non-const time multiplication ladder + unsafeLadder(elm: T, n: bigint, p = c.ZERO) { + let d: T = elm + while (n > _0n) { + if (n & _1n) p = p.add(d) + d = d.double() + n >>= _1n + } + return p + }, + + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param elm Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(elm: T, W: number): Group[] { + const { windows, windowSize } = calcWOpts(W, bits) + const points: T[] = [] + let p: T = elm + let base = p + for (let window = 0; window < windows; window++) { + base = p + points.push(base) + // i=1, bc we skip 0 + for (let i = 1; i < windowSize; i++) { + base = base.add(p) + points.push(base) + } + p = base.double() + } + return points + }, + + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @returns real and fake (for const-time) points + */ + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } { + // Smaller version: + // https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541 + // TODO: check the scalar is less than group order? + // wNAF behavior is undefined otherwise. But have to carefully remove + // other checks before wNAF. ORDER == bits here. + // Accumulators + let p = c.ZERO + let f = c.BASE + // This code was first written with assumption that 'f' and 'p' will never be infinity point: + // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, + // there is negate now: it is possible that negated element from low value + // would be the same as high element, which will create carry into next window. + // It's not obvious how this can fail, but still worth investigating later. + const wo = calcWOpts(W, bits) + for (let window = 0; window < wo.windows; window++) { + // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise + const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo) + n = nextN + if (isZero) { + // bits are 0: add garbage to fake point + // Important part for const-time getPublicKey: add random "noise" point to f. + f = f.add(constTimeNegate(isNegF, precomputes[offsetF])) + } else { + // bits are 1: add to result point + p = p.add(constTimeNegate(isNeg, precomputes[offset])) + } + } + // Return both real and fake points: JIT won't eliminate f. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. + return { p, f } + }, + + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc: T = c.ZERO): T { + const wo = calcWOpts(W, bits) + for (let window = 0; window < wo.windows; window++) { + if (n === _0n) break // Early-exit, skip 0 value + const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo) + n = nextN + if (isZero) { + // Window bits are 0: skip processing. + // Move to next window. + continue + } else { + const item = precomputes[offset] + acc = acc.add(isNeg ? item.negate() : item) // Re-using acc allows to save adds in MSM + } + } + return acc + }, + + getPrecomputes(W: number, P: T, transform: Mapper): T[] { + // Calculate precomputes on a first run, reuse them after + let comp = pointPrecomputes.get(P) + if (!comp) { + comp = this.precomputeWindow(P, W) as T[] + if (W !== 1) pointPrecomputes.set(P, transform(comp)) + } + return comp + }, + + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } { + const W = getW(P) + return this.wNAF(W, this.getPrecomputes(W, P, transform), n) + }, + + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T { + const W = getW(P) + if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster + return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) + }, + + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + + setWindowSize(P: T, W: number) { + validateW(W, bits) + pointWindowSizes.set(P, W) + pointPrecomputes.delete(P) + }, + } +} + +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster than precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export function pippenger>( + c: GroupConstructor, + fieldN: IField, + points: T[], + scalars: bigint[], +): T { + // If we split scalars by some window (let's say 8 bits), every chunk will only + // take 256 buckets even if there are 4096 scalars, also re-uses double. + // TODO: + // - https://eprint.iacr.org/2024/750.pdf + // - https://tches.iacr.org/index.php/TCHES/article/view/10287 + // 0 is accepted in scalars + validateMSMPoints(points, c) + validateMSMScalars(scalars, fieldN) + if (points.length !== scalars.length) + throw new Error('arrays of points and scalars must have equal length') + const zero = c.ZERO + const wbits = bitLen(BigInt(points.length)) + const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits + const MASK = bitMask(windowSize) + const buckets = new Array(Number(MASK) + 1).fill(zero) // +1 for zero array + const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize + let sum = zero + for (let i = lastBits; i >= 0; i -= windowSize) { + buckets.fill(zero) + for (let j = 0; j < scalars.length; j++) { + const scalar = scalars[j] + const wbits = Number((scalar >> BigInt(i)) & MASK) + buckets[wbits] = buckets[wbits].add(points[j]) + } + let resI = zero // not using this will do small speed-up, but will lose ct + // Skip first bucket, because it is zero + for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { + sumI = sumI.add(buckets[j]) + resI = resI.add(sumI) + } + sum = sum.add(resI) + if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() + } + return sum as T +} +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export function precomputeMSMUnsafe>( + c: GroupConstructor, + fieldN: IField, + points: T[], + windowSize: number, +): (scalars: bigint[]) => T { + /** + * Performance Analysis of Window-based Precomputation + * + * Base Case (256-bit scalar, 8-bit window): + * - Standard precomputation requires: + * - 31 additions per scalar × 256 scalars = 7,936 ops + * - Plus 255 summary additions = 8,191 total ops + * Note: Summary additions can be optimized via accumulator + * + * Chunked Precomputation Analysis: + * - Using 32 chunks requires: + * - 255 additions per chunk + * - 256 doublings + * - Total: (255 × 32) + 256 = 8,416 ops + * + * Memory Usage Comparison: + * Window Size | Standard Points | Chunked Points + * ------------|-----------------|--------------- + * 4-bit | 520 | 15 + * 8-bit | 4,224 | 255 + * 10-bit | 13,824 | 1,023 + * 16-bit | 557,056 | 65,535 + * + * Key Advantages: + * 1. Enables larger window sizes due to reduced memory overhead + * 2. More efficient for smaller scalar counts: + * - 16 chunks: (16 × 255) + 256 = 4,336 ops + * - ~2x faster than standard 8,191 ops + * + * Limitations: + * - Not suitable for plain precomputes (requires 256 constant doublings) + * - Performance degrades with larger scalar counts: + * - Optimal for ~256 scalars + * - Less efficient for 4096+ scalars (Pippenger preferred) + */ + validateW(windowSize, fieldN.BITS) + validateMSMPoints(points, c) + const zero = c.ZERO + const tableSize = 2 ** windowSize - 1 // table size (without zero) + const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item + const MASK = bitMask(windowSize) + const tables = points.map((p: T) => { + const res = [] + for (let i = 0, acc = p; i < tableSize; i++) { + res.push(acc) + acc = acc.add(p) + } + return res + }) + return (scalars: bigint[]): T => { + validateMSMScalars(scalars, fieldN) + if (scalars.length > points.length) + throw new Error('array of scalars must be smaller than array of points') + let res = zero + for (let i = 0; i < chunks; i++) { + // No need to double if accumulator is still zero. + if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() + const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) + for (let j = 0; j < scalars.length; j++) { + const n = scalars[j] + const curr = Number((n >> shiftBy) & MASK) + if (!curr) continue // skip zero scalars chunks + res = res.add(tables[j][curr - 1]) + } + } + return res + } +} + +/** + * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. + * Though generator can be different (Fp2 / Fp6 for BLS). + */ +export type BasicCurve = { + Fp: IField // Field over which we'll do calculations (Fp) + n: bigint // Curve order, total count of valid points in the field + nBitLength?: number // bit length of curve order + nByteLength?: number // byte length of curve order + h: bigint // cofactor. we can assign default=1, but users will just ignore it w/o validation + hEff?: bigint // Number to multiply to clear cofactor + Gx: T // base point X coordinate + Gy: T // base point Y coordinate + allowInfinityPoint?: boolean // bls12-381 requires it. ZERO point is valid, but invalid pubkey +} + +export function validateBasic( + curve: BasicCurve & T, +): Readonly< + { + readonly nBitLength: number + readonly nByteLength: number + } & BasicCurve & + T & { + p: bigint + } +> { + validateField(curve.Fp) + validateObject( + curve, + { + n: 'bigint', + h: 'bigint', + Gx: 'field', + Gy: 'field', + }, + { + nBitLength: 'isSafeInteger', + nByteLength: 'isSafeInteger', + }, + ) + // Set defaults + return Object.freeze({ + ...nLength(curve.n, curve.nBitLength), + ...curve, + ...{ p: curve.Fp.ORDER }, + } as const) +} diff --git a/packages/noble-curves-tmp/src/abstract/edwards.ts b/packages/noble-curves-tmp/src/abstract/edwards.ts new file mode 100644 index 00000000000..d54d0d5da78 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/edwards.ts @@ -0,0 +1,567 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.ts' +import { Field, mod } from './modular.ts' +// prettier-ignore +import { + type FHash, + type Hex, + aInRange, + abool, + bytesToHex, + bytesToNumberLE, + concatBytes, + ensureBytes, + memoized, + numberToBytesLE, + validateObject, +} from './utils.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _8n = BigInt(8) + +/** Edwards curves must declare params a & d. */ +export type CurveType = BasicCurve & { + a: bigint // curve param a + d: bigint // curve param d + hash: FHash // Hashing + randomBytes: (bytesLength?: number) => Uint8Array // CSPRNG + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array // clears bits to get valid field elemtn + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array // Used for hashing + uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint } // Ratio √(u/v) + prehash?: FHash // RFC 8032 pre-hashing of messages to sign() / verify() + mapToCurve?: (scalar: bigint[]) => AffinePoint // for hash-to-curve standard +} + +export type CurveTypeWithLength = Readonly + +// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: +const VERIFY_DEFAULT = { zip215: true } + +function validateOpts(curve: CurveType): CurveTypeWithLength { + const opts = validateBasic(curve) + validateObject( + curve, + { + hash: 'function', + a: 'bigint', + d: 'bigint', + randomBytes: 'function', + }, + { + adjustScalarBytes: 'function', + domain: 'function', + uvRatio: 'function', + mapToCurve: 'function', + }, + ) + // Set defaults + return Object.freeze({ ...opts } as const) +} + +/** Instance of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointType extends Group { + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + get x(): bigint + get y(): bigint + assertValidity(): void + multiply(scalar: bigint): ExtPointType + multiplyUnsafe(scalar: bigint): ExtPointType + isSmallOrder(): boolean + isTorsionFree(): boolean + clearCofactor(): ExtPointType + toAffine(iz?: bigint): AffinePoint + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + _setWindowSize(windowSize: number): void +} +/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType + fromAffine(p: AffinePoint): ExtPointType + fromHex(hex: Hex): ExtPointType + fromPrivateKey(privateKey: Hex): ExtPointType + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType +} + +/** + * Edwards Curve interface. + * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. + */ +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: Hex) => Uint8Array + sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { context?: Hex; zip215: boolean }, + ) => boolean + ExtendedPoint: ExtPointConstructor + utils: { + randomPrivateKey: () => Uint8Array + getExtendedPublicKey: (key: Hex) => { + head: Uint8Array + prefix: Uint8Array + scalar: bigint + point: ExtPointType + pointBytes: Uint8Array + } + precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType + } +} + +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export function twistedEdwards(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { + Fp, + n: CURVE_ORDER, + prehash: prehash, + hash: cHash, + randomBytes, + nByteLength, + h: cofactor, + } = CURVE + // Important: + // There are some places where Fp.BYTES is used instead of nByteLength. + // So far, everything has been tested with curves of Fp.BYTES == nByteLength. + // TODO: test and find curves which behave otherwise. + const MASK = _2n << (BigInt(nByteLength * 8) - _1n) + const modP = Fp.create // Function overrides + const Fn = Field(CURVE.n, CURVE.nBitLength) + + // sqrt(u/v) + const uvRatio = + CURVE.uvRatio || + ((u: bigint, v: bigint) => { + try { + return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } + } catch (e) { + return { isValid: false, value: _0n } + } + }) + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) // NOOP + const domain = + CURVE.domain || + ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + abool('phflag', phflag) + if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') + return data + }) // NOOP + // 0 <= n < MASK + // Coordinates larger than Fp.ORDER are allowed for zip215 + function aCoordinate(title: string, n: bigint, banZero = false) { + const min = banZero ? _1n : _0n + aInRange('coordinate ' + title, n, min, MASK) + } + + function aextpoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint => { + const { ex: x, ey: y, ez: z } = p + const is0 = p.is0() + if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint) // 8 was chosen arbitrarily + const ax = modP(x * iz) + const ay = modP(y * iz) + const zz = modP(z * iz) + if (is0) return { x: _0n, y: _1n } + if (zz !== _1n) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + const assertValidMemo = memoized((p: Point) => { + const { a, d } = CURVE + if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? + // Equation in affine coordinates: ax² + y² = 1 + dx²y² + // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² + const { ex: X, ey: Y, ez: Z, et: T } = p + const X2 = modP(X * X) // X² + const Y2 = modP(Y * Y) // Y² + const Z2 = modP(Z * Z) // Z² + const Z4 = modP(Z2 * Z2) // Z⁴ + const aX2 = modP(X2 * a) // aX² + const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² + const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² + if (left !== right) throw new Error('bad point: equation left != right (1)') + // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T + const XY = modP(X * Y) + const ZT = modP(Z * T) + if (XY !== ZT) throw new Error('bad point: equation left != right (2)') + return true + }) + + // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). + // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates + class Point implements ExtPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) + static readonly ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + + constructor(ex: bigint, ey: bigint, ez: bigint, et: bigint) { + aCoordinate('x', ex) + aCoordinate('y', ey) + aCoordinate('z', ez, true) + aCoordinate('t', et) + this.ex = ex + this.ey = ey + this.ez = ez + this.et = et + Object.freeze(this) + } + + get x(): bigint { + return this.toAffine().x + } + get y(): bigint { + return this.toAffine().y + } + + static fromAffine(p: AffinePoint): Point { + if (p instanceof Point) throw new Error('extended point not allowed') + const { x, y } = p || {} + aCoordinate('x', x) + aCoordinate('y', y) + return new Point(x, y, _1n, modP(x * y)) + } + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.ez)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + // Not required for fromHex(), which always creates valid points. + // Could be useful for fromAffine(). + assertValidity(): void { + assertValidMemo(this) + } + + // Compare one point to another. + equals(other: Point): boolean { + aextpoint(other) + const { ex: X1, ey: Y1, ez: Z1 } = this + const { ex: X2, ey: Y2, ez: Z2 } = other + const X1Z2 = modP(X1 * Z2) + const X2Z1 = modP(X2 * Z1) + const Y1Z2 = modP(Y1 * Z2) + const Y2Z1 = modP(Y2 * Z1) + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 + } + + is0(): boolean { + return this.equals(Point.ZERO) + } + + negate(): Point { + // Flips point sign to a negative one (-x, y in affine coords) + return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) + } + + // Fast algo for doubling Extended Point. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd + // Cost: 4M + 4S + 1*a + 6add + 1*2. + double(): Point { + const { a } = CURVE + const { ex: X1, ey: Y1, ez: Z1 } = this + const A = modP(X1 * X1) // A = X12 + const B = modP(Y1 * Y1) // B = Y12 + const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 + const D = modP(a * A) // D = a*A + const x1y1 = X1 + Y1 + const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B + const G = D + B // G = D+B + const F = G - C // F = G-C + const H = D - B // H = D-B + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + + // Fast algo for adding 2 Extended Points. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd + // Cost: 9M + 1*a + 1*d + 7add. + add(other: Point) { + aextpoint(other) + const { a, d } = CURVE + const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this + const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other + const A = modP(X1 * X2) // A = X1*X2 + const B = modP(Y1 * Y2) // B = Y1*Y2 + const C = modP(T1 * d * T2) // C = T1*d*T2 + const D = modP(Z1 * Z2) // D = Z1*Z2 + const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B + const F = D - C // F = D-C + const G = D + C // G = D+C + const H = modP(B - a * A) // H = B-a*A + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + + subtract(other: Point): Point { + return this.add(other.negate()) + } + + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + // Constant-time multiplication. + multiply(scalar: bigint): Point { + const n = scalar + aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L + const { p, f } = this.wNAF(n) + return Point.normalizeZ([p, f])[0] + } + + // Non-constant-time multiplication. Uses double-and-add algorithm. + // It's faster, but should only be used when you don't care about + // an exposed private key e.g. sig verification. + // Does NOT allow scalars higher than CURVE.n. + // Accepts optional accumulator to merge with multiply (important for sparse scalars) + multiplyUnsafe(scalar: bigint, acc = Point.ZERO): Point { + const n = scalar + aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L + if (n === _0n) return I + if (this.is0() || n === _1n) return this + return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) + } + + // Checks if point is of small order. + // If you add something to small order point, you will have "dirty" + // point with torsion component. + // Multiplies point by cofactor and checks if the result is 0. + isSmallOrder(): boolean { + return this.multiplyUnsafe(cofactor).is0() + } + + // Multiplies point by curve order and checks if the result is 0. + // Returns `false` is the point is dirty. + isTorsionFree(): boolean { + return wnaf.unsafeLadder(this, CURVE_ORDER).is0() + } + + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + toAffine(iz?: bigint): AffinePoint { + return toAffineMemo(this, iz) + } + + clearCofactor(): Point { + const { h: cofactor } = CURVE + if (cofactor === _1n) return this + return this.multiplyUnsafe(cofactor) + } + + // Converts hash string or Uint8Array to Point. + // Uses algo from RFC8032 5.1.3. + static fromHex(hex: Hex, zip215 = false): Point { + const { d, a } = CURVE + const len = Fp.BYTES + hex = ensureBytes('pointHex', hex, len) // copy hex to a new array + abool('zip215', zip215) + const normed = hex.slice() // copy again, we'll manipulate it + const lastByte = hex[len - 1] // select last byte + normed[len - 1] = lastByte & ~0x80 // clear last bit + const y = bytesToNumberLE(normed) + + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // RFC8032 prohibits >= p, but ZIP215 doesn't + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + const max = zip215 ? MASK : Fp.ORDER + aInRange('pointHex.y', y, _0n, max) + + // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: + // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) + const y2 = modP(y * y) // denominator is always non-0 mod p. + const u = modP(y2 - _1n) // u = y² - 1 + const v = modP(d * y2 - a) // v = d y² + 1. + let { isValid, value: x } = uvRatio(u, v) // √(u/v) + if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') + const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper + const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1') + if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x + return Point.fromAffine({ x, y }) + } + static fromPrivateKey(privKey: Hex): Point { + const { scalar } = getPrivateScalar(privKey) + return G.multiply(scalar) // reduced one call of `toRawBytes` + } + toRawBytes(): Uint8Array { + const { x, y } = this.toAffine() + const bytes = numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) + bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y + return bytes // and use the last byte to encode sign of x + } + toHex(): string { + return bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. + } + } + const { BASE: G, ZERO: I } = Point + const wnaf = wNAF(Point, nByteLength * 8) + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + // Little-endian SHA512 with modulo n + function modN_LE(hash: Uint8Array): bigint { + return modN(bytesToNumberLE(hash)) + } + + // Get the hashed private scalar per RFC8032 5.1.5 + function getPrivateScalar(key: Hex) { + const len = Fp.BYTES + key = ensureBytes('private key', key, len) + // Hash private key with curve's hash function to produce uniformingly random input + // Check byte lengths: ensure(64, h(ensure(32, key))) + const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) + const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE + const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) + const scalar = modN_LE(head) // The actual private scalar + return { head, prefix, scalar } + } + + // Convenience method that creates public key from scalar. RFC8032 5.1.5 + function getExtendedPublicKey(key: Hex) { + const { head, prefix, scalar } = getPrivateScalar(key) + const point = G.multiply(scalar) // Point on Edwards curve aka public key + const pointBytes = point.toRawBytes() // Uint8Array representation + return { head, prefix, scalar, point, pointBytes } + } + + // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared + function getPublicKey(privKey: Hex): Uint8Array { + return getExtendedPublicKey(privKey).pointBytes + } + + // int('LE', SHA512(dom2(F, C) || msgs)) mod N + function hashDomainToScalar(context: Hex = Uint8Array.of(), ...msgs: Uint8Array[]) { + const msg = concatBytes(...msgs) + return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) + } + + /** Signs message with privateKey. RFC8032 5.1.6 */ + function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array { + msg = ensureBytes('message', msg) + if (prehash) msg = prehash(msg) // for ed25519ph etc. + const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) + const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) + const R = G.multiply(r).toRawBytes() // R = rG + const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) + const s = modN(r + k * scalar) // S = (r + k * s) mod L + aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l + const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES)) + return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature + } + + const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT + + /** + * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + * An extended group equation is checked. + */ + function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean { + const { context, zip215 } = options + const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. + msg = ensureBytes('message', msg) + publicKey = ensureBytes('publicKey', publicKey, len) + if (zip215 !== undefined) abool('zip215', zip215) + if (prehash) msg = prehash(msg) // for ed25519ph, etc + + const s = bytesToNumberLE(sig.slice(len, 2 * len)) + let A, R, SB + try { + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + A = Point.fromHex(publicKey, zip215) + R = Point.fromHex(sig.slice(0, len), zip215) + SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside + } catch (error) { + return false + } + if (!zip215 && A.isSmallOrder()) return false + + const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) + const RkA = R.add(A.multiplyUnsafe(k)) + // Extended group equation + // [8][S]B = [8]R + [8][k]A' + return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) + } + + G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. + + const utils = { + getExtendedPublicKey, + /** ed25519 priv keys are uniform 32b. No need to check for modulo bias, like in secp256k1. */ + randomPrivateKey: (): Uint8Array => randomBytes(Fp.BYTES), + + /** + * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT + * values. This slows down first getPublicKey() by milliseconds (see Speed section), + * but allows to speed-up subsequent getPublicKey() calls up to 20x. + * @param windowSize 2, 4, 8, 16 + */ + precompute(windowSize = 8, point: ExtPointType = Point.BASE): ExtPointType { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) + return point + }, + } + + return { + CURVE, + getPublicKey, + sign, + verify, + ExtendedPoint: Point, + utils, + } +} diff --git a/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts b/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts new file mode 100644 index 00000000000..c73b2993e94 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts @@ -0,0 +1,265 @@ +/** + * hash-to-curve from RFC 9380. + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * https://www.rfc-editor.org/rfc/rfc9380 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import type { AffinePoint, Group, GroupConstructor } from './curve.ts' +import { type IField, mod } from './modular.ts' +import type { CHash } from './utils.ts' +import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.ts' + +export type UnicodeOrBytes = string | Uint8Array + +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +export type Opts = { + DST: UnicodeOrBytes + p: bigint + m: number + k: number + expand: 'xmd' | 'xof' + hash: CHash +} + +// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. +const os2ip = bytesToNumberBE + +// Integer to Octet Stream (numberToBytesBE) +function i2osp(value: number, length: number): Uint8Array { + anum(value) + anum(length) + if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) + const res = Array.from({ length }).fill(0) as number[] + for (let i = length - 1; i >= 0; i--) { + res[i] = value & 0xff + value >>>= 8 + } + return new Uint8Array(res) +} + +function strxor(a: Uint8Array, b: Uint8Array): Uint8Array { + const arr = new Uint8Array(a.length) + for (let i = 0; i < a.length; i++) { + arr[i] = a[i] ^ b[i] + } + return arr +} + +function anum(item: unknown): void { + if (!Number.isSafeInteger(item)) throw new Error('number expected') +} + +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) + const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H + const ell = Math.ceil(lenInBytes / b_in_bytes) + if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') + 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) // len_in_bytes_str + const b = new Array(ell) + const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) + b[0] = 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] = H(concatBytes(...args)) + } + const pseudo_random_bytes = concatBytes(...b) + return pseudo_random_bytes.slice(0, lenInBytes) +} + +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); + if (DST.length > 255) { + const dkLen = Math.ceil((2 * k) / 8) + DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() + } + if (lenInBytes > 65535 || DST.length > 255) + throw new Error('expand_message_xof: invalid lenInBytes') + return ( + H.create({ dkLen: lenInBytes }) + .update(msg) + .update(i2osp(lenInBytes, 2)) + // 2. DST_prime = DST || I2OSP(len(DST), 1) + .update(DST) + .update(i2osp(DST.length, 1)) + .digest() + ) +} + +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] { + validateObject(options, { + DST: 'stringOrUint8Array', + p: 'bigint', + m: 'isSafeInteger', + k: 'isSafeInteger', + hash: 'hash', + }) + const { p, k, m, hash, expand, DST: _DST } = options + abytes(msg) + anum(count) + const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST + const log2p = p.toString(2).length + const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above + const len_in_bytes = count * m * L + let prb // pseudo_random_bytes + if (expand === 'xmd') { + prb = expand_message_xmd(msg, DST, len_in_bytes, hash) + } else if (expand === 'xof') { + prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) + } else if (expand === '_internal_pass') { + // for internal tests only + prb = msg + } else { + throw new Error('expand must be "xmd" or "xof"') + } + const u = new Array(count) + for (let i = 0; i < count; i++) { + const e = new Array(m) + for (let j = 0; j < m; j++) { + const elm_offset = L * (j + i * m) + const tv = prb.subarray(elm_offset, elm_offset + L) + e[j] = mod(os2ip(tv), p) + } + u[i] = e + } + return u +} + +export type XY = ( + x: T, + y: T, +) => { + x: T + y: T +} +export function isogenyMap>(field: F, map: [T[], T[], T[], T[]]): XY { + // Make same order as in spec + const COEFF = map.map((i) => Array.from(i).reverse()) + return (x: T, y: T) => { + const [xNum, xDen, yNum, yDen] = COEFF.map((val) => + val.reduce((acc, i) => field.add(field.mul(acc, x), i)), + ) + // 6.6.3 + // Exceptional cases of iso_map are inputs that cause the denominator of + // either rational function to evaluate to zero; such cases MUST return + // the identity point on E. + if (field.is0(xDen) || field.is0(yDen)) return { x: field.ZERO, y: field.ZERO } + x = field.div(xNum, xDen) // xNum / xDen + y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) + return { x: x, y: y } + } +} + +/** Point interface, which curves must implement to work correctly with the module. */ +export interface H2CPoint extends Group> { + add(rhs: H2CPoint): H2CPoint + toAffine(iz?: bigint): AffinePoint + clearCofactor(): H2CPoint + assertValidity(): void +} + +export interface H2CPointConstructor extends GroupConstructor> { + fromAffine(ap: AffinePoint): H2CPoint +} + +export type MapToCurve = (scalar: bigint[]) => AffinePoint + +// Separated from initialization opts, so users won't accidentally change per-curve parameters +// (changing DST is ok!) +export type htfBasicOpts = { DST: UnicodeOrBytes } +export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint +export type MapMethod = (scalars: bigint[]) => H2CPoint +export type Hasher = { + hashToCurve: HTFMethod + encodeToCurve: HTFMethod + mapToCurve: MapMethod + defaults: Opts & { encodeDST?: UnicodeOrBytes } +} + +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export function createHasher( + Point: H2CPointConstructor, + mapToCurve: MapToCurve, + defaults: Opts & { encodeDST?: UnicodeOrBytes }, +): Hasher { + if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') + return { + defaults, + + // Encodes byte string to elliptic curve. + // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + hashToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 2, { ...defaults, DST: defaults.DST, ...options } as Opts) + const u0 = Point.fromAffine(mapToCurve(u[0])) + const u1 = Point.fromAffine(mapToCurve(u[1])) + const P = u0.add(u1).clearCofactor() + P.assertValidity() + return P + }, + + // Encodes byte string to elliptic curve. + // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 1, { ...defaults, DST: defaults.encodeDST, ...options } as Opts) + const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() + P.assertValidity() + return P + }, + // Same as encodeToCurve, but without hash + mapToCurve(scalars: bigint[]): H2CPoint { + if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') + for (const i of scalars) + if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') + const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() + P.assertValidity() + return P + }, + } +} diff --git a/packages/noble-curves-tmp/src/abstract/modular.ts b/packages/noble-curves-tmp/src/abstract/modular.ts new file mode 100644 index 00000000000..8c0b703e745 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/modular.ts @@ -0,0 +1,555 @@ +/** + * Utils for modular division and finite fields. + * A finite field over 11 is integer number operations `mod 11`. + * There is no division: it is replaced by modular multiplicative inverse. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + bitMask, + bytesToNumberBE, + bytesToNumberLE, + ensureBytes, + numberToBytesBE, + numberToBytesLE, + validateObject, +} from './utils.ts' + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = /* @__PURE__ */ BigInt(2), + _3n = /* @__PURE__ */ BigInt(3) +// prettier-ignore +const _4n = /* @__PURE__ */ BigInt(4), + _5n = /* @__PURE__ */ BigInt(5), + _8n = /* @__PURE__ */ BigInt(8) +// prettier-ignore +const _9n = /* @__PURE__ */ BigInt(9), + _16n = /* @__PURE__ */ BigInt(16) + +// Calculates a modulo b +export function mod(a: bigint, b: bigint): bigint { + const result = a % b + return result >= _0n ? result : b + result +} +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export function pow(num: bigint, power: bigint, modulo: bigint): bigint { + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (modulo <= _0n) throw new Error('invalid modulus') + 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 +} + +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export function pow2(x: bigint, power: bigint, modulo: bigint): bigint { + let res = x + while (power-- > _0n) { + res *= res + res %= modulo + } + return res +} + +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export function invert(number: bigint, modulo: bigint): bigint { + if (number === _0n) throw new Error('invert: expected non-zero number') + if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) + // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. + let a = mod(number, modulo) + let b = modulo + // prettier-ignore + let x = _0n, + y = _1n, + u = _1n, + v = _0n + while (a !== _0n) { + // JIT applies optimization if those two lines follow each other + const q = b / a + const r = b % a + const m = x - u * q + const n = y - v * q + // prettier-ignore + ;(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) +} + +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export function tonelliShanks(P: bigint): (Fp: IField, n: T) => T { + // Legendre constant: used to calculate Legendre symbol (a | p), + // which denotes the value of a^((p-1)/2) (mod p). + // (a | p) ≡ 1 if a is a square (mod p) + // (a | p) ≡ -1 if a is not a square (mod p) + // (a | p) ≡ 0 if a ≡ 0 (mod p) + const legendreC = (P - _1n) / _2n + + let Q: bigint, S: number, Z: bigint + // Step 1: By factoring out powers of 2 from p - 1, + // find q and s such that p - 1 = q*(2^s) with q odd + for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); + + // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq + for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { + // Crash instead of infinity loop, we cannot reasonable count until P. + if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') + } + + // Fast-path + if (S === 1) { + const p1div4 = (P + _1n) / _4n + return function tonelliFast(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Slow-path + const Q1div2 = (Q + _1n) / _2n + return function tonelliSlow(Fp: IField, n: T): T { + // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 + if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') + let r = S + // TODO: will fail at Fp2/etc + let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b + let x = Fp.pow(n, Q1div2) // first guess at the square root + let b = Fp.pow(n, Q) // first guess at the fudge factor + + while (!Fp.eql(b, Fp.ONE)) { + if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) + // Find m such b^(2^m)==1 + let m = 1 + for (let t2 = Fp.sqr(b); m < r; m++) { + if (Fp.eql(t2, Fp.ONE)) break + t2 = Fp.sqr(t2) // t2 *= t2 + } + // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow + const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) + g = Fp.sqr(ge) // g = ge * ge + x = Fp.mul(x, ge) // x *= ge + b = Fp.mul(b, g) // b *= g + r = m + } + return x + } +} + +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export function FpSqrt(P: bigint): (Fp: IField, n: T) => T { + // P ≡ 3 (mod 4) + // √n = n^((P+1)/4) + if (P % _4n === _3n) { + // Not all roots possible! + // const ORDER = + // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; + // const NUM = 72057594037927816n; + const p1div4 = (P + _1n) / _4n + return function sqrt3mod4(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + // Throw if root**2 != n + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) + if (P % _8n === _5n) { + const c1 = (P - _5n) / _8n + return function sqrt5mod8(Fp: IField, n: T) { + const n2 = Fp.mul(n, _2n) + const v = Fp.pow(n2, c1) + const nv = Fp.mul(n, v) + const i = Fp.mul(Fp.mul(nv, _2n), v) + const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // P ≡ 9 (mod 16) + if (P % _16n === _9n) { + // NOTE: tonelli is too slow for bls-Fp2 calculations even on start + // Means we cannot use sqrt for constants at all! + // + // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F + // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F + // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F + // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic + // sqrt = (x) => { + // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 + // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 + // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 + // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 + // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x + // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x + // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x + // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x + // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x + // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 + // } + } + // Other cases: Tonelli-Shanks algorithm + return tonelliShanks(P) +} + +// Little-endian check for first LE bit (last BE bit); +export const isNegativeLE = (num: bigint, modulo: bigint): boolean => + (mod(num, modulo) & _1n) === _1n + +/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ +export interface IField { + ORDER: bigint + isLE: boolean + BYTES: number + BITS: number + MASK: bigint + ZERO: T + ONE: T + // 1-arg + create: (num: T) => T + isValid: (num: T) => boolean + is0: (num: T) => boolean + neg(num: T): T + inv(num: T): T + sqrt(num: T): T + sqr(num: T): T + // 2-args + eql(lhs: T, rhs: T): boolean + add(lhs: T, rhs: T): T + sub(lhs: T, rhs: T): T + mul(lhs: T, rhs: T | bigint): T + pow(lhs: T, power: bigint): T + div(lhs: T, rhs: T | bigint): T + // N for NonNormalized (for now) + addN(lhs: T, rhs: T): T + subN(lhs: T, rhs: T): T + mulN(lhs: T, rhs: T | bigint): T + sqrN(num: T): T + + // Optional + // Should be same as sgn0 function in + // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1). + // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway. + isOdd?(num: T): boolean // Odd instead of even since we have it for Fp2 + // legendre?(num: T): T; + pow(lhs: T, power: bigint): T + invertBatch: (lst: T[]) => T[] + toBytes(num: T): Uint8Array + fromBytes(bytes: Uint8Array): T + // If c is False, CMOV returns a, otherwise it returns b. + cmov(a: T, b: T, c: boolean): T +} +// prettier-ignore +const FIELD_FIELDS = [ + 'create', + 'isValid', + 'is0', + 'neg', + 'inv', + 'sqrt', + 'sqr', + 'eql', + 'add', + 'sub', + 'mul', + 'pow', + 'div', + 'addN', + 'subN', + 'mulN', + 'sqrN', +] as const +export function validateField(field: IField): IField { + const initial = { + ORDER: 'bigint', + MASK: 'bigint', + BYTES: 'isSafeInteger', + BITS: 'isSafeInteger', + } as Record + const opts = FIELD_FIELDS.reduce((map, val: string) => { + map[val] = 'function' + return map + }, initial) + return validateObject(field, opts) +} + +// Generic field functions + +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export function FpPow(f: IField, num: T, power: bigint): T { + // Should have same speed as pow for bigints + // TODO: benchmark! + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (power === _0n) return f.ONE + if (power === _1n) return num + let p = f.ONE + let d = num + while (power > _0n) { + if (power & _1n) p = f.mul(p, d) + d = f.sqr(d) + power >>= _1n + } + return p +} + +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export function FpInvertBatch(f: IField, nums: T[]): T[] { + const tmp = new Array(nums.length) + // Walk from first to last, multiply them by each other MOD p + const lastMultiplied = nums.reduce((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = acc + return f.mul(acc, num) + }, f.ONE) + // Invert last element + const inverted = f.inv(lastMultiplied) + // Walk from last to first, multiply them by inverted each other MOD p + nums.reduceRight((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = f.mul(acc, tmp[i]) + return f.mul(acc, num) + }, inverted) + return tmp +} + +export function FpDiv(f: IField, lhs: T, rhs: T | bigint): T { + return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) +} + +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export function FpLegendre(order: bigint): (f: IField, x: T) => T { + const legendreConst = (order - _1n) / _2n // Integer arithmetic + return (f: IField, x: T): T => f.pow(x, legendreConst) +} + +// This function returns True whenever the value x is a square in the field F. +export function FpIsSquare(f: IField): (x: T) => boolean { + const legendre = FpLegendre(f.ORDER) + return (x: T): boolean => { + const p = legendre(f, x) + return f.eql(p, f.ZERO) || f.eql(p, f.ONE) + } +} + +// CURVE.n lengths +export function nLength( + n: bigint, + nBitLength?: number, +): { + nBitLength: number + nByteLength: number +} { + // Bit size, byte size of CURVE.n + const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length + const nByteLength = Math.ceil(_nBitLength / 8) + return { nBitLength: _nBitLength, nByteLength } +} + +type FpField = IField & Required, 'isOdd'>> +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export function Field( + ORDER: bigint, + bitLen?: number, + isLE = false, + redef: Partial> = {}, +): Readonly { + if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) + const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) + if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') + let sqrtP: ReturnType // cached sqrtP + const f: Readonly = Object.freeze({ + ORDER, + isLE, + BITS, + BYTES, + MASK: bitMask(BITS), + ZERO: _0n, + ONE: _1n, + create: (num) => mod(num, ORDER), + isValid: (num) => { + if (typeof num !== 'bigint') + throw new Error('invalid field element: expected bigint, got ' + typeof num) + return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible + }, + is0: (num) => num === _0n, + isOdd: (num) => (num & _1n) === _1n, + neg: (num) => mod(-num, ORDER), + eql: (lhs, rhs) => lhs === rhs, + + sqr: (num) => mod(num * num, ORDER), + add: (lhs, rhs) => mod(lhs + rhs, ORDER), + sub: (lhs, rhs) => mod(lhs - rhs, ORDER), + mul: (lhs, rhs) => mod(lhs * rhs, ORDER), + pow: (num, power) => FpPow(f, num, power), + div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + + // Same as above, but doesn't normalize + sqrN: (num) => num * num, + addN: (lhs, rhs) => lhs + rhs, + subN: (lhs, rhs) => lhs - rhs, + mulN: (lhs, rhs) => lhs * rhs, + + inv: (num) => invert(num, ORDER), + sqrt: + redef.sqrt || + ((n) => { + if (!sqrtP) sqrtP = FpSqrt(ORDER) + return sqrtP(f, n) + }), + invertBatch: (lst) => FpInvertBatch(f, lst), + // TODO: do we really need constant cmov? + // We don't have const-time bigints anyway, so probably will be not very useful + cmov: (a, b, c) => (c ? b : a), + toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), + fromBytes: (bytes) => { + if (bytes.length !== BYTES) + throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) + return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) + }, + } as FpField) + return Object.freeze(f) +} + +export function FpSqrtOdd(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? root : Fp.neg(root) +} + +export function FpSqrtEven(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? Fp.neg(root) : root +} + +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export function hashToPrivateScalar( + hash: string | Uint8Array, + groupOrder: bigint, + isLE = false, +): bigint { + hash = ensureBytes('privateHash', hash) + const hashLen = hash.length + const minLen = nLength(groupOrder).nByteLength + 8 + if (minLen < 24 || hashLen < minLen || hashLen > 1024) + throw new Error( + 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, + ) + const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) + return mod(num, groupOrder - _1n) + _1n +} + +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export function getFieldBytesLength(fieldOrder: bigint): number { + if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') + const bitLength = fieldOrder.toString(2).length + return Math.ceil(bitLength / 8) +} + +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export function getMinHashLength(fieldOrder: bigint): number { + const length = getFieldBytesLength(fieldOrder) + return length + Math.ceil(length / 2) +} + +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array { + const len = key.length + const fieldLen = getFieldBytesLength(fieldOrder) + const minLen = getMinHashLength(fieldOrder) + // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. + if (len < 16 || len < minLen || len > 1024) + throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) + const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) + // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 + const reduced = mod(num, fieldOrder - _1n) + _1n + return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) +} diff --git a/packages/noble-curves-tmp/src/abstract/montgomery.ts b/packages/noble-curves-tmp/src/abstract/montgomery.ts new file mode 100644 index 00000000000..122406e3350 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/montgomery.ts @@ -0,0 +1,190 @@ +/** + * Montgomery curve methods. It's not really whole montgomery curve, + * just bunch of very specific methods for X25519 / X448 from + * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { mod, pow } from './modular.ts' +import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.ts' + +const _0n = BigInt(0) +const _1n = BigInt(1) +type Hex = string | Uint8Array + +export type CurveType = { + P: bigint // finite field prime + nByteLength: number + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + a: bigint + montgomeryBits: number + powPminus2?: (x: bigint) => bigint + xyToU?: (x: bigint, y: bigint) => bigint + Gu: bigint + randomBytes?: (bytesLength?: number) => Uint8Array +} + +export type CurveFn = { + scalarMult: (scalar: Hex, u: Hex) => Uint8Array + scalarMultBase: (scalar: Hex) => Uint8Array + getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array + getPublicKey: (privateKey: Hex) => Uint8Array + utils: { randomPrivateKey: () => Uint8Array } + GuBytes: Uint8Array +} + +function validateOpts(curve: CurveType) { + validateObject( + curve, + { + a: 'bigint', + }, + { + montgomeryBits: 'isSafeInteger', + nByteLength: 'isSafeInteger', + adjustScalarBytes: 'function', + domain: 'function', + powPminus2: 'function', + Gu: 'bigint', + }, + ) + // Set defaults + return Object.freeze({ ...curve } as const) +} + +// Uses only one coordinate instead of two +export function montgomery(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) + const { P } = CURVE + const modP = (n: bigint) => mod(n, P) + const montgomeryBits = CURVE.montgomeryBits + const montgomeryBytes = Math.ceil(montgomeryBits / 8) + const fieldLen = CURVE.nByteLength + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) + const powPminus2 = CURVE.powPminus2 || ((x: bigint) => pow(x, P - BigInt(2), P)) + + // cswap from RFC7748. But it is not from RFC7748! + /* + cswap(swap, x_2, x_3): + dummy = mask(swap) AND (x_2 XOR x_3) + x_2 = x_2 XOR dummy + x_3 = x_3 XOR dummy + Return (x_2, x_3) + Where mask(swap) is the all-1 or all-0 word of the same length as x_2 + and x_3, computed, e.g., as mask(swap) = 0 - swap. + */ + function cswap(swap: bigint, x_2: bigint, x_3: bigint): [bigint, bigint] { + const dummy = modP(swap * (x_2 - x_3)) + x_2 = modP(x_2 - dummy) + x_3 = modP(x_3 + dummy) + return [x_2, x_3] + } + + // x25519 from 4 + // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 + const a24 = (CURVE.a - BigInt(2)) / BigInt(4) + /** + * + * @param pointU u coordinate (x) on Montgomery Curve 25519 + * @param scalar by which the point would be multiplied + * @returns new Point on Montgomery curve + */ + function montgomeryLadder(u: bigint, scalar: bigint): bigint { + aInRange('u', u, _0n, P) + aInRange('scalar', scalar, _0n, P) + // Section 5: Implementations MUST accept non-canonical values and process them as + // if they had been reduced modulo the field prime. + const k = scalar + const x_1 = u + let x_2 = _1n + let z_2 = _0n + let x_3 = u + let z_3 = _1n + let swap = _0n + let sw: [bigint, bigint] + for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { + const k_t = (k >> t) & _1n + swap ^= k_t + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + swap = k_t + + const A = x_2 + z_2 + const AA = modP(A * A) + const B = x_2 - z_2 + const BB = modP(B * B) + const E = AA - BB + const C = x_3 + z_3 + const D = x_3 - z_3 + const DA = modP(D * A) + const CB = modP(C * B) + const dacb = DA + CB + const da_cb = DA - CB + x_3 = modP(dacb * dacb) + z_3 = modP(x_1 * modP(da_cb * da_cb)) + x_2 = modP(AA * BB) + z_2 = modP(E * (AA + modP(a24 * E))) + } + // (x_2, x_3) = cswap(swap, x_2, x_3) + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + // (z_2, z_3) = cswap(swap, z_2, z_3) + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + // z_2^(p - 2) + const z2 = powPminus2(z_2) + // Return x_2 * (z_2^(p - 2)) + return modP(x_2 * z2) + } + + function encodeUCoordinate(u: bigint): Uint8Array { + return numberToBytesLE(modP(u), montgomeryBytes) + } + + function decodeUCoordinate(uEnc: Hex): bigint { + // Section 5: When receiving such an array, implementations of X25519 + // MUST mask the most significant bit in the final byte. + const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) + if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 + return bytesToNumberLE(u) + } + function decodeScalar(n: Hex): bigint { + const bytes = ensureBytes('scalar', n) + const len = bytes.length + if (len !== montgomeryBytes && len !== fieldLen) { + let valid = '' + montgomeryBytes + ' or ' + fieldLen + throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) + } + return bytesToNumberLE(adjustScalarBytes(bytes)) + } + function scalarMult(scalar: Hex, u: Hex): Uint8Array { + const pointU = decodeUCoordinate(u) + const _scalar = decodeScalar(scalar) + const pu = montgomeryLadder(pointU, _scalar) + // The result was not contributory + // https://cr.yp.to/ecdh.html#validate + if (pu === _0n) throw new Error('invalid private or public key received') + return encodeUCoordinate(pu) + } + // Computes public key from private. By doing scalar multiplication of base point. + const GuBytes = encodeUCoordinate(CURVE.Gu) + function scalarMultBase(scalar: Hex): Uint8Array { + return scalarMult(scalar, GuBytes) + } + + return { + scalarMult, + scalarMultBase, + getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey), + getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey), + utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) }, + GuBytes: GuBytes, + } +} diff --git a/packages/noble-curves-tmp/src/abstract/poseidon.ts b/packages/noble-curves-tmp/src/abstract/poseidon.ts new file mode 100644 index 00000000000..6edaad90986 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/poseidon.ts @@ -0,0 +1,329 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { FpPow, type IField, validateField } from './modular.ts' +import { bitGet } from './utils.ts' + +// Grain LFSR (Linear-Feedback Shift Register): https://eprint.iacr.org/2009/109.pdf +function grainLFSR(state: number[]): () => boolean { + let pos = 0 + if (state.length !== 80) throw new Error('grainLFRS: wrong state length, should be 80 bits') + const getBit = (): boolean => { + const r = (offset: number) => state[(pos + offset) % 80] + const bit = r(62) ^ r(51) ^ r(38) ^ r(23) ^ r(13) ^ r(0) + state[pos] = bit + pos = ++pos % 80 + return !!bit + } + for (let i = 0; i < 160; i++) getBit() + return () => { + // https://en.wikipedia.org/wiki/Shrinking_generator + while (true) { + const b1 = getBit() + const b2 = getBit() + if (!b1) continue + return b2 + } + } +} + +export type PoseidonBasicOpts = { + Fp: IField + t: number // t = rate + capacity + roundsFull: number + roundsPartial: number + isSboxInverse?: boolean +} + +function validateBasicOpts(opts: PoseidonBasicOpts) { + const { Fp, roundsFull } = opts + validateField(Fp) + for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + if (opts.isSboxInverse !== undefined && typeof opts.isSboxInverse !== 'boolean') + throw new Error(`Poseidon: invalid param isSboxInverse=${opts.isSboxInverse}`) + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) +} + +function poseidonGrain(opts: PoseidonBasicOpts) { + validateBasicOpts(opts) + const { Fp } = opts + const state = Array(80).fill(1) + let pos = 0 + const writeBits = (value: bigint, bitCount: number) => { + for (let i = bitCount - 1; i >= 0; i--) state[pos++] = Number(bitGet(value, i)) + } + writeBits(1n, 2) // prime field + writeBits(opts.isSboxInverse ? 1n : 0n, 4) // b2..b5 + writeBits(BigInt(Fp.BITS), 12) // b6..b17 + writeBits(BigInt(opts.t), 12) // b18..b29 + writeBits(BigInt(opts.roundsFull), 10) // b30..b39 + writeBits(BigInt(opts.roundsPartial), 10) // b40..b49 + + const getBit = grainLFSR(state) + return (count: number, reject: boolean): bigint[] => { + const res: bigint[] = [] + for (let i = 0; i < count; i++) { + while (true) { + let num = 0n + for (let i = 0; i < Fp.BITS; i++) { + num <<= 1n + if (getBit()) num |= 1n + } + if (reject && num >= Fp.ORDER) continue // rejection sampling + res.push(Fp.create(num)) + break + } + } + return res + } +} + +export type PoseidonGrainOpts = PoseidonBasicOpts & { + sboxPower?: number +} + +type PoseidonConstants = { mds: bigint[][]; roundConstants: bigint[][] } + +// NOTE: this is not standard but used often for constant generation for poseidon +// (grain LFRS-like structure) +export function grainGenConstants(opts: PoseidonGrainOpts, skipMDS: number = 0): PoseidonConstants { + const { Fp, t, roundsFull, roundsPartial } = opts + const rounds = roundsFull + roundsPartial + const sample = poseidonGrain(opts) + const roundConstants: bigint[][] = [] + for (let r = 0; r < rounds; r++) roundConstants.push(sample(t, true)) + if (skipMDS > 0) for (let i = 0; i < skipMDS; i++) sample(2 * t, false) + const xs = sample(t, false) + const ys = sample(t, false) + // Construct MDS Matrix M[i][j] = 1 / (xs[i] + ys[j]) + const mds: bigint[][] = [] + for (let i = 0; i < t; i++) { + const row: bigint[] = [] + for (let j = 0; j < t; j++) { + const xy = Fp.add(xs[i], ys[j]) + if (Fp.is0(xy)) + throw new Error(`Error generating MDS matrix: xs[${i}] + ys[${j}] resulted in zero.`) + row.push(xy) + } + mds.push(Fp.invertBatch(row)) + } + + return { roundConstants, mds } +} + +export type PoseidonOpts = PoseidonBasicOpts & + PoseidonConstants & { + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark + } + +export function validateOpts(opts: PoseidonOpts): Readonly<{ + rounds: number + sboxFn: (n: bigint) => bigint + roundConstants: bigint[][] + mds: bigint[][] + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark +}> { + validateBasicOpts(opts) + const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts + const { roundsFull, roundsPartial, sboxPower, t } = opts + + // MDS is TxT matrix + if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') + const _mds = mds.map((mdsRow) => { + if (!Array.isArray(mdsRow) || mdsRow.length !== t) + throw new Error('invalid MDS matrix row: ' + mdsRow) + return mdsRow.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) + return Fp.create(i) + }) + }) + + if (rev !== undefined && typeof rev !== 'boolean') + throw new Error('invalid param reversePartialPowIdx=' + rev) + + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) + const rounds = roundsFull + roundsPartial + + if (!Array.isArray(rc) || rc.length !== rounds) + throw new Error('Poseidon: invalid round constants') + const roundConstants = rc.map((rc) => { + if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') + return rc.map((i) => { + if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') + return Fp.create(i) + }) + }) + + if (!sboxPower || ![3, 5, 7, 17].includes(sboxPower)) throw new Error('invalid sboxPower') + const _sboxPower = BigInt(sboxPower) + let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower) + // Unwrapped sbox power for common cases (195->142μs) + if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(n), n) + else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) + + return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) +} + +export function splitConstants(rc: bigint[], t: number): bigint[][] { + if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') + if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') + const res = [] + let tmp = [] + for (let i = 0; i < rc.length; i++) { + tmp.push(rc[i]) + if (tmp.length === t) { + res.push(tmp) + tmp = [] + } + } + return res +} + +/** Poseidon NTT-friendly hash. */ +export function poseidon(opts: PoseidonOpts): { + (values: bigint[]): bigint[] + // For verification in tests + roundConstants: bigint[][] +} { + const _opts = validateOpts(opts) + const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts + const halfRoundsFull = _opts.roundsFull / 2 + const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 + const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => { + values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) + + if (isFull) values = values.map((i) => sboxFn(i)) + else values[partialIdx] = sboxFn(values[partialIdx]) + // Matrix multiplication + values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) + return values + } + const poseidonHash = function poseidonHash(values: bigint[]) { + if (!Array.isArray(values) || values.length !== t) + throw new Error('invalid values, expected array of bigints with length ' + t) + values = values.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) + return Fp.create(i) + }) + let lastRound = 0 + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + // Apply r_p partial rounds. + for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + + if (lastRound !== totalRounds) throw new Error('invalid number of rounds') + return values + } + // For verification in tests + poseidonHash.roundConstants = roundConstants + return poseidonHash +} + +export class PoseidonSponge { + private Fp: IField + readonly rate: number + readonly capacity: number + readonly hash: ReturnType + private state: bigint[] // [...capacity, ...rate] + private pos = 0 + private isAbsorbing = true + + constructor( + Fp: IField, + rate: number, + capacity: number, + hash: ReturnType, + ) { + this.Fp = Fp + this.hash = hash + this.rate = rate + this.capacity = capacity + this.state = new Array(rate + capacity) + this.clean() + } + private process(): void { + this.state = this.hash(this.state) + } + absorb(input: bigint[]): void { + for (const i of input) + if (typeof i !== 'bigint' || !this.Fp.isValid(i)) throw new Error('invalid input: ' + i) + for (let i = 0; i < input.length; ) { + if (!this.isAbsorbing || this.pos === this.rate) { + this.process() + this.pos = 0 + this.isAbsorbing = true + } + const chunk = Math.min(this.rate - this.pos, input.length - i) + for (let j = 0; j < chunk; j++) { + const idx = this.capacity + this.pos++ + this.state[idx] = this.Fp.add(this.state[idx], input[i++]) + } + } + } + squeeze(count: number): bigint[] { + const res: bigint[] = [] + while (res.length < count) { + if (this.isAbsorbing || this.pos === this.rate) { + this.process() + this.pos = 0 + this.isAbsorbing = false + } + const chunk = Math.min(this.rate - this.pos, count - res.length) + for (let i = 0; i < chunk; i++) res.push(this.state[this.capacity + this.pos++]) + } + return res + } + clean(): void { + this.state.fill(this.Fp.ZERO) + this.isAbsorbing = true + this.pos = 0 + } + clone(): PoseidonSponge { + const c = new PoseidonSponge(this.Fp, this.rate, this.capacity, this.hash) + c.pos = this.pos + c.state = [...this.state] + return c + } +} + +export type PoseidonSpongeOpts = Omit & { + rate: number + capacity: number +} + +/** + * The method is not defined in spec, but nevertheless used often. + * Check carefully for compatibility: there are many edge cases, like absorbing an empty array. + * We cross-test against: + * - https://github.com/ProvableHQ/snarkVM/tree/staging/algorithms + * - https://github.com/arkworks-rs/crypto-primitives/tree/main + */ +export function poseidonSponge(opts: PoseidonSpongeOpts): () => PoseidonSponge { + for (const i of ['rate', 'capacity'] as const) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + const { rate, capacity } = opts + const t = opts.rate + opts.capacity + // Re-use hash instance between multiple instances + const hash = poseidon({ ...opts, t }) + const { Fp } = opts + return () => new PoseidonSponge(Fp, rate, capacity, hash) +} diff --git a/packages/noble-curves-tmp/src/abstract/tower.ts b/packages/noble-curves-tmp/src/abstract/tower.ts new file mode 100644 index 00000000000..4135dc08816 --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/tower.ts @@ -0,0 +1,664 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.ts' +import { bitLen, bitMask, concatBytes, notImplemented } from './utils.ts' +import type { ProjConstructor, ProjPointType } from './weierstrass.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +// Fp₂ over complex plane +export type BigintTuple = [bigint, bigint] +export type Fp = bigint +// Finite extension field over irreducible polynominal. +// Fp(u) / (u² - β) where β = -1 +export type Fp2 = { c0: bigint; c1: bigint } +export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] +export type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 } +export type Fp12 = { c0: Fp6; c1: Fp6 } // Fp₁₂ = Fp₆² => Fp₂³, Fp₆(w) / (w² - γ) where γ = v +// prettier-ignore +export type BigintTwelve = [ + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, +] + +export type Fp2Bls = mod.IField & { + reim: (num: Fp2) => { re: Fp; im: Fp } + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + fromBigTuple(num: [bigint, bigint]): Fp2 +} + +export type Fp12Bls = mod.IField & { + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + fromBigTwelve(num: BigintTwelve): Fp12 +} + +function calcFrobeniusCoefficients( + Fp: mod.IField, + nonResidue: T, + modulus: bigint, + degree: number, + num: number = 1, + divisor?: number, +) { + const _divisor = BigInt(divisor === undefined ? degree : divisor) + const towerModulus: any = modulus ** BigInt(degree) + const res: T[][] = [] + for (let i = 0; i < num; i++) { + const a = BigInt(i + 1) + const powers: T[] = [] + for (let j = 0, qPower = _1n; j < degree; j++) { + const power = ((a * qPower - a) / _divisor) % towerModulus + powers.push(Fp.pow(nonResidue, power)) + qPower *= modulus + } + res.push(powers) + } + return res +} + +// This works same at least for bls12-381, bn254 and bls12-377 +export function psiFrobenius( + Fp: mod.IField, + Fp2: Fp2Bls, + base: Fp2, +): { + psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] + psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] + G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType + G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType + PSI_X: Fp2 + PSI_Y: Fp2 + PSI2_X: Fp2 + PSI2_Y: Fp2 +} { + // Ψ endomorphism + const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) + const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) + function psi(x: Fp2, y: Fp2): [Fp2, Fp2] { + // This x10 faster than previous version in bls12-381 + const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) + const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) + return [x2, y2] + } + // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) + const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) + // This equals -1, which causes y to be Fp2.neg(y). + // But not sure if there are case when this is not true? + const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) + if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') + function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] { + return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] + } + // Map points + const mapAffine = + (fn: (x: T, y: T) => [T, T]) => + (c: ProjConstructor, P: ProjPointType) => { + const affine = P.toAffine() + const p = fn(affine.x, affine.y) + return c.fromAffine({ x: p[0], y: p[1] }) + } + const G2psi = mapAffine(psi) + const G2psi2 = mapAffine(psi2) + return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } +} + +export type Tower12Opts = { + ORDER: bigint + NONRESIDUE?: Fp + // Fp2 + FP2_NONRESIDUE: BigintTuple + Fp2sqrt?: (num: Fp2) => Fp2 + Fp2mulByB: (num: Fp2) => Fp2 + // Fp12 + Fp12cyclotomicSquare: (num: Fp12) => Fp12 + Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 + Fp12finalExponentiate: (num: Fp12) => Fp12 +} + +export function tower12(opts: Tower12Opts): { + Fp: Readonly & Required, 'isOdd'>>> + Fp2: mod.IField & { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + Fp6: mod.IField & { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 } + Fp12: mod.IField & { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } +} { + const { ORDER } = opts + // Fp + const Fp = mod.Field(ORDER) + const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) + const FpLegendre = mod.FpLegendre(ORDER) + const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 + + // Fp2 + const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] + const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.add(c0, r0), + c1: Fp.add(c1, r1), + }) + const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.sub(c0, r0), + c1: Fp.sub(c1, r1), + }) + const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => { + if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } + // (a+bi)(c+di) = (ac−bd) + (ad+bc)i + const { c0: r0, c1: r1 } = rhs + let t1 = Fp.mul(c0, r0) // c0 * o0 + let t2 = Fp.mul(c1, r1) // c1 * o1 + // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i + const o0 = Fp.sub(t1, t2) + const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) + return { c0: o0, c1: o1 } + } + const Fp2Square = ({ c0, c1 }: Fp2) => { + const a = Fp.add(c0, c1) + const b = Fp.sub(c0, c1) + const c = Fp.add(c0, c0) + return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } + } + type Fp2Utils = { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => { + if (tuple.length !== 2) throw new Error('invalid tuple') + const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp] + return { c0: fps[0], c1: fps[1] } + } + + const FP2_ORDER = ORDER * ORDER + const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) + const Fp2: mod.IField & Fp2Utils = { + ORDER: FP2_ORDER, + isLE: Fp.isLE, + NONRESIDUE: Fp2Nonresidue, + BITS: bitLen(FP2_ORDER), + BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), + MASK: bitMask(bitLen(FP2_ORDER)), + ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, + ONE: { c0: Fp.ONE, c1: Fp.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', + is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), + eql: ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => Fp.eql(c0, r0) && Fp.eql(c1, r1), + neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), + pow: (num, power) => mod.FpPow(Fp2, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), + // Normalized + add: Fp2Add, + sub: Fp2Subtract, + mul: Fp2Multiply, + sqr: Fp2Square, + // NonNormalized stuff + addN: Fp2Add, + subN: Fp2Subtract, + mulN: Fp2Multiply, + sqrN: Fp2Square, + // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? + div: (lhs, rhs) => + Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), + inv: ({ c0: a, c1: b }) => { + // We wish to find the multiplicative inverse of a nonzero + // element a + bu in Fp2. We leverage an identity + // + // (a + bu)(a - bu) = a² + b² + // + // which holds because u² = -1. This can be rewritten as + // + // (a + bu)(a - bu)/(a² + b²) = 1 + // + // because a² + b² = 0 has no nonzero solutions for (a, b). + // This gives that (a - bu)/(a² + b²) is the inverse + // of (a + bu). Importantly, this can be computing using + // only a single inversion in Fp. + const factor = Fp.inv(Fp.create(a * a + b * b)) + return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } + }, + sqrt: (num) => { + if (opts.Fp2sqrt) return opts.Fp2sqrt(num) + // This is generic for all quadratic extensions (Fp2) + const { c0, c1 } = num + if (Fp.is0(c1)) { + // if c0 is quadratic residue + if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) + else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) + } + const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) + let d = Fp.mul(Fp.add(a, c0), Fpdiv2) + const legendre = FpLegendre(Fp, d) + // -1, Quadratic non residue + if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) + const a0 = Fp.sqrt(d) + const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) + if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') + // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num + const x1 = candidateSqrt + const x2 = Fp2.neg(x1) + const { re: re1, im: im1 } = Fp2.reim(x1) + const { re: re2, im: im2 } = Fp2.reim(x2) + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 + return x2 + }, + // Same as sgn0_m_eq_2 in RFC 9380 + isOdd: (x: Fp2) => { + const { re: x0, im: x1 } = Fp2.reim(x) + const sign_0 = x0 % _2n + const zero_0 = x0 === _0n + const sign_1 = x1 % _2n + return BigInt(sign_0 || (zero_0 && sign_1)) == _1n + }, + // Bytes util + fromBytes(b: Uint8Array): Fp2 { + if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } + }, + toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp.cmov(c0, r0, c), + c1: Fp.cmov(c1, r1, c), + }), + reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), + // multiply by u + 1 + mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), + mulByB: opts.Fp2mulByB, + fromBigTuple: Fp2fromBigTuple, + frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({ + c0, + c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), + }), + } + // Fp6 + const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.add(c0, r0), + c1: Fp2.add(c1, r1), + c2: Fp2.add(c2, r2), + }) + const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.sub(c0, r0), + c1: Fp2.sub(c1, r1), + c2: Fp2.sub(c2, r2), + }) + const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => { + if (typeof rhs === 'bigint') { + return { + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + } + } + const { c0: r0, c1: r1, c2: r2 } = rhs + const t0 = Fp2.mul(c0, r0) // c0 * o0 + const t1 = Fp2.mul(c1, r1) // c1 * o1 + const t2 = Fp2.mul(c2, r2) // c2 * o2 + return { + // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) + c0: Fp2.add( + t0, + Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), + ), + // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) + c1: Fp2.add( + Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), + Fp2.mulByNonresidue(t2), + ), + // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 + c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), + } + } + const Fp6Square = ({ c0, c1, c2 }: Fp6) => { + let t0 = Fp2.sqr(c0) // c0² + let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 + let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 + let t4 = Fp2.sqr(c2) // c2² + return { + c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 + c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 + // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 + c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), + } + } + type Fp6Utils = { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + + const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 6, + 2, + 3, + ) + + const Fp6: mod.IField & Fp6Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp2.isLE, + BITS: 3 * Fp2.BITS, + BYTES: 3 * Fp2.BYTES, + MASK: bitMask(3 * Fp2.BITS), + ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, + ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, + create: (num) => num, + isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), + is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), + neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), + eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => + Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), + sqrt: notImplemented, + // Do we need division by bigint at all? Should be done via order: + div: (lhs, rhs) => + Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp6, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), + // Normalized + add: Fp6Add, + sub: Fp6Subtract, + mul: Fp6Multiply, + sqr: Fp6Square, + // NonNormalized stuff + addN: Fp6Add, + subN: Fp6Subtract, + mulN: Fp6Multiply, + sqrN: Fp6Square, + + inv: ({ c0, c1, c2 }) => { + let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) + let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 + let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 + // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) + let t4 = Fp2.inv( + Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), + ) + return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } + }, + // Bytes utils + fromBytes: (b: Uint8Array): Fp6 => { + if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), + c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), + c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), + } + }, + toBytes: ({ c0, c1, c2 }): Uint8Array => + concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), + cmov: ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6, c) => ({ + c0: Fp2.cmov(c0, r0, c), + c1: Fp2.cmov(c1, r1, c), + c2: Fp2.cmov(c2, r2, c), + }), + fromBigSix: (t: BigintSix): Fp6 => { + if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') + return { + c0: Fp2.fromBigTuple(t.slice(0, 2)), + c1: Fp2.fromBigTuple(t.slice(2, 4)), + c2: Fp2.fromBigTuple(t.slice(4, 6)), + } + }, + frobeniusMap: ({ c0, c1, c2 }, power: number) => ({ + c0: Fp2.frobeniusMap(c0, power), + c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + }), + mulByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({ + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + }), + mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), + // Sparse multiplication + mul1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({ + c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), + c1: Fp2.mul(c0, b1), + c2: Fp2.mul(c1, b1), + }), + // Sparse multiplication + mul01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 { + let t0 = Fp2.mul(c0, b0) // c0 * b0 + let t1 = Fp2.mul(c1, b1) // c1 * b1 + return { + // ((c1 + c2) * b1 - T1) * (u + 1) + T0 + c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), + // (b0 + b1) * (c0 + c1) - T0 - T1 + c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), + // (c0 + c2) * b0 - T0 + T1 + c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), + } + }, + } + + // Fp12 + const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 12, + 1, + 6, + )[0] + + const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.add(c0, r0), + c1: Fp6.add(c1, r1), + }) + const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.sub(c0, r0), + c1: Fp6.sub(c1, r1), + }) + const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => { + if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } + let { c0: r0, c1: r1 } = rhs + let t1 = Fp6.mul(c0, r0) // c0 * r0 + let t2 = Fp6.mul(c1, r1) // c1 * r1 + return { + c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v + // (c0 + c1) * (r0 + r1) - (T1 + T2) + c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), + } + } + const Fp12Square = ({ c0, c1 }: Fp12) => { + let ab = Fp6.mul(c0, c1) // c0 * c1 + return { + // (c1 * v + c0) * (c0 + c1) - AB - AB * v + c0: Fp6.sub( + Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), + Fp6.mulByNonresidue(ab), + ), + c1: Fp6.add(ab, ab), + } // AB + AB + } + function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } { + const a2 = Fp2.sqr(a) + const b2 = Fp2.sqr(b) + return { + first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² + second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² + } + } + type Fp12Utils = { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } + + const Fp12: mod.IField & Fp12Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp6.isLE, + BITS: 2 * Fp6.BITS, + BYTES: 2 * Fp6.BYTES, + MASK: bitMask(2 * Fp6.BITS), + ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, + ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), + is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), + neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), + sqrt: notImplemented, + inv: ({ c0, c1 }) => { + let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) + return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w + }, + div: (lhs, rhs) => + Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp12, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), + // Normalized + add: Fp12Add, + sub: Fp12Subtract, + mul: Fp12Multiply, + sqr: Fp12Square, + // NonNormalized stuff + addN: Fp12Add, + subN: Fp12Subtract, + mulN: Fp12Multiply, + sqrN: Fp12Square, + + // Bytes utils + fromBytes: (b: Uint8Array): Fp12 => { + if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), + c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), + } + }, + toBytes: ({ c0, c1 }): Uint8Array => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp6.cmov(c0, r0, c), + c1: Fp6.cmov(c1, r1, c), + }), + // Utils + // toString() { + // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); + // }, + // fromTuple(c: [Fp6, Fp6]) { + // return new Fp12(...c); + // } + fromBigTwelve: (t: BigintTwelve): Fp12 => ({ + c0: Fp6.fromBigSix(t.slice(0, 6) as BigintSix), + c1: Fp6.fromBigSix(t.slice(6, 12) as BigintSix), + }), + // Raises to q**i -th power + frobeniusMap(lhs, power: number) { + const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] + return { + c0: Fp6.frobeniusMap(lhs.c0, power), + c1: Fp6.create({ + c0: Fp2.mul(c0, coeff), + c1: Fp2.mul(c1, coeff), + c2: Fp2.mul(c2, coeff), + }), + } + }, + mulByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({ + c0: Fp6.mulByFp2(c0, rhs), + c1: Fp6.mulByFp2(c1, rhs), + }), + conjugate: ({ c0, c1 }): Fp12 => ({ c0, c1: Fp6.neg(c1) }), + // Sparse multiplication + mul014: ({ c0, c1 }, o0: Fp2, o1: Fp2, o4: Fp2) => { + let t0 = Fp6.mul01(c0, o0, o1) + let t1 = Fp6.mul1(c1, o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 + // (c1 + c0) * [o0, o1+o4] - T0 - T1 + c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), + } + }, + mul034: ({ c0, c1 }, o0: Fp2, o3: Fp2, o4: Fp2) => { + const a = Fp6.create({ + c0: Fp2.mul(c0.c0, o0), + c1: Fp2.mul(c0.c1, o0), + c2: Fp2.mul(c0.c2, o0), + }) + const b = Fp6.mul01(c1, o3, o4) + const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(b), a), + c1: Fp6.sub(e, Fp6.add(a, b)), + } + }, + + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + _cyclotomicSquare: opts.Fp12cyclotomicSquare, + _cyclotomicExp: opts.Fp12cyclotomicExp, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + finalExponentiate: opts.Fp12finalExponentiate, + } + + return { Fp, Fp2, Fp6, Fp4Square, Fp12 } +} diff --git a/packages/noble-curves-tmp/src/abstract/utils.ts b/packages/noble-curves-tmp/src/abstract/utils.ts new file mode 100644 index 00000000000..de81eaef58b --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/utils.ts @@ -0,0 +1,378 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ + +// 100 lines of code in the file are duplicated from noble-hashes (utils). +// This is OK: `abstract` directory does not use noble-hashes. +// User may opt-in into using different hashing library. This way, noble-hashes +// won't be included into their bundle. +const _0n = /* @__PURE__ */ BigInt(0) +const _1n = /* @__PURE__ */ BigInt(1) +export type Hex = Uint8Array | string // hex strings are accepted for simplicity +export type PrivKey = Hex | bigint // bigints are accepted to ease learning curve +export type CHash = { + (message: Uint8Array | string): Uint8Array + blockLen: number + outputLen: number + create(opts?: { dkLen?: number }): any // For shake +} +export type FHash = (message: Uint8Array | string) => Uint8Array + +export function isBytes(a: unknown): a is Uint8Array { + return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') +} + +export function abytes(item: unknown): void { + if (!isBytes(item)) throw new Error('Uint8Array expected') +} + +export function abool(title: string, value: boolean): void { + if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) +} + +export function numberToHexUnpadded(num: number | bigint): string { + const hex = num.toString(16) + return hex.length & 1 ? '0' + hex : hex +} + +export function hexToNumber(hex: string): bigint { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian +} + +// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex +const hasHexBuiltin: boolean = + // @ts-ignore + typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function' + +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) + +/** + * Convert byte array to hex string. Uses built-in function, when available. + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export function bytesToHex(bytes: Uint8Array): string { + abytes(bytes) + // @ts-ignore + if (hasHexBuiltin) return bytes.toHex() + // pre-caching improves the speed 6x + let hex = '' + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]] + } + return hex +} + +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const +function asciiToBase16(ch: number): number | undefined { + if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 + if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) + if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) + return +} + +/** + * Convert hex string to byte array. Uses built-in function, when available. + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export function hexToBytes(hex: string): Uint8Array { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + // @ts-ignore + if (hasHexBuiltin) return Uint8Array.fromHex(hex) + const hl = hex.length + const al = hl / 2 + if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) + const array = new Uint8Array(al) + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)) + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1] + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) + } + array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 + } + return array +} + +// BE: Big Endian, LE: Little Endian +export function bytesToNumberBE(bytes: Uint8Array): bigint { + return hexToNumber(bytesToHex(bytes)) +} +export function bytesToNumberLE(bytes: Uint8Array): bigint { + abytes(bytes) + return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) +} + +export function numberToBytesBE(n: number | bigint, len: number): Uint8Array { + return hexToBytes(n.toString(16).padStart(len * 2, '0')) +} +export function numberToBytesLE(n: number | bigint, len: number): Uint8Array { + return numberToBytesBE(n, len).reverse() +} +// Unpadded, rarely used +export function numberToVarBytesBE(n: number | bigint): Uint8Array { + return hexToBytes(numberToHexUnpadded(n)) +} + +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array { + let res: Uint8Array + if (typeof hex === 'string') { + try { + res = hexToBytes(hex) + } catch (e) { + throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) + } + } else if (isBytes(hex)) { + // Uint8Array.from() instead of hash.slice() because node.js Buffer + // is instance of Uint8Array, and its slice() creates **mutable** copy + res = Uint8Array.from(hex) + } else { + throw new Error(title + ' must be hex string or Uint8Array') + } + const len = res.length + if (typeof expectedLength === 'number' && len !== expectedLength) + throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) + return res +} + +/** + * Copies several Uint8Arrays into one. + */ +export function concatBytes(...arrays: Uint8Array[]): Uint8Array { + let sum = 0 + for (let i = 0; i < arrays.length; i++) { + const a = arrays[i] + abytes(a) + sum += a.length + } + const res = new Uint8Array(sum) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const a = arrays[i] + res.set(a, pad) + pad += a.length + } + return res +} + +// Compares 2 u8a-s in kinda constant time +export function equalBytes(a: Uint8Array, b: Uint8Array): boolean { + if (a.length !== b.length) return false + let diff = 0 + for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] + return diff === 0 +} + +// Global symbols in both browsers and Node.js since v11 +// See https://github.com/microsoft/TypeScript/issues/31535 +declare const TextEncoder: any + +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export function utf8ToBytes(str: string): Uint8Array { + if (typeof str !== 'string') throw new Error('string expected') + return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 +} + +// Is positive bigint +const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n + +export function inRange(n: bigint, min: bigint, max: bigint): boolean { + return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max +} + +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void { + // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? + // consider P=256n, min=0n, max=P + // - a for min=0 would require -1: `inRange('x', x, -1n, P)` + // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` + // - our way is the cleanest: `inRange('x', x, 0n, P) + if (!inRange(n, min, max)) + throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) +} + +// Bit operations + +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export function bitLen(n: bigint): number { + let len + for (len = 0; n > _0n; n >>= _1n, len += 1); + return len +} + +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export function bitGet(n: bigint, pos: number): bigint { + return (n >> BigInt(pos)) & _1n +} + +/** + * Sets single bit at position. + */ +export function bitSet(n: bigint, pos: number, value: boolean): bigint { + return n | ((value ? _1n : _0n) << BigInt(pos)) +} + +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n + +// DRBG + +const u8n = (len: number) => new Uint8Array(len) // creates Uint8Array +const u8fr = (arr: ArrayLike) => Uint8Array.from(arr) // another shortcut +type Pred = (v: Uint8Array) => T | undefined +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export function createHmacDrbg( + hashLen: number, + qByteLen: number, + hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, +): (seed: Uint8Array, predicate: Pred) => T { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') + if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0 // Iterations counter, will throw when over 1000 + const reset = () => { + v.fill(1) + k.fill(0) + i = 0 + } + const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) + const reseed = (seed = u8n(0)) => { + // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) + v = h() // v = hmac(k || v) + if (seed.length === 0) return + k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) + v = h() // v = hmac(k || v) + } + const gen = () => { + // HMAC-DRBG generate() function + if (i++ >= 1000) throw new Error('drbg: tried 1000 values') + let len = 0 + const out: Uint8Array[] = [] + while (len < qByteLen) { + v = h() + const sl = v.slice() + out.push(sl) + len += v.length + } + return concatBytes(...out) + } + const genUntil = (seed: Uint8Array, pred: Pred): T => { + reset() + reseed(seed) // Steps D-G + let res: T | undefined = undefined // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed() + reset() + return res + } + return genUntil +} + +// Validating curves and fields + +const validatorFns = { + bigint: (val: any): boolean => typeof val === 'bigint', + function: (val: any): boolean => typeof val === 'function', + boolean: (val: any): boolean => typeof val === 'boolean', + string: (val: any): boolean => typeof val === 'string', + stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val), + isSafeInteger: (val: any): boolean => Number.isSafeInteger(val), + array: (val: any): boolean => Array.isArray(val), + field: (val: any, object: any): any => (object as any).Fp.isValid(val), + hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen), +} as const +type Validator = keyof typeof validatorFns +type ValMap> = { [K in keyof T]?: Validator } +// type Record = { [P in K]: T; } + +export function validateObject>( + object: T, + validators: ValMap, + optValidators: ValMap = {}, +): T { + const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => { + const checkVal = validatorFns[type] + if (typeof checkVal !== 'function') throw new Error('invalid validator function') + + const val = object[fieldName as keyof typeof object] + if (isOptional && val === undefined) return + if (!checkVal(val, object)) { + throw new Error( + 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, + ) + } + } + for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false) + for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true) + return object +} +// validate type tests +// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; +// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! +// // Should fail type-check +// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); +// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); +// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); +// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); + +/** + * throws not implemented error + */ +export const notImplemented = (): never => { + throw new Error('not implemented') +} + +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export function memoized( + fn: (arg: T, ...args: O) => R, +): (arg: T, ...args: O) => R { + const map = new WeakMap() + return (arg: T, ...args: O): R => { + const val = map.get(arg) + if (val !== undefined) return val + const computed = fn(arg, ...args) + map.set(arg, computed) + return computed + } +} diff --git a/packages/noble-curves-tmp/src/abstract/weierstrass.ts b/packages/noble-curves-tmp/src/abstract/weierstrass.ts new file mode 100644 index 00000000000..b713756adbe --- /dev/null +++ b/packages/noble-curves-tmp/src/abstract/weierstrass.ts @@ -0,0 +1,1419 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Parameters + * + * To initialize a weierstrass curve, one needs to pass following params: + * + * * a: formula param + * * b: formula param + * * Fp: finite Field over which we'll do calculations. Can be complex (Fp2, Fp12) + * * n: Curve prime subgroup order, total count of valid points in the field + * * Gx: Base point (x, y) aka generator point x coordinate + * * Gy: ...y coordinate + * * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order) + * * lowS: whether to enable (default) or disable "low-s" non-malleable signatures + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// prettier-ignore +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.ts' +// prettier-ignore +import { + Field, + type IField, + getMinHashLength, + invert, + mapHashToField, + mod, + validateField, +} from './modular.ts' +// prettier-ignore +import { + type CHash, + type Hex, + type PrivKey, + aInRange, + abool, + bitMask, + bytesToHex, + bytesToNumberBE, + concatBytes, + createHmacDrbg, + ensureBytes, + hexToBytes, + inRange, + isBytes, + memoized, + numberToBytesBE, + numberToHexUnpadded, + validateObject, +} from './utils.ts' + +export type { AffinePoint } +type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array +type EndomorphismOpts = { + beta: bigint + splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint } +} +export type BasicWCurve = BasicCurve & { + // Params: a, b + a: T + b: T + + // Optional params + allowedPrivateKeyLengths?: readonly number[] // for P521 + wrapPrivateKey?: boolean // bls12-381 requires mod(n) instead of rejecting keys >= n + endo?: EndomorphismOpts // Endomorphism options for Koblitz curves + // When a cofactor != 1, there can be an effective methods to: + // 1. Determine whether a point is torsion-free + isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean + // 2. Clear torsion component + clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType +} + +export type Entropy = Hex | boolean +export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean } +export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined } + +function validateSigVerOpts(opts: SignOpts | VerOpts) { + if (opts.lowS !== undefined) abool('lowS', opts.lowS) + if (opts.prehash !== undefined) abool('prehash', opts.prehash) +} + +// Instance for 3d XYZ points +export interface ProjPointType extends Group> { + readonly px: T + readonly py: T + readonly pz: T + get x(): T + get y(): T + toAffine(iz?: T): AffinePoint + toHex(isCompressed?: boolean): string + toRawBytes(isCompressed?: boolean): Uint8Array + + assertValidity(): void + hasEvenY(): boolean + multiplyUnsafe(scalar: bigint): ProjPointType + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined + isTorsionFree(): boolean + clearCofactor(): ProjPointType + _setWindowSize(windowSize: number): void +} +// Static methods for 3d XYZ points +export interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType + fromAffine(p: AffinePoint): ProjPointType + fromHex(hex: Hex): ProjPointType + fromPrivateKey(privateKey: PrivKey): ProjPointType + normalizeZ(points: ProjPointType[]): ProjPointType[] + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType +} + +export type CurvePointsType = BasicWCurve & { + // Bytes + fromBytes?: (bytes: Uint8Array) => AffinePoint + toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array +} + +export type CurvePointsTypeWithLength = Readonly< + CurvePointsType & { nByteLength: number; nBitLength: number } +> + +function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength { + const opts = validateBasic(curve) + validateObject( + opts, + { + a: 'field', + b: 'field', + }, + { + allowedPrivateKeyLengths: 'array', + wrapPrivateKey: 'boolean', + isTorsionFree: 'function', + clearCofactor: 'function', + allowInfinityPoint: 'boolean', + fromBytes: 'function', + toBytes: 'function', + }, + ) + const { endo, Fp, a } = opts + if (endo) { + if (!Fp.eql(a, Fp.ZERO)) { + throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') + } + if ( + typeof endo !== 'object' || + typeof endo.beta !== 'bigint' || + typeof endo.splitScalar !== 'function' + ) { + throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') + } + } + return Object.freeze({ ...opts } as const) +} + +export type CurvePointsRes = { + CURVE: ReturnType> + ProjectivePoint: ProjConstructor + normPrivateKeyToScalar: (key: PrivKey) => bigint + weierstrassEquation: (x: T) => T + isWithinCurveOrder: (num: bigint) => boolean +} + +export class DERErr extends Error { + constructor(m = '') { + super(m) + } +} +export type IDER = { + // asn.1 DER encoding utils + Err: typeof DERErr + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string) => string + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } + } + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string + decode(data: Uint8Array): bigint + } + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } + hexFromSig(sig: { r: bigint; s: bigint }): string +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export const DER: IDER = { + // asn.1 DER encoding utils + Err: DERErr, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string): string => { + const { Err: E } = DER + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length & 1) throw new E('tlv.encode: unpadded data') + const dataLen = data.length / 2 + const len = numberToHexUnpadded(dataLen) + if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big') + // length of length with long form flag + const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '' + const t = numberToHexUnpadded(tag) + return t + lenLen + len + data + }, + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } { + const { Err: E } = DER + let pos = 0 + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') + const first = data[pos++] + const isLong = !!(first & 0b1000_0000) // First bit of first length byte is flag for short/long form + let length = 0 + if (!isLong) length = first + else { + // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] + const lenLen = first & 0b0111_1111 + if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') + if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js + const lengthBytes = data.subarray(pos, pos + lenLen) + if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') + if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') + for (const b of lengthBytes) length = (length << 8) | b + pos += lenLen + if (length < 128) throw new E('tlv.decode(long): not minimal encoding') + } + const v = data.subarray(pos, pos + length) + if (v.length !== length) throw new E('tlv.decode: wrong value length') + return { v, l: data.subarray(pos + length) } + }, + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string { + const { Err: E } = DER + if (num < _0n) throw new E('integer: negative integers are not allowed') + let hex = numberToHexUnpadded(num) + // Pad with zero byte if negative flag is present + if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex + if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') + return hex + }, + decode(data: Uint8Array): bigint { + const { Err: E } = DER + if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative') + if (data[0] === 0x00 && !(data[1] & 0b1000_0000)) + throw new E('invalid signature integer: unnecessary leading zero') + return bytesToNumberBE(data) + }, + }, + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { + // parse DER signature + const { Err: E, _int: int, _tlv: tlv } = DER + const data = ensureBytes('signature', hex) + const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) + if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) + const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) + if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + return { r: int.decode(rBytes), s: int.decode(sBytes) } + }, + hexFromSig(sig: { r: bigint; s: bigint }): string { + const { _tlv: tlv, _int: int } = DER + const rs = tlv.encode(0x02, int.encode(sig.r)) + const ss = tlv.encode(0x02, int.encode(sig.s)) + const seq = rs + ss + return tlv.encode(0x30, seq) + }, +} + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +export function weierstrassPoints(opts: CurvePointsType): CurvePointsRes { + const CURVE = validatePointOpts(opts) + const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ + const Fn = Field(CURVE.n, CURVE.nBitLength) + + const toBytes = + CURVE.toBytes || + ((_c: ProjConstructor, point: ProjPointType, _isCompressed: boolean) => { + const a = point.toAffine() + return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) + }) + const fromBytes = + CURVE.fromBytes || + ((bytes: Uint8Array) => { + // const head = bytes[0]; + const tail = bytes.subarray(1) + // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + }) + + /** + * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y². + * @returns y² + */ + function weierstrassEquation(x: T): T { + const { a, b } = CURVE + const x2 = Fp.sqr(x) // x * x + const x3 = Fp.mul(x2, x) // x2 * x + return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b + } + // Validate whether the passed curve params are valid. + // We check if curve equation works for generator point. + // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. + // ProjectivePoint class has not been initialized yet. + if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) + throw new Error('bad generator point: equation left != right') + + // Valid group elements reside in range 1..n-1 + function isWithinCurveOrder(num: bigint): boolean { + return inRange(num, _1n, CURVE.n) + } + // Validates if priv key is valid and converts it to bigint. + // Supports options allowedPrivateKeyLengths and wrapPrivateKey. + function normPrivateKeyToScalar(key: PrivKey): bigint { + const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE + if (lengths && typeof key !== 'bigint') { + if (isBytes(key)) key = bytesToHex(key) + // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes + if (typeof key !== 'string' || !lengths.includes(key.length)) + throw new Error('invalid private key') + key = key.padStart(nByteLength * 2, '0') + } + let num: bigint + try { + num = + typeof key === 'bigint' + ? key + : bytesToNumberBE(ensureBytes('private key', key, nByteLength)) + } catch (error) { + throw new Error( + 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, + ) + } + if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS + aInRange('private key', num, _1n, N) // num in range [1..N-1] + return num + } + + function aprjpoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') + } + + // Memoized toAffine / validity check. They are heavy. Points are immutable. + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint => { + const { px: x, py: y, pz: z } = p + // Fast-path for normalized points + if (Fp.eql(z, Fp.ONE)) return { x, y } + const is0 = p.is0() + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 1. + if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) + const ax = Fp.mul(x, iz) + const ay = Fp.mul(y, iz) + const zz = Fp.mul(z, iz) + if (is0) return { x: Fp.ZERO, y: Fp.ZERO } + if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + // NOTE: on exception this will crash 'cached' and no value will be set. + // Otherwise true will be return + const assertValidMemo = memoized((p: Point) => { + if (p.is0()) { + // (0, 1, 0) aka ZERO is invalid in most contexts. + // In BLS, ZERO can be serialized, so we allow it. + // (0, 0, 0) is invalid representation of ZERO. + if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return + throw new Error('bad point: ZERO') + } + // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` + const { x, y } = p.toAffine() + // Check if x, y are valid field elements + if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') + const left = Fp.sqr(y) // y² + const right = weierstrassEquation(x) // x³ + ax + b + if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') + if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') + return true + }) + + /** + * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) + * Default Point works in 2d / affine coordinates: (x, y) + * We're doing calculations in projective, because its operations don't require costly inversion. + */ + class Point implements ProjPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) + static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) // 0, 1, 0 + readonly px: T + readonly py: T + readonly pz: T + + constructor(px: T, py: T, pz: T) { + if (px == null || !Fp.isValid(px)) throw new Error('x required') + if (py == null || !Fp.isValid(py) || Fp.is0(py)) throw new Error('y required') + if (pz == null || !Fp.isValid(pz)) throw new Error('z required') + this.px = px + this.py = py + this.pz = pz + Object.freeze(this) + } + + // Does not validate if the point is on-curve. + // Use fromHex instead, or call assertValidity() later. + static fromAffine(p: AffinePoint): Point { + const { x, y } = p || {} + if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') + if (p instanceof Point) throw new Error('projective point not allowed') + const is0 = (i: T) => Fp.eql(i, Fp.ZERO) + // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) + if (is0(x) && is0(y)) return Point.ZERO + return new Point(x, y, Fp.ONE) + } + + get x(): T { + return this.toAffine().x + } + get y(): T { + return this.toAffine().y + } + + /** + * Takes a bunch of Projective Points but executes only one + * inversion on all of them. Inversion is very slow operation, + * so this improves performance massively. + * Optimization: converts a list of projective points to a list of identical points with Z=1. + */ + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.pz)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + + /** + * Converts hash string or Uint8Array to Point. + * @param hex short/long ECDSA hex + */ + static fromHex(hex: Hex): Point { + const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) + P.assertValidity() + return P + } + + // Multiplies generator point by privateKey. + static fromPrivateKey(privateKey: PrivKey) { + return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) + } + + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + + // A point on curve is valid if it conforms to equation. + assertValidity(): void { + assertValidMemo(this) + } + + hasEvenY(): boolean { + const { y } = this.toAffine() + if (Fp.isOdd) return !Fp.isOdd(y) + throw new Error("Field doesn't support isOdd") + } + + /** + * Compare one point to another. + */ + equals(other: Point): boolean { + aprjpoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) + const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) + return U1 && U2 + } + + /** + * Flips point to one corresponding to (x, -y) in Affine coordinates. + */ + negate(): Point { + return new Point(this.px, Fp.neg(this.py), this.pz) + } + + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a, b } = CURVE + const b3 = Fp.mul(b, _3n) + const { px: X1, py: Y1, pz: Z1 } = this + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + let t0 = Fp.mul(X1, X1) // step 1 + let t1 = Fp.mul(Y1, Y1) + let t2 = Fp.mul(Z1, Z1) + let t3 = Fp.mul(X1, Y1) + t3 = Fp.add(t3, t3) // step 5 + Z3 = Fp.mul(X1, Z1) + Z3 = Fp.add(Z3, Z3) + X3 = Fp.mul(a, Z3) + Y3 = Fp.mul(b3, t2) + Y3 = Fp.add(X3, Y3) // step 10 + X3 = Fp.sub(t1, Y3) + Y3 = Fp.add(t1, Y3) + Y3 = Fp.mul(X3, Y3) + X3 = Fp.mul(t3, X3) + Z3 = Fp.mul(b3, Z3) // step 15 + t2 = Fp.mul(a, t2) + t3 = Fp.sub(t0, t2) + t3 = Fp.mul(a, t3) + t3 = Fp.add(t3, Z3) + Z3 = Fp.add(t0, t0) // step 20 + t0 = Fp.add(Z3, t0) + t0 = Fp.add(t0, t2) + t0 = Fp.mul(t0, t3) + Y3 = Fp.add(Y3, t0) + t2 = Fp.mul(Y1, Z1) // step 25 + t2 = Fp.add(t2, t2) + t0 = Fp.mul(t2, t3) + X3 = Fp.sub(X3, t0) + Z3 = Fp.mul(t2, t1) + Z3 = Fp.add(Z3, Z3) // step 30 + Z3 = Fp.add(Z3, Z3) + return new Point(X3, Y3, Z3) + } + + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(other: Point): Point { + aprjpoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + const a = CURVE.a + const b3 = Fp.mul(CURVE.b, _3n) + let t0 = Fp.mul(X1, X2) // step 1 + let t1 = Fp.mul(Y1, Y2) + let t2 = Fp.mul(Z1, Z2) + let t3 = Fp.add(X1, Y1) + let t4 = Fp.add(X2, Y2) // step 5 + t3 = Fp.mul(t3, t4) + t4 = Fp.add(t0, t1) + t3 = Fp.sub(t3, t4) + t4 = Fp.add(X1, Z1) + let t5 = Fp.add(X2, Z2) // step 10 + t4 = Fp.mul(t4, t5) + t5 = Fp.add(t0, t2) + t4 = Fp.sub(t4, t5) + t5 = Fp.add(Y1, Z1) + X3 = Fp.add(Y2, Z2) // step 15 + t5 = Fp.mul(t5, X3) + X3 = Fp.add(t1, t2) + t5 = Fp.sub(t5, X3) + Z3 = Fp.mul(a, t4) + X3 = Fp.mul(b3, t2) // step 20 + Z3 = Fp.add(X3, Z3) + X3 = Fp.sub(t1, Z3) + Z3 = Fp.add(t1, Z3) + Y3 = Fp.mul(X3, Z3) + t1 = Fp.add(t0, t0) // step 25 + t1 = Fp.add(t1, t0) + t2 = Fp.mul(a, t2) + t4 = Fp.mul(b3, t4) + t1 = Fp.add(t1, t2) + t2 = Fp.sub(t0, t2) // step 30 + t2 = Fp.mul(a, t2) + t4 = Fp.add(t4, t2) + t0 = Fp.mul(t1, t4) + Y3 = Fp.add(Y3, t0) + t0 = Fp.mul(t5, t4) // step 35 + X3 = Fp.mul(t3, X3) + X3 = Fp.sub(X3, t0) + t0 = Fp.mul(t3, t1) + Z3 = Fp.mul(t5, Z3) + Z3 = Fp.add(Z3, t0) // step 40 + return new Point(X3, Y3, Z3) + } + + subtract(other: Point) { + return this.add(other.negate()) + } + + is0() { + return this.equals(Point.ZERO) + } + + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed private key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(sc: bigint): Point { + const { endo, n: N } = CURVE + aInRange('scalar', sc, _0n, N) + const I = Point.ZERO + if (sc === _0n) return I + if (this.is0() || sc === _1n) return this + + // Case a: no endomorphism. Case b: has precomputes. + if (!endo || wnaf.hasPrecomputes(this)) + return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) + + // Case c: endomorphism + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) + let k1p = I + let k2p = I + let d: Point = this + while (k1 > _0n || k2 > _0n) { + if (k1 & _1n) k1p = k1p.add(d) + if (k2 & _1n) k2p = k2p.add(d) + d = d.double() + k1 >>= _1n + k2 >>= _1n + } + if (k1neg) k1p = k1p.negate() + if (k2neg) k2p = k2p.negate() + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + return k1p.add(k2p) + } + + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(scalar: bigint): Point { + const { endo, n: N } = CURVE + aInRange('scalar', scalar, _1n, N) + let point: Point, fake: Point // Fake point is used to const-time mult + if (endo) { + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) + let { p: k1p, f: f1p } = this.wNAF(k1) + let { p: k2p, f: f2p } = this.wNAF(k2) + k1p = wnaf.constTimeNegate(k1neg, k1p) + k2p = wnaf.constTimeNegate(k2neg, k2p) + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + point = k1p.add(k2p) + fake = f1p.add(f2p) + } else { + const { p, f } = this.wNAF(scalar) + point = p + fake = f + } + // Normalize `z` for both points, but return only real one + return Point.normalizeZ([point, fake])[0] + } + + /** + * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. + * Not using Strauss-Shamir trick: precomputation tables are faster. + * The trick could be useful if both P and Q are not G (not in our case). + * @returns non-zero affine point + */ + multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { + const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes + const mul = ( + P: Point, + a: bigint, // Select faster multiply() method + ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) + const sum = mul(this, a).add(mul(Q, b)) + return sum.is0() ? undefined : sum + } + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + toAffine(iz?: T): AffinePoint { + return toAffineMemo(this, iz) + } + isTorsionFree(): boolean { + const { h: cofactor, isTorsionFree } = CURVE + if (cofactor === _1n) return true // No subgroups, always torsion-free + if (isTorsionFree) return isTorsionFree(Point, this) + throw new Error('isTorsionFree() has not been declared for the elliptic curve') + } + clearCofactor(): Point { + const { h: cofactor, clearCofactor } = CURVE + if (cofactor === _1n) return this // Fast-path + if (clearCofactor) return clearCofactor(Point, this) as Point + return this.multiplyUnsafe(CURVE.h) + } + + toRawBytes(isCompressed = true): Uint8Array { + abool('isCompressed', isCompressed) + this.assertValidity() + return toBytes(Point, this, isCompressed) + } + + toHex(isCompressed = true): string { + abool('isCompressed', isCompressed) + return bytesToHex(this.toRawBytes(isCompressed)) + } + } + const _bits = CURVE.nBitLength + const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) + // Validate if generator point is on curve + return { + CURVE, + ProjectivePoint: Point as ProjConstructor, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } +} + +// Instance +export interface SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + assertValidity(): void + addRecoveryBit(recovery: number): RecoveredSignatureType + hasHighS(): boolean + normalizeS(): SignatureType + recoverPublicKey(msgHash: Hex): ProjPointType + toCompactRawBytes(): Uint8Array + toCompactHex(): string + toDERRawBytes(isCompressed?: boolean): Uint8Array + toDERHex(isCompressed?: boolean): string +} +export type RecoveredSignatureType = SignatureType & { + readonly recovery: number +} +// Static methods +export type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType + fromCompact(hex: Hex): SignatureType + fromDER(hex: Hex): SignatureType +} +type SignatureLike = { r: bigint; s: bigint } + +export type PubKey = Hex | ProjPointType + +export type CurveType = BasicWCurve & { + hash: CHash // CHash not FHash because we need outputLen for DRBG + hmac: HmacFnSync + randomBytes: (bytesLength?: number) => Uint8Array + lowS?: boolean + bits2int?: (bytes: Uint8Array) => bigint + bits2int_modN?: (bytes: Uint8Array) => bigint +} + +function validateOpts( + curve: CurveType, +): Readonly { + const opts = validateBasic(curve) + validateObject( + opts, + { + hash: 'hash', + hmac: 'function', + randomBytes: 'function', + }, + { + bits2int: 'function', + bits2int_modN: 'function', + lowS: 'boolean', + }, + ) + return Object.freeze({ lowS: true, ...opts } as const) +} + +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType + verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean + ProjectivePoint: ProjConstructor + Signature: SignatureConstructor + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint + isValidPrivateKey(privateKey: PrivKey): boolean + randomPrivateKey: () => Uint8Array + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType + } +} + +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export function weierstrass(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { Fp, n: CURVE_ORDER } = CURVE + const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 + const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + function invN(a: bigint) { + return invert(a, CURVE_ORDER) + } + + const { + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } = weierstrassPoints({ + ...CURVE, + toBytes(_c, point, isCompressed: boolean): Uint8Array { + const a = point.toAffine() + const x = Fp.toBytes(a.x) + const cat = concatBytes + abool('isCompressed', isCompressed) + if (isCompressed) { + return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) + } else { + return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) + } + }, + fromBytes(bytes: Uint8Array) { + const len = bytes.length + const head = bytes[0] + const tail = bytes.subarray(1) + // this.assertValidity() is done inside of fromHex + if (len === compressedLen && (head === 0x02 || head === 0x03)) { + const x = bytesToNumberBE(tail) + if (!inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') + const y2 = weierstrassEquation(x) // y² = x³ + ax + b + let y: bigint + try { + y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 + } catch (sqrtError) { + const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' + throw new Error('Point is not on curve' + suffix) + } + const isYOdd = (y & _1n) === _1n + // ECDSA + const isHeadOdd = (head & 1) === 1 + if (isHeadOdd !== isYOdd) y = Fp.neg(y) + return { x, y } + } else if (len === uncompressedLen && head === 0x04) { + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + } else { + const cl = compressedLen + const ul = uncompressedLen + throw new Error( + 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, + ) + } + }, + }) + const numToNByteHex = (num: bigint): string => bytesToHex(numberToBytesBE(num, CURVE.nByteLength)) + + function isBiggerThanHalfOrder(number: bigint) { + const HALF = CURVE_ORDER >> _1n + return number > HALF + } + + function normalizeS(s: bigint) { + return isBiggerThanHalfOrder(s) ? modN(-s) : s + } + // slice bytes num + const slcNum = (b: Uint8Array, from: number, to: number) => bytesToNumberBE(b.slice(from, to)) + + /** + * ECDSA signature with its (r, s) properties. Supports DER & compact representations. + */ + class Signature implements SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + constructor(r: bigint, s: bigint, recovery?: number) { + aInRange('r', r, _1n, CURVE_ORDER) // r in [1..N] + aInRange('s', s, _1n, CURVE_ORDER) // s in [1..N] + this.r = r + this.s = s + if (recovery != null) this.recovery = recovery + Object.freeze(this) + } + + // pair (bytes of r, bytes of s) + static fromCompact(hex: Hex) { + const l = CURVE.nByteLength + hex = ensureBytes('compactSignature', hex, l * 2) + return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) + } + + // DER encoded ECDSA signature + // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script + static fromDER(hex: Hex) { + const { r, s } = DER.toSig(ensureBytes('DER', hex)) + return new Signature(r, s) + } + + /** + * @todo remove + * @deprecated + */ + assertValidity(): void {} + + addRecoveryBit(recovery: number): RecoveredSignature { + return new Signature(this.r, this.s, recovery) as RecoveredSignature + } + + recoverPublicKey(msgHash: Hex): typeof Point.BASE { + const { r, s, recovery: rec } = this + const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash + if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') + const radj = rec === 2 || rec === 3 ? r + CURVE.n : r + if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') + const prefix = (rec & 1) === 0 ? '02' : '03' + const R = Point.fromHex(prefix + numToNByteHex(radj)) + const ir = invN(radj) // r^-1 + const u1 = modN(-h * ir) // -hr^-1 + const u2 = modN(s * ir) // sr^-1 + const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) + if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked + Q.assertValidity() + return Q + } + + // Signatures should be low-s, to prevent malleability. + hasHighS(): boolean { + return isBiggerThanHalfOrder(this.s) + } + + normalizeS() { + return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this + } + + // DER-encoded + toDERRawBytes() { + return hexToBytes(this.toDERHex()) + } + toDERHex() { + return DER.hexFromSig({ r: this.r, s: this.s }) + } + + // padded bytes of r, then padded bytes of s + toCompactRawBytes() { + return hexToBytes(this.toCompactHex()) + } + toCompactHex() { + return numToNByteHex(this.r) + numToNByteHex(this.s) + } + } + type RecoveredSignature = Signature & { recovery: number } + + const utils = { + isValidPrivateKey(privateKey: PrivKey) { + try { + normPrivateKeyToScalar(privateKey) + return true + } catch (error) { + return false + } + }, + normPrivateKeyToScalar: normPrivateKeyToScalar, + + /** + * Produces cryptographically secure private key from random of size + * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. + */ + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(CURVE.n) + return mapHashToField(CURVE.randomBytes(length), CURVE.n) + }, + + /** + * Creates precompute table for an arbitrary EC point. Makes point "cached". + * Allows to massively speed-up `point.multiply(scalar)`. + * @returns cached point + * @example + * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); + * fast.multiply(privKey); // much faster ECDH now + */ + precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here + return point + }, + } + + /** + * Computes public key for a private key. Checks for validity of the private key. + * @param privateKey private key + * @param isCompressed whether to return compact (default), or full key + * @returns Public key, full when isCompressed=false; short when isCompressed=true + */ + function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array { + return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) + } + + /** + * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. + */ + function isProbPub(item: PrivKey | PubKey): boolean { + const arr = isBytes(item) + const str = typeof item === 'string' + const len = (arr || str) && (item as Hex).length + if (arr) return len === compressedLen || len === uncompressedLen + if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen + if (item instanceof Point) return true + return false + } + + /** + * ECDH (Elliptic Curve Diffie Hellman). + * Computes shared public key from private key and public key. + * Checks: 1) private key validity 2) shared key is on-curve. + * Does NOT hash the result. + * @param privateA private key + * @param publicB different public key + * @param isCompressed whether to return compact (default), or full key + * @returns shared public key + */ + function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array { + if (isProbPub(privateA)) throw new Error('first arg must be private key') + if (!isProbPub(publicB)) throw new Error('second arg must be public key') + const b = Point.fromHex(publicB) // check for being on-curve + return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) + } + + // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. + // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. + // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. + // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors + const bits2int = + CURVE.bits2int || + function (bytes: Uint8Array): bigint { + // Our custom check "just in case" + if (bytes.length > 8192) throw new Error('input is too large') + // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) + // for some cases, since bytes.length * 8 is not actual bitLength. + const num = bytesToNumberBE(bytes) // check for == u8 done here + const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits + return delta > 0 ? num >> BigInt(delta) : num + } + const bits2int_modN = + CURVE.bits2int_modN || + function (bytes: Uint8Array): bigint { + return modN(bits2int(bytes)) // can't use bytesToNumberBE here + } + // NOTE: pads output with zero as per spec + const ORDER_MASK = bitMask(CURVE.nBitLength) + /** + * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. + */ + function int2octets(num: bigint): Uint8Array { + aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) + // works with order, can have different size than numToField! + return numberToBytesBE(num, CURVE.nByteLength) + } + + // Steps A, D of RFC6979 3.2 + // Creates RFC6979 seed; converts msg/privKey to numbers. + // Used only in sign, not in verify. + // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, + // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 + function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) { + if (['recovered', 'canonical'].some((k) => k in opts)) + throw new Error('sign() legacy options not supported') + const { hash, randomBytes } = CURVE + let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default + if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash + msgHash = ensureBytes('msgHash', msgHash) + validateSigVerOpts(opts) + if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) + + // We can't later call bits2octets, since nested bits2int is broken for curves + // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. + // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) + const h1int = bits2int_modN(msgHash) + const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint + const seedArgs = [int2octets(d), int2octets(h1int)] + // extraEntropy. RFC6979 3.6: additional k' (optional). + if (ent != null && ent !== false) { + // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is + seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes + } + const seed = concatBytes(...seedArgs) // Step D of RFC6979 3.2 + const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! + // Converts signature params into point w r/s, checks result for validity. + function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined { + // RFC 6979 Section 3.2, step 3: k = bits2int(T) + const k = bits2int(kBytes) // Cannot use fields methods, since it is group element + if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N + const ik = invN(k) // k^-1 mod n + const q = Point.BASE.multiply(k).toAffine() // q = Gk + const r = modN(q.x) // r = q.x mod n + if (r === _0n) return + // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to + // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: + // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT + const s = modN(ik * modN(m + r * d)) // Not using blinding here + if (s === _0n) return + let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) + let normS = s + if (lowS && isBiggerThanHalfOrder(s)) { + normS = normalizeS(s) // if lowS was passed, ensure s is always + recovery ^= 1 // // in the bottom half of N + } + return new Signature(r, normS, recovery) as RecoveredSignature // use normS, not s + } + return { seed, k2sig } + } + const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false } + const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false } + + /** + * Signs message hash with a private key. + * ``` + * sign(m, d, k) where + * (x, y) = G × k + * r = x mod n + * s = (m + dr)/k mod n + * ``` + * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. + * @param privKey private key + * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. + * @returns signature with recovery param + */ + function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature { + const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. + const C = CURVE + const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) + return drbg(seed, k2sig) // Steps B, C, D, E, F, G + } + + // Enable precomputes. Slows down first publicKey computation by 20ms. + Point.BASE._setWindowSize(8) + // utils.precompute(8, ProjectivePoint.BASE) + + /** + * Verifies a signature against message hash and public key. + * Rejects lowS signatures by default: to override, + * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: + * + * ``` + * verify(r, s, h, P) where + * U1 = hs^-1 mod n + * U2 = rs^-1 mod n + * R = U1⋅G - U2⋅P + * mod(R.x, n) == r + * ``` + */ + function verify( + signature: Hex | SignatureLike, + msgHash: Hex, + publicKey: Hex, + opts = defaultVerOpts, + ): boolean { + const sg = signature + msgHash = ensureBytes('msgHash', msgHash) + publicKey = ensureBytes('publicKey', publicKey) + const { lowS, prehash, format } = opts + + // Verify opts, deduce signature format + validateSigVerOpts(opts) + if ('strict' in opts) throw new Error('options.strict was renamed to lowS') + if (format !== undefined && format !== 'compact' && format !== 'der') + throw new Error('format must be compact or der') + const isHex = typeof sg === 'string' || isBytes(sg) + const isObj = + !isHex && + !format && + typeof sg === 'object' && + sg !== null && + typeof sg.r === 'bigint' && + typeof sg.s === 'bigint' + if (!isHex && !isObj) + throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') + + let _sig: Signature | undefined = undefined + let P: ProjPointType + try { + if (isObj) _sig = new Signature(sg.r, sg.s) + if (isHex) { + // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). + // Since DER can also be 2*nByteLength bytes, we check for it first. + try { + if (format !== 'compact') _sig = Signature.fromDER(sg) + } catch (derError) { + if (!(derError instanceof DER.Err)) throw derError + } + if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) + } + P = Point.fromHex(publicKey) + } catch (error) { + return false + } + if (!_sig) return false + if (lowS && _sig.hasHighS()) return false + if (prehash) msgHash = CURVE.hash(msgHash) + const { r, s } = _sig + const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element + const is = invN(s) // s^-1 + const u1 = modN(h * is) // u1 = hs^-1 mod n + const u2 = modN(r * is) // u2 = rs^-1 mod n + const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P + if (!R) return false + const v = modN(R.x) + return v === r + } + return { + CURVE, + getPublicKey, + getSharedSecret, + sign, + verify, + ProjectivePoint: Point, + Signature, + utils, + } +} + +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export function SWUFpSqrtRatio( + Fp: IField, + Z: T, +): (u: T, v: T) => { isValid: boolean; value: T } { + // Generic implementation + const q = Fp.ORDER + let l = _0n + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n + const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. + // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. + // 2n ** c1 == 2n << (c1-1) + const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) + const _2n_pow_c1 = _2n_pow_c1_1 * _2n + const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 + const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) + let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { + let tv1 = c6 // 1. tv1 = c6 + let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 + let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 + tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v + let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 + tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 + tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 + tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v + tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u + let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 + tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 + let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 + tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 + tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) + // 17. for i in (c1, c1 - 1, ..., 2): + for (let i = c1; i > _1n; i--) { + let tv5 = i - _2n // 18. tv5 = i - 2 + tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 + let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 + const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 + tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 + tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 + tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) + } + return { isValid: isQR, value: tv3 } + } + if (Fp.ORDER % _4n === _3n) { + // sqrt_ratio_3mod4(u, v) + const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) + sqrtRatio = (u: T, v: T) => { + let tv1 = Fp.sqr(v) // 1. tv1 = v^2 + const tv2 = Fp.mul(u, v) // 2. tv2 = u * v + tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 + let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 + y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 + const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 + const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v + const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u + let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) + return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 + } + } + // No curves uses that + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 + return sqrtRatio +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export function mapToCurveSimpleSWU( + Fp: IField, + opts: { + A: T + B: T + Z: T + }, +): (u: T) => { x: T; y: T } { + validateField(Fp) + if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) + throw new Error('mapToCurveSimpleSWU: invalid opts') + const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) + if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') + // Input: u, an element of F. + // Output: (x, y), a point on E. + return (u: T): { x: T; y: T } => { + // prettier-ignore + let tv1, tv2, tv3, tv4, tv5, tv6, x, y + tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 + tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 + tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 + tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 + tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 + tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) + tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 + tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 + tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 + tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 + tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 + tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 + tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 + tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 + tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 + x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 + const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 + y = Fp.mul(y, value) // 20. y = y * y1 + x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) + y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) + const e1 = Fp.isOdd!(u) === Fp.isOdd!(y) // 23. e1 = sgn0(u) == sgn0(y) + y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) + x = Fp.div(x, tv4) // 25. x = x / tv4 + return { x, y } + } +} diff --git a/packages/noble-curves-tmp/src/bls12-381.ts b/packages/noble-curves-tmp/src/bls12-381.ts new file mode 100644 index 00000000000..5c0232a8ec4 --- /dev/null +++ b/packages/noble-curves-tmp/src/bls12-381.ts @@ -0,0 +1,774 @@ +/** + * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: + * * Construct zk-SNARKs at the ~120-bit security + * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: + * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr + * + * ### Summary + * 1. BLS Relies on Bilinear Pairing (expensive) + * 2. Private Keys: 32 bytes + * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. + * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. + * - The signature is a point on the G2 subgroup, which is defined over a finite field + * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the + * complex numbers). + * - We also support reversed 96-byte pubkeys & 48-byte short signatures. + * 5. The 12 stands for the Embedding degree. + * + * ### Formulas + * - `P = pk x G` - public keys + * - `S = pk x H(m)` - signing + * - `e(P, H(m)) == e(G, S)` - verification using pairings + * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation + * + * ### Compatibility and notes + * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. + * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. + * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". + * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) + * 4. Compatible with specs: + * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), + * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), + * RFC 9380. + * + * ### Params + * To verify curve parameters, see + * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). + * Basic math is done over finite fields over p. + * More complicated math is done over polynominal extension fields. + * To simplify calculations in Fp12, we construct extension tower: + * + * Embedding degree (k): 12 + * Seed (X): -15132376222941642752 + * Fr: (x⁴-x²+1) + * Fp: ((x-1)² ⋅ r(x)/3+x) + * (E/Fp): Y²=X³+4 + * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) + * Ate loop size: X + * + * ### Towers + * - Fp₁₂ = Fp₆² => Fp₂³ + * - Fp(u) / (u² - β) where β = -1 + * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 + * - Fp₆(w) / (w² - γ) where γ = v + * - Fp²[u] = Fp/u²+1 + * - Fp⁶[v] = Fp²/v³-1-u + * - Fp¹²[w] = Fp⁶/w²-v + * + * @todo construct bls & bn fp/fr from seed. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFn, bls } from './abstract/bls.ts' +// Types +import { isogenyMap } from './abstract/hash-to-curve.ts' +import { Field } from './abstract/modular.ts' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' +import { psiFrobenius, tower12 } from './abstract/tower.ts' +import { + type Hex, + bitGet, + bitLen, + bytesToHex, + bytesToNumberBE, + concatBytes as concatB, + ensureBytes, + numberToBytesBE, +} from './abstract/utils.ts' +import { + type AffinePoint, + type ProjPointType, + mapToCurveSimpleSWU, +} from './abstract/weierstrass.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! +const BLS_X = BigInt('0xd201000000010000') +const BLS_X_LEN = bitLen(BLS_X) + +// CURVE FIELDS +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + // Order of Fp + ORDER: BigInt( + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', + ), + // Finite extension field over irreducible polynominal. + // Fp(u) / (u² - β) where β = -1 + FP2_NONRESIDUE: [_1n, _1n], + Fp2mulByB: ({ c0, c1 }) => { + const t0 = Fp.mul(c0, _4n) // 4 * c0 + const t1 = Fp.mul(c1, _4n) // 4 * c1 + // (T0-T1) + (T0+T1)*i + return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } + }, + // Fp12 + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const x = BLS_X + // this^(q⁶) / this + const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) + // t0^(q²) * t0 + const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) + const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) + const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) + const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) + const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) + const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) + const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) + const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) + const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) + const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) + const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) + // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 + return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) + }, +}) + +// Finite field over r. +// This particular field is not used anywhere in bls12-381, but it is still useful. +const Fr = Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) + +// END OF CURVE FIELDS + +// HashToCurve + +// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 +const isogenyMapG2 = isogenyMap( + Fp2, + [ + // xNum + [ + [ + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + ], + [ + '0x0', + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', + ], + [ + '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', + '0x0', + ], + ], + // xDen + [ + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', + ], + [ + '0xc', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', + ], + ['0x1', '0x0'], // LAST 1 + ], + // yNum + [ + [ + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + ], + [ + '0x0', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', + ], + [ + '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', + '0x0', + ], + ], + // yDen + [ + [ + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + ], + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', + ], + [ + '0x12', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', + ], + ['0x1', '0x0'], // LAST 1 + ], + ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))) as [Fp2[], Fp2[], Fp2[], Fp2[]], +) +// 11-isogeny map from E' to E +const isogenyMapG1 = isogenyMap( + Fp, + [ + // xNum + [ + '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', + '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', + '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', + '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', + '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', + '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', + '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', + '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', + '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', + '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', + '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', + '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', + ], + // xDen + [ + '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', + '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', + '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', + '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', + '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', + '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', + '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', + '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', + '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', + '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', + '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', + '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', + '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', + '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', + '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', + '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', + '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', + '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', + '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', + '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', + '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', + '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', + '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', + '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', + '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', + ], + // yDen + [ + '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', + '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', + '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', + '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', + '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', + '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', + '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', + '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', + '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', + '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', + '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', + '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', + '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', + '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', + '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]], +) + +// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i +const G2_SWU = mapToCurveSimpleSWU(Fp2, { + A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I + B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) + Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) +}) +// Optimized SWU Map - Fp to G1 +const G1_SWU = mapToCurveSimpleSWU(Fp, { + A: Fp.create( + BigInt( + '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', + ), + ), + B: Fp.create( + BigInt( + '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', + ), + ), + Z: Fp.create(BigInt(11)), +}) + +// Endomorphisms (for fast cofactor clearing) +// Ψ(P) endomorphism +const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) + +// Default hash_to_field options are for hash to G2. +// +// Parameter definitions are in section 5.3 of the spec unless otherwise noted. +// Parameter values come from section 8.8.2 of the spec. +// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 +// +// Base field F is GF(p^m) +// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +// m = 2 (or 1 for G1 see section 8.8.1) +// k = 128 +const htfDefaults = Object.freeze({ + // DST: a domain separation tag + // defined in section 2.2.5 + // Use utils.getDSTLabel(), utils.setDSTLabel(value) + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + // p: the characteristic of F + // where F is a finite field of characteristic p and order q = p^m + p: Fp.ORDER, + // m: the extension degree of F, m >= 1 + // where F is a finite field of characteristic p and order q = p^m + m: 2, + // k: the target security level for the suite in bits + // defined in section 5.1 + k: 128, + // option to use a message that has already been processed by + // expand_message_xmd + expand: 'xmd', + // Hash functions for: expand_message_xmd is appropriate for use with a + // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. + // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 + hash: sha256, +} as const) + +// Encoding utils +// Point on G1 curve: (x, y) + +// Compressed point of infinity +const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits + +function parseMask(bytes: Uint8Array) { + // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. + bytes = bytes.slice() + const mask = bytes[0] & 0b1110_0000 + const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) + const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) + const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) + bytes[0] &= 0b0001_1111 // clear mask (zero first 3 bits) + return { compressed, infinity, sort, value: bytes } +} + +function setMask( + bytes: Uint8Array, + mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }, +) { + if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask') + if (mask.compressed) bytes[0] |= 0b1000_0000 + if (mask.infinity) bytes[0] |= 0b0100_0000 + if (mask.sort) bytes[0] |= 0b0010_0000 + return bytes +} + +function signatureG1ToRawBytes(point: ProjPointType) { + point.assertValidity() + const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) + const { x, y } = point.toAffine() + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) +} + +function signatureG2ToRawBytes(point: ProjPointType) { + // NOTE: by some reasons it was missed in bls12-381, looks like bug + point.assertValidity() + const len = Fp.BYTES + if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) + return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const { x, y } = point.toAffine() + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + const tmp = y1 > _0n ? y1 * _2n : y0 * _2n + const sort = Boolean((tmp / Fp.ORDER) & _1n) + const z2 = x0 + return concatB( + setMask(numberToBytesBE(x1, len), { sort, compressed: true }), + numberToBytesBE(z2, len), + ) +} + +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export const bls12_381: CurveFn = bls({ + // Fields + fields: { + Fp, + Fp2, + Fp6, + Fp12, + Fr, + }, + // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where + // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 + G1: { + Fp, + // cofactor; (z - 1)²/3 + h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), + // generator's coordinates + // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 + // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 + Gx: BigInt( + '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', + ), + Gy: BigInt( + '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', + ), + a: Fp.ZERO, + b: _4n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, point): boolean => { + // φ endomorphism + const cubicRootOfUnityModP = BigInt( + '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', + ) + const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) + + // todo: unroll + const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P + const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P + return u2P.equals(phi) + + // https://eprint.iacr.org/2019/814.pdf + // (z² − 1)/3 + // const c1 = BigInt('0x396c8c005555e1560000000055555555'); + // const P = this; + // const S = P.sigma(); + // const Q = S.double(); + // const S2 = S.sigma(); + // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O + // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); + // const C = left.subtract(S2); + // return C.isZero(); + }, + // Clear cofactor of G1 + // https://eprint.iacr.org/2019/403 + clearCofactor: (_c, point) => { + // return this.multiplyUnsafe(CURVE.h); + return point.multiplyUnsafe(BLS_X).add(point) // x*P + P + }, + mapToCurve: (scalars: bigint[]) => { + const { x, y } = G1_SWU(Fp.create(scalars[0])) + return isogenyMapG1(x, y) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if (value.length === 48 && compressed) { + // TODO: Fp.bytes + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + const x = Fp.create(compressedValue & Fp.MASK) + if (infinity) { + if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') + return { x: _0n, y: _0n } + } + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) + return { x: Fp.create(x), y: Fp.create(y) } + } else if (value.length === 96 && !compressed) { + // Check if the infinity flag is set + const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) + const y = bytesToNumberBE(value.subarray(Fp.BYTES)) + if (infinity) { + if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') + return bls12_381.G1.ProjectivePoint.ZERO.toAffine() + } + return { x: Fp.create(x), y: Fp.create(y) } + } else { + throw new Error('invalid point G1, expected 48/96 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) + } else { + if (isZero) { + // 2x PUBLIC_KEY_LENGTH + const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) + return x + } else { + return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) + } + } + }, + ShortSignature: { + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + if (infinity) return bls12_381.G1.ProjectivePoint.ZERO + const x = Fp.create(compressedValue & Fp.MASK) + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + const aflag = BigInt(sort) + if ((y * _2n) / P !== aflag) y = Fp.neg(y) + const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG1ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG1ToRawBytes(point)) + }, + }, + }, + // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), + // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where + // G² - 1 + // h2q + G2: { + Fp: Fp2, + // cofactor + h: BigInt( + '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', + ), + Gx: Fp2.fromBigTuple([ + BigInt( + '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', + ), + BigInt( + '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', + ), + ]), + // y = + // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, + // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + Gy: Fp2.fromBigTuple([ + BigInt( + '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', + ), + BigInt( + '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', + ), + ]), + a: Fp2.ZERO, + b: Fp2.fromBigTuple([_4n, _4n]), + hEff: BigInt( + '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', + ), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: (scalars: bigint[]) => { + const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) + return isogenyMapG2(x, y) + }, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, P): boolean => { + return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) + // Older version: https://eprint.iacr.org/2019/814.pdf + // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O + // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); + }, + // Maps the point into the prime-order subgroup G2. + // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 + // https://eprint.iacr.org/2017/419.pdf + // prettier-ignore + clearCofactor: (c, P) => { + const x = BLS_X + let t1 = P.multiplyUnsafe(x).negate() // [-x]P + let t2 = G2psi(c, P) // Ψ(P) + let t3 = P.double() // 2P + t3 = G2psi2(c, t3) // Ψ²(2P) + t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) + t2 = t1.add(t2) // [-x]P + Ψ(P) + t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) + t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P + const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P + return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if ( + (!compressed && !infinity && sort) || // 00100000 + (!compressed && infinity && sort) || // 01100000 + (sort && infinity && compressed) // 11100000 + ) { + throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000)) + } + const L = Fp.BYTES + const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to)) + if (value.length === 96 && compressed) { + const b = bls12_381.params.G2b + const P = Fp.ORDER + if (infinity) { + // check that all bytes are 0 + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid compressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x_1 = slc(value, 0, L) + const x_0 = slc(value, L, 2 * L) + const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) + const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b + let y = Fp2.sqrt(right) + const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n + y = sort && Y_bit > 0 ? y : Fp2.neg(y) + return { x, y } + } else if (value.length === 192 && !compressed) { + if (infinity) { + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid uncompressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x1 = slc(value, 0, L) + const x0 = slc(value, L, 2 * L) + const y1 = slc(value, 2 * L, 3 * L) + const y0 = slc(value, 3 * L, 4 * L) + return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } + } else { + throw new Error('invalid point G2, expected 96/192 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const { BYTES: len, ORDER: P } = Fp + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) + return concatB( + setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), + numberToBytesBE(x.c0, len), + ) + } else { + if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + return concatB( + numberToBytesBE(x1, len), + numberToBytesBE(x0, len), + numberToBytesBE(y1, len), + numberToBytesBE(y0, len), + ) + } + }, + Signature: { + // TODO: Optimize, it's very slow because of sqrt. + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) + const P = Fp.ORDER + const half = value.length / 2 + if (half !== 48 && half !== 96) + throw new Error('invalid compressed signature length, must be 96 or 192') + const z1 = bytesToNumberBE(value.slice(0, half)) + const z2 = bytesToNumberBE(value.slice(half)) + // Indicates the infinity point + if (infinity) return bls12_381.G2.ProjectivePoint.ZERO + const x1 = Fp.create(z1 & Fp.MASK) + const x2 = Fp.create(z2) + const x = Fp2.create({ c0: x2, c1: x1 }) + const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 + // The slow part + let y = Fp2.sqrt(y2) + if (!y) throw new Error('Failed to find a square root') + + // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 + // If y1 happens to be zero, then use the bit of y0 + const { re: y0, im: y1 } = Fp2.reim(y) + const aflag1 = BigInt(sort) + const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 + const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 + if (isGreater || isZero) y = Fp2.neg(y) + const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG2ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG2ToRawBytes(point)) + }, + }, + }, + params: { + ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 + r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves + xNegative: true, + twistType: 'multiplicative', + }, + htfDefaults, + hash: sha256, + randomBytes, +}) diff --git a/packages/noble-curves-tmp/src/bn254.ts b/packages/noble-curves-tmp/src/bn254.ts new file mode 100644 index 00000000000..f2ffdb887ac --- /dev/null +++ b/packages/noble-curves-tmp/src/bn254.ts @@ -0,0 +1,255 @@ +/** + * bn254, previously known as alt_bn_128, when it had 128-bit security. + +Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, +so the naming has been adjusted to its prime bit count: +https://hal.science/hal-01534101/file/main.pdf. +Compatible with EIP-196 and EIP-197. + +There are huge compatibility issues in the ecosystem: + +1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". +2. libff has bn128, but it's a different curve with different G2: + https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 +3. halo2curves bn256 is also incompatible and returns different outputs + +The goal of our implementation is to support "Ethereum" variant of the curve, +because it at least has specs: + +- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM +- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings +- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 +- The existing implementations are bad. Some are deprecated: + - https://github.com/paritytech/bn (old version) + - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) + - https://github.com/zcash-hackworks/bn + - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs +- Python implementations use different towers and produce different Fp12 outputs: + - https://github.com/ethereum/py_pairing + - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py +- Points are encoded differently in different implementations + +### Params +Seed (X): 4965661367192848881 +Fr: (36x⁴+36x³+18x²+6x+1) +Fp: (36x⁴+36x³+24x²+6x+1) +(E / Fp ): Y² = X³+3 +(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) +Ate loop size: 6x+2 + +### Towers +- Fp²[u] = Fp/u²+1 +- Fp⁶[v] = Fp²/v³-9-u +- Fp¹²[w] = Fp⁶/w²-v + + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.ts' +import { + type CurveFn as BLSCurveFn, + type PostPrecomputeFn, + type PostPrecomputePointAddFn, + bls, +} from './abstract/bls.ts' +import { Field } from './abstract/modular.ts' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' +import { psiFrobenius, tower12 } from './abstract/tower.ts' +import { bitGet, bitLen, notImplemented } from './abstract/utils.ts' +import { type CurveFn, weierstrass } from './abstract/weierstrass.ts' +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +const _6n = BigInt(6) + +const BN_X = BigInt('4965661367192848881') +const BN_X_LEN = bitLen(BN_X) +const SIX_X_SQUARED = _6n * BN_X ** _2n + +// Finite field over r. It's for convenience and is not used in the code below. +const Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) +// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) +const Fp2B = { + c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), + c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), +} + +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), + FP2_NONRESIDUE: [BigInt(9), _1n], + Fp2mulByB: (num) => Fp2.mul(num, Fp2B), + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BN_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) + const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) + const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) + const y1 = Fp12._cyclotomicSquare(powMinusX(r)) + const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) + const y4 = powMinusX(y2) + const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) + const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) + const y9 = Fp12.mul(y8, y1) + return Fp12.mul( + Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), + Fp12.mul( + Fp12.frobeniusMap(y8, 2), + Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), + ), + ) + }, +}) + +// END OF CURVE FIELDS +const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) + +/* +No hashToCurve for now (and signatures): + +- RFC 9380 doesn't mention bn254 and doesn't provide test vectors +- Overall seems like nobody is using BLS signatures on top of bn254 +- Seems like it can utilize SVDW, which is not implemented yet +*/ +const htfDefaults = Object.freeze({ + // DST: a domain separation tag defined in section 2.2.5 + DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + p: Fp.ORDER, + m: 2, + k: 128, + expand: 'xmd', + hash: sha256, +} as const) + +export const _postPrecompute: PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => { + const q = psi(Qx, Qy) + ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) + const q2 = psi(q[0], q[1]) + pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) +} + +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export const bn254: BLSCurveFn = bls({ + // Fields + fields: { Fp, Fp2, Fp6, Fp12, Fr }, + G1: { + Fp, + h: BigInt(1), + Gx: BigInt(1), + Gy: BigInt(2), + a: Fp.ZERO, + b: _3n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + ShortSignature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + G2: { + Fp: Fp2, + // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 + h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + Gx: Fp2.fromBigTuple([ + BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), + BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), + ]), + Gy: Fp2.fromBigTuple([ + BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), + BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), + ]), + a: Fp2.ZERO, + b: Fp2B, + hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + Signature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + params: { + ateLoopSize: BN_X * _6n + _2n, + r: Fr.ORDER, + xNegative: false, + twistType: 'divisive', + }, + htfDefaults, + hash: sha256, + randomBytes, + + postPrecompute: _postPrecompute, +}) + +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + * @deprecated + */ +export const bn254_weierstrass: CurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(3), + Fp, + n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), + Gx: BigInt(1), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/noble-curves-tmp/src/ed25519.ts b/packages/noble-curves-tmp/src/ed25519.ts new file mode 100644 index 00000000000..138d05b2e04 --- /dev/null +++ b/packages/noble-curves-tmp/src/ed25519.ts @@ -0,0 +1,554 @@ +/** + * ed25519 Twisted Edwards curve with following addons: + * - X25519 ECDH + * - Ristretto cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha2' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { type AffinePoint, type Group, pippenger } from './abstract/curve.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { + type HTFMethod, + type Hasher, + createHasher, + expand_message_xmd, + type htfBasicOpts, +} from './abstract/hash-to-curve.ts' +import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.ts' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.ts' + +// 2n**255n - 19n +const ED25519_P = BigInt( + '57896044618658097711785492504343953926634992332820282019728792003956564819949', +) +// √(-1) aka √(a) aka 2^((p-1)/4) +// Fp.sqrt(Fp.neg(1)) +const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( + '19681161376707505956807079304988542015446066515923890162744021073123829784752', +) + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// prettier-ignore +const _5n = BigInt(5), + _8n = BigInt(8) + +function ed25519_pow_2_252_3(x: bigint) { + // prettier-ignore + const _10n = BigInt(10), + _20n = BigInt(20), + _40n = BigInt(40), + _80n = BigInt(80) + const P = ED25519_P + const x2 = (x * x) % P + const b2 = (x2 * x) % P // x^3, 11 + const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 + const b5 = (pow2(b4, _1n, P) * x) % P // x^31 + const b10 = (pow2(b5, _5n, P) * b5) % P + const b20 = (pow2(b10, _10n, P) * b10) % P + const b40 = (pow2(b20, _20n, P) * b20) % P + const b80 = (pow2(b40, _40n, P) * b40) % P + const b160 = (pow2(b80, _80n, P) * b80) % P + const b240 = (pow2(b160, _80n, P) * b80) % P + const b250 = (pow2(b240, _10n, P) * b10) % P + const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P + // ^ To pow to (p+3)/8, multiply it by x. + return { pow_p_5_8, b2 } +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, + // set the three least significant bits of the first byte + bytes[0] &= 248 // 0b1111_1000 + // and the most significant bit of the last to zero, + bytes[31] &= 127 // 0b0111_1111 + // set the second most significant bit of the last byte to 1 + bytes[31] |= 64 // 0b0100_0000 + return bytes +} + +// sqrt(u/v) +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ED25519_P + const v3 = mod(v * v * v, P) // v³ + const v7 = mod(v3 * v3 * v, P) // v⁷ + // (p+3)/8 and (p-5)/8 + const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 + let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 + const vx2 = mod(v * x * x, P) // vx² + const root1 = x // First root candidate + const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate + const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root + const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) + const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) + if (useRoot1) x = root1 + if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time + if (isNegativeLE(x, P)) x = mod(-x, P) + return { isValid: useRoot1 || useRoot2, value: x } +} + +/** Weird / bogus points, useful for debugging. */ +export const ED25519_TORSION_SUBGROUP: string[] = [ + '0100000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', + '0000000000000000000000000000000000000000000000000000000000000080', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', + '0000000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', +] + +const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() + +const ed25519Defaults = /* @__PURE__ */ (() => + ({ + // Removing Fp.create() will still work, and is 10% faster on sign + a: Fp.create(BigInt(-1)), + // d is -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666)) + d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), + // Finite field 2n**255n - 19n + Fp, + // Subgroup order 2n**252n + 27742317777372353535851937790883648493n; + n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), + h: _8n, + Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), + Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), + hash: sha512, + randomBytes, + adjustScalarBytes, + // dom2 + // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. + // Constant-time, u/√v + uvRatio, + }) as const)() + +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() + +function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) { + if (ctx.length > 255) throw new Error('Context is too big') + return concatBytes( + utf8ToBytes('SigEd25519 no Ed25519 collisions'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) +} + +export const ed25519ctx: CurveFn = /* @__PURE__ */ (() => + twistedEdwards({ + ...ed25519Defaults, + domain: ed25519_domain, + }))() +export const ed25519ph: CurveFn = /* @__PURE__ */ (() => + twistedEdwards( + Object.assign({}, ed25519Defaults, { + domain: ed25519_domain, + prehash: sha512, + }), + ))() + +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export const x25519: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x: bigint): bigint => { + const P = ED25519_P + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) + return mod(pow2(pow_p_5_8, _3n, P) * b2, P) + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array { + const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) +} +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated + +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array { + const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) + return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) +} + +// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) +// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since +// SageMath returns different root first and everything falls apart + +const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic +const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 +const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) + +// prettier-ignore +function map_to_curve_elligator2_curve25519(u: bigint) { + const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic + const ELL2_J = BigInt(486662) + + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 + let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not + let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) + let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 + tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 + tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 + tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 + tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 + let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) + y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) + let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 + tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 + tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd + let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 + let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt + let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd + let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u + y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 + let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 + let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) + tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 + tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 + let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt + tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd + let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 + let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) +} + +const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 +function map_to_curve_elligator2_edwards25519(u: bigint) { + const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = + // map_to_curve_elligator2_curve25519(u) + let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd + xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 + let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM + let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd + let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) + let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd + let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 + xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) + xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) + yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) + yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) + + const inv = Fp.invertBatch([xd, yd]) // batch division + return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) +} + +export const ed25519_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + ed25519.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512, + }, + ))() +/** + * @deprecated Use `ed25519_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed25519_hasher.hashToCurve)() +/** + * @deprecated Use `ed25519_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => + ed25519_hasher.encodeToCurve)() + +function aristp(other: unknown) { + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') +} + +// √(-1) aka √(a) aka 2^((p-1)/4) +const SQRT_M1 = ED25519_SQRT_M1 +// √(ad - 1) +const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( + '25063068953384623474111414158702152701244531502492656460079210482610430750235', +) +// 1 / √(a-d) +const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( + '54469307008909316920995813868745141605393597292927456921205312896311721017578', +) +// 1-d² +const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( + '1159843021668779879193775521855586647937357759715417654439879720876111806838', +) +// (d-1)² +const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( + '40440834346308536858101042469323190826248399146238708352240133220865137265952', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_255B = /* @__PURE__ */ BigInt( + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes255ToNumberLE = (bytes: Uint8Array) => + ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Ristretto +// https://ristretto.group/formulas/elligator.html +function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { + const { d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const r = mod(SQRT_M1 * r0 * r0) // 1 + const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 + let c = BigInt(-1) // 3 + const D = mod((c - d * r) * mod(r + d)) // 4 + let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 + let s_ = mod(s * r0) // 6 + if (!isNegativeLE(s_, P)) s_ = mod(-s_) + if (!Ns_D_is_sq) s = s_ // 7 + if (!Ns_D_is_sq) c = r // 8 + const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 + const s2 = s * s + const W0 = mod((s + s) * D) // 10 + const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 + const W2 = mod(_1n - s2) // 12 + const W3 = mod(_1n + s2) // 13 + return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class RistPoint implements Group { + static BASE: RistPoint + static ZERO: RistPoint + private readonly ep: ExtendedPoint + // Private property to discourage combining ExtendedPoint + RistrettoPoint + // Always use Ristretto encoding/decoding instead. + constructor(ep: ExtendedPoint) { + this.ep = ep + } + + static fromAffine(ap: AffinePoint): RistPoint { + return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHash', hex, 64) + const r1 = bytes255ToNumberLE(hex.slice(0, 32)) + const R1 = calcElligatorRistrettoMap(r1) + const r2 = bytes255ToNumberLE(hex.slice(32, 64)) + const R2 = calcElligatorRistrettoMap(r2) + return new RistPoint(R1.add(R2)) + } + + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHex', hex, 32) + const { a, d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' + const s = bytes255ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 3. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) + const s2 = mod(s * s) + const u1 = mod(_1n + a * s2) // 4 (a is -1) + const u2 = mod(_1n - a * s2) // 5 + const u1_2 = mod(u1 * u1) + const u2_2 = mod(u2 * u2) + const v = mod(a * d * u1_2 - u2_2) // 6 + const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 + const Dx = mod(I * u2) // 8 + const Dy = mod(I * Dx * v) // 9 + let x = mod((s + s) * Dx) // 10 + if (isNegativeLE(x, P)) x = mod(-x) // 10 + const y = mod(u1 * Dy) // 11 + const t = mod(x * y) // 12 + if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) + return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: RistPoint[], scalars: bigint[]): RistPoint { + const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) + return pippenger(RistPoint, Fn, points, scalars) + } + + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: y, ez: z, et: t } = this.ep + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const u1 = mod(mod(z + y) * mod(z - y)) // 1 + const u2 = mod(x * y) // 2 + // Square root always exists + const u2sq = mod(u2 * u2) + const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 + const D1 = mod(invsqrt * u1) // 4 + const D2 = mod(invsqrt * u2) // 5 + const zInv = mod(D1 * D2 * t) // 6 + let D: bigint // 7 + if (isNegativeLE(t * zInv, P)) { + let _x = mod(y * SQRT_M1) + let _y = mod(x * SQRT_M1) + x = _x + y = _y + D = mod(D1 * INVSQRT_A_MINUS_D) + } else { + D = D2 // 8 + } + if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 + let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) + if (isNegativeLE(s, P)) s = mod(-s) + return numberToBytesLE(s, 32) // 11 + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + equals(other: RistPoint): boolean { + aristp(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed25519.CURVE.Fp.create + // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) + const one = mod(X1 * Y2) === mod(Y1 * X2) + const two = mod(Y1 * Y2) === mod(X1 * X2) + return one || two + } + + add(other: RistPoint): RistPoint { + aristp(other) + return new RistPoint(this.ep.add(other.ep)) + } + + subtract(other: RistPoint): RistPoint { + aristp(other) + return new RistPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): RistPoint { + return new RistPoint(this.ep.double()) + } + + negate(): RistPoint { + return new RistPoint(this.ep.negate()) + } +} +export const RistrettoPoint: typeof RistPoint = /* @__PURE__ */ (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) + return RistPoint +})() + +// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B +export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts): RistPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) + const P = RistPoint.hashToCurve(uniform_bytes) + return P +} +/** @deprecated */ +export const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint = + hashToRistretto255 // legacy diff --git a/packages/noble-curves-tmp/src/ed448.ts b/packages/noble-curves-tmp/src/ed448.ts new file mode 100644 index 00000000000..c39163373f2 --- /dev/null +++ b/packages/noble-curves-tmp/src/ed448.ts @@ -0,0 +1,522 @@ +/** + * Edwards448 (not Ed448-Goldilocks) curve with following addons: + * - X448 ECDH + * - Decaf cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { shake256 } from '@noble/hashes/sha3' +import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' +import type { AffinePoint, Group } from './abstract/curve.ts' +import { pippenger } from './abstract/curve.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { + type HTFMethod, + type Hasher, + createHasher, + expand_message_xof, + type htfBasicOpts, +} from './abstract/hash-to-curve.ts' +import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.ts' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.ts' + +const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) +const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) +const ed448P = BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', +) + +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4), + _11n = BigInt(11) +// prettier-ignore +const _22n = BigInt(22), + _44n = BigInt(44), + _88n = BigInt(88), + _223n = BigInt(223) + +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +// Used for efficient square root calculation. +// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] +function ed448_pow_Pminus3div4(x: bigint): bigint { + const P = ed448P + const b2 = (x * x * x) % P + const b3 = (b2 * b2 * x) % P + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b222 = (pow2(b220, _2n, P) * b2) % P + const b223 = (pow2(b222, _1n, P) * x) % P + return (pow2(b223, _223n, P) * b222) % P +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most + // significant bit of the last byte to 1. + bytes[0] &= 252 // 0b11111100 + // and the most significant bit of the last byte to 1. + bytes[55] |= 128 // 0b10000000 + // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) + bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) + return bytes +} + +// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. +// Uses algo from RFC8032 5.1.3. +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ed448P + // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 + // To compute the square root of (u/v), the first step is to compute the + // candidate root x = (u/v)^((p+1)/4). This can be done using the + // following trick, to use a single modular powering for both the + // inversion of v and the square root: + // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) + const u2v = mod(u * u * v, P) // u²v + const u3v = mod(u2v * u, P) // u³v + const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ + const root = ed448_pow_Pminus3div4(u5v3) + const x = mod(u3v * root, P) + // Verify that root is exists + const x2 = mod(x * x, P) // x² + // If vx² = u, the recovered x-coordinate is x. Otherwise, no + // square root exists, and the decoding fails. + return { isValid: mod(x2 * v, P) === u, value: x } +} + +const Fp = Field(ed448P, 456, true) + +const ED448_DEF = { + // Param: a + a: BigInt(1), + // -39081 a.k.a. Fp.neg(39081) + d: BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', + ), + // Finite field 2n**448n - 2n**224n - 1n + Fp, + // Subgroup order + // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n + n: BigInt( + '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', + ), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + nBitLength: 456, + h: BigInt(4), + Gx: BigInt( + '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', + ), + Gy: BigInt( + '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', + ), + // SHAKE256(dom4(phflag,context)||x, 114) + hash: shake256_114, + randomBytes, + adjustScalarBytes, + // dom4 + domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) + return concatBytes( + utf8ToBytes('SigEd448'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) + }, + uvRatio, +} as const + +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export const ed448: CurveFn = /* @__PURE__ */ twistedEdwards(ED448_DEF) +// NOTE: there is no ed448ctx, since ed448 supports ctx by default +export const ed448ph: CurveFn = /* @__PURE__ */ twistedEdwards({ + ...ED448_DEF, + prehash: shake256_64, +}) + +/** + * ECDH using curve448 aka x448. + */ +export const x448: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + a: BigInt(156326), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + montgomeryBits: 448, + nByteLength: 56, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x: bigint): bigint => { + const P = ed448P + const Pminus3div4 = ed448_pow_Pminus3div4(x) + const Pminus3 = pow2(Pminus3div4, BigInt(2), P) + return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array { + const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) +} + +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated +// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version + +// Hash To Curve Elligator2 Map +const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic +const ELL2_J = BigInt(156326) + +function map_to_curve_elligator2_curve448(u: bigint) { + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 + tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 + let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 + let x1n = Fp.neg(ELL2_J) // 5. x1n = -J + let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 + tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd + tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 + let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) + y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) + let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd + let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u + y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) + tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 + let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) + return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) +} + +function map_to_curve_elligator2_edwards448(u: bigint) { + let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) + let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 + let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 + let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 + let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 + let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 + let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 + let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 + xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 + xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd + xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn + xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 + tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 + tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 + let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 + let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 + tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 + let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 + tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn + let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 + let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 + yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 + yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 + tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 + tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 + tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd + tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 + tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 + let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 + tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 + yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 + tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd + let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 + xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) + xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) + yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) + yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) + + const inv = Fp.invertBatch([xEd, yEd]) // batch division + return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) +} + +export const ed448_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + ed448.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), + { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: shake256, + }, + ))() +/** + * @deprecated Use `ed448_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.hashToCurve)() +/** + * @deprecated Use `ed448_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.encodeToCurve)() + +function adecafp(other: unknown) { + if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') +} + +// 1-d +const ONE_MINUS_D = BigInt('39082') +// 1-2d +const ONE_MINUS_TWO_D = BigInt('78163') +// √(-d) +const SQRT_MINUS_D = BigInt( + '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', +) +// 1 / √(-d) +const INVSQRT_MINUS_D = BigInt( + '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_448B = BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes448ToNumberLE = (bytes: Uint8Array) => + ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Decaf +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 +function calcElligatorDecafMap(r0: bigint): ExtendedPoint { + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const r = mod(-(r0 * r0)) // 1 + const u0 = mod(d * (r - _1n)) // 2 + const u1 = mod((u0 + _1n) * (u0 - r)) // 3 + + const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 + + let v_prime = v // 5 + if (!was_square) v_prime = mod(r0 * v) + + let sgn = _1n // 6 + if (!was_square) sgn = mod(-_1n) + + const s = mod(v_prime * (r + _1n)) // 7 + let s_abs = s + if (isNegativeLE(s, P)) s_abs = mod(-s) + + const s2 = s * s + const W0 = mod(s_abs * _2n) // 8 + const W1 = mod(s2 + _1n) // 9 + const W2 = mod(s2 - _1n) // 10 + const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 + return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class DcfPoint implements Group { + static BASE: DcfPoint + static ZERO: DcfPoint + private readonly ep: ExtendedPoint + // Private property to discourage combining ExtendedPoint + DecafPoint + // Always use Decaf encoding/decoding instead. + constructor(ep: ExtendedPoint) { + this.ep = ep + } + + static fromAffine(ap: AffinePoint): DcfPoint { + return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex: Hex): DcfPoint { + hex = ensureBytes('decafHash', hex, 112) + const r1 = bytes448ToNumberLE(hex.slice(0, 56)) + const R1 = calcElligatorDecafMap(r1) + const r2 = bytes448ToNumberLE(hex.slice(56, 112)) + const R2 = calcElligatorDecafMap(r2) + return new DcfPoint(R1.add(R2)) + } + + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex: Hex): DcfPoint { + hex = ensureBytes('decafHex', hex, 56) + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' + const s = bytes448ToNumberLE(hex) + + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 2. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) + + const s2 = mod(s * s) // 1 + const u1 = mod(_1n + s2) // 2 + const u1sq = mod(u1 * u1) + const u2 = mod(u1sq - _4n * d * s2) // 3 + + const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 + + let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 + if (isNegativeLE(u3, P)) u3 = mod(-u3) + + const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 + const y = mod((_1n - s2) * invsqrt * u1) // 7 + const t = mod(x * y) // 8 + + if (!isValid) throw new Error(emsg) + return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint { + const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) + return pippenger(DcfPoint, Fn, points, scalars) + } + + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: _y, ez: z, et: t } = this.ep + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const u1 = mod(mod(x + t) * mod(x - t)) // 1 + const x2 = mod(x * x) + const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 + + let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 + if (isNegativeLE(ratio, P)) ratio = mod(-ratio) + + const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 + + let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 + if (isNegativeLE(s, P)) s = mod(-s) + + return numberToBytesLE(s, 56) + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 + equals(other: DcfPoint): boolean { + adecafp(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed448.CURVE.Fp.create + // (x1 * y2 == y1 * x2) + return mod(X1 * Y2) === mod(Y1 * X2) + } + + add(other: DcfPoint): DcfPoint { + adecafp(other) + return new DcfPoint(this.ep.add(other.ep)) + } + + subtract(other: DcfPoint): DcfPoint { + adecafp(other) + return new DcfPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): DcfPoint { + return new DcfPoint(this.ep.double()) + } + + negate(): DcfPoint { + return new DcfPoint(this.ep.negate()) + } +} + +export const DecafPoint: typeof DcfPoint = /* @__PURE__ */ (() => { + // decaf448 base point is ed448 base x 2 + // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 + if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) + if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) + return DcfPoint +})() + +// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C +export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts): DcfPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) + const P = DcfPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_decaf448: typeof hashToDecaf448 = hashToDecaf448 // legacy diff --git a/packages/noble-curves-tmp/src/index.ts b/packages/noble-curves-tmp/src/index.ts new file mode 100644 index 00000000000..8b4ac3bb10f --- /dev/null +++ b/packages/noble-curves-tmp/src/index.ts @@ -0,0 +1,17 @@ +/** + * Audited & minimal JS implementation of elliptic curve cryptography. + * @module + * @example +```js +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + */ +throw new Error('root module cannot be imported: import submodules instead. Check out README') diff --git a/packages/noble-curves-tmp/src/jubjub.ts b/packages/noble-curves-tmp/src/jubjub.ts new file mode 100644 index 00000000000..7c2c07f240c --- /dev/null +++ b/packages/noble-curves-tmp/src/jubjub.ts @@ -0,0 +1,5 @@ +export { + jubjub_findGroupHash as findGroupHash, + jubjub_groupHash as groupHash, + jubjub, +} from './misc.ts' diff --git a/packages/noble-curves-tmp/src/misc.ts b/packages/noble-curves-tmp/src/misc.ts new file mode 100644 index 00000000000..e7736884109 --- /dev/null +++ b/packages/noble-curves-tmp/src/misc.ts @@ -0,0 +1,117 @@ +/** + * Miscellaneous, rarely used curves. + * jubjub, babyjubjub, pallas, vesta. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { blake256 } from '@noble/hashes/blake1' +import { blake2s } from '@noble/hashes/blake2s' +import { sha256, sha512 } from '@noble/hashes/sha2' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { Field, mod } from './abstract/modular.ts' +import { type CurveFn as WCurveFn, weierstrass } from './abstract/weierstrass.ts' + +// Jubjub curves have 𝔽p over scalar fields of other curves. They are friendly to ZK proofs. +// jubjub Fp = bls n. babyjubjub Fp = bn254 n. +// verify manually, check bls12-381.ts and bn254.ts. +// https://neuromancer.sk/std/other/JubJub + +const bls12_381_Fr = Field( + BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), +) +const bn254_Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) + +/** Curve over scalar field of bls12-381. jubjub Fp = bls n */ +export const jubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ + a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), + d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), + Fp: bls12_381_Fr, + n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), + h: BigInt(8), + Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), + Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), + hash: sha512, + randomBytes, +} as const) + +/** Curve over scalar field of bn254. babyjubjub Fp = bn254 n */ +export const babyjubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ + a: BigInt(168700), + d: BigInt(168696), + Fp: bn254_Fr, + n: BigInt('21888242871839275222246405745257275088614511777268538073601725287587578984328'), + h: BigInt(8), + Gx: BigInt('995203441582195749578291179787384436505546430278305826713579947235728471134'), + Gy: BigInt('5472060717959818805561601436314318772137091100104008585924551046643952123905'), + hash: blake256, + randomBytes, +} as const) + +const jubjub_gh_first_block = utf8ToBytes( + '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', +) + +// Returns point at JubJub curve which is prime order and not zero +export function jubjub_groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType { + const h = blake2s.create({ personalization, dkLen: 32 }) + h.update(jubjub_gh_first_block) + h.update(tag) + // NOTE: returns ExtendedPoint, in case it will be multiplied later + let p = jubjub.ExtendedPoint.fromHex(h.digest()) + // NOTE: cannot replace with isSmallOrder, returns Point*8 + p = p.multiply(jubjub.CURVE.h) + if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') + return p +} + +// No secret data is leaked here at all. +// It operates over public data: +// const G_SPEND = jubjub.findGroupHash(Uint8Array.of(), utf8ToBytes('Item_G_')); +export function jubjub_findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType { + const tag = concatBytes(m, new Uint8Array([0])) + const hashes = [] + for (let i = 0; i < 256; i++) { + tag[tag.length - 1] = i + try { + hashes.push(jubjub_groupHash(tag, personalization)) + } catch (e) {} + } + if (!hashes.length) throw new Error('findGroupHash tag overflow') + return hashes[0] +} + +// Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). + +export const pasta_p: bigint = BigInt( + '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001', +) +export const pasta_q: bigint = BigInt( + '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001', +) + +/** https://neuromancer.sk/std/other/Pallas */ +export const pallas: WCurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(pasta_p), + n: pasta_q, + Gx: mod(BigInt(-1), pasta_p), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +/** https://neuromancer.sk/std/other/Vesta */ +export const vesta: WCurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(pasta_q), + n: pasta_p, + Gx: mod(BigInt(-1), pasta_q), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/noble-curves-tmp/src/nist.ts b/packages/noble-curves-tmp/src/nist.ts new file mode 100644 index 00000000000..44c3eb545df --- /dev/null +++ b/packages/noble-curves-tmp/src/nist.ts @@ -0,0 +1,171 @@ +/** + * NIST secp256r1 aka p256. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256, sha384, sha512 } from '@noble/hashes/sha2' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' +import { type Hasher, createHasher } from './abstract/hash-to-curve.ts' +import { Field } from './abstract/modular.ts' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.ts' + +const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) +const p256_a = Fp256.create(BigInt('-3')) +const p256_b = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') + +/** + * secp256r1 curve, ECDSA and ECDH methods. + * Field: `2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n` + */ +// prettier-ignore +export const p256: CurveFnWithCreate = createCurve( + { + a: p256_a, + b: p256_b, + Fp: Fp256, + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, + } as const, + sha256, +) +/** Alias to p256. */ +export const secp256r1: CurveFnWithCreate = p256 + +const p256_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp256, { + A: p256_a, + B: p256_b, + Z: Fp256.create(BigInt('-10')), + }))() + +/** Hashing / encoding to p256 points / field. RFC 9380 methods. */ +export const p256_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => p256_mapSWU(scalars[0]), { + DST: 'P256_XMD:SHA-256_SSWU_RO_', + encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', + p: Fp256.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }))() + +// Field over which we'll do calculations. +const Fp384 = Field( + BigInt( + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', + ), +) +const p384_a = Fp384.create(BigInt('-3')) +// prettier-ignore +const p384_b = BigInt( + '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', +) + +/** + * secp384r1 curve, ECDSA and ECDH methods. + * Field: `2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n`. + * */ +// prettier-ignore +export const p384: CurveFnWithCreate = createCurve( + { + a: p384_a, + b: p384_b, + Fp: Fp384, + n: BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', + ), + Gx: BigInt( + '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', + ), + Gy: BigInt( + '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', + ), + h: BigInt(1), + lowS: false, + } as const, + sha384, +) +/** Alias to p384. */ +export const secp384r1: CurveFnWithCreate = p384 + +const p384_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp384, { + A: p384_a, + B: p384_b, + Z: Fp384.create(BigInt('-12')), + }))() + +/** Hashing / encoding to p384 points / field. RFC 9380 methods. */ +export const p384_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => p384_mapSWU(scalars[0]), { + DST: 'P384_XMD:SHA-384_SSWU_RO_', + encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', + p: Fp384.ORDER, + m: 1, + k: 192, + expand: 'xmd', + hash: sha384, + }))() + +// Field over which we'll do calculations. +const Fp521 = Field( + BigInt( + '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + ), +) + +const p521_a = Fp521.create(BigInt('-3')) +const p521_b = BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', +) + +/** + * NIST secp521r1 aka p521 curve, ECDSA and ECDH methods. + * Field: `2n**521n - 1n`. + */ +// prettier-ignore +export const p521: CurveFnWithCreate = createCurve( + { + a: p521_a, + b: p521_b, + Fp: Fp521, + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', + ), + h: BigInt(1), + lowS: false, + allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b + } as const, + sha512, +) +export const secp521r1: CurveFnWithCreate = p521 + +const p521_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp521, { + A: p521_a, + B: p521_b, + Z: Fp521.create(BigInt('-4')), + }))() + +/** Hashing / encoding to p521 points / field. RFC 9380 methods. */ +export const p521_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => p521_mapSWU(scalars[0]), { + DST: 'P521_XMD:SHA-512_SSWU_RO_', + encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', + p: Fp521.ORDER, + m: 1, + k: 256, + expand: 'xmd', + hash: sha512, + }))() diff --git a/packages/noble-curves-tmp/src/p256.ts b/packages/noble-curves-tmp/src/p256.ts new file mode 100644 index 00000000000..f1bf69ad74e --- /dev/null +++ b/packages/noble-curves-tmp/src/p256.ts @@ -0,0 +1,23 @@ +/** + * NIST secp256r1 aka p256. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p256_hasher, p256 as p256n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p256: typeof p256n = p256n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp256r1: typeof p256n = p256n +/** + * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.hashToCurve)() +/** + * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/p384.ts b/packages/noble-curves-tmp/src/p384.ts new file mode 100644 index 00000000000..f08cc70b11a --- /dev/null +++ b/packages/noble-curves-tmp/src/p384.ts @@ -0,0 +1,23 @@ +/** + * NIST secp384r1 aka p384. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p384_hasher, p384 as p384n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p384: typeof p384n = p384n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp384r1: typeof p384n = p384n +/** + * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.hashToCurve)() +/** + * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/p521.ts b/packages/noble-curves-tmp/src/p521.ts new file mode 100644 index 00000000000..feedf852f72 --- /dev/null +++ b/packages/noble-curves-tmp/src/p521.ts @@ -0,0 +1,23 @@ +/** + * NIST secp521r1 aka p521. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p521_hasher, p521 as p521n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p521: typeof p521n = p521n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp521r1: typeof p521n = p521n +/** + * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.hashToCurve)() +/** + * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/package.json b/packages/noble-curves-tmp/src/package.json new file mode 100644 index 00000000000..3dbc1ca591c --- /dev/null +++ b/packages/noble-curves-tmp/src/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/noble-curves-tmp/src/pasta.ts b/packages/noble-curves-tmp/src/pasta.ts new file mode 100644 index 00000000000..18aa8b858c7 --- /dev/null +++ b/packages/noble-curves-tmp/src/pasta.ts @@ -0,0 +1 @@ +export { pallas, vesta } from './misc.ts' diff --git a/packages/noble-curves-tmp/src/secp256k1.ts b/packages/noble-curves-tmp/src/secp256k1.ts new file mode 100644 index 00000000000..810c5698ac6 --- /dev/null +++ b/packages/noble-curves-tmp/src/secp256k1.ts @@ -0,0 +1,343 @@ +/** + * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). + * + * Seems to be rigid (not backdoored) + * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). + * + * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. + * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. + * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. + * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' +import { type HTFMethod, type Hasher, createHasher, isogenyMap } from './abstract/hash-to-curve.ts' +import { Field, mod, pow2 } from './abstract/modular.ts' +import type { Hex, PrivKey } from './abstract/utils.ts' +import { + aInRange, + bytesToNumberBE, + concatBytes, + ensureBytes, + inRange, + numberToBytesBE, +} from './abstract/utils.ts' +import { type ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.ts' + +const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') +const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') +const _1n = BigInt(1) +const _2n = BigInt(2) +const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b + +/** + * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ +function sqrtMod(y: bigint): bigint { + const P = secp256k1P + // prettier-ignore + const _3n = BigInt(3), + _6n = BigInt(6), + _11n = BigInt(11), + _22n = BigInt(22) + // prettier-ignore + const _23n = BigInt(23), + _44n = BigInt(44), + _88n = BigInt(88) + const b2 = (y * y * y) % P // x^3, 11 + const b3 = (b2 * b2 * y) % P // x^7 + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b223 = (pow2(b220, _3n, P) * b3) % P + const t1 = (pow2(b223, _23n, P) * b22) % P + const t2 = (pow2(t1, _6n, P) * b2) % P + const root = pow2(t2, _2n, P) + if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') + return root +} + +const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) + +/** + * secp256k1 curve, ECDSA and ECDH methods. + * + * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n` + * + * @example + * ```js + * import { secp256k1 } from '@noble/curves/secp256k1'; + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + * ``` + */ +export const secp256k1: CurveFnWithCreate = createCurve( + { + a: BigInt(0), + b: BigInt(7), + Fp: Fpk1, + n: secp256k1N, + Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), + Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + h: BigInt(1), // Cofactor + lowS: true, // Allow only low-S signatures by default in sign() and verify() + endo: { + // Endomorphism, see above + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + splitScalar: (k: bigint) => { + const n = secp256k1N + const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') + const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') + const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') + const b2 = a1 + const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) + + const c1 = divNearest(b2 * k, n) + const c2 = divNearest(-b1 * k, n) + let k1 = mod(k - c1 * a1 - c2 * a2, n) + let k2 = mod(-c1 * b1 - c2 * b2, n) + const k1neg = k1 > POW_2_128 + const k2neg = k2 > POW_2_128 + if (k1neg) k1 = n - k1 + if (k2neg) k2 = n - k2 + if (k1 > POW_2_128 || k2 > POW_2_128) { + throw new Error('splitScalar: Endomorphism failed, k=' + k) + } + return { k1neg, k1, k2neg, k2 } + }, + }, + }, + sha256, +) + +// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. +// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +const _0n = BigInt(0) +/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {} +function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array { + let tagP = TAGGED_HASH_PREFIXES[tag] + if (tagP === undefined) { + const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) + tagP = concatBytes(tagH, tagH) + TAGGED_HASH_PREFIXES[tag] = tagP + } + return sha256(concatBytes(tagP, ...messages)) +} + +// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 +const pointToBytes = (point: PointType) => point.toRawBytes(true).slice(1) +const numTo32b = (n: bigint) => numberToBytesBE(n, 32) +const modP = (x: bigint) => mod(x, secp256k1P) +const modN = (x: bigint) => mod(x, secp256k1N) +const Point = secp256k1.ProjectivePoint +const GmulAdd = (Q: PointType, a: bigint, b: bigint) => + Point.BASE.multiplyAndAddUnsafe(Q, a, b) + +// Calculate point, scalar and bytes +function schnorrGetExtPubKey(priv: PrivKey) { + let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey + let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside + const scalar = p.hasEvenY() ? d_ : modN(-d_) + return { scalar: scalar, bytes: pointToBytes(p) } +} +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +function lift_x(x: bigint): PointType { + aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. + const xx = modP(x * x) + const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. + let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. + if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and + const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. + p.assertValidity() + return p +} +const num = bytesToNumberBE +/** + * Create tagged hash, convert it to bigint, reduce modulo-n. + */ +function challenge(...args: Uint8Array[]): bigint { + return modN(num(taggedHash('BIP0340/challenge', ...args))) +} + +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +function schnorrGetPublicKey(privateKey: Hex): Uint8Array { + return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) +} + +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +function schnorrSign( + message: Hex, + privateKey: PrivKey, + auxRand: Hex = randomBytes(32), +): Uint8Array { + const m = ensureBytes('message', message) + const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder + const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array + const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) + const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) + const k_ = modN(num(rand)) // Let k' = int(rand) mod n + if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. + const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. + const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. + const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). + sig.set(rx, 0) + sig.set(numTo32b(modN(k + e * d)), 32) + // If Verify(bytes(P), m, sig) (see below) returns failure, abort + if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') + return sig +} + +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { + const sig = ensureBytes('signature', signature, 64) + const m = ensureBytes('message', message) + const pub = ensureBytes('publicKey', publicKey, 32) + try { + const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails + const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. + if (!inRange(r, _1n, secp256k1P)) return false + const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. + if (!inRange(s, _1n, secp256k1N)) return false + const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n + const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P + if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P + return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. + } catch (error) { + return false + } +} + +export type SecpSchnorr = { + getPublicKey: typeof schnorrGetPublicKey + sign: typeof schnorrSign + verify: typeof schnorrVerify + utils: { + randomPrivateKey: () => Uint8Array + lift_x: typeof lift_x + pointToBytes: (point: PointType) => Uint8Array + numberToBytesBE: typeof numberToBytesBE + bytesToNumberBE: typeof bytesToNumberBE + taggedHash: typeof taggedHash + mod: typeof mod + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * ```js + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + * ``` + */ +export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => ({ + getPublicKey: schnorrGetPublicKey, + sign: schnorrSign, + verify: schnorrVerify, + utils: { + randomPrivateKey: secp256k1.utils.randomPrivateKey, + lift_x, + pointToBytes, + numberToBytesBE, + bytesToNumberBE, + taggedHash, + mod, + }, +}))() + +const isoMap = /* @__PURE__ */ (() => + isogenyMap( + Fpk1, + [ + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]], + ))() +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fpk1, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fpk1.create(BigInt('-11')), + }))() +/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */ +export const secp256k1_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + secp256k1.ProjectivePoint, + (scalars: bigint[]) => { + const { x, y } = mapSWU(Fpk1.create(scalars[0])) + return isoMap(x, y) + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fpk1.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + } as const, + ))() + +/** + * @deprecated Use `secp256k1_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => secp256k1_hasher.hashToCurve)() + +/** + * @deprecated Use `secp256k1_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => + secp256k1_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/tsconfig.json b/packages/noble-curves-tmp/tsconfig.json new file mode 100644 index 00000000000..d2e7d4625d9 --- /dev/null +++ b/packages/noble-curves-tmp/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../config/tsconfig.json", + "compilerOptions": { + "outDir": "./dist" + }, + "include": ["src/**/*.ts", "test/**/*.ts"] +} diff --git a/packages/noble-curves-tmp/tsconfig.lint.json b/packages/noble-curves-tmp/tsconfig.lint.json new file mode 100644 index 00000000000..3698f4f0be3 --- /dev/null +++ b/packages/noble-curves-tmp/tsconfig.lint.json @@ -0,0 +1,3 @@ +{ + "extends": "../../config/tsconfig.lint.json" +} diff --git a/packages/noble-curves-tmp/tsconfig.prod.cjs.json b/packages/noble-curves-tmp/tsconfig.prod.cjs.json new file mode 100644 index 00000000000..6e1d752908c --- /dev/null +++ b/packages/noble-curves-tmp/tsconfig.prod.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": "../../config/tsconfig.prod.cjs.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist/cjs" + }, + "include": ["src/**/*.ts"], + "references": [{ "path": "../rlp/tsconfig.prod.cjs.json" }] +} diff --git a/packages/noble-curves-tmp/tsconfig.prod.esm.json b/packages/noble-curves-tmp/tsconfig.prod.esm.json new file mode 100644 index 00000000000..cbc8c91a0d6 --- /dev/null +++ b/packages/noble-curves-tmp/tsconfig.prod.esm.json @@ -0,0 +1,13 @@ +{ + "extends": "../../config/tsconfig.prod.esm.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist/esm" + }, + "include": ["src/**/*.ts"], + "references": [ + { "path": "../rlp/tsconfig.prod.esm.json" }, + { "path": "../block/tsconfig.prod.esm.json" }, + { "path": "../blockchain/tsconfig.prod.esm.json" } + ] +} diff --git a/packages/noble-curves-tmp/typedoc.cjs b/packages/noble-curves-tmp/typedoc.cjs new file mode 100644 index 00000000000..0c5a50bf952 --- /dev/null +++ b/packages/noble-curves-tmp/typedoc.cjs @@ -0,0 +1,6 @@ +module.exports = { + extends: '../../config/typedoc.cjs', + entryPoints: ['src'], + out: 'docs', + exclude: ['test/*.ts'], +} From a1cb906fc313c606d8ca2f6265faf591cb1f8458 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 22 Apr 2025 16:26:42 +0200 Subject: [PATCH 08/10] remove noble pkg again [no ci] --- packages/noble-curves-tmp/.c8rc.json | 4 - packages/noble-curves-tmp/.gitignore | 1 - packages/noble-curves-tmp/CHANGELOG.md | 19 - packages/noble-curves-tmp/LICENSE | 22 - packages/noble-curves-tmp/README.md | 114 -- packages/noble-curves-tmp/eslint.config.mjs | 19 - packages/noble-curves-tmp/package.json | 63 - .../noble-curves-tmp/src/_shortw_utils.ts | 30 - packages/noble-curves-tmp/src/abstract/bls.ts | 573 ------- .../noble-curves-tmp/src/abstract/curve.ts | 466 ------ .../noble-curves-tmp/src/abstract/edwards.ts | 567 ------- .../src/abstract/hash-to-curve.ts | 265 --- .../noble-curves-tmp/src/abstract/modular.ts | 555 ------- .../src/abstract/montgomery.ts | 190 --- .../noble-curves-tmp/src/abstract/poseidon.ts | 329 ---- .../noble-curves-tmp/src/abstract/tower.ts | 664 -------- .../noble-curves-tmp/src/abstract/utils.ts | 378 ----- .../src/abstract/weierstrass.ts | 1419 ----------------- packages/noble-curves-tmp/src/bls12-381.ts | 774 --------- packages/noble-curves-tmp/src/bn254.ts | 255 --- packages/noble-curves-tmp/src/ed25519.ts | 554 ------- packages/noble-curves-tmp/src/ed448.ts | 522 ------ packages/noble-curves-tmp/src/index.ts | 17 - packages/noble-curves-tmp/src/jubjub.ts | 5 - packages/noble-curves-tmp/src/misc.ts | 117 -- packages/noble-curves-tmp/src/nist.ts | 171 -- packages/noble-curves-tmp/src/p256.ts | 23 - packages/noble-curves-tmp/src/p384.ts | 23 - packages/noble-curves-tmp/src/p521.ts | 23 - packages/noble-curves-tmp/src/package.json | 3 - packages/noble-curves-tmp/src/pasta.ts | 1 - packages/noble-curves-tmp/src/secp256k1.ts | 343 ---- packages/noble-curves-tmp/tsconfig.json | 7 - packages/noble-curves-tmp/tsconfig.lint.json | 3 - .../noble-curves-tmp/tsconfig.prod.cjs.json | 9 - .../noble-curves-tmp/tsconfig.prod.esm.json | 13 - packages/noble-curves-tmp/typedoc.cjs | 6 - 37 files changed, 8547 deletions(-) delete mode 100644 packages/noble-curves-tmp/.c8rc.json delete mode 100644 packages/noble-curves-tmp/.gitignore delete mode 100644 packages/noble-curves-tmp/CHANGELOG.md delete mode 100644 packages/noble-curves-tmp/LICENSE delete mode 100644 packages/noble-curves-tmp/README.md delete mode 100644 packages/noble-curves-tmp/eslint.config.mjs delete mode 100644 packages/noble-curves-tmp/package.json delete mode 100644 packages/noble-curves-tmp/src/_shortw_utils.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/bls.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/curve.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/edwards.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/hash-to-curve.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/modular.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/montgomery.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/poseidon.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/tower.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/utils.ts delete mode 100644 packages/noble-curves-tmp/src/abstract/weierstrass.ts delete mode 100644 packages/noble-curves-tmp/src/bls12-381.ts delete mode 100644 packages/noble-curves-tmp/src/bn254.ts delete mode 100644 packages/noble-curves-tmp/src/ed25519.ts delete mode 100644 packages/noble-curves-tmp/src/ed448.ts delete mode 100644 packages/noble-curves-tmp/src/index.ts delete mode 100644 packages/noble-curves-tmp/src/jubjub.ts delete mode 100644 packages/noble-curves-tmp/src/misc.ts delete mode 100644 packages/noble-curves-tmp/src/nist.ts delete mode 100644 packages/noble-curves-tmp/src/p256.ts delete mode 100644 packages/noble-curves-tmp/src/p384.ts delete mode 100644 packages/noble-curves-tmp/src/p521.ts delete mode 100644 packages/noble-curves-tmp/src/package.json delete mode 100644 packages/noble-curves-tmp/src/pasta.ts delete mode 100644 packages/noble-curves-tmp/src/secp256k1.ts delete mode 100644 packages/noble-curves-tmp/tsconfig.json delete mode 100644 packages/noble-curves-tmp/tsconfig.lint.json delete mode 100644 packages/noble-curves-tmp/tsconfig.prod.cjs.json delete mode 100644 packages/noble-curves-tmp/tsconfig.prod.esm.json delete mode 100644 packages/noble-curves-tmp/typedoc.cjs diff --git a/packages/noble-curves-tmp/.c8rc.json b/packages/noble-curves-tmp/.c8rc.json deleted file mode 100644 index 52eb43c23b8..00000000000 --- a/packages/noble-curves-tmp/.c8rc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../../config/.c8rc.json", - "include": ["src/**/*.ts"] -} diff --git a/packages/noble-curves-tmp/.gitignore b/packages/noble-curves-tmp/.gitignore deleted file mode 100644 index 8b137891791..00000000000 --- a/packages/noble-curves-tmp/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/noble-curves-tmp/CHANGELOG.md b/packages/noble-curves-tmp/CHANGELOG.md deleted file mode 100644 index 796d8e1acff..00000000000 --- a/packages/noble-curves-tmp/CHANGELOG.md +++ /dev/null @@ -1,19 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -(modification: no type change headlines) and this project adheres to -[Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## 10.0.0-dev-rc.1 - 2025-03-24 - -Initial development release - -Features: - -- Export history data as Era1 -- Read Era1 files which store pre-merge execution layer block history in 8192 block increments (i.e. eras) -- Read Era files which store SSZ encoded signed beacon blocks by era (8192 blocks) - -Note: This library is still **experimental** and the API might change along minor release versions! \ No newline at end of file diff --git a/packages/noble-curves-tmp/LICENSE b/packages/noble-curves-tmp/LICENSE deleted file mode 100644 index 4a5293bea8d..00000000000 --- a/packages/noble-curves-tmp/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2025 EthereumJS - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/packages/noble-curves-tmp/README.md b/packages/noble-curves-tmp/README.md deleted file mode 100644 index 9c62e0c14ae..00000000000 --- a/packages/noble-curves-tmp/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# @ethereumjs/era - -[![NPM Package][era-npm-badge]][era-npm-link] -[![GitHub Issues][era-issues-badge]][era-issues-link] -[![Actions Status][era-actions-badge]][era-actions-link] -[![Code Coverage][era-coverage-badge]][era-coverage-link] -[![Discord][discord-badge]][discord-link] - -| A collection of utility functions for Ethereum. | -| ----------------------------------------------- | - -## Installation - -To obtain the latest version, simply require the project using `npm`: - -```shell -npm install @ethereumjs/era -``` - -## Usage - -All helpers are re-exported from the root level and deep imports are not necessary. So an import can be done like this: - -```ts -import { formatEntry } from "@ethereumjs/era"; -``` - -### Export History as Era1 - -Export history in epochs of 8192 blocks as Era1 files - -```ts -import { exportEpochAsEra1 } from "@ethereumjs/era"; - -const dataDir = PATH_TO_ETHEREUMJS_CLIENT_DB; -const epoch = 0; - -// generates ${dataDir}/era1/epoch-0.era1 -await exportEpochAsEra1(epoch, dataDir); -``` - -### Read Era1 file - -`readERA1` returns an async iterator of block tuples (header + body + receipts + totalDifficulty) - -```ts -import { - readBinaryFile, - validateERA1, - readERA1, - parseBlockTuple, - blockFromTuple, - getHeaderRecords, - EpochAccumulator, -} from "@ethereumjs/era"; - -const era1File = readBinaryFile(PATH_TO_ERA1_FILE); - -// validate era1 file -const isValid = validateERA1(era1File); - -// read blocks from era1 file -const blocks = readERA1(era1File); - -for await (const blockTuple of blocks) { - const { header, body, receipts } = await parseBlockTuple(blockTuple); - const block = blockFromTuple({ header, body }); - console.log(block.header.number); -} - -// reconstruct epoch accumulator -const headerRecords = await getHeaderRecords(era1File); -const epochAccumulator = EpochAccumulator.encode(headerRecords); -const epochAccumulatorRoot = EpochAccumulator.merkleRoot(headerRecords); -``` - -### Read Era file - -```ts -import { readBeaconState } from "@ethereumjs/era"; - -const eraFile = readBinaryFile(PATH_TO_ERA_FILE); - -// Extract BeaconState -const state = await readBeaconState(eraFile); -console.log(state.slot) - -// Read Beacon Blocks from era file -let count = 0 -for await (const block of readBlocksFromEra(eraFile)) { - console.log(block.message.slot) - count++ - if (count > 10) break -} -``` - -## EthereumJS - -See our organizational [documentation](https://ethereumjs.readthedocs.io) for an introduction to `EthereumJS` as well as information on current standards and best practices. If you want to join for work or carry out improvements on the libraries, please review our [contribution guidelines](https://ethereumjs.readthedocs.io/en/latest/contributing.html) first. - -## License - -[MPL-2.0]() - -[era-npm-badge]: https://img.shields.io/npm/v/@ethereumjs/era.svg -[era-npm-link]: https://www.npmjs.org/package/@ethereumjs/era -[era-issues-badge]: https://img.shields.io/github/issues/ethereumjs/ethereumjs-monorepo/package:%20era?label=issues -[era-issues-link]: https://github.com/ethereumjs/ethereumjs-monorepo/issues?q=is%3Aopen+is%3Aissue+label%3A"package%3A+era" -[era-actions-badge]: https://github.com/ethereumjs/ethereumjs-monorepo/workflows/Era/badge.svg -[era-actions-link]: https://github.com/ethereumjs/ethereumjs-monorepo/actions?query=workflow%3A%22Era%22 -[era-coverage-badge]: https://codecov.io/gh/ethereumjs/ethereumjs-monorepo/branch/master/graph/badge.svg?flag=era -[era-coverage-link]: https://codecov.io/gh/ethereumjs/ethereumjs-monorepo/tree/master/packages/era -[discord-badge]: https://img.shields.io/static/v1?logo=discord&label=discord&message=Join&color=blue -[discord-link]: https://discord.gg/TNwARpR diff --git a/packages/noble-curves-tmp/eslint.config.mjs b/packages/noble-curves-tmp/eslint.config.mjs deleted file mode 100644 index a6ffefbcaed..00000000000 --- a/packages/noble-curves-tmp/eslint.config.mjs +++ /dev/null @@ -1,19 +0,0 @@ -import rootConfig from '../../config/eslint.config.mjs' - -export default [ - ...rootConfig, - { - languageOptions: { - parserOptions: { - project: ['./tsconfig.lint.json'], - }, - }, - }, - { - files: ['examples/**/*'], - rules: { - 'no-console': 'off', - '@typescript-eslint/no-unused-vars': 'off', - }, - }, -] diff --git a/packages/noble-curves-tmp/package.json b/packages/noble-curves-tmp/package.json deleted file mode 100644 index ceb38a78dd8..00000000000 --- a/packages/noble-curves-tmp/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "@ethereumjs/nbl-curves-tmp", - "version": "10.0.0-dev-rc.1", - "description": "Era file support for EthereumJS", - "keywords": ["ethereum", "era", "era1"], - "homepage": "https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/era#readme", - "bugs": { - "url": "https://github.com/ethereumjs/ethereumjs-monorepo/issues?q=is%3Aissue+label%3A%22package%3A+era%22" - }, - "repository": { - "type": "git", - "url": "https://github.com/ethereumjs/ethereumjs-monorepo.git" - }, - "license": "MIT", - "author": "EthereumJS Team", - "contributors": [ - { - "name": "ScottyPoi", - "url": "https://github.com/scottypoi" - } - ], - "type": "module", - "sideEffects": false, - "main": "dist/cjs/index.js", - "module": "dist/esm/index.js", - "exports": { - ".": { - "import": { - "typescript": "./src/index.ts", - "default": "./dist/esm/index.js" - }, - "require": "./dist/cjs/index.js" - } - }, - "files": ["dist", "src"], - "scripts": { - "biome": "npx @biomejs/biome check", - "biome:fix": "npx @biomejs/biome check --write", - "build": "../../config/cli/ts-build.sh", - "clean": "../../config/cli/clean-package.sh", - "coverage": "DEBUG=ethjs npx vitest run -c ../../config/vitest.config.coverage.mts", - "coverage:istanbul": "DEBUG=ethjs npx vitest run -c ../../config/vitest.config.coverage.istanbul.mts", - "docs:build": "npx typedoc --options typedoc.cjs", - "examples": "tsx ../../scripts/examples-runner.ts -- util", - "examples:build": "npx embedme README.md", - "lint": "npm run biome && eslint --config ./eslint.config.mjs .", - "lint:fix": "npm run biome:fix && eslint --fix --config ./eslint.config.mjs .", - "prepublishOnly": "../../config/cli/prepublish.sh", - "sc": "npm run spellcheck", - "spellcheck": "npm run spellcheck:ts && npm run spellcheck:md", - "spellcheck:ts": "npx cspell --gitignore -c ../../config/cspell-ts.json \"./**/*.ts\" --cache --show-suggestions --show-context", - "spellcheck:md": "npx cspell --gitignore -c ../../config/cspell-md.json \"**.md\" --cache --show-suggestions --show-context", - "test": "npm run test:node", - "test:node": "npx vitest run -c ../../config/vitest.config.mts", - "tsc": "../../config/cli/ts-compile.sh" - }, - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": ">=18" - } -} diff --git a/packages/noble-curves-tmp/src/_shortw_utils.ts b/packages/noble-curves-tmp/src/_shortw_utils.ts deleted file mode 100644 index d5bc2717d58..00000000000 --- a/packages/noble-curves-tmp/src/_shortw_utils.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Utilities for short weierstrass curves, combined with noble-hashes. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { hmac } from '@noble/hashes/hmac' -import { concatBytes, randomBytes } from '@noble/hashes/utils' -import type { CHash } from './abstract/utils.ts' -import { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.ts' - -/** connects noble-curves to noble-hashes */ -export function getHash(hash: CHash): { - hash: CHash - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array - randomBytes: typeof randomBytes -} { - return { - hash, - hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)), - randomBytes, - } -} -/** Same API as @noble/hashes, with ability to create curve with custom hash */ -export type CurveDef = Readonly> -export type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn } - -export function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate { - const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, ...getHash(hash) }) - return { ...create(defHash), create } -} diff --git a/packages/noble-curves-tmp/src/abstract/bls.ts b/packages/noble-curves-tmp/src/abstract/bls.ts deleted file mode 100644 index 37e8eead962..00000000000 --- a/packages/noble-curves-tmp/src/abstract/bls.ts +++ /dev/null @@ -1,573 +0,0 @@ -/** - * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. - * BLS != BLS. - * The file implements BLS (Boneh-Lynn-Shacham) signatures. - * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) - * families of pairing-friendly curves. - * Consists of two curves: G1 and G2: - * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. - * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 - * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in - * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. - * Pairing is used to aggregate and verify signatures. - * There are two main ways to use it: - * 1. Fp for short private keys, Fp₂ for signatures - * 2. Fp for short signatures, Fp₂ for private keys - * @module - **/ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// TODO: import { AffinePoint } from './curve.ts'; -import { - type H2CPointConstructor, - type Opts as HTFOpts, - type MapToCurve, - createHasher, - type htfBasicOpts, -} from './hash-to-curve.ts' -import { type IField, getMinHashLength, mapHashToField } from './modular.ts' -import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.ts' -import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.ts' -import { - type CurvePointsRes, - type CurvePointsType, - type ProjPointType, - weierstrassPoints, -} from './weierstrass.ts' - -type Fp = bigint // Can be different field? - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) - -export type TwistType = 'multiplicative' | 'divisive' - -export type ShortSignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} - -export type SignatureCoder = { - fromHex(hex: Hex): ProjPointType - toRawBytes(point: ProjPointType): Uint8Array - toHex(point: ProjPointType): string -} - -export type PostPrecomputePointAddFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, -) => { Rx: Fp2; Ry: Fp2; Rz: Fp2 } -export type PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => void -export type CurveType = { - G1: Omit, 'n'> & { - ShortSignature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - G2: Omit, 'n'> & { - Signature: SignatureCoder - mapToCurve: MapToCurve - htfDefaults: HTFOpts - } - fields: { - Fp: IField - Fr: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - } - params: { - // NOTE: MSB is always ignored and used as marker for length, - // otherwise leading zeros will be lost. - // Can be different from 'X' (seed) param! - ateLoopSize: bigint - xNegative: boolean - r: bigint - twistType: TwistType // BLS12-381: Multiplicative, BN254: Divisive - } - htfDefaults: HTFOpts - hash: CHash // Because we need outputLen for DRBG - randomBytes: (bytesLength?: number) => Uint8Array - // This is super ugly hack for untwist point in BN254 after miller loop - postPrecompute?: PostPrecomputeFn -} - -type PrecomputeSingle = [Fp2, Fp2, Fp2][] -type Precompute = PrecomputeSingle[] - -export type CurveFn = { - getPublicKey: (privateKey: PrivKey) => Uint8Array - getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array - sign: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - signShortSignature: { - (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType - } - verify: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyShortSignature: ( - signature: Hex | ProjPointType, - message: Hex | ProjPointType, - publicKey: Hex | ProjPointType, - htfOpts?: htfBasicOpts, - ) => boolean - verifyBatch: ( - signature: Hex | ProjPointType, - messages: (Hex | ProjPointType)[], - publicKeys: (Hex | ProjPointType)[], - htfOpts?: htfBasicOpts, - ) => boolean - aggregatePublicKeys: { - (publicKeys: Hex[]): Uint8Array - (publicKeys: ProjPointType[]): ProjPointType - } - aggregateSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - aggregateShortSignatures: { - (signatures: Hex[]): Uint8Array - (signatures: ProjPointType[]): ProjPointType - } - millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 - pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 - pairingBatch: ( - pairs: { g1: ProjPointType; g2: ProjPointType }[], - withFinalExponent?: boolean, - ) => Fp12 - G1: CurvePointsRes & ReturnType> - G2: CurvePointsRes & ReturnType> - Signature: SignatureCoder - ShortSignature: ShortSignatureCoder - params: { - ateLoopSize: bigint - r: bigint - G1b: bigint - G2b: Fp2 - } - fields: { - Fp: IField - Fp2: Fp2Bls - Fp6: IField - Fp12: Fp12Bls - Fr: IField - } - utils: { - randomPrivateKey: () => Uint8Array - calcPairingPrecomputes: (p: ProjPointType) => Precompute - } -} - -// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. -function NAfDecomposition(a: bigint) { - const res = [] - // a>1 because of marker bit - for (; a > _1n; a >>= _1n) { - if ((a & _1n) === _0n) res.unshift(0) - else if ((a & _3n) === _3n) { - res.unshift(-1) - a += _1n - } else res.unshift(1) - } - return res -} - -export function bls(CURVE: CurveType): CurveFn { - // Fields are specific for curve, so for now we'll need to pass them with opts - const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields - const BLS_X_IS_NEGATIVE = CURVE.params.xNegative - const TWIST: TwistType = CURVE.params.twistType - // Point on G1 curve: (x, y) - const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) - const G1 = Object.assign( - G1_, - createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G1.htfDefaults, - }), - ) - // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) - const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) - const G2 = Object.assign( - G2_, - createHasher(G2_.ProjectivePoint as H2CPointConstructor, CURVE.G2.mapToCurve, { - ...CURVE.htfDefaults, - ...CURVE.G2.htfDefaults, - }), - ) - type G1 = typeof G1.ProjectivePoint.BASE - type G2 = typeof G2.ProjectivePoint.BASE - - // Applies sparse multiplication as line function - let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12 - if (TWIST === 'multiplicative') { - lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => - Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) - } else if (TWIST === 'divisive') { - // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of - // precompute calculations. - lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => - Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) - } else throw new Error('bls: unknown twist type') - - const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) - function pointDouble(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2) { - const t0 = Fp2.sqr(Ry) // Ry² - const t1 = Fp2.sqr(Rz) // Rz² - const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B - const t3 = Fp2.mul(t2, _3n) // 3 * T2 - const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 - const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) - const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² - const c2 = Fp2.neg(t4) // -T4 (-h) - - ell.push([c0, c1, c2]) - - Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 - Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² - Rz = Fp2.mul(t0, t4) // T0 * T4 - return { Rx, Ry, Rz } - } - function pointAdd(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) { - // Addition - const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz - const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz - const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy - const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry - const c2 = t1 // == Rx - Qx * Rz - - ell.push([c0, c1, c2]) - - const t2 = Fp2.sqr(t1) // T1² - const t3 = Fp2.mul(t2, t1) // T2 * T1 - const t4 = Fp2.mul(t2, Rx) // T2 * Rx - const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz - Rx = Fp2.mul(t1, t5) // T1 * T5 - Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry - Rz = Fp2.mul(Rz, t3) // Rz * T3 - return { Rx, Ry, Rz } - } - - // Pre-compute coefficients for sparse multiplication - // Point addition and point double calculations is reused for coefficients - // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine - // add + double in windowed precomputes here, otherwise it would be single op (since X is static) - const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) - - const calcPairingPrecomputes = memoized((point: G2) => { - const p = point - const { x, y } = p.toAffine() - // prettier-ignore - const Qx = x, - Qy = y, - negQy = Fp2.neg(y) - // prettier-ignore - let Rx = Qx, - Ry = Qy, - Rz = Fp2.ONE - const ell: Precompute = [] - for (const bit of ATE_NAF) { - const cur: PrecomputeSingle = [] - ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) - if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) - ell.push(cur) - } - if (CURVE.postPrecompute) { - const last = ell[ell.length - 1] - CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) - } - return ell - }) - - // Main pairing logic is here. Computes product of miller loops + final exponentiate - // Applies calculated precomputes - type MillerInput = [Precompute, Fp, Fp][] - function millerLoopBatch(pairs: MillerInput, withFinalExponent: boolean = false) { - let f12 = Fp12.ONE - if (pairs.length) { - const ellLen = pairs[0][0].length - for (let i = 0; i < ellLen; i++) { - f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings - // NOTE: we apply multiple pairings in parallel here - for (const [ell, Px, Py] of pairs) { - for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) - } - } - } - if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) - return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 - } - type PairingInput = { g1: G1; g2: G2 } - // Calculates product of multiple pairings - // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` - function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) { - const res: MillerInput = [] - // This cache precomputed toAffine for all points - G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) - G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) - for (const { g1, g2 } of pairs) { - if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) - throw new Error('pairing is not available for ZERO point') - // This uses toAffine inside - g1.assertValidity() - g2.assertValidity() - const Qa = g1.toAffine() - res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) - } - return millerLoopBatch(res, withFinalExponent) - } - // Calculates bilinear pairing - function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 { - return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) - } - - const utils = { - randomPrivateKey: (): Uint8Array => { - const length = getMinHashLength(Fr.ORDER) - return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) - }, - calcPairingPrecomputes, - } - - const { ShortSignature } = CURVE.G1 - const { Signature } = CURVE.G2 - - type G1Hex = Hex | G1 - type G2Hex = Hex | G2 - function normP1(point: G1Hex): G1 { - return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point) - } - function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 { - return point instanceof G1.ProjectivePoint - ? point - : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1) - } - function normP2(point: G2Hex): G2 { - return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) - } - function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 { - return point instanceof G2.ProjectivePoint - ? point - : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2) - } - - // Multiplies generator (G1) by private key. - // P = pk x G - function getPublicKey(privateKey: PrivKey): Uint8Array { - return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - - // Multiplies generator (G2) by private key. - // P = pk x G - function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array { - return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) - } - - // Executes `hashToCurve` on the message and then multiplies the result by private key. - // S = pk x H(m) - function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2 - function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 { - const msgPoint = normP2Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G2.ProjectivePoint) return sigPoint - return Signature.toRawBytes(sigPoint) - } - - function signShortSignature(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array - function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1 - function signShortSignature( - message: G1Hex, - privateKey: PrivKey, - htfOpts?: htfBasicOpts, - ): Uint8Array | G1 { - const msgPoint = normP1Hash(message, htfOpts) - msgPoint.assertValidity() - const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) - if (message instanceof G1.ProjectivePoint) return sigPoint - return ShortSignature.toRawBytes(sigPoint) - } - - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(P, H(m)) == e(G, S) - function verify( - signature: G2Hex, - message: G2Hex, - publicKey: G1Hex, - htfOpts?: htfBasicOpts, - ): boolean { - const P = normP1(publicKey) - const Hm = normP2Hash(message, htfOpts) - const G = G1.ProjectivePoint.BASE - const S = normP2(signature) - const exp = pairingBatch([ - { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); - { g1: G, g2: S }, // eGS = pairing(G, S, false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - - // Checks if pairing of public key & hash is equal to pairing of generator & signature. - // e(S, G) == e(H(m), P) - function verifyShortSignature( - signature: G1Hex, - message: G1Hex, - publicKey: G2Hex, - htfOpts?: htfBasicOpts, - ): boolean { - const P = normP2(publicKey) - const Hm = normP1Hash(message, htfOpts) - const G = G2.ProjectivePoint.BASE - const S = normP1(signature) - const exp = pairingBatch([ - { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); - { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); - ]) - return Fp12.eql(exp, Fp12.ONE) - } - - function aNonEmpty(arr: any[]) { - if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') - } - - // Adds a bunch of public key points together. - // pk1 + pk2 + pk3 = pkA - function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array - function aggregatePublicKeys(publicKeys: G1[]): G1 - function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 { - aNonEmpty(publicKeys) - const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (publicKeys[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - // toRawBytes ensures point validity - return aggAffine.toRawBytes(true) - } - - // Adds a bunch of signature points together. - function aggregateSignatures(signatures: Hex[]): Uint8Array - function aggregateSignatures(signatures: G2[]): G2 - function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 { - aNonEmpty(signatures) - const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G2.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return Signature.toRawBytes(aggAffine) - } - - // Adds a bunch of signature points together. - function aggregateShortSignatures(signatures: Hex[]): Uint8Array - function aggregateShortSignatures(signatures: G1[]): G1 - function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 { - aNonEmpty(signatures) - const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) - const aggAffine = agg //.toAffine(); - if (signatures[0] instanceof G1.ProjectivePoint) { - aggAffine.assertValidity() - return aggAffine - } - return ShortSignature.toRawBytes(aggAffine) - } - - // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 - // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) - function verifyBatch( - signature: G2Hex, - // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? - messages: G2Hex[], - publicKeys: G1Hex[], - htfOpts?: htfBasicOpts, - ): boolean { - aNonEmpty(messages) - if (publicKeys.length !== messages.length) - throw new Error('amount of public keys and messages should be equal') - const sig = normP2(signature) - const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) - const nPublicKeys = publicKeys.map(normP1) - // NOTE: this works only for exact same object - const messagePubKeyMap = new Map() - for (let i = 0; i < nPublicKeys.length; i++) { - const pub = nPublicKeys[i] - const msg = nMessages[i] - let keys = messagePubKeyMap.get(msg) - if (keys === undefined) { - keys = [] - messagePubKeyMap.set(msg, keys) - } - keys.push(pub) - } - const paired = [] - try { - for (const [msg, keys] of messagePubKeyMap) { - const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) - paired.push({ g1: groupPublicKey, g2: msg }) - } - paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) - return Fp12.eql(pairingBatch(paired), Fp12.ONE) - } catch { - return false - } - } - - G1.ProjectivePoint.BASE._setWindowSize(4) - - return { - getPublicKey, - getPublicKeyForShortSignatures, - sign, - signShortSignature, - verify, - verifyBatch, - verifyShortSignature, - aggregatePublicKeys, - aggregateSignatures, - aggregateShortSignatures, - millerLoopBatch, - pairing, - pairingBatch, - G1, - G2, - Signature, - ShortSignature, - fields: { - Fr, - Fp, - Fp2, - Fp6, - Fp12, - }, - params: { - ateLoopSize: CURVE.params.ateLoopSize, - r: CURVE.params.r, - G1b: CURVE.G1.b, - G2b: CURVE.G2.b, - }, - utils, - } -} diff --git a/packages/noble-curves-tmp/src/abstract/curve.ts b/packages/noble-curves-tmp/src/abstract/curve.ts deleted file mode 100644 index 6a7830a1970..00000000000 --- a/packages/noble-curves-tmp/src/abstract/curve.ts +++ /dev/null @@ -1,466 +0,0 @@ -/** - * Methods for elliptic curve multiplication by scalars. - * Contains wNAF, pippenger - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type IField, nLength, validateField } from './modular.ts' -import { bitLen, bitMask, validateObject } from './utils.ts' - -const _0n = BigInt(0) -const _1n = BigInt(1) - -export type AffinePoint = { - x: T - y: T -} & { z?: never; t?: never } - -export interface Group> { - double(): T - negate(): T - add(other: T): T - subtract(other: T): T - equals(other: T): boolean - multiply(scalar: bigint): T -} - -export type GroupConstructor = { - BASE: T - ZERO: T -} -export type Mapper = (i: T[]) => T[] - -function constTimeNegate>(condition: boolean, item: T): T { - const neg = item.negate() - return condition ? neg : item -} - -function validateW(W: number, bits: number) { - if (!Number.isSafeInteger(W) || W <= 0 || W > bits) - throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) -} - -/** Internal wNAF opts for specific W and scalarBits */ -export type WOpts = { - windows: number - windowSize: number - mask: bigint - maxNumber: number - shiftBy: bigint -} - -function calcWOpts(W: number, scalarBits: number): WOpts { - validateW(W, scalarBits) - const windows = Math.ceil(scalarBits / W) + 1 // W=8 33. Not 32, because we skip zero - const windowSize = 2 ** (W - 1) // W=8 128. Not 256, because we skip zero - const maxNumber = 2 ** W // W=8 256 - const mask = bitMask(W) // W=8 255 == mask 0b11111111 - const shiftBy = BigInt(W) // W=8 8 - return { windows, windowSize, mask, maxNumber, shiftBy } -} - -function calcOffsets(n: bigint, window: number, wOpts: WOpts) { - const { windowSize, mask, maxNumber, shiftBy } = wOpts - let wbits = Number(n & mask) // extract W bits. - let nextN = n >> shiftBy // shift number by W bits. - - // What actually happens here: - // const highestBit = Number(mask ^ (mask >> 1n)); - // let wbits2 = wbits - 1; // skip zero - // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~); - - // split if bits > max: +224 => 256-32 - if (wbits > windowSize) { - // we skip zero, which means instead of `>= size-1`, we do `> size` - wbits -= maxNumber // -32, can be maxNumber - wbits, but then we need to set isNeg here. - nextN += _1n // +256 (carry) - } - const offsetStart = window * windowSize - const offset = offsetStart + Math.abs(wbits) - 1 // -1 because we skip zero - const isZero = wbits === 0 // is current window slice a 0? - const isNeg = wbits < 0 // is current window slice negative? - const isNegF = window % 2 !== 0 // fake random statement for noise - const offsetF = offsetStart // fake offset for noise - return { nextN, offset, isZero, isNeg, isNegF, offsetF } -} - -function validateMSMPoints(points: any[], c: any) { - if (!Array.isArray(points)) throw new Error('array expected') - points.forEach((p, i) => { - if (!(p instanceof c)) throw new Error('invalid point at index ' + i) - }) -} -function validateMSMScalars(scalars: any[], field: any) { - if (!Array.isArray(scalars)) throw new Error('array of scalars expected') - scalars.forEach((s, i) => { - if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) - }) -} - -// Since points in different groups cannot be equal (different object constructor), -// we can have single place to store precomputes. -// Allows to make points frozen / immutable. -const pointPrecomputes = new WeakMap() -const pointWindowSizes = new WeakMap() - -function getW(P: any): number { - return pointWindowSizes.get(P) || 1 -} - -export type IWNAF> = { - constTimeNegate: >(condition: boolean, item: T) => T - hasPrecomputes(elm: T): boolean - unsafeLadder(elm: T, n: bigint, p?: T): T - precomputeWindow(elm: T, W: number): Group[] - getPrecomputes(W: number, P: T, transform: Mapper): T[] - wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T - wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T - setWindowSize(P: T, W: number): void -} - -/** - * Elliptic curve multiplication of Point by scalar. Fragile. - * Scalars should always be less than curve order: this should be checked inside of a curve itself. - * Creates precomputation tables for fast multiplication: - * - private scalar is split by fixed size windows of W bits - * - every window point is collected from window's table & added to accumulator - * - since windows are different, same point inside tables won't be accessed more than once per calc - * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) - * - +1 window is neccessary for wNAF - * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication - * - * @todo Research returning 2d JS array of windows, instead of a single window. - * This would allow windows to be in different memory locations - */ -export function wNAF>(c: GroupConstructor, bits: number): IWNAF { - return { - constTimeNegate, - - hasPrecomputes(elm: T) { - return getW(elm) !== 1 - }, - - // non-const time multiplication ladder - unsafeLadder(elm: T, n: bigint, p = c.ZERO) { - let d: T = elm - while (n > _0n) { - if (n & _1n) p = p.add(d) - d = d.double() - n >>= _1n - } - return p - }, - - /** - * Creates a wNAF precomputation window. Used for caching. - * Default window size is set by `utils.precompute()` and is equal to 8. - * Number of precomputed points depends on the curve size: - * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: - * - 𝑊 is the window size - * - 𝑛 is the bitlength of the curve order. - * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. - * @param elm Point instance - * @param W window size - * @returns precomputed point tables flattened to a single array - */ - precomputeWindow(elm: T, W: number): Group[] { - const { windows, windowSize } = calcWOpts(W, bits) - const points: T[] = [] - let p: T = elm - let base = p - for (let window = 0; window < windows; window++) { - base = p - points.push(base) - // i=1, bc we skip 0 - for (let i = 1; i < windowSize; i++) { - base = base.add(p) - points.push(base) - } - p = base.double() - } - return points - }, - - /** - * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @returns real and fake (for const-time) points - */ - wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } { - // Smaller version: - // https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541 - // TODO: check the scalar is less than group order? - // wNAF behavior is undefined otherwise. But have to carefully remove - // other checks before wNAF. ORDER == bits here. - // Accumulators - let p = c.ZERO - let f = c.BASE - // This code was first written with assumption that 'f' and 'p' will never be infinity point: - // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, - // there is negate now: it is possible that negated element from low value - // would be the same as high element, which will create carry into next window. - // It's not obvious how this can fail, but still worth investigating later. - const wo = calcWOpts(W, bits) - for (let window = 0; window < wo.windows; window++) { - // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise - const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo) - n = nextN - if (isZero) { - // bits are 0: add garbage to fake point - // Important part for const-time getPublicKey: add random "noise" point to f. - f = f.add(constTimeNegate(isNegF, precomputes[offsetF])) - } else { - // bits are 1: add to result point - p = p.add(constTimeNegate(isNeg, precomputes[offset])) - } - } - // Return both real and fake points: JIT won't eliminate f. - // At this point there is a way to F be infinity-point even if p is not, - // which makes it less const-time: around 1 bigint multiply. - return { p, f } - }, - - /** - * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. - * @param W window size - * @param precomputes precomputed tables - * @param n scalar (we don't check here, but should be less than curve order) - * @param acc accumulator point to add result of multiplication - * @returns point - */ - wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc: T = c.ZERO): T { - const wo = calcWOpts(W, bits) - for (let window = 0; window < wo.windows; window++) { - if (n === _0n) break // Early-exit, skip 0 value - const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo) - n = nextN - if (isZero) { - // Window bits are 0: skip processing. - // Move to next window. - continue - } else { - const item = precomputes[offset] - acc = acc.add(isNeg ? item.negate() : item) // Re-using acc allows to save adds in MSM - } - } - return acc - }, - - getPrecomputes(W: number, P: T, transform: Mapper): T[] { - // Calculate precomputes on a first run, reuse them after - let comp = pointPrecomputes.get(P) - if (!comp) { - comp = this.precomputeWindow(P, W) as T[] - if (W !== 1) pointPrecomputes.set(P, transform(comp)) - } - return comp - }, - - wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } { - const W = getW(P) - return this.wNAF(W, this.getPrecomputes(W, P, transform), n) - }, - - wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T { - const W = getW(P) - if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster - return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) - }, - - // We calculate precomputes for elliptic curve point multiplication - // using windowed method. This specifies window size and - // stores precomputed values. Usually only base point would be precomputed. - - setWindowSize(P: T, W: number) { - validateW(W, bits) - pointWindowSizes.set(P, W) - pointPrecomputes.delete(P) - }, - } -} - -/** - * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * 30x faster vs naive addition on L=4096, 10x faster than precomputes. - * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. - * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @param scalars array of L scalars (aka private keys / bigints) - */ -export function pippenger>( - c: GroupConstructor, - fieldN: IField, - points: T[], - scalars: bigint[], -): T { - // If we split scalars by some window (let's say 8 bits), every chunk will only - // take 256 buckets even if there are 4096 scalars, also re-uses double. - // TODO: - // - https://eprint.iacr.org/2024/750.pdf - // - https://tches.iacr.org/index.php/TCHES/article/view/10287 - // 0 is accepted in scalars - validateMSMPoints(points, c) - validateMSMScalars(scalars, fieldN) - if (points.length !== scalars.length) - throw new Error('arrays of points and scalars must have equal length') - const zero = c.ZERO - const wbits = bitLen(BigInt(points.length)) - const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits - const MASK = bitMask(windowSize) - const buckets = new Array(Number(MASK) + 1).fill(zero) // +1 for zero array - const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize - let sum = zero - for (let i = lastBits; i >= 0; i -= windowSize) { - buckets.fill(zero) - for (let j = 0; j < scalars.length; j++) { - const scalar = scalars[j] - const wbits = Number((scalar >> BigInt(i)) & MASK) - buckets[wbits] = buckets[wbits].add(points[j]) - } - let resI = zero // not using this will do small speed-up, but will lose ct - // Skip first bucket, because it is zero - for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { - sumI = sumI.add(buckets[j]) - resI = resI.add(sumI) - } - sum = sum.add(resI) - if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() - } - return sum as T -} -/** - * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). - * @param c Curve Point constructor - * @param fieldN field over CURVE.N - important that it's not over CURVE.P - * @param points array of L curve points - * @returns function which multiplies points with scaars - */ -export function precomputeMSMUnsafe>( - c: GroupConstructor, - fieldN: IField, - points: T[], - windowSize: number, -): (scalars: bigint[]) => T { - /** - * Performance Analysis of Window-based Precomputation - * - * Base Case (256-bit scalar, 8-bit window): - * - Standard precomputation requires: - * - 31 additions per scalar × 256 scalars = 7,936 ops - * - Plus 255 summary additions = 8,191 total ops - * Note: Summary additions can be optimized via accumulator - * - * Chunked Precomputation Analysis: - * - Using 32 chunks requires: - * - 255 additions per chunk - * - 256 doublings - * - Total: (255 × 32) + 256 = 8,416 ops - * - * Memory Usage Comparison: - * Window Size | Standard Points | Chunked Points - * ------------|-----------------|--------------- - * 4-bit | 520 | 15 - * 8-bit | 4,224 | 255 - * 10-bit | 13,824 | 1,023 - * 16-bit | 557,056 | 65,535 - * - * Key Advantages: - * 1. Enables larger window sizes due to reduced memory overhead - * 2. More efficient for smaller scalar counts: - * - 16 chunks: (16 × 255) + 256 = 4,336 ops - * - ~2x faster than standard 8,191 ops - * - * Limitations: - * - Not suitable for plain precomputes (requires 256 constant doublings) - * - Performance degrades with larger scalar counts: - * - Optimal for ~256 scalars - * - Less efficient for 4096+ scalars (Pippenger preferred) - */ - validateW(windowSize, fieldN.BITS) - validateMSMPoints(points, c) - const zero = c.ZERO - const tableSize = 2 ** windowSize - 1 // table size (without zero) - const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item - const MASK = bitMask(windowSize) - const tables = points.map((p: T) => { - const res = [] - for (let i = 0, acc = p; i < tableSize; i++) { - res.push(acc) - acc = acc.add(p) - } - return res - }) - return (scalars: bigint[]): T => { - validateMSMScalars(scalars, fieldN) - if (scalars.length > points.length) - throw new Error('array of scalars must be smaller than array of points') - let res = zero - for (let i = 0; i < chunks; i++) { - // No need to double if accumulator is still zero. - if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() - const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) - for (let j = 0; j < scalars.length; j++) { - const n = scalars[j] - const curr = Number((n >> shiftBy) & MASK) - if (!curr) continue // skip zero scalars chunks - res = res.add(tables[j][curr - 1]) - } - } - return res - } -} - -/** - * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. - * Though generator can be different (Fp2 / Fp6 for BLS). - */ -export type BasicCurve = { - Fp: IField // Field over which we'll do calculations (Fp) - n: bigint // Curve order, total count of valid points in the field - nBitLength?: number // bit length of curve order - nByteLength?: number // byte length of curve order - h: bigint // cofactor. we can assign default=1, but users will just ignore it w/o validation - hEff?: bigint // Number to multiply to clear cofactor - Gx: T // base point X coordinate - Gy: T // base point Y coordinate - allowInfinityPoint?: boolean // bls12-381 requires it. ZERO point is valid, but invalid pubkey -} - -export function validateBasic( - curve: BasicCurve & T, -): Readonly< - { - readonly nBitLength: number - readonly nByteLength: number - } & BasicCurve & - T & { - p: bigint - } -> { - validateField(curve.Fp) - validateObject( - curve, - { - n: 'bigint', - h: 'bigint', - Gx: 'field', - Gy: 'field', - }, - { - nBitLength: 'isSafeInteger', - nByteLength: 'isSafeInteger', - }, - ) - // Set defaults - return Object.freeze({ - ...nLength(curve.n, curve.nBitLength), - ...curve, - ...{ p: curve.Fp.ORDER }, - } as const) -} diff --git a/packages/noble-curves-tmp/src/abstract/edwards.ts b/packages/noble-curves-tmp/src/abstract/edwards.ts deleted file mode 100644 index d54d0d5da78..00000000000 --- a/packages/noble-curves-tmp/src/abstract/edwards.ts +++ /dev/null @@ -1,567 +0,0 @@ -/** - * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². - * For design rationale of types / exports, see weierstrass module documentation. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - type AffinePoint, - type BasicCurve, - type Group, - type GroupConstructor, - pippenger, - validateBasic, - wNAF, -} from './curve.ts' -import { Field, mod } from './modular.ts' -// prettier-ignore -import { - type FHash, - type Hex, - aInRange, - abool, - bytesToHex, - bytesToNumberLE, - concatBytes, - ensureBytes, - memoized, - numberToBytesLE, - validateObject, -} from './utils.ts' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _8n = BigInt(8) - -/** Edwards curves must declare params a & d. */ -export type CurveType = BasicCurve & { - a: bigint // curve param a - d: bigint // curve param d - hash: FHash // Hashing - randomBytes: (bytesLength?: number) => Uint8Array // CSPRNG - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array // clears bits to get valid field elemtn - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array // Used for hashing - uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint } // Ratio √(u/v) - prehash?: FHash // RFC 8032 pre-hashing of messages to sign() / verify() - mapToCurve?: (scalar: bigint[]) => AffinePoint // for hash-to-curve standard -} - -export type CurveTypeWithLength = Readonly - -// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: -const VERIFY_DEFAULT = { zip215: true } - -function validateOpts(curve: CurveType): CurveTypeWithLength { - const opts = validateBasic(curve) - validateObject( - curve, - { - hash: 'function', - a: 'bigint', - d: 'bigint', - randomBytes: 'function', - }, - { - adjustScalarBytes: 'function', - domain: 'function', - uvRatio: 'function', - mapToCurve: 'function', - }, - ) - // Set defaults - return Object.freeze({ ...opts } as const) -} - -/** Instance of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointType extends Group { - readonly ex: bigint - readonly ey: bigint - readonly ez: bigint - readonly et: bigint - get x(): bigint - get y(): bigint - assertValidity(): void - multiply(scalar: bigint): ExtPointType - multiplyUnsafe(scalar: bigint): ExtPointType - isSmallOrder(): boolean - isTorsionFree(): boolean - clearCofactor(): ExtPointType - toAffine(iz?: bigint): AffinePoint - toRawBytes(isCompressed?: boolean): Uint8Array - toHex(isCompressed?: boolean): string - _setWindowSize(windowSize: number): void -} -/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ -export interface ExtPointConstructor extends GroupConstructor { - new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType - fromAffine(p: AffinePoint): ExtPointType - fromHex(hex: Hex): ExtPointType - fromPrivateKey(privateKey: Hex): ExtPointType - msm(points: ExtPointType[], scalars: bigint[]): ExtPointType -} - -/** - * Edwards Curve interface. - * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. - */ -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: Hex) => Uint8Array - sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array - verify: ( - sig: Hex, - message: Hex, - publicKey: Hex, - options?: { context?: Hex; zip215: boolean }, - ) => boolean - ExtendedPoint: ExtPointConstructor - utils: { - randomPrivateKey: () => Uint8Array - getExtendedPublicKey: (key: Hex) => { - head: Uint8Array - prefix: Uint8Array - scalar: bigint - point: ExtPointType - pointBytes: Uint8Array - } - precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType - } -} - -/** - * Creates Twisted Edwards curve with EdDSA signatures. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h - * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) - */ -export function twistedEdwards(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) as ReturnType - const { - Fp, - n: CURVE_ORDER, - prehash: prehash, - hash: cHash, - randomBytes, - nByteLength, - h: cofactor, - } = CURVE - // Important: - // There are some places where Fp.BYTES is used instead of nByteLength. - // So far, everything has been tested with curves of Fp.BYTES == nByteLength. - // TODO: test and find curves which behave otherwise. - const MASK = _2n << (BigInt(nByteLength * 8) - _1n) - const modP = Fp.create // Function overrides - const Fn = Field(CURVE.n, CURVE.nBitLength) - - // sqrt(u/v) - const uvRatio = - CURVE.uvRatio || - ((u: bigint, v: bigint) => { - try { - return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } - } catch (e) { - return { isValid: false, value: _0n } - } - }) - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) // NOOP - const domain = - CURVE.domain || - ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { - abool('phflag', phflag) - if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') - return data - }) // NOOP - // 0 <= n < MASK - // Coordinates larger than Fp.ORDER are allowed for zip215 - function aCoordinate(title: string, n: bigint, banZero = false) { - const min = banZero ? _1n : _0n - aInRange('coordinate ' + title, n, min, MASK) - } - - function aextpoint(other: unknown) { - if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') - } - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint => { - const { ex: x, ey: y, ez: z } = p - const is0 = p.is0() - if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint) // 8 was chosen arbitrarily - const ax = modP(x * iz) - const ay = modP(y * iz) - const zz = modP(z * iz) - if (is0) return { x: _0n, y: _1n } - if (zz !== _1n) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - const assertValidMemo = memoized((p: Point) => { - const { a, d } = CURVE - if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? - // Equation in affine coordinates: ax² + y² = 1 + dx²y² - // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² - const { ex: X, ey: Y, ez: Z, et: T } = p - const X2 = modP(X * X) // X² - const Y2 = modP(Y * Y) // Y² - const Z2 = modP(Z * Z) // Z² - const Z4 = modP(Z2 * Z2) // Z⁴ - const aX2 = modP(X2 * a) // aX² - const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² - const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² - if (left !== right) throw new Error('bad point: equation left != right (1)') - // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T - const XY = modP(X * Y) - const ZT = modP(Z * T) - if (XY !== ZT) throw new Error('bad point: equation left != right (2)') - return true - }) - - // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). - // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates - class Point implements ExtPointType { - static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) - static readonly ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 - readonly ex: bigint - readonly ey: bigint - readonly ez: bigint - readonly et: bigint - - constructor(ex: bigint, ey: bigint, ez: bigint, et: bigint) { - aCoordinate('x', ex) - aCoordinate('y', ey) - aCoordinate('z', ez, true) - aCoordinate('t', et) - this.ex = ex - this.ey = ey - this.ez = ez - this.et = et - Object.freeze(this) - } - - get x(): bigint { - return this.toAffine().x - } - get y(): bigint { - return this.toAffine().y - } - - static fromAffine(p: AffinePoint): Point { - if (p instanceof Point) throw new Error('extended point not allowed') - const { x, y } = p || {} - aCoordinate('x', x) - aCoordinate('y', y) - return new Point(x, y, _1n, modP(x * y)) - } - static normalizeZ(points: Point[]): Point[] { - const toInv = Fp.invertBatch(points.map((p) => p.ez)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - // Multiscalar Multiplication - static msm(points: Point[], scalars: bigint[]): Point { - return pippenger(Point, Fn, points, scalars) - } - - // "Private method", don't use it directly - _setWindowSize(windowSize: number) { - wnaf.setWindowSize(this, windowSize) - } - // Not required for fromHex(), which always creates valid points. - // Could be useful for fromAffine(). - assertValidity(): void { - assertValidMemo(this) - } - - // Compare one point to another. - equals(other: Point): boolean { - aextpoint(other) - const { ex: X1, ey: Y1, ez: Z1 } = this - const { ex: X2, ey: Y2, ez: Z2 } = other - const X1Z2 = modP(X1 * Z2) - const X2Z1 = modP(X2 * Z1) - const Y1Z2 = modP(Y1 * Z2) - const Y2Z1 = modP(Y2 * Z1) - return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 - } - - is0(): boolean { - return this.equals(Point.ZERO) - } - - negate(): Point { - // Flips point sign to a negative one (-x, y in affine coords) - return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) - } - - // Fast algo for doubling Extended Point. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd - // Cost: 4M + 4S + 1*a + 6add + 1*2. - double(): Point { - const { a } = CURVE - const { ex: X1, ey: Y1, ez: Z1 } = this - const A = modP(X1 * X1) // A = X12 - const B = modP(Y1 * Y1) // B = Y12 - const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 - const D = modP(a * A) // D = a*A - const x1y1 = X1 + Y1 - const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B - const G = D + B // G = D+B - const F = G - C // F = G-C - const H = D - B // H = D-B - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - - // Fast algo for adding 2 Extended Points. - // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd - // Cost: 9M + 1*a + 1*d + 7add. - add(other: Point) { - aextpoint(other) - const { a, d } = CURVE - const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this - const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other - const A = modP(X1 * X2) // A = X1*X2 - const B = modP(Y1 * Y2) // B = Y1*Y2 - const C = modP(T1 * d * T2) // C = T1*d*T2 - const D = modP(Z1 * Z2) // D = Z1*Z2 - const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B - const F = D - C // F = D-C - const G = D + C // G = D+C - const H = modP(B - a * A) // H = B-a*A - const X3 = modP(E * F) // X3 = E*F - const Y3 = modP(G * H) // Y3 = G*H - const T3 = modP(E * H) // T3 = E*H - const Z3 = modP(F * G) // Z3 = F*G - return new Point(X3, Y3, Z3, T3) - } - - subtract(other: Point): Point { - return this.add(other.negate()) - } - - private wNAF(n: bigint): { p: Point; f: Point } { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - - // Constant-time multiplication. - multiply(scalar: bigint): Point { - const n = scalar - aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L - const { p, f } = this.wNAF(n) - return Point.normalizeZ([p, f])[0] - } - - // Non-constant-time multiplication. Uses double-and-add algorithm. - // It's faster, but should only be used when you don't care about - // an exposed private key e.g. sig verification. - // Does NOT allow scalars higher than CURVE.n. - // Accepts optional accumulator to merge with multiply (important for sparse scalars) - multiplyUnsafe(scalar: bigint, acc = Point.ZERO): Point { - const n = scalar - aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L - if (n === _0n) return I - if (this.is0() || n === _1n) return this - return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) - } - - // Checks if point is of small order. - // If you add something to small order point, you will have "dirty" - // point with torsion component. - // Multiplies point by cofactor and checks if the result is 0. - isSmallOrder(): boolean { - return this.multiplyUnsafe(cofactor).is0() - } - - // Multiplies point by curve order and checks if the result is 0. - // Returns `false` is the point is dirty. - isTorsionFree(): boolean { - return wnaf.unsafeLadder(this, CURVE_ORDER).is0() - } - - // Converts Extended point to default (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - toAffine(iz?: bigint): AffinePoint { - return toAffineMemo(this, iz) - } - - clearCofactor(): Point { - const { h: cofactor } = CURVE - if (cofactor === _1n) return this - return this.multiplyUnsafe(cofactor) - } - - // Converts hash string or Uint8Array to Point. - // Uses algo from RFC8032 5.1.3. - static fromHex(hex: Hex, zip215 = false): Point { - const { d, a } = CURVE - const len = Fp.BYTES - hex = ensureBytes('pointHex', hex, len) // copy hex to a new array - abool('zip215', zip215) - const normed = hex.slice() // copy again, we'll manipulate it - const lastByte = hex[len - 1] // select last byte - normed[len - 1] = lastByte & ~0x80 // clear last bit - const y = bytesToNumberLE(normed) - - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // RFC8032 prohibits >= p, but ZIP215 doesn't - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - const max = zip215 ? MASK : Fp.ORDER - aInRange('pointHex.y', y, _0n, max) - - // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: - // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) - const y2 = modP(y * y) // denominator is always non-0 mod p. - const u = modP(y2 - _1n) // u = y² - 1 - const v = modP(d * y2 - a) // v = d y² + 1. - let { isValid, value: x } = uvRatio(u, v) // √(u/v) - if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') - const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper - const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit - if (!zip215 && x === _0n && isLastByteOdd) - // if x=0 and x_0 = 1, fail - throw new Error('Point.fromHex: x=0 and x_0=1') - if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x - return Point.fromAffine({ x, y }) - } - static fromPrivateKey(privKey: Hex): Point { - const { scalar } = getPrivateScalar(privKey) - return G.multiply(scalar) // reduced one call of `toRawBytes` - } - toRawBytes(): Uint8Array { - const { x, y } = this.toAffine() - const bytes = numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) - bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y - return bytes // and use the last byte to encode sign of x - } - toHex(): string { - return bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. - } - } - const { BASE: G, ZERO: I } = Point - const wnaf = wNAF(Point, nByteLength * 8) - - function modN(a: bigint) { - return mod(a, CURVE_ORDER) - } - // Little-endian SHA512 with modulo n - function modN_LE(hash: Uint8Array): bigint { - return modN(bytesToNumberLE(hash)) - } - - // Get the hashed private scalar per RFC8032 5.1.5 - function getPrivateScalar(key: Hex) { - const len = Fp.BYTES - key = ensureBytes('private key', key, len) - // Hash private key with curve's hash function to produce uniformingly random input - // Check byte lengths: ensure(64, h(ensure(32, key))) - const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) - const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE - const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) - const scalar = modN_LE(head) // The actual private scalar - return { head, prefix, scalar } - } - - // Convenience method that creates public key from scalar. RFC8032 5.1.5 - function getExtendedPublicKey(key: Hex) { - const { head, prefix, scalar } = getPrivateScalar(key) - const point = G.multiply(scalar) // Point on Edwards curve aka public key - const pointBytes = point.toRawBytes() // Uint8Array representation - return { head, prefix, scalar, point, pointBytes } - } - - // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared - function getPublicKey(privKey: Hex): Uint8Array { - return getExtendedPublicKey(privKey).pointBytes - } - - // int('LE', SHA512(dom2(F, C) || msgs)) mod N - function hashDomainToScalar(context: Hex = Uint8Array.of(), ...msgs: Uint8Array[]) { - const msg = concatBytes(...msgs) - return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) - } - - /** Signs message with privateKey. RFC8032 5.1.6 */ - function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array { - msg = ensureBytes('message', msg) - if (prehash) msg = prehash(msg) // for ed25519ph etc. - const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) - const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) - const R = G.multiply(r).toRawBytes() // R = rG - const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) - const s = modN(r + k * scalar) // S = (r + k * s) mod L - aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l - const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES)) - return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature - } - - const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT - - /** - * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - * An extended group equation is checked. - */ - function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean { - const { context, zip215 } = options - const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. - sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. - msg = ensureBytes('message', msg) - publicKey = ensureBytes('publicKey', publicKey, len) - if (zip215 !== undefined) abool('zip215', zip215) - if (prehash) msg = prehash(msg) // for ed25519ph, etc - - const s = bytesToNumberLE(sig.slice(len, 2 * len)) - let A, R, SB - try { - // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. - // zip215=true: 0 <= y < MASK (2^256 for ed25519) - // zip215=false: 0 <= y < P (2^255-19 for ed25519) - A = Point.fromHex(publicKey, zip215) - R = Point.fromHex(sig.slice(0, len), zip215) - SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside - } catch (error) { - return false - } - if (!zip215 && A.isSmallOrder()) return false - - const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) - const RkA = R.add(A.multiplyUnsafe(k)) - // Extended group equation - // [8][S]B = [8]R + [8][k]A' - return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) - } - - G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. - - const utils = { - getExtendedPublicKey, - /** ed25519 priv keys are uniform 32b. No need to check for modulo bias, like in secp256k1. */ - randomPrivateKey: (): Uint8Array => randomBytes(Fp.BYTES), - - /** - * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT - * values. This slows down first getPublicKey() by milliseconds (see Speed section), - * but allows to speed-up subsequent getPublicKey() calls up to 20x. - * @param windowSize 2, 4, 8, 16 - */ - precompute(windowSize = 8, point: ExtPointType = Point.BASE): ExtPointType { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) - return point - }, - } - - return { - CURVE, - getPublicKey, - sign, - verify, - ExtendedPoint: Point, - utils, - } -} diff --git a/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts b/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts deleted file mode 100644 index c73b2993e94..00000000000 --- a/packages/noble-curves-tmp/src/abstract/hash-to-curve.ts +++ /dev/null @@ -1,265 +0,0 @@ -/** - * hash-to-curve from RFC 9380. - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * https://www.rfc-editor.org/rfc/rfc9380 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import type { AffinePoint, Group, GroupConstructor } from './curve.ts' -import { type IField, mod } from './modular.ts' -import type { CHash } from './utils.ts' -import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.ts' - -export type UnicodeOrBytes = string | Uint8Array - -/** - * * `DST` is a domain separation tag, defined in section 2.2.5 - * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m - * * `m` is extension degree (1 for prime fields) - * * `k` is the target security target in bits (e.g. 128), from section 5.1 - * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) - * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props - */ -export type Opts = { - DST: UnicodeOrBytes - p: bigint - m: number - k: number - expand: 'xmd' | 'xof' - hash: CHash -} - -// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. -const os2ip = bytesToNumberBE - -// Integer to Octet Stream (numberToBytesBE) -function i2osp(value: number, length: number): Uint8Array { - anum(value) - anum(length) - if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) - const res = Array.from({ length }).fill(0) as number[] - for (let i = length - 1; i >= 0; i--) { - res[i] = value & 0xff - value >>>= 8 - } - return new Uint8Array(res) -} - -function strxor(a: Uint8Array, b: Uint8Array): Uint8Array { - const arr = new Uint8Array(a.length) - for (let i = 0; i < a.length; i++) { - arr[i] = a[i] ^ b[i] - } - return arr -} - -function anum(item: unknown): void { - if (!Number.isSafeInteger(item)) throw new Error('number expected') -} - -/** - * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. - * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). - */ -export function expand_message_xmd( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - H: CHash, -): Uint8Array { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) - const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H - const ell = Math.ceil(lenInBytes / b_in_bytes) - if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') - 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) // len_in_bytes_str - const b = new Array(ell) - const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) - b[0] = 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] = H(concatBytes(...args)) - } - const pseudo_random_bytes = concatBytes(...b) - return pseudo_random_bytes.slice(0, lenInBytes) -} - -/** - * Produces a uniformly random byte string using an extendable-output function (XOF) H. - * 1. The collision resistance of H MUST be at least k bits. - * 2. H MUST be an XOF that has been proved indifferentiable from - * a random oracle under a reasonable cryptographic assumption. - * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). - */ -export function expand_message_xof( - msg: Uint8Array, - DST: Uint8Array, - lenInBytes: number, - k: number, - H: CHash, -): Uint8Array { - abytes(msg) - abytes(DST) - anum(lenInBytes) - // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 - // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); - if (DST.length > 255) { - const dkLen = Math.ceil((2 * k) / 8) - DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() - } - if (lenInBytes > 65535 || DST.length > 255) - throw new Error('expand_message_xof: invalid lenInBytes') - return ( - H.create({ dkLen: lenInBytes }) - .update(msg) - .update(i2osp(lenInBytes, 2)) - // 2. DST_prime = DST || I2OSP(len(DST), 1) - .update(DST) - .update(i2osp(DST.length, 1)) - .digest() - ) -} - -/** - * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. - * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). - * @param msg a byte string containing the message to hash - * @param count the number of elements of F to output - * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above - * @returns [u_0, ..., u_(count - 1)], a list of field elements. - */ -export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] { - validateObject(options, { - DST: 'stringOrUint8Array', - p: 'bigint', - m: 'isSafeInteger', - k: 'isSafeInteger', - hash: 'hash', - }) - const { p, k, m, hash, expand, DST: _DST } = options - abytes(msg) - anum(count) - const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST - const log2p = p.toString(2).length - const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above - const len_in_bytes = count * m * L - let prb // pseudo_random_bytes - if (expand === 'xmd') { - prb = expand_message_xmd(msg, DST, len_in_bytes, hash) - } else if (expand === 'xof') { - prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) - } else if (expand === '_internal_pass') { - // for internal tests only - prb = msg - } else { - throw new Error('expand must be "xmd" or "xof"') - } - const u = new Array(count) - for (let i = 0; i < count; i++) { - const e = new Array(m) - for (let j = 0; j < m; j++) { - const elm_offset = L * (j + i * m) - const tv = prb.subarray(elm_offset, elm_offset + L) - e[j] = mod(os2ip(tv), p) - } - u[i] = e - } - return u -} - -export type XY = ( - x: T, - y: T, -) => { - x: T - y: T -} -export function isogenyMap>(field: F, map: [T[], T[], T[], T[]]): XY { - // Make same order as in spec - const COEFF = map.map((i) => Array.from(i).reverse()) - return (x: T, y: T) => { - const [xNum, xDen, yNum, yDen] = COEFF.map((val) => - val.reduce((acc, i) => field.add(field.mul(acc, x), i)), - ) - // 6.6.3 - // Exceptional cases of iso_map are inputs that cause the denominator of - // either rational function to evaluate to zero; such cases MUST return - // the identity point on E. - if (field.is0(xDen) || field.is0(yDen)) return { x: field.ZERO, y: field.ZERO } - x = field.div(xNum, xDen) // xNum / xDen - y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) - return { x: x, y: y } - } -} - -/** Point interface, which curves must implement to work correctly with the module. */ -export interface H2CPoint extends Group> { - add(rhs: H2CPoint): H2CPoint - toAffine(iz?: bigint): AffinePoint - clearCofactor(): H2CPoint - assertValidity(): void -} - -export interface H2CPointConstructor extends GroupConstructor> { - fromAffine(ap: AffinePoint): H2CPoint -} - -export type MapToCurve = (scalar: bigint[]) => AffinePoint - -// Separated from initialization opts, so users won't accidentally change per-curve parameters -// (changing DST is ok!) -export type htfBasicOpts = { DST: UnicodeOrBytes } -export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint -export type MapMethod = (scalars: bigint[]) => H2CPoint -export type Hasher = { - hashToCurve: HTFMethod - encodeToCurve: HTFMethod - mapToCurve: MapMethod - defaults: Opts & { encodeDST?: UnicodeOrBytes } -} - -/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ -export function createHasher( - Point: H2CPointConstructor, - mapToCurve: MapToCurve, - defaults: Opts & { encodeDST?: UnicodeOrBytes }, -): Hasher { - if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') - return { - defaults, - - // Encodes byte string to elliptic curve. - // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - hashToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { - const u = hash_to_field(msg, 2, { ...defaults, DST: defaults.DST, ...options } as Opts) - const u0 = Point.fromAffine(mapToCurve(u[0])) - const u1 = Point.fromAffine(mapToCurve(u[1])) - const P = u0.add(u1).clearCofactor() - P.assertValidity() - return P - }, - - // Encodes byte string to elliptic curve. - // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 - encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { - const u = hash_to_field(msg, 1, { ...defaults, DST: defaults.encodeDST, ...options } as Opts) - const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() - P.assertValidity() - return P - }, - // Same as encodeToCurve, but without hash - mapToCurve(scalars: bigint[]): H2CPoint { - if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') - for (const i of scalars) - if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') - const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() - P.assertValidity() - return P - }, - } -} diff --git a/packages/noble-curves-tmp/src/abstract/modular.ts b/packages/noble-curves-tmp/src/abstract/modular.ts deleted file mode 100644 index 8c0b703e745..00000000000 --- a/packages/noble-curves-tmp/src/abstract/modular.ts +++ /dev/null @@ -1,555 +0,0 @@ -/** - * Utils for modular division and finite fields. - * A finite field over 11 is integer number operations `mod 11`. - * There is no division: it is replaced by modular multiplicative inverse. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { - bitMask, - bytesToNumberBE, - bytesToNumberLE, - ensureBytes, - numberToBytesBE, - numberToBytesLE, - validateObject, -} from './utils.ts' - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = /* @__PURE__ */ BigInt(2), - _3n = /* @__PURE__ */ BigInt(3) -// prettier-ignore -const _4n = /* @__PURE__ */ BigInt(4), - _5n = /* @__PURE__ */ BigInt(5), - _8n = /* @__PURE__ */ BigInt(8) -// prettier-ignore -const _9n = /* @__PURE__ */ BigInt(9), - _16n = /* @__PURE__ */ BigInt(16) - -// Calculates a modulo b -export function mod(a: bigint, b: bigint): bigint { - const result = a % b - return result >= _0n ? result : b + result -} -/** - * Efficiently raise num to power and do modular division. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - * @todo use field version && remove - * @example - * pow(2n, 6n, 11n) // 64n % 11n == 9n - */ -export function pow(num: bigint, power: bigint, modulo: bigint): bigint { - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (modulo <= _0n) throw new Error('invalid modulus') - 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 -} - -/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ -export function pow2(x: bigint, power: bigint, modulo: bigint): bigint { - let res = x - while (power-- > _0n) { - res *= res - res %= modulo - } - return res -} - -/** - * Inverses number over modulo. - * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). - */ -export function invert(number: bigint, modulo: bigint): bigint { - if (number === _0n) throw new Error('invert: expected non-zero number') - if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) - // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. - let a = mod(number, modulo) - let b = modulo - // prettier-ignore - let x = _0n, - y = _1n, - u = _1n, - v = _0n - while (a !== _0n) { - // JIT applies optimization if those two lines follow each other - const q = b / a - const r = b % a - const m = x - u * q - const n = y - v * q - // prettier-ignore - ;(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) -} - -/** - * Tonelli-Shanks square root search algorithm. - * 1. https://eprint.iacr.org/2012/685.pdf (page 12) - * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks - * Will start an infinite loop if field order P is not prime. - * @param P field order - * @returns function that takes field Fp (created from P) and number n - */ -export function tonelliShanks(P: bigint): (Fp: IField, n: T) => T { - // Legendre constant: used to calculate Legendre symbol (a | p), - // which denotes the value of a^((p-1)/2) (mod p). - // (a | p) ≡ 1 if a is a square (mod p) - // (a | p) ≡ -1 if a is not a square (mod p) - // (a | p) ≡ 0 if a ≡ 0 (mod p) - const legendreC = (P - _1n) / _2n - - let Q: bigint, S: number, Z: bigint - // Step 1: By factoring out powers of 2 from p - 1, - // find q and s such that p - 1 = q*(2^s) with q odd - for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); - - // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq - for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { - // Crash instead of infinity loop, we cannot reasonable count until P. - if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') - } - - // Fast-path - if (S === 1) { - const p1div4 = (P + _1n) / _4n - return function tonelliFast(Fp: IField, n: T) { - const root = Fp.pow(n, p1div4) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // Slow-path - const Q1div2 = (Q + _1n) / _2n - return function tonelliSlow(Fp: IField, n: T): T { - // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 - if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') - let r = S - // TODO: will fail at Fp2/etc - let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b - let x = Fp.pow(n, Q1div2) // first guess at the square root - let b = Fp.pow(n, Q) // first guess at the fudge factor - - while (!Fp.eql(b, Fp.ONE)) { - if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) - // Find m such b^(2^m)==1 - let m = 1 - for (let t2 = Fp.sqr(b); m < r; m++) { - if (Fp.eql(t2, Fp.ONE)) break - t2 = Fp.sqr(t2) // t2 *= t2 - } - // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow - const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) - g = Fp.sqr(ge) // g = ge * ge - x = Fp.mul(x, ge) // x *= ge - b = Fp.mul(b, g) // b *= g - r = m - } - return x - } -} - -/** - * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: - * - * 1. P ≡ 3 (mod 4) - * 2. P ≡ 5 (mod 8) - * 3. P ≡ 9 (mod 16) - * 4. Tonelli-Shanks algorithm - * - * Different algorithms can give different roots, it is up to user to decide which one they want. - * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). - */ -export function FpSqrt(P: bigint): (Fp: IField, n: T) => T { - // P ≡ 3 (mod 4) - // √n = n^((P+1)/4) - if (P % _4n === _3n) { - // Not all roots possible! - // const ORDER = - // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; - // const NUM = 72057594037927816n; - const p1div4 = (P + _1n) / _4n - return function sqrt3mod4(Fp: IField, n: T) { - const root = Fp.pow(n, p1div4) - // Throw if root**2 != n - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) - if (P % _8n === _5n) { - const c1 = (P - _5n) / _8n - return function sqrt5mod8(Fp: IField, n: T) { - const n2 = Fp.mul(n, _2n) - const v = Fp.pow(n2, c1) - const nv = Fp.mul(n, v) - const i = Fp.mul(Fp.mul(nv, _2n), v) - const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) - if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') - return root - } - } - - // P ≡ 9 (mod 16) - if (P % _16n === _9n) { - // NOTE: tonelli is too slow for bls-Fp2 calculations even on start - // Means we cannot use sqrt for constants at all! - // - // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F - // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F - // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F - // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic - // sqrt = (x) => { - // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 - // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 - // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 - // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 - // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x - // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x - // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x - // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x - // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x - // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 - // } - } - // Other cases: Tonelli-Shanks algorithm - return tonelliShanks(P) -} - -// Little-endian check for first LE bit (last BE bit); -export const isNegativeLE = (num: bigint, modulo: bigint): boolean => - (mod(num, modulo) & _1n) === _1n - -/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ -export interface IField { - ORDER: bigint - isLE: boolean - BYTES: number - BITS: number - MASK: bigint - ZERO: T - ONE: T - // 1-arg - create: (num: T) => T - isValid: (num: T) => boolean - is0: (num: T) => boolean - neg(num: T): T - inv(num: T): T - sqrt(num: T): T - sqr(num: T): T - // 2-args - eql(lhs: T, rhs: T): boolean - add(lhs: T, rhs: T): T - sub(lhs: T, rhs: T): T - mul(lhs: T, rhs: T | bigint): T - pow(lhs: T, power: bigint): T - div(lhs: T, rhs: T | bigint): T - // N for NonNormalized (for now) - addN(lhs: T, rhs: T): T - subN(lhs: T, rhs: T): T - mulN(lhs: T, rhs: T | bigint): T - sqrN(num: T): T - - // Optional - // Should be same as sgn0 function in - // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1). - // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway. - isOdd?(num: T): boolean // Odd instead of even since we have it for Fp2 - // legendre?(num: T): T; - pow(lhs: T, power: bigint): T - invertBatch: (lst: T[]) => T[] - toBytes(num: T): Uint8Array - fromBytes(bytes: Uint8Array): T - // If c is False, CMOV returns a, otherwise it returns b. - cmov(a: T, b: T, c: boolean): T -} -// prettier-ignore -const FIELD_FIELDS = [ - 'create', - 'isValid', - 'is0', - 'neg', - 'inv', - 'sqrt', - 'sqr', - 'eql', - 'add', - 'sub', - 'mul', - 'pow', - 'div', - 'addN', - 'subN', - 'mulN', - 'sqrN', -] as const -export function validateField(field: IField): IField { - const initial = { - ORDER: 'bigint', - MASK: 'bigint', - BYTES: 'isSafeInteger', - BITS: 'isSafeInteger', - } as Record - const opts = FIELD_FIELDS.reduce((map, val: string) => { - map[val] = 'function' - return map - }, initial) - return validateObject(field, opts) -} - -// Generic field functions - -/** - * Same as `pow` but for Fp: non-constant-time. - * Unsafe in some contexts: uses ladder, so can expose bigint bits. - */ -export function FpPow(f: IField, num: T, power: bigint): T { - // Should have same speed as pow for bigints - // TODO: benchmark! - if (power < _0n) throw new Error('invalid exponent, negatives unsupported') - if (power === _0n) return f.ONE - if (power === _1n) return num - let p = f.ONE - let d = num - while (power > _0n) { - if (power & _1n) p = f.mul(p, d) - d = f.sqr(d) - power >>= _1n - } - return p -} - -/** - * Efficiently invert an array of Field elements. - * `inv(0)` will return `undefined` here: make sure to throw an error. - */ -export function FpInvertBatch(f: IField, nums: T[]): T[] { - const tmp = new Array(nums.length) - // Walk from first to last, multiply them by each other MOD p - const lastMultiplied = nums.reduce((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = acc - return f.mul(acc, num) - }, f.ONE) - // Invert last element - const inverted = f.inv(lastMultiplied) - // Walk from last to first, multiply them by inverted each other MOD p - nums.reduceRight((acc, num, i) => { - if (f.is0(num)) return acc - tmp[i] = f.mul(acc, tmp[i]) - return f.mul(acc, num) - }, inverted) - return tmp -} - -export function FpDiv(f: IField, lhs: T, rhs: T | bigint): T { - return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) -} - -/** - * Legendre symbol. - * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue - * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue - * * (a | p) ≡ 0 if a ≡ 0 (mod p) - */ -export function FpLegendre(order: bigint): (f: IField, x: T) => T { - const legendreConst = (order - _1n) / _2n // Integer arithmetic - return (f: IField, x: T): T => f.pow(x, legendreConst) -} - -// This function returns True whenever the value x is a square in the field F. -export function FpIsSquare(f: IField): (x: T) => boolean { - const legendre = FpLegendre(f.ORDER) - return (x: T): boolean => { - const p = legendre(f, x) - return f.eql(p, f.ZERO) || f.eql(p, f.ONE) - } -} - -// CURVE.n lengths -export function nLength( - n: bigint, - nBitLength?: number, -): { - nBitLength: number - nByteLength: number -} { - // Bit size, byte size of CURVE.n - const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length - const nByteLength = Math.ceil(_nBitLength / 8) - return { nBitLength: _nBitLength, nByteLength } -} - -type FpField = IField & Required, 'isOdd'>> -/** - * Initializes a finite field over prime. - * Major performance optimizations: - * * a) denormalized operations like mulN instead of mul - * * b) same object shape: never add or remove keys - * * c) Object.freeze - * Fragile: always run a benchmark on a change. - * Security note: operations don't check 'isValid' for all elements for performance reasons, - * it is caller responsibility to check this. - * This is low-level code, please make sure you know what you're doing. - * @param ORDER prime positive bigint - * @param bitLen how many bits the field consumes - * @param isLE (def: false) if encoding / decoding should be in little-endian - * @param redef optional faster redefinitions of sqrt and other methods - */ -export function Field( - ORDER: bigint, - bitLen?: number, - isLE = false, - redef: Partial> = {}, -): Readonly { - if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) - const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) - if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') - let sqrtP: ReturnType // cached sqrtP - const f: Readonly = Object.freeze({ - ORDER, - isLE, - BITS, - BYTES, - MASK: bitMask(BITS), - ZERO: _0n, - ONE: _1n, - create: (num) => mod(num, ORDER), - isValid: (num) => { - if (typeof num !== 'bigint') - throw new Error('invalid field element: expected bigint, got ' + typeof num) - return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible - }, - is0: (num) => num === _0n, - isOdd: (num) => (num & _1n) === _1n, - neg: (num) => mod(-num, ORDER), - eql: (lhs, rhs) => lhs === rhs, - - sqr: (num) => mod(num * num, ORDER), - add: (lhs, rhs) => mod(lhs + rhs, ORDER), - sub: (lhs, rhs) => mod(lhs - rhs, ORDER), - mul: (lhs, rhs) => mod(lhs * rhs, ORDER), - pow: (num, power) => FpPow(f, num, power), - div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), - - // Same as above, but doesn't normalize - sqrN: (num) => num * num, - addN: (lhs, rhs) => lhs + rhs, - subN: (lhs, rhs) => lhs - rhs, - mulN: (lhs, rhs) => lhs * rhs, - - inv: (num) => invert(num, ORDER), - sqrt: - redef.sqrt || - ((n) => { - if (!sqrtP) sqrtP = FpSqrt(ORDER) - return sqrtP(f, n) - }), - invertBatch: (lst) => FpInvertBatch(f, lst), - // TODO: do we really need constant cmov? - // We don't have const-time bigints anyway, so probably will be not very useful - cmov: (a, b, c) => (c ? b : a), - toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), - fromBytes: (bytes) => { - if (bytes.length !== BYTES) - throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) - return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) - }, - } as FpField) - return Object.freeze(f) -} - -export function FpSqrtOdd(Fp: IField, elm: T): T { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? root : Fp.neg(root) -} - -export function FpSqrtEven(Fp: IField, elm: T): T { - if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") - const root = Fp.sqrt(elm) - return Fp.isOdd(root) ? Fp.neg(root) : root -} - -/** - * "Constant-time" private key generation utility. - * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). - * Which makes it slightly more biased, less secure. - * @deprecated use `mapKeyToField` instead - */ -export function hashToPrivateScalar( - hash: string | Uint8Array, - groupOrder: bigint, - isLE = false, -): bigint { - hash = ensureBytes('privateHash', hash) - const hashLen = hash.length - const minLen = nLength(groupOrder).nByteLength + 8 - if (minLen < 24 || hashLen < minLen || hashLen > 1024) - throw new Error( - 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, - ) - const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) - return mod(num, groupOrder - _1n) + _1n -} - -/** - * Returns total number of bytes consumed by the field element. - * For example, 32 bytes for usual 256-bit weierstrass curve. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of field - */ -export function getFieldBytesLength(fieldOrder: bigint): number { - if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') - const bitLength = fieldOrder.toString(2).length - return Math.ceil(bitLength / 8) -} - -/** - * Returns minimal amount of bytes that can be safely reduced - * by field order. - * Should be 2^-128 for 128-bit curve such as P256. - * @param fieldOrder number of field elements, usually CURVE.n - * @returns byte length of target hash - */ -export function getMinHashLength(fieldOrder: bigint): number { - const length = getFieldBytesLength(fieldOrder) - return length + Math.ceil(length / 2) -} - -/** - * "Constant-time" private key generation utility. - * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF - * and convert them into private scalar, with the modulo bias being negligible. - * Needs at least 48 bytes of input for 32-byte private key. - * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ - * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final - * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 - * @param hash hash output from SHA3 or a similar function - * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) - * @param isLE interpret hash bytes as LE num - * @returns valid private scalar - */ -export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array { - const len = key.length - const fieldLen = getFieldBytesLength(fieldOrder) - const minLen = getMinHashLength(fieldOrder) - // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. - if (len < 16 || len < minLen || len > 1024) - throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) - const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) - // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 - const reduced = mod(num, fieldOrder - _1n) + _1n - return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) -} diff --git a/packages/noble-curves-tmp/src/abstract/montgomery.ts b/packages/noble-curves-tmp/src/abstract/montgomery.ts deleted file mode 100644 index 122406e3350..00000000000 --- a/packages/noble-curves-tmp/src/abstract/montgomery.ts +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Montgomery curve methods. It's not really whole montgomery curve, - * just bunch of very specific methods for X25519 / X448 from - * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { mod, pow } from './modular.ts' -import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.ts' - -const _0n = BigInt(0) -const _1n = BigInt(1) -type Hex = string | Uint8Array - -export type CurveType = { - P: bigint // finite field prime - nByteLength: number - adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array - domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array - a: bigint - montgomeryBits: number - powPminus2?: (x: bigint) => bigint - xyToU?: (x: bigint, y: bigint) => bigint - Gu: bigint - randomBytes?: (bytesLength?: number) => Uint8Array -} - -export type CurveFn = { - scalarMult: (scalar: Hex, u: Hex) => Uint8Array - scalarMultBase: (scalar: Hex) => Uint8Array - getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array - getPublicKey: (privateKey: Hex) => Uint8Array - utils: { randomPrivateKey: () => Uint8Array } - GuBytes: Uint8Array -} - -function validateOpts(curve: CurveType) { - validateObject( - curve, - { - a: 'bigint', - }, - { - montgomeryBits: 'isSafeInteger', - nByteLength: 'isSafeInteger', - adjustScalarBytes: 'function', - domain: 'function', - powPminus2: 'function', - Gu: 'bigint', - }, - ) - // Set defaults - return Object.freeze({ ...curve } as const) -} - -// Uses only one coordinate instead of two -export function montgomery(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) - const { P } = CURVE - const modP = (n: bigint) => mod(n, P) - const montgomeryBits = CURVE.montgomeryBits - const montgomeryBytes = Math.ceil(montgomeryBits / 8) - const fieldLen = CURVE.nByteLength - const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) - const powPminus2 = CURVE.powPminus2 || ((x: bigint) => pow(x, P - BigInt(2), P)) - - // cswap from RFC7748. But it is not from RFC7748! - /* - cswap(swap, x_2, x_3): - dummy = mask(swap) AND (x_2 XOR x_3) - x_2 = x_2 XOR dummy - x_3 = x_3 XOR dummy - Return (x_2, x_3) - Where mask(swap) is the all-1 or all-0 word of the same length as x_2 - and x_3, computed, e.g., as mask(swap) = 0 - swap. - */ - function cswap(swap: bigint, x_2: bigint, x_3: bigint): [bigint, bigint] { - const dummy = modP(swap * (x_2 - x_3)) - x_2 = modP(x_2 - dummy) - x_3 = modP(x_3 + dummy) - return [x_2, x_3] - } - - // x25519 from 4 - // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 - const a24 = (CURVE.a - BigInt(2)) / BigInt(4) - /** - * - * @param pointU u coordinate (x) on Montgomery Curve 25519 - * @param scalar by which the point would be multiplied - * @returns new Point on Montgomery curve - */ - function montgomeryLadder(u: bigint, scalar: bigint): bigint { - aInRange('u', u, _0n, P) - aInRange('scalar', scalar, _0n, P) - // Section 5: Implementations MUST accept non-canonical values and process them as - // if they had been reduced modulo the field prime. - const k = scalar - const x_1 = u - let x_2 = _1n - let z_2 = _0n - let x_3 = u - let z_3 = _1n - let swap = _0n - let sw: [bigint, bigint] - for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { - const k_t = (k >> t) & _1n - swap ^= k_t - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - swap = k_t - - const A = x_2 + z_2 - const AA = modP(A * A) - const B = x_2 - z_2 - const BB = modP(B * B) - const E = AA - BB - const C = x_3 + z_3 - const D = x_3 - z_3 - const DA = modP(D * A) - const CB = modP(C * B) - const dacb = DA + CB - const da_cb = DA - CB - x_3 = modP(dacb * dacb) - z_3 = modP(x_1 * modP(da_cb * da_cb)) - x_2 = modP(AA * BB) - z_2 = modP(E * (AA + modP(a24 * E))) - } - // (x_2, x_3) = cswap(swap, x_2, x_3) - sw = cswap(swap, x_2, x_3) - x_2 = sw[0] - x_3 = sw[1] - // (z_2, z_3) = cswap(swap, z_2, z_3) - sw = cswap(swap, z_2, z_3) - z_2 = sw[0] - z_3 = sw[1] - // z_2^(p - 2) - const z2 = powPminus2(z_2) - // Return x_2 * (z_2^(p - 2)) - return modP(x_2 * z2) - } - - function encodeUCoordinate(u: bigint): Uint8Array { - return numberToBytesLE(modP(u), montgomeryBytes) - } - - function decodeUCoordinate(uEnc: Hex): bigint { - // Section 5: When receiving such an array, implementations of X25519 - // MUST mask the most significant bit in the final byte. - const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) - if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 - return bytesToNumberLE(u) - } - function decodeScalar(n: Hex): bigint { - const bytes = ensureBytes('scalar', n) - const len = bytes.length - if (len !== montgomeryBytes && len !== fieldLen) { - let valid = '' + montgomeryBytes + ' or ' + fieldLen - throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) - } - return bytesToNumberLE(adjustScalarBytes(bytes)) - } - function scalarMult(scalar: Hex, u: Hex): Uint8Array { - const pointU = decodeUCoordinate(u) - const _scalar = decodeScalar(scalar) - const pu = montgomeryLadder(pointU, _scalar) - // The result was not contributory - // https://cr.yp.to/ecdh.html#validate - if (pu === _0n) throw new Error('invalid private or public key received') - return encodeUCoordinate(pu) - } - // Computes public key from private. By doing scalar multiplication of base point. - const GuBytes = encodeUCoordinate(CURVE.Gu) - function scalarMultBase(scalar: Hex): Uint8Array { - return scalarMult(scalar, GuBytes) - } - - return { - scalarMult, - scalarMultBase, - getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey), - getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey), - utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) }, - GuBytes: GuBytes, - } -} diff --git a/packages/noble-curves-tmp/src/abstract/poseidon.ts b/packages/noble-curves-tmp/src/abstract/poseidon.ts deleted file mode 100644 index 6edaad90986..00000000000 --- a/packages/noble-curves-tmp/src/abstract/poseidon.ts +++ /dev/null @@ -1,329 +0,0 @@ -/** - * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. - * - * There are many poseidon variants with different constants. - * We don't provide them: you should construct them manually. - * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { FpPow, type IField, validateField } from './modular.ts' -import { bitGet } from './utils.ts' - -// Grain LFSR (Linear-Feedback Shift Register): https://eprint.iacr.org/2009/109.pdf -function grainLFSR(state: number[]): () => boolean { - let pos = 0 - if (state.length !== 80) throw new Error('grainLFRS: wrong state length, should be 80 bits') - const getBit = (): boolean => { - const r = (offset: number) => state[(pos + offset) % 80] - const bit = r(62) ^ r(51) ^ r(38) ^ r(23) ^ r(13) ^ r(0) - state[pos] = bit - pos = ++pos % 80 - return !!bit - } - for (let i = 0; i < 160; i++) getBit() - return () => { - // https://en.wikipedia.org/wiki/Shrinking_generator - while (true) { - const b1 = getBit() - const b2 = getBit() - if (!b1) continue - return b2 - } - } -} - -export type PoseidonBasicOpts = { - Fp: IField - t: number // t = rate + capacity - roundsFull: number - roundsPartial: number - isSboxInverse?: boolean -} - -function validateBasicOpts(opts: PoseidonBasicOpts) { - const { Fp, roundsFull } = opts - validateField(Fp) - for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) { - if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) - throw new Error('invalid number ' + i) - } - if (opts.isSboxInverse !== undefined && typeof opts.isSboxInverse !== 'boolean') - throw new Error(`Poseidon: invalid param isSboxInverse=${opts.isSboxInverse}`) - if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) -} - -function poseidonGrain(opts: PoseidonBasicOpts) { - validateBasicOpts(opts) - const { Fp } = opts - const state = Array(80).fill(1) - let pos = 0 - const writeBits = (value: bigint, bitCount: number) => { - for (let i = bitCount - 1; i >= 0; i--) state[pos++] = Number(bitGet(value, i)) - } - writeBits(1n, 2) // prime field - writeBits(opts.isSboxInverse ? 1n : 0n, 4) // b2..b5 - writeBits(BigInt(Fp.BITS), 12) // b6..b17 - writeBits(BigInt(opts.t), 12) // b18..b29 - writeBits(BigInt(opts.roundsFull), 10) // b30..b39 - writeBits(BigInt(opts.roundsPartial), 10) // b40..b49 - - const getBit = grainLFSR(state) - return (count: number, reject: boolean): bigint[] => { - const res: bigint[] = [] - for (let i = 0; i < count; i++) { - while (true) { - let num = 0n - for (let i = 0; i < Fp.BITS; i++) { - num <<= 1n - if (getBit()) num |= 1n - } - if (reject && num >= Fp.ORDER) continue // rejection sampling - res.push(Fp.create(num)) - break - } - } - return res - } -} - -export type PoseidonGrainOpts = PoseidonBasicOpts & { - sboxPower?: number -} - -type PoseidonConstants = { mds: bigint[][]; roundConstants: bigint[][] } - -// NOTE: this is not standard but used often for constant generation for poseidon -// (grain LFRS-like structure) -export function grainGenConstants(opts: PoseidonGrainOpts, skipMDS: number = 0): PoseidonConstants { - const { Fp, t, roundsFull, roundsPartial } = opts - const rounds = roundsFull + roundsPartial - const sample = poseidonGrain(opts) - const roundConstants: bigint[][] = [] - for (let r = 0; r < rounds; r++) roundConstants.push(sample(t, true)) - if (skipMDS > 0) for (let i = 0; i < skipMDS; i++) sample(2 * t, false) - const xs = sample(t, false) - const ys = sample(t, false) - // Construct MDS Matrix M[i][j] = 1 / (xs[i] + ys[j]) - const mds: bigint[][] = [] - for (let i = 0; i < t; i++) { - const row: bigint[] = [] - for (let j = 0; j < t; j++) { - const xy = Fp.add(xs[i], ys[j]) - if (Fp.is0(xy)) - throw new Error(`Error generating MDS matrix: xs[${i}] + ys[${j}] resulted in zero.`) - row.push(xy) - } - mds.push(Fp.invertBatch(row)) - } - - return { roundConstants, mds } -} - -export type PoseidonOpts = PoseidonBasicOpts & - PoseidonConstants & { - sboxPower?: number - reversePartialPowIdx?: boolean // Hack for stark - } - -export function validateOpts(opts: PoseidonOpts): Readonly<{ - rounds: number - sboxFn: (n: bigint) => bigint - roundConstants: bigint[][] - mds: bigint[][] - Fp: IField - t: number - roundsFull: number - roundsPartial: number - sboxPower?: number - reversePartialPowIdx?: boolean // Hack for stark -}> { - validateBasicOpts(opts) - const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts - const { roundsFull, roundsPartial, sboxPower, t } = opts - - // MDS is TxT matrix - if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') - const _mds = mds.map((mdsRow) => { - if (!Array.isArray(mdsRow) || mdsRow.length !== t) - throw new Error('invalid MDS matrix row: ' + mdsRow) - return mdsRow.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) - return Fp.create(i) - }) - }) - - if (rev !== undefined && typeof rev !== 'boolean') - throw new Error('invalid param reversePartialPowIdx=' + rev) - - if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) - const rounds = roundsFull + roundsPartial - - if (!Array.isArray(rc) || rc.length !== rounds) - throw new Error('Poseidon: invalid round constants') - const roundConstants = rc.map((rc) => { - if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') - return rc.map((i) => { - if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') - return Fp.create(i) - }) - }) - - if (!sboxPower || ![3, 5, 7, 17].includes(sboxPower)) throw new Error('invalid sboxPower') - const _sboxPower = BigInt(sboxPower) - let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower) - // Unwrapped sbox power for common cases (195->142μs) - if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(n), n) - else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) - - return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) -} - -export function splitConstants(rc: bigint[], t: number): bigint[][] { - if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') - if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') - const res = [] - let tmp = [] - for (let i = 0; i < rc.length; i++) { - tmp.push(rc[i]) - if (tmp.length === t) { - res.push(tmp) - tmp = [] - } - } - return res -} - -/** Poseidon NTT-friendly hash. */ -export function poseidon(opts: PoseidonOpts): { - (values: bigint[]): bigint[] - // For verification in tests - roundConstants: bigint[][] -} { - const _opts = validateOpts(opts) - const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts - const halfRoundsFull = _opts.roundsFull / 2 - const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 - const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => { - values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) - - if (isFull) values = values.map((i) => sboxFn(i)) - else values[partialIdx] = sboxFn(values[partialIdx]) - // Matrix multiplication - values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) - return values - } - const poseidonHash = function poseidonHash(values: bigint[]) { - if (!Array.isArray(values) || values.length !== t) - throw new Error('invalid values, expected array of bigints with length ' + t) - values = values.map((i) => { - if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) - return Fp.create(i) - }) - let lastRound = 0 - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - // Apply r_p partial rounds. - for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) - // Apply r_f/2 full rounds. - for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) - - if (lastRound !== totalRounds) throw new Error('invalid number of rounds') - return values - } - // For verification in tests - poseidonHash.roundConstants = roundConstants - return poseidonHash -} - -export class PoseidonSponge { - private Fp: IField - readonly rate: number - readonly capacity: number - readonly hash: ReturnType - private state: bigint[] // [...capacity, ...rate] - private pos = 0 - private isAbsorbing = true - - constructor( - Fp: IField, - rate: number, - capacity: number, - hash: ReturnType, - ) { - this.Fp = Fp - this.hash = hash - this.rate = rate - this.capacity = capacity - this.state = new Array(rate + capacity) - this.clean() - } - private process(): void { - this.state = this.hash(this.state) - } - absorb(input: bigint[]): void { - for (const i of input) - if (typeof i !== 'bigint' || !this.Fp.isValid(i)) throw new Error('invalid input: ' + i) - for (let i = 0; i < input.length; ) { - if (!this.isAbsorbing || this.pos === this.rate) { - this.process() - this.pos = 0 - this.isAbsorbing = true - } - const chunk = Math.min(this.rate - this.pos, input.length - i) - for (let j = 0; j < chunk; j++) { - const idx = this.capacity + this.pos++ - this.state[idx] = this.Fp.add(this.state[idx], input[i++]) - } - } - } - squeeze(count: number): bigint[] { - const res: bigint[] = [] - while (res.length < count) { - if (this.isAbsorbing || this.pos === this.rate) { - this.process() - this.pos = 0 - this.isAbsorbing = false - } - const chunk = Math.min(this.rate - this.pos, count - res.length) - for (let i = 0; i < chunk; i++) res.push(this.state[this.capacity + this.pos++]) - } - return res - } - clean(): void { - this.state.fill(this.Fp.ZERO) - this.isAbsorbing = true - this.pos = 0 - } - clone(): PoseidonSponge { - const c = new PoseidonSponge(this.Fp, this.rate, this.capacity, this.hash) - c.pos = this.pos - c.state = [...this.state] - return c - } -} - -export type PoseidonSpongeOpts = Omit & { - rate: number - capacity: number -} - -/** - * The method is not defined in spec, but nevertheless used often. - * Check carefully for compatibility: there are many edge cases, like absorbing an empty array. - * We cross-test against: - * - https://github.com/ProvableHQ/snarkVM/tree/staging/algorithms - * - https://github.com/arkworks-rs/crypto-primitives/tree/main - */ -export function poseidonSponge(opts: PoseidonSpongeOpts): () => PoseidonSponge { - for (const i of ['rate', 'capacity'] as const) { - if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) - throw new Error('invalid number ' + i) - } - const { rate, capacity } = opts - const t = opts.rate + opts.capacity - // Re-use hash instance between multiple instances - const hash = poseidon({ ...opts, t }) - const { Fp } = opts - return () => new PoseidonSponge(Fp, rate, capacity, hash) -} diff --git a/packages/noble-curves-tmp/src/abstract/tower.ts b/packages/noble-curves-tmp/src/abstract/tower.ts deleted file mode 100644 index 4135dc08816..00000000000 --- a/packages/noble-curves-tmp/src/abstract/tower.ts +++ /dev/null @@ -1,664 +0,0 @@ -/** - * Towered extension fields. - * Rather than implementing a massive 12th-degree extension directly, it is more efficient - * to build it up from smaller extensions: a tower of extensions. - * - * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, - * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. - * - * For more info: "Pairings for beginners" by Costello, section 7.3. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import * as mod from './modular.ts' -import { bitLen, bitMask, concatBytes, notImplemented } from './utils.ts' -import type { ProjConstructor, ProjPointType } from './weierstrass.ts' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) - -// Fp₂ over complex plane -export type BigintTuple = [bigint, bigint] -export type Fp = bigint -// Finite extension field over irreducible polynominal. -// Fp(u) / (u² - β) where β = -1 -export type Fp2 = { c0: bigint; c1: bigint } -export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] -export type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 } -export type Fp12 = { c0: Fp6; c1: Fp6 } // Fp₁₂ = Fp₆² => Fp₂³, Fp₆(w) / (w² - γ) where γ = v -// prettier-ignore -export type BigintTwelve = [ - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, - bigint, -] - -export type Fp2Bls = mod.IField & { - reim: (num: Fp2) => { re: Fp; im: Fp } - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - fromBigTuple(num: [bigint, bigint]): Fp2 -} - -export type Fp12Bls = mod.IField & { - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - fromBigTwelve(num: BigintTwelve): Fp12 -} - -function calcFrobeniusCoefficients( - Fp: mod.IField, - nonResidue: T, - modulus: bigint, - degree: number, - num: number = 1, - divisor?: number, -) { - const _divisor = BigInt(divisor === undefined ? degree : divisor) - const towerModulus: any = modulus ** BigInt(degree) - const res: T[][] = [] - for (let i = 0; i < num; i++) { - const a = BigInt(i + 1) - const powers: T[] = [] - for (let j = 0, qPower = _1n; j < degree; j++) { - const power = ((a * qPower - a) / _divisor) % towerModulus - powers.push(Fp.pow(nonResidue, power)) - qPower *= modulus - } - res.push(powers) - } - return res -} - -// This works same at least for bls12-381, bn254 and bls12-377 -export function psiFrobenius( - Fp: mod.IField, - Fp2: Fp2Bls, - base: Fp2, -): { - psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] - psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] - G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType - G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType - PSI_X: Fp2 - PSI_Y: Fp2 - PSI2_X: Fp2 - PSI2_Y: Fp2 -} { - // Ψ endomorphism - const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) - const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) - function psi(x: Fp2, y: Fp2): [Fp2, Fp2] { - // This x10 faster than previous version in bls12-381 - const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) - const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) - return [x2, y2] - } - // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) - const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) - // This equals -1, which causes y to be Fp2.neg(y). - // But not sure if there are case when this is not true? - const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) - if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') - function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] { - return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] - } - // Map points - const mapAffine = - (fn: (x: T, y: T) => [T, T]) => - (c: ProjConstructor, P: ProjPointType) => { - const affine = P.toAffine() - const p = fn(affine.x, affine.y) - return c.fromAffine({ x: p[0], y: p[1] }) - } - const G2psi = mapAffine(psi) - const G2psi2 = mapAffine(psi2) - return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } -} - -export type Tower12Opts = { - ORDER: bigint - NONRESIDUE?: Fp - // Fp2 - FP2_NONRESIDUE: BigintTuple - Fp2sqrt?: (num: Fp2) => Fp2 - Fp2mulByB: (num: Fp2) => Fp2 - // Fp12 - Fp12cyclotomicSquare: (num: Fp12) => Fp12 - Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 - Fp12finalExponentiate: (num: Fp12) => Fp12 -} - -export function tower12(opts: Tower12Opts): { - Fp: Readonly & Required, 'isOdd'>>> - Fp2: mod.IField & { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { re: bigint; im: bigint } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - Fp6: mod.IField & { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 } - Fp12: mod.IField & { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } -} { - const { ORDER } = opts - // Fp - const Fp = mod.Field(ORDER) - const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) - const FpLegendre = mod.FpLegendre(ORDER) - const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 - - // Fp2 - const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] - const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ - c0: Fp.add(c0, r0), - c1: Fp.add(c1, r1), - }) - const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ - c0: Fp.sub(c0, r0), - c1: Fp.sub(c1, r1), - }) - const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => { - if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } - // (a+bi)(c+di) = (ac−bd) + (ad+bc)i - const { c0: r0, c1: r1 } = rhs - let t1 = Fp.mul(c0, r0) // c0 * o0 - let t2 = Fp.mul(c1, r1) // c1 * o1 - // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i - const o0 = Fp.sub(t1, t2) - const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) - return { c0: o0, c1: o1 } - } - const Fp2Square = ({ c0, c1 }: Fp2) => { - const a = Fp.add(c0, c1) - const b = Fp.sub(c0, c1) - const c = Fp.add(c0, c0) - return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } - } - type Fp2Utils = { - NONRESIDUE: Fp2 - fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 - reim: (num: Fp2) => { re: bigint; im: bigint } - mulByNonresidue: (num: Fp2) => Fp2 - mulByB: (num: Fp2) => Fp2 - frobeniusMap(num: Fp2, power: number): Fp2 - } - const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => { - if (tuple.length !== 2) throw new Error('invalid tuple') - const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp] - return { c0: fps[0], c1: fps[1] } - } - - const FP2_ORDER = ORDER * ORDER - const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) - const Fp2: mod.IField & Fp2Utils = { - ORDER: FP2_ORDER, - isLE: Fp.isLE, - NONRESIDUE: Fp2Nonresidue, - BITS: bitLen(FP2_ORDER), - BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), - MASK: bitMask(bitLen(FP2_ORDER)), - ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, - ONE: { c0: Fp.ONE, c1: Fp.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', - is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), - eql: ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => Fp.eql(c0, r0) && Fp.eql(c1, r1), - neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), - pow: (num, power) => mod.FpPow(Fp2, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), - // Normalized - add: Fp2Add, - sub: Fp2Subtract, - mul: Fp2Multiply, - sqr: Fp2Square, - // NonNormalized stuff - addN: Fp2Add, - subN: Fp2Subtract, - mulN: Fp2Multiply, - sqrN: Fp2Square, - // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? - div: (lhs, rhs) => - Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), - inv: ({ c0: a, c1: b }) => { - // We wish to find the multiplicative inverse of a nonzero - // element a + bu in Fp2. We leverage an identity - // - // (a + bu)(a - bu) = a² + b² - // - // which holds because u² = -1. This can be rewritten as - // - // (a + bu)(a - bu)/(a² + b²) = 1 - // - // because a² + b² = 0 has no nonzero solutions for (a, b). - // This gives that (a - bu)/(a² + b²) is the inverse - // of (a + bu). Importantly, this can be computing using - // only a single inversion in Fp. - const factor = Fp.inv(Fp.create(a * a + b * b)) - return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } - }, - sqrt: (num) => { - if (opts.Fp2sqrt) return opts.Fp2sqrt(num) - // This is generic for all quadratic extensions (Fp2) - const { c0, c1 } = num - if (Fp.is0(c1)) { - // if c0 is quadratic residue - if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) - else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) - } - const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) - let d = Fp.mul(Fp.add(a, c0), Fpdiv2) - const legendre = FpLegendre(Fp, d) - // -1, Quadratic non residue - if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) - const a0 = Fp.sqrt(d) - const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) - if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') - // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num - const x1 = candidateSqrt - const x2 = Fp2.neg(x1) - const { re: re1, im: im1 } = Fp2.reim(x1) - const { re: re2, im: im2 } = Fp2.reim(x2) - if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 - return x2 - }, - // Same as sgn0_m_eq_2 in RFC 9380 - isOdd: (x: Fp2) => { - const { re: x0, im: x1 } = Fp2.reim(x) - const sign_0 = x0 % _2n - const zero_0 = x0 === _0n - const sign_1 = x1 % _2n - return BigInt(sign_0 || (zero_0 && sign_1)) == _1n - }, - // Bytes util - fromBytes(b: Uint8Array): Fp2 { - if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } - }, - toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp.cmov(c0, r0, c), - c1: Fp.cmov(c1, r1, c), - }), - reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), - // multiply by u + 1 - mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), - mulByB: opts.Fp2mulByB, - fromBigTuple: Fp2fromBigTuple, - frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({ - c0, - c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), - }), - } - // Fp6 - const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ - c0: Fp2.add(c0, r0), - c1: Fp2.add(c1, r1), - c2: Fp2.add(c2, r2), - }) - const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ - c0: Fp2.sub(c0, r0), - c1: Fp2.sub(c1, r1), - c2: Fp2.sub(c2, r2), - }) - const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => { - if (typeof rhs === 'bigint') { - return { - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - } - } - const { c0: r0, c1: r1, c2: r2 } = rhs - const t0 = Fp2.mul(c0, r0) // c0 * o0 - const t1 = Fp2.mul(c1, r1) // c1 * o1 - const t2 = Fp2.mul(c2, r2) // c2 * o2 - return { - // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) - c0: Fp2.add( - t0, - Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), - ), - // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) - c1: Fp2.add( - Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), - Fp2.mulByNonresidue(t2), - ), - // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 - c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), - } - } - const Fp6Square = ({ c0, c1, c2 }: Fp6) => { - let t0 = Fp2.sqr(c0) // c0² - let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 - let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 - let t4 = Fp2.sqr(c2) // c2² - return { - c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 - c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 - // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 - c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), - } - } - type Fp6Utils = { - fromBigSix: (tuple: BigintSix) => Fp6 - mulByNonresidue: (num: Fp6) => Fp6 - frobeniusMap(num: Fp6, power: number): Fp6 - mul1(num: Fp6, b1: Fp2): Fp6 - mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 - mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 - } - - const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 6, - 2, - 3, - ) - - const Fp6: mod.IField & Fp6Utils = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp2.isLE, - BITS: 3 * Fp2.BITS, - BYTES: 3 * Fp2.BYTES, - MASK: bitMask(3 * Fp2.BITS), - ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, - ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, - create: (num) => num, - isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), - is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), - neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), - eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => - Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), - sqrt: notImplemented, - // Do we need division by bigint at all? Should be done via order: - div: (lhs, rhs) => - Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp6, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), - // Normalized - add: Fp6Add, - sub: Fp6Subtract, - mul: Fp6Multiply, - sqr: Fp6Square, - // NonNormalized stuff - addN: Fp6Add, - subN: Fp6Subtract, - mulN: Fp6Multiply, - sqrN: Fp6Square, - - inv: ({ c0, c1, c2 }) => { - let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) - let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 - let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 - // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) - let t4 = Fp2.inv( - Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), - ) - return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } - }, - // Bytes utils - fromBytes: (b: Uint8Array): Fp6 => { - if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), - c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), - c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), - } - }, - toBytes: ({ c0, c1, c2 }): Uint8Array => - concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), - cmov: ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6, c) => ({ - c0: Fp2.cmov(c0, r0, c), - c1: Fp2.cmov(c1, r1, c), - c2: Fp2.cmov(c2, r2, c), - }), - fromBigSix: (t: BigintSix): Fp6 => { - if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') - return { - c0: Fp2.fromBigTuple(t.slice(0, 2)), - c1: Fp2.fromBigTuple(t.slice(2, 4)), - c2: Fp2.fromBigTuple(t.slice(4, 6)), - } - }, - frobeniusMap: ({ c0, c1, c2 }, power: number) => ({ - c0: Fp2.frobeniusMap(c0, power), - c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), - c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), - }), - mulByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({ - c0: Fp2.mul(c0, rhs), - c1: Fp2.mul(c1, rhs), - c2: Fp2.mul(c2, rhs), - }), - mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), - // Sparse multiplication - mul1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({ - c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), - c1: Fp2.mul(c0, b1), - c2: Fp2.mul(c1, b1), - }), - // Sparse multiplication - mul01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 { - let t0 = Fp2.mul(c0, b0) // c0 * b0 - let t1 = Fp2.mul(c1, b1) // c1 * b1 - return { - // ((c1 + c2) * b1 - T1) * (u + 1) + T0 - c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), - // (b0 + b1) * (c0 + c1) - T0 - T1 - c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), - // (c0 + c2) * b0 - T0 + T1 - c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), - } - }, - } - - // Fp12 - const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( - Fp2, - Fp2Nonresidue, - Fp.ORDER, - 12, - 1, - 6, - )[0] - - const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ - c0: Fp6.add(c0, r0), - c1: Fp6.add(c1, r1), - }) - const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ - c0: Fp6.sub(c0, r0), - c1: Fp6.sub(c1, r1), - }) - const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => { - if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } - let { c0: r0, c1: r1 } = rhs - let t1 = Fp6.mul(c0, r0) // c0 * r0 - let t2 = Fp6.mul(c1, r1) // c1 * r1 - return { - c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v - // (c0 + c1) * (r0 + r1) - (T1 + T2) - c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), - } - } - const Fp12Square = ({ c0, c1 }: Fp12) => { - let ab = Fp6.mul(c0, c1) // c0 * c1 - return { - // (c1 * v + c0) * (c0 + c1) - AB - AB * v - c0: Fp6.sub( - Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), - Fp6.mulByNonresidue(ab), - ), - c1: Fp6.add(ab, ab), - } // AB + AB - } - function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } { - const a2 = Fp2.sqr(a) - const b2 = Fp2.sqr(b) - return { - first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² - second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² - } - } - type Fp12Utils = { - fromBigTwelve: (t: BigintTwelve) => Fp12 - frobeniusMap(num: Fp12, power: number): Fp12 - mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 - mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 - mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 - conjugate(num: Fp12): Fp12 - finalExponentiate(num: Fp12): Fp12 - _cyclotomicSquare(num: Fp12): Fp12 - _cyclotomicExp(num: Fp12, n: bigint): Fp12 - } - - const Fp12: mod.IField & Fp12Utils = { - ORDER: Fp2.ORDER, // TODO: unused, but need to verify - isLE: Fp6.isLE, - BITS: 2 * Fp6.BITS, - BYTES: 2 * Fp6.BYTES, - MASK: bitMask(2 * Fp6.BITS), - ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, - ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, - create: (num) => num, - isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), - is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), - neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), - eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), - sqrt: notImplemented, - inv: ({ c0, c1 }) => { - let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) - return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w - }, - div: (lhs, rhs) => - Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), - pow: (num, power) => mod.FpPow(Fp12, num, power), - invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), - // Normalized - add: Fp12Add, - sub: Fp12Subtract, - mul: Fp12Multiply, - sqr: Fp12Square, - // NonNormalized stuff - addN: Fp12Add, - subN: Fp12Subtract, - mulN: Fp12Multiply, - sqrN: Fp12Square, - - // Bytes utils - fromBytes: (b: Uint8Array): Fp12 => { - if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) - return { - c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), - c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), - } - }, - toBytes: ({ c0, c1 }): Uint8Array => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), - cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ - c0: Fp6.cmov(c0, r0, c), - c1: Fp6.cmov(c1, r1, c), - }), - // Utils - // toString() { - // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); - // }, - // fromTuple(c: [Fp6, Fp6]) { - // return new Fp12(...c); - // } - fromBigTwelve: (t: BigintTwelve): Fp12 => ({ - c0: Fp6.fromBigSix(t.slice(0, 6) as BigintSix), - c1: Fp6.fromBigSix(t.slice(6, 12) as BigintSix), - }), - // Raises to q**i -th power - frobeniusMap(lhs, power: number) { - const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) - const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] - return { - c0: Fp6.frobeniusMap(lhs.c0, power), - c1: Fp6.create({ - c0: Fp2.mul(c0, coeff), - c1: Fp2.mul(c1, coeff), - c2: Fp2.mul(c2, coeff), - }), - } - }, - mulByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({ - c0: Fp6.mulByFp2(c0, rhs), - c1: Fp6.mulByFp2(c1, rhs), - }), - conjugate: ({ c0, c1 }): Fp12 => ({ c0, c1: Fp6.neg(c1) }), - // Sparse multiplication - mul014: ({ c0, c1 }, o0: Fp2, o1: Fp2, o4: Fp2) => { - let t0 = Fp6.mul01(c0, o0, o1) - let t1 = Fp6.mul1(c1, o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 - // (c1 + c0) * [o0, o1+o4] - T0 - T1 - c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), - } - }, - mul034: ({ c0, c1 }, o0: Fp2, o3: Fp2, o4: Fp2) => { - const a = Fp6.create({ - c0: Fp2.mul(c0.c0, o0), - c1: Fp2.mul(c0.c1, o0), - c2: Fp2.mul(c0.c2, o0), - }) - const b = Fp6.mul01(c1, o3, o4) - const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) - return { - c0: Fp6.add(Fp6.mulByNonresidue(b), a), - c1: Fp6.sub(e, Fp6.add(a, b)), - } - }, - - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - _cyclotomicSquare: opts.Fp12cyclotomicSquare, - _cyclotomicExp: opts.Fp12cyclotomicExp, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - finalExponentiate: opts.Fp12finalExponentiate, - } - - return { Fp, Fp2, Fp6, Fp4Square, Fp12 } -} diff --git a/packages/noble-curves-tmp/src/abstract/utils.ts b/packages/noble-curves-tmp/src/abstract/utils.ts deleted file mode 100644 index de81eaef58b..00000000000 --- a/packages/noble-curves-tmp/src/abstract/utils.ts +++ /dev/null @@ -1,378 +0,0 @@ -/** - * Hex, bytes and number utilities. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ - -// 100 lines of code in the file are duplicated from noble-hashes (utils). -// This is OK: `abstract` directory does not use noble-hashes. -// User may opt-in into using different hashing library. This way, noble-hashes -// won't be included into their bundle. -const _0n = /* @__PURE__ */ BigInt(0) -const _1n = /* @__PURE__ */ BigInt(1) -export type Hex = Uint8Array | string // hex strings are accepted for simplicity -export type PrivKey = Hex | bigint // bigints are accepted to ease learning curve -export type CHash = { - (message: Uint8Array | string): Uint8Array - blockLen: number - outputLen: number - create(opts?: { dkLen?: number }): any // For shake -} -export type FHash = (message: Uint8Array | string) => Uint8Array - -export function isBytes(a: unknown): a is Uint8Array { - return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') -} - -export function abytes(item: unknown): void { - if (!isBytes(item)) throw new Error('Uint8Array expected') -} - -export function abool(title: string, value: boolean): void { - if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) -} - -export function numberToHexUnpadded(num: number | bigint): string { - const hex = num.toString(16) - return hex.length & 1 ? '0' + hex : hex -} - -export function hexToNumber(hex: string): bigint { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian -} - -// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex -const hasHexBuiltin: boolean = - // @ts-ignore - typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function' - -// Array where index 0xf0 (240) is mapped to string 'f0' -const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) - -/** - * Convert byte array to hex string. Uses built-in function, when available. - * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' - */ -export function bytesToHex(bytes: Uint8Array): string { - abytes(bytes) - // @ts-ignore - if (hasHexBuiltin) return bytes.toHex() - // pre-caching improves the speed 6x - let hex = '' - for (let i = 0; i < bytes.length; i++) { - hex += hexes[bytes[i]] - } - return hex -} - -// We use optimized technique to convert hex string to byte array -const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const -function asciiToBase16(ch: number): number | undefined { - if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 - if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) - if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) - return -} - -/** - * Convert hex string to byte array. Uses built-in function, when available. - * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) - */ -export function hexToBytes(hex: string): Uint8Array { - if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) - // @ts-ignore - if (hasHexBuiltin) return Uint8Array.fromHex(hex) - const hl = hex.length - const al = hl / 2 - if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) - const array = new Uint8Array(al) - for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { - const n1 = asciiToBase16(hex.charCodeAt(hi)) - const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) - if (n1 === undefined || n2 === undefined) { - const char = hex[hi] + hex[hi + 1] - throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) - } - array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 - } - return array -} - -// BE: Big Endian, LE: Little Endian -export function bytesToNumberBE(bytes: Uint8Array): bigint { - return hexToNumber(bytesToHex(bytes)) -} -export function bytesToNumberLE(bytes: Uint8Array): bigint { - abytes(bytes) - return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) -} - -export function numberToBytesBE(n: number | bigint, len: number): Uint8Array { - return hexToBytes(n.toString(16).padStart(len * 2, '0')) -} -export function numberToBytesLE(n: number | bigint, len: number): Uint8Array { - return numberToBytesBE(n, len).reverse() -} -// Unpadded, rarely used -export function numberToVarBytesBE(n: number | bigint): Uint8Array { - return hexToBytes(numberToHexUnpadded(n)) -} - -/** - * Takes hex string or Uint8Array, converts to Uint8Array. - * Validates output length. - * Will throw error for other types. - * @param title descriptive title for an error e.g. 'private key' - * @param hex hex string or Uint8Array - * @param expectedLength optional, will compare to result array's length - * @returns - */ -export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array { - let res: Uint8Array - if (typeof hex === 'string') { - try { - res = hexToBytes(hex) - } catch (e) { - throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) - } - } else if (isBytes(hex)) { - // Uint8Array.from() instead of hash.slice() because node.js Buffer - // is instance of Uint8Array, and its slice() creates **mutable** copy - res = Uint8Array.from(hex) - } else { - throw new Error(title + ' must be hex string or Uint8Array') - } - const len = res.length - if (typeof expectedLength === 'number' && len !== expectedLength) - throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) - return res -} - -/** - * Copies several Uint8Arrays into one. - */ -export function concatBytes(...arrays: Uint8Array[]): Uint8Array { - let sum = 0 - for (let i = 0; i < arrays.length; i++) { - const a = arrays[i] - abytes(a) - sum += a.length - } - const res = new Uint8Array(sum) - for (let i = 0, pad = 0; i < arrays.length; i++) { - const a = arrays[i] - res.set(a, pad) - pad += a.length - } - return res -} - -// Compares 2 u8a-s in kinda constant time -export function equalBytes(a: Uint8Array, b: Uint8Array): boolean { - if (a.length !== b.length) return false - let diff = 0 - for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] - return diff === 0 -} - -// Global symbols in both browsers and Node.js since v11 -// See https://github.com/microsoft/TypeScript/issues/31535 -declare const TextEncoder: any - -/** - * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) - */ -export function utf8ToBytes(str: string): Uint8Array { - if (typeof str !== 'string') throw new Error('string expected') - return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 -} - -// Is positive bigint -const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n - -export function inRange(n: bigint, min: bigint, max: bigint): boolean { - return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max -} - -/** - * Asserts min <= n < max. NOTE: It's < max and not <= max. - * @example - * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) - */ -export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void { - // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? - // consider P=256n, min=0n, max=P - // - a for min=0 would require -1: `inRange('x', x, -1n, P)` - // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` - // - our way is the cleanest: `inRange('x', x, 0n, P) - if (!inRange(n, min, max)) - throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) -} - -// Bit operations - -/** - * Calculates amount of bits in a bigint. - * Same as `n.toString(2).length` - */ -export function bitLen(n: bigint): number { - let len - for (len = 0; n > _0n; n >>= _1n, len += 1); - return len -} - -/** - * Gets single bit at position. - * NOTE: first bit position is 0 (same as arrays) - * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` - */ -export function bitGet(n: bigint, pos: number): bigint { - return (n >> BigInt(pos)) & _1n -} - -/** - * Sets single bit at position. - */ -export function bitSet(n: bigint, pos: number, value: boolean): bigint { - return n | ((value ? _1n : _0n) << BigInt(pos)) -} - -/** - * Calculate mask for N bits. Not using ** operator with bigints because of old engines. - * Same as BigInt(`0b${Array(i).fill('1').join('')}`) - */ -export const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n - -// DRBG - -const u8n = (len: number) => new Uint8Array(len) // creates Uint8Array -const u8fr = (arr: ArrayLike) => Uint8Array.from(arr) // another shortcut -type Pred = (v: Uint8Array) => T | undefined -/** - * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - * @returns function that will call DRBG until 2nd arg returns something meaningful - * @example - * const drbg = createHmacDRBG(32, 32, hmac); - * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined - */ -export function createHmacDrbg( - hashLen: number, - qByteLen: number, - hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, -): (seed: Uint8Array, predicate: Pred) => T { - if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') - if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') - if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') - // Step B, Step C: set hashLen to 8*ceil(hlen/8) - let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. - let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same - let i = 0 // Iterations counter, will throw when over 1000 - const reset = () => { - v.fill(1) - k.fill(0) - i = 0 - } - const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) - const reseed = (seed = u8n(0)) => { - // HMAC-DRBG reseed() function. Steps D-G - k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) - v = h() // v = hmac(k || v) - if (seed.length === 0) return - k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) - v = h() // v = hmac(k || v) - } - const gen = () => { - // HMAC-DRBG generate() function - if (i++ >= 1000) throw new Error('drbg: tried 1000 values') - let len = 0 - const out: Uint8Array[] = [] - while (len < qByteLen) { - v = h() - const sl = v.slice() - out.push(sl) - len += v.length - } - return concatBytes(...out) - } - const genUntil = (seed: Uint8Array, pred: Pred): T => { - reset() - reseed(seed) // Steps D-G - let res: T | undefined = undefined // Step H: grind until k is in [1..n-1] - while (!(res = pred(gen()))) reseed() - reset() - return res - } - return genUntil -} - -// Validating curves and fields - -const validatorFns = { - bigint: (val: any): boolean => typeof val === 'bigint', - function: (val: any): boolean => typeof val === 'function', - boolean: (val: any): boolean => typeof val === 'boolean', - string: (val: any): boolean => typeof val === 'string', - stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val), - isSafeInteger: (val: any): boolean => Number.isSafeInteger(val), - array: (val: any): boolean => Array.isArray(val), - field: (val: any, object: any): any => (object as any).Fp.isValid(val), - hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen), -} as const -type Validator = keyof typeof validatorFns -type ValMap> = { [K in keyof T]?: Validator } -// type Record = { [P in K]: T; } - -export function validateObject>( - object: T, - validators: ValMap, - optValidators: ValMap = {}, -): T { - const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => { - const checkVal = validatorFns[type] - if (typeof checkVal !== 'function') throw new Error('invalid validator function') - - const val = object[fieldName as keyof typeof object] - if (isOptional && val === undefined) return - if (!checkVal(val, object)) { - throw new Error( - 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, - ) - } - } - for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false) - for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true) - return object -} -// validate type tests -// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; -// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! -// // Should fail type-check -// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); -// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); -// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); -// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); - -/** - * throws not implemented error - */ -export const notImplemented = (): never => { - throw new Error('not implemented') -} - -/** - * Memoizes (caches) computation result. - * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. - */ -export function memoized( - fn: (arg: T, ...args: O) => R, -): (arg: T, ...args: O) => R { - const map = new WeakMap() - return (arg: T, ...args: O): R => { - const val = map.get(arg) - if (val !== undefined) return val - const computed = fn(arg, ...args) - map.set(arg, computed) - return computed - } -} diff --git a/packages/noble-curves-tmp/src/abstract/weierstrass.ts b/packages/noble-curves-tmp/src/abstract/weierstrass.ts deleted file mode 100644 index b713756adbe..00000000000 --- a/packages/noble-curves-tmp/src/abstract/weierstrass.ts +++ /dev/null @@ -1,1419 +0,0 @@ -/** - * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. - * - * ### Parameters - * - * To initialize a weierstrass curve, one needs to pass following params: - * - * * a: formula param - * * b: formula param - * * Fp: finite Field over which we'll do calculations. Can be complex (Fp2, Fp12) - * * n: Curve prime subgroup order, total count of valid points in the field - * * Gx: Base point (x, y) aka generator point x coordinate - * * Gy: ...y coordinate - * * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order) - * * lowS: whether to enable (default) or disable "low-s" non-malleable signatures - * - * ### Design rationale for types - * - * * Interaction between classes from different curves should fail: - * `k256.Point.BASE.add(p256.Point.BASE)` - * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime - * * Different calls of `curve()` would return different classes - - * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, - * it won't affect others - * - * TypeScript can't infer types for classes created inside a function. Classes is one instance - * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create - * unique type for every function call. - * - * We can use generic types via some param, like curve opts, but that would: - * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) - * which is hard to debug. - * 2. Params can be generic and we can't enforce them to be constant value: - * if somebody creates curve from non-constant params, - * it would be allowed to interact with other curves with non-constant params - * - * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -// prettier-ignore -import { - type AffinePoint, - type BasicCurve, - type Group, - type GroupConstructor, - pippenger, - validateBasic, - wNAF, -} from './curve.ts' -// prettier-ignore -import { - Field, - type IField, - getMinHashLength, - invert, - mapHashToField, - mod, - validateField, -} from './modular.ts' -// prettier-ignore -import { - type CHash, - type Hex, - type PrivKey, - aInRange, - abool, - bitMask, - bytesToHex, - bytesToNumberBE, - concatBytes, - createHmacDrbg, - ensureBytes, - hexToBytes, - inRange, - isBytes, - memoized, - numberToBytesBE, - numberToHexUnpadded, - validateObject, -} from './utils.ts' - -export type { AffinePoint } -type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array -type EndomorphismOpts = { - beta: bigint - splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint } -} -export type BasicWCurve = BasicCurve & { - // Params: a, b - a: T - b: T - - // Optional params - allowedPrivateKeyLengths?: readonly number[] // for P521 - wrapPrivateKey?: boolean // bls12-381 requires mod(n) instead of rejecting keys >= n - endo?: EndomorphismOpts // Endomorphism options for Koblitz curves - // When a cofactor != 1, there can be an effective methods to: - // 1. Determine whether a point is torsion-free - isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean - // 2. Clear torsion component - clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType -} - -export type Entropy = Hex | boolean -export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean } -export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined } - -function validateSigVerOpts(opts: SignOpts | VerOpts) { - if (opts.lowS !== undefined) abool('lowS', opts.lowS) - if (opts.prehash !== undefined) abool('prehash', opts.prehash) -} - -// Instance for 3d XYZ points -export interface ProjPointType extends Group> { - readonly px: T - readonly py: T - readonly pz: T - get x(): T - get y(): T - toAffine(iz?: T): AffinePoint - toHex(isCompressed?: boolean): string - toRawBytes(isCompressed?: boolean): Uint8Array - - assertValidity(): void - hasEvenY(): boolean - multiplyUnsafe(scalar: bigint): ProjPointType - multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined - isTorsionFree(): boolean - clearCofactor(): ProjPointType - _setWindowSize(windowSize: number): void -} -// Static methods for 3d XYZ points -export interface ProjConstructor extends GroupConstructor> { - new (x: T, y: T, z: T): ProjPointType - fromAffine(p: AffinePoint): ProjPointType - fromHex(hex: Hex): ProjPointType - fromPrivateKey(privateKey: PrivKey): ProjPointType - normalizeZ(points: ProjPointType[]): ProjPointType[] - msm(points: ProjPointType[], scalars: bigint[]): ProjPointType -} - -export type CurvePointsType = BasicWCurve & { - // Bytes - fromBytes?: (bytes: Uint8Array) => AffinePoint - toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array -} - -export type CurvePointsTypeWithLength = Readonly< - CurvePointsType & { nByteLength: number; nBitLength: number } -> - -function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength { - const opts = validateBasic(curve) - validateObject( - opts, - { - a: 'field', - b: 'field', - }, - { - allowedPrivateKeyLengths: 'array', - wrapPrivateKey: 'boolean', - isTorsionFree: 'function', - clearCofactor: 'function', - allowInfinityPoint: 'boolean', - fromBytes: 'function', - toBytes: 'function', - }, - ) - const { endo, Fp, a } = opts - if (endo) { - if (!Fp.eql(a, Fp.ZERO)) { - throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') - } - if ( - typeof endo !== 'object' || - typeof endo.beta !== 'bigint' || - typeof endo.splitScalar !== 'function' - ) { - throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') - } - } - return Object.freeze({ ...opts } as const) -} - -export type CurvePointsRes = { - CURVE: ReturnType> - ProjectivePoint: ProjConstructor - normPrivateKeyToScalar: (key: PrivKey) => bigint - weierstrassEquation: (x: T) => T - isWithinCurveOrder: (num: bigint) => boolean -} - -export class DERErr extends Error { - constructor(m = '') { - super(m) - } -} -export type IDER = { - // asn.1 DER encoding utils - Err: typeof DERErr - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag: number, data: string) => string - // v - value, l - left bytes (unparsed) - decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } - } - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num: bigint): string - decode(data: Uint8Array): bigint - } - toSig(hex: string | Uint8Array): { r: bigint; s: bigint } - hexFromSig(sig: { r: bigint; s: bigint }): string -} -/** - * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: - * - * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] - * - * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html - */ -export const DER: IDER = { - // asn.1 DER encoding utils - Err: DERErr, - // Basic building block is TLV (Tag-Length-Value) - _tlv: { - encode: (tag: number, data: string): string => { - const { Err: E } = DER - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length & 1) throw new E('tlv.encode: unpadded data') - const dataLen = data.length / 2 - const len = numberToHexUnpadded(dataLen) - if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big') - // length of length with long form flag - const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '' - const t = numberToHexUnpadded(tag) - return t + lenLen + len + data - }, - // v - value, l - left bytes (unparsed) - decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } { - const { Err: E } = DER - let pos = 0 - if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') - if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') - const first = data[pos++] - const isLong = !!(first & 0b1000_0000) // First bit of first length byte is flag for short/long form - let length = 0 - if (!isLong) length = first - else { - // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] - const lenLen = first & 0b0111_1111 - if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') - if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js - const lengthBytes = data.subarray(pos, pos + lenLen) - if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') - if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') - for (const b of lengthBytes) length = (length << 8) | b - pos += lenLen - if (length < 128) throw new E('tlv.decode(long): not minimal encoding') - } - const v = data.subarray(pos, pos + length) - if (v.length !== length) throw new E('tlv.decode: wrong value length') - return { v, l: data.subarray(pos + length) } - }, - }, - // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, - // since we always use positive integers here. It must always be empty: - // - add zero byte if exists - // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) - _int: { - encode(num: bigint): string { - const { Err: E } = DER - if (num < _0n) throw new E('integer: negative integers are not allowed') - let hex = numberToHexUnpadded(num) - // Pad with zero byte if negative flag is present - if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex - if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') - return hex - }, - decode(data: Uint8Array): bigint { - const { Err: E } = DER - if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative') - if (data[0] === 0x00 && !(data[1] & 0b1000_0000)) - throw new E('invalid signature integer: unnecessary leading zero') - return bytesToNumberBE(data) - }, - }, - toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { - // parse DER signature - const { Err: E, _int: int, _tlv: tlv } = DER - const data = ensureBytes('signature', hex) - const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) - if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) - const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) - if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') - return { r: int.decode(rBytes), s: int.decode(sBytes) } - }, - hexFromSig(sig: { r: bigint; s: bigint }): string { - const { _tlv: tlv, _int: int } = DER - const rs = tlv.encode(0x02, int.encode(sig.r)) - const ss = tlv.encode(0x02, int.encode(sig.s)) - const seq = rs + ss - return tlv.encode(0x30, seq) - }, -} - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) - -export function weierstrassPoints(opts: CurvePointsType): CurvePointsRes { - const CURVE = validatePointOpts(opts) - const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ - const Fn = Field(CURVE.n, CURVE.nBitLength) - - const toBytes = - CURVE.toBytes || - ((_c: ProjConstructor, point: ProjPointType, _isCompressed: boolean) => { - const a = point.toAffine() - return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) - }) - const fromBytes = - CURVE.fromBytes || - ((bytes: Uint8Array) => { - // const head = bytes[0]; - const tail = bytes.subarray(1) - // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - }) - - /** - * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y². - * @returns y² - */ - function weierstrassEquation(x: T): T { - const { a, b } = CURVE - const x2 = Fp.sqr(x) // x * x - const x3 = Fp.mul(x2, x) // x2 * x - return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b - } - // Validate whether the passed curve params are valid. - // We check if curve equation works for generator point. - // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. - // ProjectivePoint class has not been initialized yet. - if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) - throw new Error('bad generator point: equation left != right') - - // Valid group elements reside in range 1..n-1 - function isWithinCurveOrder(num: bigint): boolean { - return inRange(num, _1n, CURVE.n) - } - // Validates if priv key is valid and converts it to bigint. - // Supports options allowedPrivateKeyLengths and wrapPrivateKey. - function normPrivateKeyToScalar(key: PrivKey): bigint { - const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE - if (lengths && typeof key !== 'bigint') { - if (isBytes(key)) key = bytesToHex(key) - // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes - if (typeof key !== 'string' || !lengths.includes(key.length)) - throw new Error('invalid private key') - key = key.padStart(nByteLength * 2, '0') - } - let num: bigint - try { - num = - typeof key === 'bigint' - ? key - : bytesToNumberBE(ensureBytes('private key', key, nByteLength)) - } catch (error) { - throw new Error( - 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, - ) - } - if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS - aInRange('private key', num, _1n, N) // num in range [1..N-1] - return num - } - - function aprjpoint(other: unknown) { - if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') - } - - // Memoized toAffine / validity check. They are heavy. Points are immutable. - - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint => { - const { px: x, py: y, pz: z } = p - // Fast-path for normalized points - if (Fp.eql(z, Fp.ONE)) return { x, y } - const is0 = p.is0() - // If invZ was 0, we return zero point. However we still want to execute - // all operations, so we replace invZ with a random number, 1. - if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) - const ax = Fp.mul(x, iz) - const ay = Fp.mul(y, iz) - const zz = Fp.mul(z, iz) - if (is0) return { x: Fp.ZERO, y: Fp.ZERO } - if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') - return { x: ax, y: ay } - }) - // NOTE: on exception this will crash 'cached' and no value will be set. - // Otherwise true will be return - const assertValidMemo = memoized((p: Point) => { - if (p.is0()) { - // (0, 1, 0) aka ZERO is invalid in most contexts. - // In BLS, ZERO can be serialized, so we allow it. - // (0, 0, 0) is invalid representation of ZERO. - if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return - throw new Error('bad point: ZERO') - } - // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` - const { x, y } = p.toAffine() - // Check if x, y are valid field elements - if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') - const left = Fp.sqr(y) // y² - const right = weierstrassEquation(x) // x³ + ax + b - if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') - if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') - return true - }) - - /** - * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) - * Default Point works in 2d / affine coordinates: (x, y) - * We're doing calculations in projective, because its operations don't require costly inversion. - */ - class Point implements ProjPointType { - static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) - static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) // 0, 1, 0 - readonly px: T - readonly py: T - readonly pz: T - - constructor(px: T, py: T, pz: T) { - if (px == null || !Fp.isValid(px)) throw new Error('x required') - if (py == null || !Fp.isValid(py) || Fp.is0(py)) throw new Error('y required') - if (pz == null || !Fp.isValid(pz)) throw new Error('z required') - this.px = px - this.py = py - this.pz = pz - Object.freeze(this) - } - - // Does not validate if the point is on-curve. - // Use fromHex instead, or call assertValidity() later. - static fromAffine(p: AffinePoint): Point { - const { x, y } = p || {} - if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') - if (p instanceof Point) throw new Error('projective point not allowed') - const is0 = (i: T) => Fp.eql(i, Fp.ZERO) - // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) - if (is0(x) && is0(y)) return Point.ZERO - return new Point(x, y, Fp.ONE) - } - - get x(): T { - return this.toAffine().x - } - get y(): T { - return this.toAffine().y - } - - /** - * Takes a bunch of Projective Points but executes only one - * inversion on all of them. Inversion is very slow operation, - * so this improves performance massively. - * Optimization: converts a list of projective points to a list of identical points with Z=1. - */ - static normalizeZ(points: Point[]): Point[] { - const toInv = Fp.invertBatch(points.map((p) => p.pz)) - return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) - } - - /** - * Converts hash string or Uint8Array to Point. - * @param hex short/long ECDSA hex - */ - static fromHex(hex: Hex): Point { - const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) - P.assertValidity() - return P - } - - // Multiplies generator point by privateKey. - static fromPrivateKey(privateKey: PrivKey) { - return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) - } - - // Multiscalar Multiplication - static msm(points: Point[], scalars: bigint[]): Point { - return pippenger(Point, Fn, points, scalars) - } - - // "Private method", don't use it directly - _setWindowSize(windowSize: number) { - wnaf.setWindowSize(this, windowSize) - } - - // A point on curve is valid if it conforms to equation. - assertValidity(): void { - assertValidMemo(this) - } - - hasEvenY(): boolean { - const { y } = this.toAffine() - if (Fp.isOdd) return !Fp.isOdd(y) - throw new Error("Field doesn't support isOdd") - } - - /** - * Compare one point to another. - */ - equals(other: Point): boolean { - aprjpoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) - const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) - return U1 && U2 - } - - /** - * Flips point to one corresponding to (x, -y) in Affine coordinates. - */ - negate(): Point { - return new Point(this.px, Fp.neg(this.py), this.pz) - } - - // Renes-Costello-Batina exception-free doubling formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 3 - // Cost: 8M + 3S + 3*a + 2*b3 + 15add. - double() { - const { a, b } = CURVE - const b3 = Fp.mul(b, _3n) - const { px: X1, py: Y1, pz: Z1 } = this - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - let t0 = Fp.mul(X1, X1) // step 1 - let t1 = Fp.mul(Y1, Y1) - let t2 = Fp.mul(Z1, Z1) - let t3 = Fp.mul(X1, Y1) - t3 = Fp.add(t3, t3) // step 5 - Z3 = Fp.mul(X1, Z1) - Z3 = Fp.add(Z3, Z3) - X3 = Fp.mul(a, Z3) - Y3 = Fp.mul(b3, t2) - Y3 = Fp.add(X3, Y3) // step 10 - X3 = Fp.sub(t1, Y3) - Y3 = Fp.add(t1, Y3) - Y3 = Fp.mul(X3, Y3) - X3 = Fp.mul(t3, X3) - Z3 = Fp.mul(b3, Z3) // step 15 - t2 = Fp.mul(a, t2) - t3 = Fp.sub(t0, t2) - t3 = Fp.mul(a, t3) - t3 = Fp.add(t3, Z3) - Z3 = Fp.add(t0, t0) // step 20 - t0 = Fp.add(Z3, t0) - t0 = Fp.add(t0, t2) - t0 = Fp.mul(t0, t3) - Y3 = Fp.add(Y3, t0) - t2 = Fp.mul(Y1, Z1) // step 25 - t2 = Fp.add(t2, t2) - t0 = Fp.mul(t2, t3) - X3 = Fp.sub(X3, t0) - Z3 = Fp.mul(t2, t1) - Z3 = Fp.add(Z3, Z3) // step 30 - Z3 = Fp.add(Z3, Z3) - return new Point(X3, Y3, Z3) - } - - // Renes-Costello-Batina exception-free addition formula. - // There is 30% faster Jacobian formula, but it is not complete. - // https://eprint.iacr.org/2015/1060, algorithm 1 - // Cost: 12M + 0S + 3*a + 3*b3 + 23add. - add(other: Point): Point { - aprjpoint(other) - const { px: X1, py: Y1, pz: Z1 } = this - const { px: X2, py: Y2, pz: Z2 } = other - let X3 = Fp.ZERO, - Y3 = Fp.ZERO, - Z3 = Fp.ZERO // prettier-ignore - const a = CURVE.a - const b3 = Fp.mul(CURVE.b, _3n) - let t0 = Fp.mul(X1, X2) // step 1 - let t1 = Fp.mul(Y1, Y2) - let t2 = Fp.mul(Z1, Z2) - let t3 = Fp.add(X1, Y1) - let t4 = Fp.add(X2, Y2) // step 5 - t3 = Fp.mul(t3, t4) - t4 = Fp.add(t0, t1) - t3 = Fp.sub(t3, t4) - t4 = Fp.add(X1, Z1) - let t5 = Fp.add(X2, Z2) // step 10 - t4 = Fp.mul(t4, t5) - t5 = Fp.add(t0, t2) - t4 = Fp.sub(t4, t5) - t5 = Fp.add(Y1, Z1) - X3 = Fp.add(Y2, Z2) // step 15 - t5 = Fp.mul(t5, X3) - X3 = Fp.add(t1, t2) - t5 = Fp.sub(t5, X3) - Z3 = Fp.mul(a, t4) - X3 = Fp.mul(b3, t2) // step 20 - Z3 = Fp.add(X3, Z3) - X3 = Fp.sub(t1, Z3) - Z3 = Fp.add(t1, Z3) - Y3 = Fp.mul(X3, Z3) - t1 = Fp.add(t0, t0) // step 25 - t1 = Fp.add(t1, t0) - t2 = Fp.mul(a, t2) - t4 = Fp.mul(b3, t4) - t1 = Fp.add(t1, t2) - t2 = Fp.sub(t0, t2) // step 30 - t2 = Fp.mul(a, t2) - t4 = Fp.add(t4, t2) - t0 = Fp.mul(t1, t4) - Y3 = Fp.add(Y3, t0) - t0 = Fp.mul(t5, t4) // step 35 - X3 = Fp.mul(t3, X3) - X3 = Fp.sub(X3, t0) - t0 = Fp.mul(t3, t1) - Z3 = Fp.mul(t5, Z3) - Z3 = Fp.add(Z3, t0) // step 40 - return new Point(X3, Y3, Z3) - } - - subtract(other: Point) { - return this.add(other.negate()) - } - - is0() { - return this.equals(Point.ZERO) - } - - private wNAF(n: bigint): { p: Point; f: Point } { - return wnaf.wNAFCached(this, n, Point.normalizeZ) - } - - /** - * Non-constant-time multiplication. Uses double-and-add algorithm. - * It's faster, but should only be used when you don't care about - * an exposed private key e.g. sig verification, which works over *public* keys. - */ - multiplyUnsafe(sc: bigint): Point { - const { endo, n: N } = CURVE - aInRange('scalar', sc, _0n, N) - const I = Point.ZERO - if (sc === _0n) return I - if (this.is0() || sc === _1n) return this - - // Case a: no endomorphism. Case b: has precomputes. - if (!endo || wnaf.hasPrecomputes(this)) - return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) - - // Case c: endomorphism - let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) - let k1p = I - let k2p = I - let d: Point = this - while (k1 > _0n || k2 > _0n) { - if (k1 & _1n) k1p = k1p.add(d) - if (k2 & _1n) k2p = k2p.add(d) - d = d.double() - k1 >>= _1n - k2 >>= _1n - } - if (k1neg) k1p = k1p.negate() - if (k2neg) k2p = k2p.negate() - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - return k1p.add(k2p) - } - - /** - * Constant time multiplication. - * Uses wNAF method. Windowed method may be 10% faster, - * but takes 2x longer to generate and consumes 2x memory. - * Uses precomputes when available. - * Uses endomorphism for Koblitz curves. - * @param scalar by which the point would be multiplied - * @returns New point - */ - multiply(scalar: bigint): Point { - const { endo, n: N } = CURVE - aInRange('scalar', scalar, _1n, N) - let point: Point, fake: Point // Fake point is used to const-time mult - if (endo) { - const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) - let { p: k1p, f: f1p } = this.wNAF(k1) - let { p: k2p, f: f2p } = this.wNAF(k2) - k1p = wnaf.constTimeNegate(k1neg, k1p) - k2p = wnaf.constTimeNegate(k2neg, k2p) - k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) - point = k1p.add(k2p) - fake = f1p.add(f2p) - } else { - const { p, f } = this.wNAF(scalar) - point = p - fake = f - } - // Normalize `z` for both points, but return only real one - return Point.normalizeZ([point, fake])[0] - } - - /** - * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. - * Not using Strauss-Shamir trick: precomputation tables are faster. - * The trick could be useful if both P and Q are not G (not in our case). - * @returns non-zero affine point - */ - multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { - const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes - const mul = ( - P: Point, - a: bigint, // Select faster multiply() method - ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) - const sum = mul(this, a).add(mul(Q, b)) - return sum.is0() ? undefined : sum - } - - // Converts Projective point to affine (x, y) coordinates. - // Can accept precomputed Z^-1 - for example, from invertBatch. - // (x, y, z) ∋ (x=x/z, y=y/z) - toAffine(iz?: T): AffinePoint { - return toAffineMemo(this, iz) - } - isTorsionFree(): boolean { - const { h: cofactor, isTorsionFree } = CURVE - if (cofactor === _1n) return true // No subgroups, always torsion-free - if (isTorsionFree) return isTorsionFree(Point, this) - throw new Error('isTorsionFree() has not been declared for the elliptic curve') - } - clearCofactor(): Point { - const { h: cofactor, clearCofactor } = CURVE - if (cofactor === _1n) return this // Fast-path - if (clearCofactor) return clearCofactor(Point, this) as Point - return this.multiplyUnsafe(CURVE.h) - } - - toRawBytes(isCompressed = true): Uint8Array { - abool('isCompressed', isCompressed) - this.assertValidity() - return toBytes(Point, this, isCompressed) - } - - toHex(isCompressed = true): string { - abool('isCompressed', isCompressed) - return bytesToHex(this.toRawBytes(isCompressed)) - } - } - const _bits = CURVE.nBitLength - const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) - // Validate if generator point is on curve - return { - CURVE, - ProjectivePoint: Point as ProjConstructor, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } -} - -// Instance -export interface SignatureType { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - assertValidity(): void - addRecoveryBit(recovery: number): RecoveredSignatureType - hasHighS(): boolean - normalizeS(): SignatureType - recoverPublicKey(msgHash: Hex): ProjPointType - toCompactRawBytes(): Uint8Array - toCompactHex(): string - toDERRawBytes(isCompressed?: boolean): Uint8Array - toDERHex(isCompressed?: boolean): string -} -export type RecoveredSignatureType = SignatureType & { - readonly recovery: number -} -// Static methods -export type SignatureConstructor = { - new (r: bigint, s: bigint): SignatureType - fromCompact(hex: Hex): SignatureType - fromDER(hex: Hex): SignatureType -} -type SignatureLike = { r: bigint; s: bigint } - -export type PubKey = Hex | ProjPointType - -export type CurveType = BasicWCurve & { - hash: CHash // CHash not FHash because we need outputLen for DRBG - hmac: HmacFnSync - randomBytes: (bytesLength?: number) => Uint8Array - lowS?: boolean - bits2int?: (bytes: Uint8Array) => bigint - bits2int_modN?: (bytes: Uint8Array) => bigint -} - -function validateOpts( - curve: CurveType, -): Readonly { - const opts = validateBasic(curve) - validateObject( - opts, - { - hash: 'hash', - hmac: 'function', - randomBytes: 'function', - }, - { - bits2int: 'function', - bits2int_modN: 'function', - lowS: 'boolean', - }, - ) - return Object.freeze({ lowS: true, ...opts } as const) -} - -export type CurveFn = { - CURVE: ReturnType - getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array - getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array - sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType - verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean - ProjectivePoint: ProjConstructor - Signature: SignatureConstructor - utils: { - normPrivateKeyToScalar: (key: PrivKey) => bigint - isValidPrivateKey(privateKey: PrivKey): boolean - randomPrivateKey: () => Uint8Array - precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType - } -} - -/** - * Creates short weierstrass curve and ECDSA signature methods for it. - * @example - * import { Field } from '@noble/curves/abstract/modular'; - * // Before that, define BigInt-s: a, b, p, n, Gx, Gy - * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) - */ -export function weierstrass(curveDef: CurveType): CurveFn { - const CURVE = validateOpts(curveDef) as ReturnType - const { Fp, n: CURVE_ORDER } = CURVE - const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 - const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 - - function modN(a: bigint) { - return mod(a, CURVE_ORDER) - } - function invN(a: bigint) { - return invert(a, CURVE_ORDER) - } - - const { - ProjectivePoint: Point, - normPrivateKeyToScalar, - weierstrassEquation, - isWithinCurveOrder, - } = weierstrassPoints({ - ...CURVE, - toBytes(_c, point, isCompressed: boolean): Uint8Array { - const a = point.toAffine() - const x = Fp.toBytes(a.x) - const cat = concatBytes - abool('isCompressed', isCompressed) - if (isCompressed) { - return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) - } else { - return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) - } - }, - fromBytes(bytes: Uint8Array) { - const len = bytes.length - const head = bytes[0] - const tail = bytes.subarray(1) - // this.assertValidity() is done inside of fromHex - if (len === compressedLen && (head === 0x02 || head === 0x03)) { - const x = bytesToNumberBE(tail) - if (!inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') - const y2 = weierstrassEquation(x) // y² = x³ + ax + b - let y: bigint - try { - y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 - } catch (sqrtError) { - const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' - throw new Error('Point is not on curve' + suffix) - } - const isYOdd = (y & _1n) === _1n - // ECDSA - const isHeadOdd = (head & 1) === 1 - if (isHeadOdd !== isYOdd) y = Fp.neg(y) - return { x, y } - } else if (len === uncompressedLen && head === 0x04) { - const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) - const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) - return { x, y } - } else { - const cl = compressedLen - const ul = uncompressedLen - throw new Error( - 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, - ) - } - }, - }) - const numToNByteHex = (num: bigint): string => bytesToHex(numberToBytesBE(num, CURVE.nByteLength)) - - function isBiggerThanHalfOrder(number: bigint) { - const HALF = CURVE_ORDER >> _1n - return number > HALF - } - - function normalizeS(s: bigint) { - return isBiggerThanHalfOrder(s) ? modN(-s) : s - } - // slice bytes num - const slcNum = (b: Uint8Array, from: number, to: number) => bytesToNumberBE(b.slice(from, to)) - - /** - * ECDSA signature with its (r, s) properties. Supports DER & compact representations. - */ - class Signature implements SignatureType { - readonly r: bigint - readonly s: bigint - readonly recovery?: number - constructor(r: bigint, s: bigint, recovery?: number) { - aInRange('r', r, _1n, CURVE_ORDER) // r in [1..N] - aInRange('s', s, _1n, CURVE_ORDER) // s in [1..N] - this.r = r - this.s = s - if (recovery != null) this.recovery = recovery - Object.freeze(this) - } - - // pair (bytes of r, bytes of s) - static fromCompact(hex: Hex) { - const l = CURVE.nByteLength - hex = ensureBytes('compactSignature', hex, l * 2) - return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) - } - - // DER encoded ECDSA signature - // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script - static fromDER(hex: Hex) { - const { r, s } = DER.toSig(ensureBytes('DER', hex)) - return new Signature(r, s) - } - - /** - * @todo remove - * @deprecated - */ - assertValidity(): void {} - - addRecoveryBit(recovery: number): RecoveredSignature { - return new Signature(this.r, this.s, recovery) as RecoveredSignature - } - - recoverPublicKey(msgHash: Hex): typeof Point.BASE { - const { r, s, recovery: rec } = this - const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash - if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') - const radj = rec === 2 || rec === 3 ? r + CURVE.n : r - if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') - const prefix = (rec & 1) === 0 ? '02' : '03' - const R = Point.fromHex(prefix + numToNByteHex(radj)) - const ir = invN(radj) // r^-1 - const u1 = modN(-h * ir) // -hr^-1 - const u2 = modN(s * ir) // sr^-1 - const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) - if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked - Q.assertValidity() - return Q - } - - // Signatures should be low-s, to prevent malleability. - hasHighS(): boolean { - return isBiggerThanHalfOrder(this.s) - } - - normalizeS() { - return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this - } - - // DER-encoded - toDERRawBytes() { - return hexToBytes(this.toDERHex()) - } - toDERHex() { - return DER.hexFromSig({ r: this.r, s: this.s }) - } - - // padded bytes of r, then padded bytes of s - toCompactRawBytes() { - return hexToBytes(this.toCompactHex()) - } - toCompactHex() { - return numToNByteHex(this.r) + numToNByteHex(this.s) - } - } - type RecoveredSignature = Signature & { recovery: number } - - const utils = { - isValidPrivateKey(privateKey: PrivKey) { - try { - normPrivateKeyToScalar(privateKey) - return true - } catch (error) { - return false - } - }, - normPrivateKeyToScalar: normPrivateKeyToScalar, - - /** - * Produces cryptographically secure private key from random of size - * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. - */ - randomPrivateKey: (): Uint8Array => { - const length = getMinHashLength(CURVE.n) - return mapHashToField(CURVE.randomBytes(length), CURVE.n) - }, - - /** - * Creates precompute table for an arbitrary EC point. Makes point "cached". - * Allows to massively speed-up `point.multiply(scalar)`. - * @returns cached point - * @example - * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); - * fast.multiply(privKey); // much faster ECDH now - */ - precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE { - point._setWindowSize(windowSize) - point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here - return point - }, - } - - /** - * Computes public key for a private key. Checks for validity of the private key. - * @param privateKey private key - * @param isCompressed whether to return compact (default), or full key - * @returns Public key, full when isCompressed=false; short when isCompressed=true - */ - function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array { - return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) - } - - /** - * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. - */ - function isProbPub(item: PrivKey | PubKey): boolean { - const arr = isBytes(item) - const str = typeof item === 'string' - const len = (arr || str) && (item as Hex).length - if (arr) return len === compressedLen || len === uncompressedLen - if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen - if (item instanceof Point) return true - return false - } - - /** - * ECDH (Elliptic Curve Diffie Hellman). - * Computes shared public key from private key and public key. - * Checks: 1) private key validity 2) shared key is on-curve. - * Does NOT hash the result. - * @param privateA private key - * @param publicB different public key - * @param isCompressed whether to return compact (default), or full key - * @returns shared public key - */ - function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array { - if (isProbPub(privateA)) throw new Error('first arg must be private key') - if (!isProbPub(publicB)) throw new Error('second arg must be public key') - const b = Point.fromHex(publicB) // check for being on-curve - return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) - } - - // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. - // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. - // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. - // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors - const bits2int = - CURVE.bits2int || - function (bytes: Uint8Array): bigint { - // Our custom check "just in case" - if (bytes.length > 8192) throw new Error('input is too large') - // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) - // for some cases, since bytes.length * 8 is not actual bitLength. - const num = bytesToNumberBE(bytes) // check for == u8 done here - const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits - return delta > 0 ? num >> BigInt(delta) : num - } - const bits2int_modN = - CURVE.bits2int_modN || - function (bytes: Uint8Array): bigint { - return modN(bits2int(bytes)) // can't use bytesToNumberBE here - } - // NOTE: pads output with zero as per spec - const ORDER_MASK = bitMask(CURVE.nBitLength) - /** - * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. - */ - function int2octets(num: bigint): Uint8Array { - aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) - // works with order, can have different size than numToField! - return numberToBytesBE(num, CURVE.nByteLength) - } - - // Steps A, D of RFC6979 3.2 - // Creates RFC6979 seed; converts msg/privKey to numbers. - // Used only in sign, not in verify. - // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, - // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 - function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) { - if (['recovered', 'canonical'].some((k) => k in opts)) - throw new Error('sign() legacy options not supported') - const { hash, randomBytes } = CURVE - let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default - if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash - msgHash = ensureBytes('msgHash', msgHash) - validateSigVerOpts(opts) - if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) - - // We can't later call bits2octets, since nested bits2int is broken for curves - // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. - // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) - const h1int = bits2int_modN(msgHash) - const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint - const seedArgs = [int2octets(d), int2octets(h1int)] - // extraEntropy. RFC6979 3.6: additional k' (optional). - if (ent != null && ent !== false) { - // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') - const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is - seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes - } - const seed = concatBytes(...seedArgs) // Step D of RFC6979 3.2 - const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! - // Converts signature params into point w r/s, checks result for validity. - function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined { - // RFC 6979 Section 3.2, step 3: k = bits2int(T) - const k = bits2int(kBytes) // Cannot use fields methods, since it is group element - if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N - const ik = invN(k) // k^-1 mod n - const q = Point.BASE.multiply(k).toAffine() // q = Gk - const r = modN(q.x) // r = q.x mod n - if (r === _0n) return - // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to - // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: - // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT - const s = modN(ik * modN(m + r * d)) // Not using blinding here - if (s === _0n) return - let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) - let normS = s - if (lowS && isBiggerThanHalfOrder(s)) { - normS = normalizeS(s) // if lowS was passed, ensure s is always - recovery ^= 1 // // in the bottom half of N - } - return new Signature(r, normS, recovery) as RecoveredSignature // use normS, not s - } - return { seed, k2sig } - } - const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false } - const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false } - - /** - * Signs message hash with a private key. - * ``` - * sign(m, d, k) where - * (x, y) = G × k - * r = x mod n - * s = (m + dr)/k mod n - * ``` - * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. - * @param privKey private key - * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. - * @returns signature with recovery param - */ - function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature { - const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. - const C = CURVE - const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) - return drbg(seed, k2sig) // Steps B, C, D, E, F, G - } - - // Enable precomputes. Slows down first publicKey computation by 20ms. - Point.BASE._setWindowSize(8) - // utils.precompute(8, ProjectivePoint.BASE) - - /** - * Verifies a signature against message hash and public key. - * Rejects lowS signatures by default: to override, - * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: - * - * ``` - * verify(r, s, h, P) where - * U1 = hs^-1 mod n - * U2 = rs^-1 mod n - * R = U1⋅G - U2⋅P - * mod(R.x, n) == r - * ``` - */ - function verify( - signature: Hex | SignatureLike, - msgHash: Hex, - publicKey: Hex, - opts = defaultVerOpts, - ): boolean { - const sg = signature - msgHash = ensureBytes('msgHash', msgHash) - publicKey = ensureBytes('publicKey', publicKey) - const { lowS, prehash, format } = opts - - // Verify opts, deduce signature format - validateSigVerOpts(opts) - if ('strict' in opts) throw new Error('options.strict was renamed to lowS') - if (format !== undefined && format !== 'compact' && format !== 'der') - throw new Error('format must be compact or der') - const isHex = typeof sg === 'string' || isBytes(sg) - const isObj = - !isHex && - !format && - typeof sg === 'object' && - sg !== null && - typeof sg.r === 'bigint' && - typeof sg.s === 'bigint' - if (!isHex && !isObj) - throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') - - let _sig: Signature | undefined = undefined - let P: ProjPointType - try { - if (isObj) _sig = new Signature(sg.r, sg.s) - if (isHex) { - // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). - // Since DER can also be 2*nByteLength bytes, we check for it first. - try { - if (format !== 'compact') _sig = Signature.fromDER(sg) - } catch (derError) { - if (!(derError instanceof DER.Err)) throw derError - } - if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) - } - P = Point.fromHex(publicKey) - } catch (error) { - return false - } - if (!_sig) return false - if (lowS && _sig.hasHighS()) return false - if (prehash) msgHash = CURVE.hash(msgHash) - const { r, s } = _sig - const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element - const is = invN(s) // s^-1 - const u1 = modN(h * is) // u1 = hs^-1 mod n - const u2 = modN(r * is) // u2 = rs^-1 mod n - const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P - if (!R) return false - const v = modN(R.x) - return v === r - } - return { - CURVE, - getPublicKey, - getSharedSecret, - sign, - verify, - ProjectivePoint: Point, - Signature, - utils, - } -} - -/** - * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. - * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. - * b = True and y = sqrt(u / v) if (u / v) is square in F, and - * b = False and y = sqrt(Z * (u / v)) otherwise. - * @param Fp - * @param Z - * @returns - */ -export function SWUFpSqrtRatio( - Fp: IField, - Z: T, -): (u: T, v: T) => { isValid: boolean; value: T } { - // Generic implementation - const q = Fp.ORDER - let l = _0n - for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n - const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. - // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. - // 2n ** c1 == 2n << (c1-1) - const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) - const _2n_pow_c1 = _2n_pow_c1_1 * _2n - const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic - const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic - const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic - const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic - const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 - const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) - let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { - let tv1 = c6 // 1. tv1 = c6 - let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 - let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 - tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v - let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 - tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 - tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 - tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v - tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u - let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 - tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 - let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 - tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 - tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) - tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) - // 17. for i in (c1, c1 - 1, ..., 2): - for (let i = c1; i > _1n; i--) { - let tv5 = i - _2n // 18. tv5 = i - 2 - tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 - let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 - const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 - tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 - tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 - tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 - tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) - tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) - } - return { isValid: isQR, value: tv3 } - } - if (Fp.ORDER % _4n === _3n) { - // sqrt_ratio_3mod4(u, v) - const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic - const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) - sqrtRatio = (u: T, v: T) => { - let tv1 = Fp.sqr(v) // 1. tv1 = v^2 - const tv2 = Fp.mul(u, v) // 2. tv2 = u * v - tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 - let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 - y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 - const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 - const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v - const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u - let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) - return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 - } - } - // No curves uses that - // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 - return sqrtRatio -} -/** - * Simplified Shallue-van de Woestijne-Ulas Method - * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 - */ -export function mapToCurveSimpleSWU( - Fp: IField, - opts: { - A: T - B: T - Z: T - }, -): (u: T) => { x: T; y: T } { - validateField(Fp) - if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) - throw new Error('mapToCurveSimpleSWU: invalid opts') - const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) - if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') - // Input: u, an element of F. - // Output: (x, y), a point on E. - return (u: T): { x: T; y: T } => { - // prettier-ignore - let tv1, tv2, tv3, tv4, tv5, tv6, x, y - tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 - tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 - tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 - tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 - tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 - tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) - tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 - tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 - tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 - tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 - tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 - tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 - tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 - tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 - tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 - x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 - const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) - y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 - y = Fp.mul(y, value) // 20. y = y * y1 - x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) - y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) - const e1 = Fp.isOdd!(u) === Fp.isOdd!(y) // 23. e1 = sgn0(u) == sgn0(y) - y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) - x = Fp.div(x, tv4) // 25. x = x / tv4 - return { x, y } - } -} diff --git a/packages/noble-curves-tmp/src/bls12-381.ts b/packages/noble-curves-tmp/src/bls12-381.ts deleted file mode 100644 index 5c0232a8ec4..00000000000 --- a/packages/noble-curves-tmp/src/bls12-381.ts +++ /dev/null @@ -1,774 +0,0 @@ -/** - * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: - * * Construct zk-SNARKs at the ~120-bit security - * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: - * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr - * - * ### Summary - * 1. BLS Relies on Bilinear Pairing (expensive) - * 2. Private Keys: 32 bytes - * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. - * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. - * - The signature is a point on the G2 subgroup, which is defined over a finite field - * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the - * complex numbers). - * - We also support reversed 96-byte pubkeys & 48-byte short signatures. - * 5. The 12 stands for the Embedding degree. - * - * ### Formulas - * - `P = pk x G` - public keys - * - `S = pk x H(m)` - signing - * - `e(P, H(m)) == e(G, S)` - verification using pairings - * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation - * - * ### Compatibility and notes - * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. - * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. - * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". - * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) - * 4. Compatible with specs: - * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), - * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), - * RFC 9380. - * - * ### Params - * To verify curve parameters, see - * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). - * Basic math is done over finite fields over p. - * More complicated math is done over polynominal extension fields. - * To simplify calculations in Fp12, we construct extension tower: - * - * Embedding degree (k): 12 - * Seed (X): -15132376222941642752 - * Fr: (x⁴-x²+1) - * Fp: ((x-1)² ⋅ r(x)/3+x) - * (E/Fp): Y²=X³+4 - * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) - * Ate loop size: X - * - * ### Towers - * - Fp₁₂ = Fp₆² => Fp₂³ - * - Fp(u) / (u² - β) where β = -1 - * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 - * - Fp₆(w) / (w² - γ) where γ = v - * - Fp²[u] = Fp/u²+1 - * - Fp⁶[v] = Fp²/v³-1-u - * - Fp¹²[w] = Fp⁶/w²-v - * - * @todo construct bls & bn fp/fr from seed. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha2' -import { randomBytes } from '@noble/hashes/utils' -import { type CurveFn, bls } from './abstract/bls.ts' -// Types -import { isogenyMap } from './abstract/hash-to-curve.ts' -import { Field } from './abstract/modular.ts' -import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' -import { psiFrobenius, tower12 } from './abstract/tower.ts' -import { - type Hex, - bitGet, - bitLen, - bytesToHex, - bytesToNumberBE, - concatBytes as concatB, - ensureBytes, - numberToBytesBE, -} from './abstract/utils.ts' -import { - type AffinePoint, - type ProjPointType, - mapToCurveSimpleSWU, -} from './abstract/weierstrass.ts' - -// Be friendly to bad ECMAScript parsers by not using bigint literals -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4) - -// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! -const BLS_X = BigInt('0xd201000000010000') -const BLS_X_LEN = bitLen(BLS_X) - -// CURVE FIELDS -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - // Order of Fp - ORDER: BigInt( - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', - ), - // Finite extension field over irreducible polynominal. - // Fp(u) / (u² - β) where β = -1 - FP2_NONRESIDUE: [_1n, _1n], - Fp2mulByB: ({ c0, c1 }) => { - const t0 = Fp.mul(c0, _4n) // 4 * c0 - const t1 = Fp.mul(c1, _4n) // 4 * c1 - // (T0-T1) + (T0+T1)*i - return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } - }, - // Fp12 - // A cyclotomic group is a subgroup of Fp^n defined by - // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BLS_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const x = BLS_X - // this^(q⁶) / this - const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) - // t0^(q²) * t0 - const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) - const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) - const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) - const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) - const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) - const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) - const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) - const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) - const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) - const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) - const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) - // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 - return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) - }, -}) - -// Finite field over r. -// This particular field is not used anywhere in bls12-381, but it is still useful. -const Fr = Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) - -// END OF CURVE FIELDS - -// HashToCurve - -// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 -const isogenyMapG2 = isogenyMap( - Fp2, - [ - // xNum - [ - [ - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', - ], - [ - '0x0', - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', - ], - [ - '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', - '0x0', - ], - ], - // xDen - [ - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', - ], - [ - '0xc', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', - ], - ['0x1', '0x0'], // LAST 1 - ], - // yNum - [ - [ - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', - ], - [ - '0x0', - '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', - ], - [ - '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', - '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', - ], - [ - '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', - '0x0', - ], - ], - // yDen - [ - [ - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', - ], - [ - '0x0', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', - ], - [ - '0x12', - '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', - ], - ['0x1', '0x0'], // LAST 1 - ], - ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))) as [Fp2[], Fp2[], Fp2[], Fp2[]], -) -// 11-isogeny map from E' to E -const isogenyMapG1 = isogenyMap( - Fp, - [ - // xNum - [ - '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', - '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', - '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', - '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', - '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', - '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', - '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', - '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', - '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', - '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', - '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', - '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', - ], - // xDen - [ - '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', - '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', - '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', - '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', - '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', - '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', - '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', - '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', - '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', - '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', - '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', - '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', - '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', - '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', - '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', - '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', - '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', - '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', - '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', - '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', - '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', - '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', - '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', - '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', - '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', - ], - // yDen - [ - '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', - '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', - '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', - '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', - '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', - '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', - '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', - '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', - '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', - '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', - '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', - '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', - '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', - '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', - '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]], -) - -// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i -const G2_SWU = mapToCurveSimpleSWU(Fp2, { - A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I - B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) - Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) -}) -// Optimized SWU Map - Fp to G1 -const G1_SWU = mapToCurveSimpleSWU(Fp, { - A: Fp.create( - BigInt( - '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', - ), - ), - B: Fp.create( - BigInt( - '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', - ), - ), - Z: Fp.create(BigInt(11)), -}) - -// Endomorphisms (for fast cofactor clearing) -// Ψ(P) endomorphism -const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) - -// Default hash_to_field options are for hash to G2. -// -// Parameter definitions are in section 5.3 of the spec unless otherwise noted. -// Parameter values come from section 8.8.2 of the spec. -// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 -// -// Base field F is GF(p^m) -// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab -// m = 2 (or 1 for G1 see section 8.8.1) -// k = 128 -const htfDefaults = Object.freeze({ - // DST: a domain separation tag - // defined in section 2.2.5 - // Use utils.getDSTLabel(), utils.setDSTLabel(value) - DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', - // p: the characteristic of F - // where F is a finite field of characteristic p and order q = p^m - p: Fp.ORDER, - // m: the extension degree of F, m >= 1 - // where F is a finite field of characteristic p and order q = p^m - m: 2, - // k: the target security level for the suite in bits - // defined in section 5.1 - k: 128, - // option to use a message that has already been processed by - // expand_message_xmd - expand: 'xmd', - // Hash functions for: expand_message_xmd is appropriate for use with a - // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. - // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 - hash: sha256, -} as const) - -// Encoding utils -// Point on G1 curve: (x, y) - -// Compressed point of infinity -const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits - -function parseMask(bytes: Uint8Array) { - // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. - bytes = bytes.slice() - const mask = bytes[0] & 0b1110_0000 - const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) - const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) - const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) - bytes[0] &= 0b0001_1111 // clear mask (zero first 3 bits) - return { compressed, infinity, sort, value: bytes } -} - -function setMask( - bytes: Uint8Array, - mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }, -) { - if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask') - if (mask.compressed) bytes[0] |= 0b1000_0000 - if (mask.infinity) bytes[0] |= 0b0100_0000 - if (mask.sort) bytes[0] |= 0b0010_0000 - return bytes -} - -function signatureG1ToRawBytes(point: ProjPointType) { - point.assertValidity() - const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) - const { x, y } = point.toAffine() - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) -} - -function signatureG2ToRawBytes(point: ProjPointType) { - // NOTE: by some reasons it was missed in bls12-381, looks like bug - point.assertValidity() - const len = Fp.BYTES - if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) - return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const { x, y } = point.toAffine() - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - const tmp = y1 > _0n ? y1 * _2n : y0 * _2n - const sort = Boolean((tmp / Fp.ORDER) & _1n) - const z2 = x0 - return concatB( - setMask(numberToBytesBE(x1, len), { sort, compressed: true }), - numberToBytesBE(z2, len), - ) -} - -/** - * bls12-381 pairing-friendly curve. - * @example - * import { bls12_381 as bls } from '@noble/curves/bls12-381'; - * // G1 keys, G2 signatures - * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; - * const message = '64726e3da8'; - * const publicKey = bls.getPublicKey(privateKey); - * const signature = bls.sign(message, privateKey); - * const isValid = bls.verify(signature, message, publicKey); - */ -export const bls12_381: CurveFn = bls({ - // Fields - fields: { - Fp, - Fp2, - Fp6, - Fp12, - Fr, - }, - // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where - // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 - G1: { - Fp, - // cofactor; (z - 1)²/3 - h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), - // generator's coordinates - // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 - // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 - Gx: BigInt( - '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', - ), - Gy: BigInt( - '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', - ), - a: Fp.ZERO, - b: _4n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, point): boolean => { - // φ endomorphism - const cubicRootOfUnityModP = BigInt( - '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', - ) - const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) - - // todo: unroll - const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P - const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P - return u2P.equals(phi) - - // https://eprint.iacr.org/2019/814.pdf - // (z² − 1)/3 - // const c1 = BigInt('0x396c8c005555e1560000000055555555'); - // const P = this; - // const S = P.sigma(); - // const Q = S.double(); - // const S2 = S.sigma(); - // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O - // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); - // const C = left.subtract(S2); - // return C.isZero(); - }, - // Clear cofactor of G1 - // https://eprint.iacr.org/2019/403 - clearCofactor: (_c, point) => { - // return this.multiplyUnsafe(CURVE.h); - return point.multiplyUnsafe(BLS_X).add(point) // x*P + P - }, - mapToCurve: (scalars: bigint[]) => { - const { x, y } = G1_SWU(Fp.create(scalars[0])) - return isogenyMapG1(x, y) - }, - fromBytes: (bytes: Uint8Array): AffinePoint => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if (value.length === 48 && compressed) { - // TODO: Fp.bytes - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - const x = Fp.create(compressedValue & Fp.MASK) - if (infinity) { - if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') - return { x: _0n, y: _0n } - } - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) - return { x: Fp.create(x), y: Fp.create(y) } - } else if (value.length === 96 && !compressed) { - // Check if the infinity flag is set - const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) - const y = bytesToNumberBE(value.subarray(Fp.BYTES)) - if (infinity) { - if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') - return bls12_381.G1.ProjectivePoint.ZERO.toAffine() - } - return { x: Fp.create(x), y: Fp.create(y) } - } else { - throw new Error('invalid point G1, expected 48/96 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return COMPRESSED_ZERO.slice() - const P = Fp.ORDER - const sort = Boolean((y * _2n) / P) - return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) - } else { - if (isZero) { - // 2x PUBLIC_KEY_LENGTH - const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) - return x - } else { - return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) - } - } - }, - ShortSignature: { - fromHex(hex: Hex): ProjPointType { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) - const P = Fp.ORDER - const compressedValue = bytesToNumberBE(value) - // Zero - if (infinity) return bls12_381.G1.ProjectivePoint.ZERO - const x = Fp.create(compressedValue & Fp.MASK) - const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b - let y = Fp.sqrt(right) - if (!y) throw new Error('invalid compressed G1 point') - const aflag = BigInt(sort) - if ((y * _2n) / P !== aflag) y = Fp.neg(y) - const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point: ProjPointType) { - return signatureG1ToRawBytes(point) - }, - toHex(point: ProjPointType) { - return bytesToHex(signatureG1ToRawBytes(point)) - }, - }, - }, - // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), - // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where - // G² - 1 - // h2q - G2: { - Fp: Fp2, - // cofactor - h: BigInt( - '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', - ), - Gx: Fp2.fromBigTuple([ - BigInt( - '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', - ), - BigInt( - '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', - ), - ]), - // y = - // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, - // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 - Gy: Fp2.fromBigTuple([ - BigInt( - '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', - ), - BigInt( - '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', - ), - ]), - a: Fp2.ZERO, - b: Fp2.fromBigTuple([_4n, _4n]), - hEff: BigInt( - '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', - ), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: (scalars: bigint[]) => { - const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) - return isogenyMapG2(x, y) - }, - // Checks is the point resides in prime-order subgroup. - // point.isTorsionFree() should return true for valid points - // It returns false for shitty points. - // https://eprint.iacr.org/2021/1130.pdf - isTorsionFree: (c, P): boolean => { - return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) - // Older version: https://eprint.iacr.org/2019/814.pdf - // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O - // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); - }, - // Maps the point into the prime-order subgroup G2. - // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 - // https://eprint.iacr.org/2017/419.pdf - // prettier-ignore - clearCofactor: (c, P) => { - const x = BLS_X - let t1 = P.multiplyUnsafe(x).negate() // [-x]P - let t2 = G2psi(c, P) // Ψ(P) - let t3 = P.double() // 2P - t3 = G2psi2(c, t3) // Ψ²(2P) - t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) - t2 = t1.add(t2) // [-x]P + Ψ(P) - t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) - t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) - t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P - return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) - }, - fromBytes: (bytes: Uint8Array): AffinePoint => { - const { compressed, infinity, sort, value } = parseMask(bytes) - if ( - (!compressed && !infinity && sort) || // 00100000 - (!compressed && infinity && sort) || // 01100000 - (sort && infinity && compressed) // 11100000 - ) { - throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000)) - } - const L = Fp.BYTES - const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to)) - if (value.length === 96 && compressed) { - const b = bls12_381.params.G2b - const P = Fp.ORDER - if (infinity) { - // check that all bytes are 0 - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid compressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x_1 = slc(value, 0, L) - const x_0 = slc(value, L, 2 * L) - const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) - const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b - let y = Fp2.sqrt(right) - const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n - y = sort && Y_bit > 0 ? y : Fp2.neg(y) - return { x, y } - } else if (value.length === 192 && !compressed) { - if (infinity) { - if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { - throw new Error('invalid uncompressed G2 point') - } - return { x: Fp2.ZERO, y: Fp2.ZERO } - } - const x1 = slc(value, 0, L) - const x0 = slc(value, L, 2 * L) - const y1 = slc(value, 2 * L, 3 * L) - const y0 = slc(value, 3 * L, 4 * L) - return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } - } else { - throw new Error('invalid point G2, expected 96/192 bytes') - } - }, - toBytes: (c, point, isCompressed) => { - const { BYTES: len, ORDER: P } = Fp - const isZero = point.equals(c.ZERO) - const { x, y } = point.toAffine() - if (isCompressed) { - if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) - const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) - return concatB( - setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), - numberToBytesBE(x.c0, len), - ) - } else { - if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; - const { re: x0, im: x1 } = Fp2.reim(x) - const { re: y0, im: y1 } = Fp2.reim(y) - return concatB( - numberToBytesBE(x1, len), - numberToBytesBE(x0, len), - numberToBytesBE(y1, len), - numberToBytesBE(y0, len), - ) - } - }, - Signature: { - // TODO: Optimize, it's very slow because of sqrt. - fromHex(hex: Hex): ProjPointType { - const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) - const P = Fp.ORDER - const half = value.length / 2 - if (half !== 48 && half !== 96) - throw new Error('invalid compressed signature length, must be 96 or 192') - const z1 = bytesToNumberBE(value.slice(0, half)) - const z2 = bytesToNumberBE(value.slice(half)) - // Indicates the infinity point - if (infinity) return bls12_381.G2.ProjectivePoint.ZERO - const x1 = Fp.create(z1 & Fp.MASK) - const x2 = Fp.create(z2) - const x = Fp2.create({ c0: x2, c1: x1 }) - const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 - // The slow part - let y = Fp2.sqrt(y2) - if (!y) throw new Error('Failed to find a square root') - - // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 - // If y1 happens to be zero, then use the bit of y0 - const { re: y0, im: y1 } = Fp2.reim(y) - const aflag1 = BigInt(sort) - const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 - const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 - if (isGreater || isZero) y = Fp2.neg(y) - const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) - point.assertValidity() - return point - }, - toRawBytes(point: ProjPointType) { - return signatureG2ToRawBytes(point) - }, - toHex(point: ProjPointType) { - return bytesToHex(signatureG2ToRawBytes(point)) - }, - }, - }, - params: { - ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 - r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves - xNegative: true, - twistType: 'multiplicative', - }, - htfDefaults, - hash: sha256, - randomBytes, -}) diff --git a/packages/noble-curves-tmp/src/bn254.ts b/packages/noble-curves-tmp/src/bn254.ts deleted file mode 100644 index f2ffdb887ac..00000000000 --- a/packages/noble-curves-tmp/src/bn254.ts +++ /dev/null @@ -1,255 +0,0 @@ -/** - * bn254, previously known as alt_bn_128, when it had 128-bit security. - -Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, -so the naming has been adjusted to its prime bit count: -https://hal.science/hal-01534101/file/main.pdf. -Compatible with EIP-196 and EIP-197. - -There are huge compatibility issues in the ecosystem: - -1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". -2. libff has bn128, but it's a different curve with different G2: - https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 -3. halo2curves bn256 is also incompatible and returns different outputs - -The goal of our implementation is to support "Ethereum" variant of the curve, -because it at least has specs: - -- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM -- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings -- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 -- The existing implementations are bad. Some are deprecated: - - https://github.com/paritytech/bn (old version) - - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) - - https://github.com/zcash-hackworks/bn - - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs -- Python implementations use different towers and produce different Fp12 outputs: - - https://github.com/ethereum/py_pairing - - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py -- Points are encoded differently in different implementations - -### Params -Seed (X): 4965661367192848881 -Fr: (36x⁴+36x³+18x²+6x+1) -Fp: (36x⁴+36x³+24x²+6x+1) -(E / Fp ): Y² = X³+3 -(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) -Ate loop size: 6x+2 - -### Towers -- Fp²[u] = Fp/u²+1 -- Fp⁶[v] = Fp²/v³-9-u -- Fp¹²[w] = Fp⁶/w²-v - - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha2' -import { randomBytes } from '@noble/hashes/utils' -import { getHash } from './_shortw_utils.ts' -import { - type CurveFn as BLSCurveFn, - type PostPrecomputeFn, - type PostPrecomputePointAddFn, - bls, -} from './abstract/bls.ts' -import { Field } from './abstract/modular.ts' -import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' -import { psiFrobenius, tower12 } from './abstract/tower.ts' -import { bitGet, bitLen, notImplemented } from './abstract/utils.ts' -import { type CurveFn, weierstrass } from './abstract/weierstrass.ts' -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -const _6n = BigInt(6) - -const BN_X = BigInt('4965661367192848881') -const BN_X_LEN = bitLen(BN_X) -const SIX_X_SQUARED = _6n * BN_X ** _2n - -// Finite field over r. It's for convenience and is not used in the code below. -const Fr = Field( - BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), -) -// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) -const Fp2B = { - c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), - c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), -} - -const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ - ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), - FP2_NONRESIDUE: [BigInt(9), _1n], - Fp2mulByB: (num) => Fp2.mul(num, Fp2B), - // The result of any pairing is in a cyclotomic subgroup - // https://eprint.iacr.org/2009/565.pdf - Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { - const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 - const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 - const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) - const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) - const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) - let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) - return { - c0: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 - c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 - c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), - }), // 2 * (T7 - c0c2) + T7 - c1: Fp6.create({ - c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 - c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 - c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), - }), - } // 2 * (T6 + c1c2) + T6 - }, - Fp12cyclotomicExp(num, n) { - let z = Fp12.ONE - for (let i = BN_X_LEN - 1; i >= 0; i--) { - z = Fp12._cyclotomicSquare(z) - if (bitGet(n, i)) z = Fp12.mul(z, num) - } - return z - }, - // https://eprint.iacr.org/2010/354.pdf - // https://eprint.iacr.org/2009/565.pdf - Fp12finalExponentiate: (num) => { - const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) - const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) - const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) - const y1 = Fp12._cyclotomicSquare(powMinusX(r)) - const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) - const y4 = powMinusX(y2) - const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) - const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) - const y9 = Fp12.mul(y8, y1) - return Fp12.mul( - Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), - Fp12.mul( - Fp12.frobeniusMap(y8, 2), - Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), - ), - ) - }, -}) - -// END OF CURVE FIELDS -const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) - -/* -No hashToCurve for now (and signatures): - -- RFC 9380 doesn't mention bn254 and doesn't provide test vectors -- Overall seems like nobody is using BLS signatures on top of bn254 -- Seems like it can utilize SVDW, which is not implemented yet -*/ -const htfDefaults = Object.freeze({ - // DST: a domain separation tag defined in section 2.2.5 - DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', - p: Fp.ORDER, - m: 2, - k: 128, - expand: 'xmd', - hash: sha256, -} as const) - -export const _postPrecompute: PostPrecomputeFn = ( - Rx: Fp2, - Ry: Fp2, - Rz: Fp2, - Qx: Fp2, - Qy: Fp2, - pointAdd: PostPrecomputePointAddFn, -) => { - const q = psi(Qx, Qy) - ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) - const q2 = psi(q[0], q[1]) - pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) -} - -/** - * bn254 (a.k.a. alt_bn128) pairing-friendly curve. - * Contains G1 / G2 operations and pairings. - */ -export const bn254: BLSCurveFn = bls({ - // Fields - fields: { Fp, Fp2, Fp6, Fp12, Fr }, - G1: { - Fp, - h: BigInt(1), - Gx: BigInt(1), - Gy: BigInt(2), - a: Fp.ZERO, - b: _3n, - htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, - wrapPrivateKey: true, - allowInfinityPoint: true, - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - ShortSignature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - G2: { - Fp: Fp2, - // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 - h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - Gx: Fp2.fromBigTuple([ - BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), - BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), - ]), - Gy: Fp2.fromBigTuple([ - BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), - BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), - ]), - a: Fp2.ZERO, - b: Fp2B, - hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), - htfDefaults: { ...htfDefaults }, - wrapPrivateKey: true, - allowInfinityPoint: true, - isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P - mapToCurve: notImplemented, - fromBytes: notImplemented, - toBytes: notImplemented, - Signature: { - fromHex: notImplemented, - toRawBytes: notImplemented, - toHex: notImplemented, - }, - }, - params: { - ateLoopSize: BN_X * _6n + _2n, - r: Fr.ORDER, - xNegative: false, - twistType: 'divisive', - }, - htfDefaults, - hash: sha256, - randomBytes, - - postPrecompute: _postPrecompute, -}) - -/** - * bn254 weierstrass curve with ECDSA. - * This is very rare and probably not used anywhere. - * Instead, you should use G1 / G2, defined above. - * @deprecated - */ -export const bn254_weierstrass: CurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(3), - Fp, - n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), - Gx: BigInt(1), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) diff --git a/packages/noble-curves-tmp/src/ed25519.ts b/packages/noble-curves-tmp/src/ed25519.ts deleted file mode 100644 index 138d05b2e04..00000000000 --- a/packages/noble-curves-tmp/src/ed25519.ts +++ /dev/null @@ -1,554 +0,0 @@ -/** - * ed25519 Twisted Edwards curve with following addons: - * - X25519 ECDH - * - Ristretto cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha512 } from '@noble/hashes/sha2' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { type AffinePoint, type Group, pippenger } from './abstract/curve.ts' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' -import { - type HTFMethod, - type Hasher, - createHasher, - expand_message_xmd, - type htfBasicOpts, -} from './abstract/hash-to-curve.ts' -import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.ts' -import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' -import { - type Hex, - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.ts' - -// 2n**255n - 19n -const ED25519_P = BigInt( - '57896044618658097711785492504343953926634992332820282019728792003956564819949', -) -// √(-1) aka √(a) aka 2^((p-1)/4) -// Fp.sqrt(Fp.neg(1)) -const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( - '19681161376707505956807079304988542015446066515923890162744021073123829784752', -) - -// prettier-ignore -const _0n = BigInt(0), - _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3) -// prettier-ignore -const _5n = BigInt(5), - _8n = BigInt(8) - -function ed25519_pow_2_252_3(x: bigint) { - // prettier-ignore - const _10n = BigInt(10), - _20n = BigInt(20), - _40n = BigInt(40), - _80n = BigInt(80) - const P = ED25519_P - const x2 = (x * x) % P - const b2 = (x2 * x) % P // x^3, 11 - const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 - const b5 = (pow2(b4, _1n, P) * x) % P // x^31 - const b10 = (pow2(b5, _5n, P) * b5) % P - const b20 = (pow2(b10, _10n, P) * b10) % P - const b40 = (pow2(b20, _20n, P) * b20) % P - const b80 = (pow2(b40, _40n, P) * b40) % P - const b160 = (pow2(b80, _80n, P) * b80) % P - const b240 = (pow2(b160, _80n, P) * b80) % P - const b250 = (pow2(b240, _10n, P) * b10) % P - const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P - // ^ To pow to (p+3)/8, multiply it by x. - return { pow_p_5_8, b2 } -} - -function adjustScalarBytes(bytes: Uint8Array): Uint8Array { - // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, - // set the three least significant bits of the first byte - bytes[0] &= 248 // 0b1111_1000 - // and the most significant bit of the last to zero, - bytes[31] &= 127 // 0b0111_1111 - // set the second most significant bit of the last byte to 1 - bytes[31] |= 64 // 0b0100_0000 - return bytes -} - -// sqrt(u/v) -function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { - const P = ED25519_P - const v3 = mod(v * v * v, P) // v³ - const v7 = mod(v3 * v3 * v, P) // v⁷ - // (p+3)/8 and (p-5)/8 - const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 - let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 - const vx2 = mod(v * x * x, P) // vx² - const root1 = x // First root candidate - const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate - const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root - const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) - const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) - if (useRoot1) x = root1 - if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time - if (isNegativeLE(x, P)) x = mod(-x, P) - return { isValid: useRoot1 || useRoot2, value: x } -} - -/** Weird / bogus points, useful for debugging. */ -export const ED25519_TORSION_SUBGROUP: string[] = [ - '0100000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', - '0000000000000000000000000000000000000000000000000000000000000080', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', - 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', - '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', - '0000000000000000000000000000000000000000000000000000000000000000', - 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', -] - -const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() - -const ed25519Defaults = /* @__PURE__ */ (() => - ({ - // Removing Fp.create() will still work, and is 10% faster on sign - a: Fp.create(BigInt(-1)), - // d is -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666)) - d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), - // Finite field 2n**255n - 19n - Fp, - // Subgroup order 2n**252n + 27742317777372353535851937790883648493n; - n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), - h: _8n, - Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), - Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), - hash: sha512, - randomBytes, - adjustScalarBytes, - // dom2 - // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. - // Constant-time, u/√v - uvRatio, - }) as const)() - -/** - * ed25519 curve with EdDSA signatures. - * @example - * import { ed25519 } from '@noble/curves/ed25519'; - * const priv = ed25519.utils.randomPrivateKey(); - * const pub = ed25519.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = ed25519.sign(msg, priv); - * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 - * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 - */ -export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() - -function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) { - if (ctx.length > 255) throw new Error('Context is too big') - return concatBytes( - utf8ToBytes('SigEd25519 no Ed25519 collisions'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) -} - -export const ed25519ctx: CurveFn = /* @__PURE__ */ (() => - twistedEdwards({ - ...ed25519Defaults, - domain: ed25519_domain, - }))() -export const ed25519ph: CurveFn = /* @__PURE__ */ (() => - twistedEdwards( - Object.assign({}, ed25519Defaults, { - domain: ed25519_domain, - prehash: sha512, - }), - ))() - -/** - * ECDH using curve25519 aka x25519. - * @example - * import { x25519 } from '@noble/curves/ed25519'; - * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; - * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; - * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases - * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); - * x25519.getPublicKey(x25519.utils.randomPrivateKey()); - */ -export const x25519: XCurveFn = /* @__PURE__ */ (() => - montgomery({ - P: ED25519_P, - a: BigInt(486662), - montgomeryBits: 255, // n is 253 bits - nByteLength: 32, - Gu: BigInt(9), - powPminus2: (x: bigint): bigint => { - const P = ED25519_P - // x^(p-2) aka x^(2^255-21) - const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) - return mod(pow2(pow_p_5_8, _3n, P) * b2, P) - }, - adjustScalarBytes, - randomBytes, - }))() - -/** - * Converts ed25519 public key to x25519 public key. Uses formula: - * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` - * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` - * @example - * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); - * const aPriv = x25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array { - const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) -} -export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated - -/** - * Converts ed25519 secret key to x25519 secret key. - * @example - * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); - * const aPriv = ed25519.utils.randomPrivateKey(); - * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) - */ -export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array { - const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) - return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) -} - -// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) -// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since -// SageMath returns different root first and everything falls apart - -const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic -const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 -const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) - -// prettier-ignore -function map_to_curve_elligator2_curve25519(u: bigint) { - const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic - const ELL2_J = BigInt(486662) - - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 - let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not - let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) - let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 - tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 - tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 - tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 - tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 - let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) - y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) - let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 - tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 - tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd - let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 - let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt - let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd - let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u - y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 - let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 - let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) - tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 - tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 - let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt - tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd - let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 - let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) - return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) -} - -const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 -function map_to_curve_elligator2_edwards25519(u: bigint) { - const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = - // map_to_curve_elligator2_curve25519(u) - let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd - xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 - let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM - let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd - let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) - let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd - let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 - xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) - xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) - yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) - yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) - - const inv = Fp.invertBatch([xd, yd]) // batch division - return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) -} - -export const ed25519_hasher: Hasher = /* @__PURE__ */ (() => - createHasher( - ed25519.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), - { - DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', - encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha512, - }, - ))() -/** - * @deprecated Use `ed25519_hasher` - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed25519_hasher.hashToCurve)() -/** - * @deprecated Use `ed25519_hasher` - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => - ed25519_hasher.encodeToCurve)() - -function aristp(other: unknown) { - if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') -} - -// √(-1) aka √(a) aka 2^((p-1)/4) -const SQRT_M1 = ED25519_SQRT_M1 -// √(ad - 1) -const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( - '25063068953384623474111414158702152701244531502492656460079210482610430750235', -) -// 1 / √(a-d) -const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( - '54469307008909316920995813868745141605393597292927456921205312896311721017578', -) -// 1-d² -const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( - '1159843021668779879193775521855586647937357759715417654439879720876111806838', -) -// (d-1)² -const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( - '40440834346308536858101042469323190826248399146238708352240133220865137265952', -) -// Calculates 1/√(number) -const invertSqrt = (number: bigint) => uvRatio(_1n, number) - -const MAX_255B = /* @__PURE__ */ BigInt( - '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes255ToNumberLE = (bytes: Uint8Array) => - ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) - -type ExtendedPoint = ExtPointType - -// Computes Elligator map for Ristretto -// https://ristretto.group/formulas/elligator.html -function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { - const { d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const r = mod(SQRT_M1 * r0 * r0) // 1 - const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 - let c = BigInt(-1) // 3 - const D = mod((c - d * r) * mod(r + d)) // 4 - let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 - let s_ = mod(s * r0) // 6 - if (!isNegativeLE(s_, P)) s_ = mod(-s_) - if (!Ns_D_is_sq) s = s_ // 7 - if (!Ns_D_is_sq) c = r // 8 - const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 - const s2 = s * s - const W0 = mod((s + s) * D) // 10 - const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 - const W2 = mod(_1n - s2) // 12 - const W3 = mod(_1n + s2) // 13 - return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} - -/** - * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. - * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class RistPoint implements Group { - static BASE: RistPoint - static ZERO: RistPoint - private readonly ep: ExtendedPoint - // Private property to discourage combining ExtendedPoint + RistrettoPoint - // Always use Ristretto encoding/decoding instead. - constructor(ep: ExtendedPoint) { - this.ep = ep - } - - static fromAffine(ap: AffinePoint): RistPoint { - return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) - } - - /** - * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://ristretto.group/formulas/elligator.html - * @param hex 64-byte output of a hash function - */ - static hashToCurve(hex: Hex): RistPoint { - hex = ensureBytes('ristrettoHash', hex, 64) - const r1 = bytes255ToNumberLE(hex.slice(0, 32)) - const R1 = calcElligatorRistrettoMap(r1) - const r2 = bytes255ToNumberLE(hex.slice(32, 64)) - const R2 = calcElligatorRistrettoMap(r2) - return new RistPoint(R1.add(R2)) - } - - /** - * Converts ristretto-encoded string to ristretto point. - * https://ristretto.group/formulas/decoding.html - * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding - */ - static fromHex(hex: Hex): RistPoint { - hex = ensureBytes('ristrettoHex', hex, 32) - const { a, d } = ed25519.CURVE - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' - const s = bytes255ToNumberLE(hex) - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 3. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) - const s2 = mod(s * s) - const u1 = mod(_1n + a * s2) // 4 (a is -1) - const u2 = mod(_1n - a * s2) // 5 - const u1_2 = mod(u1 * u1) - const u2_2 = mod(u2 * u2) - const v = mod(a * d * u1_2 - u2_2) // 6 - const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 - const Dx = mod(I * u2) // 8 - const Dy = mod(I * Dx * v) // 9 - let x = mod((s + s) * Dx) // 10 - if (isNegativeLE(x, P)) x = mod(-x) // 10 - const y = mod(u1 * Dy) // 11 - const t = mod(x * y) // 12 - if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) - return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) - } - - static msm(points: RistPoint[], scalars: bigint[]): RistPoint { - const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) - return pippenger(RistPoint, Fn, points, scalars) - } - - /** - * Encodes ristretto point to Uint8Array. - * https://ristretto.group/formulas/encoding.html - */ - toRawBytes(): Uint8Array { - let { ex: x, ey: y, ez: z, et: t } = this.ep - const P = ed25519.CURVE.Fp.ORDER - const mod = ed25519.CURVE.Fp.create - const u1 = mod(mod(z + y) * mod(z - y)) // 1 - const u2 = mod(x * y) // 2 - // Square root always exists - const u2sq = mod(u2 * u2) - const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 - const D1 = mod(invsqrt * u1) // 4 - const D2 = mod(invsqrt * u2) // 5 - const zInv = mod(D1 * D2 * t) // 6 - let D: bigint // 7 - if (isNegativeLE(t * zInv, P)) { - let _x = mod(y * SQRT_M1) - let _y = mod(x * SQRT_M1) - x = _x - y = _y - D = mod(D1 * INVSQRT_A_MINUS_D) - } else { - D = D2 // 8 - } - if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 - let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) - if (isNegativeLE(s, P)) s = mod(-s) - return numberToBytesLE(s, 32) // 11 - } - - toHex(): string { - return bytesToHex(this.toRawBytes()) - } - - toString(): string { - return this.toHex() - } - - // Compare one point to another. - equals(other: RistPoint): boolean { - aristp(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed25519.CURVE.Fp.create - // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) - const one = mod(X1 * Y2) === mod(Y1 * X2) - const two = mod(Y1 * Y2) === mod(X1 * X2) - return one || two - } - - add(other: RistPoint): RistPoint { - aristp(other) - return new RistPoint(this.ep.add(other.ep)) - } - - subtract(other: RistPoint): RistPoint { - aristp(other) - return new RistPoint(this.ep.subtract(other.ep)) - } - - multiply(scalar: bigint): RistPoint { - return new RistPoint(this.ep.multiply(scalar)) - } - - multiplyUnsafe(scalar: bigint): RistPoint { - return new RistPoint(this.ep.multiplyUnsafe(scalar)) - } - - double(): RistPoint { - return new RistPoint(this.ep.double()) - } - - negate(): RistPoint { - return new RistPoint(this.ep.negate()) - } -} -export const RistrettoPoint: typeof RistPoint = /* @__PURE__ */ (() => { - if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) - if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) - return RistPoint -})() - -// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B -export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts): RistPoint => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) - const P = RistPoint.hashToCurve(uniform_bytes) - return P -} -/** @deprecated */ -export const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint = - hashToRistretto255 // legacy diff --git a/packages/noble-curves-tmp/src/ed448.ts b/packages/noble-curves-tmp/src/ed448.ts deleted file mode 100644 index c39163373f2..00000000000 --- a/packages/noble-curves-tmp/src/ed448.ts +++ /dev/null @@ -1,522 +0,0 @@ -/** - * Edwards448 (not Ed448-Goldilocks) curve with following addons: - * - X448 ECDH - * - Decaf cofactor elimination - * - Elligator hash-to-group / point indistinguishability - * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { shake256 } from '@noble/hashes/sha3' -import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' -import type { AffinePoint, Group } from './abstract/curve.ts' -import { pippenger } from './abstract/curve.ts' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' -import { - type HTFMethod, - type Hasher, - createHasher, - expand_message_xof, - type htfBasicOpts, -} from './abstract/hash-to-curve.ts' -import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.ts' -import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' -import { - type Hex, - bytesToHex, - bytesToNumberLE, - ensureBytes, - equalBytes, - numberToBytesLE, -} from './abstract/utils.ts' - -const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) -const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) -const ed448P = BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', -) - -// prettier-ignore -const _1n = BigInt(1), - _2n = BigInt(2), - _3n = BigInt(3), - _4n = BigInt(4), - _11n = BigInt(11) -// prettier-ignore -const _22n = BigInt(22), - _44n = BigInt(44), - _88n = BigInt(88), - _223n = BigInt(223) - -// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. -// Used for efficient square root calculation. -// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] -function ed448_pow_Pminus3div4(x: bigint): bigint { - const P = ed448P - const b2 = (x * x * x) % P - const b3 = (b2 * b2 * x) % P - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b222 = (pow2(b220, _2n, P) * b2) % P - const b223 = (pow2(b222, _1n, P) * x) % P - return (pow2(b223, _223n, P) * b222) % P -} - -function adjustScalarBytes(bytes: Uint8Array): Uint8Array { - // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most - // significant bit of the last byte to 1. - bytes[0] &= 252 // 0b11111100 - // and the most significant bit of the last byte to 1. - bytes[55] |= 128 // 0b10000000 - // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) - bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) - return bytes -} - -// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. -// Uses algo from RFC8032 5.1.3. -function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { - const P = ed448P - // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 - // To compute the square root of (u/v), the first step is to compute the - // candidate root x = (u/v)^((p+1)/4). This can be done using the - // following trick, to use a single modular powering for both the - // inversion of v and the square root: - // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) - const u2v = mod(u * u * v, P) // u²v - const u3v = mod(u2v * u, P) // u³v - const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ - const root = ed448_pow_Pminus3div4(u5v3) - const x = mod(u3v * root, P) - // Verify that root is exists - const x2 = mod(x * x, P) // x² - // If vx² = u, the recovered x-coordinate is x. Otherwise, no - // square root exists, and the decoding fails. - return { isValid: mod(x2 * v, P) === u, value: x } -} - -const Fp = Field(ed448P, 456, true) - -const ED448_DEF = { - // Param: a - a: BigInt(1), - // -39081 a.k.a. Fp.neg(39081) - d: BigInt( - '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', - ), - // Finite field 2n**448n - 2n**224n - 1n - Fp, - // Subgroup order - // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n - n: BigInt( - '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', - ), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - nBitLength: 456, - h: BigInt(4), - Gx: BigInt( - '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', - ), - Gy: BigInt( - '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', - ), - // SHAKE256(dom4(phflag,context)||x, 114) - hash: shake256_114, - randomBytes, - adjustScalarBytes, - // dom4 - domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { - if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) - return concatBytes( - utf8ToBytes('SigEd448'), - new Uint8Array([phflag ? 1 : 0, ctx.length]), - ctx, - data, - ) - }, - uvRatio, -} as const - -/** - * ed448 EdDSA curve and methods. - * @example - * import { ed448 } from '@noble/curves/ed448'; - * const priv = ed448.utils.randomPrivateKey(); - * const pub = ed448.getPublicKey(priv); - * const msg = new TextEncoder().encode('whatsup'); - * const sig = ed448.sign(msg, priv); - * ed448.verify(sig, msg, pub); - */ -export const ed448: CurveFn = /* @__PURE__ */ twistedEdwards(ED448_DEF) -// NOTE: there is no ed448ctx, since ed448 supports ctx by default -export const ed448ph: CurveFn = /* @__PURE__ */ twistedEdwards({ - ...ED448_DEF, - prehash: shake256_64, -}) - -/** - * ECDH using curve448 aka x448. - */ -export const x448: XCurveFn = /* @__PURE__ */ (() => - montgomery({ - a: BigInt(156326), - // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys - montgomeryBits: 448, - nByteLength: 56, - P: ed448P, - Gu: BigInt(5), - powPminus2: (x: bigint): bigint => { - const P = ed448P - const Pminus3div4 = ed448_pow_Pminus3div4(x) - const Pminus3 = pow2(Pminus3div4, BigInt(2), P) - return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 - }, - adjustScalarBytes, - randomBytes, - }))() - -/** - * Converts edwards448 public key to x448 public key. Uses formula: - * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` - * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` - * @example - * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); - * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) - */ -export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array { - const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) - const _1n = BigInt(1) - return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) -} - -export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated -// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version - -// Hash To Curve Elligator2 Map -const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic -const ELL2_J = BigInt(156326) - -function map_to_curve_elligator2_curve448(u: bigint) { - let tv1 = Fp.sqr(u) // 1. tv1 = u^2 - let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 - tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 - let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 - let x1n = Fp.neg(ELL2_J) // 5. x1n = -J - let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 - let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 - let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd - gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd - gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 - gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 - let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 - tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd - tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 - let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) - y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) - let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd - let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u - y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) - tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 - tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd - let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 - let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 - let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 - let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y - y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) - return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) -} - -function map_to_curve_elligator2_edwards448(u: bigint) { - let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) - let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 - let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 - let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 - let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 - let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 - let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 - let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 - xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 - xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd - xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn - xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 - tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 - tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 - let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 - let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 - tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 - let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 - tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn - let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 - let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 - yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 - yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 - tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 - tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 - tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd - tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 - tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 - let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 - tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 - yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 - tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd - let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 - xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) - xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) - yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) - yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) - - const inv = Fp.invertBatch([xEd, yEd]) // batch division - return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) -} - -export const ed448_hasher: Hasher = /* @__PURE__ */ (() => - createHasher( - ed448.ExtendedPoint, - (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), - { - DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', - encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', - p: Fp.ORDER, - m: 1, - k: 224, - expand: 'xof', - hash: shake256, - }, - ))() -/** - * @deprecated Use `ed448_hasher` - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.hashToCurve)() -/** - * @deprecated Use `ed448_hasher` - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.encodeToCurve)() - -function adecafp(other: unknown) { - if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') -} - -// 1-d -const ONE_MINUS_D = BigInt('39082') -// 1-2d -const ONE_MINUS_TWO_D = BigInt('78163') -// √(-d) -const SQRT_MINUS_D = BigInt( - '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', -) -// 1 / √(-d) -const INVSQRT_MINUS_D = BigInt( - '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', -) -// Calculates 1/√(number) -const invertSqrt = (number: bigint) => uvRatio(_1n, number) - -const MAX_448B = BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', -) -const bytes448ToNumberLE = (bytes: Uint8Array) => - ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) - -type ExtendedPoint = ExtPointType - -// Computes Elligator map for Decaf -// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 -function calcElligatorDecafMap(r0: bigint): ExtendedPoint { - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - - const r = mod(-(r0 * r0)) // 1 - const u0 = mod(d * (r - _1n)) // 2 - const u1 = mod((u0 + _1n) * (u0 - r)) // 3 - - const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 - - let v_prime = v // 5 - if (!was_square) v_prime = mod(r0 * v) - - let sgn = _1n // 6 - if (!was_square) sgn = mod(-_1n) - - const s = mod(v_prime * (r + _1n)) // 7 - let s_abs = s - if (isNegativeLE(s, P)) s_abs = mod(-s) - - const s2 = s * s - const W0 = mod(s_abs * _2n) // 8 - const W1 = mod(s2 + _1n) // 9 - const W2 = mod(s2 - _1n) // 10 - const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 - return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) -} - -/** - * Each ed448/ExtendedPoint has 4 different equivalent points. This can be - * a source of bugs for protocols like ring signatures. Decaf was created to solve this. - * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, - * but it should work in its own namespace: do not combine those two. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 - */ -class DcfPoint implements Group { - static BASE: DcfPoint - static ZERO: DcfPoint - private readonly ep: ExtendedPoint - // Private property to discourage combining ExtendedPoint + DecafPoint - // Always use Decaf encoding/decoding instead. - constructor(ep: ExtendedPoint) { - this.ep = ep - } - - static fromAffine(ap: AffinePoint): DcfPoint { - return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) - } - - /** - * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. - * The hash-to-group operation applies Elligator twice and adds the results. - * **Note:** this is one-way map, there is no conversion from point to hash. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 - * @param hex 112-byte output of a hash function - */ - static hashToCurve(hex: Hex): DcfPoint { - hex = ensureBytes('decafHash', hex, 112) - const r1 = bytes448ToNumberLE(hex.slice(0, 56)) - const R1 = calcElligatorDecafMap(r1) - const r2 = bytes448ToNumberLE(hex.slice(56, 112)) - const R2 = calcElligatorDecafMap(r2) - return new DcfPoint(R1.add(R2)) - } - - /** - * Converts decaf-encoded string to decaf point. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 - * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding - */ - static fromHex(hex: Hex): DcfPoint { - hex = ensureBytes('decafHex', hex, 56) - const { d } = ed448.CURVE - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' - const s = bytes448ToNumberLE(hex) - - // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. - // 2. Check that s is non-negative, or else abort - if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) - - const s2 = mod(s * s) // 1 - const u1 = mod(_1n + s2) // 2 - const u1sq = mod(u1 * u1) - const u2 = mod(u1sq - _4n * d * s2) // 3 - - const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 - - let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 - if (isNegativeLE(u3, P)) u3 = mod(-u3) - - const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 - const y = mod((_1n - s2) * invsqrt * u1) // 7 - const t = mod(x * y) // 8 - - if (!isValid) throw new Error(emsg) - return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) - } - - static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint { - const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) - return pippenger(DcfPoint, Fn, points, scalars) - } - - /** - * Encodes decaf point to Uint8Array. - * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 - */ - toRawBytes(): Uint8Array { - let { ex: x, ey: _y, ez: z, et: t } = this.ep - const P = ed448.CURVE.Fp.ORDER - const mod = ed448.CURVE.Fp.create - - const u1 = mod(mod(x + t) * mod(x - t)) // 1 - const x2 = mod(x * x) - const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 - - let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 - if (isNegativeLE(ratio, P)) ratio = mod(-ratio) - - const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 - - let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 - if (isNegativeLE(s, P)) s = mod(-s) - - return numberToBytesLE(s, 56) - } - - toHex(): string { - return bytesToHex(this.toRawBytes()) - } - - toString(): string { - return this.toHex() - } - - // Compare one point to another. - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 - equals(other: DcfPoint): boolean { - adecafp(other) - const { ex: X1, ey: Y1 } = this.ep - const { ex: X2, ey: Y2 } = other.ep - const mod = ed448.CURVE.Fp.create - // (x1 * y2 == y1 * x2) - return mod(X1 * Y2) === mod(Y1 * X2) - } - - add(other: DcfPoint): DcfPoint { - adecafp(other) - return new DcfPoint(this.ep.add(other.ep)) - } - - subtract(other: DcfPoint): DcfPoint { - adecafp(other) - return new DcfPoint(this.ep.subtract(other.ep)) - } - - multiply(scalar: bigint): DcfPoint { - return new DcfPoint(this.ep.multiply(scalar)) - } - - multiplyUnsafe(scalar: bigint): DcfPoint { - return new DcfPoint(this.ep.multiplyUnsafe(scalar)) - } - - double(): DcfPoint { - return new DcfPoint(this.ep.double()) - } - - negate(): DcfPoint { - return new DcfPoint(this.ep.negate()) - } -} - -export const DecafPoint: typeof DcfPoint = /* @__PURE__ */ (() => { - // decaf448 base point is ed448 base x 2 - // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 - if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) - if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) - return DcfPoint -})() - -// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C -export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts): DcfPoint => { - const d = options.DST - const DST = typeof d === 'string' ? utf8ToBytes(d) : d - const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) - const P = DcfPoint.hashToCurve(uniform_bytes) - return P -} -export const hash_to_decaf448: typeof hashToDecaf448 = hashToDecaf448 // legacy diff --git a/packages/noble-curves-tmp/src/index.ts b/packages/noble-curves-tmp/src/index.ts deleted file mode 100644 index 8b4ac3bb10f..00000000000 --- a/packages/noble-curves-tmp/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Audited & minimal JS implementation of elliptic curve cryptography. - * @module - * @example -```js -import { secp256k1, schnorr } from '@noble/curves/secp256k1'; -import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; -import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; -import { p256 } from '@noble/curves/p256'; -import { p384 } from '@noble/curves/p384'; -import { p521 } from '@noble/curves/p521'; -import { bls12_381 } from '@noble/curves/bls12-381'; -import { bn254 } from '@noble/curves/bn254'; -import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; -``` - */ -throw new Error('root module cannot be imported: import submodules instead. Check out README') diff --git a/packages/noble-curves-tmp/src/jubjub.ts b/packages/noble-curves-tmp/src/jubjub.ts deleted file mode 100644 index 7c2c07f240c..00000000000 --- a/packages/noble-curves-tmp/src/jubjub.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - jubjub_findGroupHash as findGroupHash, - jubjub_groupHash as groupHash, - jubjub, -} from './misc.ts' diff --git a/packages/noble-curves-tmp/src/misc.ts b/packages/noble-curves-tmp/src/misc.ts deleted file mode 100644 index e7736884109..00000000000 --- a/packages/noble-curves-tmp/src/misc.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Miscellaneous, rarely used curves. - * jubjub, babyjubjub, pallas, vesta. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { blake256 } from '@noble/hashes/blake1' -import { blake2s } from '@noble/hashes/blake2s' -import { sha256, sha512 } from '@noble/hashes/sha2' -import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' -import { getHash } from './_shortw_utils.ts' -import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' -import { Field, mod } from './abstract/modular.ts' -import { type CurveFn as WCurveFn, weierstrass } from './abstract/weierstrass.ts' - -// Jubjub curves have 𝔽p over scalar fields of other curves. They are friendly to ZK proofs. -// jubjub Fp = bls n. babyjubjub Fp = bn254 n. -// verify manually, check bls12-381.ts and bn254.ts. -// https://neuromancer.sk/std/other/JubJub - -const bls12_381_Fr = Field( - BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), -) -const bn254_Fr = Field( - BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), -) - -/** Curve over scalar field of bls12-381. jubjub Fp = bls n */ -export const jubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ - a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), - d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), - Fp: bls12_381_Fr, - n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), - h: BigInt(8), - Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), - Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), - hash: sha512, - randomBytes, -} as const) - -/** Curve over scalar field of bn254. babyjubjub Fp = bn254 n */ -export const babyjubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ - a: BigInt(168700), - d: BigInt(168696), - Fp: bn254_Fr, - n: BigInt('21888242871839275222246405745257275088614511777268538073601725287587578984328'), - h: BigInt(8), - Gx: BigInt('995203441582195749578291179787384436505546430278305826713579947235728471134'), - Gy: BigInt('5472060717959818805561601436314318772137091100104008585924551046643952123905'), - hash: blake256, - randomBytes, -} as const) - -const jubjub_gh_first_block = utf8ToBytes( - '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', -) - -// Returns point at JubJub curve which is prime order and not zero -export function jubjub_groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType { - const h = blake2s.create({ personalization, dkLen: 32 }) - h.update(jubjub_gh_first_block) - h.update(tag) - // NOTE: returns ExtendedPoint, in case it will be multiplied later - let p = jubjub.ExtendedPoint.fromHex(h.digest()) - // NOTE: cannot replace with isSmallOrder, returns Point*8 - p = p.multiply(jubjub.CURVE.h) - if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') - return p -} - -// No secret data is leaked here at all. -// It operates over public data: -// const G_SPEND = jubjub.findGroupHash(Uint8Array.of(), utf8ToBytes('Item_G_')); -export function jubjub_findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType { - const tag = concatBytes(m, new Uint8Array([0])) - const hashes = [] - for (let i = 0; i < 256; i++) { - tag[tag.length - 1] = i - try { - hashes.push(jubjub_groupHash(tag, personalization)) - } catch (e) {} - } - if (!hashes.length) throw new Error('findGroupHash tag overflow') - return hashes[0] -} - -// Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). - -export const pasta_p: bigint = BigInt( - '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001', -) -export const pasta_q: bigint = BigInt( - '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001', -) - -/** https://neuromancer.sk/std/other/Pallas */ -export const pallas: WCurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(pasta_p), - n: pasta_q, - Gx: mod(BigInt(-1), pasta_p), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) -/** https://neuromancer.sk/std/other/Vesta */ -export const vesta: WCurveFn = weierstrass({ - a: BigInt(0), - b: BigInt(5), - Fp: Field(pasta_q), - n: pasta_p, - Gx: mod(BigInt(-1), pasta_q), - Gy: BigInt(2), - h: BigInt(1), - ...getHash(sha256), -}) diff --git a/packages/noble-curves-tmp/src/nist.ts b/packages/noble-curves-tmp/src/nist.ts deleted file mode 100644 index 44c3eb545df..00000000000 --- a/packages/noble-curves-tmp/src/nist.ts +++ /dev/null @@ -1,171 +0,0 @@ -/** - * NIST secp256r1 aka p256. - * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256, sha384, sha512 } from '@noble/hashes/sha2' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' -import { type Hasher, createHasher } from './abstract/hash-to-curve.ts' -import { Field } from './abstract/modular.ts' -import { mapToCurveSimpleSWU } from './abstract/weierstrass.ts' - -const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) -const p256_a = Fp256.create(BigInt('-3')) -const p256_b = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') - -/** - * secp256r1 curve, ECDSA and ECDH methods. - * Field: `2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n` - */ -// prettier-ignore -export const p256: CurveFnWithCreate = createCurve( - { - a: p256_a, - b: p256_b, - Fp: Fp256, - n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), - Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), - Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), - h: BigInt(1), - lowS: false, - } as const, - sha256, -) -/** Alias to p256. */ -export const secp256r1: CurveFnWithCreate = p256 - -const p256_mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp256, { - A: p256_a, - B: p256_b, - Z: Fp256.create(BigInt('-10')), - }))() - -/** Hashing / encoding to p256 points / field. RFC 9380 methods. */ -export const p256_hasher: Hasher = /* @__PURE__ */ (() => - createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => p256_mapSWU(scalars[0]), { - DST: 'P256_XMD:SHA-256_SSWU_RO_', - encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', - p: Fp256.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - }))() - -// Field over which we'll do calculations. -const Fp384 = Field( - BigInt( - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', - ), -) -const p384_a = Fp384.create(BigInt('-3')) -// prettier-ignore -const p384_b = BigInt( - '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', -) - -/** - * secp384r1 curve, ECDSA and ECDH methods. - * Field: `2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n`. - * */ -// prettier-ignore -export const p384: CurveFnWithCreate = createCurve( - { - a: p384_a, - b: p384_b, - Fp: Fp384, - n: BigInt( - '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', - ), - Gx: BigInt( - '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', - ), - Gy: BigInt( - '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', - ), - h: BigInt(1), - lowS: false, - } as const, - sha384, -) -/** Alias to p384. */ -export const secp384r1: CurveFnWithCreate = p384 - -const p384_mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp384, { - A: p384_a, - B: p384_b, - Z: Fp384.create(BigInt('-12')), - }))() - -/** Hashing / encoding to p384 points / field. RFC 9380 methods. */ -export const p384_hasher: Hasher = /* @__PURE__ */ (() => - createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => p384_mapSWU(scalars[0]), { - DST: 'P384_XMD:SHA-384_SSWU_RO_', - encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', - p: Fp384.ORDER, - m: 1, - k: 192, - expand: 'xmd', - hash: sha384, - }))() - -// Field over which we'll do calculations. -const Fp521 = Field( - BigInt( - '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', - ), -) - -const p521_a = Fp521.create(BigInt('-3')) -const p521_b = BigInt( - '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', -) - -/** - * NIST secp521r1 aka p521 curve, ECDSA and ECDH methods. - * Field: `2n**521n - 1n`. - */ -// prettier-ignore -export const p521: CurveFnWithCreate = createCurve( - { - a: p521_a, - b: p521_b, - Fp: Fp521, - n: BigInt( - '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', - ), - Gx: BigInt( - '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', - ), - Gy: BigInt( - '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', - ), - h: BigInt(1), - lowS: false, - allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b - } as const, - sha512, -) -export const secp521r1: CurveFnWithCreate = p521 - -const p521_mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fp521, { - A: p521_a, - B: p521_b, - Z: Fp521.create(BigInt('-4')), - }))() - -/** Hashing / encoding to p521 points / field. RFC 9380 methods. */ -export const p521_hasher: Hasher = /* @__PURE__ */ (() => - createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => p521_mapSWU(scalars[0]), { - DST: 'P521_XMD:SHA-512_SSWU_RO_', - encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', - p: Fp521.ORDER, - m: 1, - k: 256, - expand: 'xmd', - hash: sha512, - }))() diff --git a/packages/noble-curves-tmp/src/p256.ts b/packages/noble-curves-tmp/src/p256.ts deleted file mode 100644 index f1bf69ad74e..00000000000 --- a/packages/noble-curves-tmp/src/p256.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * NIST secp256r1 aka p256. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type HTFMethod } from './abstract/hash-to-curve.ts' -import { p256_hasher, p256 as p256n } from './nist.ts' -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const p256: typeof p256n = p256n -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const secp256r1: typeof p256n = p256n -/** - * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.hashToCurve)() -/** - * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/p384.ts b/packages/noble-curves-tmp/src/p384.ts deleted file mode 100644 index f08cc70b11a..00000000000 --- a/packages/noble-curves-tmp/src/p384.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * NIST secp384r1 aka p384. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type HTFMethod } from './abstract/hash-to-curve.ts' -import { p384_hasher, p384 as p384n } from './nist.ts' -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const p384: typeof p384n = p384n -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const secp384r1: typeof p384n = p384n -/** - * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.hashToCurve)() -/** - * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/p521.ts b/packages/noble-curves-tmp/src/p521.ts deleted file mode 100644 index feedf852f72..00000000000 --- a/packages/noble-curves-tmp/src/p521.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * NIST secp521r1 aka p521. - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { type HTFMethod } from './abstract/hash-to-curve.ts' -import { p521_hasher, p521 as p521n } from './nist.ts' -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const p521: typeof p521n = p521n -/** - * @deprecated Use `@noble/curves/nist` module directly. - */ -export const secp521r1: typeof p521n = p521n -/** - * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.hashToCurve)() -/** - * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/src/package.json b/packages/noble-curves-tmp/src/package.json deleted file mode 100644 index 3dbc1ca591c..00000000000 --- a/packages/noble-curves-tmp/src/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/packages/noble-curves-tmp/src/pasta.ts b/packages/noble-curves-tmp/src/pasta.ts deleted file mode 100644 index 18aa8b858c7..00000000000 --- a/packages/noble-curves-tmp/src/pasta.ts +++ /dev/null @@ -1 +0,0 @@ -export { pallas, vesta } from './misc.ts' diff --git a/packages/noble-curves-tmp/src/secp256k1.ts b/packages/noble-curves-tmp/src/secp256k1.ts deleted file mode 100644 index 810c5698ac6..00000000000 --- a/packages/noble-curves-tmp/src/secp256k1.ts +++ /dev/null @@ -1,343 +0,0 @@ -/** - * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). - * - * Seems to be rigid (not backdoored) - * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). - * - * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. - * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. - * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. - * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). - * @module - */ -/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ -import { sha256 } from '@noble/hashes/sha2' -import { randomBytes } from '@noble/hashes/utils' -import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' -import { type HTFMethod, type Hasher, createHasher, isogenyMap } from './abstract/hash-to-curve.ts' -import { Field, mod, pow2 } from './abstract/modular.ts' -import type { Hex, PrivKey } from './abstract/utils.ts' -import { - aInRange, - bytesToNumberBE, - concatBytes, - ensureBytes, - inRange, - numberToBytesBE, -} from './abstract/utils.ts' -import { type ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.ts' - -const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') -const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') -const _1n = BigInt(1) -const _2n = BigInt(2) -const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b - -/** - * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. - * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] - */ -function sqrtMod(y: bigint): bigint { - const P = secp256k1P - // prettier-ignore - const _3n = BigInt(3), - _6n = BigInt(6), - _11n = BigInt(11), - _22n = BigInt(22) - // prettier-ignore - const _23n = BigInt(23), - _44n = BigInt(44), - _88n = BigInt(88) - const b2 = (y * y * y) % P // x^3, 11 - const b3 = (b2 * b2 * y) % P // x^7 - const b6 = (pow2(b3, _3n, P) * b3) % P - const b9 = (pow2(b6, _3n, P) * b3) % P - const b11 = (pow2(b9, _2n, P) * b2) % P - const b22 = (pow2(b11, _11n, P) * b11) % P - const b44 = (pow2(b22, _22n, P) * b22) % P - const b88 = (pow2(b44, _44n, P) * b44) % P - const b176 = (pow2(b88, _88n, P) * b88) % P - const b220 = (pow2(b176, _44n, P) * b44) % P - const b223 = (pow2(b220, _3n, P) * b3) % P - const t1 = (pow2(b223, _23n, P) * b22) % P - const t2 = (pow2(t1, _6n, P) * b2) % P - const root = pow2(t2, _2n, P) - if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') - return root -} - -const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) - -/** - * secp256k1 curve, ECDSA and ECDH methods. - * - * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n` - * - * @example - * ```js - * import { secp256k1 } from '@noble/curves/secp256k1'; - * const priv = secp256k1.utils.randomPrivateKey(); - * const pub = secp256k1.getPublicKey(priv); - * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa - * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available - * const isValid = secp256k1.verify(sig, msg, pub) === true; - * ``` - */ -export const secp256k1: CurveFnWithCreate = createCurve( - { - a: BigInt(0), - b: BigInt(7), - Fp: Fpk1, - n: secp256k1N, - Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), - Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), - h: BigInt(1), // Cofactor - lowS: true, // Allow only low-S signatures by default in sign() and verify() - endo: { - // Endomorphism, see above - beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), - splitScalar: (k: bigint) => { - const n = secp256k1N - const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') - const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') - const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') - const b2 = a1 - const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) - - const c1 = divNearest(b2 * k, n) - const c2 = divNearest(-b1 * k, n) - let k1 = mod(k - c1 * a1 - c2 * a2, n) - let k2 = mod(-c1 * b1 - c2 * b2, n) - const k1neg = k1 > POW_2_128 - const k2neg = k2 > POW_2_128 - if (k1neg) k1 = n - k1 - if (k2neg) k2 = n - k2 - if (k1 > POW_2_128 || k2 > POW_2_128) { - throw new Error('splitScalar: Endomorphism failed, k=' + k) - } - return { k1neg, k1, k2neg, k2 } - }, - }, - }, - sha256, -) - -// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. -// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki -const _0n = BigInt(0) -/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ -const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {} -function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array { - let tagP = TAGGED_HASH_PREFIXES[tag] - if (tagP === undefined) { - const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) - tagP = concatBytes(tagH, tagH) - TAGGED_HASH_PREFIXES[tag] = tagP - } - return sha256(concatBytes(tagP, ...messages)) -} - -// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 -const pointToBytes = (point: PointType) => point.toRawBytes(true).slice(1) -const numTo32b = (n: bigint) => numberToBytesBE(n, 32) -const modP = (x: bigint) => mod(x, secp256k1P) -const modN = (x: bigint) => mod(x, secp256k1N) -const Point = secp256k1.ProjectivePoint -const GmulAdd = (Q: PointType, a: bigint, b: bigint) => - Point.BASE.multiplyAndAddUnsafe(Q, a, b) - -// Calculate point, scalar and bytes -function schnorrGetExtPubKey(priv: PrivKey) { - let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey - let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside - const scalar = p.hasEvenY() ? d_ : modN(-d_) - return { scalar: scalar, bytes: pointToBytes(p) } -} -/** - * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. - * @returns valid point checked for being on-curve - */ -function lift_x(x: bigint): PointType { - aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. - const xx = modP(x * x) - const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. - let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. - if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and - const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. - p.assertValidity() - return p -} -const num = bytesToNumberBE -/** - * Create tagged hash, convert it to bigint, reduce modulo-n. - */ -function challenge(...args: Uint8Array[]): bigint { - return modN(num(taggedHash('BIP0340/challenge', ...args))) -} - -/** - * Schnorr public key is just `x` coordinate of Point as per BIP340. - */ -function schnorrGetPublicKey(privateKey: Hex): Uint8Array { - return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) -} - -/** - * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. - * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. - */ -function schnorrSign( - message: Hex, - privateKey: PrivKey, - auxRand: Hex = randomBytes(32), -): Uint8Array { - const m = ensureBytes('message', message) - const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder - const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array - const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) - const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) - const k_ = modN(num(rand)) // Let k' = int(rand) mod n - if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. - const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. - const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. - const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). - sig.set(rx, 0) - sig.set(numTo32b(modN(k + e * d)), 32) - // If Verify(bytes(P), m, sig) (see below) returns failure, abort - if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') - return sig -} - -/** - * Verifies Schnorr signature. - * Will swallow errors & return false except for initial type validation of arguments. - */ -function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { - const sig = ensureBytes('signature', signature, 64) - const m = ensureBytes('message', message) - const pub = ensureBytes('publicKey', publicKey, 32) - try { - const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails - const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. - if (!inRange(r, _1n, secp256k1P)) return false - const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. - if (!inRange(s, _1n, secp256k1N)) return false - const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n - const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P - if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P - return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. - } catch (error) { - return false - } -} - -export type SecpSchnorr = { - getPublicKey: typeof schnorrGetPublicKey - sign: typeof schnorrSign - verify: typeof schnorrVerify - utils: { - randomPrivateKey: () => Uint8Array - lift_x: typeof lift_x - pointToBytes: (point: PointType) => Uint8Array - numberToBytesBE: typeof numberToBytesBE - bytesToNumberBE: typeof bytesToNumberBE - taggedHash: typeof taggedHash - mod: typeof mod - } -} -/** - * Schnorr signatures over secp256k1. - * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki - * @example - * ```js - * import { schnorr } from '@noble/curves/secp256k1'; - * const priv = schnorr.utils.randomPrivateKey(); - * const pub = schnorr.getPublicKey(priv); - * const msg = new TextEncoder().encode('hello'); - * const sig = schnorr.sign(msg, priv); - * const isValid = schnorr.verify(sig, msg, pub); - * ``` - */ -export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => ({ - getPublicKey: schnorrGetPublicKey, - sign: schnorrSign, - verify: schnorrVerify, - utils: { - randomPrivateKey: secp256k1.utils.randomPrivateKey, - lift_x, - pointToBytes, - numberToBytesBE, - bytesToNumberBE, - taggedHash, - mod, - }, -}))() - -const isoMap = /* @__PURE__ */ (() => - isogenyMap( - Fpk1, - [ - // xNum - [ - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', - '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', - '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', - '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', - ], - // xDen - [ - '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', - '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - // yNum - [ - '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', - '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', - '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', - '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', - ], - // yDen - [ - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', - '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', - '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', - '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 - ], - ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]], - ))() -const mapSWU = /* @__PURE__ */ (() => - mapToCurveSimpleSWU(Fpk1, { - A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), - B: BigInt('1771'), - Z: Fpk1.create(BigInt('-11')), - }))() -/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */ -export const secp256k1_hasher: Hasher = /* @__PURE__ */ (() => - createHasher( - secp256k1.ProjectivePoint, - (scalars: bigint[]) => { - const { x, y } = mapSWU(Fpk1.create(scalars[0])) - return isoMap(x, y) - }, - { - DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', - encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', - p: Fpk1.ORDER, - m: 1, - k: 128, - expand: 'xmd', - hash: sha256, - } as const, - ))() - -/** - * @deprecated Use `secp256k1_hasher` - */ -export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => secp256k1_hasher.hashToCurve)() - -/** - * @deprecated Use `secp256k1_hasher` - */ -export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => - secp256k1_hasher.encodeToCurve)() diff --git a/packages/noble-curves-tmp/tsconfig.json b/packages/noble-curves-tmp/tsconfig.json deleted file mode 100644 index d2e7d4625d9..00000000000 --- a/packages/noble-curves-tmp/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../config/tsconfig.json", - "compilerOptions": { - "outDir": "./dist" - }, - "include": ["src/**/*.ts", "test/**/*.ts"] -} diff --git a/packages/noble-curves-tmp/tsconfig.lint.json b/packages/noble-curves-tmp/tsconfig.lint.json deleted file mode 100644 index 3698f4f0be3..00000000000 --- a/packages/noble-curves-tmp/tsconfig.lint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../config/tsconfig.lint.json" -} diff --git a/packages/noble-curves-tmp/tsconfig.prod.cjs.json b/packages/noble-curves-tmp/tsconfig.prod.cjs.json deleted file mode 100644 index 6e1d752908c..00000000000 --- a/packages/noble-curves-tmp/tsconfig.prod.cjs.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../config/tsconfig.prod.cjs.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/cjs" - }, - "include": ["src/**/*.ts"], - "references": [{ "path": "../rlp/tsconfig.prod.cjs.json" }] -} diff --git a/packages/noble-curves-tmp/tsconfig.prod.esm.json b/packages/noble-curves-tmp/tsconfig.prod.esm.json deleted file mode 100644 index cbc8c91a0d6..00000000000 --- a/packages/noble-curves-tmp/tsconfig.prod.esm.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../config/tsconfig.prod.esm.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm" - }, - "include": ["src/**/*.ts"], - "references": [ - { "path": "../rlp/tsconfig.prod.esm.json" }, - { "path": "../block/tsconfig.prod.esm.json" }, - { "path": "../blockchain/tsconfig.prod.esm.json" } - ] -} diff --git a/packages/noble-curves-tmp/typedoc.cjs b/packages/noble-curves-tmp/typedoc.cjs deleted file mode 100644 index 0c5a50bf952..00000000000 --- a/packages/noble-curves-tmp/typedoc.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - extends: '../../config/typedoc.cjs', - entryPoints: ['src'], - out: 'docs', - exclude: ['test/*.ts'], -} From f6bc1f8ca657f9d910e345ce47fb654cd232461f Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 22 Apr 2025 16:31:07 +0200 Subject: [PATCH 09/10] add noble as internal pkg --- .../bls12_381/nbl/src/_shortw_utils.ts | 30 + .../bls12_381/nbl/src/abstract/bls.ts | 573 +++++++ .../bls12_381/nbl/src/abstract/curve.ts | 466 ++++++ .../bls12_381/nbl/src/abstract/edwards.ts | 567 +++++++ .../nbl/src/abstract/hash-to-curve.ts | 262 +++ .../bls12_381/nbl/src/abstract/modular.ts | 555 +++++++ .../bls12_381/nbl/src/abstract/montgomery.ts | 190 +++ .../bls12_381/nbl/src/abstract/poseidon.ts | 329 ++++ .../bls12_381/nbl/src/abstract/tower.ts | 664 ++++++++ .../bls12_381/nbl/src/abstract/utils.ts | 378 +++++ .../bls12_381/nbl/src/abstract/weierstrass.ts | 1419 +++++++++++++++++ .../bls12_381/nbl/src/bls12-381.ts | 776 +++++++++ .../precompiles/bls12_381/nbl/src/bn254.ts | 255 +++ .../precompiles/bls12_381/nbl/src/ed25519.ts | 554 +++++++ .../precompiles/bls12_381/nbl/src/ed448.ts | 522 ++++++ .../precompiles/bls12_381/nbl/src/index.ts | 17 + .../precompiles/bls12_381/nbl/src/jubjub.ts | 5 + .../src/precompiles/bls12_381/nbl/src/misc.ts | 117 ++ .../src/precompiles/bls12_381/nbl/src/nist.ts | 171 ++ .../src/precompiles/bls12_381/nbl/src/p256.ts | 23 + .../src/precompiles/bls12_381/nbl/src/p384.ts | 23 + .../src/precompiles/bls12_381/nbl/src/p521.ts | 23 + .../bls12_381/nbl/src/package.json | 3 + .../precompiles/bls12_381/nbl/src/pasta.ts | 1 + .../bls12_381/nbl/src/secp256k1.ts | 343 ++++ .../evm/src/precompiles/bls12_381/noble.ts | 2 +- 26 files changed, 8267 insertions(+), 1 deletion(-) create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/_shortw_utils.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/bls.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/curve.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/edwards.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/hash-to-curve.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/modular.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/montgomery.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/poseidon.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/tower.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/utils.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/abstract/weierstrass.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/bls12-381.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/bn254.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/ed25519.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/ed448.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/index.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/jubjub.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/misc.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/nist.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/p256.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/p384.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/p521.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/package.json create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/pasta.ts create mode 100644 packages/evm/src/precompiles/bls12_381/nbl/src/secp256k1.ts diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/_shortw_utils.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/_shortw_utils.ts new file mode 100644 index 00000000000..d5bc2717d58 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/_shortw_utils.ts @@ -0,0 +1,30 @@ +/** + * Utilities for short weierstrass curves, combined with noble-hashes. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { hmac } from '@noble/hashes/hmac' +import { concatBytes, randomBytes } from '@noble/hashes/utils' +import type { CHash } from './abstract/utils.ts' +import { type CurveFn, type CurveType, weierstrass } from './abstract/weierstrass.ts' + +/** connects noble-curves to noble-hashes */ +export function getHash(hash: CHash): { + hash: CHash + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array + randomBytes: typeof randomBytes +} { + return { + hash, + hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => hmac(hash, key, concatBytes(...msgs)), + randomBytes, + } +} +/** Same API as @noble/hashes, with ability to create curve with custom hash */ +export type CurveDef = Readonly> +export type CurveFnWithCreate = CurveFn & { create: (hash: CHash) => CurveFn } + +export function createCurve(curveDef: CurveDef, defHash: CHash): CurveFnWithCreate { + const create = (hash: CHash): CurveFn => weierstrass({ ...curveDef, ...getHash(hash) }) + return { ...create(defHash), create } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/bls.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/bls.ts new file mode 100644 index 00000000000..37e8eead962 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/bls.ts @@ -0,0 +1,573 @@ +/** + * BLS (Barreto-Lynn-Scott) family of pairing-friendly curves. + * BLS != BLS. + * The file implements BLS (Boneh-Lynn-Shacham) signatures. + * Used in both BLS (Barreto-Lynn-Scott) and BN (Barreto-Naehrig) + * families of pairing-friendly curves. + * Consists of two curves: G1 and G2: + * - G1 is a subgroup of (x, y) E(Fq) over y² = x³ + 4. + * - G2 is a subgroup of ((x₁, x₂+i), (y₁, y₂+i)) E(Fq²) over y² = x³ + 4(1 + i) where i is √-1 + * - Gt, created by bilinear (ate) pairing e(G1, G2), consists of p-th roots of unity in + * Fq^k where k is embedding degree. Only degree 12 is currently supported, 24 is not. + * Pairing is used to aggregate and verify signatures. + * There are two main ways to use it: + * 1. Fp for short private keys, Fp₂ for signatures + * 2. Fp for short signatures, Fp₂ for private keys + * @module + **/ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// TODO: import { AffinePoint } from './curve.ts'; +import { + type H2CPointConstructor, + type Opts as HTFOpts, + type MapToCurve, + createHasher, + type htfBasicOpts, +} from './hash-to-curve.ts' +import { type IField, getMinHashLength, mapHashToField } from './modular.ts' +import type { Fp2, Fp2Bls, Fp6, Fp12, Fp12Bls } from './tower.ts' +import { type CHash, type Hex, type PrivKey, ensureBytes, memoized } from './utils.ts' +import { + type CurvePointsRes, + type CurvePointsType, + type ProjPointType, + weierstrassPoints, +} from './weierstrass.ts' + +type Fp = bigint // Can be different field? + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +export type TwistType = 'multiplicative' | 'divisive' + +export type ShortSignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type SignatureCoder = { + fromHex(hex: Hex): ProjPointType + toRawBytes(point: ProjPointType): Uint8Array + toHex(point: ProjPointType): string +} + +export type PostPrecomputePointAddFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, +) => { Rx: Fp2; Ry: Fp2; Rz: Fp2 } +export type PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => void +export type CurveType = { + G1: Omit, 'n'> & { + ShortSignature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + G2: Omit, 'n'> & { + Signature: SignatureCoder + mapToCurve: MapToCurve + htfDefaults: HTFOpts + } + fields: { + Fp: IField + Fr: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + } + params: { + // NOTE: MSB is always ignored and used as marker for length, + // otherwise leading zeros will be lost. + // Can be different from 'X' (seed) param! + ateLoopSize: bigint + xNegative: boolean + r: bigint + twistType: TwistType // BLS12-381: Multiplicative, BN254: Divisive + } + htfDefaults: HTFOpts + hash: CHash // Because we need outputLen for DRBG + randomBytes: (bytesLength?: number) => Uint8Array + // This is super ugly hack for untwist point in BN254 after miller loop + postPrecompute?: PostPrecomputeFn +} + +type PrecomputeSingle = [Fp2, Fp2, Fp2][] +type Precompute = PrecomputeSingle[] + +export type CurveFn = { + getPublicKey: (privateKey: PrivKey) => Uint8Array + getPublicKeyForShortSignatures: (privateKey: PrivKey) => Uint8Array + sign: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + signShortSignature: { + (message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + (message: ProjPointType, privateKey: PrivKey, htfOpts?: htfBasicOpts): ProjPointType + } + verify: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyShortSignature: ( + signature: Hex | ProjPointType, + message: Hex | ProjPointType, + publicKey: Hex | ProjPointType, + htfOpts?: htfBasicOpts, + ) => boolean + verifyBatch: ( + signature: Hex | ProjPointType, + messages: (Hex | ProjPointType)[], + publicKeys: (Hex | ProjPointType)[], + htfOpts?: htfBasicOpts, + ) => boolean + aggregatePublicKeys: { + (publicKeys: Hex[]): Uint8Array + (publicKeys: ProjPointType[]): ProjPointType + } + aggregateSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + aggregateShortSignatures: { + (signatures: Hex[]): Uint8Array + (signatures: ProjPointType[]): ProjPointType + } + millerLoopBatch: (pairs: [Precompute, Fp, Fp][]) => Fp12 + pairing: (P: ProjPointType, Q: ProjPointType, withFinalExponent?: boolean) => Fp12 + pairingBatch: ( + pairs: { g1: ProjPointType; g2: ProjPointType }[], + withFinalExponent?: boolean, + ) => Fp12 + G1: CurvePointsRes & ReturnType> + G2: CurvePointsRes & ReturnType> + Signature: SignatureCoder + ShortSignature: ShortSignatureCoder + params: { + ateLoopSize: bigint + r: bigint + G1b: bigint + G2b: Fp2 + } + fields: { + Fp: IField + Fp2: Fp2Bls + Fp6: IField + Fp12: Fp12Bls + Fr: IField + } + utils: { + randomPrivateKey: () => Uint8Array + calcPairingPrecomputes: (p: ProjPointType) => Precompute + } +} + +// Not used with BLS12-381 (no sequential `11` in X). Useful for other curves. +function NAfDecomposition(a: bigint) { + const res = [] + // a>1 because of marker bit + for (; a > _1n; a >>= _1n) { + if ((a & _1n) === _0n) res.unshift(0) + else if ((a & _3n) === _3n) { + res.unshift(-1) + a += _1n + } else res.unshift(1) + } + return res +} + +export function bls(CURVE: CurveType): CurveFn { + // Fields are specific for curve, so for now we'll need to pass them with opts + const { Fp, Fr, Fp2, Fp6, Fp12 } = CURVE.fields + const BLS_X_IS_NEGATIVE = CURVE.params.xNegative + const TWIST: TwistType = CURVE.params.twistType + // Point on G1 curve: (x, y) + const G1_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G1 }) + const G1 = Object.assign( + G1_, + createHasher(G1_.ProjectivePoint, CURVE.G1.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G1.htfDefaults, + }), + ) + // Point on G2 curve (complex numbers): (x₁, x₂+i), (y₁, y₂+i) + const G2_ = weierstrassPoints({ n: Fr.ORDER, ...CURVE.G2 }) + const G2 = Object.assign( + G2_, + createHasher(G2_.ProjectivePoint as H2CPointConstructor, CURVE.G2.mapToCurve, { + ...CURVE.htfDefaults, + ...CURVE.G2.htfDefaults, + }), + ) + type G1 = typeof G1.ProjectivePoint.BASE + type G2 = typeof G2.ProjectivePoint.BASE + + // Applies sparse multiplication as line function + let lineFunction: (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => Fp12 + if (TWIST === 'multiplicative') { + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul014(f, c0, Fp2.mul(c1, Px), Fp2.mul(c2, Py)) + } else if (TWIST === 'divisive') { + // NOTE: it should be [c0, c1, c2], but we use different order here to reduce complexity of + // precompute calculations. + lineFunction = (c0: Fp2, c1: Fp2, c2: Fp2, f: Fp12, Px: Fp, Py: Fp) => + Fp12.mul034(f, Fp2.mul(c2, Py), Fp2.mul(c1, Px), c0) + } else throw new Error('bls: unknown twist type') + + const Fp2div2 = Fp2.div(Fp2.ONE, Fp2.mul(Fp2.ONE, _2n)) + function pointDouble(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2) { + const t0 = Fp2.sqr(Ry) // Ry² + const t1 = Fp2.sqr(Rz) // Rz² + const t2 = Fp2.mulByB(Fp2.mul(t1, _3n)) // 3 * T1 * B + const t3 = Fp2.mul(t2, _3n) // 3 * T2 + const t4 = Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(Ry, Rz)), t1), t0) // (Ry + Rz)² - T1 - T0 + const c0 = Fp2.sub(t2, t0) // T2 - T0 (i) + const c1 = Fp2.mul(Fp2.sqr(Rx), _3n) // 3 * Rx² + const c2 = Fp2.neg(t4) // -T4 (-h) + + ell.push([c0, c1, c2]) + + Rx = Fp2.mul(Fp2.mul(Fp2.mul(Fp2.sub(t0, t3), Rx), Ry), Fp2div2) // ((T0 - T3) * Rx * Ry) / 2 + Ry = Fp2.sub(Fp2.sqr(Fp2.mul(Fp2.add(t0, t3), Fp2div2)), Fp2.mul(Fp2.sqr(t2), _3n)) // ((T0 + T3) / 2)² - 3 * T2² + Rz = Fp2.mul(t0, t4) // T0 * T4 + return { Rx, Ry, Rz } + } + function pointAdd(ell: PrecomputeSingle, Rx: Fp2, Ry: Fp2, Rz: Fp2, Qx: Fp2, Qy: Fp2) { + // Addition + const t0 = Fp2.sub(Ry, Fp2.mul(Qy, Rz)) // Ry - Qy * Rz + const t1 = Fp2.sub(Rx, Fp2.mul(Qx, Rz)) // Rx - Qx * Rz + const c0 = Fp2.sub(Fp2.mul(t0, Qx), Fp2.mul(t1, Qy)) // T0 * Qx - T1 * Qy == Ry * Qx - Rx * Qy + const c1 = Fp2.neg(t0) // -T0 == Qy * Rz - Ry + const c2 = t1 // == Rx - Qx * Rz + + ell.push([c0, c1, c2]) + + const t2 = Fp2.sqr(t1) // T1² + const t3 = Fp2.mul(t2, t1) // T2 * T1 + const t4 = Fp2.mul(t2, Rx) // T2 * Rx + const t5 = Fp2.add(Fp2.sub(t3, Fp2.mul(t4, _2n)), Fp2.mul(Fp2.sqr(t0), Rz)) // T3 - 2 * T4 + T0² * Rz + Rx = Fp2.mul(t1, t5) // T1 * T5 + Ry = Fp2.sub(Fp2.mul(Fp2.sub(t4, t5), t0), Fp2.mul(t3, Ry)) // (T4 - T5) * T0 - T3 * Ry + Rz = Fp2.mul(Rz, t3) // Rz * T3 + return { Rx, Ry, Rz } + } + + // Pre-compute coefficients for sparse multiplication + // Point addition and point double calculations is reused for coefficients + // pointAdd happens only if bit set, so wNAF is reasonable. Unfortunately we cannot combine + // add + double in windowed precomputes here, otherwise it would be single op (since X is static) + const ATE_NAF = NAfDecomposition(CURVE.params.ateLoopSize) + + const calcPairingPrecomputes = memoized((point: G2) => { + const p = point + const { x, y } = p.toAffine() + // prettier-ignore + const Qx = x, + Qy = y, + negQy = Fp2.neg(y) + // prettier-ignore + let Rx = Qx, + Ry = Qy, + Rz = Fp2.ONE + const ell: Precompute = [] + for (const bit of ATE_NAF) { + const cur: PrecomputeSingle = [] + ;({ Rx, Ry, Rz } = pointDouble(cur, Rx, Ry, Rz)) + if (bit) ({ Rx, Ry, Rz } = pointAdd(cur, Rx, Ry, Rz, Qx, bit === -1 ? negQy : Qy)) + ell.push(cur) + } + if (CURVE.postPrecompute) { + const last = ell[ell.length - 1] + CURVE.postPrecompute(Rx, Ry, Rz, Qx, Qy, pointAdd.bind(null, last)) + } + return ell + }) + + // Main pairing logic is here. Computes product of miller loops + final exponentiate + // Applies calculated precomputes + type MillerInput = [Precompute, Fp, Fp][] + function millerLoopBatch(pairs: MillerInput, withFinalExponent: boolean = false) { + let f12 = Fp12.ONE + if (pairs.length) { + const ellLen = pairs[0][0].length + for (let i = 0; i < ellLen; i++) { + f12 = Fp12.sqr(f12) // This allows us to do sqr only one time for all pairings + // NOTE: we apply multiple pairings in parallel here + for (const [ell, Px, Py] of pairs) { + for (const [c0, c1, c2] of ell[i]) f12 = lineFunction(c0, c1, c2, f12, Px, Py) + } + } + } + if (BLS_X_IS_NEGATIVE) f12 = Fp12.conjugate(f12) + return withFinalExponent ? Fp12.finalExponentiate(f12) : f12 + } + type PairingInput = { g1: G1; g2: G2 } + // Calculates product of multiple pairings + // This up to x2 faster than just `map(({g1, g2})=>pairing({g1,g2}))` + function pairingBatch(pairs: PairingInput[], withFinalExponent: boolean = true) { + const res: MillerInput = [] + // This cache precomputed toAffine for all points + G1.ProjectivePoint.normalizeZ(pairs.map(({ g1 }) => g1)) + G2.ProjectivePoint.normalizeZ(pairs.map(({ g2 }) => g2)) + for (const { g1, g2 } of pairs) { + if (g1.equals(G1.ProjectivePoint.ZERO) || g2.equals(G2.ProjectivePoint.ZERO)) + throw new Error('pairing is not available for ZERO point') + // This uses toAffine inside + g1.assertValidity() + g2.assertValidity() + const Qa = g1.toAffine() + res.push([calcPairingPrecomputes(g2), Qa.x, Qa.y]) + } + return millerLoopBatch(res, withFinalExponent) + } + // Calculates bilinear pairing + function pairing(Q: G1, P: G2, withFinalExponent: boolean = true): Fp12 { + return pairingBatch([{ g1: Q, g2: P }], withFinalExponent) + } + + const utils = { + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(Fr.ORDER) + return mapHashToField(CURVE.randomBytes(length), Fr.ORDER) + }, + calcPairingPrecomputes, + } + + const { ShortSignature } = CURVE.G1 + const { Signature } = CURVE.G2 + + type G1Hex = Hex | G1 + type G2Hex = Hex | G2 + function normP1(point: G1Hex): G1 { + return point instanceof G1.ProjectivePoint ? (point as G1) : G1.ProjectivePoint.fromHex(point) + } + function normP1Hash(point: G1Hex, htfOpts?: htfBasicOpts): G1 { + return point instanceof G1.ProjectivePoint + ? point + : (G1.hashToCurve(ensureBytes('point', point), htfOpts) as G1) + } + function normP2(point: G2Hex): G2 { + return point instanceof G2.ProjectivePoint ? point : Signature.fromHex(point) + } + function normP2Hash(point: G2Hex, htfOpts?: htfBasicOpts): G2 { + return point instanceof G2.ProjectivePoint + ? point + : (G2.hashToCurve(ensureBytes('point', point), htfOpts) as G2) + } + + // Multiplies generator (G1) by private key. + // P = pk x G + function getPublicKey(privateKey: PrivKey): Uint8Array { + return G1.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Multiplies generator (G2) by private key. + // P = pk x G + function getPublicKeyForShortSignatures(privateKey: PrivKey): Uint8Array { + return G2.ProjectivePoint.fromPrivateKey(privateKey).toRawBytes(true) + } + + // Executes `hashToCurve` on the message and then multiplies the result by private key. + // S = pk x H(m) + function sign(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function sign(message: G2, privateKey: PrivKey, htfOpts?: htfBasicOpts): G2 + function sign(message: G2Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array | G2 { + const msgPoint = normP2Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G2.ProjectivePoint) return sigPoint + return Signature.toRawBytes(sigPoint) + } + + function signShortSignature(message: Hex, privateKey: PrivKey, htfOpts?: htfBasicOpts): Uint8Array + function signShortSignature(message: G1, privateKey: PrivKey, htfOpts?: htfBasicOpts): G1 + function signShortSignature( + message: G1Hex, + privateKey: PrivKey, + htfOpts?: htfBasicOpts, + ): Uint8Array | G1 { + const msgPoint = normP1Hash(message, htfOpts) + msgPoint.assertValidity() + const sigPoint = msgPoint.multiply(G1.normPrivateKeyToScalar(privateKey)) + if (message instanceof G1.ProjectivePoint) return sigPoint + return ShortSignature.toRawBytes(sigPoint) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(P, H(m)) == e(G, S) + function verify( + signature: G2Hex, + message: G2Hex, + publicKey: G1Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP1(publicKey) + const Hm = normP2Hash(message, htfOpts) + const G = G1.ProjectivePoint.BASE + const S = normP2(signature) + const exp = pairingBatch([ + { g1: P.negate(), g2: Hm }, // ePHM = pairing(P.negate(), Hm, false); + { g1: G, g2: S }, // eGS = pairing(G, S, false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + // Checks if pairing of public key & hash is equal to pairing of generator & signature. + // e(S, G) == e(H(m), P) + function verifyShortSignature( + signature: G1Hex, + message: G1Hex, + publicKey: G2Hex, + htfOpts?: htfBasicOpts, + ): boolean { + const P = normP2(publicKey) + const Hm = normP1Hash(message, htfOpts) + const G = G2.ProjectivePoint.BASE + const S = normP1(signature) + const exp = pairingBatch([ + { g1: Hm, g2: P }, // eHmP = pairing(Hm, P, false); + { g1: S, g2: G.negate() }, // eSG = pairing(S, G.negate(), false); + ]) + return Fp12.eql(exp, Fp12.ONE) + } + + function aNonEmpty(arr: any[]) { + if (!Array.isArray(arr) || arr.length === 0) throw new Error('expected non-empty array') + } + + // Adds a bunch of public key points together. + // pk1 + pk2 + pk3 = pkA + function aggregatePublicKeys(publicKeys: Hex[]): Uint8Array + function aggregatePublicKeys(publicKeys: G1[]): G1 + function aggregatePublicKeys(publicKeys: G1Hex[]): Uint8Array | G1 { + aNonEmpty(publicKeys) + const agg = publicKeys.map(normP1).reduce((sum, p) => sum.add(p), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (publicKeys[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + // toRawBytes ensures point validity + return aggAffine.toRawBytes(true) + } + + // Adds a bunch of signature points together. + function aggregateSignatures(signatures: Hex[]): Uint8Array + function aggregateSignatures(signatures: G2[]): G2 + function aggregateSignatures(signatures: G2Hex[]): Uint8Array | G2 { + aNonEmpty(signatures) + const agg = signatures.map(normP2).reduce((sum, s) => sum.add(s), G2.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G2.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return Signature.toRawBytes(aggAffine) + } + + // Adds a bunch of signature points together. + function aggregateShortSignatures(signatures: Hex[]): Uint8Array + function aggregateShortSignatures(signatures: G1[]): G1 + function aggregateShortSignatures(signatures: G1Hex[]): Uint8Array | G1 { + aNonEmpty(signatures) + const agg = signatures.map(normP1).reduce((sum, s) => sum.add(s), G1.ProjectivePoint.ZERO) + const aggAffine = agg //.toAffine(); + if (signatures[0] instanceof G1.ProjectivePoint) { + aggAffine.assertValidity() + return aggAffine + } + return ShortSignature.toRawBytes(aggAffine) + } + + // https://ethresear.ch/t/fast-verification-of-multiple-bls-signatures/5407 + // e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si)) + function verifyBatch( + signature: G2Hex, + // TODO: maybe `{message: G2Hex, publicKey: G1Hex}[]` instead? + messages: G2Hex[], + publicKeys: G1Hex[], + htfOpts?: htfBasicOpts, + ): boolean { + aNonEmpty(messages) + if (publicKeys.length !== messages.length) + throw new Error('amount of public keys and messages should be equal') + const sig = normP2(signature) + const nMessages = messages.map((i) => normP2Hash(i, htfOpts)) + const nPublicKeys = publicKeys.map(normP1) + // NOTE: this works only for exact same object + const messagePubKeyMap = new Map() + for (let i = 0; i < nPublicKeys.length; i++) { + const pub = nPublicKeys[i] + const msg = nMessages[i] + let keys = messagePubKeyMap.get(msg) + if (keys === undefined) { + keys = [] + messagePubKeyMap.set(msg, keys) + } + keys.push(pub) + } + const paired = [] + try { + for (const [msg, keys] of messagePubKeyMap) { + const groupPublicKey = keys.reduce((acc, msg) => acc.add(msg)) + paired.push({ g1: groupPublicKey, g2: msg }) + } + paired.push({ g1: G1.ProjectivePoint.BASE.negate(), g2: sig }) + return Fp12.eql(pairingBatch(paired), Fp12.ONE) + } catch { + return false + } + } + + G1.ProjectivePoint.BASE._setWindowSize(4) + + return { + getPublicKey, + getPublicKeyForShortSignatures, + sign, + signShortSignature, + verify, + verifyBatch, + verifyShortSignature, + aggregatePublicKeys, + aggregateSignatures, + aggregateShortSignatures, + millerLoopBatch, + pairing, + pairingBatch, + G1, + G2, + Signature, + ShortSignature, + fields: { + Fr, + Fp, + Fp2, + Fp6, + Fp12, + }, + params: { + ateLoopSize: CURVE.params.ateLoopSize, + r: CURVE.params.r, + G1b: CURVE.G1.b, + G2b: CURVE.G2.b, + }, + utils, + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/curve.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/curve.ts new file mode 100644 index 00000000000..6a7830a1970 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/curve.ts @@ -0,0 +1,466 @@ +/** + * Methods for elliptic curve multiplication by scalars. + * Contains wNAF, pippenger + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type IField, nLength, validateField } from './modular.ts' +import { bitLen, bitMask, validateObject } from './utils.ts' + +const _0n = BigInt(0) +const _1n = BigInt(1) + +export type AffinePoint = { + x: T + y: T +} & { z?: never; t?: never } + +export interface Group> { + double(): T + negate(): T + add(other: T): T + subtract(other: T): T + equals(other: T): boolean + multiply(scalar: bigint): T +} + +export type GroupConstructor = { + BASE: T + ZERO: T +} +export type Mapper = (i: T[]) => T[] + +function constTimeNegate>(condition: boolean, item: T): T { + const neg = item.negate() + return condition ? neg : item +} + +function validateW(W: number, bits: number) { + if (!Number.isSafeInteger(W) || W <= 0 || W > bits) + throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W) +} + +/** Internal wNAF opts for specific W and scalarBits */ +export type WOpts = { + windows: number + windowSize: number + mask: bigint + maxNumber: number + shiftBy: bigint +} + +function calcWOpts(W: number, scalarBits: number): WOpts { + validateW(W, scalarBits) + const windows = Math.ceil(scalarBits / W) + 1 // W=8 33. Not 32, because we skip zero + const windowSize = 2 ** (W - 1) // W=8 128. Not 256, because we skip zero + const maxNumber = 2 ** W // W=8 256 + const mask = bitMask(W) // W=8 255 == mask 0b11111111 + const shiftBy = BigInt(W) // W=8 8 + return { windows, windowSize, mask, maxNumber, shiftBy } +} + +function calcOffsets(n: bigint, window: number, wOpts: WOpts) { + const { windowSize, mask, maxNumber, shiftBy } = wOpts + let wbits = Number(n & mask) // extract W bits. + let nextN = n >> shiftBy // shift number by W bits. + + // What actually happens here: + // const highestBit = Number(mask ^ (mask >> 1n)); + // let wbits2 = wbits - 1; // skip zero + // if (wbits2 & highestBit) { wbits2 ^= Number(mask); // (~); + + // split if bits > max: +224 => 256-32 + if (wbits > windowSize) { + // we skip zero, which means instead of `>= size-1`, we do `> size` + wbits -= maxNumber // -32, can be maxNumber - wbits, but then we need to set isNeg here. + nextN += _1n // +256 (carry) + } + const offsetStart = window * windowSize + const offset = offsetStart + Math.abs(wbits) - 1 // -1 because we skip zero + const isZero = wbits === 0 // is current window slice a 0? + const isNeg = wbits < 0 // is current window slice negative? + const isNegF = window % 2 !== 0 // fake random statement for noise + const offsetF = offsetStart // fake offset for noise + return { nextN, offset, isZero, isNeg, isNegF, offsetF } +} + +function validateMSMPoints(points: any[], c: any) { + if (!Array.isArray(points)) throw new Error('array expected') + points.forEach((p, i) => { + if (!(p instanceof c)) throw new Error('invalid point at index ' + i) + }) +} +function validateMSMScalars(scalars: any[], field: any) { + if (!Array.isArray(scalars)) throw new Error('array of scalars expected') + scalars.forEach((s, i) => { + if (!field.isValid(s)) throw new Error('invalid scalar at index ' + i) + }) +} + +// Since points in different groups cannot be equal (different object constructor), +// we can have single place to store precomputes. +// Allows to make points frozen / immutable. +const pointPrecomputes = new WeakMap() +const pointWindowSizes = new WeakMap() + +function getW(P: any): number { + return pointWindowSizes.get(P) || 1 +} + +export type IWNAF> = { + constTimeNegate: >(condition: boolean, item: T) => T + hasPrecomputes(elm: T): boolean + unsafeLadder(elm: T, n: bigint, p?: T): T + precomputeWindow(elm: T, W: number): Group[] + getPrecomputes(W: number, P: T, transform: Mapper): T[] + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc?: T): T + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T + setWindowSize(P: T, W: number): void +} + +/** + * Elliptic curve multiplication of Point by scalar. Fragile. + * Scalars should always be less than curve order: this should be checked inside of a curve itself. + * Creates precomputation tables for fast multiplication: + * - private scalar is split by fixed size windows of W bits + * - every window point is collected from window's table & added to accumulator + * - since windows are different, same point inside tables won't be accessed more than once per calc + * - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar) + * - +1 window is neccessary for wNAF + * - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication + * + * @todo Research returning 2d JS array of windows, instead of a single window. + * This would allow windows to be in different memory locations + */ +export function wNAF>(c: GroupConstructor, bits: number): IWNAF { + return { + constTimeNegate, + + hasPrecomputes(elm: T) { + return getW(elm) !== 1 + }, + + // non-const time multiplication ladder + unsafeLadder(elm: T, n: bigint, p = c.ZERO) { + let d: T = elm + while (n > _0n) { + if (n & _1n) p = p.add(d) + d = d.double() + n >>= _1n + } + return p + }, + + /** + * Creates a wNAF precomputation window. Used for caching. + * Default window size is set by `utils.precompute()` and is equal to 8. + * Number of precomputed points depends on the curve size: + * 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where: + * - 𝑊 is the window size + * - 𝑛 is the bitlength of the curve order. + * For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224. + * @param elm Point instance + * @param W window size + * @returns precomputed point tables flattened to a single array + */ + precomputeWindow(elm: T, W: number): Group[] { + const { windows, windowSize } = calcWOpts(W, bits) + const points: T[] = [] + let p: T = elm + let base = p + for (let window = 0; window < windows; window++) { + base = p + points.push(base) + // i=1, bc we skip 0 + for (let i = 1; i < windowSize; i++) { + base = base.add(p) + points.push(base) + } + p = base.double() + } + return points + }, + + /** + * Implements ec multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @returns real and fake (for const-time) points + */ + wNAF(W: number, precomputes: T[], n: bigint): { p: T; f: T } { + // Smaller version: + // https://github.com/paulmillr/noble-secp256k1/blob/47cb1669b6e506ad66b35fe7d76132ae97465da2/index.ts#L502-L541 + // TODO: check the scalar is less than group order? + // wNAF behavior is undefined otherwise. But have to carefully remove + // other checks before wNAF. ORDER == bits here. + // Accumulators + let p = c.ZERO + let f = c.BASE + // This code was first written with assumption that 'f' and 'p' will never be infinity point: + // since each addition is multiplied by 2 ** W, it cannot cancel each other. However, + // there is negate now: it is possible that negated element from low value + // would be the same as high element, which will create carry into next window. + // It's not obvious how this can fail, but still worth investigating later. + const wo = calcWOpts(W, bits) + for (let window = 0; window < wo.windows; window++) { + // (n === _0n) is handled and not early-exited. isEven and offsetF are used for noise + const { nextN, offset, isZero, isNeg, isNegF, offsetF } = calcOffsets(n, window, wo) + n = nextN + if (isZero) { + // bits are 0: add garbage to fake point + // Important part for const-time getPublicKey: add random "noise" point to f. + f = f.add(constTimeNegate(isNegF, precomputes[offsetF])) + } else { + // bits are 1: add to result point + p = p.add(constTimeNegate(isNeg, precomputes[offset])) + } + } + // Return both real and fake points: JIT won't eliminate f. + // At this point there is a way to F be infinity-point even if p is not, + // which makes it less const-time: around 1 bigint multiply. + return { p, f } + }, + + /** + * Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form. + * @param W window size + * @param precomputes precomputed tables + * @param n scalar (we don't check here, but should be less than curve order) + * @param acc accumulator point to add result of multiplication + * @returns point + */ + wNAFUnsafe(W: number, precomputes: T[], n: bigint, acc: T = c.ZERO): T { + const wo = calcWOpts(W, bits) + for (let window = 0; window < wo.windows; window++) { + if (n === _0n) break // Early-exit, skip 0 value + const { nextN, offset, isZero, isNeg } = calcOffsets(n, window, wo) + n = nextN + if (isZero) { + // Window bits are 0: skip processing. + // Move to next window. + continue + } else { + const item = precomputes[offset] + acc = acc.add(isNeg ? item.negate() : item) // Re-using acc allows to save adds in MSM + } + } + return acc + }, + + getPrecomputes(W: number, P: T, transform: Mapper): T[] { + // Calculate precomputes on a first run, reuse them after + let comp = pointPrecomputes.get(P) + if (!comp) { + comp = this.precomputeWindow(P, W) as T[] + if (W !== 1) pointPrecomputes.set(P, transform(comp)) + } + return comp + }, + + wNAFCached(P: T, n: bigint, transform: Mapper): { p: T; f: T } { + const W = getW(P) + return this.wNAF(W, this.getPrecomputes(W, P, transform), n) + }, + + wNAFCachedUnsafe(P: T, n: bigint, transform: Mapper, prev?: T): T { + const W = getW(P) + if (W === 1) return this.unsafeLadder(P, n, prev) // For W=1 ladder is ~x2 faster + return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev) + }, + + // We calculate precomputes for elliptic curve point multiplication + // using windowed method. This specifies window size and + // stores precomputed values. Usually only base point would be precomputed. + + setWindowSize(P: T, W: number) { + validateW(W, bits) + pointWindowSizes.set(P, W) + pointPrecomputes.delete(P) + }, + } +} + +/** + * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * 30x faster vs naive addition on L=4096, 10x faster than precomputes. + * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL. + * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0. + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @param scalars array of L scalars (aka private keys / bigints) + */ +export function pippenger>( + c: GroupConstructor, + fieldN: IField, + points: T[], + scalars: bigint[], +): T { + // If we split scalars by some window (let's say 8 bits), every chunk will only + // take 256 buckets even if there are 4096 scalars, also re-uses double. + // TODO: + // - https://eprint.iacr.org/2024/750.pdf + // - https://tches.iacr.org/index.php/TCHES/article/view/10287 + // 0 is accepted in scalars + validateMSMPoints(points, c) + validateMSMScalars(scalars, fieldN) + if (points.length !== scalars.length) + throw new Error('arrays of points and scalars must have equal length') + const zero = c.ZERO + const wbits = bitLen(BigInt(points.length)) + const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1 // in bits + const MASK = bitMask(windowSize) + const buckets = new Array(Number(MASK) + 1).fill(zero) // +1 for zero array + const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize + let sum = zero + for (let i = lastBits; i >= 0; i -= windowSize) { + buckets.fill(zero) + for (let j = 0; j < scalars.length; j++) { + const scalar = scalars[j] + const wbits = Number((scalar >> BigInt(i)) & MASK) + buckets[wbits] = buckets[wbits].add(points[j]) + } + let resI = zero // not using this will do small speed-up, but will lose ct + // Skip first bucket, because it is zero + for (let j = buckets.length - 1, sumI = zero; j > 0; j--) { + sumI = sumI.add(buckets[j]) + resI = resI.add(sumI) + } + sum = sum.add(resI) + if (i !== 0) for (let j = 0; j < windowSize; j++) sum = sum.double() + } + return sum as T +} +/** + * Precomputed multi-scalar multiplication (MSM, Pa + Qb + Rc + ...). + * @param c Curve Point constructor + * @param fieldN field over CURVE.N - important that it's not over CURVE.P + * @param points array of L curve points + * @returns function which multiplies points with scaars + */ +export function precomputeMSMUnsafe>( + c: GroupConstructor, + fieldN: IField, + points: T[], + windowSize: number, +): (scalars: bigint[]) => T { + /** + * Performance Analysis of Window-based Precomputation + * + * Base Case (256-bit scalar, 8-bit window): + * - Standard precomputation requires: + * - 31 additions per scalar × 256 scalars = 7,936 ops + * - Plus 255 summary additions = 8,191 total ops + * Note: Summary additions can be optimized via accumulator + * + * Chunked Precomputation Analysis: + * - Using 32 chunks requires: + * - 255 additions per chunk + * - 256 doublings + * - Total: (255 × 32) + 256 = 8,416 ops + * + * Memory Usage Comparison: + * Window Size | Standard Points | Chunked Points + * ------------|-----------------|--------------- + * 4-bit | 520 | 15 + * 8-bit | 4,224 | 255 + * 10-bit | 13,824 | 1,023 + * 16-bit | 557,056 | 65,535 + * + * Key Advantages: + * 1. Enables larger window sizes due to reduced memory overhead + * 2. More efficient for smaller scalar counts: + * - 16 chunks: (16 × 255) + 256 = 4,336 ops + * - ~2x faster than standard 8,191 ops + * + * Limitations: + * - Not suitable for plain precomputes (requires 256 constant doublings) + * - Performance degrades with larger scalar counts: + * - Optimal for ~256 scalars + * - Less efficient for 4096+ scalars (Pippenger preferred) + */ + validateW(windowSize, fieldN.BITS) + validateMSMPoints(points, c) + const zero = c.ZERO + const tableSize = 2 ** windowSize - 1 // table size (without zero) + const chunks = Math.ceil(fieldN.BITS / windowSize) // chunks of item + const MASK = bitMask(windowSize) + const tables = points.map((p: T) => { + const res = [] + for (let i = 0, acc = p; i < tableSize; i++) { + res.push(acc) + acc = acc.add(p) + } + return res + }) + return (scalars: bigint[]): T => { + validateMSMScalars(scalars, fieldN) + if (scalars.length > points.length) + throw new Error('array of scalars must be smaller than array of points') + let res = zero + for (let i = 0; i < chunks; i++) { + // No need to double if accumulator is still zero. + if (res !== zero) for (let j = 0; j < windowSize; j++) res = res.double() + const shiftBy = BigInt(chunks * windowSize - (i + 1) * windowSize) + for (let j = 0; j < scalars.length; j++) { + const n = scalars[j] + const curr = Number((n >> shiftBy) & MASK) + if (!curr) continue // skip zero scalars chunks + res = res.add(tables[j][curr - 1]) + } + } + return res + } +} + +/** + * Generic BasicCurve interface: works even for polynomial fields (BLS): P, n, h would be ok. + * Though generator can be different (Fp2 / Fp6 for BLS). + */ +export type BasicCurve = { + Fp: IField // Field over which we'll do calculations (Fp) + n: bigint // Curve order, total count of valid points in the field + nBitLength?: number // bit length of curve order + nByteLength?: number // byte length of curve order + h: bigint // cofactor. we can assign default=1, but users will just ignore it w/o validation + hEff?: bigint // Number to multiply to clear cofactor + Gx: T // base point X coordinate + Gy: T // base point Y coordinate + allowInfinityPoint?: boolean // bls12-381 requires it. ZERO point is valid, but invalid pubkey +} + +export function validateBasic( + curve: BasicCurve & T, +): Readonly< + { + readonly nBitLength: number + readonly nByteLength: number + } & BasicCurve & + T & { + p: bigint + } +> { + validateField(curve.Fp) + validateObject( + curve, + { + n: 'bigint', + h: 'bigint', + Gx: 'field', + Gy: 'field', + }, + { + nBitLength: 'isSafeInteger', + nByteLength: 'isSafeInteger', + }, + ) + // Set defaults + return Object.freeze({ + ...nLength(curve.n, curve.nBitLength), + ...curve, + ...{ p: curve.Fp.ORDER }, + } as const) +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/edwards.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/edwards.ts new file mode 100644 index 00000000000..79a37fad3f9 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/edwards.ts @@ -0,0 +1,567 @@ +/** + * Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y². + * For design rationale of types / exports, see weierstrass module documentation. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.ts' +import { Field, mod } from './modular.ts' +// prettier-ignore +import { + type FHash, + type Hex, + aInRange, + abool, + bytesToHex, + bytesToNumberLE, + concatBytes, + ensureBytes, + memoized, + numberToBytesLE, + validateObject, +} from './utils.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _8n = BigInt(8) + +/** Edwards curves must declare params a & d. */ +export type CurveType = BasicCurve & { + a: bigint // curve param a + d: bigint // curve param d + hash: FHash // Hashing + randomBytes: (bytesLength?: number) => Uint8Array // CSPRNG + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array // clears bits to get valid field elemtn + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array // Used for hashing + uvRatio?: (u: bigint, v: bigint) => { isValid: boolean; value: bigint } // Ratio √(u/v) + prehash?: FHash // RFC 8032 pre-hashing of messages to sign() / verify() + mapToCurve?: (scalar: bigint[]) => AffinePoint // for hash-to-curve standard +} + +export type CurveTypeWithLength = Readonly + +// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex: +const VERIFY_DEFAULT = { zip215: true } + +function validateOpts(curve: CurveType): CurveTypeWithLength { + const opts = validateBasic(curve) + validateObject( + curve, + { + hash: 'function', + a: 'bigint', + d: 'bigint', + randomBytes: 'function', + }, + { + adjustScalarBytes: 'function', + domain: 'function', + uvRatio: 'function', + mapToCurve: 'function', + }, + ) + // Set defaults + return Object.freeze({ ...opts } as const) +} + +/** Instance of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointType extends Group { + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + get x(): bigint + get y(): bigint + assertValidity(): void + multiply(scalar: bigint): ExtPointType + multiplyUnsafe(scalar: bigint): ExtPointType + isSmallOrder(): boolean + isTorsionFree(): boolean + clearCofactor(): ExtPointType + toAffine(iz?: bigint): AffinePoint + toRawBytes(isCompressed?: boolean): Uint8Array + toHex(isCompressed?: boolean): string + _setWindowSize(windowSize: number): void +} +/** Static methods of Extended Point with coordinates in X, Y, Z, T. */ +export interface ExtPointConstructor extends GroupConstructor { + new (x: bigint, y: bigint, z: bigint, t: bigint): ExtPointType + fromAffine(p: AffinePoint): ExtPointType + fromHex(hex: Hex): ExtPointType + fromPrivateKey(privateKey: Hex): ExtPointType + msm(points: ExtPointType[], scalars: bigint[]): ExtPointType +} + +/** + * Edwards Curve interface. + * Main methods: `getPublicKey(priv)`, `sign(msg, priv)`, `verify(sig, msg, pub)`. + */ +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: Hex) => Uint8Array + sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { context?: Hex; zip215: boolean }, + ) => boolean + ExtendedPoint: ExtPointConstructor + utils: { + randomPrivateKey: () => Uint8Array + getExtendedPublicKey: (key: Hex) => { + head: Uint8Array + prefix: Uint8Array + scalar: bigint + point: ExtPointType + pointBytes: Uint8Array + } + precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType + } +} + +/** + * Creates Twisted Edwards curve with EdDSA signatures. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, d, p, n, Gx, Gy, h + * const curve = twistedEdwards({ a, d, Fp: Field(p), n, Gx, Gy, h }) + */ +export function twistedEdwards(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { + Fp, + n: CURVE_ORDER, + prehash: prehash, + hash: cHash, + randomBytes, + nByteLength, + h: cofactor, + } = CURVE + // Important: + // There are some places where Fp.BYTES is used instead of nByteLength. + // So far, everything has been tested with curves of Fp.BYTES == nByteLength. + // TODO: test and find curves which behave otherwise. + const MASK = _2n << (BigInt(nByteLength * 8) - _1n) + const modP = Fp.create // Function overrides + const Fn = Field(CURVE.n, CURVE.nBitLength) + + // sqrt(u/v) + const uvRatio = + CURVE.uvRatio || + ((u: bigint, v: bigint) => { + try { + return { isValid: true, value: Fp.sqrt(u * Fp.inv(v)) } + } catch (e) { + return { isValid: false, value: _0n } + } + }) + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) // NOOP + const domain = + CURVE.domain || + ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + abool('phflag', phflag) + if (ctx.length || phflag) throw new Error('Contexts/pre-hash are not supported') + return data + }) // NOOP + // 0 <= n < MASK + // Coordinates larger than Fp.ORDER are allowed for zip215 + function aCoordinate(title: string, n: bigint, banZero = false) { + const min = banZero ? _1n : _0n + aInRange('coordinate ' + title, n, min, MASK) + } + + function aextpoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ExtendedPoint expected') + } + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint => { + const { ex: x, ey: y, ez: z } = p + const is0 = p.is0() + if (iz == null) iz = is0 ? _8n : (Fp.inv(z) as bigint) // 8 was chosen arbitrarily + const ax = modP(x * iz) + const ay = modP(y * iz) + const zz = modP(z * iz) + if (is0) return { x: _0n, y: _1n } + if (zz !== _1n) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + const assertValidMemo = memoized((p: Point) => { + const { a, d } = CURVE + if (p.is0()) throw new Error('bad point: ZERO') // TODO: optimize, with vars below? + // Equation in affine coordinates: ax² + y² = 1 + dx²y² + // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y² + const { ex: X, ey: Y, ez: Z, et: T } = p + const X2 = modP(X * X) // X² + const Y2 = modP(Y * Y) // Y² + const Z2 = modP(Z * Z) // Z² + const Z4 = modP(Z2 * Z2) // Z⁴ + const aX2 = modP(X2 * a) // aX² + const left = modP(Z2 * modP(aX2 + Y2)) // (aX² + Y²)Z² + const right = modP(Z4 + modP(d * modP(X2 * Y2))) // Z⁴ + dX²Y² + if (left !== right) throw new Error('bad point: equation left != right (1)') + // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T + const XY = modP(X * Y) + const ZT = modP(Z * T) + if (XY !== ZT) throw new Error('bad point: equation left != right (2)') + return true + }) + + // Extended Point works in extended coordinates: (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). + // https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates + class Point implements ExtPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy)) + static readonly ZERO = new Point(_0n, _1n, _1n, _0n) // 0, 1, 1, 0 + readonly ex: bigint + readonly ey: bigint + readonly ez: bigint + readonly et: bigint + + constructor(ex: bigint, ey: bigint, ez: bigint, et: bigint) { + aCoordinate('x', ex) + aCoordinate('y', ey) + aCoordinate('z', ez, true) + aCoordinate('t', et) + this.ex = ex + this.ey = ey + this.ez = ez + this.et = et + Object.freeze(this) + } + + get x(): bigint { + return this.toAffine().x + } + get y(): bigint { + return this.toAffine().y + } + + static fromAffine(p: AffinePoint): Point { + if (p instanceof Point) throw new Error('extended point not allowed') + const { x, y } = p || {} + aCoordinate('x', x) + aCoordinate('y', y) + return new Point(x, y, _1n, modP(x * y)) + } + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.ez)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + // Not required for fromHex(), which always creates valid points. + // Could be useful for fromAffine(). + assertValidity(): void { + assertValidMemo(this) + } + + // Compare one point to another. + equals(other: Point): boolean { + aextpoint(other) + const { ex: X1, ey: Y1, ez: Z1 } = this + const { ex: X2, ey: Y2, ez: Z2 } = other + const X1Z2 = modP(X1 * Z2) + const X2Z1 = modP(X2 * Z1) + const Y1Z2 = modP(Y1 * Z2) + const Y2Z1 = modP(Y2 * Z1) + return X1Z2 === X2Z1 && Y1Z2 === Y2Z1 + } + + is0(): boolean { + return this.equals(Point.ZERO) + } + + negate(): Point { + // Flips point sign to a negative one (-x, y in affine coords) + return new Point(modP(-this.ex), this.ey, this.ez, modP(-this.et)) + } + + // Fast algo for doubling Extended Point. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd + // Cost: 4M + 4S + 1*a + 6add + 1*2. + double(): Point { + const { a } = CURVE + const { ex: X1, ey: Y1, ez: Z1 } = this + const A = modP(X1 * X1) // A = X12 + const B = modP(Y1 * Y1) // B = Y12 + const C = modP(_2n * modP(Z1 * Z1)) // C = 2*Z12 + const D = modP(a * A) // D = a*A + const x1y1 = X1 + Y1 + const E = modP(modP(x1y1 * x1y1) - A - B) // E = (X1+Y1)2-A-B + const G = D + B // G = D+B + const F = G - C // F = G-C + const H = D - B // H = D-B + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + + // Fast algo for adding 2 Extended Points. + // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd + // Cost: 9M + 1*a + 1*d + 7add. + add(other: Point) { + aextpoint(other) + const { a, d } = CURVE + const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this + const { ex: X2, ey: Y2, ez: Z2, et: T2 } = other + const A = modP(X1 * X2) // A = X1*X2 + const B = modP(Y1 * Y2) // B = Y1*Y2 + const C = modP(T1 * d * T2) // C = T1*d*T2 + const D = modP(Z1 * Z2) // D = Z1*Z2 + const E = modP((X1 + Y1) * (X2 + Y2) - A - B) // E = (X1+Y1)*(X2+Y2)-A-B + const F = D - C // F = D-C + const G = D + C // G = D+C + const H = modP(B - a * A) // H = B-a*A + const X3 = modP(E * F) // X3 = E*F + const Y3 = modP(G * H) // Y3 = G*H + const T3 = modP(E * H) // T3 = E*H + const Z3 = modP(F * G) // Z3 = F*G + return new Point(X3, Y3, Z3, T3) + } + + subtract(other: Point): Point { + return this.add(other.negate()) + } + + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + // Constant-time multiplication. + multiply(scalar: bigint): Point { + const n = scalar + aInRange('scalar', n, _1n, CURVE_ORDER) // 1 <= scalar < L + const { p, f } = this.wNAF(n) + return Point.normalizeZ([p, f])[0] + } + + // Non-constant-time multiplication. Uses double-and-add algorithm. + // It's faster, but should only be used when you don't care about + // an exposed private key e.g. sig verification. + // Does NOT allow scalars higher than CURVE.n. + // Accepts optional accumulator to merge with multiply (important for sparse scalars) + multiplyUnsafe(scalar: bigint, acc = Point.ZERO): Point { + const n = scalar + aInRange('scalar', n, _0n, CURVE_ORDER) // 0 <= scalar < L + if (n === _0n) return I + if (this.is0() || n === _1n) return this + return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc) + } + + // Checks if point is of small order. + // If you add something to small order point, you will have "dirty" + // point with torsion component. + // Multiplies point by cofactor and checks if the result is 0. + isSmallOrder(): boolean { + return this.multiplyUnsafe(cofactor).is0() + } + + // Multiplies point by curve order and checks if the result is 0. + // Returns `false` is the point is dirty. + isTorsionFree(): boolean { + return wnaf.unsafeLadder(this, CURVE_ORDER).is0() + } + + // Converts Extended point to default (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + toAffine(iz?: bigint): AffinePoint { + return toAffineMemo(this, iz) + } + + clearCofactor(): Point { + const { h: cofactor } = CURVE + if (cofactor === _1n) return this + return this.multiplyUnsafe(cofactor) + } + + // Converts hash string or Uint8Array to Point. + // Uses algo from RFC8032 5.1.3. + static fromHex(hex: Hex, zip215 = false): Point { + const { d, a } = CURVE + const len = Fp.BYTES + hex = ensureBytes('pointHex', hex, len) // copy hex to a new array + abool('zip215', zip215) + const normed = hex.slice() // copy again, we'll manipulate it + const lastByte = hex[len - 1] // select last byte + normed[len - 1] = lastByte & ~0x80 // clear last bit + const y = bytesToNumberLE(normed) + + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // RFC8032 prohibits >= p, but ZIP215 doesn't + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + const max = zip215 ? MASK : Fp.ORDER + aInRange('pointHex.y', y, _0n, max) + + // Ed25519: x² = (y²-1)/(dy²+1) mod p. Ed448: x² = (y²-1)/(dy²-1) mod p. Generic case: + // ax²+y²=1+dx²y² => y²-1=dx²y²-ax² => y²-1=x²(dy²-a) => x²=(y²-1)/(dy²-a) + const y2 = modP(y * y) // denominator is always non-0 mod p. + const u = modP(y2 - _1n) // u = y² - 1 + const v = modP(d * y2 - a) // v = d y² + 1. + let { isValid, value: x } = uvRatio(u, v) // √(u/v) + if (!isValid) throw new Error('Point.fromHex: invalid y coordinate') + const isXOdd = (x & _1n) === _1n // There are 2 square roots. Use x_0 bit to select proper + const isLastByteOdd = (lastByte & 0x80) !== 0 // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1') + if (isLastByteOdd !== isXOdd) x = modP(-x) // if x_0 != x mod 2, set x = p-x + return Point.fromAffine({ x, y }) + } + static fromPrivateKey(privKey: Hex): Point { + const { scalar } = getPrivateScalar(privKey) + return G.multiply(scalar) // reduced one call of `toRawBytes` + } + toRawBytes(): Uint8Array { + const { x, y } = this.toAffine() + const bytes = numberToBytesLE(y, Fp.BYTES) // each y has 2 x values (x, -y) + bytes[bytes.length - 1] |= x & _1n ? 0x80 : 0 // when compressing, it's enough to store y + return bytes // and use the last byte to encode sign of x + } + toHex(): string { + return bytesToHex(this.toRawBytes()) // Same as toRawBytes, but returns string. + } + } + const { BASE: G, ZERO: I } = Point + const wnaf = wNAF(Point, nByteLength * 8) + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + // Little-endian SHA512 with modulo n + function modN_LE(hash: Uint8Array): bigint { + return modN(bytesToNumberLE(hash)) + } + + // Get the hashed private scalar per RFC8032 5.1.5 + function getPrivateScalar(key: Hex) { + const len = Fp.BYTES + key = ensureBytes('private key', key, len) + // Hash private key with curve's hash function to produce uniformingly random input + // Check byte lengths: ensure(64, h(ensure(32, key))) + const hashed = ensureBytes('hashed private key', cHash(key), 2 * len) + const head = adjustScalarBytes(hashed.slice(0, len)) // clear first half bits, produce FE + const prefix = hashed.slice(len, 2 * len) // second half is called key prefix (5.1.6) + const scalar = modN_LE(head) // The actual private scalar + return { head, prefix, scalar } + } + + // Convenience method that creates public key from scalar. RFC8032 5.1.5 + function getExtendedPublicKey(key: Hex) { + const { head, prefix, scalar } = getPrivateScalar(key) + const point = G.multiply(scalar) // Point on Edwards curve aka public key + const pointBytes = point.toRawBytes() // Uint8Array representation + return { head, prefix, scalar, point, pointBytes } + } + + // Calculates EdDSA pub key. RFC8032 5.1.5. Privkey is hashed. Use first half with 3 bits cleared + function getPublicKey(privKey: Hex): Uint8Array { + return getExtendedPublicKey(privKey).pointBytes + } + + // int('LE', SHA512(dom2(F, C) || msgs)) mod N + function hashDomainToScalar(context: Hex = new Uint8Array(), ...msgs: Uint8Array[]) { + const msg = concatBytes(...msgs) + return modN_LE(cHash(domain(msg, ensureBytes('context', context), !!prehash))) + } + + /** Signs message with privateKey. RFC8032 5.1.6 */ + function sign(msg: Hex, privKey: Hex, options: { context?: Hex } = {}): Uint8Array { + msg = ensureBytes('message', msg) + if (prehash) msg = prehash(msg) // for ed25519ph etc. + const { prefix, scalar, pointBytes } = getExtendedPublicKey(privKey) + const r = hashDomainToScalar(options.context, prefix, msg) // r = dom2(F, C) || prefix || PH(M) + const R = G.multiply(r).toRawBytes() // R = rG + const k = hashDomainToScalar(options.context, R, pointBytes, msg) // R || A || PH(M) + const s = modN(r + k * scalar) // S = (r + k * s) mod L + aInRange('signature.s', s, _0n, CURVE_ORDER) // 0 <= s < l + const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES)) + return ensureBytes('result', res, Fp.BYTES * 2) // 64-byte signature + } + + const verifyOpts: { context?: Hex; zip215?: boolean } = VERIFY_DEFAULT + + /** + * Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + * An extended group equation is checked. + */ + function verify(sig: Hex, msg: Hex, publicKey: Hex, options = verifyOpts): boolean { + const { context, zip215 } = options + const len = Fp.BYTES // Verifies EdDSA signature against message and public key. RFC8032 5.1.7. + sig = ensureBytes('signature', sig, 2 * len) // An extended group equation is checked. + msg = ensureBytes('message', msg) + publicKey = ensureBytes('publicKey', publicKey, len) + if (zip215 !== undefined) abool('zip215', zip215) + if (prehash) msg = prehash(msg) // for ed25519ph, etc + + const s = bytesToNumberLE(sig.slice(len, 2 * len)) + let A, R, SB + try { + // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5. + // zip215=true: 0 <= y < MASK (2^256 for ed25519) + // zip215=false: 0 <= y < P (2^255-19 for ed25519) + A = Point.fromHex(publicKey, zip215) + R = Point.fromHex(sig.slice(0, len), zip215) + SB = G.multiplyUnsafe(s) // 0 <= s < l is done inside + } catch (error) { + return false + } + if (!zip215 && A.isSmallOrder()) return false + + const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg) + const RkA = R.add(A.multiplyUnsafe(k)) + // Extended group equation + // [8][S]B = [8]R + [8][k]A' + return RkA.subtract(SB).clearCofactor().equals(Point.ZERO) + } + + G._setWindowSize(8) // Enable precomputes. Slows down first publicKey computation by 20ms. + + const utils = { + getExtendedPublicKey, + /** ed25519 priv keys are uniform 32b. No need to check for modulo bias, like in secp256k1. */ + randomPrivateKey: (): Uint8Array => randomBytes(Fp.BYTES), + + /** + * We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT + * values. This slows down first getPublicKey() by milliseconds (see Speed section), + * but allows to speed-up subsequent getPublicKey() calls up to 20x. + * @param windowSize 2, 4, 8, 16 + */ + precompute(windowSize = 8, point: ExtPointType = Point.BASE): ExtPointType { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) + return point + }, + } + + return { + CURVE, + getPublicKey, + sign, + verify, + ExtendedPoint: Point, + utils, + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/hash-to-curve.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/hash-to-curve.ts new file mode 100644 index 00000000000..7ce3aad8cb2 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/hash-to-curve.ts @@ -0,0 +1,262 @@ +/** + * hash-to-curve from RFC 9380. + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * https://www.rfc-editor.org/rfc/rfc9380 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import type { AffinePoint, Group, GroupConstructor } from './curve.ts' +import { type IField, mod } from './modular.ts' +import type { CHash } from './utils.ts' +import { abytes, bytesToNumberBE, concatBytes, utf8ToBytes, validateObject } from './utils.ts' + +export type UnicodeOrBytes = string | Uint8Array + +/** + * * `DST` is a domain separation tag, defined in section 2.2.5 + * * `p` characteristic of F, where F is a finite field of characteristic p and order q = p^m + * * `m` is extension degree (1 for prime fields) + * * `k` is the target security target in bits (e.g. 128), from section 5.1 + * * `expand` is `xmd` (SHA2, SHA3, BLAKE) or `xof` (SHAKE, BLAKE-XOF) + * * `hash` conforming to `utils.CHash` interface, with `outputLen` / `blockLen` props + */ +export type Opts = { + DST: UnicodeOrBytes + p: bigint + m: number + k: number + expand: 'xmd' | 'xof' + hash: CHash +} + +// Octet Stream to Integer. "spec" implementation of os2ip is 2.5x slower vs bytesToNumberBE. +const os2ip = bytesToNumberBE + +// Integer to Octet Stream (numberToBytesBE) +function i2osp(value: number, length: number): Uint8Array { + anum(value) + anum(length) + if (value < 0 || value >= 1 << (8 * length)) throw new Error('invalid I2OSP input: ' + value) + const res = Array.from({ length }).fill(0) as number[] + for (let i = length - 1; i >= 0; i--) { + res[i] = value & 0xff + value >>>= 8 + } + return new Uint8Array(res) +} + +function strxor(a: Uint8Array, b: Uint8Array): Uint8Array { + const arr = new Uint8Array(a.length) + for (let i = 0; i < a.length; i++) { + arr[i] = a[i] ^ b[i] + } + return arr +} + +function anum(item: unknown): void { + if (!Number.isSafeInteger(item)) throw new Error('number expected') +} + +/** + * Produces a uniformly random byte string using a cryptographic hash function H that outputs b bits. + * [RFC 9380 5.3.1](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.1). + */ +export function expand_message_xmd( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + if (DST.length > 255) DST = H(concatBytes(utf8ToBytes('H2C-OVERSIZE-DST-'), DST)) + const { outputLen: b_in_bytes, blockLen: r_in_bytes } = H + const ell = Math.ceil(lenInBytes / b_in_bytes) + if (lenInBytes > 65535 || ell > 255) throw new Error('expand_message_xmd: invalid lenInBytes') + 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) // len_in_bytes_str + const b = new Array(ell) + const b_0 = H(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime)) + b[0] = 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] = H(concatBytes(...args)) + } + const pseudo_random_bytes = concatBytes(...b) + return pseudo_random_bytes.slice(0, lenInBytes) +} + +/** + * Produces a uniformly random byte string using an extendable-output function (XOF) H. + * 1. The collision resistance of H MUST be at least k bits. + * 2. H MUST be an XOF that has been proved indifferentiable from + * a random oracle under a reasonable cryptographic assumption. + * [RFC 9380 5.3.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.3.2). + */ +export function expand_message_xof( + msg: Uint8Array, + DST: Uint8Array, + lenInBytes: number, + k: number, + H: CHash, +): Uint8Array { + abytes(msg) + abytes(DST) + anum(lenInBytes) + // https://www.rfc-editor.org/rfc/rfc9380#section-5.3.3 + // DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8)); + if (DST.length > 255) { + const dkLen = Math.ceil((2 * k) / 8) + DST = H.create({ dkLen }).update(utf8ToBytes('H2C-OVERSIZE-DST-')).update(DST).digest() + } + if (lenInBytes > 65535 || DST.length > 255) + throw new Error('expand_message_xof: invalid lenInBytes') + return ( + H.create({ dkLen: lenInBytes }) + .update(msg) + .update(i2osp(lenInBytes, 2)) + // 2. DST_prime = DST || I2OSP(len(DST), 1) + .update(DST) + .update(i2osp(DST.length, 1)) + .digest() + ) +} + +/** + * Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F. + * [RFC 9380 5.2](https://www.rfc-editor.org/rfc/rfc9380#section-5.2). + * @param msg a byte string containing the message to hash + * @param count the number of elements of F to output + * @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`, see above + * @returns [u_0, ..., u_(count - 1)], a list of field elements. + */ +export function hash_to_field(msg: Uint8Array, count: number, options: Opts): bigint[][] { + validateObject(options, { + DST: 'stringOrUint8Array', + p: 'bigint', + m: 'isSafeInteger', + k: 'isSafeInteger', + hash: 'hash', + }) + const { p, k, m, hash, expand, DST: _DST } = options + abytes(msg) + anum(count) + const DST = typeof _DST === 'string' ? utf8ToBytes(_DST) : _DST + const log2p = p.toString(2).length + const L = Math.ceil((log2p + k) / 8) // section 5.1 of ietf draft link above + const len_in_bytes = count * m * L + let prb // pseudo_random_bytes + if (expand === 'xmd') { + prb = expand_message_xmd(msg, DST, len_in_bytes, hash) + } else if (expand === 'xof') { + prb = expand_message_xof(msg, DST, len_in_bytes, k, hash) + } else if (expand === '_internal_pass') { + // for internal tests only + prb = msg + } else { + throw new Error('expand must be "xmd" or "xof"') + } + const u = new Array(count) + for (let i = 0; i < count; i++) { + const e = new Array(m) + for (let j = 0; j < m; j++) { + const elm_offset = L * (j + i * m) + const tv = prb.subarray(elm_offset, elm_offset + L) + e[j] = mod(os2ip(tv), p) + } + u[i] = e + } + return u +} + +export type XY = ( + x: T, + y: T, +) => { + x: T + y: T +} +export function isogenyMap>(field: F, map: [T[], T[], T[], T[]]): XY { + // Make same order as in spec + const COEFF = map.map((i) => Array.from(i).reverse()) + return (x: T, y: T) => { + const [xNum, xDen, yNum, yDen] = COEFF.map((val) => + val.reduce((acc, i) => field.add(field.mul(acc, x), i)), + ) + console.log(x) + if (field.is0(xDen) || field.is0(yDen)) throw new Error('bad point: ZERO') + x = field.div(xNum, xDen) // xNum / xDen + y = field.mul(y, field.div(yNum, yDen)) // y * (yNum / yDev) + return { x: x, y: y } + } +} + +/** Point interface, which curves must implement to work correctly with the module. */ +export interface H2CPoint extends Group> { + add(rhs: H2CPoint): H2CPoint + toAffine(iz?: bigint): AffinePoint + clearCofactor(): H2CPoint + assertValidity(): void +} + +export interface H2CPointConstructor extends GroupConstructor> { + fromAffine(ap: AffinePoint): H2CPoint +} + +export type MapToCurve = (scalar: bigint[]) => AffinePoint + +// Separated from initialization opts, so users won't accidentally change per-curve parameters +// (changing DST is ok!) +export type htfBasicOpts = { DST: UnicodeOrBytes } +export type HTFMethod = (msg: Uint8Array, options?: htfBasicOpts) => H2CPoint +export type MapMethod = (scalars: bigint[]) => H2CPoint +export type Hasher = { + hashToCurve: HTFMethod + encodeToCurve: HTFMethod + mapToCurve: MapMethod + defaults: Opts & { encodeDST?: UnicodeOrBytes } +} + +/** Creates hash-to-curve methods from EC Point and mapToCurve function. */ +export function createHasher( + Point: H2CPointConstructor, + mapToCurve: MapToCurve, + defaults: Opts & { encodeDST?: UnicodeOrBytes }, +): Hasher { + if (typeof mapToCurve !== 'function') throw new Error('mapToCurve() must be defined') + return { + defaults, + + // Encodes byte string to elliptic curve. + // hash_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + hashToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 2, { ...defaults, DST: defaults.DST, ...options } as Opts) + const u0 = Point.fromAffine(mapToCurve(u[0])) + const u1 = Point.fromAffine(mapToCurve(u[1])) + const P = u0.add(u1).clearCofactor() + P.assertValidity() + return P + }, + + // Encodes byte string to elliptic curve. + // encode_to_curve from https://www.rfc-editor.org/rfc/rfc9380#section-3 + encodeToCurve(msg: Uint8Array, options?: htfBasicOpts): H2CPoint { + const u = hash_to_field(msg, 1, { ...defaults, DST: defaults.encodeDST, ...options } as Opts) + const P = Point.fromAffine(mapToCurve(u[0])).clearCofactor() + P.assertValidity() + return P + }, + // Same as encodeToCurve, but without hash + mapToCurve(scalars: bigint[]): H2CPoint { + if (!Array.isArray(scalars)) throw new Error('mapToCurve: expected array of bigints') + for (const i of scalars) + if (typeof i !== 'bigint') throw new Error('mapToCurve: expected array of bigints') + const P = Point.fromAffine(mapToCurve(scalars)).clearCofactor() + P.assertValidity() + return P + }, + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/modular.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/modular.ts new file mode 100644 index 00000000000..8c0b703e745 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/modular.ts @@ -0,0 +1,555 @@ +/** + * Utils for modular division and finite fields. + * A finite field over 11 is integer number operations `mod 11`. + * There is no division: it is replaced by modular multiplicative inverse. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { + bitMask, + bytesToNumberBE, + bytesToNumberLE, + ensureBytes, + numberToBytesBE, + numberToBytesLE, + validateObject, +} from './utils.ts' + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = /* @__PURE__ */ BigInt(2), + _3n = /* @__PURE__ */ BigInt(3) +// prettier-ignore +const _4n = /* @__PURE__ */ BigInt(4), + _5n = /* @__PURE__ */ BigInt(5), + _8n = /* @__PURE__ */ BigInt(8) +// prettier-ignore +const _9n = /* @__PURE__ */ BigInt(9), + _16n = /* @__PURE__ */ BigInt(16) + +// Calculates a modulo b +export function mod(a: bigint, b: bigint): bigint { + const result = a % b + return result >= _0n ? result : b + result +} +/** + * Efficiently raise num to power and do modular division. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + * @todo use field version && remove + * @example + * pow(2n, 6n, 11n) // 64n % 11n == 9n + */ +export function pow(num: bigint, power: bigint, modulo: bigint): bigint { + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (modulo <= _0n) throw new Error('invalid modulus') + 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 +} + +/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */ +export function pow2(x: bigint, power: bigint, modulo: bigint): bigint { + let res = x + while (power-- > _0n) { + res *= res + res %= modulo + } + return res +} + +/** + * Inverses number over modulo. + * Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/). + */ +export function invert(number: bigint, modulo: bigint): bigint { + if (number === _0n) throw new Error('invert: expected non-zero number') + if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo) + // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower. + let a = mod(number, modulo) + let b = modulo + // prettier-ignore + let x = _0n, + y = _1n, + u = _1n, + v = _0n + while (a !== _0n) { + // JIT applies optimization if those two lines follow each other + const q = b / a + const r = b % a + const m = x - u * q + const n = y - v * q + // prettier-ignore + ;(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) +} + +/** + * Tonelli-Shanks square root search algorithm. + * 1. https://eprint.iacr.org/2012/685.pdf (page 12) + * 2. Square Roots from 1; 24, 51, 10 to Dan Shanks + * Will start an infinite loop if field order P is not prime. + * @param P field order + * @returns function that takes field Fp (created from P) and number n + */ +export function tonelliShanks(P: bigint): (Fp: IField, n: T) => T { + // Legendre constant: used to calculate Legendre symbol (a | p), + // which denotes the value of a^((p-1)/2) (mod p). + // (a | p) ≡ 1 if a is a square (mod p) + // (a | p) ≡ -1 if a is not a square (mod p) + // (a | p) ≡ 0 if a ≡ 0 (mod p) + const legendreC = (P - _1n) / _2n + + let Q: bigint, S: number, Z: bigint + // Step 1: By factoring out powers of 2 from p - 1, + // find q and s such that p - 1 = q*(2^s) with q odd + for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++); + + // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq + for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) { + // Crash instead of infinity loop, we cannot reasonable count until P. + if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P') + } + + // Fast-path + if (S === 1) { + const p1div4 = (P + _1n) / _4n + return function tonelliFast(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Slow-path + const Q1div2 = (Q + _1n) / _2n + return function tonelliSlow(Fp: IField, n: T): T { + // Step 0: Check that n is indeed a square: (n | p) should not be ≡ -1 + if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE)) throw new Error('Cannot find square root') + let r = S + // TODO: will fail at Fp2/etc + let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q) // will update both x and b + let x = Fp.pow(n, Q1div2) // first guess at the square root + let b = Fp.pow(n, Q) // first guess at the fudge factor + + while (!Fp.eql(b, Fp.ONE)) { + if (Fp.eql(b, Fp.ZERO)) return Fp.ZERO // https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm (4. If t = 0, return r = 0) + // Find m such b^(2^m)==1 + let m = 1 + for (let t2 = Fp.sqr(b); m < r; m++) { + if (Fp.eql(t2, Fp.ONE)) break + t2 = Fp.sqr(t2) // t2 *= t2 + } + // NOTE: r-m-1 can be bigger than 32, need to convert to bigint before shift, otherwise there will be overflow + const ge = Fp.pow(g, _1n << BigInt(r - m - 1)) // ge = 2^(r-m-1) + g = Fp.sqr(ge) // g = ge * ge + x = Fp.mul(x, ge) // x *= ge + b = Fp.mul(b, g) // b *= g + r = m + } + return x + } +} + +/** + * Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4: + * + * 1. P ≡ 3 (mod 4) + * 2. P ≡ 5 (mod 8) + * 3. P ≡ 9 (mod 16) + * 4. Tonelli-Shanks algorithm + * + * Different algorithms can give different roots, it is up to user to decide which one they want. + * For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve). + */ +export function FpSqrt(P: bigint): (Fp: IField, n: T) => T { + // P ≡ 3 (mod 4) + // √n = n^((P+1)/4) + if (P % _4n === _3n) { + // Not all roots possible! + // const ORDER = + // 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn; + // const NUM = 72057594037927816n; + const p1div4 = (P + _1n) / _4n + return function sqrt3mod4(Fp: IField, n: T) { + const root = Fp.pow(n, p1div4) + // Throw if root**2 != n + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10) + if (P % _8n === _5n) { + const c1 = (P - _5n) / _8n + return function sqrt5mod8(Fp: IField, n: T) { + const n2 = Fp.mul(n, _2n) + const v = Fp.pow(n2, c1) + const nv = Fp.mul(n, v) + const i = Fp.mul(Fp.mul(nv, _2n), v) + const root = Fp.mul(nv, Fp.sub(i, Fp.ONE)) + if (!Fp.eql(Fp.sqr(root), n)) throw new Error('Cannot find square root') + return root + } + } + + // P ≡ 9 (mod 16) + if (P % _16n === _9n) { + // NOTE: tonelli is too slow for bls-Fp2 calculations even on start + // Means we cannot use sqrt for constants at all! + // + // const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F + // const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F + // const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F + // const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic + // sqrt = (x) => { + // let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4 + // let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1 + // const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1 + // let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1 + // const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x + // const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x + // tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x + // tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x + // const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x + // return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2 + // } + } + // Other cases: Tonelli-Shanks algorithm + return tonelliShanks(P) +} + +// Little-endian check for first LE bit (last BE bit); +export const isNegativeLE = (num: bigint, modulo: bigint): boolean => + (mod(num, modulo) & _1n) === _1n + +/** Field is not always over prime: for example, Fp2 has ORDER(q)=p^m. */ +export interface IField { + ORDER: bigint + isLE: boolean + BYTES: number + BITS: number + MASK: bigint + ZERO: T + ONE: T + // 1-arg + create: (num: T) => T + isValid: (num: T) => boolean + is0: (num: T) => boolean + neg(num: T): T + inv(num: T): T + sqrt(num: T): T + sqr(num: T): T + // 2-args + eql(lhs: T, rhs: T): boolean + add(lhs: T, rhs: T): T + sub(lhs: T, rhs: T): T + mul(lhs: T, rhs: T | bigint): T + pow(lhs: T, power: bigint): T + div(lhs: T, rhs: T | bigint): T + // N for NonNormalized (for now) + addN(lhs: T, rhs: T): T + subN(lhs: T, rhs: T): T + mulN(lhs: T, rhs: T | bigint): T + sqrN(num: T): T + + // Optional + // Should be same as sgn0 function in + // [RFC9380](https://www.rfc-editor.org/rfc/rfc9380#section-4.1). + // NOTE: sgn0 is 'negative in LE', which is same as odd. And negative in LE is kinda strange definition anyway. + isOdd?(num: T): boolean // Odd instead of even since we have it for Fp2 + // legendre?(num: T): T; + pow(lhs: T, power: bigint): T + invertBatch: (lst: T[]) => T[] + toBytes(num: T): Uint8Array + fromBytes(bytes: Uint8Array): T + // If c is False, CMOV returns a, otherwise it returns b. + cmov(a: T, b: T, c: boolean): T +} +// prettier-ignore +const FIELD_FIELDS = [ + 'create', + 'isValid', + 'is0', + 'neg', + 'inv', + 'sqrt', + 'sqr', + 'eql', + 'add', + 'sub', + 'mul', + 'pow', + 'div', + 'addN', + 'subN', + 'mulN', + 'sqrN', +] as const +export function validateField(field: IField): IField { + const initial = { + ORDER: 'bigint', + MASK: 'bigint', + BYTES: 'isSafeInteger', + BITS: 'isSafeInteger', + } as Record + const opts = FIELD_FIELDS.reduce((map, val: string) => { + map[val] = 'function' + return map + }, initial) + return validateObject(field, opts) +} + +// Generic field functions + +/** + * Same as `pow` but for Fp: non-constant-time. + * Unsafe in some contexts: uses ladder, so can expose bigint bits. + */ +export function FpPow(f: IField, num: T, power: bigint): T { + // Should have same speed as pow for bigints + // TODO: benchmark! + if (power < _0n) throw new Error('invalid exponent, negatives unsupported') + if (power === _0n) return f.ONE + if (power === _1n) return num + let p = f.ONE + let d = num + while (power > _0n) { + if (power & _1n) p = f.mul(p, d) + d = f.sqr(d) + power >>= _1n + } + return p +} + +/** + * Efficiently invert an array of Field elements. + * `inv(0)` will return `undefined` here: make sure to throw an error. + */ +export function FpInvertBatch(f: IField, nums: T[]): T[] { + const tmp = new Array(nums.length) + // Walk from first to last, multiply them by each other MOD p + const lastMultiplied = nums.reduce((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = acc + return f.mul(acc, num) + }, f.ONE) + // Invert last element + const inverted = f.inv(lastMultiplied) + // Walk from last to first, multiply them by inverted each other MOD p + nums.reduceRight((acc, num, i) => { + if (f.is0(num)) return acc + tmp[i] = f.mul(acc, tmp[i]) + return f.mul(acc, num) + }, inverted) + return tmp +} + +export function FpDiv(f: IField, lhs: T, rhs: T | bigint): T { + return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.inv(rhs)) +} + +/** + * Legendre symbol. + * * (a | p) ≡ 1 if a is a square (mod p), quadratic residue + * * (a | p) ≡ -1 if a is not a square (mod p), quadratic non residue + * * (a | p) ≡ 0 if a ≡ 0 (mod p) + */ +export function FpLegendre(order: bigint): (f: IField, x: T) => T { + const legendreConst = (order - _1n) / _2n // Integer arithmetic + return (f: IField, x: T): T => f.pow(x, legendreConst) +} + +// This function returns True whenever the value x is a square in the field F. +export function FpIsSquare(f: IField): (x: T) => boolean { + const legendre = FpLegendre(f.ORDER) + return (x: T): boolean => { + const p = legendre(f, x) + return f.eql(p, f.ZERO) || f.eql(p, f.ONE) + } +} + +// CURVE.n lengths +export function nLength( + n: bigint, + nBitLength?: number, +): { + nBitLength: number + nByteLength: number +} { + // Bit size, byte size of CURVE.n + const _nBitLength = nBitLength !== undefined ? nBitLength : n.toString(2).length + const nByteLength = Math.ceil(_nBitLength / 8) + return { nBitLength: _nBitLength, nByteLength } +} + +type FpField = IField & Required, 'isOdd'>> +/** + * Initializes a finite field over prime. + * Major performance optimizations: + * * a) denormalized operations like mulN instead of mul + * * b) same object shape: never add or remove keys + * * c) Object.freeze + * Fragile: always run a benchmark on a change. + * Security note: operations don't check 'isValid' for all elements for performance reasons, + * it is caller responsibility to check this. + * This is low-level code, please make sure you know what you're doing. + * @param ORDER prime positive bigint + * @param bitLen how many bits the field consumes + * @param isLE (def: false) if encoding / decoding should be in little-endian + * @param redef optional faster redefinitions of sqrt and other methods + */ +export function Field( + ORDER: bigint, + bitLen?: number, + isLE = false, + redef: Partial> = {}, +): Readonly { + if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER) + const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen) + if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes') + let sqrtP: ReturnType // cached sqrtP + const f: Readonly = Object.freeze({ + ORDER, + isLE, + BITS, + BYTES, + MASK: bitMask(BITS), + ZERO: _0n, + ONE: _1n, + create: (num) => mod(num, ORDER), + isValid: (num) => { + if (typeof num !== 'bigint') + throw new Error('invalid field element: expected bigint, got ' + typeof num) + return _0n <= num && num < ORDER // 0 is valid element, but it's not invertible + }, + is0: (num) => num === _0n, + isOdd: (num) => (num & _1n) === _1n, + neg: (num) => mod(-num, ORDER), + eql: (lhs, rhs) => lhs === rhs, + + sqr: (num) => mod(num * num, ORDER), + add: (lhs, rhs) => mod(lhs + rhs, ORDER), + sub: (lhs, rhs) => mod(lhs - rhs, ORDER), + mul: (lhs, rhs) => mod(lhs * rhs, ORDER), + pow: (num, power) => FpPow(f, num, power), + div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER), + + // Same as above, but doesn't normalize + sqrN: (num) => num * num, + addN: (lhs, rhs) => lhs + rhs, + subN: (lhs, rhs) => lhs - rhs, + mulN: (lhs, rhs) => lhs * rhs, + + inv: (num) => invert(num, ORDER), + sqrt: + redef.sqrt || + ((n) => { + if (!sqrtP) sqrtP = FpSqrt(ORDER) + return sqrtP(f, n) + }), + invertBatch: (lst) => FpInvertBatch(f, lst), + // TODO: do we really need constant cmov? + // We don't have const-time bigints anyway, so probably will be not very useful + cmov: (a, b, c) => (c ? b : a), + toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)), + fromBytes: (bytes) => { + if (bytes.length !== BYTES) + throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length) + return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes) + }, + } as FpField) + return Object.freeze(f) +} + +export function FpSqrtOdd(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? root : Fp.neg(root) +} + +export function FpSqrtEven(Fp: IField, elm: T): T { + if (!Fp.isOdd) throw new Error("Field doesn't have isOdd") + const root = Fp.sqrt(elm) + return Fp.isOdd(root) ? Fp.neg(root) : root +} + +/** + * "Constant-time" private key generation utility. + * Same as mapKeyToField, but accepts less bytes (40 instead of 48 for 32-byte field). + * Which makes it slightly more biased, less secure. + * @deprecated use `mapKeyToField` instead + */ +export function hashToPrivateScalar( + hash: string | Uint8Array, + groupOrder: bigint, + isLE = false, +): bigint { + hash = ensureBytes('privateHash', hash) + const hashLen = hash.length + const minLen = nLength(groupOrder).nByteLength + 8 + if (minLen < 24 || hashLen < minLen || hashLen > 1024) + throw new Error( + 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen, + ) + const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash) + return mod(num, groupOrder - _1n) + _1n +} + +/** + * Returns total number of bytes consumed by the field element. + * For example, 32 bytes for usual 256-bit weierstrass curve. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of field + */ +export function getFieldBytesLength(fieldOrder: bigint): number { + if (typeof fieldOrder !== 'bigint') throw new Error('field order must be bigint') + const bitLength = fieldOrder.toString(2).length + return Math.ceil(bitLength / 8) +} + +/** + * Returns minimal amount of bytes that can be safely reduced + * by field order. + * Should be 2^-128 for 128-bit curve such as P256. + * @param fieldOrder number of field elements, usually CURVE.n + * @returns byte length of target hash + */ +export function getMinHashLength(fieldOrder: bigint): number { + const length = getFieldBytesLength(fieldOrder) + return length + Math.ceil(length / 2) +} + +/** + * "Constant-time" private key generation utility. + * Can take (n + n/2) or more bytes of uniform input e.g. from CSPRNG or KDF + * and convert them into private scalar, with the modulo bias being negligible. + * Needs at least 48 bytes of input for 32-byte private key. + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final + * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5 + * @param hash hash output from SHA3 or a similar function + * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n) + * @param isLE interpret hash bytes as LE num + * @returns valid private scalar + */ +export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false): Uint8Array { + const len = key.length + const fieldLen = getFieldBytesLength(fieldOrder) + const minLen = getMinHashLength(fieldOrder) + // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings. + if (len < 16 || len < minLen || len > 1024) + throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len) + const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key) + // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0 + const reduced = mod(num, fieldOrder - _1n) + _1n + return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen) +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/montgomery.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/montgomery.ts new file mode 100644 index 00000000000..122406e3350 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/montgomery.ts @@ -0,0 +1,190 @@ +/** + * Montgomery curve methods. It's not really whole montgomery curve, + * just bunch of very specific methods for X25519 / X448 from + * [RFC 7748](https://www.rfc-editor.org/rfc/rfc7748) + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { mod, pow } from './modular.ts' +import { aInRange, bytesToNumberLE, ensureBytes, numberToBytesLE, validateObject } from './utils.ts' + +const _0n = BigInt(0) +const _1n = BigInt(1) +type Hex = string | Uint8Array + +export type CurveType = { + P: bigint // finite field prime + nByteLength: number + adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array + domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array + a: bigint + montgomeryBits: number + powPminus2?: (x: bigint) => bigint + xyToU?: (x: bigint, y: bigint) => bigint + Gu: bigint + randomBytes?: (bytesLength?: number) => Uint8Array +} + +export type CurveFn = { + scalarMult: (scalar: Hex, u: Hex) => Uint8Array + scalarMultBase: (scalar: Hex) => Uint8Array + getSharedSecret: (privateKeyA: Hex, publicKeyB: Hex) => Uint8Array + getPublicKey: (privateKey: Hex) => Uint8Array + utils: { randomPrivateKey: () => Uint8Array } + GuBytes: Uint8Array +} + +function validateOpts(curve: CurveType) { + validateObject( + curve, + { + a: 'bigint', + }, + { + montgomeryBits: 'isSafeInteger', + nByteLength: 'isSafeInteger', + adjustScalarBytes: 'function', + domain: 'function', + powPminus2: 'function', + Gu: 'bigint', + }, + ) + // Set defaults + return Object.freeze({ ...curve } as const) +} + +// Uses only one coordinate instead of two +export function montgomery(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) + const { P } = CURVE + const modP = (n: bigint) => mod(n, P) + const montgomeryBits = CURVE.montgomeryBits + const montgomeryBytes = Math.ceil(montgomeryBits / 8) + const fieldLen = CURVE.nByteLength + const adjustScalarBytes = CURVE.adjustScalarBytes || ((bytes: Uint8Array) => bytes) + const powPminus2 = CURVE.powPminus2 || ((x: bigint) => pow(x, P - BigInt(2), P)) + + // cswap from RFC7748. But it is not from RFC7748! + /* + cswap(swap, x_2, x_3): + dummy = mask(swap) AND (x_2 XOR x_3) + x_2 = x_2 XOR dummy + x_3 = x_3 XOR dummy + Return (x_2, x_3) + Where mask(swap) is the all-1 or all-0 word of the same length as x_2 + and x_3, computed, e.g., as mask(swap) = 0 - swap. + */ + function cswap(swap: bigint, x_2: bigint, x_3: bigint): [bigint, bigint] { + const dummy = modP(swap * (x_2 - x_3)) + x_2 = modP(x_2 - dummy) + x_3 = modP(x_3 + dummy) + return [x_2, x_3] + } + + // x25519 from 4 + // The constant a24 is (486662 - 2) / 4 = 121665 for curve25519/X25519 + const a24 = (CURVE.a - BigInt(2)) / BigInt(4) + /** + * + * @param pointU u coordinate (x) on Montgomery Curve 25519 + * @param scalar by which the point would be multiplied + * @returns new Point on Montgomery curve + */ + function montgomeryLadder(u: bigint, scalar: bigint): bigint { + aInRange('u', u, _0n, P) + aInRange('scalar', scalar, _0n, P) + // Section 5: Implementations MUST accept non-canonical values and process them as + // if they had been reduced modulo the field prime. + const k = scalar + const x_1 = u + let x_2 = _1n + let z_2 = _0n + let x_3 = u + let z_3 = _1n + let swap = _0n + let sw: [bigint, bigint] + for (let t = BigInt(montgomeryBits - 1); t >= _0n; t--) { + const k_t = (k >> t) & _1n + swap ^= k_t + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + swap = k_t + + const A = x_2 + z_2 + const AA = modP(A * A) + const B = x_2 - z_2 + const BB = modP(B * B) + const E = AA - BB + const C = x_3 + z_3 + const D = x_3 - z_3 + const DA = modP(D * A) + const CB = modP(C * B) + const dacb = DA + CB + const da_cb = DA - CB + x_3 = modP(dacb * dacb) + z_3 = modP(x_1 * modP(da_cb * da_cb)) + x_2 = modP(AA * BB) + z_2 = modP(E * (AA + modP(a24 * E))) + } + // (x_2, x_3) = cswap(swap, x_2, x_3) + sw = cswap(swap, x_2, x_3) + x_2 = sw[0] + x_3 = sw[1] + // (z_2, z_3) = cswap(swap, z_2, z_3) + sw = cswap(swap, z_2, z_3) + z_2 = sw[0] + z_3 = sw[1] + // z_2^(p - 2) + const z2 = powPminus2(z_2) + // Return x_2 * (z_2^(p - 2)) + return modP(x_2 * z2) + } + + function encodeUCoordinate(u: bigint): Uint8Array { + return numberToBytesLE(modP(u), montgomeryBytes) + } + + function decodeUCoordinate(uEnc: Hex): bigint { + // Section 5: When receiving such an array, implementations of X25519 + // MUST mask the most significant bit in the final byte. + const u = ensureBytes('u coordinate', uEnc, montgomeryBytes) + if (fieldLen === 32) u[31] &= 127 // 0b0111_1111 + return bytesToNumberLE(u) + } + function decodeScalar(n: Hex): bigint { + const bytes = ensureBytes('scalar', n) + const len = bytes.length + if (len !== montgomeryBytes && len !== fieldLen) { + let valid = '' + montgomeryBytes + ' or ' + fieldLen + throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len) + } + return bytesToNumberLE(adjustScalarBytes(bytes)) + } + function scalarMult(scalar: Hex, u: Hex): Uint8Array { + const pointU = decodeUCoordinate(u) + const _scalar = decodeScalar(scalar) + const pu = montgomeryLadder(pointU, _scalar) + // The result was not contributory + // https://cr.yp.to/ecdh.html#validate + if (pu === _0n) throw new Error('invalid private or public key received') + return encodeUCoordinate(pu) + } + // Computes public key from private. By doing scalar multiplication of base point. + const GuBytes = encodeUCoordinate(CURVE.Gu) + function scalarMultBase(scalar: Hex): Uint8Array { + return scalarMult(scalar, GuBytes) + } + + return { + scalarMult, + scalarMultBase, + getSharedSecret: (privateKey: Hex, publicKey: Hex) => scalarMult(privateKey, publicKey), + getPublicKey: (privateKey: Hex): Uint8Array => scalarMultBase(privateKey), + utils: { randomPrivateKey: () => CURVE.randomBytes!(CURVE.nByteLength) }, + GuBytes: GuBytes, + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/poseidon.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/poseidon.ts new file mode 100644 index 00000000000..6edaad90986 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/poseidon.ts @@ -0,0 +1,329 @@ +/** + * Implements [Poseidon](https://www.poseidon-hash.info) ZK-friendly hash. + * + * There are many poseidon variants with different constants. + * We don't provide them: you should construct them manually. + * Check out [micro-starknet](https://github.com/paulmillr/micro-starknet) package for a proper example. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { FpPow, type IField, validateField } from './modular.ts' +import { bitGet } from './utils.ts' + +// Grain LFSR (Linear-Feedback Shift Register): https://eprint.iacr.org/2009/109.pdf +function grainLFSR(state: number[]): () => boolean { + let pos = 0 + if (state.length !== 80) throw new Error('grainLFRS: wrong state length, should be 80 bits') + const getBit = (): boolean => { + const r = (offset: number) => state[(pos + offset) % 80] + const bit = r(62) ^ r(51) ^ r(38) ^ r(23) ^ r(13) ^ r(0) + state[pos] = bit + pos = ++pos % 80 + return !!bit + } + for (let i = 0; i < 160; i++) getBit() + return () => { + // https://en.wikipedia.org/wiki/Shrinking_generator + while (true) { + const b1 = getBit() + const b2 = getBit() + if (!b1) continue + return b2 + } + } +} + +export type PoseidonBasicOpts = { + Fp: IField + t: number // t = rate + capacity + roundsFull: number + roundsPartial: number + isSboxInverse?: boolean +} + +function validateBasicOpts(opts: PoseidonBasicOpts) { + const { Fp, roundsFull } = opts + validateField(Fp) + for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + if (opts.isSboxInverse !== undefined && typeof opts.isSboxInverse !== 'boolean') + throw new Error(`Poseidon: invalid param isSboxInverse=${opts.isSboxInverse}`) + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) +} + +function poseidonGrain(opts: PoseidonBasicOpts) { + validateBasicOpts(opts) + const { Fp } = opts + const state = Array(80).fill(1) + let pos = 0 + const writeBits = (value: bigint, bitCount: number) => { + for (let i = bitCount - 1; i >= 0; i--) state[pos++] = Number(bitGet(value, i)) + } + writeBits(1n, 2) // prime field + writeBits(opts.isSboxInverse ? 1n : 0n, 4) // b2..b5 + writeBits(BigInt(Fp.BITS), 12) // b6..b17 + writeBits(BigInt(opts.t), 12) // b18..b29 + writeBits(BigInt(opts.roundsFull), 10) // b30..b39 + writeBits(BigInt(opts.roundsPartial), 10) // b40..b49 + + const getBit = grainLFSR(state) + return (count: number, reject: boolean): bigint[] => { + const res: bigint[] = [] + for (let i = 0; i < count; i++) { + while (true) { + let num = 0n + for (let i = 0; i < Fp.BITS; i++) { + num <<= 1n + if (getBit()) num |= 1n + } + if (reject && num >= Fp.ORDER) continue // rejection sampling + res.push(Fp.create(num)) + break + } + } + return res + } +} + +export type PoseidonGrainOpts = PoseidonBasicOpts & { + sboxPower?: number +} + +type PoseidonConstants = { mds: bigint[][]; roundConstants: bigint[][] } + +// NOTE: this is not standard but used often for constant generation for poseidon +// (grain LFRS-like structure) +export function grainGenConstants(opts: PoseidonGrainOpts, skipMDS: number = 0): PoseidonConstants { + const { Fp, t, roundsFull, roundsPartial } = opts + const rounds = roundsFull + roundsPartial + const sample = poseidonGrain(opts) + const roundConstants: bigint[][] = [] + for (let r = 0; r < rounds; r++) roundConstants.push(sample(t, true)) + if (skipMDS > 0) for (let i = 0; i < skipMDS; i++) sample(2 * t, false) + const xs = sample(t, false) + const ys = sample(t, false) + // Construct MDS Matrix M[i][j] = 1 / (xs[i] + ys[j]) + const mds: bigint[][] = [] + for (let i = 0; i < t; i++) { + const row: bigint[] = [] + for (let j = 0; j < t; j++) { + const xy = Fp.add(xs[i], ys[j]) + if (Fp.is0(xy)) + throw new Error(`Error generating MDS matrix: xs[${i}] + ys[${j}] resulted in zero.`) + row.push(xy) + } + mds.push(Fp.invertBatch(row)) + } + + return { roundConstants, mds } +} + +export type PoseidonOpts = PoseidonBasicOpts & + PoseidonConstants & { + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark + } + +export function validateOpts(opts: PoseidonOpts): Readonly<{ + rounds: number + sboxFn: (n: bigint) => bigint + roundConstants: bigint[][] + mds: bigint[][] + Fp: IField + t: number + roundsFull: number + roundsPartial: number + sboxPower?: number + reversePartialPowIdx?: boolean // Hack for stark +}> { + validateBasicOpts(opts) + const { Fp, mds, reversePartialPowIdx: rev, roundConstants: rc } = opts + const { roundsFull, roundsPartial, sboxPower, t } = opts + + // MDS is TxT matrix + if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix') + const _mds = mds.map((mdsRow) => { + if (!Array.isArray(mdsRow) || mdsRow.length !== t) + throw new Error('invalid MDS matrix row: ' + mdsRow) + return mdsRow.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i) + return Fp.create(i) + }) + }) + + if (rev !== undefined && typeof rev !== 'boolean') + throw new Error('invalid param reversePartialPowIdx=' + rev) + + if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull) + const rounds = roundsFull + roundsPartial + + if (!Array.isArray(rc) || rc.length !== rounds) + throw new Error('Poseidon: invalid round constants') + const roundConstants = rc.map((rc) => { + if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants') + return rc.map((i) => { + if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant') + return Fp.create(i) + }) + }) + + if (!sboxPower || ![3, 5, 7, 17].includes(sboxPower)) throw new Error('invalid sboxPower') + const _sboxPower = BigInt(sboxPower) + let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower) + // Unwrapped sbox power for common cases (195->142μs) + if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(n), n) + else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.sqrN(Fp.sqrN(n)), n) + + return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds: _mds }) +} + +export function splitConstants(rc: bigint[], t: number): bigint[][] { + if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t') + if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc') + const res = [] + let tmp = [] + for (let i = 0; i < rc.length; i++) { + tmp.push(rc[i]) + if (tmp.length === t) { + res.push(tmp) + tmp = [] + } + } + return res +} + +/** Poseidon NTT-friendly hash. */ +export function poseidon(opts: PoseidonOpts): { + (values: bigint[]): bigint[] + // For verification in tests + roundConstants: bigint[][] +} { + const _opts = validateOpts(opts) + const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts + const halfRoundsFull = _opts.roundsFull / 2 + const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0 + const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => { + values = values.map((i, j) => Fp.add(i, roundConstants[idx][j])) + + if (isFull) values = values.map((i) => sboxFn(i)) + else values[partialIdx] = sboxFn(values[partialIdx]) + // Matrix multiplication + values = mds.map((i) => i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)) + return values + } + const poseidonHash = function poseidonHash(values: bigint[]) { + if (!Array.isArray(values) || values.length !== t) + throw new Error('invalid values, expected array of bigints with length ' + t) + values = values.map((i) => { + if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i) + return Fp.create(i) + }) + let lastRound = 0 + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + // Apply r_p partial rounds. + for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++) + // Apply r_f/2 full rounds. + for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++) + + if (lastRound !== totalRounds) throw new Error('invalid number of rounds') + return values + } + // For verification in tests + poseidonHash.roundConstants = roundConstants + return poseidonHash +} + +export class PoseidonSponge { + private Fp: IField + readonly rate: number + readonly capacity: number + readonly hash: ReturnType + private state: bigint[] // [...capacity, ...rate] + private pos = 0 + private isAbsorbing = true + + constructor( + Fp: IField, + rate: number, + capacity: number, + hash: ReturnType, + ) { + this.Fp = Fp + this.hash = hash + this.rate = rate + this.capacity = capacity + this.state = new Array(rate + capacity) + this.clean() + } + private process(): void { + this.state = this.hash(this.state) + } + absorb(input: bigint[]): void { + for (const i of input) + if (typeof i !== 'bigint' || !this.Fp.isValid(i)) throw new Error('invalid input: ' + i) + for (let i = 0; i < input.length; ) { + if (!this.isAbsorbing || this.pos === this.rate) { + this.process() + this.pos = 0 + this.isAbsorbing = true + } + const chunk = Math.min(this.rate - this.pos, input.length - i) + for (let j = 0; j < chunk; j++) { + const idx = this.capacity + this.pos++ + this.state[idx] = this.Fp.add(this.state[idx], input[i++]) + } + } + } + squeeze(count: number): bigint[] { + const res: bigint[] = [] + while (res.length < count) { + if (this.isAbsorbing || this.pos === this.rate) { + this.process() + this.pos = 0 + this.isAbsorbing = false + } + const chunk = Math.min(this.rate - this.pos, count - res.length) + for (let i = 0; i < chunk; i++) res.push(this.state[this.capacity + this.pos++]) + } + return res + } + clean(): void { + this.state.fill(this.Fp.ZERO) + this.isAbsorbing = true + this.pos = 0 + } + clone(): PoseidonSponge { + const c = new PoseidonSponge(this.Fp, this.rate, this.capacity, this.hash) + c.pos = this.pos + c.state = [...this.state] + return c + } +} + +export type PoseidonSpongeOpts = Omit & { + rate: number + capacity: number +} + +/** + * The method is not defined in spec, but nevertheless used often. + * Check carefully for compatibility: there are many edge cases, like absorbing an empty array. + * We cross-test against: + * - https://github.com/ProvableHQ/snarkVM/tree/staging/algorithms + * - https://github.com/arkworks-rs/crypto-primitives/tree/main + */ +export function poseidonSponge(opts: PoseidonSpongeOpts): () => PoseidonSponge { + for (const i of ['rate', 'capacity'] as const) { + if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i])) + throw new Error('invalid number ' + i) + } + const { rate, capacity } = opts + const t = opts.rate + opts.capacity + // Re-use hash instance between multiple instances + const hash = poseidon({ ...opts, t }) + const { Fp } = opts + return () => new PoseidonSponge(Fp, rate, capacity, hash) +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/tower.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/tower.ts new file mode 100644 index 00000000000..4135dc08816 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/tower.ts @@ -0,0 +1,664 @@ +/** + * Towered extension fields. + * Rather than implementing a massive 12th-degree extension directly, it is more efficient + * to build it up from smaller extensions: a tower of extensions. + * + * For BLS12-381, the Fp12 field is implemented as a quadratic (degree two) extension, + * on top of a cubic (degree three) extension, on top of a quadratic extension of Fp. + * + * For more info: "Pairings for beginners" by Costello, section 7.3. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import * as mod from './modular.ts' +import { bitLen, bitMask, concatBytes, notImplemented } from './utils.ts' +import type { ProjConstructor, ProjPointType } from './weierstrass.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) + +// Fp₂ over complex plane +export type BigintTuple = [bigint, bigint] +export type Fp = bigint +// Finite extension field over irreducible polynominal. +// Fp(u) / (u² - β) where β = -1 +export type Fp2 = { c0: bigint; c1: bigint } +export type BigintSix = [bigint, bigint, bigint, bigint, bigint, bigint] +export type Fp6 = { c0: Fp2; c1: Fp2; c2: Fp2 } +export type Fp12 = { c0: Fp6; c1: Fp6 } // Fp₁₂ = Fp₆² => Fp₂³, Fp₆(w) / (w² - γ) where γ = v +// prettier-ignore +export type BigintTwelve = [ + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, + bigint, +] + +export type Fp2Bls = mod.IField & { + reim: (num: Fp2) => { re: Fp; im: Fp } + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + fromBigTuple(num: [bigint, bigint]): Fp2 +} + +export type Fp12Bls = mod.IField & { + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + fromBigTwelve(num: BigintTwelve): Fp12 +} + +function calcFrobeniusCoefficients( + Fp: mod.IField, + nonResidue: T, + modulus: bigint, + degree: number, + num: number = 1, + divisor?: number, +) { + const _divisor = BigInt(divisor === undefined ? degree : divisor) + const towerModulus: any = modulus ** BigInt(degree) + const res: T[][] = [] + for (let i = 0; i < num; i++) { + const a = BigInt(i + 1) + const powers: T[] = [] + for (let j = 0, qPower = _1n; j < degree; j++) { + const power = ((a * qPower - a) / _divisor) % towerModulus + powers.push(Fp.pow(nonResidue, power)) + qPower *= modulus + } + res.push(powers) + } + return res +} + +// This works same at least for bls12-381, bn254 and bls12-377 +export function psiFrobenius( + Fp: mod.IField, + Fp2: Fp2Bls, + base: Fp2, +): { + psi: (x: Fp2, y: Fp2) => [Fp2, Fp2] + psi2: (x: Fp2, y: Fp2) => [Fp2, Fp2] + G2psi: (c: ProjConstructor, P: ProjPointType) => ProjPointType + G2psi2: (c: ProjConstructor, P: ProjPointType) => ProjPointType + PSI_X: Fp2 + PSI_Y: Fp2 + PSI2_X: Fp2 + PSI2_Y: Fp2 +} { + // Ψ endomorphism + const PSI_X = Fp2.pow(base, (Fp.ORDER - _1n) / _3n) // u^((p-1)/3) + const PSI_Y = Fp2.pow(base, (Fp.ORDER - _1n) / _2n) // u^((p-1)/2) + function psi(x: Fp2, y: Fp2): [Fp2, Fp2] { + // This x10 faster than previous version in bls12-381 + const x2 = Fp2.mul(Fp2.frobeniusMap(x, 1), PSI_X) + const y2 = Fp2.mul(Fp2.frobeniusMap(y, 1), PSI_Y) + return [x2, y2] + } + // Ψ²(P) endomorphism (psi2(x) = psi(psi(x))) + const PSI2_X = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _3n) // u^((p^2 - 1)/3) + // This equals -1, which causes y to be Fp2.neg(y). + // But not sure if there are case when this is not true? + const PSI2_Y = Fp2.pow(base, (Fp.ORDER ** _2n - _1n) / _2n) // u^((p^2 - 1)/3) + if (!Fp2.eql(PSI2_Y, Fp2.neg(Fp2.ONE))) throw new Error('psiFrobenius: PSI2_Y!==-1') + function psi2(x: Fp2, y: Fp2): [Fp2, Fp2] { + return [Fp2.mul(x, PSI2_X), Fp2.neg(y)] + } + // Map points + const mapAffine = + (fn: (x: T, y: T) => [T, T]) => + (c: ProjConstructor, P: ProjPointType) => { + const affine = P.toAffine() + const p = fn(affine.x, affine.y) + return c.fromAffine({ x: p[0], y: p[1] }) + } + const G2psi = mapAffine(psi) + const G2psi2 = mapAffine(psi2) + return { psi, psi2, G2psi, G2psi2, PSI_X, PSI_Y, PSI2_X, PSI2_Y } +} + +export type Tower12Opts = { + ORDER: bigint + NONRESIDUE?: Fp + // Fp2 + FP2_NONRESIDUE: BigintTuple + Fp2sqrt?: (num: Fp2) => Fp2 + Fp2mulByB: (num: Fp2) => Fp2 + // Fp12 + Fp12cyclotomicSquare: (num: Fp12) => Fp12 + Fp12cyclotomicExp: (num: Fp12, n: bigint) => Fp12 + Fp12finalExponentiate: (num: Fp12) => Fp12 +} + +export function tower12(opts: Tower12Opts): { + Fp: Readonly & Required, 'isOdd'>>> + Fp2: mod.IField & { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + Fp6: mod.IField & { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + Fp4Square: (a: Fp2, b: Fp2) => { first: Fp2; second: Fp2 } + Fp12: mod.IField & { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } +} { + const { ORDER } = opts + // Fp + const Fp = mod.Field(ORDER) + const FpNONRESIDUE = Fp.create(opts.NONRESIDUE || BigInt(-1)) + const FpLegendre = mod.FpLegendre(ORDER) + const Fpdiv2 = Fp.div(Fp.ONE, _2n) // 1/2 + + // Fp2 + const FP2_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients(Fp, FpNONRESIDUE, Fp.ORDER, 2)[0] + const Fp2Add = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.add(c0, r0), + c1: Fp.add(c1, r1), + }) + const Fp2Subtract = ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => ({ + c0: Fp.sub(c0, r0), + c1: Fp.sub(c1, r1), + }) + const Fp2Multiply = ({ c0, c1 }: Fp2, rhs: Fp2) => { + if (typeof rhs === 'bigint') return { c0: Fp.mul(c0, rhs), c1: Fp.mul(c1, rhs) } + // (a+bi)(c+di) = (ac−bd) + (ad+bc)i + const { c0: r0, c1: r1 } = rhs + let t1 = Fp.mul(c0, r0) // c0 * o0 + let t2 = Fp.mul(c1, r1) // c1 * o1 + // (T1 - T2) + ((c0 + c1) * (r0 + r1) - (T1 + T2))*i + const o0 = Fp.sub(t1, t2) + const o1 = Fp.sub(Fp.mul(Fp.add(c0, c1), Fp.add(r0, r1)), Fp.add(t1, t2)) + return { c0: o0, c1: o1 } + } + const Fp2Square = ({ c0, c1 }: Fp2) => { + const a = Fp.add(c0, c1) + const b = Fp.sub(c0, c1) + const c = Fp.add(c0, c0) + return { c0: Fp.mul(a, b), c1: Fp.mul(c, c1) } + } + type Fp2Utils = { + NONRESIDUE: Fp2 + fromBigTuple: (tuple: BigintTuple | bigint[]) => Fp2 + reim: (num: Fp2) => { re: bigint; im: bigint } + mulByNonresidue: (num: Fp2) => Fp2 + mulByB: (num: Fp2) => Fp2 + frobeniusMap(num: Fp2, power: number): Fp2 + } + const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => { + if (tuple.length !== 2) throw new Error('invalid tuple') + const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp] + return { c0: fps[0], c1: fps[1] } + } + + const FP2_ORDER = ORDER * ORDER + const Fp2Nonresidue = Fp2fromBigTuple(opts.FP2_NONRESIDUE) + const Fp2: mod.IField & Fp2Utils = { + ORDER: FP2_ORDER, + isLE: Fp.isLE, + NONRESIDUE: Fp2Nonresidue, + BITS: bitLen(FP2_ORDER), + BYTES: Math.ceil(bitLen(FP2_ORDER) / 8), + MASK: bitMask(bitLen(FP2_ORDER)), + ZERO: { c0: Fp.ZERO, c1: Fp.ZERO }, + ONE: { c0: Fp.ONE, c1: Fp.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => typeof c0 === 'bigint' && typeof c1 === 'bigint', + is0: ({ c0, c1 }) => Fp.is0(c0) && Fp.is0(c1), + eql: ({ c0, c1 }: Fp2, { c0: r0, c1: r1 }: Fp2) => Fp.eql(c0, r0) && Fp.eql(c1, r1), + neg: ({ c0, c1 }) => ({ c0: Fp.neg(c0), c1: Fp.neg(c1) }), + pow: (num, power) => mod.FpPow(Fp2, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp2, nums), + // Normalized + add: Fp2Add, + sub: Fp2Subtract, + mul: Fp2Multiply, + sqr: Fp2Square, + // NonNormalized stuff + addN: Fp2Add, + subN: Fp2Subtract, + mulN: Fp2Multiply, + sqrN: Fp2Square, + // Why inversion for bigint inside Fp instead of Fp2? it is even used in that context? + div: (lhs, rhs) => + Fp2.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp2.inv(rhs)), + inv: ({ c0: a, c1: b }) => { + // We wish to find the multiplicative inverse of a nonzero + // element a + bu in Fp2. We leverage an identity + // + // (a + bu)(a - bu) = a² + b² + // + // which holds because u² = -1. This can be rewritten as + // + // (a + bu)(a - bu)/(a² + b²) = 1 + // + // because a² + b² = 0 has no nonzero solutions for (a, b). + // This gives that (a - bu)/(a² + b²) is the inverse + // of (a + bu). Importantly, this can be computing using + // only a single inversion in Fp. + const factor = Fp.inv(Fp.create(a * a + b * b)) + return { c0: Fp.mul(factor, Fp.create(a)), c1: Fp.mul(factor, Fp.create(-b)) } + }, + sqrt: (num) => { + if (opts.Fp2sqrt) return opts.Fp2sqrt(num) + // This is generic for all quadratic extensions (Fp2) + const { c0, c1 } = num + if (Fp.is0(c1)) { + // if c0 is quadratic residue + if (Fp.eql(FpLegendre(Fp, c0), Fp.ONE)) return Fp2.create({ c0: Fp.sqrt(c0), c1: Fp.ZERO }) + else return Fp2.create({ c0: Fp.ZERO, c1: Fp.sqrt(Fp.div(c0, FpNONRESIDUE)) }) + } + const a = Fp.sqrt(Fp.sub(Fp.sqr(c0), Fp.mul(Fp.sqr(c1), FpNONRESIDUE))) + let d = Fp.mul(Fp.add(a, c0), Fpdiv2) + const legendre = FpLegendre(Fp, d) + // -1, Quadratic non residue + if (!Fp.is0(legendre) && !Fp.eql(legendre, Fp.ONE)) d = Fp.sub(d, a) + const a0 = Fp.sqrt(d) + const candidateSqrt = Fp2.create({ c0: a0, c1: Fp.div(Fp.mul(c1, Fpdiv2), a0) }) + if (!Fp2.eql(Fp2.sqr(candidateSqrt), num)) throw new Error('Cannot find square root') + // Normalize root: at this point candidateSqrt ** 2 = num, but also -candidateSqrt ** 2 = num + const x1 = candidateSqrt + const x2 = Fp2.neg(x1) + const { re: re1, im: im1 } = Fp2.reim(x1) + const { re: re2, im: im2 } = Fp2.reim(x2) + if (im1 > im2 || (im1 === im2 && re1 > re2)) return x1 + return x2 + }, + // Same as sgn0_m_eq_2 in RFC 9380 + isOdd: (x: Fp2) => { + const { re: x0, im: x1 } = Fp2.reim(x) + const sign_0 = x0 % _2n + const zero_0 = x0 === _0n + const sign_1 = x1 % _2n + return BigInt(sign_0 || (zero_0 && sign_1)) == _1n + }, + // Bytes util + fromBytes(b: Uint8Array): Fp2 { + if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) } + }, + toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp.cmov(c0, r0, c), + c1: Fp.cmov(c1, r1, c), + }), + reim: ({ c0, c1 }) => ({ re: c0, im: c1 }), + // multiply by u + 1 + mulByNonresidue: ({ c0, c1 }) => Fp2.mul({ c0, c1 }, Fp2Nonresidue), + mulByB: opts.Fp2mulByB, + fromBigTuple: Fp2fromBigTuple, + frobeniusMap: ({ c0, c1 }, power: number): Fp2 => ({ + c0, + c1: Fp.mul(c1, FP2_FROBENIUS_COEFFICIENTS[power % 2]), + }), + } + // Fp6 + const Fp6Add = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.add(c0, r0), + c1: Fp2.add(c1, r1), + c2: Fp2.add(c2, r2), + }) + const Fp6Subtract = ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6) => ({ + c0: Fp2.sub(c0, r0), + c1: Fp2.sub(c1, r1), + c2: Fp2.sub(c2, r2), + }) + const Fp6Multiply = ({ c0, c1, c2 }: Fp6, rhs: Fp6 | bigint) => { + if (typeof rhs === 'bigint') { + return { + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + } + } + const { c0: r0, c1: r1, c2: r2 } = rhs + const t0 = Fp2.mul(c0, r0) // c0 * o0 + const t1 = Fp2.mul(c1, r1) // c1 * o1 + const t2 = Fp2.mul(c2, r2) // c2 * o2 + return { + // t0 + (c1 + c2) * (r1 * r2) - (T1 + T2) * (u + 1) + c0: Fp2.add( + t0, + Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), Fp2.add(r1, r2)), Fp2.add(t1, t2))), + ), + // (c0 + c1) * (r0 + r1) - (T0 + T1) + T2 * (u + 1) + c1: Fp2.add( + Fp2.sub(Fp2.mul(Fp2.add(c0, c1), Fp2.add(r0, r1)), Fp2.add(t0, t1)), + Fp2.mulByNonresidue(t2), + ), + // T1 + (c0 + c2) * (r0 + r2) - T0 + T2 + c2: Fp2.sub(Fp2.add(t1, Fp2.mul(Fp2.add(c0, c2), Fp2.add(r0, r2))), Fp2.add(t0, t2)), + } + } + const Fp6Square = ({ c0, c1, c2 }: Fp6) => { + let t0 = Fp2.sqr(c0) // c0² + let t1 = Fp2.mul(Fp2.mul(c0, c1), _2n) // 2 * c0 * c1 + let t3 = Fp2.mul(Fp2.mul(c1, c2), _2n) // 2 * c1 * c2 + let t4 = Fp2.sqr(c2) // c2² + return { + c0: Fp2.add(Fp2.mulByNonresidue(t3), t0), // T3 * (u + 1) + T0 + c1: Fp2.add(Fp2.mulByNonresidue(t4), t1), // T4 * (u + 1) + T1 + // T1 + (c0 - c1 + c2)² + T3 - T0 - T4 + c2: Fp2.sub(Fp2.sub(Fp2.add(Fp2.add(t1, Fp2.sqr(Fp2.add(Fp2.sub(c0, c1), c2))), t3), t0), t4), + } + } + type Fp6Utils = { + fromBigSix: (tuple: BigintSix) => Fp6 + mulByNonresidue: (num: Fp6) => Fp6 + frobeniusMap(num: Fp6, power: number): Fp6 + mul1(num: Fp6, b1: Fp2): Fp6 + mul01(num: Fp6, b0: Fp2, b1: Fp2): Fp6 + mulByFp2(lhs: Fp6, rhs: Fp2): Fp6 + } + + const [FP6_FROBENIUS_COEFFICIENTS_1, FP6_FROBENIUS_COEFFICIENTS_2] = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 6, + 2, + 3, + ) + + const Fp6: mod.IField & Fp6Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp2.isLE, + BITS: 3 * Fp2.BITS, + BYTES: 3 * Fp2.BYTES, + MASK: bitMask(3 * Fp2.BITS), + ZERO: { c0: Fp2.ZERO, c1: Fp2.ZERO, c2: Fp2.ZERO }, + ONE: { c0: Fp2.ONE, c1: Fp2.ZERO, c2: Fp2.ZERO }, + create: (num) => num, + isValid: ({ c0, c1, c2 }) => Fp2.isValid(c0) && Fp2.isValid(c1) && Fp2.isValid(c2), + is0: ({ c0, c1, c2 }) => Fp2.is0(c0) && Fp2.is0(c1) && Fp2.is0(c2), + neg: ({ c0, c1, c2 }) => ({ c0: Fp2.neg(c0), c1: Fp2.neg(c1), c2: Fp2.neg(c2) }), + eql: ({ c0, c1, c2 }, { c0: r0, c1: r1, c2: r2 }) => + Fp2.eql(c0, r0) && Fp2.eql(c1, r1) && Fp2.eql(c2, r2), + sqrt: notImplemented, + // Do we need division by bigint at all? Should be done via order: + div: (lhs, rhs) => + Fp6.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp6.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp6, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp6, nums), + // Normalized + add: Fp6Add, + sub: Fp6Subtract, + mul: Fp6Multiply, + sqr: Fp6Square, + // NonNormalized stuff + addN: Fp6Add, + subN: Fp6Subtract, + mulN: Fp6Multiply, + sqrN: Fp6Square, + + inv: ({ c0, c1, c2 }) => { + let t0 = Fp2.sub(Fp2.sqr(c0), Fp2.mulByNonresidue(Fp2.mul(c2, c1))) // c0² - c2 * c1 * (u + 1) + let t1 = Fp2.sub(Fp2.mulByNonresidue(Fp2.sqr(c2)), Fp2.mul(c0, c1)) // c2² * (u + 1) - c0 * c1 + let t2 = Fp2.sub(Fp2.sqr(c1), Fp2.mul(c0, c2)) // c1² - c0 * c2 + // 1/(((c2 * T1 + c1 * T2) * v) + c0 * T0) + let t4 = Fp2.inv( + Fp2.add(Fp2.mulByNonresidue(Fp2.add(Fp2.mul(c2, t1), Fp2.mul(c1, t2))), Fp2.mul(c0, t0)), + ) + return { c0: Fp2.mul(t4, t0), c1: Fp2.mul(t4, t1), c2: Fp2.mul(t4, t2) } + }, + // Bytes utils + fromBytes: (b: Uint8Array): Fp6 => { + if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)), + c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)), + c2: Fp2.fromBytes(b.subarray(2 * Fp2.BYTES)), + } + }, + toBytes: ({ c0, c1, c2 }): Uint8Array => + concatBytes(Fp2.toBytes(c0), Fp2.toBytes(c1), Fp2.toBytes(c2)), + cmov: ({ c0, c1, c2 }: Fp6, { c0: r0, c1: r1, c2: r2 }: Fp6, c) => ({ + c0: Fp2.cmov(c0, r0, c), + c1: Fp2.cmov(c1, r1, c), + c2: Fp2.cmov(c2, r2, c), + }), + fromBigSix: (t: BigintSix): Fp6 => { + if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage') + return { + c0: Fp2.fromBigTuple(t.slice(0, 2)), + c1: Fp2.fromBigTuple(t.slice(2, 4)), + c2: Fp2.fromBigTuple(t.slice(4, 6)), + } + }, + frobeniusMap: ({ c0, c1, c2 }, power: number) => ({ + c0: Fp2.frobeniusMap(c0, power), + c1: Fp2.mul(Fp2.frobeniusMap(c1, power), FP6_FROBENIUS_COEFFICIENTS_1[power % 6]), + c2: Fp2.mul(Fp2.frobeniusMap(c2, power), FP6_FROBENIUS_COEFFICIENTS_2[power % 6]), + }), + mulByFp2: ({ c0, c1, c2 }, rhs: Fp2): Fp6 => ({ + c0: Fp2.mul(c0, rhs), + c1: Fp2.mul(c1, rhs), + c2: Fp2.mul(c2, rhs), + }), + mulByNonresidue: ({ c0, c1, c2 }) => ({ c0: Fp2.mulByNonresidue(c2), c1: c0, c2: c1 }), + // Sparse multiplication + mul1: ({ c0, c1, c2 }, b1: Fp2): Fp6 => ({ + c0: Fp2.mulByNonresidue(Fp2.mul(c2, b1)), + c1: Fp2.mul(c0, b1), + c2: Fp2.mul(c1, b1), + }), + // Sparse multiplication + mul01({ c0, c1, c2 }, b0: Fp2, b1: Fp2): Fp6 { + let t0 = Fp2.mul(c0, b0) // c0 * b0 + let t1 = Fp2.mul(c1, b1) // c1 * b1 + return { + // ((c1 + c2) * b1 - T1) * (u + 1) + T0 + c0: Fp2.add(Fp2.mulByNonresidue(Fp2.sub(Fp2.mul(Fp2.add(c1, c2), b1), t1)), t0), + // (b0 + b1) * (c0 + c1) - T0 - T1 + c1: Fp2.sub(Fp2.sub(Fp2.mul(Fp2.add(b0, b1), Fp2.add(c0, c1)), t0), t1), + // (c0 + c2) * b0 - T0 + T1 + c2: Fp2.add(Fp2.sub(Fp2.mul(Fp2.add(c0, c2), b0), t0), t1), + } + }, + } + + // Fp12 + const FP12_FROBENIUS_COEFFICIENTS = calcFrobeniusCoefficients( + Fp2, + Fp2Nonresidue, + Fp.ORDER, + 12, + 1, + 6, + )[0] + + const Fp12Add = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.add(c0, r0), + c1: Fp6.add(c1, r1), + }) + const Fp12Subtract = ({ c0, c1 }: Fp12, { c0: r0, c1: r1 }: Fp12) => ({ + c0: Fp6.sub(c0, r0), + c1: Fp6.sub(c1, r1), + }) + const Fp12Multiply = ({ c0, c1 }: Fp12, rhs: Fp12 | bigint) => { + if (typeof rhs === 'bigint') return { c0: Fp6.mul(c0, rhs), c1: Fp6.mul(c1, rhs) } + let { c0: r0, c1: r1 } = rhs + let t1 = Fp6.mul(c0, r0) // c0 * r0 + let t2 = Fp6.mul(c1, r1) // c1 * r1 + return { + c0: Fp6.add(t1, Fp6.mulByNonresidue(t2)), // T1 + T2 * v + // (c0 + c1) * (r0 + r1) - (T1 + T2) + c1: Fp6.sub(Fp6.mul(Fp6.add(c0, c1), Fp6.add(r0, r1)), Fp6.add(t1, t2)), + } + } + const Fp12Square = ({ c0, c1 }: Fp12) => { + let ab = Fp6.mul(c0, c1) // c0 * c1 + return { + // (c1 * v + c0) * (c0 + c1) - AB - AB * v + c0: Fp6.sub( + Fp6.sub(Fp6.mul(Fp6.add(Fp6.mulByNonresidue(c1), c0), Fp6.add(c0, c1)), ab), + Fp6.mulByNonresidue(ab), + ), + c1: Fp6.add(ab, ab), + } // AB + AB + } + function Fp4Square(a: Fp2, b: Fp2): { first: Fp2; second: Fp2 } { + const a2 = Fp2.sqr(a) + const b2 = Fp2.sqr(b) + return { + first: Fp2.add(Fp2.mulByNonresidue(b2), a2), // b² * Nonresidue + a² + second: Fp2.sub(Fp2.sub(Fp2.sqr(Fp2.add(a, b)), a2), b2), // (a + b)² - a² - b² + } + } + type Fp12Utils = { + fromBigTwelve: (t: BigintTwelve) => Fp12 + frobeniusMap(num: Fp12, power: number): Fp12 + mul014(num: Fp12, o0: Fp2, o1: Fp2, o4: Fp2): Fp12 + mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12 + mulByFp2(lhs: Fp12, rhs: Fp2): Fp12 + conjugate(num: Fp12): Fp12 + finalExponentiate(num: Fp12): Fp12 + _cyclotomicSquare(num: Fp12): Fp12 + _cyclotomicExp(num: Fp12, n: bigint): Fp12 + } + + const Fp12: mod.IField & Fp12Utils = { + ORDER: Fp2.ORDER, // TODO: unused, but need to verify + isLE: Fp6.isLE, + BITS: 2 * Fp6.BITS, + BYTES: 2 * Fp6.BYTES, + MASK: bitMask(2 * Fp6.BITS), + ZERO: { c0: Fp6.ZERO, c1: Fp6.ZERO }, + ONE: { c0: Fp6.ONE, c1: Fp6.ZERO }, + create: (num) => num, + isValid: ({ c0, c1 }) => Fp6.isValid(c0) && Fp6.isValid(c1), + is0: ({ c0, c1 }) => Fp6.is0(c0) && Fp6.is0(c1), + neg: ({ c0, c1 }) => ({ c0: Fp6.neg(c0), c1: Fp6.neg(c1) }), + eql: ({ c0, c1 }, { c0: r0, c1: r1 }) => Fp6.eql(c0, r0) && Fp6.eql(c1, r1), + sqrt: notImplemented, + inv: ({ c0, c1 }) => { + let t = Fp6.inv(Fp6.sub(Fp6.sqr(c0), Fp6.mulByNonresidue(Fp6.sqr(c1)))) // 1 / (c0² - c1² * v) + return { c0: Fp6.mul(c0, t), c1: Fp6.neg(Fp6.mul(c1, t)) } // ((C0 * T) * T) + (-C1 * T) * w + }, + div: (lhs, rhs) => + Fp12.mul(lhs, typeof rhs === 'bigint' ? Fp.inv(Fp.create(rhs)) : Fp12.inv(rhs)), + pow: (num, power) => mod.FpPow(Fp12, num, power), + invertBatch: (nums) => mod.FpInvertBatch(Fp12, nums), + // Normalized + add: Fp12Add, + sub: Fp12Subtract, + mul: Fp12Multiply, + sqr: Fp12Square, + // NonNormalized stuff + addN: Fp12Add, + subN: Fp12Subtract, + mulN: Fp12Multiply, + sqrN: Fp12Square, + + // Bytes utils + fromBytes: (b: Uint8Array): Fp12 => { + if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length) + return { + c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)), + c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)), + } + }, + toBytes: ({ c0, c1 }): Uint8Array => concatBytes(Fp6.toBytes(c0), Fp6.toBytes(c1)), + cmov: ({ c0, c1 }, { c0: r0, c1: r1 }, c) => ({ + c0: Fp6.cmov(c0, r0, c), + c1: Fp6.cmov(c1, r1, c), + }), + // Utils + // toString() { + // return '' + 'Fp12(' + this.c0 + this.c1 + '* w'); + // }, + // fromTuple(c: [Fp6, Fp6]) { + // return new Fp12(...c); + // } + fromBigTwelve: (t: BigintTwelve): Fp12 => ({ + c0: Fp6.fromBigSix(t.slice(0, 6) as BigintSix), + c1: Fp6.fromBigSix(t.slice(6, 12) as BigintSix), + }), + // Raises to q**i -th power + frobeniusMap(lhs, power: number) { + const { c0, c1, c2 } = Fp6.frobeniusMap(lhs.c1, power) + const coeff = FP12_FROBENIUS_COEFFICIENTS[power % 12] + return { + c0: Fp6.frobeniusMap(lhs.c0, power), + c1: Fp6.create({ + c0: Fp2.mul(c0, coeff), + c1: Fp2.mul(c1, coeff), + c2: Fp2.mul(c2, coeff), + }), + } + }, + mulByFp2: ({ c0, c1 }, rhs: Fp2): Fp12 => ({ + c0: Fp6.mulByFp2(c0, rhs), + c1: Fp6.mulByFp2(c1, rhs), + }), + conjugate: ({ c0, c1 }): Fp12 => ({ c0, c1: Fp6.neg(c1) }), + // Sparse multiplication + mul014: ({ c0, c1 }, o0: Fp2, o1: Fp2, o4: Fp2) => { + let t0 = Fp6.mul01(c0, o0, o1) + let t1 = Fp6.mul1(c1, o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(t1), t0), // T1 * v + T0 + // (c1 + c0) * [o0, o1+o4] - T0 - T1 + c1: Fp6.sub(Fp6.sub(Fp6.mul01(Fp6.add(c1, c0), o0, Fp2.add(o1, o4)), t0), t1), + } + }, + mul034: ({ c0, c1 }, o0: Fp2, o3: Fp2, o4: Fp2) => { + const a = Fp6.create({ + c0: Fp2.mul(c0.c0, o0), + c1: Fp2.mul(c0.c1, o0), + c2: Fp2.mul(c0.c2, o0), + }) + const b = Fp6.mul01(c1, o3, o4) + const e = Fp6.mul01(Fp6.add(c0, c1), Fp2.add(o0, o3), o4) + return { + c0: Fp6.add(Fp6.mulByNonresidue(b), a), + c1: Fp6.sub(e, Fp6.add(a, b)), + } + }, + + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + _cyclotomicSquare: opts.Fp12cyclotomicSquare, + _cyclotomicExp: opts.Fp12cyclotomicExp, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + finalExponentiate: opts.Fp12finalExponentiate, + } + + return { Fp, Fp2, Fp6, Fp4Square, Fp12 } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/utils.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/utils.ts new file mode 100644 index 00000000000..de81eaef58b --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/utils.ts @@ -0,0 +1,378 @@ +/** + * Hex, bytes and number utilities. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ + +// 100 lines of code in the file are duplicated from noble-hashes (utils). +// This is OK: `abstract` directory does not use noble-hashes. +// User may opt-in into using different hashing library. This way, noble-hashes +// won't be included into their bundle. +const _0n = /* @__PURE__ */ BigInt(0) +const _1n = /* @__PURE__ */ BigInt(1) +export type Hex = Uint8Array | string // hex strings are accepted for simplicity +export type PrivKey = Hex | bigint // bigints are accepted to ease learning curve +export type CHash = { + (message: Uint8Array | string): Uint8Array + blockLen: number + outputLen: number + create(opts?: { dkLen?: number }): any // For shake +} +export type FHash = (message: Uint8Array | string) => Uint8Array + +export function isBytes(a: unknown): a is Uint8Array { + return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array') +} + +export function abytes(item: unknown): void { + if (!isBytes(item)) throw new Error('Uint8Array expected') +} + +export function abool(title: string, value: boolean): void { + if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value) +} + +export function numberToHexUnpadded(num: number | bigint): string { + const hex = num.toString(16) + return hex.length & 1 ? '0' + hex : hex +} + +export function hexToNumber(hex: string): bigint { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + return hex === '' ? _0n : BigInt('0x' + hex) // Big Endian +} + +// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex +const hasHexBuiltin: boolean = + // @ts-ignore + typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function' + +// Array where index 0xf0 (240) is mapped to string 'f0' +const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')) + +/** + * Convert byte array to hex string. Uses built-in function, when available. + * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' + */ +export function bytesToHex(bytes: Uint8Array): string { + abytes(bytes) + // @ts-ignore + if (hasHexBuiltin) return bytes.toHex() + // pre-caching improves the speed 6x + let hex = '' + for (let i = 0; i < bytes.length; i++) { + hex += hexes[bytes[i]] + } + return hex +} + +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const +function asciiToBase16(ch: number): number | undefined { + if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0 // '2' => 50-48 + if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10) // 'B' => 66-(65-10) + if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10) // 'b' => 98-(97-10) + return +} + +/** + * Convert hex string to byte array. Uses built-in function, when available. + * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) + */ +export function hexToBytes(hex: string): Uint8Array { + if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex) + // @ts-ignore + if (hasHexBuiltin) return Uint8Array.fromHex(hex) + const hl = hex.length + const al = hl / 2 + if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl) + const array = new Uint8Array(al) + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)) + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)) + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1] + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi) + } + array[ai] = n1 * 16 + n2 // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 + } + return array +} + +// BE: Big Endian, LE: Little Endian +export function bytesToNumberBE(bytes: Uint8Array): bigint { + return hexToNumber(bytesToHex(bytes)) +} +export function bytesToNumberLE(bytes: Uint8Array): bigint { + abytes(bytes) + return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse())) +} + +export function numberToBytesBE(n: number | bigint, len: number): Uint8Array { + return hexToBytes(n.toString(16).padStart(len * 2, '0')) +} +export function numberToBytesLE(n: number | bigint, len: number): Uint8Array { + return numberToBytesBE(n, len).reverse() +} +// Unpadded, rarely used +export function numberToVarBytesBE(n: number | bigint): Uint8Array { + return hexToBytes(numberToHexUnpadded(n)) +} + +/** + * Takes hex string or Uint8Array, converts to Uint8Array. + * Validates output length. + * Will throw error for other types. + * @param title descriptive title for an error e.g. 'private key' + * @param hex hex string or Uint8Array + * @param expectedLength optional, will compare to result array's length + * @returns + */ +export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array { + let res: Uint8Array + if (typeof hex === 'string') { + try { + res = hexToBytes(hex) + } catch (e) { + throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e) + } + } else if (isBytes(hex)) { + // Uint8Array.from() instead of hash.slice() because node.js Buffer + // is instance of Uint8Array, and its slice() creates **mutable** copy + res = Uint8Array.from(hex) + } else { + throw new Error(title + ' must be hex string or Uint8Array') + } + const len = res.length + if (typeof expectedLength === 'number' && len !== expectedLength) + throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len) + return res +} + +/** + * Copies several Uint8Arrays into one. + */ +export function concatBytes(...arrays: Uint8Array[]): Uint8Array { + let sum = 0 + for (let i = 0; i < arrays.length; i++) { + const a = arrays[i] + abytes(a) + sum += a.length + } + const res = new Uint8Array(sum) + for (let i = 0, pad = 0; i < arrays.length; i++) { + const a = arrays[i] + res.set(a, pad) + pad += a.length + } + return res +} + +// Compares 2 u8a-s in kinda constant time +export function equalBytes(a: Uint8Array, b: Uint8Array): boolean { + if (a.length !== b.length) return false + let diff = 0 + for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i] + return diff === 0 +} + +// Global symbols in both browsers and Node.js since v11 +// See https://github.com/microsoft/TypeScript/issues/31535 +declare const TextEncoder: any + +/** + * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99]) + */ +export function utf8ToBytes(str: string): Uint8Array { + if (typeof str !== 'string') throw new Error('string expected') + return new Uint8Array(new TextEncoder().encode(str)) // https://bugzil.la/1681809 +} + +// Is positive bigint +const isPosBig = (n: bigint) => typeof n === 'bigint' && _0n <= n + +export function inRange(n: bigint, min: bigint, max: bigint): boolean { + return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max +} + +/** + * Asserts min <= n < max. NOTE: It's < max and not <= max. + * @example + * aInRange('x', x, 1n, 256n); // would assume x is in (1n..255n) + */ +export function aInRange(title: string, n: bigint, min: bigint, max: bigint): void { + // Why min <= n < max and not a (min < n < max) OR b (min <= n <= max)? + // consider P=256n, min=0n, max=P + // - a for min=0 would require -1: `inRange('x', x, -1n, P)` + // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)` + // - our way is the cleanest: `inRange('x', x, 0n, P) + if (!inRange(n, min, max)) + throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n) +} + +// Bit operations + +/** + * Calculates amount of bits in a bigint. + * Same as `n.toString(2).length` + */ +export function bitLen(n: bigint): number { + let len + for (len = 0; n > _0n; n >>= _1n, len += 1); + return len +} + +/** + * Gets single bit at position. + * NOTE: first bit position is 0 (same as arrays) + * Same as `!!+Array.from(n.toString(2)).reverse()[pos]` + */ +export function bitGet(n: bigint, pos: number): bigint { + return (n >> BigInt(pos)) & _1n +} + +/** + * Sets single bit at position. + */ +export function bitSet(n: bigint, pos: number, value: boolean): bigint { + return n | ((value ? _1n : _0n) << BigInt(pos)) +} + +/** + * Calculate mask for N bits. Not using ** operator with bigints because of old engines. + * Same as BigInt(`0b${Array(i).fill('1').join('')}`) + */ +export const bitMask = (n: number): bigint => (_1n << BigInt(n)) - _1n + +// DRBG + +const u8n = (len: number) => new Uint8Array(len) // creates Uint8Array +const u8fr = (arr: ArrayLike) => Uint8Array.from(arr) // another shortcut +type Pred = (v: Uint8Array) => T | undefined +/** + * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + * @returns function that will call DRBG until 2nd arg returns something meaningful + * @example + * const drbg = createHmacDRBG(32, 32, hmac); + * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined + */ +export function createHmacDrbg( + hashLen: number, + qByteLen: number, + hmacFn: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array, +): (seed: Uint8Array, predicate: Pred) => T { + if (typeof hashLen !== 'number' || hashLen < 2) throw new Error('hashLen must be a number') + if (typeof qByteLen !== 'number' || qByteLen < 2) throw new Error('qByteLen must be a number') + if (typeof hmacFn !== 'function') throw new Error('hmacFn must be a function') + // Step B, Step C: set hashLen to 8*ceil(hlen/8) + let v = u8n(hashLen) // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs. + let k = u8n(hashLen) // Steps B and C of RFC6979 3.2: set hashLen, in our case always same + let i = 0 // Iterations counter, will throw when over 1000 + const reset = () => { + v.fill(1) + k.fill(0) + i = 0 + } + const h = (...b: Uint8Array[]) => hmacFn(k, v, ...b) // hmac(k)(v, ...values) + const reseed = (seed = u8n(0)) => { + // HMAC-DRBG reseed() function. Steps D-G + k = h(u8fr([0x00]), seed) // k = hmac(k || v || 0x00 || seed) + v = h() // v = hmac(k || v) + if (seed.length === 0) return + k = h(u8fr([0x01]), seed) // k = hmac(k || v || 0x01 || seed) + v = h() // v = hmac(k || v) + } + const gen = () => { + // HMAC-DRBG generate() function + if (i++ >= 1000) throw new Error('drbg: tried 1000 values') + let len = 0 + const out: Uint8Array[] = [] + while (len < qByteLen) { + v = h() + const sl = v.slice() + out.push(sl) + len += v.length + } + return concatBytes(...out) + } + const genUntil = (seed: Uint8Array, pred: Pred): T => { + reset() + reseed(seed) // Steps D-G + let res: T | undefined = undefined // Step H: grind until k is in [1..n-1] + while (!(res = pred(gen()))) reseed() + reset() + return res + } + return genUntil +} + +// Validating curves and fields + +const validatorFns = { + bigint: (val: any): boolean => typeof val === 'bigint', + function: (val: any): boolean => typeof val === 'function', + boolean: (val: any): boolean => typeof val === 'boolean', + string: (val: any): boolean => typeof val === 'string', + stringOrUint8Array: (val: any): boolean => typeof val === 'string' || isBytes(val), + isSafeInteger: (val: any): boolean => Number.isSafeInteger(val), + array: (val: any): boolean => Array.isArray(val), + field: (val: any, object: any): any => (object as any).Fp.isValid(val), + hash: (val: any): boolean => typeof val === 'function' && Number.isSafeInteger(val.outputLen), +} as const +type Validator = keyof typeof validatorFns +type ValMap> = { [K in keyof T]?: Validator } +// type Record = { [P in K]: T; } + +export function validateObject>( + object: T, + validators: ValMap, + optValidators: ValMap = {}, +): T { + const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => { + const checkVal = validatorFns[type] + if (typeof checkVal !== 'function') throw new Error('invalid validator function') + + const val = object[fieldName as keyof typeof object] + if (isOptional && val === undefined) return + if (!checkVal(val, object)) { + throw new Error( + 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val, + ) + } + } + for (const [fieldName, type] of Object.entries(validators)) checkField(fieldName, type!, false) + for (const [fieldName, type] of Object.entries(optValidators)) checkField(fieldName, type!, true) + return object +} +// validate type tests +// const o: { a: number; b: number; c: number } = { a: 1, b: 5, c: 6 }; +// const z0 = validateObject(o, { a: 'isSafeInteger' }, { c: 'bigint' }); // Ok! +// // Should fail type-check +// const z1 = validateObject(o, { a: 'tmp' }, { c: 'zz' }); +// const z2 = validateObject(o, { a: 'isSafeInteger' }, { c: 'zz' }); +// const z3 = validateObject(o, { test: 'boolean', z: 'bug' }); +// const z4 = validateObject(o, { a: 'boolean', z: 'bug' }); + +/** + * throws not implemented error + */ +export const notImplemented = (): never => { + throw new Error('not implemented') +} + +/** + * Memoizes (caches) computation result. + * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed. + */ +export function memoized( + fn: (arg: T, ...args: O) => R, +): (arg: T, ...args: O) => R { + const map = new WeakMap() + return (arg: T, ...args: O): R => { + const val = map.get(arg) + if (val !== undefined) return val + const computed = fn(arg, ...args) + map.set(arg, computed) + return computed + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/weierstrass.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/weierstrass.ts new file mode 100644 index 00000000000..b713756adbe --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/abstract/weierstrass.ts @@ -0,0 +1,1419 @@ +/** + * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b. + * + * ### Parameters + * + * To initialize a weierstrass curve, one needs to pass following params: + * + * * a: formula param + * * b: formula param + * * Fp: finite Field over which we'll do calculations. Can be complex (Fp2, Fp12) + * * n: Curve prime subgroup order, total count of valid points in the field + * * Gx: Base point (x, y) aka generator point x coordinate + * * Gy: ...y coordinate + * * h: cofactor, usually 1. h*n = curve group order (n is only subgroup order) + * * lowS: whether to enable (default) or disable "low-s" non-malleable signatures + * + * ### Design rationale for types + * + * * Interaction between classes from different curves should fail: + * `k256.Point.BASE.add(p256.Point.BASE)` + * * For this purpose we want to use `instanceof` operator, which is fast and works during runtime + * * Different calls of `curve()` would return different classes - + * `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve, + * it won't affect others + * + * TypeScript can't infer types for classes created inside a function. Classes is one instance + * of nominative types in TypeScript and interfaces only check for shape, so it's hard to create + * unique type for every function call. + * + * We can use generic types via some param, like curve opts, but that would: + * 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params) + * which is hard to debug. + * 2. Params can be generic and we can't enforce them to be constant value: + * if somebody creates curve from non-constant params, + * it would be allowed to interact with other curves with non-constant params + * + * @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +// prettier-ignore +import { + type AffinePoint, + type BasicCurve, + type Group, + type GroupConstructor, + pippenger, + validateBasic, + wNAF, +} from './curve.ts' +// prettier-ignore +import { + Field, + type IField, + getMinHashLength, + invert, + mapHashToField, + mod, + validateField, +} from './modular.ts' +// prettier-ignore +import { + type CHash, + type Hex, + type PrivKey, + aInRange, + abool, + bitMask, + bytesToHex, + bytesToNumberBE, + concatBytes, + createHmacDrbg, + ensureBytes, + hexToBytes, + inRange, + isBytes, + memoized, + numberToBytesBE, + numberToHexUnpadded, + validateObject, +} from './utils.ts' + +export type { AffinePoint } +type HmacFnSync = (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array +type EndomorphismOpts = { + beta: bigint + splitScalar: (k: bigint) => { k1neg: boolean; k1: bigint; k2neg: boolean; k2: bigint } +} +export type BasicWCurve = BasicCurve & { + // Params: a, b + a: T + b: T + + // Optional params + allowedPrivateKeyLengths?: readonly number[] // for P521 + wrapPrivateKey?: boolean // bls12-381 requires mod(n) instead of rejecting keys >= n + endo?: EndomorphismOpts // Endomorphism options for Koblitz curves + // When a cofactor != 1, there can be an effective methods to: + // 1. Determine whether a point is torsion-free + isTorsionFree?: (c: ProjConstructor, point: ProjPointType) => boolean + // 2. Clear torsion component + clearCofactor?: (c: ProjConstructor, point: ProjPointType) => ProjPointType +} + +export type Entropy = Hex | boolean +export type SignOpts = { lowS?: boolean; extraEntropy?: Entropy; prehash?: boolean } +export type VerOpts = { lowS?: boolean; prehash?: boolean; format?: 'compact' | 'der' | undefined } + +function validateSigVerOpts(opts: SignOpts | VerOpts) { + if (opts.lowS !== undefined) abool('lowS', opts.lowS) + if (opts.prehash !== undefined) abool('prehash', opts.prehash) +} + +// Instance for 3d XYZ points +export interface ProjPointType extends Group> { + readonly px: T + readonly py: T + readonly pz: T + get x(): T + get y(): T + toAffine(iz?: T): AffinePoint + toHex(isCompressed?: boolean): string + toRawBytes(isCompressed?: boolean): Uint8Array + + assertValidity(): void + hasEvenY(): boolean + multiplyUnsafe(scalar: bigint): ProjPointType + multiplyAndAddUnsafe(Q: ProjPointType, a: bigint, b: bigint): ProjPointType | undefined + isTorsionFree(): boolean + clearCofactor(): ProjPointType + _setWindowSize(windowSize: number): void +} +// Static methods for 3d XYZ points +export interface ProjConstructor extends GroupConstructor> { + new (x: T, y: T, z: T): ProjPointType + fromAffine(p: AffinePoint): ProjPointType + fromHex(hex: Hex): ProjPointType + fromPrivateKey(privateKey: PrivKey): ProjPointType + normalizeZ(points: ProjPointType[]): ProjPointType[] + msm(points: ProjPointType[], scalars: bigint[]): ProjPointType +} + +export type CurvePointsType = BasicWCurve & { + // Bytes + fromBytes?: (bytes: Uint8Array) => AffinePoint + toBytes?: (c: ProjConstructor, point: ProjPointType, isCompressed: boolean) => Uint8Array +} + +export type CurvePointsTypeWithLength = Readonly< + CurvePointsType & { nByteLength: number; nBitLength: number } +> + +function validatePointOpts(curve: CurvePointsType): CurvePointsTypeWithLength { + const opts = validateBasic(curve) + validateObject( + opts, + { + a: 'field', + b: 'field', + }, + { + allowedPrivateKeyLengths: 'array', + wrapPrivateKey: 'boolean', + isTorsionFree: 'function', + clearCofactor: 'function', + allowInfinityPoint: 'boolean', + fromBytes: 'function', + toBytes: 'function', + }, + ) + const { endo, Fp, a } = opts + if (endo) { + if (!Fp.eql(a, Fp.ZERO)) { + throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0') + } + if ( + typeof endo !== 'object' || + typeof endo.beta !== 'bigint' || + typeof endo.splitScalar !== 'function' + ) { + throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function') + } + } + return Object.freeze({ ...opts } as const) +} + +export type CurvePointsRes = { + CURVE: ReturnType> + ProjectivePoint: ProjConstructor + normPrivateKeyToScalar: (key: PrivKey) => bigint + weierstrassEquation: (x: T) => T + isWithinCurveOrder: (num: bigint) => boolean +} + +export class DERErr extends Error { + constructor(m = '') { + super(m) + } +} +export type IDER = { + // asn.1 DER encoding utils + Err: typeof DERErr + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string) => string + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } + } + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string + decode(data: Uint8Array): bigint + } + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } + hexFromSig(sig: { r: bigint; s: bigint }): string +} +/** + * ASN.1 DER encoding utilities. ASN is very complex & fragile. Format: + * + * [0x30 (SEQUENCE), bytelength, 0x02 (INTEGER), intLength, R, 0x02 (INTEGER), intLength, S] + * + * Docs: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/, https://luca.ntop.org/Teaching/Appunti/asn1.html + */ +export const DER: IDER = { + // asn.1 DER encoding utils + Err: DERErr, + // Basic building block is TLV (Tag-Length-Value) + _tlv: { + encode: (tag: number, data: string): string => { + const { Err: E } = DER + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length & 1) throw new E('tlv.encode: unpadded data') + const dataLen = data.length / 2 + const len = numberToHexUnpadded(dataLen) + if ((len.length / 2) & 0b1000_0000) throw new E('tlv.encode: long form length too big') + // length of length with long form flag + const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '' + const t = numberToHexUnpadded(tag) + return t + lenLen + len + data + }, + // v - value, l - left bytes (unparsed) + decode(tag: number, data: Uint8Array): { v: Uint8Array; l: Uint8Array } { + const { Err: E } = DER + let pos = 0 + if (tag < 0 || tag > 256) throw new E('tlv.encode: wrong tag') + if (data.length < 2 || data[pos++] !== tag) throw new E('tlv.decode: wrong tlv') + const first = data[pos++] + const isLong = !!(first & 0b1000_0000) // First bit of first length byte is flag for short/long form + let length = 0 + if (!isLong) length = first + else { + // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)] + const lenLen = first & 0b0111_1111 + if (!lenLen) throw new E('tlv.decode(long): indefinite length not supported') + if (lenLen > 4) throw new E('tlv.decode(long): byte length is too big') // this will overflow u32 in js + const lengthBytes = data.subarray(pos, pos + lenLen) + if (lengthBytes.length !== lenLen) throw new E('tlv.decode: length bytes not complete') + if (lengthBytes[0] === 0) throw new E('tlv.decode(long): zero leftmost byte') + for (const b of lengthBytes) length = (length << 8) | b + pos += lenLen + if (length < 128) throw new E('tlv.decode(long): not minimal encoding') + } + const v = data.subarray(pos, pos + length) + if (v.length !== length) throw new E('tlv.decode: wrong value length') + return { v, l: data.subarray(pos + length) } + }, + }, + // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag, + // since we always use positive integers here. It must always be empty: + // - add zero byte if exists + // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding) + _int: { + encode(num: bigint): string { + const { Err: E } = DER + if (num < _0n) throw new E('integer: negative integers are not allowed') + let hex = numberToHexUnpadded(num) + // Pad with zero byte if negative flag is present + if (Number.parseInt(hex[0], 16) & 0b1000) hex = '00' + hex + if (hex.length & 1) throw new E('unexpected DER parsing assertion: unpadded hex') + return hex + }, + decode(data: Uint8Array): bigint { + const { Err: E } = DER + if (data[0] & 0b1000_0000) throw new E('invalid signature integer: negative') + if (data[0] === 0x00 && !(data[1] & 0b1000_0000)) + throw new E('invalid signature integer: unnecessary leading zero') + return bytesToNumberBE(data) + }, + }, + toSig(hex: string | Uint8Array): { r: bigint; s: bigint } { + // parse DER signature + const { Err: E, _int: int, _tlv: tlv } = DER + const data = ensureBytes('signature', hex) + const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data) + if (seqLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes) + const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes) + if (sLeftBytes.length) throw new E('invalid signature: left bytes after parsing') + return { r: int.decode(rBytes), s: int.decode(sBytes) } + }, + hexFromSig(sig: { r: bigint; s: bigint }): string { + const { _tlv: tlv, _int: int } = DER + const rs = tlv.encode(0x02, int.encode(sig.r)) + const ss = tlv.encode(0x02, int.encode(sig.s)) + const seq = rs + ss + return tlv.encode(0x30, seq) + }, +} + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +export function weierstrassPoints(opts: CurvePointsType): CurvePointsRes { + const CURVE = validatePointOpts(opts) + const { Fp } = CURVE // All curves has same field / group length as for now, but they can differ + const Fn = Field(CURVE.n, CURVE.nBitLength) + + const toBytes = + CURVE.toBytes || + ((_c: ProjConstructor, point: ProjPointType, _isCompressed: boolean) => { + const a = point.toAffine() + return concatBytes(Uint8Array.from([0x04]), Fp.toBytes(a.x), Fp.toBytes(a.y)) + }) + const fromBytes = + CURVE.fromBytes || + ((bytes: Uint8Array) => { + // const head = bytes[0]; + const tail = bytes.subarray(1) + // if (head !== 0x04) throw new Error('Only non-compressed encoding is supported'); + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + }) + + /** + * y² = x³ + ax + b: Short weierstrass curve formula. Takes x, returns y². + * @returns y² + */ + function weierstrassEquation(x: T): T { + const { a, b } = CURVE + const x2 = Fp.sqr(x) // x * x + const x3 = Fp.mul(x2, x) // x2 * x + return Fp.add(Fp.add(x3, Fp.mul(x, a)), b) // x3 + a * x + b + } + // Validate whether the passed curve params are valid. + // We check if curve equation works for generator point. + // `assertValidity()` won't work: `isTorsionFree()` is not available at this point in bls12-381. + // ProjectivePoint class has not been initialized yet. + if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx))) + throw new Error('bad generator point: equation left != right') + + // Valid group elements reside in range 1..n-1 + function isWithinCurveOrder(num: bigint): boolean { + return inRange(num, _1n, CURVE.n) + } + // Validates if priv key is valid and converts it to bigint. + // Supports options allowedPrivateKeyLengths and wrapPrivateKey. + function normPrivateKeyToScalar(key: PrivKey): bigint { + const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE + if (lengths && typeof key !== 'bigint') { + if (isBytes(key)) key = bytesToHex(key) + // Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes + if (typeof key !== 'string' || !lengths.includes(key.length)) + throw new Error('invalid private key') + key = key.padStart(nByteLength * 2, '0') + } + let num: bigint + try { + num = + typeof key === 'bigint' + ? key + : bytesToNumberBE(ensureBytes('private key', key, nByteLength)) + } catch (error) { + throw new Error( + 'invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key, + ) + } + if (wrapPrivateKey) num = mod(num, N) // disabled by default, enabled for BLS + aInRange('private key', num, _1n, N) // num in range [1..N-1] + return num + } + + function aprjpoint(other: unknown) { + if (!(other instanceof Point)) throw new Error('ProjectivePoint expected') + } + + // Memoized toAffine / validity check. They are heavy. Points are immutable. + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + const toAffineMemo = memoized((p: Point, iz?: T): AffinePoint => { + const { px: x, py: y, pz: z } = p + // Fast-path for normalized points + if (Fp.eql(z, Fp.ONE)) return { x, y } + const is0 = p.is0() + // If invZ was 0, we return zero point. However we still want to execute + // all operations, so we replace invZ with a random number, 1. + if (iz == null) iz = is0 ? Fp.ONE : Fp.inv(z) + const ax = Fp.mul(x, iz) + const ay = Fp.mul(y, iz) + const zz = Fp.mul(z, iz) + if (is0) return { x: Fp.ZERO, y: Fp.ZERO } + if (!Fp.eql(zz, Fp.ONE)) throw new Error('invZ was invalid') + return { x: ax, y: ay } + }) + // NOTE: on exception this will crash 'cached' and no value will be set. + // Otherwise true will be return + const assertValidMemo = memoized((p: Point) => { + if (p.is0()) { + // (0, 1, 0) aka ZERO is invalid in most contexts. + // In BLS, ZERO can be serialized, so we allow it. + // (0, 0, 0) is invalid representation of ZERO. + if (CURVE.allowInfinityPoint && !Fp.is0(p.py)) return + throw new Error('bad point: ZERO') + } + // Some 3rd-party test vectors require different wording between here & `fromCompressedHex` + const { x, y } = p.toAffine() + // Check if x, y are valid field elements + if (!Fp.isValid(x) || !Fp.isValid(y)) throw new Error('bad point: x or y not FE') + const left = Fp.sqr(y) // y² + const right = weierstrassEquation(x) // x³ + ax + b + if (!Fp.eql(left, right)) throw new Error('bad point: equation left != right') + if (!p.isTorsionFree()) throw new Error('bad point: not in prime-order subgroup') + return true + }) + + /** + * Projective Point works in 3d / projective (homogeneous) coordinates: (x, y, z) ∋ (x=x/z, y=y/z) + * Default Point works in 2d / affine coordinates: (x, y) + * We're doing calculations in projective, because its operations don't require costly inversion. + */ + class Point implements ProjPointType { + static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE) + static readonly ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO) // 0, 1, 0 + readonly px: T + readonly py: T + readonly pz: T + + constructor(px: T, py: T, pz: T) { + if (px == null || !Fp.isValid(px)) throw new Error('x required') + if (py == null || !Fp.isValid(py) || Fp.is0(py)) throw new Error('y required') + if (pz == null || !Fp.isValid(pz)) throw new Error('z required') + this.px = px + this.py = py + this.pz = pz + Object.freeze(this) + } + + // Does not validate if the point is on-curve. + // Use fromHex instead, or call assertValidity() later. + static fromAffine(p: AffinePoint): Point { + const { x, y } = p || {} + if (!p || !Fp.isValid(x) || !Fp.isValid(y)) throw new Error('invalid affine point') + if (p instanceof Point) throw new Error('projective point not allowed') + const is0 = (i: T) => Fp.eql(i, Fp.ZERO) + // fromAffine(x:0, y:0) would produce (x:0, y:0, z:1), but we need (x:0, y:1, z:0) + if (is0(x) && is0(y)) return Point.ZERO + return new Point(x, y, Fp.ONE) + } + + get x(): T { + return this.toAffine().x + } + get y(): T { + return this.toAffine().y + } + + /** + * Takes a bunch of Projective Points but executes only one + * inversion on all of them. Inversion is very slow operation, + * so this improves performance massively. + * Optimization: converts a list of projective points to a list of identical points with Z=1. + */ + static normalizeZ(points: Point[]): Point[] { + const toInv = Fp.invertBatch(points.map((p) => p.pz)) + return points.map((p, i) => p.toAffine(toInv[i])).map(Point.fromAffine) + } + + /** + * Converts hash string or Uint8Array to Point. + * @param hex short/long ECDSA hex + */ + static fromHex(hex: Hex): Point { + const P = Point.fromAffine(fromBytes(ensureBytes('pointHex', hex))) + P.assertValidity() + return P + } + + // Multiplies generator point by privateKey. + static fromPrivateKey(privateKey: PrivKey) { + return Point.BASE.multiply(normPrivateKeyToScalar(privateKey)) + } + + // Multiscalar Multiplication + static msm(points: Point[], scalars: bigint[]): Point { + return pippenger(Point, Fn, points, scalars) + } + + // "Private method", don't use it directly + _setWindowSize(windowSize: number) { + wnaf.setWindowSize(this, windowSize) + } + + // A point on curve is valid if it conforms to equation. + assertValidity(): void { + assertValidMemo(this) + } + + hasEvenY(): boolean { + const { y } = this.toAffine() + if (Fp.isOdd) return !Fp.isOdd(y) + throw new Error("Field doesn't support isOdd") + } + + /** + * Compare one point to another. + */ + equals(other: Point): boolean { + aprjpoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1)) + const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1)) + return U1 && U2 + } + + /** + * Flips point to one corresponding to (x, -y) in Affine coordinates. + */ + negate(): Point { + return new Point(this.px, Fp.neg(this.py), this.pz) + } + + // Renes-Costello-Batina exception-free doubling formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 3 + // Cost: 8M + 3S + 3*a + 2*b3 + 15add. + double() { + const { a, b } = CURVE + const b3 = Fp.mul(b, _3n) + const { px: X1, py: Y1, pz: Z1 } = this + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + let t0 = Fp.mul(X1, X1) // step 1 + let t1 = Fp.mul(Y1, Y1) + let t2 = Fp.mul(Z1, Z1) + let t3 = Fp.mul(X1, Y1) + t3 = Fp.add(t3, t3) // step 5 + Z3 = Fp.mul(X1, Z1) + Z3 = Fp.add(Z3, Z3) + X3 = Fp.mul(a, Z3) + Y3 = Fp.mul(b3, t2) + Y3 = Fp.add(X3, Y3) // step 10 + X3 = Fp.sub(t1, Y3) + Y3 = Fp.add(t1, Y3) + Y3 = Fp.mul(X3, Y3) + X3 = Fp.mul(t3, X3) + Z3 = Fp.mul(b3, Z3) // step 15 + t2 = Fp.mul(a, t2) + t3 = Fp.sub(t0, t2) + t3 = Fp.mul(a, t3) + t3 = Fp.add(t3, Z3) + Z3 = Fp.add(t0, t0) // step 20 + t0 = Fp.add(Z3, t0) + t0 = Fp.add(t0, t2) + t0 = Fp.mul(t0, t3) + Y3 = Fp.add(Y3, t0) + t2 = Fp.mul(Y1, Z1) // step 25 + t2 = Fp.add(t2, t2) + t0 = Fp.mul(t2, t3) + X3 = Fp.sub(X3, t0) + Z3 = Fp.mul(t2, t1) + Z3 = Fp.add(Z3, Z3) // step 30 + Z3 = Fp.add(Z3, Z3) + return new Point(X3, Y3, Z3) + } + + // Renes-Costello-Batina exception-free addition formula. + // There is 30% faster Jacobian formula, but it is not complete. + // https://eprint.iacr.org/2015/1060, algorithm 1 + // Cost: 12M + 0S + 3*a + 3*b3 + 23add. + add(other: Point): Point { + aprjpoint(other) + const { px: X1, py: Y1, pz: Z1 } = this + const { px: X2, py: Y2, pz: Z2 } = other + let X3 = Fp.ZERO, + Y3 = Fp.ZERO, + Z3 = Fp.ZERO // prettier-ignore + const a = CURVE.a + const b3 = Fp.mul(CURVE.b, _3n) + let t0 = Fp.mul(X1, X2) // step 1 + let t1 = Fp.mul(Y1, Y2) + let t2 = Fp.mul(Z1, Z2) + let t3 = Fp.add(X1, Y1) + let t4 = Fp.add(X2, Y2) // step 5 + t3 = Fp.mul(t3, t4) + t4 = Fp.add(t0, t1) + t3 = Fp.sub(t3, t4) + t4 = Fp.add(X1, Z1) + let t5 = Fp.add(X2, Z2) // step 10 + t4 = Fp.mul(t4, t5) + t5 = Fp.add(t0, t2) + t4 = Fp.sub(t4, t5) + t5 = Fp.add(Y1, Z1) + X3 = Fp.add(Y2, Z2) // step 15 + t5 = Fp.mul(t5, X3) + X3 = Fp.add(t1, t2) + t5 = Fp.sub(t5, X3) + Z3 = Fp.mul(a, t4) + X3 = Fp.mul(b3, t2) // step 20 + Z3 = Fp.add(X3, Z3) + X3 = Fp.sub(t1, Z3) + Z3 = Fp.add(t1, Z3) + Y3 = Fp.mul(X3, Z3) + t1 = Fp.add(t0, t0) // step 25 + t1 = Fp.add(t1, t0) + t2 = Fp.mul(a, t2) + t4 = Fp.mul(b3, t4) + t1 = Fp.add(t1, t2) + t2 = Fp.sub(t0, t2) // step 30 + t2 = Fp.mul(a, t2) + t4 = Fp.add(t4, t2) + t0 = Fp.mul(t1, t4) + Y3 = Fp.add(Y3, t0) + t0 = Fp.mul(t5, t4) // step 35 + X3 = Fp.mul(t3, X3) + X3 = Fp.sub(X3, t0) + t0 = Fp.mul(t3, t1) + Z3 = Fp.mul(t5, Z3) + Z3 = Fp.add(Z3, t0) // step 40 + return new Point(X3, Y3, Z3) + } + + subtract(other: Point) { + return this.add(other.negate()) + } + + is0() { + return this.equals(Point.ZERO) + } + + private wNAF(n: bigint): { p: Point; f: Point } { + return wnaf.wNAFCached(this, n, Point.normalizeZ) + } + + /** + * Non-constant-time multiplication. Uses double-and-add algorithm. + * It's faster, but should only be used when you don't care about + * an exposed private key e.g. sig verification, which works over *public* keys. + */ + multiplyUnsafe(sc: bigint): Point { + const { endo, n: N } = CURVE + aInRange('scalar', sc, _0n, N) + const I = Point.ZERO + if (sc === _0n) return I + if (this.is0() || sc === _1n) return this + + // Case a: no endomorphism. Case b: has precomputes. + if (!endo || wnaf.hasPrecomputes(this)) + return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ) + + // Case c: endomorphism + let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc) + let k1p = I + let k2p = I + let d: Point = this + while (k1 > _0n || k2 > _0n) { + if (k1 & _1n) k1p = k1p.add(d) + if (k2 & _1n) k2p = k2p.add(d) + d = d.double() + k1 >>= _1n + k2 >>= _1n + } + if (k1neg) k1p = k1p.negate() + if (k2neg) k2p = k2p.negate() + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + return k1p.add(k2p) + } + + /** + * Constant time multiplication. + * Uses wNAF method. Windowed method may be 10% faster, + * but takes 2x longer to generate and consumes 2x memory. + * Uses precomputes when available. + * Uses endomorphism for Koblitz curves. + * @param scalar by which the point would be multiplied + * @returns New point + */ + multiply(scalar: bigint): Point { + const { endo, n: N } = CURVE + aInRange('scalar', scalar, _1n, N) + let point: Point, fake: Point // Fake point is used to const-time mult + if (endo) { + const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar) + let { p: k1p, f: f1p } = this.wNAF(k1) + let { p: k2p, f: f2p } = this.wNAF(k2) + k1p = wnaf.constTimeNegate(k1neg, k1p) + k2p = wnaf.constTimeNegate(k2neg, k2p) + k2p = new Point(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz) + point = k1p.add(k2p) + fake = f1p.add(f2p) + } else { + const { p, f } = this.wNAF(scalar) + point = p + fake = f + } + // Normalize `z` for both points, but return only real one + return Point.normalizeZ([point, fake])[0] + } + + /** + * Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly. + * Not using Strauss-Shamir trick: precomputation tables are faster. + * The trick could be useful if both P and Q are not G (not in our case). + * @returns non-zero affine point + */ + multiplyAndAddUnsafe(Q: Point, a: bigint, b: bigint): Point | undefined { + const G = Point.BASE // No Strauss-Shamir trick: we have 10% faster G precomputes + const mul = ( + P: Point, + a: bigint, // Select faster multiply() method + ) => (a === _0n || a === _1n || !P.equals(G) ? P.multiplyUnsafe(a) : P.multiply(a)) + const sum = mul(this, a).add(mul(Q, b)) + return sum.is0() ? undefined : sum + } + + // Converts Projective point to affine (x, y) coordinates. + // Can accept precomputed Z^-1 - for example, from invertBatch. + // (x, y, z) ∋ (x=x/z, y=y/z) + toAffine(iz?: T): AffinePoint { + return toAffineMemo(this, iz) + } + isTorsionFree(): boolean { + const { h: cofactor, isTorsionFree } = CURVE + if (cofactor === _1n) return true // No subgroups, always torsion-free + if (isTorsionFree) return isTorsionFree(Point, this) + throw new Error('isTorsionFree() has not been declared for the elliptic curve') + } + clearCofactor(): Point { + const { h: cofactor, clearCofactor } = CURVE + if (cofactor === _1n) return this // Fast-path + if (clearCofactor) return clearCofactor(Point, this) as Point + return this.multiplyUnsafe(CURVE.h) + } + + toRawBytes(isCompressed = true): Uint8Array { + abool('isCompressed', isCompressed) + this.assertValidity() + return toBytes(Point, this, isCompressed) + } + + toHex(isCompressed = true): string { + abool('isCompressed', isCompressed) + return bytesToHex(this.toRawBytes(isCompressed)) + } + } + const _bits = CURVE.nBitLength + const wnaf = wNAF(Point, CURVE.endo ? Math.ceil(_bits / 2) : _bits) + // Validate if generator point is on curve + return { + CURVE, + ProjectivePoint: Point as ProjConstructor, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } +} + +// Instance +export interface SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + assertValidity(): void + addRecoveryBit(recovery: number): RecoveredSignatureType + hasHighS(): boolean + normalizeS(): SignatureType + recoverPublicKey(msgHash: Hex): ProjPointType + toCompactRawBytes(): Uint8Array + toCompactHex(): string + toDERRawBytes(isCompressed?: boolean): Uint8Array + toDERHex(isCompressed?: boolean): string +} +export type RecoveredSignatureType = SignatureType & { + readonly recovery: number +} +// Static methods +export type SignatureConstructor = { + new (r: bigint, s: bigint): SignatureType + fromCompact(hex: Hex): SignatureType + fromDER(hex: Hex): SignatureType +} +type SignatureLike = { r: bigint; s: bigint } + +export type PubKey = Hex | ProjPointType + +export type CurveType = BasicWCurve & { + hash: CHash // CHash not FHash because we need outputLen for DRBG + hmac: HmacFnSync + randomBytes: (bytesLength?: number) => Uint8Array + lowS?: boolean + bits2int?: (bytes: Uint8Array) => bigint + bits2int_modN?: (bytes: Uint8Array) => bigint +} + +function validateOpts( + curve: CurveType, +): Readonly { + const opts = validateBasic(curve) + validateObject( + opts, + { + hash: 'hash', + hmac: 'function', + randomBytes: 'function', + }, + { + bits2int: 'function', + bits2int_modN: 'function', + lowS: 'boolean', + }, + ) + return Object.freeze({ lowS: true, ...opts } as const) +} + +export type CurveFn = { + CURVE: ReturnType + getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array + getSharedSecret: (privateA: PrivKey, publicB: Hex, isCompressed?: boolean) => Uint8Array + sign: (msgHash: Hex, privKey: PrivKey, opts?: SignOpts) => RecoveredSignatureType + verify: (signature: Hex | SignatureLike, msgHash: Hex, publicKey: Hex, opts?: VerOpts) => boolean + ProjectivePoint: ProjConstructor + Signature: SignatureConstructor + utils: { + normPrivateKeyToScalar: (key: PrivKey) => bigint + isValidPrivateKey(privateKey: PrivKey): boolean + randomPrivateKey: () => Uint8Array + precompute: (windowSize?: number, point?: ProjPointType) => ProjPointType + } +} + +/** + * Creates short weierstrass curve and ECDSA signature methods for it. + * @example + * import { Field } from '@noble/curves/abstract/modular'; + * // Before that, define BigInt-s: a, b, p, n, Gx, Gy + * const curve = weierstrass({ a, b, Fp: Field(p), n, Gx, Gy, h: 1n }) + */ +export function weierstrass(curveDef: CurveType): CurveFn { + const CURVE = validateOpts(curveDef) as ReturnType + const { Fp, n: CURVE_ORDER } = CURVE + const compressedLen = Fp.BYTES + 1 // e.g. 33 for 32 + const uncompressedLen = 2 * Fp.BYTES + 1 // e.g. 65 for 32 + + function modN(a: bigint) { + return mod(a, CURVE_ORDER) + } + function invN(a: bigint) { + return invert(a, CURVE_ORDER) + } + + const { + ProjectivePoint: Point, + normPrivateKeyToScalar, + weierstrassEquation, + isWithinCurveOrder, + } = weierstrassPoints({ + ...CURVE, + toBytes(_c, point, isCompressed: boolean): Uint8Array { + const a = point.toAffine() + const x = Fp.toBytes(a.x) + const cat = concatBytes + abool('isCompressed', isCompressed) + if (isCompressed) { + return cat(Uint8Array.from([point.hasEvenY() ? 0x02 : 0x03]), x) + } else { + return cat(Uint8Array.from([0x04]), x, Fp.toBytes(a.y)) + } + }, + fromBytes(bytes: Uint8Array) { + const len = bytes.length + const head = bytes[0] + const tail = bytes.subarray(1) + // this.assertValidity() is done inside of fromHex + if (len === compressedLen && (head === 0x02 || head === 0x03)) { + const x = bytesToNumberBE(tail) + if (!inRange(x, _1n, Fp.ORDER)) throw new Error('Point is not on curve') + const y2 = weierstrassEquation(x) // y² = x³ + ax + b + let y: bigint + try { + y = Fp.sqrt(y2) // y = y² ^ (p+1)/4 + } catch (sqrtError) { + const suffix = sqrtError instanceof Error ? ': ' + sqrtError.message : '' + throw new Error('Point is not on curve' + suffix) + } + const isYOdd = (y & _1n) === _1n + // ECDSA + const isHeadOdd = (head & 1) === 1 + if (isHeadOdd !== isYOdd) y = Fp.neg(y) + return { x, y } + } else if (len === uncompressedLen && head === 0x04) { + const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES)) + const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES)) + return { x, y } + } else { + const cl = compressedLen + const ul = uncompressedLen + throw new Error( + 'invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len, + ) + } + }, + }) + const numToNByteHex = (num: bigint): string => bytesToHex(numberToBytesBE(num, CURVE.nByteLength)) + + function isBiggerThanHalfOrder(number: bigint) { + const HALF = CURVE_ORDER >> _1n + return number > HALF + } + + function normalizeS(s: bigint) { + return isBiggerThanHalfOrder(s) ? modN(-s) : s + } + // slice bytes num + const slcNum = (b: Uint8Array, from: number, to: number) => bytesToNumberBE(b.slice(from, to)) + + /** + * ECDSA signature with its (r, s) properties. Supports DER & compact representations. + */ + class Signature implements SignatureType { + readonly r: bigint + readonly s: bigint + readonly recovery?: number + constructor(r: bigint, s: bigint, recovery?: number) { + aInRange('r', r, _1n, CURVE_ORDER) // r in [1..N] + aInRange('s', s, _1n, CURVE_ORDER) // s in [1..N] + this.r = r + this.s = s + if (recovery != null) this.recovery = recovery + Object.freeze(this) + } + + // pair (bytes of r, bytes of s) + static fromCompact(hex: Hex) { + const l = CURVE.nByteLength + hex = ensureBytes('compactSignature', hex, l * 2) + return new Signature(slcNum(hex, 0, l), slcNum(hex, l, 2 * l)) + } + + // DER encoded ECDSA signature + // https://bitcoin.stackexchange.com/questions/57644/what-are-the-parts-of-a-bitcoin-transaction-input-script + static fromDER(hex: Hex) { + const { r, s } = DER.toSig(ensureBytes('DER', hex)) + return new Signature(r, s) + } + + /** + * @todo remove + * @deprecated + */ + assertValidity(): void {} + + addRecoveryBit(recovery: number): RecoveredSignature { + return new Signature(this.r, this.s, recovery) as RecoveredSignature + } + + recoverPublicKey(msgHash: Hex): typeof Point.BASE { + const { r, s, recovery: rec } = this + const h = bits2int_modN(ensureBytes('msgHash', msgHash)) // Truncate hash + if (rec == null || ![0, 1, 2, 3].includes(rec)) throw new Error('recovery id invalid') + const radj = rec === 2 || rec === 3 ? r + CURVE.n : r + if (radj >= Fp.ORDER) throw new Error('recovery id 2 or 3 invalid') + const prefix = (rec & 1) === 0 ? '02' : '03' + const R = Point.fromHex(prefix + numToNByteHex(radj)) + const ir = invN(radj) // r^-1 + const u1 = modN(-h * ir) // -hr^-1 + const u2 = modN(s * ir) // sr^-1 + const Q = Point.BASE.multiplyAndAddUnsafe(R, u1, u2) // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1) + if (!Q) throw new Error('point at infinify') // unsafe is fine: no priv data leaked + Q.assertValidity() + return Q + } + + // Signatures should be low-s, to prevent malleability. + hasHighS(): boolean { + return isBiggerThanHalfOrder(this.s) + } + + normalizeS() { + return this.hasHighS() ? new Signature(this.r, modN(-this.s), this.recovery) : this + } + + // DER-encoded + toDERRawBytes() { + return hexToBytes(this.toDERHex()) + } + toDERHex() { + return DER.hexFromSig({ r: this.r, s: this.s }) + } + + // padded bytes of r, then padded bytes of s + toCompactRawBytes() { + return hexToBytes(this.toCompactHex()) + } + toCompactHex() { + return numToNByteHex(this.r) + numToNByteHex(this.s) + } + } + type RecoveredSignature = Signature & { recovery: number } + + const utils = { + isValidPrivateKey(privateKey: PrivKey) { + try { + normPrivateKeyToScalar(privateKey) + return true + } catch (error) { + return false + } + }, + normPrivateKeyToScalar: normPrivateKeyToScalar, + + /** + * Produces cryptographically secure private key from random of size + * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible. + */ + randomPrivateKey: (): Uint8Array => { + const length = getMinHashLength(CURVE.n) + return mapHashToField(CURVE.randomBytes(length), CURVE.n) + }, + + /** + * Creates precompute table for an arbitrary EC point. Makes point "cached". + * Allows to massively speed-up `point.multiply(scalar)`. + * @returns cached point + * @example + * const fast = utils.precompute(8, ProjectivePoint.fromHex(someonesPubKey)); + * fast.multiply(privKey); // much faster ECDH now + */ + precompute(windowSize = 8, point = Point.BASE): typeof Point.BASE { + point._setWindowSize(windowSize) + point.multiply(BigInt(3)) // 3 is arbitrary, just need any number here + return point + }, + } + + /** + * Computes public key for a private key. Checks for validity of the private key. + * @param privateKey private key + * @param isCompressed whether to return compact (default), or full key + * @returns Public key, full when isCompressed=false; short when isCompressed=true + */ + function getPublicKey(privateKey: PrivKey, isCompressed = true): Uint8Array { + return Point.fromPrivateKey(privateKey).toRawBytes(isCompressed) + } + + /** + * Quick and dirty check for item being public key. Does not validate hex, or being on-curve. + */ + function isProbPub(item: PrivKey | PubKey): boolean { + const arr = isBytes(item) + const str = typeof item === 'string' + const len = (arr || str) && (item as Hex).length + if (arr) return len === compressedLen || len === uncompressedLen + if (str) return len === 2 * compressedLen || len === 2 * uncompressedLen + if (item instanceof Point) return true + return false + } + + /** + * ECDH (Elliptic Curve Diffie Hellman). + * Computes shared public key from private key and public key. + * Checks: 1) private key validity 2) shared key is on-curve. + * Does NOT hash the result. + * @param privateA private key + * @param publicB different public key + * @param isCompressed whether to return compact (default), or full key + * @returns shared public key + */ + function getSharedSecret(privateA: PrivKey, publicB: Hex, isCompressed = true): Uint8Array { + if (isProbPub(privateA)) throw new Error('first arg must be private key') + if (!isProbPub(publicB)) throw new Error('second arg must be public key') + const b = Point.fromHex(publicB) // check for being on-curve + return b.multiply(normPrivateKeyToScalar(privateA)).toRawBytes(isCompressed) + } + + // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets. + // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int. + // bits2int can produce res>N, we can do mod(res, N) since the bitLen is the same. + // int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors + const bits2int = + CURVE.bits2int || + function (bytes: Uint8Array): bigint { + // Our custom check "just in case" + if (bytes.length > 8192) throw new Error('input is too large') + // For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m) + // for some cases, since bytes.length * 8 is not actual bitLength. + const num = bytesToNumberBE(bytes) // check for == u8 done here + const delta = bytes.length * 8 - CURVE.nBitLength // truncate to nBitLength leftmost bits + return delta > 0 ? num >> BigInt(delta) : num + } + const bits2int_modN = + CURVE.bits2int_modN || + function (bytes: Uint8Array): bigint { + return modN(bits2int(bytes)) // can't use bytesToNumberBE here + } + // NOTE: pads output with zero as per spec + const ORDER_MASK = bitMask(CURVE.nBitLength) + /** + * Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`. + */ + function int2octets(num: bigint): Uint8Array { + aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK) + // works with order, can have different size than numToField! + return numberToBytesBE(num, CURVE.nByteLength) + } + + // Steps A, D of RFC6979 3.2 + // Creates RFC6979 seed; converts msg/privKey to numbers. + // Used only in sign, not in verify. + // NOTE: we cannot assume here that msgHash has same amount of bytes as curve order, + // this will be invalid at least for P521. Also it can be bigger for P224 + SHA256 + function prepSig(msgHash: Hex, privateKey: PrivKey, opts = defaultSigOpts) { + if (['recovered', 'canonical'].some((k) => k in opts)) + throw new Error('sign() legacy options not supported') + const { hash, randomBytes } = CURVE + let { lowS, prehash, extraEntropy: ent } = opts // generates low-s sigs by default + if (lowS == null) lowS = true // RFC6979 3.2: we skip step A, because we already provide hash + msgHash = ensureBytes('msgHash', msgHash) + validateSigVerOpts(opts) + if (prehash) msgHash = ensureBytes('prehashed msgHash', hash(msgHash)) + + // We can't later call bits2octets, since nested bits2int is broken for curves + // with nBitLength % 8 !== 0. Because of that, we unwrap it here as int2octets call. + // const bits2octets = (bits) => int2octets(bits2int_modN(bits)) + const h1int = bits2int_modN(msgHash) + const d = normPrivateKeyToScalar(privateKey) // validate private key, convert to bigint + const seedArgs = [int2octets(d), int2octets(h1int)] + // extraEntropy. RFC6979 3.6: additional k' (optional). + if (ent != null && ent !== false) { + // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k') + const e = ent === true ? randomBytes(Fp.BYTES) : ent // generate random bytes OR pass as-is + seedArgs.push(ensureBytes('extraEntropy', e)) // check for being bytes + } + const seed = concatBytes(...seedArgs) // Step D of RFC6979 3.2 + const m = h1int // NOTE: no need to call bits2int second time here, it is inside truncateHash! + // Converts signature params into point w r/s, checks result for validity. + function k2sig(kBytes: Uint8Array): RecoveredSignature | undefined { + // RFC 6979 Section 3.2, step 3: k = bits2int(T) + const k = bits2int(kBytes) // Cannot use fields methods, since it is group element + if (!isWithinCurveOrder(k)) return // Important: all mod() calls here must be done over N + const ik = invN(k) // k^-1 mod n + const q = Point.BASE.multiply(k).toAffine() // q = Gk + const r = modN(q.x) // r = q.x mod n + if (r === _0n) return + // Can use scalar blinding b^-1(bm + bdr) where b ∈ [1,q−1] according to + // https://tches.iacr.org/index.php/TCHES/article/view/7337/6509. We've decided against it: + // a) dependency on CSPRNG b) 15% slowdown c) doesn't really help since bigints are not CT + const s = modN(ik * modN(m + r * d)) // Not using blinding here + if (s === _0n) return + let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n) // recovery bit (2 or 3, when q.x > n) + let normS = s + if (lowS && isBiggerThanHalfOrder(s)) { + normS = normalizeS(s) // if lowS was passed, ensure s is always + recovery ^= 1 // // in the bottom half of N + } + return new Signature(r, normS, recovery) as RecoveredSignature // use normS, not s + } + return { seed, k2sig } + } + const defaultSigOpts: SignOpts = { lowS: CURVE.lowS, prehash: false } + const defaultVerOpts: VerOpts = { lowS: CURVE.lowS, prehash: false } + + /** + * Signs message hash with a private key. + * ``` + * sign(m, d, k) where + * (x, y) = G × k + * r = x mod n + * s = (m + dr)/k mod n + * ``` + * @param msgHash NOT message. msg needs to be hashed to `msgHash`, or use `prehash`. + * @param privKey private key + * @param opts lowS for non-malleable sigs. extraEntropy for mixing randomness into k. prehash will hash first arg. + * @returns signature with recovery param + */ + function sign(msgHash: Hex, privKey: PrivKey, opts = defaultSigOpts): RecoveredSignature { + const { seed, k2sig } = prepSig(msgHash, privKey, opts) // Steps A, D of RFC6979 3.2. + const C = CURVE + const drbg = createHmacDrbg(C.hash.outputLen, C.nByteLength, C.hmac) + return drbg(seed, k2sig) // Steps B, C, D, E, F, G + } + + // Enable precomputes. Slows down first publicKey computation by 20ms. + Point.BASE._setWindowSize(8) + // utils.precompute(8, ProjectivePoint.BASE) + + /** + * Verifies a signature against message hash and public key. + * Rejects lowS signatures by default: to override, + * specify option `{lowS: false}`. Implements section 4.1.4 from https://www.secg.org/sec1-v2.pdf: + * + * ``` + * verify(r, s, h, P) where + * U1 = hs^-1 mod n + * U2 = rs^-1 mod n + * R = U1⋅G - U2⋅P + * mod(R.x, n) == r + * ``` + */ + function verify( + signature: Hex | SignatureLike, + msgHash: Hex, + publicKey: Hex, + opts = defaultVerOpts, + ): boolean { + const sg = signature + msgHash = ensureBytes('msgHash', msgHash) + publicKey = ensureBytes('publicKey', publicKey) + const { lowS, prehash, format } = opts + + // Verify opts, deduce signature format + validateSigVerOpts(opts) + if ('strict' in opts) throw new Error('options.strict was renamed to lowS') + if (format !== undefined && format !== 'compact' && format !== 'der') + throw new Error('format must be compact or der') + const isHex = typeof sg === 'string' || isBytes(sg) + const isObj = + !isHex && + !format && + typeof sg === 'object' && + sg !== null && + typeof sg.r === 'bigint' && + typeof sg.s === 'bigint' + if (!isHex && !isObj) + throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance') + + let _sig: Signature | undefined = undefined + let P: ProjPointType + try { + if (isObj) _sig = new Signature(sg.r, sg.s) + if (isHex) { + // Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length). + // Since DER can also be 2*nByteLength bytes, we check for it first. + try { + if (format !== 'compact') _sig = Signature.fromDER(sg) + } catch (derError) { + if (!(derError instanceof DER.Err)) throw derError + } + if (!_sig && format !== 'der') _sig = Signature.fromCompact(sg) + } + P = Point.fromHex(publicKey) + } catch (error) { + return false + } + if (!_sig) return false + if (lowS && _sig.hasHighS()) return false + if (prehash) msgHash = CURVE.hash(msgHash) + const { r, s } = _sig + const h = bits2int_modN(msgHash) // Cannot use fields methods, since it is group element + const is = invN(s) // s^-1 + const u1 = modN(h * is) // u1 = hs^-1 mod n + const u2 = modN(r * is) // u2 = rs^-1 mod n + const R = Point.BASE.multiplyAndAddUnsafe(P, u1, u2)?.toAffine() // R = u1⋅G + u2⋅P + if (!R) return false + const v = modN(R.x) + return v === r + } + return { + CURVE, + getPublicKey, + getSharedSecret, + sign, + verify, + ProjectivePoint: Point, + Signature, + utils, + } +} + +/** + * Implementation of the Shallue and van de Woestijne method for any weierstrass curve. + * TODO: check if there is a way to merge this with uvRatio in Edwards; move to modular. + * b = True and y = sqrt(u / v) if (u / v) is square in F, and + * b = False and y = sqrt(Z * (u / v)) otherwise. + * @param Fp + * @param Z + * @returns + */ +export function SWUFpSqrtRatio( + Fp: IField, + Z: T, +): (u: T, v: T) => { isValid: boolean; value: T } { + // Generic implementation + const q = Fp.ORDER + let l = _0n + for (let o = q - _1n; o % _2n === _0n; o /= _2n) l += _1n + const c1 = l // 1. c1, the largest integer such that 2^c1 divides q - 1. + // We need 2n ** c1 and 2n ** (c1-1). We can't use **; but we can use <<. + // 2n ** c1 == 2n << (c1-1) + const _2n_pow_c1_1 = _2n << (c1 - _1n - _1n) + const _2n_pow_c1 = _2n_pow_c1_1 * _2n + const c2 = (q - _1n) / _2n_pow_c1 // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic + const c3 = (c2 - _1n) / _2n // 3. c3 = (c2 - 1) / 2 # Integer arithmetic + const c4 = _2n_pow_c1 - _1n // 4. c4 = 2^c1 - 1 # Integer arithmetic + const c5 = _2n_pow_c1_1 // 5. c5 = 2^(c1 - 1) # Integer arithmetic + const c6 = Fp.pow(Z, c2) // 6. c6 = Z^c2 + const c7 = Fp.pow(Z, (c2 + _1n) / _2n) // 7. c7 = Z^((c2 + 1) / 2) + let sqrtRatio = (u: T, v: T): { isValid: boolean; value: T } => { + let tv1 = c6 // 1. tv1 = c6 + let tv2 = Fp.pow(v, c4) // 2. tv2 = v^c4 + let tv3 = Fp.sqr(tv2) // 3. tv3 = tv2^2 + tv3 = Fp.mul(tv3, v) // 4. tv3 = tv3 * v + let tv5 = Fp.mul(u, tv3) // 5. tv5 = u * tv3 + tv5 = Fp.pow(tv5, c3) // 6. tv5 = tv5^c3 + tv5 = Fp.mul(tv5, tv2) // 7. tv5 = tv5 * tv2 + tv2 = Fp.mul(tv5, v) // 8. tv2 = tv5 * v + tv3 = Fp.mul(tv5, u) // 9. tv3 = tv5 * u + let tv4 = Fp.mul(tv3, tv2) // 10. tv4 = tv3 * tv2 + tv5 = Fp.pow(tv4, c5) // 11. tv5 = tv4^c5 + let isQR = Fp.eql(tv5, Fp.ONE) // 12. isQR = tv5 == 1 + tv2 = Fp.mul(tv3, c7) // 13. tv2 = tv3 * c7 + tv5 = Fp.mul(tv4, tv1) // 14. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, isQR) // 15. tv3 = CMOV(tv2, tv3, isQR) + tv4 = Fp.cmov(tv5, tv4, isQR) // 16. tv4 = CMOV(tv5, tv4, isQR) + // 17. for i in (c1, c1 - 1, ..., 2): + for (let i = c1; i > _1n; i--) { + let tv5 = i - _2n // 18. tv5 = i - 2 + tv5 = _2n << (tv5 - _1n) // 19. tv5 = 2^tv5 + let tvv5 = Fp.pow(tv4, tv5) // 20. tv5 = tv4^tv5 + const e1 = Fp.eql(tvv5, Fp.ONE) // 21. e1 = tv5 == 1 + tv2 = Fp.mul(tv3, tv1) // 22. tv2 = tv3 * tv1 + tv1 = Fp.mul(tv1, tv1) // 23. tv1 = tv1 * tv1 + tvv5 = Fp.mul(tv4, tv1) // 24. tv5 = tv4 * tv1 + tv3 = Fp.cmov(tv2, tv3, e1) // 25. tv3 = CMOV(tv2, tv3, e1) + tv4 = Fp.cmov(tvv5, tv4, e1) // 26. tv4 = CMOV(tv5, tv4, e1) + } + return { isValid: isQR, value: tv3 } + } + if (Fp.ORDER % _4n === _3n) { + // sqrt_ratio_3mod4(u, v) + const c1 = (Fp.ORDER - _3n) / _4n // 1. c1 = (q - 3) / 4 # Integer arithmetic + const c2 = Fp.sqrt(Fp.neg(Z)) // 2. c2 = sqrt(-Z) + sqrtRatio = (u: T, v: T) => { + let tv1 = Fp.sqr(v) // 1. tv1 = v^2 + const tv2 = Fp.mul(u, v) // 2. tv2 = u * v + tv1 = Fp.mul(tv1, tv2) // 3. tv1 = tv1 * tv2 + let y1 = Fp.pow(tv1, c1) // 4. y1 = tv1^c1 + y1 = Fp.mul(y1, tv2) // 5. y1 = y1 * tv2 + const y2 = Fp.mul(y1, c2) // 6. y2 = y1 * c2 + const tv3 = Fp.mul(Fp.sqr(y1), v) // 7. tv3 = y1^2; 8. tv3 = tv3 * v + const isQR = Fp.eql(tv3, u) // 9. isQR = tv3 == u + let y = Fp.cmov(y2, y1, isQR) // 10. y = CMOV(y2, y1, isQR) + return { isValid: isQR, value: y } // 11. return (isQR, y) isQR ? y : y*c2 + } + } + // No curves uses that + // if (Fp.ORDER % _8n === _5n) // sqrt_ratio_5mod8 + return sqrtRatio +} +/** + * Simplified Shallue-van de Woestijne-Ulas Method + * https://www.rfc-editor.org/rfc/rfc9380#section-6.6.2 + */ +export function mapToCurveSimpleSWU( + Fp: IField, + opts: { + A: T + B: T + Z: T + }, +): (u: T) => { x: T; y: T } { + validateField(Fp) + if (!Fp.isValid(opts.A) || !Fp.isValid(opts.B) || !Fp.isValid(opts.Z)) + throw new Error('mapToCurveSimpleSWU: invalid opts') + const sqrtRatio = SWUFpSqrtRatio(Fp, opts.Z) + if (!Fp.isOdd) throw new Error('Fp.isOdd is not implemented!') + // Input: u, an element of F. + // Output: (x, y), a point on E. + return (u: T): { x: T; y: T } => { + // prettier-ignore + let tv1, tv2, tv3, tv4, tv5, tv6, x, y + tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, opts.Z) // 2. tv1 = Z * tv1 + tv2 = Fp.sqr(tv1) // 3. tv2 = tv1^2 + tv2 = Fp.add(tv2, tv1) // 4. tv2 = tv2 + tv1 + tv3 = Fp.add(tv2, Fp.ONE) // 5. tv3 = tv2 + 1 + tv3 = Fp.mul(tv3, opts.B) // 6. tv3 = B * tv3 + tv4 = Fp.cmov(opts.Z, Fp.neg(tv2), !Fp.eql(tv2, Fp.ZERO)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) + tv4 = Fp.mul(tv4, opts.A) // 8. tv4 = A * tv4 + tv2 = Fp.sqr(tv3) // 9. tv2 = tv3^2 + tv6 = Fp.sqr(tv4) // 10. tv6 = tv4^2 + tv5 = Fp.mul(tv6, opts.A) // 11. tv5 = A * tv6 + tv2 = Fp.add(tv2, tv5) // 12. tv2 = tv2 + tv5 + tv2 = Fp.mul(tv2, tv3) // 13. tv2 = tv2 * tv3 + tv6 = Fp.mul(tv6, tv4) // 14. tv6 = tv6 * tv4 + tv5 = Fp.mul(tv6, opts.B) // 15. tv5 = B * tv6 + tv2 = Fp.add(tv2, tv5) // 16. tv2 = tv2 + tv5 + x = Fp.mul(tv1, tv3) // 17. x = tv1 * tv3 + const { isValid, value } = sqrtRatio(tv2, tv6) // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6) + y = Fp.mul(tv1, u) // 19. y = tv1 * u -> Z * u^3 * y1 + y = Fp.mul(y, value) // 20. y = y * y1 + x = Fp.cmov(x, tv3, isValid) // 21. x = CMOV(x, tv3, is_gx1_square) + y = Fp.cmov(y, value, isValid) // 22. y = CMOV(y, y1, is_gx1_square) + const e1 = Fp.isOdd!(u) === Fp.isOdd!(y) // 23. e1 = sgn0(u) == sgn0(y) + y = Fp.cmov(Fp.neg(y), y, e1) // 24. y = CMOV(-y, y, e1) + x = Fp.div(x, tv4) // 25. x = x / tv4 + return { x, y } + } +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/bls12-381.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/bls12-381.ts new file mode 100644 index 00000000000..067591e0a98 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/bls12-381.ts @@ -0,0 +1,776 @@ +/** + * bls12-381 is pairing-friendly Barreto-Lynn-Scott elliptic curve construction allowing to: + * * Construct zk-SNARKs at the ~120-bit security + * * Efficiently verify N aggregate signatures with 1 pairing and N ec additions: + * the Boneh-Lynn-Shacham signature scheme is orders of magnitude more efficient than Schnorr + * + * ### Summary + * 1. BLS Relies on Bilinear Pairing (expensive) + * 2. Private Keys: 32 bytes + * 3. Public Keys: 48 bytes: 381 bit affine x coordinate, encoded into 48 big-endian bytes. + * 4. Signatures: 96 bytes: two 381 bit integers (affine x coordinate), encoded into two 48 big-endian byte arrays. + * - The signature is a point on the G2 subgroup, which is defined over a finite field + * with elements twice as big as the G1 curve (G2 is over Fp2 rather than Fp. Fp2 is analogous to the + * complex numbers). + * - We also support reversed 96-byte pubkeys & 48-byte short signatures. + * 5. The 12 stands for the Embedding degree. + * + * ### Formulas + * - `P = pk x G` - public keys + * - `S = pk x H(m)` - signing + * - `e(P, H(m)) == e(G, S)` - verification using pairings + * - `e(G, S) = e(G, SUM(n)(Si)) = MUL(n)(e(G, Si))` - signature aggregation + * + * ### Compatibility and notes + * 1. It is compatible with Algorand, Chia, Dfinity, Ethereum, Filecoin, ZEC. + * Filecoin uses little endian byte arrays for private keys - make sure to reverse byte order. + * 2. Some projects use G2 for public keys and G1 for signatures. It's called "short signature". + * 3. Curve security level is about 120 bits as per [Barbulescu-Duquesne 2017](https://hal.science/hal-01534101/file/main.pdf) + * 4. Compatible with specs: + * [cfrg-pairing-friendly-curves-11](https://tools.ietf.org/html/draft-irtf-cfrg-pairing-friendly-curves-11), + * [cfrg-bls-signature-05](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05), + * RFC 9380. + * + * ### Params + * To verify curve parameters, see + * [pairing-friendly-curves spec](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11). + * Basic math is done over finite fields over p. + * More complicated math is done over polynominal extension fields. + * To simplify calculations in Fp12, we construct extension tower: + * + * Embedding degree (k): 12 + * Seed (X): -15132376222941642752 + * Fr: (x⁴-x²+1) + * Fp: ((x-1)² ⋅ r(x)/3+x) + * (E/Fp): Y²=X³+4 + * (Eₜ/Fp²): Y² = X³+4(u+1) (M-type twist) + * Ate loop size: X + * + * ### Towers + * - Fp₁₂ = Fp₆² => Fp₂³ + * - Fp(u) / (u² - β) where β = -1 + * - Fp₂(v) / (v³ - ξ) where ξ = u + 1 + * - Fp₆(w) / (w² - γ) where γ = v + * - Fp²[u] = Fp/u²+1 + * - Fp⁶[v] = Fp²/v³-1-u + * - Fp¹²[w] = Fp⁶/w²-v + * + * @todo construct bls & bn fp/fr from seed. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFn, bls } from './abstract/bls.ts' +// Types +import { isogenyMap } from './abstract/hash-to-curve.ts' +import { Field } from './abstract/modular.ts' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' +import { psiFrobenius, tower12 } from './abstract/tower.ts' +import { + type Hex, + bitGet, + bitLen, + bytesToHex, + bytesToNumberBE, + concatBytes as concatB, + ensureBytes, + numberToBytesBE, +} from './abstract/utils.ts' +import { + type AffinePoint, + type ProjPointType, + mapToCurveSimpleSWU, +} from './abstract/weierstrass.ts' + +// Be friendly to bad ECMAScript parsers by not using bigint literals +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4) + +// The BLS parameter x (seed) for BLS12-381. NOTE: it is negative! +const BLS_X = BigInt('0xd201000000010000') +const BLS_X_LEN = bitLen(BLS_X) + +// CURVE FIELDS +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + // Order of Fp + ORDER: BigInt( + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab', + ), + // Finite extension field over irreducible polynominal. + // Fp(u) / (u² - β) where β = -1 + FP2_NONRESIDUE: [_1n, _1n], + Fp2mulByB: ({ c0, c1 }) => { + const t0 = Fp.mul(c0, _4n) // 4 * c0 + const t1 = Fp.mul(c1, _4n) // 4 * c1 + // (T0-T1) + (T0+T1)*i + return { c0: Fp.sub(t0, t1), c1: Fp.add(t0, t1) } + }, + // Fp12 + // A cyclotomic group is a subgroup of Fp^n defined by + // GΦₙ(p) = {α ∈ Fpⁿ : α^Φₙ(p) = 1} + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + const t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BLS_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const x = BLS_X + // this^(q⁶) / this + const t0 = Fp12.div(Fp12.frobeniusMap(num, 6), num) + // t0^(q²) * t0 + const t1 = Fp12.mul(Fp12.frobeniusMap(t0, 2), t0) + const t2 = Fp12.conjugate(Fp12._cyclotomicExp(t1, x)) + const t3 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicSquare(t1)), t2) + const t4 = Fp12.conjugate(Fp12._cyclotomicExp(t3, x)) + const t5 = Fp12.conjugate(Fp12._cyclotomicExp(t4, x)) + const t6 = Fp12.mul(Fp12.conjugate(Fp12._cyclotomicExp(t5, x)), Fp12._cyclotomicSquare(t2)) + const t7 = Fp12.conjugate(Fp12._cyclotomicExp(t6, x)) + const t2_t5_pow_q2 = Fp12.frobeniusMap(Fp12.mul(t2, t5), 2) + const t4_t1_pow_q3 = Fp12.frobeniusMap(Fp12.mul(t4, t1), 3) + const t6_t1c_pow_q1 = Fp12.frobeniusMap(Fp12.mul(t6, Fp12.conjugate(t1)), 1) + const t7_t3c_t1 = Fp12.mul(Fp12.mul(t7, Fp12.conjugate(t3)), t1) + // (t2 * t5)^(q²) * (t4 * t1)^(q³) * (t6 * t1.conj)^(q^1) * t7 * t3.conj * t1 + return Fp12.mul(Fp12.mul(Fp12.mul(t2_t5_pow_q2, t4_t1_pow_q3), t6_t1c_pow_q1), t7_t3c_t1) + }, +}) + +// Finite field over r. +// This particular field is not used anywhere in bls12-381, but it is still useful. +const Fr = Field(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001')) + +// END OF CURVE FIELDS + +// HashToCurve + +// 3-isogeny map from E' to E https://www.rfc-editor.org/rfc/rfc9380#appendix-E.3 +const isogenyMapG2 = isogenyMap( + Fp2, + [ + // xNum + [ + [ + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6', + ], + [ + '0x0', + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d', + ], + [ + '0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1', + '0x0', + ], + ], + // xDen + [ + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63', + ], + [ + '0xc', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f', + ], + ['0x1', '0x0'], // LAST 1 + ], + // yNum + [ + [ + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + '0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706', + ], + [ + '0x0', + '0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be', + ], + [ + '0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c', + '0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f', + ], + [ + '0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10', + '0x0', + ], + ], + // yDen + [ + [ + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb', + ], + [ + '0x0', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3', + ], + [ + '0x12', + '0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99', + ], + ['0x1', '0x0'], // LAST 1 + ], + ].map((i) => i.map((pair) => Fp2.fromBigTuple(pair.map(BigInt)))) as [Fp2[], Fp2[], Fp2[], Fp2[]], +) +// 11-isogeny map from E' to E +const isogenyMapG1 = isogenyMap( + Fp, + [ + // xNum + [ + '0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7', + '0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb', + '0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0', + '0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861', + '0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9', + '0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983', + '0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84', + '0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e', + '0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317', + '0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e', + '0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b', + '0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229', + ], + // xDen + [ + '0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c', + '0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff', + '0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19', + '0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8', + '0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e', + '0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5', + '0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a', + '0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e', + '0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641', + '0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33', + '0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696', + '0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6', + '0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb', + '0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb', + '0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0', + '0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2', + '0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29', + '0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587', + '0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30', + '0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132', + '0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e', + '0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8', + '0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133', + '0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b', + '0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604', + ], + // yDen + [ + '0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1', + '0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d', + '0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2', + '0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416', + '0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d', + '0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac', + '0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c', + '0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9', + '0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a', + '0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55', + '0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8', + '0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092', + '0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc', + '0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7', + '0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f', + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [Fp[], Fp[], Fp[], Fp[]], +) + +// SWU Map - Fp2 to G2': y² = x³ + 240i * x + 1012 + 1012i +const G2_SWU = mapToCurveSimpleSWU(Fp2, { + A: Fp2.create({ c0: Fp.create(_0n), c1: Fp.create(BigInt(240)) }), // A' = 240 * I + B: Fp2.create({ c0: Fp.create(BigInt(1012)), c1: Fp.create(BigInt(1012)) }), // B' = 1012 * (1 + I) + Z: Fp2.create({ c0: Fp.create(BigInt(-2)), c1: Fp.create(BigInt(-1)) }), // Z: -(2 + I) +}) +// Optimized SWU Map - Fp to G1 +const G1_SWU = mapToCurveSimpleSWU(Fp, { + A: Fp.create( + BigInt( + '0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d', + ), + ), + B: Fp.create( + BigInt( + '0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0', + ), + ), + Z: Fp.create(BigInt(11)), +}) + +// Endomorphisms (for fast cofactor clearing) +// Ψ(P) endomorphism +const { G2psi, G2psi2 } = psiFrobenius(Fp, Fp2, Fp2.div(Fp2.ONE, Fp2.NONRESIDUE)) // 1/(u+1) + +// Default hash_to_field options are for hash to G2. +// +// Parameter definitions are in section 5.3 of the spec unless otherwise noted. +// Parameter values come from section 8.8.2 of the spec. +// https://www.rfc-editor.org/rfc/rfc9380#section-8.8.2 +// +// Base field F is GF(p^m) +// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab +// m = 2 (or 1 for G1 see section 8.8.1) +// k = 128 +const htfDefaults = Object.freeze({ + // DST: a domain separation tag + // defined in section 2.2.5 + // Use utils.getDSTLabel(), utils.setDSTLabel(value) + DST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + encodeDST: 'BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_', + // p: the characteristic of F + // where F is a finite field of characteristic p and order q = p^m + p: Fp.ORDER, + // m: the extension degree of F, m >= 1 + // where F is a finite field of characteristic p and order q = p^m + m: 2, + // k: the target security level for the suite in bits + // defined in section 5.1 + k: 128, + // option to use a message that has already been processed by + // expand_message_xmd + expand: 'xmd', + // Hash functions for: expand_message_xmd is appropriate for use with a + // wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others. + // BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247 + hash: sha256, +} as const) + +// Encoding utils +// Point on G1 curve: (x, y) + +// Compressed point of infinity +const COMPRESSED_ZERO = setMask(Fp.toBytes(_0n), { infinity: true, compressed: true }) // set compressed & point-at-infinity bits + +function parseMask(bytes: Uint8Array) { + // Copy, so we can remove mask data. It will be removed also later, when Fp.create will call modulo. + bytes = bytes.slice() + const mask = bytes[0] & 0b1110_0000 + const compressed = !!((mask >> 7) & 1) // compression bit (0b1000_0000) + const infinity = !!((mask >> 6) & 1) // point at infinity bit (0b0100_0000) + const sort = !!((mask >> 5) & 1) // sort bit (0b0010_0000) + bytes[0] &= 0b0001_1111 // clear mask (zero first 3 bits) + return { compressed, infinity, sort, value: bytes } +} + +function setMask( + bytes: Uint8Array, + mask: { compressed?: boolean; infinity?: boolean; sort?: boolean }, +) { + if (bytes[0] & 0b1110_0000) throw new Error('setMask: non-empty mask') + if (mask.compressed) bytes[0] |= 0b1000_0000 + if (mask.infinity) bytes[0] |= 0b0100_0000 + if (mask.sort) bytes[0] |= 0b0010_0000 + return bytes +} + +function signatureG1ToRawBytes(point: ProjPointType) { + point.assertValidity() + const isZero = point.equals(bls12_381.G1.ProjectivePoint.ZERO) + const { x, y } = point.toAffine() + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) +} + +function signatureG2ToRawBytes(point: ProjPointType) { + // NOTE: by some reasons it was missed in bls12-381, looks like bug + point.assertValidity() + const len = Fp.BYTES + if (point.equals(bls12_381.G2.ProjectivePoint.ZERO)) + return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const { x, y } = point.toAffine() + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + const tmp = y1 > _0n ? y1 * _2n : y0 * _2n + const sort = Boolean((tmp / Fp.ORDER) & _1n) + const z2 = x0 + return concatB( + setMask(numberToBytesBE(x1, len), { sort, compressed: true }), + numberToBytesBE(z2, len), + ) +} + +/** + * bls12-381 pairing-friendly curve. + * @example + * import { bls12_381 as bls } from '@noble/curves/bls12-381'; + * // G1 keys, G2 signatures + * const privateKey = '67d53f170b908cabb9eb326c3c337762d59289a8fec79f7bc9254b584b73265c'; + * const message = '64726e3da8'; + * const publicKey = bls.getPublicKey(privateKey); + * const signature = bls.sign(message, privateKey); + * const isValid = bls.verify(signature, message, publicKey); + */ +export const bls12_381: CurveFn = bls({ + // Fields + fields: { + Fp, + Fp2, + Fp6, + Fp12, + Fr, + }, + // G1 is the order-q subgroup of E1(Fp) : y² = x³ + 4, #E1(Fp) = h1q, where + // characteristic; z + (z⁴ - z² + 1)(z - 1)²/3 + G1: { + Fp, + // cofactor; (z - 1)²/3 + h: BigInt('0x396c8c005555e1568c00aaab0000aaab'), + // generator's coordinates + // x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 + // y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 + Gx: BigInt( + '0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb', + ), + Gy: BigInt( + '0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1', + ), + a: Fp.ZERO, + b: _4n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, point): boolean => { + // φ endomorphism + const cubicRootOfUnityModP = BigInt( + '0x5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe', + ) + const phi = new c(Fp.mul(point.px, cubicRootOfUnityModP), point.py, point.pz) + + // todo: unroll + const xP = point.multiplyUnsafe(BLS_X).negate() // [x]P + const u2P = xP.multiplyUnsafe(BLS_X) // [u2]P + return u2P.equals(phi) + + // https://eprint.iacr.org/2019/814.pdf + // (z² − 1)/3 + // const c1 = BigInt('0x396c8c005555e1560000000055555555'); + // const P = this; + // const S = P.sigma(); + // const Q = S.double(); + // const S2 = S.sigma(); + // // [(z² − 1)/3](2σ(P) − P − σ²(P)) − σ²(P) = O + // const left = Q.subtract(P).subtract(S2).multiplyUnsafe(c1); + // const C = left.subtract(S2); + // return C.isZero(); + }, + // Clear cofactor of G1 + // https://eprint.iacr.org/2019/403 + clearCofactor: (_c, point) => { + // return this.multiplyUnsafe(CURVE.h); + return point.multiplyUnsafe(BLS_X).add(point) // x*P + P + }, + mapToCurve: (scalars: bigint[]) => { + console.log('Input!', scalars, Fp.create(scalars[0])) + const { x, y } = G1_SWU(Fp.create(scalars[0])) + console.log('XVAL', x) + return isogenyMapG1(x, y) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if (value.length === 48 && compressed) { + // TODO: Fp.bytes + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + const x = Fp.create(compressedValue & Fp.MASK) + if (infinity) { + if (x !== _0n) throw new Error('G1: non-empty compressed point at infinity') + return { x: _0n, y: _0n } + } + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + if ((y * _2n) / P !== BigInt(sort)) y = Fp.neg(y) + return { x: Fp.create(x), y: Fp.create(y) } + } else if (value.length === 96 && !compressed) { + // Check if the infinity flag is set + const x = bytesToNumberBE(value.subarray(0, Fp.BYTES)) + const y = bytesToNumberBE(value.subarray(Fp.BYTES)) + if (infinity) { + if (x !== _0n || y !== _0n) throw new Error('G1: non-empty point at infinity') + return bls12_381.G1.ProjectivePoint.ZERO.toAffine() + } + return { x: Fp.create(x), y: Fp.create(y) } + } else { + throw new Error('invalid point G1, expected 48/96 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return COMPRESSED_ZERO.slice() + const P = Fp.ORDER + const sort = Boolean((y * _2n) / P) + return setMask(numberToBytesBE(x, Fp.BYTES), { compressed: true, sort }) + } else { + if (isZero) { + // 2x PUBLIC_KEY_LENGTH + const x = concatB(new Uint8Array([0x40]), new Uint8Array(2 * Fp.BYTES - 1)) + return x + } else { + return concatB(numberToBytesBE(x, Fp.BYTES), numberToBytesBE(y, Fp.BYTES)) + } + } + }, + ShortSignature: { + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex, 48)) + const P = Fp.ORDER + const compressedValue = bytesToNumberBE(value) + // Zero + if (infinity) return bls12_381.G1.ProjectivePoint.ZERO + const x = Fp.create(compressedValue & Fp.MASK) + const right = Fp.add(Fp.pow(x, _3n), Fp.create(bls12_381.params.G1b)) // y² = x³ + b + let y = Fp.sqrt(right) + if (!y) throw new Error('invalid compressed G1 point') + const aflag = BigInt(sort) + if ((y * _2n) / P !== aflag) y = Fp.neg(y) + const point = bls12_381.G1.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG1ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG1ToRawBytes(point)) + }, + }, + }, + // G2 is the order-q subgroup of E2(Fp²) : y² = x³+4(1+√−1), + // where Fp2 is Fp[√−1]/(x2+1). #E2(Fp2 ) = h2q, where + // G² - 1 + // h2q + G2: { + Fp: Fp2, + // cofactor + h: BigInt( + '0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5', + ), + Gx: Fp2.fromBigTuple([ + BigInt( + '0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8', + ), + BigInt( + '0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e', + ), + ]), + // y = + // 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, + // 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 + Gy: Fp2.fromBigTuple([ + BigInt( + '0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801', + ), + BigInt( + '0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be', + ), + ]), + a: Fp2.ZERO, + b: Fp2.fromBigTuple([_4n, _4n]), + hEff: BigInt( + '0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551', + ), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: (scalars: bigint[]) => { + const { x, y } = G2_SWU(Fp2.fromBigTuple(scalars)) + return isogenyMapG2(x, y) + }, + // Checks is the point resides in prime-order subgroup. + // point.isTorsionFree() should return true for valid points + // It returns false for shitty points. + // https://eprint.iacr.org/2021/1130.pdf + isTorsionFree: (c, P): boolean => { + return P.multiplyUnsafe(BLS_X).negate().equals(G2psi(c, P)) // ψ(P) == [u](P) + // Older version: https://eprint.iacr.org/2019/814.pdf + // Ψ²(P) => Ψ³(P) => [z]Ψ³(P) where z = -x => [z]Ψ³(P) - Ψ²(P) + P == O + // return P.psi2().psi().mulNegX().subtract(psi2).add(P).isZero(); + }, + // Maps the point into the prime-order subgroup G2. + // clear_cofactor_bls12381_g2 from cfrg-hash-to-curve-11 + // https://eprint.iacr.org/2017/419.pdf + // prettier-ignore + clearCofactor: (c, P) => { + const x = BLS_X + let t1 = P.multiplyUnsafe(x).negate() // [-x]P + let t2 = G2psi(c, P) // Ψ(P) + let t3 = P.double() // 2P + t3 = G2psi2(c, t3) // Ψ²(2P) + t3 = t3.subtract(t2) // Ψ²(2P) - Ψ(P) + t2 = t1.add(t2) // [-x]P + Ψ(P) + t2 = t2.multiplyUnsafe(x).negate() // [x²]P - [x]Ψ(P) + t3 = t3.add(t2) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + t3 = t3.subtract(t1) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P + const Q = t3.subtract(P) // Ψ²(2P) - Ψ(P) + [x²]P - [x]Ψ(P) + [x]P - 1P + return Q // [x²-x-1]P + [x-1]Ψ(P) + Ψ²(2P) + }, + fromBytes: (bytes: Uint8Array): AffinePoint => { + const { compressed, infinity, sort, value } = parseMask(bytes) + if ( + (!compressed && !infinity && sort) || // 00100000 + (!compressed && infinity && sort) || // 01100000 + (sort && infinity && compressed) // 11100000 + ) { + throw new Error('invalid encoding flag: ' + (bytes[0] & 0b1110_0000)) + } + const L = Fp.BYTES + const slc = (b: Uint8Array, from: number, to?: number) => bytesToNumberBE(b.slice(from, to)) + if (value.length === 96 && compressed) { + const b = bls12_381.params.G2b + const P = Fp.ORDER + if (infinity) { + // check that all bytes are 0 + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid compressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x_1 = slc(value, 0, L) + const x_0 = slc(value, L, 2 * L) + const x = Fp2.create({ c0: Fp.create(x_0), c1: Fp.create(x_1) }) + const right = Fp2.add(Fp2.pow(x, _3n), b) // y² = x³ + 4 * (u+1) = x³ + b + let y = Fp2.sqrt(right) + const Y_bit = y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P ? _1n : _0n + y = sort && Y_bit > 0 ? y : Fp2.neg(y) + return { x, y } + } else if (value.length === 192 && !compressed) { + if (infinity) { + if (value.reduce((p, c) => (p !== 0 ? c + 1 : c), 0) > 0) { + throw new Error('invalid uncompressed G2 point') + } + return { x: Fp2.ZERO, y: Fp2.ZERO } + } + const x1 = slc(value, 0, L) + const x0 = slc(value, L, 2 * L) + const y1 = slc(value, 2 * L, 3 * L) + const y0 = slc(value, 3 * L, 4 * L) + return { x: Fp2.fromBigTuple([x0, x1]), y: Fp2.fromBigTuple([y0, y1]) } + } else { + throw new Error('invalid point G2, expected 96/192 bytes') + } + }, + toBytes: (c, point, isCompressed) => { + const { BYTES: len, ORDER: P } = Fp + const isZero = point.equals(c.ZERO) + const { x, y } = point.toAffine() + if (isCompressed) { + if (isZero) return concatB(COMPRESSED_ZERO, numberToBytesBE(_0n, len)) + const flag = Boolean(y.c1 === _0n ? (y.c0 * _2n) / P : (y.c1 * _2n) / P) + return concatB( + setMask(numberToBytesBE(x.c1, len), { compressed: true, sort: flag }), + numberToBytesBE(x.c0, len), + ) + } else { + if (isZero) return concatB(new Uint8Array([0x40]), new Uint8Array(4 * len - 1)) // bytes[0] |= 1 << 6; + const { re: x0, im: x1 } = Fp2.reim(x) + const { re: y0, im: y1 } = Fp2.reim(y) + return concatB( + numberToBytesBE(x1, len), + numberToBytesBE(x0, len), + numberToBytesBE(y1, len), + numberToBytesBE(y0, len), + ) + } + }, + Signature: { + // TODO: Optimize, it's very slow because of sqrt. + fromHex(hex: Hex): ProjPointType { + const { infinity, sort, value } = parseMask(ensureBytes('signatureHex', hex)) + const P = Fp.ORDER + const half = value.length / 2 + if (half !== 48 && half !== 96) + throw new Error('invalid compressed signature length, must be 96 or 192') + const z1 = bytesToNumberBE(value.slice(0, half)) + const z2 = bytesToNumberBE(value.slice(half)) + // Indicates the infinity point + if (infinity) return bls12_381.G2.ProjectivePoint.ZERO + const x1 = Fp.create(z1 & Fp.MASK) + const x2 = Fp.create(z2) + const x = Fp2.create({ c0: x2, c1: x1 }) + const y2 = Fp2.add(Fp2.pow(x, _3n), bls12_381.params.G2b) // y² = x³ + 4 + // The slow part + let y = Fp2.sqrt(y2) + if (!y) throw new Error('Failed to find a square root') + + // Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 + // If y1 happens to be zero, then use the bit of y0 + const { re: y0, im: y1 } = Fp2.reim(y) + const aflag1 = BigInt(sort) + const isGreater = y1 > _0n && (y1 * _2n) / P !== aflag1 + const isZero = y1 === _0n && (y0 * _2n) / P !== aflag1 + if (isGreater || isZero) y = Fp2.neg(y) + const point = bls12_381.G2.ProjectivePoint.fromAffine({ x, y }) + point.assertValidity() + return point + }, + toRawBytes(point: ProjPointType) { + return signatureG2ToRawBytes(point) + }, + toHex(point: ProjPointType) { + return bytesToHex(signatureG2ToRawBytes(point)) + }, + }, + }, + params: { + ateLoopSize: BLS_X, // The BLS parameter x for BLS12-381 + r: Fr.ORDER, // order; z⁴ − z² + 1; CURVE.n from other curves + xNegative: true, + twistType: 'multiplicative', + }, + htfDefaults, + hash: sha256, + randomBytes, +}) diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/bn254.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/bn254.ts new file mode 100644 index 00000000000..f2ffdb887ac --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/bn254.ts @@ -0,0 +1,255 @@ +/** + * bn254, previously known as alt_bn_128, when it had 128-bit security. + +Barbulescu-Duquesne 2017 shown it's weaker: just about 100 bits, +so the naming has been adjusted to its prime bit count: +https://hal.science/hal-01534101/file/main.pdf. +Compatible with EIP-196 and EIP-197. + +There are huge compatibility issues in the ecosystem: + +1. Different libraries call it in different ways: "bn254", "bn256", "alt_bn128", "bn128". +2. libff has bn128, but it's a different curve with different G2: + https://github.com/scipr-lab/libff/blob/a44f482e18b8ac04d034c193bd9d7df7817ad73f/libff/algebra/curves/bn128/bn128_init.cpp#L166-L169 +3. halo2curves bn256 is also incompatible and returns different outputs + +The goal of our implementation is to support "Ethereum" variant of the curve, +because it at least has specs: + +- EIP196 (https://eips.ethereum.org/EIPS/eip-196) describes bn254 ECADD and ECMUL opcodes for EVM +- EIP197 (https://eips.ethereum.org/EIPS/eip-197) describes bn254 pairings +- It's hard: EIPs don't have proper tests. EIP-197 returns boolean output instead of Fp12 +- The existing implementations are bad. Some are deprecated: + - https://github.com/paritytech/bn (old version) + - https://github.com/ewasm/ethereum-bn128.rs (uses paritytech/bn) + - https://github.com/zcash-hackworks/bn + - https://github.com/arkworks-rs/curves/blob/master/bn254/src/lib.rs +- Python implementations use different towers and produce different Fp12 outputs: + - https://github.com/ethereum/py_pairing + - https://github.com/ethereum/execution-specs/blob/master/src/ethereum/crypto/alt_bn128.py +- Points are encoded differently in different implementations + +### Params +Seed (X): 4965661367192848881 +Fr: (36x⁴+36x³+18x²+6x+1) +Fp: (36x⁴+36x³+24x²+6x+1) +(E / Fp ): Y² = X³+3 +(Et / Fp²): Y² = X³+3/(u+9) (D-type twist) +Ate loop size: 6x+2 + +### Towers +- Fp²[u] = Fp/u²+1 +- Fp⁶[v] = Fp²/v³-9-u +- Fp¹²[w] = Fp⁶/w²-v + + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.ts' +import { + type CurveFn as BLSCurveFn, + type PostPrecomputeFn, + type PostPrecomputePointAddFn, + bls, +} from './abstract/bls.ts' +import { Field } from './abstract/modular.ts' +import type { Fp, Fp2, Fp6, Fp12 } from './abstract/tower.ts' +import { psiFrobenius, tower12 } from './abstract/tower.ts' +import { bitGet, bitLen, notImplemented } from './abstract/utils.ts' +import { type CurveFn, weierstrass } from './abstract/weierstrass.ts' +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +const _6n = BigInt(6) + +const BN_X = BigInt('4965661367192848881') +const BN_X_LEN = bitLen(BN_X) +const SIX_X_SQUARED = _6n * BN_X ** _2n + +// Finite field over r. It's for convenience and is not used in the code below. +const Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) +// Fp2.div(Fp2.mul(Fp2.ONE, _3n), Fp2.NONRESIDUE) +const Fp2B = { + c0: BigInt('19485874751759354771024239261021720505790618469301721065564631296452457478373'), + c1: BigInt('266929791119991161246907387137283842545076965332900288569378510910307636690'), +} + +const { Fp, Fp2, Fp6, Fp4Square, Fp12 } = tower12({ + ORDER: BigInt('21888242871839275222246405745257275088696311157297823662689037894645226208583'), + FP2_NONRESIDUE: [BigInt(9), _1n], + Fp2mulByB: (num) => Fp2.mul(num, Fp2B), + // The result of any pairing is in a cyclotomic subgroup + // https://eprint.iacr.org/2009/565.pdf + Fp12cyclotomicSquare: ({ c0, c1 }): Fp12 => { + const { c0: c0c0, c1: c0c1, c2: c0c2 } = c0 + const { c0: c1c0, c1: c1c1, c2: c1c2 } = c1 + const { first: t3, second: t4 } = Fp4Square(c0c0, c1c1) + const { first: t5, second: t6 } = Fp4Square(c1c0, c0c2) + const { first: t7, second: t8 } = Fp4Square(c0c1, c1c2) + let t9 = Fp2.mulByNonresidue(t8) // T8 * (u + 1) + return { + c0: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.sub(t3, c0c0), _2n), t3), // 2 * (T3 - c0c0) + T3 + c1: Fp2.add(Fp2.mul(Fp2.sub(t5, c0c1), _2n), t5), // 2 * (T5 - c0c1) + T5 + c2: Fp2.add(Fp2.mul(Fp2.sub(t7, c0c2), _2n), t7), + }), // 2 * (T7 - c0c2) + T7 + c1: Fp6.create({ + c0: Fp2.add(Fp2.mul(Fp2.add(t9, c1c0), _2n), t9), // 2 * (T9 + c1c0) + T9 + c1: Fp2.add(Fp2.mul(Fp2.add(t4, c1c1), _2n), t4), // 2 * (T4 + c1c1) + T4 + c2: Fp2.add(Fp2.mul(Fp2.add(t6, c1c2), _2n), t6), + }), + } // 2 * (T6 + c1c2) + T6 + }, + Fp12cyclotomicExp(num, n) { + let z = Fp12.ONE + for (let i = BN_X_LEN - 1; i >= 0; i--) { + z = Fp12._cyclotomicSquare(z) + if (bitGet(n, i)) z = Fp12.mul(z, num) + } + return z + }, + // https://eprint.iacr.org/2010/354.pdf + // https://eprint.iacr.org/2009/565.pdf + Fp12finalExponentiate: (num) => { + const powMinusX = (num: Fp12) => Fp12.conjugate(Fp12._cyclotomicExp(num, BN_X)) + const r0 = Fp12.mul(Fp12.conjugate(num), Fp12.inv(num)) + const r = Fp12.mul(Fp12.frobeniusMap(r0, 2), r0) + const y1 = Fp12._cyclotomicSquare(powMinusX(r)) + const y2 = Fp12.mul(Fp12._cyclotomicSquare(y1), y1) + const y4 = powMinusX(y2) + const y6 = powMinusX(Fp12._cyclotomicSquare(y4)) + const y8 = Fp12.mul(Fp12.mul(Fp12.conjugate(y6), y4), Fp12.conjugate(y2)) + const y9 = Fp12.mul(y8, y1) + return Fp12.mul( + Fp12.frobeniusMap(Fp12.mul(Fp12.conjugate(r), y9), 3), + Fp12.mul( + Fp12.frobeniusMap(y8, 2), + Fp12.mul(Fp12.frobeniusMap(y9, 1), Fp12.mul(Fp12.mul(y8, y4), r)), + ), + ) + }, +}) + +// END OF CURVE FIELDS +const { G2psi, psi } = psiFrobenius(Fp, Fp2, Fp2.NONRESIDUE) + +/* +No hashToCurve for now (and signatures): + +- RFC 9380 doesn't mention bn254 and doesn't provide test vectors +- Overall seems like nobody is using BLS signatures on top of bn254 +- Seems like it can utilize SVDW, which is not implemented yet +*/ +const htfDefaults = Object.freeze({ + // DST: a domain separation tag defined in section 2.2.5 + DST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + encodeDST: 'BN254G2_XMD:SHA-256_SVDW_RO_', + p: Fp.ORDER, + m: 2, + k: 128, + expand: 'xmd', + hash: sha256, +} as const) + +export const _postPrecompute: PostPrecomputeFn = ( + Rx: Fp2, + Ry: Fp2, + Rz: Fp2, + Qx: Fp2, + Qy: Fp2, + pointAdd: PostPrecomputePointAddFn, +) => { + const q = psi(Qx, Qy) + ;({ Rx, Ry, Rz } = pointAdd(Rx, Ry, Rz, q[0], q[1])) + const q2 = psi(q[0], q[1]) + pointAdd(Rx, Ry, Rz, q2[0], Fp2.neg(q2[1])) +} + +/** + * bn254 (a.k.a. alt_bn128) pairing-friendly curve. + * Contains G1 / G2 operations and pairings. + */ +export const bn254: BLSCurveFn = bls({ + // Fields + fields: { Fp, Fp2, Fp6, Fp12, Fr }, + G1: { + Fp, + h: BigInt(1), + Gx: BigInt(1), + Gy: BigInt(2), + a: Fp.ZERO, + b: _3n, + htfDefaults: { ...htfDefaults, m: 1, DST: 'BN254G2_XMD:SHA-256_SVDW_RO_' }, + wrapPrivateKey: true, + allowInfinityPoint: true, + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + ShortSignature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + G2: { + Fp: Fp2, + // cofactor: (36 * X^4) + (36 * X^3) + (30 * X^2) + 6*X + 1 + h: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + Gx: Fp2.fromBigTuple([ + BigInt('10857046999023057135944570762232829481370756359578518086990519993285655852781'), + BigInt('11559732032986387107991004021392285783925812861821192530917403151452391805634'), + ]), + Gy: Fp2.fromBigTuple([ + BigInt('8495653923123431417604973247489272438418190587263600148770280649306958101930'), + BigInt('4082367875863433681332203403145435568316851327593401208105741076214120093531'), + ]), + a: Fp2.ZERO, + b: Fp2B, + hEff: BigInt('21888242871839275222246405745257275088844257914179612981679871602714643921549'), + htfDefaults: { ...htfDefaults }, + wrapPrivateKey: true, + allowInfinityPoint: true, + isTorsionFree: (c, P) => P.multiplyUnsafe(SIX_X_SQUARED).equals(G2psi(c, P)), // [p]P = [6X^2]P + mapToCurve: notImplemented, + fromBytes: notImplemented, + toBytes: notImplemented, + Signature: { + fromHex: notImplemented, + toRawBytes: notImplemented, + toHex: notImplemented, + }, + }, + params: { + ateLoopSize: BN_X * _6n + _2n, + r: Fr.ORDER, + xNegative: false, + twistType: 'divisive', + }, + htfDefaults, + hash: sha256, + randomBytes, + + postPrecompute: _postPrecompute, +}) + +/** + * bn254 weierstrass curve with ECDSA. + * This is very rare and probably not used anywhere. + * Instead, you should use G1 / G2, defined above. + * @deprecated + */ +export const bn254_weierstrass: CurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(3), + Fp, + n: BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), + Gx: BigInt(1), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/ed25519.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/ed25519.ts new file mode 100644 index 00000000000..138d05b2e04 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/ed25519.ts @@ -0,0 +1,554 @@ +/** + * ed25519 Twisted Edwards curve with following addons: + * - X25519 ECDH + * - Ristretto cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha512 } from '@noble/hashes/sha2' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { type AffinePoint, type Group, pippenger } from './abstract/curve.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { + type HTFMethod, + type Hasher, + createHasher, + expand_message_xmd, + type htfBasicOpts, +} from './abstract/hash-to-curve.ts' +import { Field, FpSqrtEven, isNegativeLE, mod, pow2 } from './abstract/modular.ts' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.ts' + +// 2n**255n - 19n +const ED25519_P = BigInt( + '57896044618658097711785492504343953926634992332820282019728792003956564819949', +) +// √(-1) aka √(a) aka 2^((p-1)/4) +// Fp.sqrt(Fp.neg(1)) +const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt( + '19681161376707505956807079304988542015446066515923890162744021073123829784752', +) + +// prettier-ignore +const _0n = BigInt(0), + _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3) +// prettier-ignore +const _5n = BigInt(5), + _8n = BigInt(8) + +function ed25519_pow_2_252_3(x: bigint) { + // prettier-ignore + const _10n = BigInt(10), + _20n = BigInt(20), + _40n = BigInt(40), + _80n = BigInt(80) + const P = ED25519_P + const x2 = (x * x) % P + const b2 = (x2 * x) % P // x^3, 11 + const b4 = (pow2(b2, _2n, P) * b2) % P // x^15, 1111 + const b5 = (pow2(b4, _1n, P) * x) % P // x^31 + const b10 = (pow2(b5, _5n, P) * b5) % P + const b20 = (pow2(b10, _10n, P) * b10) % P + const b40 = (pow2(b20, _20n, P) * b20) % P + const b80 = (pow2(b40, _40n, P) * b40) % P + const b160 = (pow2(b80, _80n, P) * b80) % P + const b240 = (pow2(b160, _80n, P) * b80) % P + const b250 = (pow2(b240, _10n, P) * b10) % P + const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P + // ^ To pow to (p+3)/8, multiply it by x. + return { pow_p_5_8, b2 } +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: For X25519, in order to decode 32 random bytes as an integer scalar, + // set the three least significant bits of the first byte + bytes[0] &= 248 // 0b1111_1000 + // and the most significant bit of the last to zero, + bytes[31] &= 127 // 0b0111_1111 + // set the second most significant bit of the last byte to 1 + bytes[31] |= 64 // 0b0100_0000 + return bytes +} + +// sqrt(u/v) +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ED25519_P + const v3 = mod(v * v * v, P) // v³ + const v7 = mod(v3 * v3 * v, P) // v⁷ + // (p+3)/8 and (p-5)/8 + const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8 + let x = mod(u * v3 * pow, P) // (uv³)(uv⁷)^(p-5)/8 + const vx2 = mod(v * x * x, P) // vx² + const root1 = x // First root candidate + const root2 = mod(x * ED25519_SQRT_M1, P) // Second root candidate + const useRoot1 = vx2 === u // If vx² = u (mod p), x is a square root + const useRoot2 = vx2 === mod(-u, P) // If vx² = -u, set x <-- x * 2^((p-1)/4) + const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P) // There is no valid root, vx² = -u√(-1) + if (useRoot1) x = root1 + if (useRoot2 || noRoot) x = root2 // We return root2 anyway, for const-time + if (isNegativeLE(x, P)) x = mod(-x, P) + return { isValid: useRoot1 || useRoot2, value: x } +} + +/** Weird / bogus points, useful for debugging. */ +export const ED25519_TORSION_SUBGROUP: string[] = [ + '0100000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', + '0000000000000000000000000000000000000000000000000000000000000080', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', + '0000000000000000000000000000000000000000000000000000000000000000', + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', +] + +const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))() + +const ed25519Defaults = /* @__PURE__ */ (() => + ({ + // Removing Fp.create() will still work, and is 10% faster on sign + a: Fp.create(BigInt(-1)), + // d is -121665/121666 a.k.a. Fp.neg(121665 * Fp.inv(121666)) + d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'), + // Finite field 2n**255n - 19n + Fp, + // Subgroup order 2n**252n + 27742317777372353535851937790883648493n; + n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'), + h: _8n, + Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'), + Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'), + hash: sha512, + randomBytes, + adjustScalarBytes, + // dom2 + // Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3. + // Constant-time, u/√v + uvRatio, + }) as const)() + +/** + * ed25519 curve with EdDSA signatures. + * @example + * import { ed25519 } from '@noble/curves/ed25519'; + * const priv = ed25519.utils.randomPrivateKey(); + * const pub = ed25519.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = ed25519.sign(msg, priv); + * ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215 + * ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5 + */ +export const ed25519: CurveFn = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))() + +function ed25519_domain(data: Uint8Array, ctx: Uint8Array, phflag: boolean) { + if (ctx.length > 255) throw new Error('Context is too big') + return concatBytes( + utf8ToBytes('SigEd25519 no Ed25519 collisions'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) +} + +export const ed25519ctx: CurveFn = /* @__PURE__ */ (() => + twistedEdwards({ + ...ed25519Defaults, + domain: ed25519_domain, + }))() +export const ed25519ph: CurveFn = /* @__PURE__ */ (() => + twistedEdwards( + Object.assign({}, ed25519Defaults, { + domain: ed25519_domain, + prehash: sha512, + }), + ))() + +/** + * ECDH using curve25519 aka x25519. + * @example + * import { x25519 } from '@noble/curves/ed25519'; + * const priv = 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4'; + * const pub = 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c'; + * x25519.getSharedSecret(priv, pub) === x25519.scalarMult(priv, pub); // aliases + * x25519.getPublicKey(priv) === x25519.scalarMultBase(priv); + * x25519.getPublicKey(x25519.utils.randomPrivateKey()); + */ +export const x25519: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + P: ED25519_P, + a: BigInt(486662), + montgomeryBits: 255, // n is 253 bits + nByteLength: 32, + Gu: BigInt(9), + powPminus2: (x: bigint): bigint => { + const P = ED25519_P + // x^(p-2) aka x^(2^255-21) + const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x) + return mod(pow2(pow_p_5_8, _3n, P) * b2, P) + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts ed25519 public key to x25519 public key. Uses formula: + * * `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)` + * * `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))` + * @example + * const someonesPub = ed25519.getPublicKey(ed25519.utils.randomPrivateKey()); + * const aPriv = x25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(aPriv, edwardsToMontgomeryPub(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: Hex): Uint8Array { + const { y } = ed25519.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((_1n + y) * Fp.inv(_1n - y))) +} +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated + +/** + * Converts ed25519 secret key to x25519 secret key. + * @example + * const someonesPub = x25519.getPublicKey(x25519.utils.randomPrivateKey()); + * const aPriv = ed25519.utils.randomPrivateKey(); + * x25519.getSharedSecret(edwardsToMontgomeryPriv(aPriv), someonesPub) + */ +export function edwardsToMontgomeryPriv(edwardsPriv: Uint8Array): Uint8Array { + const hashed = ed25519Defaults.hash(edwardsPriv.subarray(0, 32)) + return ed25519Defaults.adjustScalarBytes(hashed).subarray(0, 32) +} + +// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator) +// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since +// SageMath returns different root first and everything falls apart + +const ELL2_C1 = /* @__PURE__ */ (() => (Fp.ORDER + _3n) / _8n)() // 1. c1 = (q + 3) / 8 # Integer arithmetic +const ELL2_C2 = /* @__PURE__ */ (() => Fp.pow(_2n, ELL2_C1))() // 2. c2 = 2^c1 +const ELL2_C3 = /* @__PURE__ */ (() => Fp.sqrt(Fp.neg(Fp.ONE)))() // 3. c3 = sqrt(-1) + +// prettier-ignore +function map_to_curve_elligator2_curve25519(u: bigint) { + const ELL2_C4 = (Fp.ORDER - _5n) / _8n // 4. c4 = (q - 5) / 8 # Integer arithmetic + const ELL2_J = BigInt(486662) + + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + tv1 = Fp.mul(tv1, _2n) // 2. tv1 = 2 * tv1 + let xd = Fp.add(tv1, Fp.ONE) // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not + let x1n = Fp.neg(ELL2_J) // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2) + let tv2 = Fp.sqr(xd) // 5. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 6. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, ELL2_J) // 7. gx1 = J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 11. tv3 = gxd^2 + tv2 = Fp.sqr(tv3) // 12. tv2 = tv3^2 # gxd^4 + tv3 = Fp.mul(tv3, gxd) // 13. tv3 = tv3 * gxd # gxd^3 + tv3 = Fp.mul(tv3, gx1) // 14. tv3 = tv3 * gx1 # gx1 * gxd^3 + tv2 = Fp.mul(tv2, tv3) // 15. tv2 = tv2 * tv3 # gx1 * gxd^7 + let y11 = Fp.pow(tv2, ELL2_C4) // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8) + y11 = Fp.mul(y11, tv3) // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8) + let y12 = Fp.mul(y11, ELL2_C3) // 18. y12 = y11 * c3 + tv2 = Fp.sqr(y11) // 19. tv2 = y11^2 + tv2 = Fp.mul(tv2, gxd) // 20. tv2 = tv2 * gxd + let e1 = Fp.eql(tv2, gx1) // 21. e1 = tv2 == gx1 + let y1 = Fp.cmov(y12, y11, e1) // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt + let x2n = Fp.mul(x1n, tv1) // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd + let y21 = Fp.mul(y11, u) // 24. y21 = y11 * u + y21 = Fp.mul(y21, ELL2_C2) // 25. y21 = y21 * c2 + let y22 = Fp.mul(y21, ELL2_C3) // 26. y22 = y21 * c3 + let gx2 = Fp.mul(gx1, tv1) // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1) + tv2 = Fp.sqr(y21) // 28. tv2 = y21^2 + tv2 = Fp.mul(tv2, gxd) // 29. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx2) // 30. e2 = tv2 == gx2 + let y2 = Fp.cmov(y22, y21, e2) // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt + tv2 = Fp.sqr(y1) // 32. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 33. tv2 = tv2 * gxd + let e3 = Fp.eql(tv2, gx1) // 34. e3 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e3) // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e3) // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2 + let e4 = Fp.isOdd(y) // 37. e4 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e3 !== e4) // 38. y = CMOV(y, -y, e3 XOR e4) + return { xMn: xn, xMd: xd, yMn: y, yMd: _1n } // 39. return (xn, xd, y, 1) +} + +const ELL2_C1_EDWARDS = /* @__PURE__ */ (() => FpSqrtEven(Fp, Fp.neg(BigInt(486664))))() // sgn0(c1) MUST equal 0 +function map_to_curve_elligator2_edwards25519(u: bigint) { + const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u) // 1. (xMn, xMd, yMn, yMd) = + // map_to_curve_elligator2_curve25519(u) + let xn = Fp.mul(xMn, yMd) // 2. xn = xMn * yMd + xn = Fp.mul(xn, ELL2_C1_EDWARDS) // 3. xn = xn * c1 + let xd = Fp.mul(xMd, yMn) // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM + let yn = Fp.sub(xMn, xMd) // 5. yn = xMn - xMd + let yd = Fp.add(xMn, xMd) // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d) + let tv1 = Fp.mul(xd, yd) // 7. tv1 = xd * yd + let e = Fp.eql(tv1, Fp.ZERO) // 8. e = tv1 == 0 + xn = Fp.cmov(xn, Fp.ZERO, e) // 9. xn = CMOV(xn, 0, e) + xd = Fp.cmov(xd, Fp.ONE, e) // 10. xd = CMOV(xd, 1, e) + yn = Fp.cmov(yn, Fp.ONE, e) // 11. yn = CMOV(yn, 1, e) + yd = Fp.cmov(yd, Fp.ONE, e) // 12. yd = CMOV(yd, 1, e) + + const inv = Fp.invertBatch([xd, yd]) // batch division + return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) } // 13. return (xn, xd, yn, yd) +} + +export const ed25519_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + ed25519.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards25519(scalars[0]), + { + DST: 'edwards25519_XMD:SHA-512_ELL2_RO_', + encodeDST: 'edwards25519_XMD:SHA-512_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha512, + }, + ))() +/** + * @deprecated Use `ed25519_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed25519_hasher.hashToCurve)() +/** + * @deprecated Use `ed25519_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => + ed25519_hasher.encodeToCurve)() + +function aristp(other: unknown) { + if (!(other instanceof RistPoint)) throw new Error('RistrettoPoint expected') +} + +// √(-1) aka √(a) aka 2^((p-1)/4) +const SQRT_M1 = ED25519_SQRT_M1 +// √(ad - 1) +const SQRT_AD_MINUS_ONE = /* @__PURE__ */ BigInt( + '25063068953384623474111414158702152701244531502492656460079210482610430750235', +) +// 1 / √(a-d) +const INVSQRT_A_MINUS_D = /* @__PURE__ */ BigInt( + '54469307008909316920995813868745141605393597292927456921205312896311721017578', +) +// 1-d² +const ONE_MINUS_D_SQ = /* @__PURE__ */ BigInt( + '1159843021668779879193775521855586647937357759715417654439879720876111806838', +) +// (d-1)² +const D_MINUS_ONE_SQ = /* @__PURE__ */ BigInt( + '40440834346308536858101042469323190826248399146238708352240133220865137265952', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_255B = /* @__PURE__ */ BigInt( + '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes255ToNumberLE = (bytes: Uint8Array) => + ed25519.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_255B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Ristretto +// https://ristretto.group/formulas/elligator.html +function calcElligatorRistrettoMap(r0: bigint): ExtendedPoint { + const { d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const r = mod(SQRT_M1 * r0 * r0) // 1 + const Ns = mod((r + _1n) * ONE_MINUS_D_SQ) // 2 + let c = BigInt(-1) // 3 + const D = mod((c - d * r) * mod(r + d)) // 4 + let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D) // 5 + let s_ = mod(s * r0) // 6 + if (!isNegativeLE(s_, P)) s_ = mod(-s_) + if (!Ns_D_is_sq) s = s_ // 7 + if (!Ns_D_is_sq) c = r // 8 + const Nt = mod(c * (r - _1n) * D_MINUS_ONE_SQ - D) // 9 + const s2 = s * s + const W0 = mod((s + s) * D) // 10 + const W1 = mod(Nt * SQRT_AD_MINUS_ONE) // 11 + const W2 = mod(_1n - s2) // 12 + const W3 = mod(_1n + s2) // 13 + return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed25519/ExtendedPoint has 8 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Ristretto was created to solve this. + * Ristretto point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class RistPoint implements Group { + static BASE: RistPoint + static ZERO: RistPoint + private readonly ep: ExtendedPoint + // Private property to discourage combining ExtendedPoint + RistrettoPoint + // Always use Ristretto encoding/decoding instead. + constructor(ep: ExtendedPoint) { + this.ep = ep + } + + static fromAffine(ap: AffinePoint): RistPoint { + return new RistPoint(ed25519.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 64-byte hash function like sha512 and converts it to `RistrettoPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://ristretto.group/formulas/elligator.html + * @param hex 64-byte output of a hash function + */ + static hashToCurve(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHash', hex, 64) + const r1 = bytes255ToNumberLE(hex.slice(0, 32)) + const R1 = calcElligatorRistrettoMap(r1) + const r2 = bytes255ToNumberLE(hex.slice(32, 64)) + const R2 = calcElligatorRistrettoMap(r2) + return new RistPoint(R1.add(R2)) + } + + /** + * Converts ristretto-encoded string to ristretto point. + * https://ristretto.group/formulas/decoding.html + * @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding + */ + static fromHex(hex: Hex): RistPoint { + hex = ensureBytes('ristrettoHex', hex, 32) + const { a, d } = ed25519.CURVE + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint' + const s = bytes255ToNumberLE(hex) + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 3. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P)) throw new Error(emsg) + const s2 = mod(s * s) + const u1 = mod(_1n + a * s2) // 4 (a is -1) + const u2 = mod(_1n - a * s2) // 5 + const u1_2 = mod(u1 * u1) + const u2_2 = mod(u2 * u2) + const v = mod(a * d * u1_2 - u2_2) // 6 + const { isValid, value: I } = invertSqrt(mod(v * u2_2)) // 7 + const Dx = mod(I * u2) // 8 + const Dy = mod(I * Dx * v) // 9 + let x = mod((s + s) * Dx) // 10 + if (isNegativeLE(x, P)) x = mod(-x) // 10 + const y = mod(u1 * Dy) // 11 + const t = mod(x * y) // 12 + if (!isValid || isNegativeLE(t, P) || y === _0n) throw new Error(emsg) + return new RistPoint(new ed25519.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: RistPoint[], scalars: bigint[]): RistPoint { + const Fn = Field(ed25519.CURVE.n, ed25519.CURVE.nBitLength) + return pippenger(RistPoint, Fn, points, scalars) + } + + /** + * Encodes ristretto point to Uint8Array. + * https://ristretto.group/formulas/encoding.html + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: y, ez: z, et: t } = this.ep + const P = ed25519.CURVE.Fp.ORDER + const mod = ed25519.CURVE.Fp.create + const u1 = mod(mod(z + y) * mod(z - y)) // 1 + const u2 = mod(x * y) // 2 + // Square root always exists + const u2sq = mod(u2 * u2) + const { value: invsqrt } = invertSqrt(mod(u1 * u2sq)) // 3 + const D1 = mod(invsqrt * u1) // 4 + const D2 = mod(invsqrt * u2) // 5 + const zInv = mod(D1 * D2 * t) // 6 + let D: bigint // 7 + if (isNegativeLE(t * zInv, P)) { + let _x = mod(y * SQRT_M1) + let _y = mod(x * SQRT_M1) + x = _x + y = _y + D = mod(D1 * INVSQRT_A_MINUS_D) + } else { + D = D2 // 8 + } + if (isNegativeLE(x * zInv, P)) y = mod(-y) // 9 + let s = mod((z - y) * D) // 10 (check footer's note, no sqrt(-a)) + if (isNegativeLE(s, P)) s = mod(-s) + return numberToBytesLE(s, 32) // 11 + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + equals(other: RistPoint): boolean { + aristp(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed25519.CURVE.Fp.create + // (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2) + const one = mod(X1 * Y2) === mod(Y1 * X2) + const two = mod(Y1 * Y2) === mod(X1 * X2) + return one || two + } + + add(other: RistPoint): RistPoint { + aristp(other) + return new RistPoint(this.ep.add(other.ep)) + } + + subtract(other: RistPoint): RistPoint { + aristp(other) + return new RistPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): RistPoint { + return new RistPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): RistPoint { + return new RistPoint(this.ep.double()) + } + + negate(): RistPoint { + return new RistPoint(this.ep.negate()) + } +} +export const RistrettoPoint: typeof RistPoint = /* @__PURE__ */ (() => { + if (!RistPoint.BASE) RistPoint.BASE = new RistPoint(ed25519.ExtendedPoint.BASE) + if (!RistPoint.ZERO) RistPoint.ZERO = new RistPoint(ed25519.ExtendedPoint.ZERO) + return RistPoint +})() + +// Hashing to ristretto255. https://www.rfc-editor.org/rfc/rfc9380#appendix-B +export const hashToRistretto255 = (msg: Uint8Array, options: htfBasicOpts): RistPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xmd(msg, DST, 64, sha512) + const P = RistPoint.hashToCurve(uniform_bytes) + return P +} +/** @deprecated */ +export const hash_to_ristretto255: (msg: Uint8Array, options: htfBasicOpts) => RistPoint = + hashToRistretto255 // legacy diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/ed448.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/ed448.ts new file mode 100644 index 00000000000..c39163373f2 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/ed448.ts @@ -0,0 +1,522 @@ +/** + * Edwards448 (not Ed448-Goldilocks) curve with following addons: + * - X448 ECDH + * - Decaf cofactor elimination + * - Elligator hash-to-group / point indistinguishability + * Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { shake256 } from '@noble/hashes/sha3' +import { concatBytes, randomBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils' +import type { AffinePoint, Group } from './abstract/curve.ts' +import { pippenger } from './abstract/curve.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { + type HTFMethod, + type Hasher, + createHasher, + expand_message_xof, + type htfBasicOpts, +} from './abstract/hash-to-curve.ts' +import { Field, isNegativeLE, mod, pow2 } from './abstract/modular.ts' +import { type CurveFn as XCurveFn, montgomery } from './abstract/montgomery.ts' +import { + type Hex, + bytesToHex, + bytesToNumberLE, + ensureBytes, + equalBytes, + numberToBytesLE, +} from './abstract/utils.ts' + +const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 })) +const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 })) +const ed448P = BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439', +) + +// prettier-ignore +const _1n = BigInt(1), + _2n = BigInt(2), + _3n = BigInt(3), + _4n = BigInt(4), + _11n = BigInt(11) +// prettier-ignore +const _22n = BigInt(22), + _44n = BigInt(44), + _88n = BigInt(88), + _223n = BigInt(223) + +// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4. +// Used for efficient square root calculation. +// ((P-3)/4).toString(2) would produce bits [223x 1, 0, 222x 1] +function ed448_pow_Pminus3div4(x: bigint): bigint { + const P = ed448P + const b2 = (x * x * x) % P + const b3 = (b2 * b2 * x) % P + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b222 = (pow2(b220, _2n, P) * b2) % P + const b223 = (pow2(b222, _1n, P) * x) % P + return (pow2(b223, _223n, P) * b222) % P +} + +function adjustScalarBytes(bytes: Uint8Array): Uint8Array { + // Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most + // significant bit of the last byte to 1. + bytes[0] &= 252 // 0b11111100 + // and the most significant bit of the last byte to 1. + bytes[55] |= 128 // 0b10000000 + // NOTE: is is NOOP for 56 bytes scalars (X25519/X448) + bytes[56] = 0 // Byte outside of group (456 buts vs 448 bits) + return bytes +} + +// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v. +// Uses algo from RFC8032 5.1.3. +function uvRatio(u: bigint, v: bigint): { isValid: boolean; value: bigint } { + const P = ed448P + // https://www.rfc-editor.org/rfc/rfc8032#section-5.2.3 + // To compute the square root of (u/v), the first step is to compute the + // candidate root x = (u/v)^((p+1)/4). This can be done using the + // following trick, to use a single modular powering for both the + // inversion of v and the square root: + // x = (u/v)^((p+1)/4) = u³v(u⁵v³)^((p-3)/4) (mod p) + const u2v = mod(u * u * v, P) // u²v + const u3v = mod(u2v * u, P) // u³v + const u5v3 = mod(u3v * u2v * v, P) // u⁵v³ + const root = ed448_pow_Pminus3div4(u5v3) + const x = mod(u3v * root, P) + // Verify that root is exists + const x2 = mod(x * x, P) // x² + // If vx² = u, the recovered x-coordinate is x. Otherwise, no + // square root exists, and the decoding fails. + return { isValid: mod(x2 * v, P) === u, value: x } +} + +const Fp = Field(ed448P, 456, true) + +const ED448_DEF = { + // Param: a + a: BigInt(1), + // -39081 a.k.a. Fp.neg(39081) + d: BigInt( + '726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358', + ), + // Finite field 2n**448n - 2n**224n - 1n + Fp, + // Subgroup order + // 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n + n: BigInt( + '181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779', + ), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + nBitLength: 456, + h: BigInt(4), + Gx: BigInt( + '224580040295924300187604334099896036246789641632564134246125461686950415467406032909029192869357953282578032075146446173674602635247710', + ), + Gy: BigInt( + '298819210078481492676017930443930673437544040154080242095928241372331506189835876003536878655418784733982303233503462500531545062832660', + ), + // SHAKE256(dom4(phflag,context)||x, 114) + hash: shake256_114, + randomBytes, + adjustScalarBytes, + // dom4 + domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => { + if (ctx.length > 255) throw new Error('context must be smaller than 255, got: ' + ctx.length) + return concatBytes( + utf8ToBytes('SigEd448'), + new Uint8Array([phflag ? 1 : 0, ctx.length]), + ctx, + data, + ) + }, + uvRatio, +} as const + +/** + * ed448 EdDSA curve and methods. + * @example + * import { ed448 } from '@noble/curves/ed448'; + * const priv = ed448.utils.randomPrivateKey(); + * const pub = ed448.getPublicKey(priv); + * const msg = new TextEncoder().encode('whatsup'); + * const sig = ed448.sign(msg, priv); + * ed448.verify(sig, msg, pub); + */ +export const ed448: CurveFn = /* @__PURE__ */ twistedEdwards(ED448_DEF) +// NOTE: there is no ed448ctx, since ed448 supports ctx by default +export const ed448ph: CurveFn = /* @__PURE__ */ twistedEdwards({ + ...ED448_DEF, + prehash: shake256_64, +}) + +/** + * ECDH using curve448 aka x448. + */ +export const x448: XCurveFn = /* @__PURE__ */ (() => + montgomery({ + a: BigInt(156326), + // RFC 7748 has 56-byte keys, RFC 8032 has 57-byte keys + montgomeryBits: 448, + nByteLength: 56, + P: ed448P, + Gu: BigInt(5), + powPminus2: (x: bigint): bigint => { + const P = ed448P + const Pminus3div4 = ed448_pow_Pminus3div4(x) + const Pminus3 = pow2(Pminus3div4, BigInt(2), P) + return mod(Pminus3 * x, P) // Pminus3 * x = Pminus2 + }, + adjustScalarBytes, + randomBytes, + }))() + +/** + * Converts edwards448 public key to x448 public key. Uses formula: + * * `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)` + * * `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))` + * @example + * const aPub = ed448.getPublicKey(utils.randomPrivateKey()); + * x448.getSharedSecret(edwardsToMontgomery(aPub), edwardsToMontgomery(someonesPub)) + */ +export function edwardsToMontgomeryPub(edwardsPub: string | Uint8Array): Uint8Array { + const { y } = ed448.ExtendedPoint.fromHex(edwardsPub) + const _1n = BigInt(1) + return Fp.toBytes(Fp.create((y - _1n) * Fp.inv(y + _1n))) +} + +export const edwardsToMontgomery: typeof edwardsToMontgomeryPub = edwardsToMontgomeryPub // deprecated +// TODO: add edwardsToMontgomeryPriv, similar to ed25519 version + +// Hash To Curve Elligator2 Map +const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4) // 1. c1 = (q - 3) / 4 # Integer arithmetic +const ELL2_J = BigInt(156326) + +function map_to_curve_elligator2_curve448(u: bigint) { + let tv1 = Fp.sqr(u) // 1. tv1 = u^2 + let e1 = Fp.eql(tv1, Fp.ONE) // 2. e1 = tv1 == 1 + tv1 = Fp.cmov(tv1, Fp.ZERO, e1) // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0 + let xd = Fp.sub(Fp.ONE, tv1) // 4. xd = 1 - tv1 + let x1n = Fp.neg(ELL2_J) // 5. x1n = -J + let tv2 = Fp.sqr(xd) // 6. tv2 = xd^2 + let gxd = Fp.mul(tv2, xd) // 7. gxd = tv2 * xd # gxd = xd^3 + let gx1 = Fp.mul(tv1, Fp.neg(ELL2_J)) // 8. gx1 = -J * tv1 # x1n + J * xd + gx1 = Fp.mul(gx1, x1n) // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd + gx1 = Fp.add(gx1, tv2) // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2 + gx1 = Fp.mul(gx1, x1n) // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2 + let tv3 = Fp.sqr(gxd) // 12. tv3 = gxd^2 + tv2 = Fp.mul(gx1, gxd) // 13. tv2 = gx1 * gxd # gx1 * gxd + tv3 = Fp.mul(tv3, tv2) // 14. tv3 = tv3 * tv2 # gx1 * gxd^3 + let y1 = Fp.pow(tv3, ELL2_C1) // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4) + y1 = Fp.mul(y1, tv2) // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4) + let x2n = Fp.mul(x1n, Fp.neg(tv1)) // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd + let y2 = Fp.mul(y1, u) // 18. y2 = y1 * u + y2 = Fp.cmov(y2, Fp.ZERO, e1) // 19. y2 = CMOV(y2, 0, e1) + tv2 = Fp.sqr(y1) // 20. tv2 = y1^2 + tv2 = Fp.mul(tv2, gxd) // 21. tv2 = tv2 * gxd + let e2 = Fp.eql(tv2, gx1) // 22. e2 = tv2 == gx1 + let xn = Fp.cmov(x2n, x1n, e2) // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2 + let y = Fp.cmov(y2, y1, e2) // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2 + let e3 = Fp.isOdd(y) // 25. e3 = sgn0(y) == 1 # Fix sign of y + y = Fp.cmov(y, Fp.neg(y), e2 !== e3) // 26. y = CMOV(y, -y, e2 XOR e3) + return { xn, xd, yn: y, yd: Fp.ONE } // 27. return (xn, xd, y, 1) +} + +function map_to_curve_elligator2_edwards448(u: bigint) { + let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u) // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u) + let xn2 = Fp.sqr(xn) // 2. xn2 = xn^2 + let xd2 = Fp.sqr(xd) // 3. xd2 = xd^2 + let xd4 = Fp.sqr(xd2) // 4. xd4 = xd2^2 + let yn2 = Fp.sqr(yn) // 5. yn2 = yn^2 + let yd2 = Fp.sqr(yd) // 6. yd2 = yd^2 + let xEn = Fp.sub(xn2, xd2) // 7. xEn = xn2 - xd2 + let tv2 = Fp.sub(xEn, xd2) // 8. tv2 = xEn - xd2 + xEn = Fp.mul(xEn, xd2) // 9. xEn = xEn * xd2 + xEn = Fp.mul(xEn, yd) // 10. xEn = xEn * yd + xEn = Fp.mul(xEn, yn) // 11. xEn = xEn * yn + xEn = Fp.mul(xEn, _4n) // 12. xEn = xEn * 4 + tv2 = Fp.mul(tv2, xn2) // 13. tv2 = tv2 * xn2 + tv2 = Fp.mul(tv2, yd2) // 14. tv2 = tv2 * yd2 + let tv3 = Fp.mul(yn2, _4n) // 15. tv3 = 4 * yn2 + let tv1 = Fp.add(tv3, yd2) // 16. tv1 = tv3 + yd2 + tv1 = Fp.mul(tv1, xd4) // 17. tv1 = tv1 * xd4 + let xEd = Fp.add(tv1, tv2) // 18. xEd = tv1 + tv2 + tv2 = Fp.mul(tv2, xn) // 19. tv2 = tv2 * xn + let tv4 = Fp.mul(xn, xd4) // 20. tv4 = xn * xd4 + let yEn = Fp.sub(tv3, yd2) // 21. yEn = tv3 - yd2 + yEn = Fp.mul(yEn, tv4) // 22. yEn = yEn * tv4 + yEn = Fp.sub(yEn, tv2) // 23. yEn = yEn - tv2 + tv1 = Fp.add(xn2, xd2) // 24. tv1 = xn2 + xd2 + tv1 = Fp.mul(tv1, xd2) // 25. tv1 = tv1 * xd2 + tv1 = Fp.mul(tv1, xd) // 26. tv1 = tv1 * xd + tv1 = Fp.mul(tv1, yn2) // 27. tv1 = tv1 * yn2 + tv1 = Fp.mul(tv1, BigInt(-2)) // 28. tv1 = -2 * tv1 + let yEd = Fp.add(tv2, tv1) // 29. yEd = tv2 + tv1 + tv4 = Fp.mul(tv4, yd2) // 30. tv4 = tv4 * yd2 + yEd = Fp.add(yEd, tv4) // 31. yEd = yEd + tv4 + tv1 = Fp.mul(xEd, yEd) // 32. tv1 = xEd * yEd + let e = Fp.eql(tv1, Fp.ZERO) // 33. e = tv1 == 0 + xEn = Fp.cmov(xEn, Fp.ZERO, e) // 34. xEn = CMOV(xEn, 0, e) + xEd = Fp.cmov(xEd, Fp.ONE, e) // 35. xEd = CMOV(xEd, 1, e) + yEn = Fp.cmov(yEn, Fp.ONE, e) // 36. yEn = CMOV(yEn, 1, e) + yEd = Fp.cmov(yEd, Fp.ONE, e) // 37. yEd = CMOV(yEd, 1, e) + + const inv = Fp.invertBatch([xEd, yEd]) // batch division + return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) } // 38. return (xEn, xEd, yEn, yEd) +} + +export const ed448_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + ed448.ExtendedPoint, + (scalars: bigint[]) => map_to_curve_elligator2_edwards448(scalars[0]), + { + DST: 'edwards448_XOF:SHAKE256_ELL2_RO_', + encodeDST: 'edwards448_XOF:SHAKE256_ELL2_NU_', + p: Fp.ORDER, + m: 1, + k: 224, + expand: 'xof', + hash: shake256, + }, + ))() +/** + * @deprecated Use `ed448_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.hashToCurve)() +/** + * @deprecated Use `ed448_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => ed448_hasher.encodeToCurve)() + +function adecafp(other: unknown) { + if (!(other instanceof DcfPoint)) throw new Error('DecafPoint expected') +} + +// 1-d +const ONE_MINUS_D = BigInt('39082') +// 1-2d +const ONE_MINUS_TWO_D = BigInt('78163') +// √(-d) +const SQRT_MINUS_D = BigInt( + '98944233647732219769177004876929019128417576295529901074099889598043702116001257856802131563896515373927712232092845883226922417596214', +) +// 1 / √(-d) +const INVSQRT_MINUS_D = BigInt( + '315019913931389607337177038330951043522456072897266928557328499619017160722351061360252776265186336876723201881398623946864393857820716', +) +// Calculates 1/√(number) +const invertSqrt = (number: bigint) => uvRatio(_1n, number) + +const MAX_448B = BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', +) +const bytes448ToNumberLE = (bytes: Uint8Array) => + ed448.CURVE.Fp.create(bytesToNumberLE(bytes) & MAX_448B) + +type ExtendedPoint = ExtPointType + +// Computes Elligator map for Decaf +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 +function calcElligatorDecafMap(r0: bigint): ExtendedPoint { + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const r = mod(-(r0 * r0)) // 1 + const u0 = mod(d * (r - _1n)) // 2 + const u1 = mod((u0 + _1n) * (u0 - r)) // 3 + + const { isValid: was_square, value: v } = uvRatio(ONE_MINUS_TWO_D, mod((r + _1n) * u1)) // 4 + + let v_prime = v // 5 + if (!was_square) v_prime = mod(r0 * v) + + let sgn = _1n // 6 + if (!was_square) sgn = mod(-_1n) + + const s = mod(v_prime * (r + _1n)) // 7 + let s_abs = s + if (isNegativeLE(s, P)) s_abs = mod(-s) + + const s2 = s * s + const W0 = mod(s_abs * _2n) // 8 + const W1 = mod(s2 + _1n) // 9 + const W2 = mod(s2 - _1n) // 10 + const W3 = mod(v_prime * s * (r - _1n) * ONE_MINUS_TWO_D + sgn) // 11 + return new ed448.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2)) +} + +/** + * Each ed448/ExtendedPoint has 4 different equivalent points. This can be + * a source of bugs for protocols like ring signatures. Decaf was created to solve this. + * Decaf point operates in X:Y:Z:T extended coordinates like ExtendedPoint, + * but it should work in its own namespace: do not combine those two. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448 + */ +class DcfPoint implements Group { + static BASE: DcfPoint + static ZERO: DcfPoint + private readonly ep: ExtendedPoint + // Private property to discourage combining ExtendedPoint + DecafPoint + // Always use Decaf encoding/decoding instead. + constructor(ep: ExtendedPoint) { + this.ep = ep + } + + static fromAffine(ap: AffinePoint): DcfPoint { + return new DcfPoint(ed448.ExtendedPoint.fromAffine(ap)) + } + + /** + * Takes uniform output of 112-byte hash function like shake256 and converts it to `DecafPoint`. + * The hash-to-group operation applies Elligator twice and adds the results. + * **Note:** this is one-way map, there is no conversion from point to hash. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-element-derivation-2 + * @param hex 112-byte output of a hash function + */ + static hashToCurve(hex: Hex): DcfPoint { + hex = ensureBytes('decafHash', hex, 112) + const r1 = bytes448ToNumberLE(hex.slice(0, 56)) + const R1 = calcElligatorDecafMap(r1) + const r2 = bytes448ToNumberLE(hex.slice(56, 112)) + const R2 = calcElligatorDecafMap(r2) + return new DcfPoint(R1.add(R2)) + } + + /** + * Converts decaf-encoded string to decaf point. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-decode-2 + * @param hex Decaf-encoded 56 bytes. Not every 56-byte string is valid decaf encoding + */ + static fromHex(hex: Hex): DcfPoint { + hex = ensureBytes('decafHex', hex, 56) + const { d } = ed448.CURVE + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + const emsg = 'DecafPoint.fromHex: the hex is not valid encoding of DecafPoint' + const s = bytes448ToNumberLE(hex) + + // 1. Check that s_bytes is the canonical encoding of a field element, or else abort. + // 2. Check that s is non-negative, or else abort + if (!equalBytes(numberToBytesLE(s, 56), hex) || isNegativeLE(s, P)) throw new Error(emsg) + + const s2 = mod(s * s) // 1 + const u1 = mod(_1n + s2) // 2 + const u1sq = mod(u1 * u1) + const u2 = mod(u1sq - _4n * d * s2) // 3 + + const { isValid, value: invsqrt } = invertSqrt(mod(u2 * u1sq)) // 4 + + let u3 = mod((s + s) * invsqrt * u1 * SQRT_MINUS_D) // 5 + if (isNegativeLE(u3, P)) u3 = mod(-u3) + + const x = mod(u3 * invsqrt * u2 * INVSQRT_MINUS_D) // 6 + const y = mod((_1n - s2) * invsqrt * u1) // 7 + const t = mod(x * y) // 8 + + if (!isValid) throw new Error(emsg) + return new DcfPoint(new ed448.ExtendedPoint(x, y, _1n, t)) + } + + static msm(points: DcfPoint[], scalars: bigint[]): DcfPoint { + const Fn = Field(ed448.CURVE.n, ed448.CURVE.nBitLength) + return pippenger(DcfPoint, Fn, points, scalars) + } + + /** + * Encodes decaf point to Uint8Array. + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-encode-2 + */ + toRawBytes(): Uint8Array { + let { ex: x, ey: _y, ez: z, et: t } = this.ep + const P = ed448.CURVE.Fp.ORDER + const mod = ed448.CURVE.Fp.create + + const u1 = mod(mod(x + t) * mod(x - t)) // 1 + const x2 = mod(x * x) + const { value: invsqrt } = invertSqrt(mod(u1 * ONE_MINUS_D * x2)) // 2 + + let ratio = mod(invsqrt * u1 * SQRT_MINUS_D) // 3 + if (isNegativeLE(ratio, P)) ratio = mod(-ratio) + + const u2 = mod(INVSQRT_MINUS_D * ratio * z - t) // 4 + + let s = mod(ONE_MINUS_D * invsqrt * x * u2) // 5 + if (isNegativeLE(s, P)) s = mod(-s) + + return numberToBytesLE(s, 56) + } + + toHex(): string { + return bytesToHex(this.toRawBytes()) + } + + toString(): string { + return this.toHex() + } + + // Compare one point to another. + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448-07#name-equals-2 + equals(other: DcfPoint): boolean { + adecafp(other) + const { ex: X1, ey: Y1 } = this.ep + const { ex: X2, ey: Y2 } = other.ep + const mod = ed448.CURVE.Fp.create + // (x1 * y2 == y1 * x2) + return mod(X1 * Y2) === mod(Y1 * X2) + } + + add(other: DcfPoint): DcfPoint { + adecafp(other) + return new DcfPoint(this.ep.add(other.ep)) + } + + subtract(other: DcfPoint): DcfPoint { + adecafp(other) + return new DcfPoint(this.ep.subtract(other.ep)) + } + + multiply(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiply(scalar)) + } + + multiplyUnsafe(scalar: bigint): DcfPoint { + return new DcfPoint(this.ep.multiplyUnsafe(scalar)) + } + + double(): DcfPoint { + return new DcfPoint(this.ep.double()) + } + + negate(): DcfPoint { + return new DcfPoint(this.ep.negate()) + } +} + +export const DecafPoint: typeof DcfPoint = /* @__PURE__ */ (() => { + // decaf448 base point is ed448 base x 2 + // https://github.com/dalek-cryptography/curve25519-dalek/blob/59837c6ecff02b77b9d5ff84dbc239d0cf33ef90/vendor/ristretto.sage#L699 + if (!DcfPoint.BASE) DcfPoint.BASE = new DcfPoint(ed448.ExtendedPoint.BASE).multiply(_2n) + if (!DcfPoint.ZERO) DcfPoint.ZERO = new DcfPoint(ed448.ExtendedPoint.ZERO) + return DcfPoint +})() + +// Hashing to decaf448. https://www.rfc-editor.org/rfc/rfc9380#appendix-C +export const hashToDecaf448 = (msg: Uint8Array, options: htfBasicOpts): DcfPoint => { + const d = options.DST + const DST = typeof d === 'string' ? utf8ToBytes(d) : d + const uniform_bytes = expand_message_xof(msg, DST, 112, 224, shake256) + const P = DcfPoint.hashToCurve(uniform_bytes) + return P +} +export const hash_to_decaf448: typeof hashToDecaf448 = hashToDecaf448 // legacy diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/index.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/index.ts new file mode 100644 index 00000000000..8b4ac3bb10f --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/index.ts @@ -0,0 +1,17 @@ +/** + * Audited & minimal JS implementation of elliptic curve cryptography. + * @module + * @example +```js +import { secp256k1, schnorr } from '@noble/curves/secp256k1'; +import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519'; +import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448'; +import { p256 } from '@noble/curves/p256'; +import { p384 } from '@noble/curves/p384'; +import { p521 } from '@noble/curves/p521'; +import { bls12_381 } from '@noble/curves/bls12-381'; +import { bn254 } from '@noble/curves/bn254'; +import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils'; +``` + */ +throw new Error('root module cannot be imported: import submodules instead. Check out README') diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/jubjub.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/jubjub.ts new file mode 100644 index 00000000000..7c2c07f240c --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/jubjub.ts @@ -0,0 +1,5 @@ +export { + jubjub_findGroupHash as findGroupHash, + jubjub_groupHash as groupHash, + jubjub, +} from './misc.ts' diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/misc.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/misc.ts new file mode 100644 index 00000000000..6109ab69b02 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/misc.ts @@ -0,0 +1,117 @@ +/** + * Miscellaneous, rarely used curves. + * jubjub, babyjubjub, pallas, vesta. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { blake256 } from '@noble/hashes/blake1' +import { blake2s } from '@noble/hashes/blake2s' +import { sha256, sha512 } from '@noble/hashes/sha2' +import { concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils' +import { getHash } from './_shortw_utils.ts' +import { type CurveFn, type ExtPointType, twistedEdwards } from './abstract/edwards.ts' +import { Field, mod } from './abstract/modular.ts' +import { type CurveFn as WCurveFn, weierstrass } from './abstract/weierstrass.ts' + +// Jubjub curves have 𝔽p over scalar fields of other curves. They are friendly to ZK proofs. +// jubjub Fp = bls n. babyjubjub Fp = bn254 n. +// verify manually, check bls12-381.ts and bn254.ts. +// https://neuromancer.sk/std/other/JubJub + +const bls12_381_Fr = Field( + BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'), +) +const bn254_Fr = Field( + BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'), +) + +/** Curve over scalar field of bls12-381. jubjub Fp = bls n */ +export const jubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ + a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'), + d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'), + Fp: bls12_381_Fr, + n: BigInt('0xe7db4ea6533afa906673b0101343b00a6682093ccc81082d0970e5ed6f72cb7'), + h: BigInt(8), + Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'), + Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'), + hash: sha512, + randomBytes, +} as const) + +/** Curve over scalar field of bn254. babyjubjub Fp = bn254 n */ +export const babyjubjub: CurveFn = /* @__PURE__ */ twistedEdwards({ + a: BigInt(168700), + d: BigInt(168696), + Fp: bn254_Fr, + n: BigInt('21888242871839275222246405745257275088614511777268538073601725287587578984328'), + h: BigInt(8), + Gx: BigInt('995203441582195749578291179787384436505546430278305826713579947235728471134'), + Gy: BigInt('5472060717959818805561601436314318772137091100104008585924551046643952123905'), + hash: blake256, + randomBytes, +} as const) + +const jubjub_gh_first_block = utf8ToBytes( + '096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0', +) + +// Returns point at JubJub curve which is prime order and not zero +export function jubjub_groupHash(tag: Uint8Array, personalization: Uint8Array): ExtPointType { + const h = blake2s.create({ personalization, dkLen: 32 }) + h.update(jubjub_gh_first_block) + h.update(tag) + // NOTE: returns ExtendedPoint, in case it will be multiplied later + let p = jubjub.ExtendedPoint.fromHex(h.digest()) + // NOTE: cannot replace with isSmallOrder, returns Point*8 + p = p.multiply(jubjub.CURVE.h) + if (p.equals(jubjub.ExtendedPoint.ZERO)) throw new Error('Point has small order') + return p +} + +// No secret data is leaked here at all. +// It operates over public data: +// const G_SPEND = jubjub.findGroupHash(new Uint8Array(), utf8ToBytes('Item_G_')); +export function jubjub_findGroupHash(m: Uint8Array, personalization: Uint8Array): ExtPointType { + const tag = concatBytes(m, new Uint8Array([0])) + const hashes = [] + for (let i = 0; i < 256; i++) { + tag[tag.length - 1] = i + try { + hashes.push(jubjub_groupHash(tag, personalization)) + } catch (e) {} + } + if (!hashes.length) throw new Error('findGroupHash tag overflow') + return hashes[0] +} + +// Pasta curves. See [Spec](https://o1-labs.github.io/proof-systems/specs/pasta.html). + +export const pasta_p: bigint = BigInt( + '0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001', +) +export const pasta_q: bigint = BigInt( + '0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001', +) + +/** https://neuromancer.sk/std/other/Pallas */ +export const pallas: WCurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(pasta_p), + n: pasta_q, + Gx: mod(BigInt(-1), pasta_p), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) +/** https://neuromancer.sk/std/other/Vesta */ +export const vesta: WCurveFn = weierstrass({ + a: BigInt(0), + b: BigInt(5), + Fp: Field(pasta_q), + n: pasta_p, + Gx: mod(BigInt(-1), pasta_q), + Gy: BigInt(2), + h: BigInt(1), + ...getHash(sha256), +}) diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/nist.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/nist.ts new file mode 100644 index 00000000000..44c3eb545df --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/nist.ts @@ -0,0 +1,171 @@ +/** + * NIST secp256r1 aka p256. + * https://www.secg.org/sec2-v2.pdf, https://neuromancer.sk/std/nist/P-256 + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256, sha384, sha512 } from '@noble/hashes/sha2' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' +import { type Hasher, createHasher } from './abstract/hash-to-curve.ts' +import { Field } from './abstract/modular.ts' +import { mapToCurveSimpleSWU } from './abstract/weierstrass.ts' + +const Fp256 = Field(BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff')) +const p256_a = Fp256.create(BigInt('-3')) +const p256_b = BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b') + +/** + * secp256r1 curve, ECDSA and ECDH methods. + * Field: `2n**224n * (2n**32n-1n) + 2n**192n + 2n**96n-1n` + */ +// prettier-ignore +export const p256: CurveFnWithCreate = createCurve( + { + a: p256_a, + b: p256_b, + Fp: Fp256, + n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'), + Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'), + Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'), + h: BigInt(1), + lowS: false, + } as const, + sha256, +) +/** Alias to p256. */ +export const secp256r1: CurveFnWithCreate = p256 + +const p256_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp256, { + A: p256_a, + B: p256_b, + Z: Fp256.create(BigInt('-10')), + }))() + +/** Hashing / encoding to p256 points / field. RFC 9380 methods. */ +export const p256_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp256r1.ProjectivePoint, (scalars: bigint[]) => p256_mapSWU(scalars[0]), { + DST: 'P256_XMD:SHA-256_SSWU_RO_', + encodeDST: 'P256_XMD:SHA-256_SSWU_NU_', + p: Fp256.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + }))() + +// Field over which we'll do calculations. +const Fp384 = Field( + BigInt( + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff', + ), +) +const p384_a = Fp384.create(BigInt('-3')) +// prettier-ignore +const p384_b = BigInt( + '0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef', +) + +/** + * secp384r1 curve, ECDSA and ECDH methods. + * Field: `2n**384n - 2n**128n - 2n**96n + 2n**32n - 1n`. + * */ +// prettier-ignore +export const p384: CurveFnWithCreate = createCurve( + { + a: p384_a, + b: p384_b, + Fp: Fp384, + n: BigInt( + '0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973', + ), + Gx: BigInt( + '0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7', + ), + Gy: BigInt( + '0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f', + ), + h: BigInt(1), + lowS: false, + } as const, + sha384, +) +/** Alias to p384. */ +export const secp384r1: CurveFnWithCreate = p384 + +const p384_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp384, { + A: p384_a, + B: p384_b, + Z: Fp384.create(BigInt('-12')), + }))() + +/** Hashing / encoding to p384 points / field. RFC 9380 methods. */ +export const p384_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp384r1.ProjectivePoint, (scalars: bigint[]) => p384_mapSWU(scalars[0]), { + DST: 'P384_XMD:SHA-384_SSWU_RO_', + encodeDST: 'P384_XMD:SHA-384_SSWU_NU_', + p: Fp384.ORDER, + m: 1, + k: 192, + expand: 'xmd', + hash: sha384, + }))() + +// Field over which we'll do calculations. +const Fp521 = Field( + BigInt( + '0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + ), +) + +const p521_a = Fp521.create(BigInt('-3')) +const p521_b = BigInt( + '0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00', +) + +/** + * NIST secp521r1 aka p521 curve, ECDSA and ECDH methods. + * Field: `2n**521n - 1n`. + */ +// prettier-ignore +export const p521: CurveFnWithCreate = createCurve( + { + a: p521_a, + b: p521_b, + Fp: Fp521, + n: BigInt( + '0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409', + ), + Gx: BigInt( + '0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66', + ), + Gy: BigInt( + '0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650', + ), + h: BigInt(1), + lowS: false, + allowedPrivateKeyLengths: [130, 131, 132], // P521 keys are variable-length. Normalize to 132b + } as const, + sha512, +) +export const secp521r1: CurveFnWithCreate = p521 + +const p521_mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fp521, { + A: p521_a, + B: p521_b, + Z: Fp521.create(BigInt('-4')), + }))() + +/** Hashing / encoding to p521 points / field. RFC 9380 methods. */ +export const p521_hasher: Hasher = /* @__PURE__ */ (() => + createHasher(secp521r1.ProjectivePoint, (scalars: bigint[]) => p521_mapSWU(scalars[0]), { + DST: 'P521_XMD:SHA-512_SSWU_RO_', + encodeDST: 'P521_XMD:SHA-512_SSWU_NU_', + p: Fp521.ORDER, + m: 1, + k: 256, + expand: 'xmd', + hash: sha512, + }))() diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/p256.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/p256.ts new file mode 100644 index 00000000000..f1bf69ad74e --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/p256.ts @@ -0,0 +1,23 @@ +/** + * NIST secp256r1 aka p256. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p256_hasher, p256 as p256n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p256: typeof p256n = p256n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp256r1: typeof p256n = p256n +/** + * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.hashToCurve)() +/** + * @deprecated Use `p256_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p256_hasher.encodeToCurve)() diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/p384.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/p384.ts new file mode 100644 index 00000000000..f08cc70b11a --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/p384.ts @@ -0,0 +1,23 @@ +/** + * NIST secp384r1 aka p384. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p384_hasher, p384 as p384n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p384: typeof p384n = p384n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp384r1: typeof p384n = p384n +/** + * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.hashToCurve)() +/** + * @deprecated Use `p384_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p384_hasher.encodeToCurve)() diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/p521.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/p521.ts new file mode 100644 index 00000000000..feedf852f72 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/p521.ts @@ -0,0 +1,23 @@ +/** + * NIST secp521r1 aka p521. + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { type HTFMethod } from './abstract/hash-to-curve.ts' +import { p521_hasher, p521 as p521n } from './nist.ts' +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const p521: typeof p521n = p521n +/** + * @deprecated Use `@noble/curves/nist` module directly. + */ +export const secp521r1: typeof p521n = p521n +/** + * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.hashToCurve)() +/** + * @deprecated Use `p521_hasher` from `@noble/curves/nist` module directly. + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => p521_hasher.encodeToCurve)() diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/package.json b/packages/evm/src/precompiles/bls12_381/nbl/src/package.json new file mode 100644 index 00000000000..3dbc1ca591c --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/pasta.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/pasta.ts new file mode 100644 index 00000000000..18aa8b858c7 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/pasta.ts @@ -0,0 +1 @@ +export { pallas, vesta } from './misc.ts' diff --git a/packages/evm/src/precompiles/bls12_381/nbl/src/secp256k1.ts b/packages/evm/src/precompiles/bls12_381/nbl/src/secp256k1.ts new file mode 100644 index 00000000000..810c5698ac6 --- /dev/null +++ b/packages/evm/src/precompiles/bls12_381/nbl/src/secp256k1.ts @@ -0,0 +1,343 @@ +/** + * NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf). + * + * Seems to be rigid (not backdoored) + * [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975). + * + * secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism. + * Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%. + * For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit. + * [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066). + * @module + */ +/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */ +import { sha256 } from '@noble/hashes/sha2' +import { randomBytes } from '@noble/hashes/utils' +import { type CurveFnWithCreate, createCurve } from './_shortw_utils.ts' +import { type HTFMethod, type Hasher, createHasher, isogenyMap } from './abstract/hash-to-curve.ts' +import { Field, mod, pow2 } from './abstract/modular.ts' +import type { Hex, PrivKey } from './abstract/utils.ts' +import { + aInRange, + bytesToNumberBE, + concatBytes, + ensureBytes, + inRange, + numberToBytesBE, +} from './abstract/utils.ts' +import { type ProjPointType as PointType, mapToCurveSimpleSWU } from './abstract/weierstrass.ts' + +const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f') +const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141') +const _1n = BigInt(1) +const _2n = BigInt(2) +const divNearest = (a: bigint, b: bigint) => (a + b / _2n) / b + +/** + * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit. + * (P+1n/4n).toString(2) would produce bits [223x 1, 0, 22x 1, 4x 0, 11, 00] + */ +function sqrtMod(y: bigint): bigint { + const P = secp256k1P + // prettier-ignore + const _3n = BigInt(3), + _6n = BigInt(6), + _11n = BigInt(11), + _22n = BigInt(22) + // prettier-ignore + const _23n = BigInt(23), + _44n = BigInt(44), + _88n = BigInt(88) + const b2 = (y * y * y) % P // x^3, 11 + const b3 = (b2 * b2 * y) % P // x^7 + const b6 = (pow2(b3, _3n, P) * b3) % P + const b9 = (pow2(b6, _3n, P) * b3) % P + const b11 = (pow2(b9, _2n, P) * b2) % P + const b22 = (pow2(b11, _11n, P) * b11) % P + const b44 = (pow2(b22, _22n, P) * b22) % P + const b88 = (pow2(b44, _44n, P) * b44) % P + const b176 = (pow2(b88, _88n, P) * b88) % P + const b220 = (pow2(b176, _44n, P) * b44) % P + const b223 = (pow2(b220, _3n, P) * b3) % P + const t1 = (pow2(b223, _23n, P) * b22) % P + const t2 = (pow2(t1, _6n, P) * b2) % P + const root = pow2(t2, _2n, P) + if (!Fpk1.eql(Fpk1.sqr(root), y)) throw new Error('Cannot find square root') + return root +} + +const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod }) + +/** + * secp256k1 curve, ECDSA and ECDH methods. + * + * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n` + * + * @example + * ```js + * import { secp256k1 } from '@noble/curves/secp256k1'; + * const priv = secp256k1.utils.randomPrivateKey(); + * const pub = secp256k1.getPublicKey(priv); + * const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa + * const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available + * const isValid = secp256k1.verify(sig, msg, pub) === true; + * ``` + */ +export const secp256k1: CurveFnWithCreate = createCurve( + { + a: BigInt(0), + b: BigInt(7), + Fp: Fpk1, + n: secp256k1N, + Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'), + Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'), + h: BigInt(1), // Cofactor + lowS: true, // Allow only low-S signatures by default in sign() and verify() + endo: { + // Endomorphism, see above + beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'), + splitScalar: (k: bigint) => { + const n = secp256k1N + const a1 = BigInt('0x3086d221a7d46bcde86c90e49284eb15') + const b1 = -_1n * BigInt('0xe4437ed6010e88286f547fa90abfe4c3') + const a2 = BigInt('0x114ca50f7a8e2f3f657c1108d9d44cfd8') + const b2 = a1 + const POW_2_128 = BigInt('0x100000000000000000000000000000000') // (2n**128n).toString(16) + + const c1 = divNearest(b2 * k, n) + const c2 = divNearest(-b1 * k, n) + let k1 = mod(k - c1 * a1 - c2 * a2, n) + let k2 = mod(-c1 * b1 - c2 * b2, n) + const k1neg = k1 > POW_2_128 + const k2neg = k2 > POW_2_128 + if (k1neg) k1 = n - k1 + if (k2neg) k2 = n - k2 + if (k1 > POW_2_128 || k2 > POW_2_128) { + throw new Error('splitScalar: Endomorphism failed, k=' + k) + } + return { k1neg, k1, k2neg, k2 } + }, + }, + }, + sha256, +) + +// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code. +// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki +const _0n = BigInt(0) +/** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {} +function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array { + let tagP = TAGGED_HASH_PREFIXES[tag] + if (tagP === undefined) { + const tagH = sha256(Uint8Array.from(tag, (c) => c.charCodeAt(0))) + tagP = concatBytes(tagH, tagH) + TAGGED_HASH_PREFIXES[tag] = tagP + } + return sha256(concatBytes(tagP, ...messages)) +} + +// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03 +const pointToBytes = (point: PointType) => point.toRawBytes(true).slice(1) +const numTo32b = (n: bigint) => numberToBytesBE(n, 32) +const modP = (x: bigint) => mod(x, secp256k1P) +const modN = (x: bigint) => mod(x, secp256k1N) +const Point = secp256k1.ProjectivePoint +const GmulAdd = (Q: PointType, a: bigint, b: bigint) => + Point.BASE.multiplyAndAddUnsafe(Q, a, b) + +// Calculate point, scalar and bytes +function schnorrGetExtPubKey(priv: PrivKey) { + let d_ = secp256k1.utils.normPrivateKeyToScalar(priv) // same method executed in fromPrivateKey + let p = Point.fromPrivateKey(d_) // P = d'⋅G; 0 < d' < n check is done inside + const scalar = p.hasEvenY() ? d_ : modN(-d_) + return { scalar: scalar, bytes: pointToBytes(p) } +} +/** + * lift_x from BIP340. Convert 32-byte x coordinate to elliptic curve point. + * @returns valid point checked for being on-curve + */ +function lift_x(x: bigint): PointType { + aInRange('x', x, _1n, secp256k1P) // Fail if x ≥ p. + const xx = modP(x * x) + const c = modP(xx * x + BigInt(7)) // Let c = x³ + 7 mod p. + let y = sqrtMod(c) // Let y = c^(p+1)/4 mod p. + if (y % _2n !== _0n) y = modP(-y) // Return the unique point P such that x(P) = x and + const p = new Point(x, y, _1n) // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise. + p.assertValidity() + return p +} +const num = bytesToNumberBE +/** + * Create tagged hash, convert it to bigint, reduce modulo-n. + */ +function challenge(...args: Uint8Array[]): bigint { + return modN(num(taggedHash('BIP0340/challenge', ...args))) +} + +/** + * Schnorr public key is just `x` coordinate of Point as per BIP340. + */ +function schnorrGetPublicKey(privateKey: Hex): Uint8Array { + return schnorrGetExtPubKey(privateKey).bytes // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G) +} + +/** + * Creates Schnorr signature as per BIP340. Verifies itself before returning anything. + * auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous. + */ +function schnorrSign( + message: Hex, + privateKey: PrivKey, + auxRand: Hex = randomBytes(32), +): Uint8Array { + const m = ensureBytes('message', message) + const { bytes: px, scalar: d } = schnorrGetExtPubKey(privateKey) // checks for isWithinCurveOrder + const a = ensureBytes('auxRand', auxRand, 32) // Auxiliary random data a: a 32-byte array + const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))) // Let t be the byte-wise xor of bytes(d) and hash/aux(a) + const rand = taggedHash('BIP0340/nonce', t, px, m) // Let rand = hash/nonce(t || bytes(P) || m) + const k_ = modN(num(rand)) // Let k' = int(rand) mod n + if (k_ === _0n) throw new Error('sign failed: k is zero') // Fail if k' = 0. + const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_) // Let R = k'⋅G. + const e = challenge(rx, px, m) // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n. + const sig = new Uint8Array(64) // Let sig = bytes(R) || bytes((k + ed) mod n). + sig.set(rx, 0) + sig.set(numTo32b(modN(k + e * d)), 32) + // If Verify(bytes(P), m, sig) (see below) returns failure, abort + if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced') + return sig +} + +/** + * Verifies Schnorr signature. + * Will swallow errors & return false except for initial type validation of arguments. + */ +function schnorrVerify(signature: Hex, message: Hex, publicKey: Hex): boolean { + const sig = ensureBytes('signature', signature, 64) + const m = ensureBytes('message', message) + const pub = ensureBytes('publicKey', publicKey, 32) + try { + const P = lift_x(num(pub)) // P = lift_x(int(pk)); fail if that fails + const r = num(sig.subarray(0, 32)) // Let r = int(sig[0:32]); fail if r ≥ p. + if (!inRange(r, _1n, secp256k1P)) return false + const s = num(sig.subarray(32, 64)) // Let s = int(sig[32:64]); fail if s ≥ n. + if (!inRange(s, _1n, secp256k1N)) return false + const e = challenge(numTo32b(r), pointToBytes(P), m) // int(challenge(bytes(r)||bytes(P)||m))%n + const R = GmulAdd(P, s, modN(-e)) // R = s⋅G - e⋅P + if (!R || !R.hasEvenY() || R.toAffine().x !== r) return false // -eP == (n-e)P + return true // Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r. + } catch (error) { + return false + } +} + +export type SecpSchnorr = { + getPublicKey: typeof schnorrGetPublicKey + sign: typeof schnorrSign + verify: typeof schnorrVerify + utils: { + randomPrivateKey: () => Uint8Array + lift_x: typeof lift_x + pointToBytes: (point: PointType) => Uint8Array + numberToBytesBE: typeof numberToBytesBE + bytesToNumberBE: typeof bytesToNumberBE + taggedHash: typeof taggedHash + mod: typeof mod + } +} +/** + * Schnorr signatures over secp256k1. + * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki + * @example + * ```js + * import { schnorr } from '@noble/curves/secp256k1'; + * const priv = schnorr.utils.randomPrivateKey(); + * const pub = schnorr.getPublicKey(priv); + * const msg = new TextEncoder().encode('hello'); + * const sig = schnorr.sign(msg, priv); + * const isValid = schnorr.verify(sig, msg, pub); + * ``` + */ +export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => ({ + getPublicKey: schnorrGetPublicKey, + sign: schnorrSign, + verify: schnorrVerify, + utils: { + randomPrivateKey: secp256k1.utils.randomPrivateKey, + lift_x, + pointToBytes, + numberToBytesBE, + bytesToNumberBE, + taggedHash, + mod, + }, +}))() + +const isoMap = /* @__PURE__ */ (() => + isogenyMap( + Fpk1, + [ + // xNum + [ + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7', + '0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581', + '0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262', + '0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c', + ], + // xDen + [ + '0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b', + '0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + // yNum + [ + '0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c', + '0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3', + '0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931', + '0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84', + ], + // yDen + [ + '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b', + '0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573', + '0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f', + '0x0000000000000000000000000000000000000000000000000000000000000001', // LAST 1 + ], + ].map((i) => i.map((j) => BigInt(j))) as [bigint[], bigint[], bigint[], bigint[]], + ))() +const mapSWU = /* @__PURE__ */ (() => + mapToCurveSimpleSWU(Fpk1, { + A: BigInt('0x3f8731abdd661adca08a5558f0f5d272e953d363cb6f0e5d405447c01a444533'), + B: BigInt('1771'), + Z: Fpk1.create(BigInt('-11')), + }))() +/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */ +export const secp256k1_hasher: Hasher = /* @__PURE__ */ (() => + createHasher( + secp256k1.ProjectivePoint, + (scalars: bigint[]) => { + const { x, y } = mapSWU(Fpk1.create(scalars[0])) + return isoMap(x, y) + }, + { + DST: 'secp256k1_XMD:SHA-256_SSWU_RO_', + encodeDST: 'secp256k1_XMD:SHA-256_SSWU_NU_', + p: Fpk1.ORDER, + m: 1, + k: 128, + expand: 'xmd', + hash: sha256, + } as const, + ))() + +/** + * @deprecated Use `secp256k1_hasher` + */ +export const hashToCurve: HTFMethod = /* @__PURE__ */ (() => secp256k1_hasher.hashToCurve)() + +/** + * @deprecated Use `secp256k1_hasher` + */ +export const encodeToCurve: HTFMethod = /* @__PURE__ */ (() => + secp256k1_hasher.encodeToCurve)() diff --git a/packages/evm/src/precompiles/bls12_381/noble.ts b/packages/evm/src/precompiles/bls12_381/noble.ts index a8658c22920..a928df90bb1 100644 --- a/packages/evm/src/precompiles/bls12_381/noble.ts +++ b/packages/evm/src/precompiles/bls12_381/noble.ts @@ -6,7 +6,7 @@ import { equalsBytes, setLengthLeft, } from '@ethereumjs/util' -import { bls12_381 } from '../../../../noble-curves/bls12-381.js' +import { bls12_381 } from './nbl/src/bls12-381.ts' import { EVMError, EVMErrorMessages } from '../../errors.ts' From de05e6620b49eb74676c8bdf9f761123c6172fe4 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Tue, 22 Apr 2025 16:35:33 +0200 Subject: [PATCH 10/10] update noble [no ci] --- packages/evm/src/precompiles/bls12_381/noble.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/evm/src/precompiles/bls12_381/noble.ts b/packages/evm/src/precompiles/bls12_381/noble.ts index a928df90bb1..89cd7a3598c 100644 --- a/packages/evm/src/precompiles/bls12_381/noble.ts +++ b/packages/evm/src/precompiles/bls12_381/noble.ts @@ -20,9 +20,9 @@ import { BLS_ZERO_BUFFER, } from './constants.ts' -import type { Fp2 } from '@noble/curves/abstract/tower' -import type { AffinePoint } from '@noble/curves/abstract/weierstrass' import type { EVMBLSInterface } from '../../types.ts' +import type { Fp2 } from './nbl/src/abstract/tower.ts' +import type { AffinePoint } from './nbl/src/abstract/weierstrass.ts' const G1_ZERO = bls12_381.G1.ProjectivePoint.ZERO const G2_ZERO = bls12_381.G2.ProjectivePoint.ZERO