├── .eslintrc ├── .eslintrc.json ├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── .solcover.js ├── .solhint.json ├── .solhintignore ├── .soliumignore ├── .soliumrc.json ├── .travis.yml ├── LICENSE ├── README.md ├── benchmark ├── EcGasHelper.sol ├── Secp256k1GasHelper.sol ├── gas.js ├── secp256k1-data.json └── secp256k1.js ├── contracts ├── EllipticCurve.sol ├── FastEcMul.sol └── helpers │ └── TestEllipticCurve.sol ├── examples └── Secp256k1.sol ├── package.json ├── test ├── data │ ├── P192.json │ ├── P224.json │ ├── P256-aux.json │ ├── P256.json │ ├── secp192k1.json │ ├── secp224k1.json │ ├── secp256k1-aux.json │ └── secp256k1.json ├── ellipticCurve.js └── fastEcMul.js └── truffle-config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["standard"], 3 | "env": { 4 | "browser": false, 5 | "node": true, 6 | "jest": true, 7 | "mocha": true, 8 | "es2021": true 9 | }, 10 | "globals" : { 11 | "artifacts": false, 12 | "contract": false, 13 | "assert": false, 14 | "web3": false 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": 12, 18 | "sourceType": "module" 19 | }, 20 | "rules": { 21 | "comma-dangle": ["error", { 22 | "arrays": "always-multiline", 23 | "objects": "always-multiline", 24 | "imports": "always-multiline", 25 | "exports": "always-multiline", 26 | "functions": "ignore" 27 | }], 28 | "indent": ["error", 2, {"SwitchCase": 1 }], 29 | "jsx-quotes": [2, "prefer-double"], 30 | "prefer-promise-reject-errors": 0, 31 | "quotes": [2, "double"], 32 | "import/export": 0, 33 | "no-useless-constructor": 1, 34 | "handle-callback-err": 1, 35 | "max-len" : ["error", { "code": 130 }] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["standard"], 3 | "env": { 4 | "browser": false, 5 | "node": true, 6 | "jest": true, 7 | "mocha": true 8 | }, 9 | "globals" : { 10 | "artifacts": false, 11 | "contract": false, 12 | "assert": false, 13 | "web3": false 14 | }, 15 | "rules": { 16 | "comma-dangle": ["error", { 17 | "arrays": "always-multiline", 18 | "objects": "always-multiline", 19 | "imports": "always-multiline", 20 | "exports": "always-multiline", 21 | "functions": "ignore" 22 | }], 23 | "indent": ["error", 2, {"SwitchCase": 1 }], 24 | "jsx-quotes": [2, "prefer-double"], 25 | "prefer-promise-reject-errors": 0, 26 | "quotes": [2, "double"], 27 | "import/export": 0, 28 | "no-useless-constructor": 1, 29 | "handle-callback-err": 1, 30 | "max-len" : ["error", { "code": 120 }] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: On push 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | env: 11 | CI: true 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v1 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - name: Install dependencies 24 | run: | 25 | npm install 26 | - name: Check format 27 | run: | 28 | npm run fmt 29 | - name: Compile solidity contracts 30 | run: | 31 | npm run compile 32 | - name: Run tests 33 | run: | 34 | npm run test 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | coverage/ 4 | coverage.json 5 | 6 | .idea 7 | .vscode 8 | 9 | yarn.lock 10 | package-lock.json -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: [ 3 | 'Migrations.sol', 4 | 'helpers/TestEllipticCurve.sol', 5 | ], 6 | } -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": [ 5 | "error", 6 | ">=0.6.0 <0.9.0" 7 | ], 8 | "constructor-syntax": "warn", 9 | "func-param-name-mixedcase": "warn", 10 | "func-visibility": [ 11 | "warn", 12 | { 13 | "ignoreConstructors": true 14 | } 15 | ], 16 | "no-global-import": "off", 17 | "modifier-name-mixedcase": "warn", 18 | "no-empty-blocks": "off", 19 | "no-inline-assembly": "off", 20 | "var-name-mixedcase": "off", 21 | "reason-string": [ 22 | "warn", 23 | { 24 | "maxLength": 128 25 | } 26 | ] 27 | } 28 | } -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/Migrations.sol 3 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:all", 3 | "plugins": ["security"], 4 | "rules": { 5 | "quotes": ["error", "double"], 6 | "indentation": ["error", 2], 7 | "linebreak-style": ["error", "unix"], 8 | "security/no-assign-params": "off", 9 | "security/no-inline-assembly": "off" 10 | } 11 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: false 3 | group: beta 4 | language: node_js 5 | node_js: 6 | - "10" 7 | - "12" 8 | 9 | cache: 10 | directories: 11 | - node_modules 12 | 13 | jobs: 14 | fast_finish: true 15 | include: 16 | - stage: tests 17 | name: "Linter" 18 | script: npm run fmt 19 | 20 | - stage: tests 21 | name: "Unit tests" 22 | script: npm run test 23 | 24 | - stage: tests 25 | name: "Coveralls" 26 | script: npm run coveralls 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Witnet Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elliptic-curve-solidity [![npm version](https://badge.fury.io/js/elliptic-curve-solidity.svg)](https://badge.fury.io/js/elliptic-curve-solidity) [![TravisCI](https://travis-ci.com/witnet/elliptic-curve-solidity.svg?branch=master)](https://travis-ci.com/witnet/elliptic-curve-solidity) [![Coverage Status](https://coveralls.io/repos/github/witnet/elliptic-curve-solidity/badge.svg?branch=master)](https://coveralls.io/github/witnet/elliptic-curve-solidity?branch=master) 2 | 3 | `elliptic-curve-solidity` is an open source implementation of Elliptic Curve arithmetic operations written in Solidity. 4 | 5 | _DISCLAIMER: This is experimental software. **Use it at your own risk**!_ 6 | 7 | The solidity contracts have been generalized in order to support any elliptic curve based on prime numbers up to 256 bits. 8 | 9 | `elliptic-curve-solidity` has been designed as a library with **only pure functions** aiming at decreasing gas consumption as much as possible. Additionally, gas consumption comparison can be found in the benchmark section. This library **does not check whether the points passed as arguments to the library belong to the curve**. However, the library exposes a method called *`isOnCurve`* that can be utilized before using the library functions. 10 | 11 | It contains 2 solidity libraries: 12 | 13 | 1. `EllipticCurve.sol`: provides main elliptic curve operations in affine and Jacobian coordinates. 14 | 2. `FastEcMul.sol`: provides a fast elliptic curve multiplication by using scalar decomposition and wNAF scalar representation. 15 | 16 | `EllipticCurve` library provides functions for: 17 | 18 | - Modular 19 | - inverse 20 | - exponentiation 21 | - Jacobian coordinates 22 | - addition 23 | - double 24 | - multiplication 25 | - Affine coordinates 26 | - inverse 27 | - addition 28 | - subtraction 29 | - multiplication 30 | - Auxiliary 31 | - conversion to affine coordinates 32 | - derive coordinate Y from compressed EC point 33 | - check if EC point is on curve 34 | 35 | `FastEcMul` library provides support for: 36 | 37 | - Scalar decomposition 38 | - Simultaneous multiplication (computes 2 EC multiplications using wNAF scalar representation) 39 | 40 | ## Supported curves 41 | 42 | The `elliptic-curve-solidity` contract supports up to 256-bit curves. However, it has been extensively tested for the following curves: 43 | 44 | - `secp256k1` 45 | - `secp224k1` 46 | - `secp192k1` 47 | - `secp256r1` (aka P256) 48 | - `secp192r1` (aka P192) 49 | - `secp224r1` (aka P224) 50 | 51 | Known limitations: 52 | 53 | - `deriveY` function do not work with the curves `secp224r1` and `secp224k1` because of the selected derivation algorithm. The computations for this curve are done with a modulo prime `p` such that `p mod 4 = 1`, thus a more complex algorithm is required (e.g. *Tonelli-Shanks algorithm*). Note that `deriveY` is just an auxiliary function, and thus does not limit the functionality of curve arithmetic operations. 54 | - the library only supports elliptic curves with `cofactor = 1` (all supported curves have a `cofactor = 1`). 55 | 56 | ## Usage 57 | 58 | `EllipticCurve.sol` library can be used directly by importing it. 59 | 60 | The [Secp256k1](https://github.com/witnet/elliptic-curve-solidity/blob/master/examples/Secp256k1.sol) example depicts how to use the library by providing a function to derive a public key from a secret key: 61 | 62 | ```solidity 63 | pragma solidity 0.6.12; 64 | 65 | import "elliptic-curve-solidity/contracts/EllipticCurve.sol"; 66 | 67 | 68 | contract Secp256k1 { 69 | 70 | uint256 public constant GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; 71 | uint256 public constant GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; 72 | uint256 public constant AA = 0; 73 | uint256 public constant BB = 7; 74 | uint256 public constant PP = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; 75 | 76 | function derivePubKey(uint256 privKey) public pure returns(uint256 qx, uint256 qy) { 77 | (qx, qy) = EllipticCurve.ecMul( 78 | privKey, 79 | GX, 80 | GY, 81 | AA, 82 | PP 83 | ); 84 | } 85 | } 86 | ``` 87 | 88 | The cost of a key derivation operation in Secp256k1 is around 550k gas. 89 | 90 | ```bash 91 | ·--------------------------------------------------|--------------------------· 92 | | Gas · Block limit: 6721975 gas │ 93 | ···················································|··························· 94 | | · 100 gwei/gas · 592.30 usd/eth │ 95 | ··················|··········|··········|··········|············|·············· 96 | | Method · Min · Max · Avg · # calls · usd (avg) │ 97 | ··················|··········|··········|··········|············|·············· 98 | | derivePubKey · 476146 · 518863 · 499884 · 18 · 29.61 │ 99 | ··················|··········|··········|··········|············|·············· 100 | ``` 101 | 102 | The cost of a simultaneous multiplication (using wNAF) consumes around 35% of the gas required by 2 EC multiplications. 103 | 104 | ## Benchmark 105 | 106 | Gas consumption and USD price estimation with a gas price of 100 Gwei, derived from [ETH Gas Station](https://ethgasstation.info/): 107 | 108 | ```bash 109 | ·----------------------------------------|---------------------------|-------------|----------------------------· 110 | | Solc version: 0.6.12+commit.27d51765 · Optimizer enabled: true · Runs: 200 · Block limit: 6718946 gas │ 111 | ·········································|···························|·············|····························· 112 | | Methods · 100 gwei/gas · 613.52 usd/eth │ 113 | ··················|······················|·············|·············|·············|··············|·············· 114 | | Contract · Method · Min · Max · Avg · # calls · usd (avg) │ 115 | ··················|······················|·············|·············|·············|··············|·············· 116 | | EllipticCurve · decomposeScalar · 55811 · 65399 · 61939 · 134 · 3.80 │ 117 | ··················|······················|·············|·············|·············|··············|·············· 118 | | EllipticCurve · deriveY · 45275 · 55545 · 50410 · 4 · 3.09 │ 119 | ··················|······················|·············|·············|·············|··············|·············· 120 | | EllipticCurve · ecAdd · 24305 · 56323 · 49119 · 472 · 3.01 │ 121 | ··················|······················|·············|·············|·············|··············|·············· 122 | | EllipticCurve · ecInv · 22906 · 23074 · 22990 · 2 · 1.41 │ 123 | ··················|······················|·············|·············|·············|··············|·············· 124 | | EllipticCurve · ecMul · 24911 · 623087 · 350939 · 561 · 21.53 │ 125 | ··················|······················|·············|·············|·············|··············|·············· 126 | | EllipticCurve · ecSimMul · 76465 · 488165 · 243763 · 125 · 14.96 │ 127 | ··················|······················|·············|·············|·············|··············|·············· 128 | | EllipticCurve · ecSub · 42634 · 56236 · 49717 · 228 · 3.05 │ 129 | ··················|······················|·············|·············|·············|··············|·············· 130 | | EllipticCurve · invMod · 22153 · 49255 · 39627 · 12 · 2.43 │ 131 | ··················|······················|·············|·············|·············|··············|·············· 132 | | EllipticCurve · isOnCurve · 23400 · 24071 · 23623 · 16 · 1.45 │ 133 | ··················|······················|·············|·············|·············|··············|·············· 134 | | EllipticCurve · toAffine · 50145 · 50850 · 50498 · 4 · 3.10 │ 135 | ·----------------------------------------|-------------|-------------|-------------|--------------|-------------· 136 | ``` 137 | 138 | ## Acknowledgements 139 | 140 | Some functions of the contract are based on: 141 | 142 | - [Comparatively Study of ECC and Jacobian Elliptic Curve Cryptography](https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf) by Anagha P. Zele and Avinash P. Wadhe 143 | - [`Numerology`](https://github.com/nucypher/numerology) by NuCypher 144 | - [`solidity-arithmetic`](https://github.com/gnosis/solidity-arithmetic) by Gnosis 145 | - [`ecsol`](https://github.com/jbaylina/ecsol) written by Jordi Baylina 146 | - [`standard contracts`](https://github.com/androlo/standard-contracts) written by Andreas Olofsson 147 | 148 | ## License 149 | 150 | `elliptic-curve-solidity` is published under the [MIT license][license]. 151 | 152 | [license]: https://github.com/witnet/elliptic-curve-solidity/blob/master/LICENSE 153 | -------------------------------------------------------------------------------- /benchmark/EcGasHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../contracts/EllipticCurve.sol"; 6 | import "../contracts/FastEcMul.sol"; 7 | 8 | /** 9 | ** @title Test Helper for the EllipticCurve contract 10 | ** @dev The aim of this contract is twofold: 11 | ** - 1. Raise the visibility modifier of contract functions for testing purposes 12 | ** - 2. Removal of the `pure` modifier to allow gas consumption analysis 13 | ** @author Witnet Foundation 14 | */ 15 | contract EcGasHelper { 16 | function _toAffine( 17 | uint256 _x, 18 | uint256 _y, 19 | uint256 _z, 20 | uint256 _pp 21 | ) 22 | external 23 | returns (uint256, uint256) 24 | { 25 | return EllipticCurve.toAffine(_x, _y, _z, _pp); 26 | } 27 | 28 | function _invMod(uint256 _x, uint256 _pp) external returns (uint256) { 29 | return EllipticCurve.invMod(_x, _pp); 30 | } 31 | 32 | function _deriveY( 33 | uint8 _prefix, 34 | uint256 _x, 35 | uint256 _aa, 36 | uint256 _bb, 37 | uint256 _pp 38 | ) external returns (uint256) { 39 | return EllipticCurve.deriveY(_prefix, _x, _aa, _bb, _pp); 40 | } 41 | 42 | function _isOnCurve( 43 | uint _x, 44 | uint _y, 45 | uint _aa, 46 | uint _bb, 47 | uint _pp 48 | ) external returns (bool) { 49 | return EllipticCurve.isOnCurve(_x, _y, _aa, _bb, _pp); 50 | } 51 | 52 | function _ecInv( 53 | uint256 _x, 54 | uint256 _y, 55 | uint256 _pp 56 | ) external returns (uint256, uint256) { 57 | return EllipticCurve.ecInv(_x, _y, _pp); 58 | } 59 | 60 | function _ecAdd( 61 | uint256 _x1, 62 | uint256 _y1, 63 | uint256 _x2, 64 | uint256 _y2, 65 | uint256 _aa, 66 | uint256 _pp 67 | ) 68 | external 69 | returns (uint256, uint256) 70 | { 71 | return EllipticCurve.ecAdd(_x1, _y1, _x2, _y2, _aa, _pp); 72 | } 73 | 74 | function _ecSub( 75 | uint256 _x1, 76 | uint256 _y1, 77 | uint256 _x2, 78 | uint256 _y2, 79 | uint256 _aa, 80 | uint256 _pp 81 | ) 82 | external 83 | returns (uint256, uint256) 84 | { 85 | return EllipticCurve.ecSub(_x1, _y1, _x2, _y2, _aa, _pp); 86 | } 87 | 88 | function _ecMul( 89 | uint256 _k, 90 | uint256 _x, 91 | uint256 _y, 92 | uint256 _aa, 93 | uint256 _pp 94 | ) 95 | external 96 | returns (uint256, uint256) 97 | { 98 | return EllipticCurve.ecMul(_k, _x, _y, _aa, _pp); 99 | } 100 | 101 | function _decomposeScalar( 102 | uint256 _k, 103 | uint256 _nn, 104 | uint256 _lambda 105 | ) 106 | external 107 | returns (int256, int256) 108 | { 109 | return FastEcMul.decomposeScalar(_k, _nn, _lambda); 110 | } 111 | 112 | function _ecSimMul( 113 | int256[4] calldata _scalars, 114 | uint256[4] calldata _points, 115 | uint256 _aa, 116 | uint256 _beta, 117 | uint256 _pp 118 | ) 119 | external 120 | returns (uint256, uint256) 121 | { 122 | return FastEcMul.ecSimMul(_scalars, _points, _aa, _beta, _pp); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /benchmark/Secp256k1GasHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../contracts/EllipticCurve.sol"; 6 | 7 | /** 8 | * @title Secp256k1 Elliptic Curve Gas Helper 9 | * @notice Example of particularization of Elliptic Curve for secp256k1 curve with a non-pure function to analyze gas cost 10 | * @author Witnet Foundation 11 | */ 12 | contract Secp256k1GasHelper { 13 | uint256 public constant GX = 14 | 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; 15 | uint256 public constant GY = 16 | 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; 17 | uint256 public constant AA = 0; 18 | uint256 public constant BB = 7; 19 | uint256 public constant PP = 20 | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; 21 | 22 | function derivePubKey( 23 | uint256 privKey 24 | ) external returns (uint256 qx, uint256 qy) { 25 | (qx, qy) = EllipticCurve.ecMul(privKey, GX, GY, AA, PP); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /benchmark/gas.js: -------------------------------------------------------------------------------- 1 | const EcGasHelper = artifacts.require("EcGasHelper") 2 | 3 | contract("EcGasHelper - Gas consumption analysis", accounts => { 4 | // /////////////////////////////////////////// // 5 | // Check auxiliary operations for given curves // 6 | // /////////////////////////////////////////// // 7 | const auxCurves = ["secp256k1", "P256"] 8 | for (const curve of auxCurves) { 9 | describe(`Aux. operations - Curve ${curve}`, () => { 10 | const curveData = require(`../test/data/${curve}-aux.json`) 11 | 12 | const pp = web3.utils.toBN(curveData.params.pp) 13 | const aa = web3.utils.toBN(curveData.params.aa) 14 | const bb = web3.utils.toBN(curveData.params.bb) 15 | 16 | let helper 17 | before(async () => { 18 | helper = await EcGasHelper.new() 19 | }) 20 | 21 | // toAffine 22 | for (const [index, test] of curveData.toAffine.valid.entries()) { 23 | it(`should convert a Jacobian point to affine (${index + 1})`, async () => { 24 | await helper._toAffine( 25 | web3.utils.toBN(test.input.x), 26 | web3.utils.toBN(test.input.y), 27 | web3.utils.toBN(test.input.z), 28 | pp 29 | ) 30 | }) 31 | } 32 | 33 | // invMod 34 | for (const [index, test] of curveData.invMod.valid.entries()) { 35 | it(`should invert a scalar (${index + 1}) - ${test.description}`, async () => { 36 | await helper._invMod( 37 | web3.utils.toBN(test.input.k), 38 | pp, 39 | ) 40 | }) 41 | } 42 | 43 | // deriveY 44 | for (const [index, test] of curveData.deriveY.valid.entries()) { 45 | it(`should decode coordinate y from compressed point (${index + 1})`, async () => { 46 | await helper._deriveY( 47 | web3.utils.hexToBytes(test.input.sign), 48 | web3.utils.hexToBytes(test.input.x), 49 | aa, 50 | bb, 51 | pp 52 | ) 53 | }) 54 | } 55 | 56 | // isOnCurve 57 | for (const [index, test] of curveData.isOnCurve.valid.entries()) { 58 | it(`should identify if point is on the curve (${index + 1}) - ${test.output.isOnCurve}`, async () => { 59 | await helper._isOnCurve( 60 | web3.utils.hexToBytes(test.input.x), 61 | web3.utils.hexToBytes(test.input.y), 62 | aa, 63 | bb, 64 | pp) 65 | }) 66 | } 67 | 68 | // invertPoint 69 | for (const [index, test] of curveData.invertPoint.valid.entries()) { 70 | it(`should invert an EC point (${index + 1})`, async () => { 71 | await helper._ecInv( 72 | web3.utils.hexToBytes(test.input.x), 73 | web3.utils.hexToBytes(test.input.y), 74 | pp 75 | ) 76 | }) 77 | } 78 | }) 79 | } 80 | 81 | // /////////////////////////////////////////////// // 82 | // Check EC arithmetic operations for given curves // 83 | // /////////////////////////////////////////////// // 84 | const curves = ["secp256k1", "secp192k1", "secp224k1", "P256", "P192", "P224"] 85 | for (const curve of curves) { 86 | describe(`Arithmetic operations - Curve ${curve}`, () => { 87 | const curveData = require(`../test/data/${curve}.json`) 88 | 89 | const pp = web3.utils.toBN(curveData.params.pp) 90 | const nn = web3.utils.toBN(curveData.params.nn) 91 | const aa = web3.utils.toBN(curveData.params.aa) 92 | const lambda = web3.utils.toBN(curveData.params.lambda) 93 | const beta = web3.utils.toBN(curveData.params.beta) 94 | 95 | let helper 96 | before(async () => { 97 | helper = await EcGasHelper.new() 98 | }) 99 | 100 | // Addition 101 | for (const [index, test] of curveData.addition.valid.entries()) { 102 | it(`should add two numbers (${index + 1}) - ${test.description}`, async () => { 103 | await helper._ecAdd( 104 | web3.utils.toBN(test.input.x1), 105 | web3.utils.toBN(test.input.y1), 106 | web3.utils.toBN(test.input.x2), 107 | web3.utils.toBN(test.input.y2), 108 | aa, 109 | pp 110 | ) 111 | }) 112 | } 113 | 114 | // Subtraction 115 | for (const [index, test] of curveData.subtraction.valid.entries()) { 116 | it(`should subtract two numbers (${index + 1}) - ${test.description}`, async () => { 117 | await helper._ecSub( 118 | web3.utils.toBN(test.input.x1), 119 | web3.utils.toBN(test.input.y1), 120 | web3.utils.toBN(test.input.x2), 121 | web3.utils.toBN(test.input.y2), 122 | aa, 123 | pp 124 | ) 125 | }) 126 | } 127 | 128 | // Multiplication 129 | for (const [index, test] of curveData.multiplication.valid.entries()) { 130 | it(`should multiply EC points (${index + 1}) - ${test.description}`, async () => { 131 | await helper._ecMul( 132 | web3.utils.toBN(test.input.k), 133 | web3.utils.toBN(test.input.x), 134 | web3.utils.toBN(test.input.y), 135 | aa, 136 | pp 137 | ) 138 | }) 139 | } 140 | 141 | // Scalar decomposition 142 | for (const [index, test] of curveData.decomposeScalar.valid.entries()) { 143 | it(`should decompose an scalar (${index + 1}) - ${test.description}`, async () => { 144 | await helper._decomposeScalar( 145 | web3.utils.toBN(test.input.k), 146 | nn, 147 | lambda) 148 | }) 149 | } 150 | 151 | // Simultaneous multiplication 152 | for (const [index, test] of curveData.simMul.valid.entries()) { 153 | it(`should do a simultaneous multiplication (${index + 1}) - ${test.description}`, async () => { 154 | await helper._ecSimMul( 155 | [ 156 | web3.utils.toBN(test.input.k1), 157 | web3.utils.toBN(test.input.k2), 158 | web3.utils.toBN(test.input.l1), 159 | web3.utils.toBN(test.input.l2), 160 | ], 161 | [ 162 | web3.utils.toBN(test.input.px), 163 | web3.utils.toBN(test.input.py), 164 | web3.utils.toBN(test.input.qx), 165 | web3.utils.toBN(test.input.qy), 166 | ], 167 | aa, 168 | beta, 169 | pp 170 | ) 171 | }) 172 | } 173 | 174 | // MulAddMul 175 | for (const [index, test] of curveData.mulAddMul.valid.entries()) { 176 | it(`should do decompose scalar and simult. multiplication (${index + 1}) - ${test.description}`, async () => { 177 | const k = await helper._decomposeScalar.call( 178 | web3.utils.toBN(test.input.k), 179 | nn, 180 | lambda) 181 | await helper._decomposeScalar( 182 | web3.utils.toBN(test.input.k), 183 | nn, 184 | lambda) 185 | const l = await helper._decomposeScalar.call( 186 | web3.utils.toBN(test.input.l), 187 | nn, 188 | lambda) 189 | await helper._decomposeScalar( 190 | web3.utils.toBN(test.input.l), 191 | nn, 192 | lambda) 193 | await helper._ecSimMul( 194 | [ 195 | web3.utils.toBN(k[0]), 196 | web3.utils.toBN(k[1]), 197 | web3.utils.toBN(l[0]), 198 | web3.utils.toBN(l[1]), 199 | ], 200 | [ 201 | web3.utils.toBN(test.input.px), 202 | web3.utils.toBN(test.input.py), 203 | web3.utils.toBN(test.input.qx), 204 | web3.utils.toBN(test.input.qy), 205 | ], 206 | aa, 207 | beta, 208 | pp 209 | ) 210 | }) 211 | } 212 | }) 213 | } 214 | }) 215 | -------------------------------------------------------------------------------- /benchmark/secp256k1-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "keypairs": [ 3 | { 4 | "priv": "0x2569d5e120b10d696933074eecb9182719fb3a89b7714bc99037d8416b391436", 5 | "pub": [ 6 | "0x27553437c338ef8e8b0da369a0c98751e6aa9296eba502e790306377119dba98", 7 | "0x518d093884d86a28bdf160e44b0db7620b187c69e15773a7d90ac3b1820afb7e" 8 | ] 9 | }, 10 | { 11 | "priv": "0xe370174cb9fea3b5c1ef39bcdf36d321cefb06e0e8a6cb856e1bb3e9be3c4385", 12 | "pub": [ 13 | "0xecffcdb5dd6d9479147a5b09b5577e7b92145a3f06f1c19437e2807642a7e0b1", 14 | "0x9f46ed2763f2a5f4b055cd21a81bf9c8301bf5f277c9160598e4b252888319cd" 15 | ] 16 | }, 17 | { 18 | "priv": "0xa5378a4c6db7a076af65cd728f6fe3cf59f416a3d8f74b31b0d76f666a868d09", 19 | "pub": [ 20 | "0xc2704fed5dc41d3979235b85edda8f86f1806c17ce0a516a034c605d2b4f9a26", 21 | "0x6970c3dd18910d09250143db08fed1065a522403df0c204ed240a07d123b29d5" 22 | ] 23 | }, 24 | { 25 | "priv": "0x40a62a62984797e129b9f84fb0202a10c37b52ad83da2d4f3f11c6a8587999f6", 26 | "pub": [ 27 | "0x92e5563bdaaabf1065127509980082e09cd7529d6416ae1d56bab6e9e04b007b", 28 | "0x6c28cf8de86dcc56467929ececa0ba91dd4a321d2a2536bb6b6967f5a81fa4fb" 29 | ] 30 | }, 31 | { 32 | "priv": "0x32e3506d0cf7c8e73c5692f67e6b4c2377a5c0728b4719ff948f420609a3bcdf", 33 | "pub": [ 34 | "0xcdd7bdaac85eb8cdfce9579400afc8bdd71736c7df8e91a0aa8fda63e3df9cae", 35 | "0xe406a9c2a29b3a0217833771eff8e098944113b8e9b9aefb7096ddddfdbb2a0b" 36 | ] 37 | }, 38 | { 39 | "priv": "0x1b3c26da0280b299ecfbdc8d9b6e69677094f1c034010a9a27ba482185355ec2", 40 | "pub": [ 41 | "0xeddd9495bfbe1b77d2f6552d70eb00fc43a161a32b5e80b85631490ba1c53aeb", 42 | "0xbd8627018988c8ecae615d02e3f35935330e66be95115aba50aa1301807a02f5" 43 | ] 44 | }, 45 | { 46 | "priv": "0x9a2e734e0057dc4cbbf8418f9e3d7b9a638e121f1e217884579284b802d0fab3", 47 | "pub": [ 48 | "0xfad4abceb55011558b4bd2215407782a913e994ccd3716a255e7551113b33e72", 49 | "0xfa8c7f550c36de84157cba0e0edc562d51a4e6b38cf62c97efeb3a2cc4dd0c45" 50 | ] 51 | }, 52 | { 53 | "priv": "0xb79a54eb34d1a2f75d956f593dbd08fb75d307847838a64aec9adc0ae74c3bb0", 54 | "pub": [ 55 | "0x09bb12d6d08516ead6aabb9120be947936c7df03293d0f1f2e8375268bab3954", 56 | "0x06a58958e595d0aa603bd66c429a7b89c858e87f11c01c6492d9bda1e913a269" 57 | ] 58 | }, 59 | { 60 | "priv": "0xb15b46827e551c12f8bfe066a634aacfd907be42186ec3e4b3d69baf8efa5bde", 61 | "pub": [ 62 | "0x218bc76d92434c0deeda76bb6a725511d5b2cc4c8ef4b75d173938aeb93f4417", 63 | "0x399d03b8347297b873c9498abdfde1374b9d059b10fc29bb1192469473bdccfe" 64 | ] 65 | }, 66 | { 67 | "priv": "0xd83a52c3d1965d9ace37fde20da4eb4c98184c6cfc8b33b1b0c56be36f3fc5c0", 68 | "pub": [ 69 | "0x4edcb03232d7161fa6013b26a97e704ab9e12a54d6fca2e4d80628059a924a36", 70 | "0x2c83e95f678ee0154be3445ea616bd809dd5f1d72c7423911d3eeef589464089" 71 | ] 72 | }, 73 | { 74 | "priv": "0x013263a84e05ca597f3c6cdeae5b33349c618308ac5ef844de0aa5b788d0a3a8", 75 | "pub": [ 76 | "0x536c48ed353b0b7b47ac251a72cb7b1eb6b8a0bfdacd9ac49bb4fc7f8d125665", 77 | "0xd376f83b3552a612d9c70710770c9555148518a81411225c4026fe5dbfd8f4b0" 78 | ] 79 | }, 80 | { 81 | "priv": "0x6ac0b7ddefa89ca0f129cba3ddda3b4a6e126d43363b4509bd6c9334dd81e0fa", 82 | "pub": [ 83 | "0xe35c32aabfd48fea25e983600287e7f83329f1a509a33f0d37bd270021269ee8", 84 | "0xb607172f651ccc6d30f52f78bbbb1b91e5c3bceecc22b4ae37e6b2963d30a910" 85 | ] 86 | }, 87 | { 88 | "priv": "0xba87e08dc57311d5518c7d46958f3e647baed528313952cc5cf34e14f3b523af", 89 | "pub": [ 90 | "0xe556d0725e393d4e567e0899fb90d8b4635ff1b96281ed0ea0008fd647a1f91e", 91 | "0xc79b21597019b9e049e641990fd58bc896cf845c62a21ce56a96ebd237c8f0ba" 92 | ] 93 | }, 94 | { 95 | "priv": "0xd8c21bd40cdd0603666fa5c6199d8058050872913fa0c68feb53fed3df35695e", 96 | "pub": [ 97 | "0xd83e9f0542c180358db9ea20acb2445dc13b24524b246250d40af7df594a33b1", 98 | "0x107313d96120cf344569d3ec08f1a0b11027d3ccfa1cefa47d84c8c24123bb38" 99 | ] 100 | }, 101 | { 102 | "priv": "0x839793d1f796da91096cd1641d06593b6f6c3dadc12e0ccd7eaaf1f10c752c25", 103 | "pub": [ 104 | "0x608b0858f50f1c0c59255be9a424e2fb20c57f73c5f019e8f82367fcdf04fabc", 105 | "0xe196009f0a0bcb1a1a0966d2d8206ef3b5020835e20ae0749c54ac99a519c98e" 106 | ] 107 | }, 108 | { 109 | "priv": "0x5c745e065ad28124ca941b02abd0ebdb4502d0c70058ddd7dfa9b659165e76a4", 110 | "pub": [ 111 | "0x911fc6b8846b46e9b2212224574c099fa3ad5353a6fe2cd7df4a50ea174c0061", 112 | "0xb4616567616e4bfd93cba5cb89595a5bde365f7f3e1488720deb3d6e1155696e" 113 | ] 114 | }, 115 | { 116 | "priv": "0x03eebcbd7958778591670c9d47c09fccd94a6dd05f13ee6b6f5f4d5a640f293c", 117 | "pub": [ 118 | "0x845284bac043225cf9f5dfe684e1d36eb5dc3f1ffe98886051b89318ee6ad88b", 119 | "0xfb597282621a1e9f76fff05ac65ddc33ba96cae768a94ce3fdb01919012e3c78" 120 | ] 121 | }, 122 | { 123 | "priv": "0xa46f162d79d24ceaf81ef56d118d904067d1e78d9a17ef91f3542183dfb44665", 124 | "pub": [ 125 | "0x4d57f7101ecd882af501ca45bfaf25c801bf2944e896181de3f19f49f550ff1f", 126 | "0xa0a3a7dcc8e1d773af4ab8876cc7b4b4e11219efc302baaf9d5c02d7960247f8" 127 | ] 128 | } 129 | ] 130 | } -------------------------------------------------------------------------------- /benchmark/secp256k1.js: -------------------------------------------------------------------------------- 1 | const Secp256k1GasHelper = artifacts.require("./Secp256k1GasHelper") 2 | const testdata = require("./secp256k1-data.json") 3 | 4 | contract("Secp256k1 - Gas consumption analysis", accounts => { 5 | describe("Public Key Derivation", () => { 6 | let helper 7 | before(async () => { 8 | helper = await Secp256k1GasHelper.new() 9 | }) 10 | it("Should derive a public key", async () => { 11 | for (const pair of testdata.keypairs) { 12 | const priv = web3.utils.toBN(pair.priv) 13 | await helper.derivePubKey(priv) 14 | } 15 | }) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /contracts/EllipticCurve.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | /** 6 | ** @title Elliptic Curve Library 7 | ** @dev Library providing arithmetic operations over elliptic curves. 8 | ** This library does not check whether the inserted points belong to the curve 9 | ** `isOnCurve` function should be used by the library user to check the aforementioned statement. 10 | ** @author Witnet Foundation 11 | */ 12 | library EllipticCurve { 13 | // Pre-computed constant for 2 ** 255 14 | uint256 private constant U255_MAX_PLUS_1 = 15 | 57896044618658097711785492504343953926634992332820282019728792003956564819968; 16 | 17 | /// @dev Modular euclidean inverse of a number (mod p). 18 | /// @param _x The number 19 | /// @param _pp The modulus 20 | /// @return q such that x*q = 1 (mod _pp) 21 | function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) { 22 | require(_x != 0 && _x != _pp && _pp != 0, "Invalid number"); 23 | uint256 q = 0; 24 | uint256 newT = 1; 25 | uint256 r = _pp; 26 | uint256 t; 27 | while (_x != 0) { 28 | t = r / _x; 29 | (q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp)); 30 | (r, _x) = (_x, r - t * _x); 31 | } 32 | 33 | return q; 34 | } 35 | 36 | /// @dev Modular exponentiation, b^e % _pp. 37 | /// Source: https://github.com/androlo/standard-contracts/blob/master/contracts/src/crypto/ECCMath.sol 38 | /// @param _base base 39 | /// @param _exp exponent 40 | /// @param _pp modulus 41 | /// @return r such that r = b**e (mod _pp) 42 | function expMod( 43 | uint256 _base, 44 | uint256 _exp, 45 | uint256 _pp 46 | ) 47 | internal pure 48 | returns (uint256) 49 | { 50 | require(_pp != 0, "EllipticCurve: modulus is zero"); 51 | 52 | if (_base == 0) return 0; 53 | if (_exp == 0) return 1; 54 | 55 | uint256 r = 1; 56 | uint256 bit = U255_MAX_PLUS_1; 57 | assembly { 58 | for { 59 | 60 | } gt(bit, 0) { 61 | 62 | } { 63 | r := mulmod( 64 | mulmod(r, r, _pp), 65 | exp(_base, iszero(iszero(and(_exp, bit)))), 66 | _pp 67 | ) 68 | r := mulmod( 69 | mulmod(r, r, _pp), 70 | exp(_base, iszero(iszero(and(_exp, div(bit, 2))))), 71 | _pp 72 | ) 73 | r := mulmod( 74 | mulmod(r, r, _pp), 75 | exp(_base, iszero(iszero(and(_exp, div(bit, 4))))), 76 | _pp 77 | ) 78 | r := mulmod( 79 | mulmod(r, r, _pp), 80 | exp(_base, iszero(iszero(and(_exp, div(bit, 8))))), 81 | _pp 82 | ) 83 | bit := div(bit, 16) 84 | } 85 | } 86 | 87 | return r; 88 | } 89 | 90 | /// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1). 91 | /// @param _x coordinate x 92 | /// @param _y coordinate y 93 | /// @param _z coordinate z 94 | /// @param _pp the modulus 95 | /// @return (x', y') affine coordinates 96 | function toAffine( 97 | uint256 _x, 98 | uint256 _y, 99 | uint256 _z, 100 | uint256 _pp 101 | ) 102 | internal pure 103 | returns (uint256, uint256) 104 | { 105 | uint256 zInv = invMod(_z, _pp); 106 | uint256 zInv2 = mulmod(zInv, zInv, _pp); 107 | uint256 x2 = mulmod(_x, zInv2, _pp); 108 | uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, _pp), _pp); 109 | 110 | return (x2, y2); 111 | } 112 | 113 | /// @dev Derives the y coordinate from a compressed-format point x [[SEC-1]](https://www.secg.org/SEC1-Ver-1.0.pdf). 114 | /// @param _prefix parity byte (0x02 even, 0x03 odd) 115 | /// @param _x coordinate x 116 | /// @param _aa constant of curve 117 | /// @param _bb constant of curve 118 | /// @param _pp the modulus 119 | /// @return y coordinate y 120 | function deriveY( 121 | uint8 _prefix, 122 | uint256 _x, 123 | uint256 _aa, 124 | uint256 _bb, 125 | uint256 _pp 126 | ) 127 | internal pure 128 | returns (uint256) 129 | { 130 | require( 131 | _prefix == 0x02 || _prefix == 0x03, 132 | "EllipticCurve:innvalid compressed EC point prefix" 133 | ); 134 | 135 | // x^3 + ax + b 136 | uint256 y2 = addmod( 137 | mulmod(_x, mulmod(_x, _x, _pp), _pp), 138 | addmod(mulmod(_x, _aa, _pp), _bb, _pp), 139 | _pp 140 | ); 141 | y2 = expMod(y2, (_pp + 1) / 4, _pp); 142 | // uint256 cmp = yBit ^ y_ & 1; 143 | uint256 y = (y2 + _prefix) % 2 == 0 ? y2 : _pp - y2; 144 | 145 | return y; 146 | } 147 | 148 | /// @dev Check whether point (x,y) is on curve defined by a, b, and _pp. 149 | /// @param _x coordinate x of P1 150 | /// @param _y coordinate y of P1 151 | /// @param _aa constant of curve 152 | /// @param _bb constant of curve 153 | /// @param _pp the modulus 154 | /// @return true if x,y in the curve, false else 155 | function isOnCurve( 156 | uint _x, 157 | uint _y, 158 | uint _aa, 159 | uint _bb, 160 | uint _pp 161 | ) 162 | internal pure 163 | returns (bool) 164 | { 165 | if (0 == _x || _x >= _pp || 0 == _y || _y >= _pp) { 166 | return false; 167 | } 168 | // y^2 169 | uint lhs = mulmod(_y, _y, _pp); 170 | // x^3 171 | uint rhs = mulmod(mulmod(_x, _x, _pp), _x, _pp); 172 | if (_aa != 0) { 173 | // x^3 + a*x 174 | rhs = addmod(rhs, mulmod(_x, _aa, _pp), _pp); 175 | } 176 | if (_bb != 0) { 177 | // x^3 + a*x + b 178 | rhs = addmod(rhs, _bb, _pp); 179 | } 180 | 181 | return lhs == rhs; 182 | } 183 | 184 | /// @dev Calculate inverse (x, -y) of point (x, y). 185 | /// @param _x coordinate x of P1 186 | /// @param _y coordinate y of P1 187 | /// @param _pp the modulus 188 | /// @return (x, -y) 189 | function ecInv( 190 | uint256 _x, 191 | uint256 _y, 192 | uint256 _pp 193 | ) 194 | internal pure 195 | returns (uint256, uint256) 196 | { 197 | return (_x, (_pp - _y) % _pp); 198 | } 199 | 200 | /// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates. 201 | /// @param _x1 coordinate x of P1 202 | /// @param _y1 coordinate y of P1 203 | /// @param _x2 coordinate x of P2 204 | /// @param _y2 coordinate y of P2 205 | /// @param _aa constant of the curve 206 | /// @param _pp the modulus 207 | /// @return (qx, qy) = P1+P2 in affine coordinates 208 | function ecAdd( 209 | uint256 _x1, 210 | uint256 _y1, 211 | uint256 _x2, 212 | uint256 _y2, 213 | uint256 _aa, 214 | uint256 _pp 215 | ) 216 | internal pure 217 | returns (uint256, uint256) 218 | { 219 | uint x = 0; 220 | uint y = 0; 221 | uint z = 0; 222 | 223 | // Double if x1==x2 else add 224 | if (_x1 == _x2) { 225 | // y1 = -y2 mod p 226 | if (addmod(_y1, _y2, _pp) == 0) { 227 | return (0, 0); 228 | } else { 229 | // P1 = P2 230 | (x, y, z) = jacDouble(_x1, _y1, 1, _aa, _pp); 231 | } 232 | } else { 233 | (x, y, z) = jacAdd(_x1, _y1, 1, _x2, _y2, 1, _pp); 234 | } 235 | // Get back to affine 236 | return toAffine(x, y, z, _pp); 237 | } 238 | 239 | /// @dev Substract two points (x1, y1) and (x2, y2) in affine coordinates. 240 | /// @param _x1 coordinate x of P1 241 | /// @param _y1 coordinate y of P1 242 | /// @param _x2 coordinate x of P2 243 | /// @param _y2 coordinate y of P2 244 | /// @param _aa constant of the curve 245 | /// @param _pp the modulus 246 | /// @return (qx, qy) = P1-P2 in affine coordinates 247 | function ecSub( 248 | uint256 _x1, 249 | uint256 _y1, 250 | uint256 _x2, 251 | uint256 _y2, 252 | uint256 _aa, 253 | uint256 _pp 254 | ) 255 | internal pure 256 | returns (uint256, uint256) 257 | { 258 | // invert square 259 | (uint256 x, uint256 y) = ecInv(_x2, _y2, _pp); 260 | // P1-square 261 | return ecAdd(_x1, _y1, x, y, _aa, _pp); 262 | } 263 | 264 | /// @dev Multiply point (x1, y1, z1) times d in affine coordinates. 265 | /// @param _k scalar to multiply 266 | /// @param _x coordinate x of P1 267 | /// @param _y coordinate y of P1 268 | /// @param _aa constant of the curve 269 | /// @param _pp the modulus 270 | /// @return (qx, qy) = d*P in affine coordinates 271 | function ecMul( 272 | uint256 _k, 273 | uint256 _x, 274 | uint256 _y, 275 | uint256 _aa, 276 | uint256 _pp 277 | ) 278 | internal pure 279 | returns (uint256, uint256) 280 | { 281 | // Jacobian multiplication 282 | (uint256 x1, uint256 y1, uint256 z1) = jacMul(_k, _x, _y, 1, _aa, _pp); 283 | // Get back to affine 284 | return toAffine(x1, y1, z1, _pp); 285 | } 286 | 287 | /// @dev Adds two points (x1, y1, z1) and (x2 y2, z2). 288 | /// @param _x1 coordinate x of P1 289 | /// @param _y1 coordinate y of P1 290 | /// @param _z1 coordinate z of P1 291 | /// @param _x2 coordinate x of square 292 | /// @param _y2 coordinate y of square 293 | /// @param _z2 coordinate z of square 294 | /// @param _pp the modulus 295 | /// @return (qx, qy, qz) P1+square in Jacobian 296 | function jacAdd( 297 | uint256 _x1, 298 | uint256 _y1, 299 | uint256 _z1, 300 | uint256 _x2, 301 | uint256 _y2, 302 | uint256 _z2, 303 | uint256 _pp 304 | ) 305 | internal pure 306 | returns (uint256, uint256, uint256) 307 | { 308 | if (_x1 == 0 && _y1 == 0) return (_x2, _y2, _z2); 309 | if (_x2 == 0 && _y2 == 0) return (_x1, _y1, _z1); 310 | 311 | // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5 312 | uint[4] memory zs; // z1^2, z1^3, z2^2, z2^3 313 | zs[0] = mulmod(_z1, _z1, _pp); 314 | zs[1] = mulmod(_z1, zs[0], _pp); 315 | zs[2] = mulmod(_z2, _z2, _pp); 316 | zs[3] = mulmod(_z2, zs[2], _pp); 317 | 318 | // u1, s1, u2, s2 319 | zs = [ 320 | mulmod(_x1, zs[2], _pp), 321 | mulmod(_y1, zs[3], _pp), 322 | mulmod(_x2, zs[0], _pp), 323 | mulmod(_y2, zs[1], _pp) 324 | ]; 325 | 326 | // In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used 327 | require( 328 | zs[0] != zs[2] || zs[1] != zs[3], 329 | "Use jacDouble function instead" 330 | ); 331 | 332 | uint[4] memory hr; 333 | //h 334 | hr[0] = addmod(zs[2], _pp - zs[0], _pp); 335 | //r 336 | hr[1] = addmod(zs[3], _pp - zs[1], _pp); 337 | //h^2 338 | hr[2] = mulmod(hr[0], hr[0], _pp); 339 | // h^3 340 | hr[3] = mulmod(hr[2], hr[0], _pp); 341 | // qx = -h^3 -2u1h^2+r^2 342 | uint256 qx = addmod(mulmod(hr[1], hr[1], _pp), _pp - hr[3], _pp); 343 | qx = addmod(qx, _pp - mulmod(2, mulmod(zs[0], hr[2], _pp), _pp), _pp); 344 | // qy = -s1*z1*h^3+r(u1*h^2 -x^3) 345 | uint256 qy = mulmod( 346 | hr[1], 347 | addmod(mulmod(zs[0], hr[2], _pp), _pp - qx, _pp), 348 | _pp 349 | ); 350 | qy = addmod(qy, _pp - mulmod(zs[1], hr[3], _pp), _pp); 351 | // qz = h*z1*z2 352 | uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, _pp), _pp); 353 | return (qx, qy, qz); 354 | } 355 | 356 | /// @dev Doubles a points (x, y, z). 357 | /// @param _x coordinate x of P1 358 | /// @param _y coordinate y of P1 359 | /// @param _z coordinate z of P1 360 | /// @param _aa the a scalar in the curve equation 361 | /// @param _pp the modulus 362 | /// @return (qx, qy, qz) 2P in Jacobian 363 | function jacDouble( 364 | uint256 _x, 365 | uint256 _y, 366 | uint256 _z, 367 | uint256 _aa, 368 | uint256 _pp 369 | ) 370 | internal pure 371 | returns (uint256, uint256, uint256) 372 | { 373 | if (_z == 0) return (_x, _y, _z); 374 | 375 | // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5 376 | // Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4) 377 | // x, y, z at this point represent the squares of _x, _y, _z 378 | uint256 x = mulmod(_x, _x, _pp); //x1^2 379 | uint256 y = mulmod(_y, _y, _pp); //y1^2 380 | uint256 z = mulmod(_z, _z, _pp); //z1^2 381 | 382 | // s 383 | uint s = mulmod(4, mulmod(_x, y, _pp), _pp); 384 | // m 385 | uint m = addmod( 386 | mulmod(3, x, _pp), 387 | mulmod(_aa, mulmod(z, z, _pp), _pp), 388 | _pp 389 | ); 390 | 391 | // x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper 392 | // This allows to reduce the gas cost and stack footprint of the algorithm 393 | // qx 394 | x = addmod(mulmod(m, m, _pp), _pp - addmod(s, s, _pp), _pp); 395 | // qy = -8*y1^4 + M(S-T) 396 | y = addmod( 397 | mulmod(m, addmod(s, _pp - x, _pp), _pp), 398 | _pp - mulmod(8, mulmod(y, y, _pp), _pp), 399 | _pp 400 | ); 401 | // qz = 2*y1*z1 402 | z = mulmod(2, mulmod(_y, _z, _pp), _pp); 403 | 404 | return (x, y, z); 405 | } 406 | 407 | /// @dev Multiply point (x, y, z) times d. 408 | /// @param _d scalar to multiply 409 | /// @param _x coordinate x of P1 410 | /// @param _y coordinate y of P1 411 | /// @param _z coordinate z of P1 412 | /// @param _aa constant of curve 413 | /// @param _pp the modulus 414 | /// @return (qx, qy, qz) d*P1 in Jacobian 415 | function jacMul( 416 | uint256 _d, 417 | uint256 _x, 418 | uint256 _y, 419 | uint256 _z, 420 | uint256 _aa, 421 | uint256 _pp 422 | ) 423 | internal pure 424 | returns (uint256, uint256, uint256) 425 | { 426 | // Early return in case that `_d == 0` 427 | if (_d == 0) { 428 | return (_x, _y, _z); 429 | } 430 | 431 | uint256 remaining = _d; 432 | uint256 qx = 0; 433 | uint256 qy = 0; 434 | uint256 qz = 1; 435 | 436 | // Double and add algorithm 437 | while (remaining != 0) { 438 | if ((remaining & 1) != 0) { 439 | (qx, qy, qz) = jacAdd(qx, qy, qz, _x, _y, _z, _pp); 440 | } 441 | remaining = remaining / 2; 442 | (_x, _y, _z) = jacDouble(_x, _y, _z, _aa, _pp); 443 | } 444 | return (qx, qy, qz); 445 | } 446 | } 447 | -------------------------------------------------------------------------------- /contracts/FastEcMul.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "./EllipticCurve.sol"; 6 | 7 | /** 8 | ** @title Fast Elliptic Curve Multiplication Library 9 | ** @dev Library providing the following speed ups to an elliptic curve multiplication operation. 10 | ** - wNAF scalar representation 11 | ** - scalar decomposition through endomorphism 12 | ** This library does not check whether the inserted points belong to the curve 13 | ** `isOnCurve` function should be used by the library user to check the aforementioned statement. 14 | ** @author Witnet Foundation 15 | **/ 16 | library FastEcMul { 17 | // Pre-computed constant for 2 ** 128 - 1 18 | uint256 private constant U128_MAX = 340282366920938463463374607431768211455; 19 | 20 | /// @dev Decomposition of the scalar k in two scalars k1 and k2 with half bit-length, such that k=k1+k2*LAMBDA (mod n) 21 | /// @param _k the scalar to be decompose 22 | /// @param _nn the modulus 23 | /// @param _lambda is a root of the characteristic polynomial of an endomorphism of the curve 24 | /// @return k1 and k2 such that k=k1+k2*LAMBDA (mod n) 25 | function decomposeScalar( 26 | uint256 _k, 27 | uint256 _nn, 28 | uint256 _lambda 29 | ) 30 | internal pure 31 | returns (int256, int256) 32 | { 33 | uint256 k = _k % _nn; 34 | // Extended Euclidean Algorithm for n and LAMBDA 35 | int256[2] memory t; 36 | t[0] = 1; 37 | t[1] = 0; 38 | uint256[2] memory r; 39 | r[0] = uint256(_lambda); 40 | r[1] = uint256(_nn); 41 | 42 | // Loop while `r[0] >= sqrt(_nn)` 43 | // Or in other words, `r[0] * r[0] >= _nn` 44 | // When `r[0] >= 2**128`, `r[0] * r[0]` will overflow so we must check that before 45 | while ((r[0] >= 2 ** 128) || (r[0] * r[0] >= _nn)) { 46 | uint256 quotient = r[1] / r[0]; 47 | (r[1], r[0]) = (r[0], r[1] - quotient * r[0]); 48 | (t[1], t[0]) = (t[0], t[1] - int256(quotient) * t[0]); 49 | } 50 | int256[4] memory ab; 51 | 52 | // the vectors v1=(a1, b1) and v2=(a2,b2) 53 | ab[0] = int256(r[0]); 54 | ab[1] = int256(-t[0]); 55 | ab[2] = int256(r[1]); 56 | ab[3] = int256(-t[1]); 57 | 58 | //b2*K 59 | uint[3] memory test; 60 | (test[0], test[1], test[2]) = _multiply256(uint(ab[3]), uint(k)); 61 | 62 | //-b1*k 63 | uint[3] memory test2; 64 | (test2[0], test2[1], test2[2]) = _multiply256(uint(-ab[1]), uint(k)); 65 | 66 | //c1 and c2 67 | uint[2] memory c1; 68 | (c1[0], c1[1]) = _bigDivision( 69 | (uint256(uint128(test[0])) << 128) | uint128(test[1]), 70 | uint256(test[2]) + (_nn / 2), 71 | _nn 72 | ); 73 | uint[2] memory c2; 74 | (c2[0], c2[1]) = _bigDivision( 75 | (uint256(uint128(test2[0])) << 128) | uint128(test2[1]), 76 | uint256(test2[2]) + (_nn / 2), 77 | _nn 78 | ); 79 | 80 | // the decomposition of k in k1 and k2 81 | int256 k1 = int256( 82 | (int256(k) - 83 | int256(c1[0]) * 84 | int256(ab[0]) - 85 | int256(c2[0]) * 86 | int256(ab[2])) % int256(_nn) 87 | ); 88 | int256 k2 = int256( 89 | (-int256(c1[0]) * int256(ab[1]) - int256(c2[0]) * int256(ab[3])) % 90 | int256(_nn) 91 | ); 92 | if (uint256(_abs(k1)) > (_nn / 2)) { 93 | k1 = int256(uint256(k1) - _nn); 94 | } 95 | if (uint256(_abs(k2)) > (_nn / 2)) { 96 | k2 = int256(uint256(k2) - _nn); 97 | } 98 | 99 | return (k1, k2); 100 | } 101 | 102 | /// @notice Simultaneous multiplication of the form kP + lQ. 103 | /// @dev Scalars k and l are expected to be decomposed such that k = k1 + k2 λ, and l = l1 + l2 λ, 104 | /// where λ is specific to the endomorphism of the curve. 105 | /// @param _scalars An array with the decomposition of k and l values, i.e., [k1, k2, l1, l2] 106 | /// @param _points An array with the affine coordinates of both P and Q, i.e., [P1, P2, Q1, Q2] 107 | function ecSimMul( 108 | int256[4] memory _scalars, 109 | uint256[4] memory _points, 110 | uint256 _aa, 111 | uint256 _beta, 112 | uint256 _pp 113 | ) 114 | internal pure 115 | returns (uint256, uint256) 116 | { 117 | uint256[4] memory wnaf; 118 | uint256 maxCount = 0; 119 | uint256 count = 0; 120 | 121 | for (uint j = 0; j < 4; j++) { 122 | (wnaf[j], count) = _wnaf(_scalars[j]); 123 | if (count > maxCount) { 124 | maxCount = count; 125 | } 126 | } 127 | 128 | (uint256 x, uint256 y, uint256 z) = _simMulWnaf( 129 | wnaf, 130 | maxCount, 131 | _points, 132 | _aa, 133 | _beta, 134 | _pp 135 | ); 136 | 137 | return EllipticCurve.toAffine(x, y, z, _pp); 138 | } 139 | 140 | /// @dev Compute the look up table for the simultaneous multiplication (P, 3P,..,Q,3Q,..). 141 | /// @param _iP the look up table were values will be stored 142 | /// @param _points the points P and Q to be multiplied 143 | /// @param _aa constant of the curve 144 | /// @param _beta constant of the curve (endomorphism) 145 | /// @param _pp the modulus 146 | function _lookupSimMul( 147 | uint256[3][4][4] memory _iP, 148 | uint256[4] memory _points, 149 | uint256 _aa, 150 | uint256 _beta, 151 | uint256 _pp 152 | ) 153 | private pure 154 | { 155 | uint256[3][4] memory iPj; 156 | uint256[3] memory double; 157 | 158 | // P1 Lookup Table 159 | iPj = _iP[0]; 160 | iPj[0] = [_points[0], _points[1], 1]; // P1 161 | 162 | (double[0], double[1], double[2]) = EllipticCurve.jacDouble( 163 | iPj[0][0], 164 | iPj[0][1], 165 | 1, 166 | _aa, 167 | _pp 168 | ); 169 | (iPj[1][0], iPj[1][1], iPj[1][2]) = EllipticCurve.jacAdd( 170 | double[0], 171 | double[1], 172 | double[2], 173 | iPj[0][0], 174 | iPj[0][1], 175 | iPj[0][2], 176 | _pp 177 | ); 178 | (iPj[2][0], iPj[2][1], iPj[2][2]) = EllipticCurve.jacAdd( 179 | double[0], 180 | double[1], 181 | double[2], 182 | iPj[1][0], 183 | iPj[1][1], 184 | iPj[1][2], 185 | _pp 186 | ); 187 | (iPj[3][0], iPj[3][1], iPj[3][2]) = EllipticCurve.jacAdd( 188 | double[0], 189 | double[1], 190 | double[2], 191 | iPj[2][0], 192 | iPj[2][1], 193 | iPj[2][2], 194 | _pp 195 | ); 196 | 197 | // P2 Lookup Table 198 | _iP[1][0] = [mulmod(_beta, _points[0], _pp), _points[1], 1]; // P2 199 | 200 | _iP[1][1] = [mulmod(_beta, iPj[1][0], _pp), iPj[1][1], iPj[1][2]]; 201 | _iP[1][2] = [mulmod(_beta, iPj[2][0], _pp), iPj[2][1], iPj[2][2]]; 202 | _iP[1][3] = [mulmod(_beta, iPj[3][0], _pp), iPj[3][1], iPj[3][2]]; 203 | 204 | // Q1 Lookup Table 205 | iPj = _iP[2]; 206 | iPj[0] = [_points[2], _points[3], 1]; // Q1 207 | (double[0], double[1], double[2]) = EllipticCurve.jacDouble( 208 | iPj[0][0], 209 | iPj[0][1], 210 | 1, 211 | _aa, 212 | _pp 213 | ); 214 | (iPj[1][0], iPj[1][1], iPj[1][2]) = EllipticCurve.jacAdd( 215 | double[0], 216 | double[1], 217 | double[2], 218 | iPj[0][0], 219 | iPj[0][1], 220 | iPj[0][2], 221 | _pp 222 | ); 223 | (iPj[2][0], iPj[2][1], iPj[2][2]) = EllipticCurve.jacAdd( 224 | double[0], 225 | double[1], 226 | double[2], 227 | iPj[1][0], 228 | iPj[1][1], 229 | iPj[1][2], 230 | _pp 231 | ); 232 | (iPj[3][0], iPj[3][1], iPj[3][2]) = EllipticCurve.jacAdd( 233 | double[0], 234 | double[1], 235 | double[2], 236 | iPj[2][0], 237 | iPj[2][1], 238 | iPj[2][2], 239 | _pp 240 | ); 241 | 242 | // Q2 Lookup Table 243 | _iP[3][0] = [mulmod(_beta, _points[2], _pp), _points[3], 1]; // P2 244 | 245 | _iP[3][1] = [mulmod(_beta, iPj[1][0], _pp), iPj[1][1], iPj[1][2]]; 246 | _iP[3][2] = [mulmod(_beta, iPj[2][0], _pp), iPj[2][1], iPj[2][2]]; 247 | _iP[3][3] = [mulmod(_beta, iPj[3][0], _pp), iPj[3][1], iPj[3][2]]; 248 | } 249 | 250 | /// @dev WNAF integer representation. Computes the WNAF representation of an integer, and puts the resulting array of coefficients in memory. 251 | /// @param _k A 256-bit integer 252 | /// @return (ptr, length) The pointer to the first coefficient, and the total length of the array 253 | function _wnaf(int256 _k) private pure returns (uint256, uint256) { 254 | int sign = _k < 0 ? -1 : int(1); 255 | uint256 k = uint256(sign * _k); 256 | 257 | uint256 ptr; 258 | uint256 length = 0; 259 | assembly { 260 | let ki := 0 261 | ptr := mload(0x40) // Get free memory pointer 262 | mstore(0x40, add(ptr, 300)) // Updates free memory pointer to +300 bytes offset 263 | for { 264 | 265 | } gt(k, 0) { 266 | 267 | } { 268 | // while k > 0 269 | if and(k, 1) { 270 | // if k is odd: 271 | ki := mod(k, 16) 272 | k := add(sub(k, ki), mul(gt(ki, 8), 16)) 273 | // if sign = 1, store ki; if sign = -1, store 16 - ki 274 | mstore8( 275 | add(ptr, length), 276 | add(mul(ki, sign), sub(8, mul(sign, 8))) 277 | ) 278 | } 279 | length := add(length, 1) 280 | k := div(k, 2) 281 | } 282 | } 283 | 284 | return (ptr, length); 285 | } 286 | 287 | /// @dev Compute the simultaneous multiplication with wnaf decomposed scalar. 288 | /// @param _wnafPointer the decomposed scalars to be multiplied in wnaf form (k1, k2, l1, l2) 289 | /// @param _length the length of the WNAF representation array 290 | /// @param _points the points P and Q to be multiplied 291 | /// @param _aa constant of the curve 292 | /// @param _beta constant of the curve (endomorphism) 293 | /// @param _pp the modulus 294 | /// @return (qx, qy, qz) d*P1 in Jacobian 295 | function _simMulWnaf( 296 | uint256[4] memory _wnafPointer, 297 | uint256 _length, 298 | uint256[4] memory _points, 299 | uint256 _aa, 300 | uint256 _beta, 301 | uint256 _pp 302 | ) 303 | private pure 304 | returns (uint256, uint256, uint256) 305 | { 306 | uint[3] memory mulPoint; 307 | uint256[3][4][4] memory iP; 308 | _lookupSimMul(iP, _points, _aa, _beta, _pp); 309 | 310 | uint256 ki; 311 | uint256 ptr; 312 | while (_length > 0) { 313 | _length--; 314 | 315 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacDouble( 316 | mulPoint[0], 317 | mulPoint[1], 318 | mulPoint[2], 319 | _aa, 320 | _pp 321 | ); 322 | 323 | ptr = _wnafPointer[0] + _length; 324 | assembly { 325 | ki := byte(0, mload(ptr)) 326 | } 327 | 328 | if (ki > 8) { 329 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 330 | mulPoint[0], 331 | mulPoint[1], 332 | mulPoint[2], 333 | iP[0][(15 - ki) / 2][0], 334 | (_pp - iP[0][(15 - ki) / 2][1]) % _pp, 335 | iP[0][(15 - ki) / 2][2], 336 | _pp 337 | ); 338 | } else if (ki > 0) { 339 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 340 | mulPoint[0], 341 | mulPoint[1], 342 | mulPoint[2], 343 | iP[0][(ki - 1) / 2][0], 344 | iP[0][(ki - 1) / 2][1], 345 | iP[0][(ki - 1) / 2][2], 346 | _pp 347 | ); 348 | } 349 | 350 | ptr = _wnafPointer[1] + _length; 351 | assembly { 352 | ki := byte(0, mload(ptr)) 353 | } 354 | 355 | if (ki > 8) { 356 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 357 | mulPoint[0], 358 | mulPoint[1], 359 | mulPoint[2], 360 | iP[1][(15 - ki) / 2][0], 361 | (_pp - iP[1][(15 - ki) / 2][1]) % _pp, 362 | iP[1][(15 - ki) / 2][2], 363 | _pp 364 | ); 365 | } else if (ki > 0) { 366 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 367 | mulPoint[0], 368 | mulPoint[1], 369 | mulPoint[2], 370 | iP[1][(ki - 1) / 2][0], 371 | iP[1][(ki - 1) / 2][1], 372 | iP[1][(ki - 1) / 2][2], 373 | _pp 374 | ); 375 | } 376 | 377 | ptr = _wnafPointer[2] + _length; 378 | assembly { 379 | ki := byte(0, mload(ptr)) 380 | } 381 | 382 | if (ki > 8) { 383 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 384 | mulPoint[0], 385 | mulPoint[1], 386 | mulPoint[2], 387 | iP[2][(15 - ki) / 2][0], 388 | (_pp - iP[2][(15 - ki) / 2][1]) % _pp, 389 | iP[2][(15 - ki) / 2][2], 390 | _pp 391 | ); 392 | } else if (ki > 0) { 393 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 394 | mulPoint[0], 395 | mulPoint[1], 396 | mulPoint[2], 397 | iP[2][(ki - 1) / 2][0], 398 | iP[2][(ki - 1) / 2][1], 399 | iP[2][(ki - 1) / 2][2], 400 | _pp 401 | ); 402 | } 403 | 404 | ptr = _wnafPointer[3] + _length; 405 | assembly { 406 | ki := byte(0, mload(ptr)) 407 | } 408 | 409 | if (ki > 8) { 410 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 411 | mulPoint[0], 412 | mulPoint[1], 413 | mulPoint[2], 414 | iP[3][(15 - ki) / 2][0], 415 | (_pp - iP[3][(15 - ki) / 2][1]) % _pp, 416 | iP[3][(15 - ki) / 2][2], 417 | _pp 418 | ); 419 | } else if (ki > 0) { 420 | (mulPoint[0], mulPoint[1], mulPoint[2]) = EllipticCurve.jacAdd( 421 | mulPoint[0], 422 | mulPoint[1], 423 | mulPoint[2], 424 | iP[3][(ki - 1) / 2][0], 425 | iP[3][(ki - 1) / 2][1], 426 | iP[3][(ki - 1) / 2][2], 427 | _pp 428 | ); 429 | } 430 | } 431 | 432 | return (mulPoint[0], mulPoint[1], mulPoint[2]); 433 | } 434 | 435 | /// @dev Multiplication of a uint256 a and uint256 b. Because in Solidity each variable can not be greater than 256 bits, 436 | /// this function separates the result of the multiplication in three parts, so the result would be the concatenation of those three. 437 | /// @param _a uint256 438 | /// @param _b uint256 439 | /// @return (ab2, ab1, ab0) 440 | function _multiply256( 441 | uint256 _a, 442 | uint256 _b 443 | ) 444 | private pure 445 | returns (uint256, uint256, uint256) 446 | { 447 | uint256 aM = _a >> 128; 448 | uint256 am = _a & U128_MAX; 449 | uint256 bM = _b >> 128; 450 | uint256 bm = _b & U128_MAX; 451 | uint256 ab0 = am * bm; 452 | uint256 ab1 = (ab0 >> 128) + 453 | ((aM * bm) & U128_MAX) + 454 | ((am * bM) & U128_MAX); 455 | uint256 ab2 = (ab1 >> 128) + 456 | aM * 457 | bM + 458 | ((aM * bm) >> 128) + 459 | ((am * bM) >> 128); 460 | ab1 &= U128_MAX; 461 | ab0 &= U128_MAX; 462 | 463 | return (ab2, ab1, ab0); 464 | } 465 | 466 | /// @dev Division of an integer of 312 bits by a 256-bit integer. 467 | /// @param _aM the higher 256 bits of the numarator 468 | /// @param _am the lower 128 bits of the numarator 469 | /// @param _b the 256-bit denominator 470 | /// @return q the result of the division and the rest r 471 | function _bigDivision( 472 | uint256 _aM, 473 | uint256 _am, 474 | uint256 _b 475 | ) 476 | private pure 477 | returns (uint256, uint256) 478 | { 479 | uint256 aM = _aM % _b; 480 | 481 | uint256 shift = 0; 482 | while (_b >> shift > 0) { 483 | shift++; 484 | } 485 | shift = 256 - shift; 486 | aM = 487 | (_aM << shift) + 488 | (shift > 128 ? _am << (shift - 128) : _am >> (128 - shift)); 489 | uint256 a0 = (_am << shift) & U128_MAX; 490 | 491 | (uint256 b1, uint256 b0) = ( 492 | (_b << shift) >> 128, 493 | (_b << shift) & U128_MAX 494 | ); 495 | 496 | uint256 rM; 497 | uint256 q = aM / b1; 498 | rM = aM % b1; 499 | 500 | uint256 rsub0 = (q & U128_MAX) * b0; 501 | uint256 rsub21 = (q >> 128) * b0 + (rsub0 >> 128); 502 | rsub0 &= U128_MAX; 503 | 504 | while (rsub21 > rM || (rsub21 == rM && rsub0 > a0)) { 505 | q--; 506 | a0 += b0; 507 | rM += b1 + (a0 >> 128); 508 | a0 &= U128_MAX; 509 | } 510 | 511 | uint256 r = (((rM - rsub21) << 128) + _am - rsub0) >> shift; 512 | 513 | // `_aM / _b` is qM from the original algorithm, inlined here to reduce stack usage 514 | return (q + _aM / _b, r); 515 | } 516 | 517 | /// @dev Absolute value of a 25-bit integer. 518 | /// @param _x the integer 519 | /// @return _x if _x>=0 or -_x if not 520 | function _abs(int256 _x) private pure returns (int256) { 521 | if (_x >= 0) { 522 | return _x; 523 | } 524 | return -_x; 525 | } 526 | } 527 | -------------------------------------------------------------------------------- /contracts/helpers/TestEllipticCurve.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../EllipticCurve.sol"; 6 | import "../FastEcMul.sol"; 7 | 8 | /** 9 | ** @title Test Helper for the EllipticCurve library 10 | ** @author Witnet Foundation 11 | */ 12 | contract TestEllipticCurve { 13 | function invMod(uint256 _x, uint256 _pp) public pure returns (uint256) { 14 | return EllipticCurve.invMod(_x, _pp); 15 | } 16 | 17 | function expMod( 18 | uint256 _base, 19 | uint256 _exp, 20 | uint256 _pp 21 | ) public pure returns (uint256) { 22 | return EllipticCurve.expMod(_base, _exp, _pp); 23 | } 24 | 25 | function toAffine( 26 | uint256 _x, 27 | uint256 _y, 28 | uint256 _z, 29 | uint256 _pp 30 | ) public pure returns (uint256, uint256) { 31 | return EllipticCurve.toAffine(_x, _y, _z, _pp); 32 | } 33 | 34 | function deriveY( 35 | uint8 _prefix, 36 | uint256 _x, 37 | uint256 _aa, 38 | uint256 _bb, 39 | uint256 _pp 40 | ) public pure returns (uint256) { 41 | return EllipticCurve.deriveY(_prefix, _x, _aa, _bb, _pp); 42 | } 43 | 44 | function isOnCurve( 45 | uint _x, 46 | uint _y, 47 | uint _aa, 48 | uint _bb, 49 | uint _pp 50 | ) public pure returns (bool) { 51 | return EllipticCurve.isOnCurve(_x, _y, _aa, _bb, _pp); 52 | } 53 | 54 | function ecInv( 55 | uint256 _x, 56 | uint256 _y, 57 | uint256 _pp 58 | ) public pure returns (uint256, uint256) { 59 | return EllipticCurve.ecInv(_x, _y, _pp); 60 | } 61 | 62 | function ecAdd( 63 | uint256 _x1, 64 | uint256 _y1, 65 | uint256 _x2, 66 | uint256 _y2, 67 | uint256 _aa, 68 | uint256 _pp 69 | ) public pure returns (uint256, uint256) { 70 | return EllipticCurve.ecAdd(_x1, _y1, _x2, _y2, _aa, _pp); 71 | } 72 | 73 | function ecSub( 74 | uint256 _x1, 75 | uint256 _y1, 76 | uint256 _x2, 77 | uint256 _y2, 78 | uint256 _aa, 79 | uint256 _pp 80 | ) public pure returns (uint256, uint256) { 81 | return EllipticCurve.ecSub(_x1, _y1, _x2, _y2, _aa, _pp); 82 | } 83 | 84 | function ecMul( 85 | uint256 _k, 86 | uint256 _x, 87 | uint256 _y, 88 | uint256 _aa, 89 | uint256 _pp 90 | ) public pure returns (uint256, uint256) { 91 | return EllipticCurve.ecMul(_k, _x, _y, _aa, _pp); 92 | } 93 | 94 | function jacAdd( 95 | uint256 _x1, 96 | uint256 _y1, 97 | uint256 _z1, 98 | uint256 _x2, 99 | uint256 _y2, 100 | uint256 _z2, 101 | uint256 _pp 102 | ) public pure returns (uint256, uint256, uint256) { 103 | return EllipticCurve.jacAdd(_x1, _y1, _z1, _x2, _y2, _z2, _pp); 104 | } 105 | 106 | function jacDouble( 107 | uint256 _x, 108 | uint256 _y, 109 | uint256 _z, 110 | uint256 _aa, 111 | uint256 _pp 112 | ) public pure returns (uint256, uint256, uint256) { 113 | return EllipticCurve.jacDouble(_x, _y, _z, _aa, _pp); 114 | } 115 | 116 | function jacMul( 117 | uint256 _d, 118 | uint256 _x, 119 | uint256 _y, 120 | uint256 _z, 121 | uint256 _aa, 122 | uint256 _pp 123 | ) public pure returns (uint256, uint256, uint256) { 124 | return EllipticCurve.jacMul(_d, _x, _y, _z, _aa, _pp); 125 | } 126 | 127 | function decomposeScalar( 128 | uint256 _k, 129 | uint256 _nn, 130 | uint256 _lambda 131 | ) public pure returns (int256, int256) { 132 | return FastEcMul.decomposeScalar(_k, _nn, _lambda); 133 | } 134 | 135 | function ecSimMul( 136 | int256[4] memory _scalars, 137 | uint256[4] memory _points, 138 | uint256 _aa, 139 | uint256 _beta, 140 | uint256 _pp 141 | ) public pure returns (uint256, uint256) { 142 | return FastEcMul.ecSimMul(_scalars, _points, _aa, _beta, _pp); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /examples/Secp256k1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "elliptic-curve-solidity/contracts/EllipticCurve.sol"; 6 | 7 | /** 8 | ** @title Secp256k1 Elliptic Curve 9 | ** @notice Example of particularization of Elliptic Curve for secp256k1 curve 10 | ** @author Witnet Foundation 11 | */ 12 | contract Secp256k1 { 13 | uint256 public constant GX = 14 | 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; 15 | uint256 public constant GY = 16 | 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; 17 | uint256 public constant AA = 0; 18 | uint256 public constant BB = 7; 19 | uint256 public constant PP = 20 | 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; 21 | 22 | /// @notice Public Key derivation from private key 23 | /// Warning: this is just an example. Do not expose your private key. 24 | /// @param privKey The private key 25 | /// @return (qx, qy) The Public Key 26 | function derivePubKey( 27 | uint256 privKey 28 | ) external pure returns (uint256, uint256) { 29 | return EllipticCurve.ecMul(privKey, GX, GY, AA, PP); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elliptic-curve-solidity", 3 | "version": "0.2.5", 4 | "description": "Elliptic Curve arithmetic for up to 256-bit curves written in solidity", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/witnet/elliptic-curve-solidity.git" 8 | }, 9 | "keywords": [ 10 | "cryptography", 11 | "ethereum", 12 | "solidity", 13 | "elliptic", 14 | "ecc", 15 | "curve", 16 | "ecdsa", 17 | "secp256k1", 18 | "secp256r1", 19 | "secp192r1" 20 | ], 21 | "author": "Witnet Foundation ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/witnet/elliptic-curve-solidity/issues" 25 | }, 26 | "homepage": "https://github.com/witnet/elliptic-curve-solidity#readme", 27 | "scripts": { 28 | "benchmark": "truffle test ./benchmark/EcGasHelper.sol ./benchmark/gas.js", 29 | "console": "truffle console", 30 | "compile": "truffle compile --all", 31 | "fmt:js": "eslint \"**/*.js\"", 32 | "fmt:sol": "solhint --max-warnings 0 \"**/*.sol\"", 33 | "fmt!:js": "eslint \"**/*.js\" --fix", 34 | "fmt!:sol": "solhint --max-warnings 0 \"**/*.sol\" --fix", 35 | "fmt!": "npm run fmt!:js && npm run fmt!:sol", 36 | "fmt": "npm run fmt:js && npm run fmt:sol", 37 | "test": "truffle test", 38 | "test:local": "truffle test --network local" 39 | }, 40 | "devDependencies": { 41 | "chai": "^4.3.7", 42 | "eslint": "^8.42.0", 43 | "eslint-config-standard": "^17.1.0", 44 | "eslint-plugin-import": "^2.27.5", 45 | "eslint-plugin-n": "^16.0.0", 46 | "eslint-plugin-promise": "^6.1.1", 47 | "eth-gas-reporter": "^0.2.25", 48 | "solhint": "^3.4.1", 49 | "truffle": "^5.9.3", 50 | "truffle-assertions": "^0.9.2" 51 | } 52 | } -------------------------------------------------------------------------------- /test/data/P192.json: -------------------------------------------------------------------------------- 1 | { 2 | "params": { 3 | "gx": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 4 | "gy": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 5 | "pp": "0xfffffffffffffffffffffffffffffffeffffffffffffffff", 6 | "nn": "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", 7 | "aa": "0xfffffffffffffffffffffffffffffffefffffffffffffffc", 8 | "bb": "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 9 | "lambda": "", 10 | "beta": "" 11 | }, 12 | "multiplication": { 13 | "valid": [ 14 | { 15 | "description": "G x1", 16 | "input": { 17 | "k": "1", 18 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 19 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 20 | }, 21 | "output": { 22 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 23 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 24 | } 25 | }, 26 | { 27 | "description": "G x2", 28 | "input": { 29 | "k": "2", 30 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 31 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 32 | }, 33 | "output": { 34 | "x": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 35 | "y": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" 36 | } 37 | }, 38 | { 39 | "description": "G x3", 40 | "input": { 41 | "k": "3", 42 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 43 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 44 | }, 45 | "output": { 46 | "x": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 47 | "y": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" 48 | } 49 | }, 50 | { 51 | "description": "G x4", 52 | "input": { 53 | "k": "4", 54 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 55 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 56 | }, 57 | "output": { 58 | "x": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 59 | "y": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32" 60 | } 61 | }, 62 | { 63 | "description": "G x5", 64 | "input": { 65 | "k": "5", 66 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 67 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 68 | }, 69 | "output": { 70 | "x": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 71 | "y": "0x31361008476f917badc9f836e62762be312b72543cceaea1" 72 | } 73 | }, 74 | { 75 | "description": "G x6", 76 | "input": { 77 | "k": "6", 78 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 79 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 80 | }, 81 | "output": { 82 | "x": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 83 | "y": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0" 84 | } 85 | }, 86 | { 87 | "description": "G x7", 88 | "input": { 89 | "k": "7", 90 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 91 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 92 | }, 93 | "output": { 94 | "x": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 95 | "y": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5" 96 | } 97 | }, 98 | { 99 | "description": "G x8", 100 | "input": { 101 | "k": "8", 102 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 103 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 104 | }, 105 | "output": { 106 | "x": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 107 | "y": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0" 108 | } 109 | }, 110 | { 111 | "description": "G x9", 112 | "input": { 113 | "k": "9", 114 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 115 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 116 | }, 117 | "output": { 118 | "x": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 119 | "y": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739" 120 | } 121 | }, 122 | { 123 | "description": "G x10", 124 | "input": { 125 | "k": "10", 126 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 127 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 128 | }, 129 | "output": { 130 | "x": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 131 | "y": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0" 132 | } 133 | }, 134 | { 135 | "description": "G x11", 136 | "input": { 137 | "k": "11", 138 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 139 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 140 | }, 141 | "output": { 142 | "x": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 143 | "y": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04" 144 | } 145 | }, 146 | { 147 | "description": "G x12", 148 | "input": { 149 | "k": "12", 150 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 151 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 152 | }, 153 | "output": { 154 | "x": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 155 | "y": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f" 156 | } 157 | }, 158 | { 159 | "description": "G x13", 160 | "input": { 161 | "k": "13", 162 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 163 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 164 | }, 165 | "output": { 166 | "x": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 167 | "y": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e" 168 | } 169 | }, 170 | { 171 | "description": "G x14", 172 | "input": { 173 | "k": "14", 174 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 175 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 176 | }, 177 | "output": { 178 | "x": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 179 | "y": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4" 180 | } 181 | }, 182 | { 183 | "description": "G x15", 184 | "input": { 185 | "k": "15", 186 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 187 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 188 | }, 189 | "output": { 190 | "x": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 191 | "y": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1" 192 | } 193 | }, 194 | { 195 | "description": "G x16", 196 | "input": { 197 | "k": "16", 198 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 199 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 200 | }, 201 | "output": { 202 | "x": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 203 | "y": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290" 204 | } 205 | }, 206 | { 207 | "description": "G x17", 208 | "input": { 209 | "k": "17", 210 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 211 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 212 | }, 213 | "output": { 214 | "x": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 215 | "y": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0" 216 | } 217 | }, 218 | { 219 | "description": "G x18", 220 | "input": { 221 | "k": "18", 222 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 223 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 224 | }, 225 | "output": { 226 | "x": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 227 | "y": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53" 228 | } 229 | }, 230 | { 231 | "description": "G x19", 232 | "input": { 233 | "k": "19", 234 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 235 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 236 | }, 237 | "output": { 238 | "x": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 239 | "y": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a" 240 | } 241 | }, 242 | { 243 | "description": "G x20", 244 | "input": { 245 | "k": "20", 246 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 247 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 248 | }, 249 | "output": { 250 | "x": "0xbb6f082321d34dbd786a1566915c6dd5edf879ab0f5add67", 251 | "y": "0x91e4dd8a77c4531c8b76def2e5339b5eb95d5d9479df4c8d" 252 | } 253 | }, 254 | { 255 | "description": "G x112233445566778899", 256 | "input": { 257 | "k": "112233445566778899", 258 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 259 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 260 | }, 261 | "output": { 262 | "x": "0x81e6e0f14c9302c8a8dca8a038b73165e9687d0490cd9f85", 263 | "y": "0xf58067119eed8579388c4281dc645a27db7764750e812477" 264 | } 265 | }, 266 | { 267 | "description": "G x112233445566778899112233445566778899", 268 | "input": { 269 | "k": "112233445566778899112233445566778899", 270 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 271 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 272 | }, 273 | "output": { 274 | "x": "0xb357b10ac985c891b29fb37da56661cccf50cec21128d4f6", 275 | "y": "0xba20dc2fa1cc228d3c2d8b538c2177c2921884c6b7f0d96f" 276 | } 277 | }, 278 | { 279 | "description": "G x28948022309329048855892746252171976963209391069768726095651290785379540373584", 280 | "input": { 281 | "k": "28948022309329048855892746252171976963209391069768726095651290785379540373584", 282 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 283 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 284 | }, 285 | "output": { 286 | "x": "0x9198d656a0cf79b95b04aae7feaf162f57c3d447dfe8ae9e", 287 | "y": "0x3b36dc4128a49e1981e3fd8c89f00a8079a5b2d0085f1048" 288 | } 289 | }, 290 | { 291 | "description": "G x57896044618658097711785492504343953926418782139537452191302581570759080747168", 292 | "input": { 293 | "k": "57896044618658097711785492504343953926418782139537452191302581570759080747168", 294 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 295 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 296 | }, 297 | "output": { 298 | "x": "0x3025319f8ae001d2916e146dc10ca5b29d8fab3f0cfd3416", 299 | "y": "0x3488cc904e937f734c1d5d6c612aa417e0af8954d62eede8" 300 | } 301 | }, 302 | { 303 | "description": "G x86844066927987146567678238756515930889628173209306178286953872356138621120752", 304 | "input": { 305 | "k": "86844066927987146567678238756515930889628173209306178286953872356138621120752", 306 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 307 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 308 | }, 309 | "output": { 310 | "x": "0xca126959d2109f4907d0b693980fbd4b4ee255e2e1a563f0", 311 | "y": "0x3b4c9b9c36b4ce7cf76d6a6f7381e21cd78c3605c92efece" 312 | } 313 | }, 314 | { 315 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494317", 316 | "input": { 317 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494317", 318 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 319 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 320 | }, 321 | "output": { 322 | "x": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 323 | "y": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684" 324 | } 325 | }, 326 | { 327 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494318", 328 | "input": { 329 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494318", 330 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 331 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 332 | }, 333 | "output": { 334 | "x": "0x2950d58101b33ca645e48d7d40a8151cf7bd5c1ad245c6b2", 335 | "y": "0x7fe7cced8f721d0fbb37da93b25568778ccaa0411738cee3" 336 | } 337 | }, 338 | { 339 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494319", 340 | "input": { 341 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494319", 342 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 343 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 344 | }, 345 | "output": { 346 | "x": "0xb5a32aecc4925fcfd768a97944f5ee38f80dd4aa586dd1e6", 347 | "y": "0x2c2ab595d1a1356720dc458dd7b82be34fc59c7b0a0a0792" 348 | } 349 | }, 350 | { 351 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494320", 352 | "input": { 353 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494320", 354 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 355 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 356 | }, 357 | "output": { 358 | "x": "0x44fdb8da22e1fe90d9bcb1dc41a91a7d77d4a9ced8988d6a", 359 | "y": "0xac3f1ba871bfcb82ddc6e8dfb35b831e465ede074d3118f8" 360 | } 361 | }, 362 | { 363 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494321", 364 | "input": { 365 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494321", 366 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 367 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 368 | }, 369 | "output": { 370 | "x": "0xb82850f97a699f5928f4d127f548e73b9080ec5d7a1f953", 371 | "y": "0x5f6987fd0341c06047f4bad1e9f5f72a87169f7a123c6bab" 372 | } 373 | }, 374 | { 375 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494322", 376 | "input": { 377 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494322", 378 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 379 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 380 | }, 381 | "output": { 382 | "x": "0xdd1e884849b31ca01cf4a35ab1b5d3eb9e52db0da5de35a5", 383 | "y": "0x312a7d6ad08b102e9f4dbec26d92c9ae01bcc313bcc6f990" 384 | } 385 | }, 386 | { 387 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494323", 388 | "input": { 389 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494323", 390 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 391 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 392 | }, 393 | "output": { 394 | "x": "0x87f47943a003427b060445b9ede8fafb83ff6d3bd3aa5887", 395 | "y": "0xf85a9f4e441f9999edc060919a16d2d21c3ba9af1effc5af" 396 | } 397 | }, 398 | { 399 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494324", 400 | "input": { 401 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494324", 402 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 403 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 404 | }, 405 | "output": { 406 | "x": "0x25306b9782fb64930f5bfe218baa28b6443d52ec48e9289f", 407 | "y": "0x8e63d4109a35a8cb861d0dd287dea49cfcd3ad442fdff70b" 408 | } 409 | }, 410 | { 411 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494325", 412 | "input": { 413 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494325", 414 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 415 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 416 | }, 417 | "output": { 418 | "x": "0x51a6ce7f3d7e4ed7bd753f46877203feef7178b0d6e1b9f5", 419 | "y": "0xfcb87228c11455b0f64799f628899ef7932937d52ce2115f" 420 | } 421 | }, 422 | { 423 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494326", 424 | "input": { 425 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494326", 426 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 427 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 428 | }, 429 | "output": { 430 | "x": "0x56b0dac2e74dfbbb07dba41533082b0bdf8146a4194d41b5", 431 | "y": "0x78aa4fcd34fa9980455557bd1e86007b7a6e7f19857669a" 432 | } 433 | }, 434 | { 435 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494327", 436 | "input": { 437 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494327", 438 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 439 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 440 | }, 441 | "output": { 442 | "x": "0xd9e999fb94c298d2ecc42eed5fe735a2db8a68f3f855d2c", 443 | "y": "0x716ca04273eeb5a8863e45b0b06e1e81ee03b577a90d5844" 444 | } 445 | }, 446 | { 447 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494328", 448 | "input": { 449 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494328", 450 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 451 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 452 | }, 453 | "output": { 454 | "x": "0x235a8ba00f9c71b1464f46ba96093900b92197e679763008", 455 | "y": "0x9cae5b3b94560331baba88c56ed7feb430317abe15d28ba6" 456 | } 457 | }, 458 | { 459 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494329", 460 | "input": { 461 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494329", 462 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 463 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 464 | }, 465 | "output": { 466 | "x": "0x6c6b22f6f44850cd4892aa1dd3ceadc5db5f81450d4947b4", 467 | "y": "0x9160c122d5f7779eb25ef58c72796cda3b2b6db5fb5e409b" 468 | } 469 | }, 470 | { 471 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494330", 472 | "input": { 473 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494330", 474 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 475 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 476 | }, 477 | "output": { 478 | "x": "0x51a9fbfb36aa3d0f058aea922b88873815ff2936c263be37", 479 | "y": "0xff96551ad3672402fc3ee8dd9b625b21d0e94254e7fb2d86" 480 | } 481 | }, 482 | { 483 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494331", 484 | "input": { 485 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494331", 486 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 487 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 488 | }, 489 | "output": { 490 | "x": "0xe65d8233295e83e0d72d0bf421d3751309d70eef20bfaa1", 491 | "y": "0x784acc03fc7fa80288b5f56b63d26aa95f5bb8121b61474" 492 | } 493 | }, 494 | { 495 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494332", 496 | "input": { 497 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494332", 498 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 499 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 500 | }, 501 | "output": { 502 | "x": "0xd1fc672ac00f93d0a7e654fdb9bcb0f424862f214f315d84", 503 | "y": "0xbe3d15e0924b0dd14d5b59ac97b03f38b4750bf5067f4cfc" 504 | } 505 | }, 506 | { 507 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494333", 508 | "input": { 509 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494333", 510 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 511 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 512 | }, 513 | "output": { 514 | "x": "0x6e9e5480ff9021dc4e1531acfc94c0afa56e12a7723ae21d", 515 | "y": "0x39857f9e91c64e6585d17eda5c254ed31cf9242fe8c20f35" 516 | } 517 | }, 518 | { 519 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494334", 520 | "input": { 521 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494334", 522 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 523 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 524 | }, 525 | "output": { 526 | "x": "0x63538a56d41453386edcebcc696f65e584bc5262a9514a57", 527 | "y": "0x2a806c25a75d581e76c0a8baa98bc6a949631919dfcaa142" 528 | } 529 | }, 530 | { 531 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494335", 532 | "input": { 533 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494335", 534 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 535 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 536 | }, 537 | "output": { 538 | "x": "0x8a6df404df875a5b677717b5602cccd6b7a0c32f3041aff1", 539 | "y": "0x1a38efbea05710933dfac5bf077567c79531ac0ad4716635" 540 | } 541 | }, 542 | { 543 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494336", 544 | "input": { 545 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494336", 546 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 547 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 548 | }, 549 | "output": { 550 | "x": "0x70b250049059f860e1a052ec161ca24980663acfab298430", 551 | "y": "0xac34a3bf7a63fcc7eb9c755510d03a803c2cdfb7c790f1f2" 552 | } 553 | }, 554 | { 555 | "description": "G x77059549740374936337596179780007572461065571555507600191520924336939429631266", 556 | "input": { 557 | "k": "77059549740374936337596179780007572461065571555507600191520924336939429631266", 558 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 559 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 560 | }, 561 | "output": { 562 | "x": "0xf17f931478f7424f49f9bd0f863f5f310600251815d6e1f7", 563 | "y": "0xcd64df7791078e71203585b2ae15d3e0ee87c4fc321b39a1" 564 | } 565 | }, 566 | { 567 | "description": "G x32670510020758816978083085130507043184471273380659243275938904335757337482424", 568 | "input": { 569 | "k": "32670510020758816978083085130507043184471273380659243275938904335757337482424", 570 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 571 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 572 | }, 573 | "output": { 574 | "x": "0x4a9f0e1e60b489ccda49662be8420b2786a1548aa9c68513", 575 | "y": "0xaa8e50eb38ea1fab50d3e507cdd844e424d23c21eb565247" 576 | } 577 | } 578 | ], 579 | "invalid": [] 580 | }, 581 | "addition": { 582 | "valid": [ 583 | { 584 | "description": "small scalar 1 xG plus G", 585 | "input": { 586 | "x1": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 587 | "y1": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 588 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 589 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 590 | }, 591 | "output": { 592 | "x": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 593 | "y": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" 594 | } 595 | }, 596 | { 597 | "description": "small scalar 2 xG plus G", 598 | "input": { 599 | "x1": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 600 | "y1": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab", 601 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 602 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 603 | }, 604 | "output": { 605 | "x": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 606 | "y": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" 607 | } 608 | }, 609 | { 610 | "description": "small scalar 3 xG plus G", 611 | "input": { 612 | "x1": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 613 | "y1": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd", 614 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 615 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 616 | }, 617 | "output": { 618 | "x": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 619 | "y": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32" 620 | } 621 | }, 622 | { 623 | "description": "small scalar 4 xG plus G", 624 | "input": { 625 | "x1": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 626 | "y1": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32", 627 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 628 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 629 | }, 630 | "output": { 631 | "x": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 632 | "y": "0x31361008476f917badc9f836e62762be312b72543cceaea1" 633 | } 634 | }, 635 | { 636 | "description": "small scalar 5 xG plus G", 637 | "input": { 638 | "x1": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 639 | "y1": "0x31361008476f917badc9f836e62762be312b72543cceaea1", 640 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 641 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 642 | }, 643 | "output": { 644 | "x": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 645 | "y": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0" 646 | } 647 | }, 648 | { 649 | "description": "small scalar 6 xG plus G", 650 | "input": { 651 | "x1": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 652 | "y1": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0", 653 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 654 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 655 | }, 656 | "output": { 657 | "x": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 658 | "y": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5" 659 | } 660 | }, 661 | { 662 | "description": "small scalar 7 xG plus G", 663 | "input": { 664 | "x1": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 665 | "y1": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5", 666 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 667 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 668 | }, 669 | "output": { 670 | "x": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 671 | "y": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0" 672 | } 673 | }, 674 | { 675 | "description": "small scalar 8 xG plus G", 676 | "input": { 677 | "x1": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 678 | "y1": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0", 679 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 680 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 681 | }, 682 | "output": { 683 | "x": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 684 | "y": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739" 685 | } 686 | }, 687 | { 688 | "description": "small scalar 9 xG plus G", 689 | "input": { 690 | "x1": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 691 | "y1": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739", 692 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 693 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 694 | }, 695 | "output": { 696 | "x": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 697 | "y": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0" 698 | } 699 | }, 700 | { 701 | "description": "small scalar 10 xG plus G", 702 | "input": { 703 | "x1": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 704 | "y1": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0", 705 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 706 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 707 | }, 708 | "output": { 709 | "x": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 710 | "y": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04" 711 | } 712 | }, 713 | { 714 | "description": "small scalar 11 xG plus G", 715 | "input": { 716 | "x1": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 717 | "y1": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04", 718 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 719 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 720 | }, 721 | "output": { 722 | "x": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 723 | "y": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f" 724 | } 725 | }, 726 | { 727 | "description": "small scalar 12 xG plus G", 728 | "input": { 729 | "x1": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 730 | "y1": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f", 731 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 732 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 733 | }, 734 | "output": { 735 | "x": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 736 | "y": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e" 737 | } 738 | }, 739 | { 740 | "description": "small scalar 13 xG plus G", 741 | "input": { 742 | "x1": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 743 | "y1": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e", 744 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 745 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 746 | }, 747 | "output": { 748 | "x": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 749 | "y": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4" 750 | } 751 | }, 752 | { 753 | "description": "small scalar 14 xG plus G", 754 | "input": { 755 | "x1": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 756 | "y1": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4", 757 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 758 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 759 | }, 760 | "output": { 761 | "x": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 762 | "y": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1" 763 | } 764 | }, 765 | { 766 | "description": "small scalar 15 xG plus G", 767 | "input": { 768 | "x1": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 769 | "y1": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1", 770 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 771 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 772 | }, 773 | "output": { 774 | "x": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 775 | "y": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290" 776 | } 777 | }, 778 | { 779 | "description": "small scalar 16 xG plus G", 780 | "input": { 781 | "x1": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 782 | "y1": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290", 783 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 784 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 785 | }, 786 | "output": { 787 | "x": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 788 | "y": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0" 789 | } 790 | }, 791 | { 792 | "description": "small scalar 17 xG plus G", 793 | "input": { 794 | "x1": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 795 | "y1": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0", 796 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 797 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 798 | }, 799 | "output": { 800 | "x": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 801 | "y": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53" 802 | } 803 | }, 804 | { 805 | "description": "small scalar 18 xG plus G", 806 | "input": { 807 | "x1": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 808 | "y1": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53", 809 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 810 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 811 | }, 812 | "output": { 813 | "x": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 814 | "y": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a" 815 | } 816 | }, 817 | { 818 | "description": "small scalar 19 xG plus G", 819 | "input": { 820 | "x1": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 821 | "y1": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a", 822 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 823 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 824 | }, 825 | "output": { 826 | "x": "0xbb6f082321d34dbd786a1566915c6dd5edf879ab0f5add67", 827 | "y": "0x91e4dd8a77c4531c8b76def2e5339b5eb95d5d9479df4c8d" 828 | } 829 | }, 830 | { 831 | "description": "big scalar 1 xG plus big scalar 2 xG", 832 | "input": { 833 | "x1": "0x9198d656a0cf79b95b04aae7feaf162f57c3d447dfe8ae9e", 834 | "y1": "0x3b36dc4128a49e1981e3fd8c89f00a8079a5b2d0085f1048", 835 | "x2": "0x3025319f8ae001d2916e146dc10ca5b29d8fab3f0cfd3416", 836 | "y2": "0x3488cc904e937f734c1d5d6c612aa417e0af8954d62eede8" 837 | }, 838 | "output": { 839 | "x": "0xca126959d2109f4907d0b693980fbd4b4ee255e2e1a563f0", 840 | "y": "0x3b4c9b9c36b4ce7cf76d6a6f7381e21cd78c3605c92efece" 841 | } 842 | }, 843 | { 844 | "description": "small scalar 1 xG plus big scalar 4 xG", 845 | "input": { 846 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 847 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 848 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 849 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 850 | }, 851 | "output": { 852 | "x": "0x2950d58101b33ca645e48d7d40a8151cf7bd5c1ad245c6b2", 853 | "y": "0x7fe7cced8f721d0fbb37da93b25568778ccaa0411738cee3" 854 | } 855 | }, 856 | { 857 | "description": "small scalar 2 xG plus big scalar 4 xG", 858 | "input": { 859 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 860 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 861 | "x2": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 862 | "y2": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" 863 | }, 864 | "output": { 865 | "x": "0xb5a32aecc4925fcfd768a97944f5ee38f80dd4aa586dd1e6", 866 | "y": "0x2c2ab595d1a1356720dc458dd7b82be34fc59c7b0a0a0792" 867 | } 868 | }, 869 | { 870 | "description": "small scalar 3 xG plus big scalar 4 xG", 871 | "input": { 872 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 873 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 874 | "x2": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 875 | "y2": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" 876 | }, 877 | "output": { 878 | "x": "0x44fdb8da22e1fe90d9bcb1dc41a91a7d77d4a9ced8988d6a", 879 | "y": "0xac3f1ba871bfcb82ddc6e8dfb35b831e465ede074d3118f8" 880 | } 881 | }, 882 | { 883 | "description": "small scalar 4 xG plus big scalar 4 xG", 884 | "input": { 885 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 886 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 887 | "x2": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 888 | "y2": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32" 889 | }, 890 | "output": { 891 | "x": "0xb82850f97a699f5928f4d127f548e73b9080ec5d7a1f953", 892 | "y": "0x5f6987fd0341c06047f4bad1e9f5f72a87169f7a123c6bab" 893 | } 894 | }, 895 | { 896 | "description": "small scalar 5 xG plus big scalar 4 xG", 897 | "input": { 898 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 899 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 900 | "x2": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 901 | "y2": "0x31361008476f917badc9f836e62762be312b72543cceaea1" 902 | }, 903 | "output": { 904 | "x": "0xdd1e884849b31ca01cf4a35ab1b5d3eb9e52db0da5de35a5", 905 | "y": "0x312a7d6ad08b102e9f4dbec26d92c9ae01bcc313bcc6f990" 906 | } 907 | }, 908 | { 909 | "description": "small scalar 6 xG plus big scalar 4 xG", 910 | "input": { 911 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 912 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 913 | "x2": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 914 | "y2": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0" 915 | }, 916 | "output": { 917 | "x": "0x87f47943a003427b060445b9ede8fafb83ff6d3bd3aa5887", 918 | "y": "0xf85a9f4e441f9999edc060919a16d2d21c3ba9af1effc5af" 919 | } 920 | }, 921 | { 922 | "description": "small scalar 7 xG plus big scalar 4 xG", 923 | "input": { 924 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 925 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 926 | "x2": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 927 | "y2": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5" 928 | }, 929 | "output": { 930 | "x": "0x25306b9782fb64930f5bfe218baa28b6443d52ec48e9289f", 931 | "y": "0x8e63d4109a35a8cb861d0dd287dea49cfcd3ad442fdff70b" 932 | } 933 | }, 934 | { 935 | "description": "small scalar 8 xG plus big scalar 4 xG", 936 | "input": { 937 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 938 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 939 | "x2": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 940 | "y2": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0" 941 | }, 942 | "output": { 943 | "x": "0x51a6ce7f3d7e4ed7bd753f46877203feef7178b0d6e1b9f5", 944 | "y": "0xfcb87228c11455b0f64799f628899ef7932937d52ce2115f" 945 | } 946 | }, 947 | { 948 | "description": "small scalar 9 xG plus big scalar 4 xG", 949 | "input": { 950 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 951 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 952 | "x2": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 953 | "y2": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739" 954 | }, 955 | "output": { 956 | "x": "0x56b0dac2e74dfbbb07dba41533082b0bdf8146a4194d41b5", 957 | "y": "0x78aa4fcd34fa9980455557bd1e86007b7a6e7f19857669a" 958 | } 959 | }, 960 | { 961 | "description": "small scalar 10 xG plus big scalar 4 xG", 962 | "input": { 963 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 964 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 965 | "x2": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 966 | "y2": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0" 967 | }, 968 | "output": { 969 | "x": "0xd9e999fb94c298d2ecc42eed5fe735a2db8a68f3f855d2c", 970 | "y": "0x716ca04273eeb5a8863e45b0b06e1e81ee03b577a90d5844" 971 | } 972 | }, 973 | { 974 | "description": "small scalar 11 xG plus big scalar 4 xG", 975 | "input": { 976 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 977 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 978 | "x2": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 979 | "y2": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04" 980 | }, 981 | "output": { 982 | "x": "0x235a8ba00f9c71b1464f46ba96093900b92197e679763008", 983 | "y": "0x9cae5b3b94560331baba88c56ed7feb430317abe15d28ba6" 984 | } 985 | }, 986 | { 987 | "description": "small scalar 12 xG plus big scalar 4 xG", 988 | "input": { 989 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 990 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 991 | "x2": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 992 | "y2": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f" 993 | }, 994 | "output": { 995 | "x": "0x6c6b22f6f44850cd4892aa1dd3ceadc5db5f81450d4947b4", 996 | "y": "0x9160c122d5f7779eb25ef58c72796cda3b2b6db5fb5e409b" 997 | } 998 | }, 999 | { 1000 | "description": "small scalar 13 xG plus big scalar 4 xG", 1001 | "input": { 1002 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1003 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1004 | "x2": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 1005 | "y2": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e" 1006 | }, 1007 | "output": { 1008 | "x": "0x51a9fbfb36aa3d0f058aea922b88873815ff2936c263be37", 1009 | "y": "0xff96551ad3672402fc3ee8dd9b625b21d0e94254e7fb2d86" 1010 | } 1011 | }, 1012 | { 1013 | "description": "small scalar 14 xG plus big scalar 4 xG", 1014 | "input": { 1015 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1016 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1017 | "x2": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 1018 | "y2": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4" 1019 | }, 1020 | "output": { 1021 | "x": "0xe65d8233295e83e0d72d0bf421d3751309d70eef20bfaa1", 1022 | "y": "0x784acc03fc7fa80288b5f56b63d26aa95f5bb8121b61474" 1023 | } 1024 | }, 1025 | { 1026 | "description": "small scalar 15 xG plus big scalar 4 xG", 1027 | "input": { 1028 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1029 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1030 | "x2": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 1031 | "y2": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1" 1032 | }, 1033 | "output": { 1034 | "x": "0xd1fc672ac00f93d0a7e654fdb9bcb0f424862f214f315d84", 1035 | "y": "0xbe3d15e0924b0dd14d5b59ac97b03f38b4750bf5067f4cfc" 1036 | } 1037 | }, 1038 | { 1039 | "description": "small scalar 16 xG plus big scalar 4 xG", 1040 | "input": { 1041 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1042 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1043 | "x2": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 1044 | "y2": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290" 1045 | }, 1046 | "output": { 1047 | "x": "0x6e9e5480ff9021dc4e1531acfc94c0afa56e12a7723ae21d", 1048 | "y": "0x39857f9e91c64e6585d17eda5c254ed31cf9242fe8c20f35" 1049 | } 1050 | }, 1051 | { 1052 | "description": "small scalar 17 xG plus big scalar 4 xG", 1053 | "input": { 1054 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1055 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1056 | "x2": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 1057 | "y2": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0" 1058 | }, 1059 | "output": { 1060 | "x": "0x63538a56d41453386edcebcc696f65e584bc5262a9514a57", 1061 | "y": "0x2a806c25a75d581e76c0a8baa98bc6a949631919dfcaa142" 1062 | } 1063 | }, 1064 | { 1065 | "description": "small scalar 18 xG plus big scalar 4 xG", 1066 | "input": { 1067 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1068 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1069 | "x2": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 1070 | "y2": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53" 1071 | }, 1072 | "output": { 1073 | "x": "0x8a6df404df875a5b677717b5602cccd6b7a0c32f3041aff1", 1074 | "y": "0x1a38efbea05710933dfac5bf077567c79531ac0ad4716635" 1075 | } 1076 | }, 1077 | { 1078 | "description": "small scalar 19 xG plus big scalar 4 xG", 1079 | "input": { 1080 | "x1": "0xf582ecaf63ce9bc6d639ac91c0b7076c25cd0c13ff05c95e", 1081 | "y1": "0x8039b0d9480f99cff3ecdd89097c9f6d5191254875428684", 1082 | "x2": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 1083 | "y2": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a" 1084 | }, 1085 | "output": { 1086 | "x": "0x70b250049059f860e1a052ec161ca24980663acfab298430", 1087 | "y": "0xac34a3bf7a63fcc7eb9c755510d03a803c2cdfb7c790f1f2" 1088 | } 1089 | } 1090 | ], 1091 | "invalid": [] 1092 | }, 1093 | "subtraction": { 1094 | "valid": [ 1095 | { 1096 | "description": "small scalar 5 xG minus G", 1097 | "input": { 1098 | "x1": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 1099 | "y1": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab", 1100 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1101 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1102 | }, 1103 | "output": { 1104 | "x": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1105 | "y": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1106 | } 1107 | }, 1108 | { 1109 | "description": "small scalar 6 xG minus G", 1110 | "input": { 1111 | "x1": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 1112 | "y1": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd", 1113 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1114 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1115 | }, 1116 | "output": { 1117 | "x": "0xdafebf5828783f2ad35534631588a3f629a70fb16982a888", 1118 | "y": "0xdd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab" 1119 | } 1120 | }, 1121 | { 1122 | "description": "small scalar 7 xG minus G", 1123 | "input": { 1124 | "x1": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 1125 | "y1": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32", 1126 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1127 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1128 | }, 1129 | "output": { 1130 | "x": "0x76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da", 1131 | "y": "0x782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd" 1132 | } 1133 | }, 1134 | { 1135 | "description": "small scalar 8 xG minus G", 1136 | "input": { 1137 | "x1": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 1138 | "y1": "0x31361008476f917badc9f836e62762be312b72543cceaea1", 1139 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1140 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1141 | }, 1142 | "output": { 1143 | "x": "0x35433907297cc378b0015703374729d7a4fe46647084e4ba", 1144 | "y": "0xa2649984f2135c301ea3acb0776cd4f125389b311db3be32" 1145 | } 1146 | }, 1147 | { 1148 | "description": "small scalar 9 xG minus G", 1149 | "input": { 1150 | "x1": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 1151 | "y1": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0", 1152 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1153 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1154 | }, 1155 | "output": { 1156 | "x": "0x10bb8e9840049b183e078d9c300e1605590118ebdd7ff590", 1157 | "y": "0x31361008476f917badc9f836e62762be312b72543cceaea1" 1158 | } 1159 | }, 1160 | { 1161 | "description": "small scalar 10 xG minus G", 1162 | "input": { 1163 | "x1": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 1164 | "y1": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5", 1165 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1166 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1167 | }, 1168 | "output": { 1169 | "x": "0xa37abc6c431f9ac398bf5bd1aa6678320ace8ecb93d23f2a", 1170 | "y": "0x851b3caec99908dbfed7040a1bbda90e081f7c5710bc68f0" 1171 | } 1172 | }, 1173 | { 1174 | "description": "small scalar 11 xG minus G", 1175 | "input": { 1176 | "x1": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 1177 | "y1": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0", 1178 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1179 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1180 | }, 1181 | "output": { 1182 | "x": "0x8da75a1f75ddcd7660f923243060edce5de37f007011fcfd", 1183 | "y": "0x57cb5fcf6860b35418240db8fdb3c01dd4b702f96409ffb5" 1184 | } 1185 | }, 1186 | { 1187 | "description": "small scalar 12 xG minus G", 1188 | "input": { 1189 | "x1": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 1190 | "y1": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739", 1191 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1192 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1193 | }, 1194 | "output": { 1195 | "x": "0x2fa1f92d1ecce92014771993cc14899d4b5977883397edde", 1196 | "y": "0xa338afdef78b7214273b8b5978ef733ff2dd8a8e9738f6c0" 1197 | } 1198 | }, 1199 | { 1200 | "description": "small scalar 13 xG minus G", 1201 | "input": { 1202 | "x1": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 1203 | "y1": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0", 1204 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1205 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1206 | }, 1207 | "output": { 1208 | "x": "0x818a4d308b1cabb74e9e8f2ba8d27c9e1d9d375ab980388f", 1209 | "y": "0x1d1aa5e208d87cd7c292f7cbb457cdf30ea542176c8e739" 1210 | } 1211 | }, 1212 | { 1213 | "description": "small scalar 14 xG minus G", 1214 | "input": { 1215 | "x1": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 1216 | "y1": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04", 1217 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1218 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1219 | }, 1220 | "output": { 1221 | "x": "0xaa7c4f9ef99e3e96d1aede2bd9238842859bb150d1fe9d85", 1222 | "y": "0x3212a36547edc62901ee3658b2f4859460eb5eb2491397b0" 1223 | } 1224 | }, 1225 | { 1226 | "description": "small scalar 15 xG minus G", 1227 | "input": { 1228 | "x1": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 1229 | "y1": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f", 1230 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1231 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1232 | }, 1233 | "output": { 1234 | "x": "0x1c995995eb76324f1844f7164d22b652280940370628a2aa", 1235 | "y": "0xef1765ce37e9eb73029f556400fa77bdb34cb8611aaa9c04" 1236 | } 1237 | }, 1238 | { 1239 | "description": "small scalar 16 xG minus G", 1240 | "input": { 1241 | "x1": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 1242 | "y1": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e", 1243 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1244 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1245 | }, 1246 | "output": { 1247 | "x": "0x1061343f3d456d0eca013877f8c9e7b28fccdcda67eeb8ab", 1248 | "y": "0x5a064caa2ea6b03798fef8e3e7a48648681eac020b27293f" 1249 | } 1250 | }, 1251 | { 1252 | "description": "small scalar 17 xG minus G", 1253 | "input": { 1254 | "x1": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 1255 | "y1": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4", 1256 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1257 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1258 | }, 1259 | "output": { 1260 | "x": "0x112af141d33efb9f2f68821e051e4ea004144a363c4a090a", 1261 | "y": "0x6e0cbe3bfc5293f72a2c1726e081e09e7f10a094432b1c1e" 1262 | } 1263 | }, 1264 | { 1265 | "description": "small scalar 18 xG minus G", 1266 | "input": { 1267 | "x1": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 1268 | "y1": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1", 1269 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1270 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1271 | }, 1272 | "output": { 1273 | "x": "0x13b9310646ebc93b591746b3f7c64e05dee08843de1081c1", 1274 | "y": "0x1edcea63b44142dd15f3b427ec41a1ec4fbaca95e186e6b4" 1275 | } 1276 | }, 1277 | { 1278 | "description": "small scalar 19 xG minus G", 1279 | "input": { 1280 | "x1": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 1281 | "y1": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290", 1282 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1283 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1284 | }, 1285 | "output": { 1286 | "x": "0x8c9595e63b56b633ba3546b2b5414de736de4a9e7578b1e7", 1287 | "y": "0x266b762a934f00c17cf387993aa566b6ad7537cdd98fc7b1" 1288 | } 1289 | }, 1290 | { 1291 | "description": "small scalar 20 xG minus G", 1292 | "input": { 1293 | "x1": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 1294 | "y1": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0", 1295 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1296 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1297 | }, 1298 | "output": { 1299 | "x": "0xb7310b4548fbfdbd29005092a5355bfcd99473733048afdf", 1300 | "y": "0xff9eae9edcd27c1e42d8585c4546d9491845c56629cf2290" 1301 | } 1302 | }, 1303 | { 1304 | "description": "small scalar 21 xG minus G", 1305 | "input": { 1306 | "x1": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 1307 | "y1": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53", 1308 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1309 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1310 | }, 1311 | "output": { 1312 | "x": "0x44275cd2e1f46dc3f9f57636c2b4213b8bb445930510ff8a", 1313 | "y": "0xefad8348fde30c87de438612a818e98d9b76a67ad25ddfd0" 1314 | } 1315 | }, 1316 | { 1317 | "description": "small scalar 22 xG minus G", 1318 | "input": { 1319 | "x1": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 1320 | "y1": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a", 1321 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1322 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1323 | }, 1324 | "output": { 1325 | "x": "0xc1b4db0227210613a6ca15c428024e40b6513365d72591a3", 1326 | "y": "0x1e26b286bca1d08f4fe8f801267df9fd7782ec3ec3f47f53" 1327 | } 1328 | }, 1329 | { 1330 | "description": "small scalar 23 xG minus G", 1331 | "input": { 1332 | "x1": "0xbb6f082321d34dbd786a1566915c6dd5edf879ab0f5add67", 1333 | "y1": "0x91e4dd8a77c4531c8b76def2e5339b5eb95d5d9479df4c8d", 1334 | "x2": "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 1335 | "y2": "0x7192b95ffc8da78631011ed6b24cdd573f977a11e794811" 1336 | }, 1337 | "output": { 1338 | "x": "0xc0626bcf247de5d307fd839238d72688774fc97a1cf8ad1b", 1339 | "y": "0x9cdc99d753973dc197e12778e829c804ec1a6b4e71faa20a" 1340 | } 1341 | } 1342 | ], 1343 | "invalid": [] 1344 | }, 1345 | "mulAddMul": { 1346 | "valid": [], 1347 | "invalid": [] 1348 | }, 1349 | "decomposeScalar": { 1350 | "valid": [], 1351 | "invalid": [] 1352 | }, 1353 | "simMul": { 1354 | "valid": [], 1355 | "invalid": [] 1356 | } 1357 | } -------------------------------------------------------------------------------- /test/data/P224.json: -------------------------------------------------------------------------------- 1 | { 2 | "params": { 3 | "gx": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 4 | "gy": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 5 | "pp": "0xffffffffffffffffffffffffffffffff000000000000000000000001", 6 | "nn": "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", 7 | "aa": "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", 8 | "bb": "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", 9 | "lambda": "", 10 | "beta": "" 11 | }, 12 | "multiplication": { 13 | "valid": [ 14 | { 15 | "description": "G x1", 16 | "input": { 17 | "k": "1", 18 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 19 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 20 | }, 21 | "output": { 22 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 23 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 24 | } 25 | }, 26 | { 27 | "description": "G x2", 28 | "input": { 29 | "k": "2", 30 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 31 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 32 | }, 33 | "output": { 34 | "x": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 35 | "y": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb" 36 | } 37 | }, 38 | { 39 | "description": "G x3", 40 | "input": { 41 | "k": "3", 42 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 43 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 44 | }, 45 | "output": { 46 | "x": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 47 | "y": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925" 48 | } 49 | }, 50 | { 51 | "description": "G x4", 52 | "input": { 53 | "k": "4", 54 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 55 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 56 | }, 57 | "output": { 58 | "x": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 59 | "y": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9" 60 | } 61 | }, 62 | { 63 | "description": "G x5", 64 | "input": { 65 | "k": "5", 66 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 67 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 68 | }, 69 | "output": { 70 | "x": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 71 | "y": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b" 72 | } 73 | }, 74 | { 75 | "description": "G x6", 76 | "input": { 77 | "k": "6", 78 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 79 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 80 | }, 81 | "output": { 82 | "x": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 83 | "y": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e" 84 | } 85 | }, 86 | { 87 | "description": "G x7", 88 | "input": { 89 | "k": "7", 90 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 91 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 92 | }, 93 | "output": { 94 | "x": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 95 | "y": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963" 96 | } 97 | }, 98 | { 99 | "description": "G x8", 100 | "input": { 101 | "k": "8", 102 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 103 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 104 | }, 105 | "output": { 106 | "x": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 107 | "y": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a" 108 | } 109 | }, 110 | { 111 | "description": "G x9", 112 | "input": { 113 | "k": "9", 114 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 115 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 116 | }, 117 | "output": { 118 | "x": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 119 | "y": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463" 120 | } 121 | }, 122 | { 123 | "description": "G x10", 124 | "input": { 125 | "k": "10", 126 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 127 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 128 | }, 129 | "output": { 130 | "x": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 131 | "y": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f" 132 | } 133 | }, 134 | { 135 | "description": "G x11", 136 | "input": { 137 | "k": "11", 138 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 139 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 140 | }, 141 | "output": { 142 | "x": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 143 | "y": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da" 144 | } 145 | }, 146 | { 147 | "description": "G x12", 148 | "input": { 149 | "k": "12", 150 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 151 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 152 | }, 153 | "output": { 154 | "x": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 155 | "y": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13" 156 | } 157 | }, 158 | { 159 | "description": "G x13", 160 | "input": { 161 | "k": "13", 162 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 163 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 164 | }, 165 | "output": { 166 | "x": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 167 | "y": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767" 168 | } 169 | }, 170 | { 171 | "description": "G x14", 172 | "input": { 173 | "k": "14", 174 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 175 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 176 | }, 177 | "output": { 178 | "x": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 179 | "y": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf" 180 | } 181 | }, 182 | { 183 | "description": "G x15", 184 | "input": { 185 | "k": "15", 186 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 187 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 188 | }, 189 | "output": { 190 | "x": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 191 | "y": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989" 192 | } 193 | }, 194 | { 195 | "description": "G x16", 196 | "input": { 197 | "k": "16", 198 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 199 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 200 | }, 201 | "output": { 202 | "x": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 203 | "y": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482" 204 | } 205 | }, 206 | { 207 | "description": "G x17", 208 | "input": { 209 | "k": "17", 210 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 211 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 212 | }, 213 | "output": { 214 | "x": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 215 | "y": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26" 216 | } 217 | }, 218 | { 219 | "description": "G x18", 220 | "input": { 221 | "k": "18", 222 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 223 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 224 | }, 225 | "output": { 226 | "x": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 227 | "y": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002" 228 | } 229 | }, 230 | { 231 | "description": "G x19", 232 | "input": { 233 | "k": "19", 234 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 235 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 236 | }, 237 | "output": { 238 | "x": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 239 | "y": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd" 240 | } 241 | }, 242 | { 243 | "description": "G x20", 244 | "input": { 245 | "k": "20", 246 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 247 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 248 | }, 249 | "output": { 250 | "x": "0xfcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", 251 | "y": "0xd5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530" 252 | } 253 | }, 254 | { 255 | "description": "G x112233445566778899", 256 | "input": { 257 | "k": "112233445566778899", 258 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 259 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 260 | }, 261 | "output": { 262 | "x": "0x61f077c6f62ed802dad7c2f38f5c67f2cc453601e61bd076bb46179e", 263 | "y": "0x2272f9e9f5933e70388ee652513443b5e289dd135dcc0d0299b225e4" 264 | } 265 | }, 266 | { 267 | "description": "G x112233445566778899112233445566778899", 268 | "input": { 269 | "k": "112233445566778899112233445566778899", 270 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 271 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 272 | }, 273 | "output": { 274 | "x": "0x29895f0af496bfc62b6ef8d8a65c88c613949b03668aab4f0429e35", 275 | "y": "0x3ea6e53f9a841f2019ec24bde1a75677aa9b5902e61081c01064de93" 276 | } 277 | }, 278 | { 279 | "description": "G x28948022309329048855892746252171976963209391069768726095651290785379540373584", 280 | "input": { 281 | "k": "28948022309329048855892746252171976963209391069768726095651290785379540373584", 282 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 283 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 284 | }, 285 | "output": { 286 | "x": "0x79ab0b461f29ee3d6979b366941f5f5a55a8efa53db0a6d176f83717", 287 | "y": "0xc67cc88bf10b79cb76f9b4964146c72560a19fd1258574951a13ae50" 288 | } 289 | }, 290 | { 291 | "description": "G x57896044618658097711785492504343953926418782139537452191302581570759080747168", 292 | "input": { 293 | "k": "57896044618658097711785492504343953926418782139537452191302581570759080747168", 294 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 295 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 296 | }, 297 | "output": { 298 | "x": "0xcab2a44808f684c5a66a3661a38ae5fead08f69cff2dd6ed0b97ee", 299 | "y": "0x75be3d6e94b8679b0d20fd6ada5f8004f19cd32b3763e9f91fa9c3f0" 300 | } 301 | }, 302 | { 303 | "description": "G x86844066927987146567678238756515930889628173209306178286953872356138621120752", 304 | "input": { 305 | "k": "86844066927987146567678238756515930889628173209306178286953872356138621120752", 306 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 307 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 308 | }, 309 | "output": { 310 | "x": "0x25981a20c0f6f8a0f4b77019303589ba3da831c7ec7697b5cf87c86c", 311 | "y": "0xb154fa1cd4cb1c42990ecab7882e67b635878dc818111351ada6124f" 312 | } 313 | }, 314 | { 315 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494317", 316 | "input": { 317 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494317", 318 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 319 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 320 | }, 321 | "output": { 322 | "x": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 323 | "y": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72" 324 | } 325 | }, 326 | { 327 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494318", 328 | "input": { 329 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494318", 330 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 331 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 332 | }, 333 | "output": { 334 | "x": "0xebbf4a4adada3f707912bc92e0c00c8a27c48192ba3cf12256609c21", 335 | "y": "0x4e85d4ee0d89242b6f6d7835a0fd6620a919388649572ecc7b65785a" 336 | } 337 | }, 338 | { 339 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494319", 340 | "input": { 341 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494319", 342 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 343 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 344 | }, 345 | "output": { 346 | "x": "0x6957fc9c1f3f40805fbaecbf60139b48bd20f4d695719dec919e136f", 347 | "y": "0xab989a84abf4e28a5df57bc9105e917dfe432d23d277fba506b3ae02" 348 | } 349 | }, 350 | { 351 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494320", 352 | "input": { 353 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494320", 354 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 355 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 356 | }, 357 | "output": { 358 | "x": "0x94e4c0f2ac0396266f423967c7730d317730d7696f3e7720acc96b9b", 359 | "y": "0xc7ae92dbe6a9d78a502c6070234725eef7f099152f10acc2a8e0d5a4" 360 | } 361 | }, 362 | { 363 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494321", 364 | "input": { 365 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494321", 366 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 367 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 368 | }, 369 | "output": { 370 | "x": "0x5b349327e0cc20ebdeb8bb6c25ccadb04a8761d10b190980abd862b2", 371 | "y": "0x8942813c24cc97299a58eb9667eb7986087a1757d69e1189fe1c4108" 372 | } 373 | }, 374 | { 375 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494322", 376 | "input": { 377 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494322", 378 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 379 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 380 | }, 381 | "output": { 382 | "x": "0x43eaba370e2052e64c8e7b14e45eb72015f4e0507b4c0f188d2a33f4", 383 | "y": "0xdcd59302552d1119ea469c5fe7dc4ae024111fa45b597bbf9d97c766" 384 | } 385 | }, 386 | { 387 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494323", 388 | "input": { 389 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494323", 390 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 391 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 392 | }, 393 | "output": { 394 | "x": "0xa38a55ed44ac9a5d4dc4114470b0dcba9f4e13e7b6b2262f40b96dbb", 395 | "y": "0xb1a29e79a3879c9db646992dd5eaf0e86052a9c580cc45def881893a" 396 | } 397 | }, 398 | { 399 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494324", 400 | "input": { 401 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494324", 402 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 403 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 404 | }, 405 | "output": { 406 | "x": "0x299d75e6e4f18fc86d6315369e93d062f9c992878d3a755ba3e54c14", 407 | "y": "0x2048708df0929c0036be899201e66c7902bb474c53f1ea4ad4da064b" 408 | } 409 | }, 410 | { 411 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494325", 412 | "input": { 413 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494325", 414 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 415 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 416 | }, 417 | "output": { 418 | "x": "0x97f256aa8e1b5b17dfbc8aa186a38e02d43fe7923cfcf1f3a51b9844", 419 | "y": "0xd49072d583f2229d06070b33164c73a0ad08c958ff91cf8d80624037" 420 | } 421 | }, 422 | { 423 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494326", 424 | "input": { 425 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494326", 426 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 427 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 428 | }, 429 | "output": { 430 | "x": "0x86c2401095d104f82d3fac6dbf6e217e5a4d034923574b2165b7cd5f", 431 | "y": "0x3db93871ea279252a99be80b530e341ea946b9c49f760d35e517c211" 432 | } 433 | }, 434 | { 435 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494327", 436 | "input": { 437 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494327", 438 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 439 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 440 | }, 441 | "output": { 442 | "x": "0x418b540969bc9b4e5d21893f4355f65b04fa127de999572169a8958d", 443 | "y": "0x4059e62a3ced6d3b4364537c9433aa36c4607f6c27e636be8d9c6f52" 444 | } 445 | }, 446 | { 447 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494328", 448 | "input": { 449 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494328", 450 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 451 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 452 | }, 453 | "output": { 454 | "x": "0x408f278df530b751d08527d7e57e27a0ee18a07b5711d4521fb669ed", 455 | "y": "0xeea174f219d3c6489342668a4daeef12f486246ca0f812a47f8cd9d7" 456 | } 457 | }, 458 | { 459 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494329", 460 | "input": { 461 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494329", 462 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 463 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 464 | }, 465 | "output": { 466 | "x": "0x5dbd3f9fd68d16385a058d0ed6dfbc8b324491a93c064a2fdaeceb51", 467 | "y": "0xd45844409ea2090884fb6b8321cee0e7143fd931e180c214f669778d" 468 | } 469 | }, 470 | { 471 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494330", 472 | "input": { 473 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494330", 474 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 475 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 476 | }, 477 | "output": { 478 | "x": "0x83457971ae964544882f13172f08608130879df2478660c4adbd8ff4", 479 | "y": "0xc67d435042b8dad33cc9614f8ac261ec7877581e79b5395ffd92bc76" 480 | } 481 | }, 482 | { 483 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494331", 484 | "input": { 485 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494331", 486 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 487 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 488 | }, 489 | "output": { 490 | "x": "0x80ee3e89c7f3043a692f3787b630216af55fae6dca4086a8427b92d9", 491 | "y": "0x21314314c1c3c015050939e794440ba79ecc1f84b71e63c942cbca70" 492 | } 493 | }, 494 | { 495 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494332", 496 | "input": { 497 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494332", 498 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 499 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 500 | }, 501 | "output": { 502 | "x": "0xaf12325bd961a7c71dcff63d636ea89d7dce3d8ad72f6967bea3f424", 503 | "y": "0x40ef73372c93d67a48ae79b7501a0c8d4c3b56206cdf18b567f1b133" 504 | } 505 | }, 506 | { 507 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494333", 508 | "input": { 509 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494333", 510 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 511 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 512 | }, 513 | "output": { 514 | "x": "0xac8c71fbc68aa682bbe155f8e3942154bce4ffed0bdaa2c40cb0e2bc", 515 | "y": "0xf7681b3781d38a7aeedfa0a04fc5fe03363b1597f2b10e514fd7647d" 516 | } 517 | }, 518 | { 519 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494334", 520 | "input": { 521 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494334", 522 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 523 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 524 | }, 525 | "output": { 526 | "x": "0xeaa9462a455a2ed184258ea43021814358a1de9e5fae898f5b46d8e", 527 | "y": "0xc5b9b36e633fb4837eebe6aa742df82c0a4a0bc94f2687bcc51d6f16" 528 | } 529 | }, 530 | { 531 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494335", 532 | "input": { 533 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494335", 534 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 535 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 536 | }, 537 | "output": { 538 | "x": "0x372d3f5f289ccb030e84225d424c266cf7df96a100a90fb194f477bd", 539 | "y": "0xfde63f32b477442599692cba69223eb2458c9c78175c69fb8347068" 540 | } 541 | }, 542 | { 543 | "description": "G x115792089237316195423570985008687907852837564279074904382605163141518161494336", 544 | "input": { 545 | "k": "115792089237316195423570985008687907852837564279074904382605163141518161494336", 546 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 547 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 548 | }, 549 | "output": { 550 | "x": "0xe7f7b4538ca84dbe60ab9932ce58fd0ee9d8e5f6cb06562f5bf50c49", 551 | "y": "0x8c9080949d23d1efa60f6ee68611c39aefae8af887f63c986fa337d4" 552 | } 553 | }, 554 | { 555 | "description": "G x77059549740374936337596179780007572461065571555507600191520924336939429631266", 556 | "input": { 557 | "k": "77059549740374936337596179780007572461065571555507600191520924336939429631266", 558 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 559 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 560 | }, 561 | "output": { 562 | "x": "0x7f786de5a63def3495fe980a8db8f2a4fa16ba0026f0457e50214526", 563 | "y": "0xfc4efccffbc143e8f293fdfd466c9bb4c5909e487232abc74d70bf4c" 564 | } 565 | }, 566 | { 567 | "description": "G x32670510020758816978083085130507043184471273380659243275938904335757337482424", 568 | "input": { 569 | "k": "32670510020758816978083085130507043184471273380659243275938904335757337482424", 570 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 571 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 572 | }, 573 | "output": { 574 | "x": "0xb41fdaf50fbfb828a550e38854b3dc33d6ebdb44a3eeb60063294948", 575 | "y": "0x6f97d84d8684714d668e3596d4a1bf378634e73a4fba8edfa66b14ae" 576 | } 577 | } 578 | ], 579 | "invalid": [] 580 | }, 581 | "addition": { 582 | "valid": [ 583 | { 584 | "description": "small scalar 1 xG plus G", 585 | "input": { 586 | "x1": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 587 | "y1": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", 588 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 589 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 590 | }, 591 | "output": { 592 | "x": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 593 | "y": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb" 594 | } 595 | }, 596 | { 597 | "description": "small scalar 2 xG plus G", 598 | "input": { 599 | "x1": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 600 | "y1": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb", 601 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 602 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 603 | }, 604 | "output": { 605 | "x": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 606 | "y": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925" 607 | } 608 | }, 609 | { 610 | "description": "small scalar 3 xG plus G", 611 | "input": { 612 | "x1": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 613 | "y1": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925", 614 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 615 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 616 | }, 617 | "output": { 618 | "x": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 619 | "y": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9" 620 | } 621 | }, 622 | { 623 | "description": "small scalar 4 xG plus G", 624 | "input": { 625 | "x1": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 626 | "y1": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9", 627 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 628 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 629 | }, 630 | "output": { 631 | "x": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 632 | "y": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b" 633 | } 634 | }, 635 | { 636 | "description": "small scalar 5 xG plus G", 637 | "input": { 638 | "x1": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 639 | "y1": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b", 640 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 641 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 642 | }, 643 | "output": { 644 | "x": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 645 | "y": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e" 646 | } 647 | }, 648 | { 649 | "description": "small scalar 6 xG plus G", 650 | "input": { 651 | "x1": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 652 | "y1": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e", 653 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 654 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 655 | }, 656 | "output": { 657 | "x": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 658 | "y": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963" 659 | } 660 | }, 661 | { 662 | "description": "small scalar 7 xG plus G", 663 | "input": { 664 | "x1": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 665 | "y1": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963", 666 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 667 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 668 | }, 669 | "output": { 670 | "x": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 671 | "y": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a" 672 | } 673 | }, 674 | { 675 | "description": "small scalar 8 xG plus G", 676 | "input": { 677 | "x1": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 678 | "y1": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a", 679 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 680 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 681 | }, 682 | "output": { 683 | "x": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 684 | "y": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463" 685 | } 686 | }, 687 | { 688 | "description": "small scalar 9 xG plus G", 689 | "input": { 690 | "x1": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 691 | "y1": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463", 692 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 693 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 694 | }, 695 | "output": { 696 | "x": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 697 | "y": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f" 698 | } 699 | }, 700 | { 701 | "description": "small scalar 10 xG plus G", 702 | "input": { 703 | "x1": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 704 | "y1": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f", 705 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 706 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 707 | }, 708 | "output": { 709 | "x": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 710 | "y": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da" 711 | } 712 | }, 713 | { 714 | "description": "small scalar 11 xG plus G", 715 | "input": { 716 | "x1": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 717 | "y1": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da", 718 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 719 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 720 | }, 721 | "output": { 722 | "x": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 723 | "y": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13" 724 | } 725 | }, 726 | { 727 | "description": "small scalar 12 xG plus G", 728 | "input": { 729 | "x1": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 730 | "y1": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13", 731 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 732 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 733 | }, 734 | "output": { 735 | "x": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 736 | "y": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767" 737 | } 738 | }, 739 | { 740 | "description": "small scalar 13 xG plus G", 741 | "input": { 742 | "x1": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 743 | "y1": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767", 744 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 745 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 746 | }, 747 | "output": { 748 | "x": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 749 | "y": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf" 750 | } 751 | }, 752 | { 753 | "description": "small scalar 14 xG plus G", 754 | "input": { 755 | "x1": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 756 | "y1": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf", 757 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 758 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 759 | }, 760 | "output": { 761 | "x": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 762 | "y": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989" 763 | } 764 | }, 765 | { 766 | "description": "small scalar 15 xG plus G", 767 | "input": { 768 | "x1": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 769 | "y1": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989", 770 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 771 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 772 | }, 773 | "output": { 774 | "x": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 775 | "y": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482" 776 | } 777 | }, 778 | { 779 | "description": "small scalar 16 xG plus G", 780 | "input": { 781 | "x1": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 782 | "y1": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482", 783 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 784 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 785 | }, 786 | "output": { 787 | "x": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 788 | "y": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26" 789 | } 790 | }, 791 | { 792 | "description": "small scalar 17 xG plus G", 793 | "input": { 794 | "x1": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 795 | "y1": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26", 796 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 797 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 798 | }, 799 | "output": { 800 | "x": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 801 | "y": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002" 802 | } 803 | }, 804 | { 805 | "description": "small scalar 18 xG plus G", 806 | "input": { 807 | "x1": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 808 | "y1": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002", 809 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 810 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 811 | }, 812 | "output": { 813 | "x": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 814 | "y": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd" 815 | } 816 | }, 817 | { 818 | "description": "small scalar 19 xG plus G", 819 | "input": { 820 | "x1": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 821 | "y1": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd", 822 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 823 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 824 | }, 825 | "output": { 826 | "x": "0xfcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", 827 | "y": "0xd5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530" 828 | } 829 | }, 830 | { 831 | "description": "big scalar 1 xG plus big scalar 2 xG", 832 | "input": { 833 | "x1": "0x79ab0b461f29ee3d6979b366941f5f5a55a8efa53db0a6d176f83717", 834 | "y1": "0xc67cc88bf10b79cb76f9b4964146c72560a19fd1258574951a13ae50", 835 | "x2": "0xcab2a44808f684c5a66a3661a38ae5fead08f69cff2dd6ed0b97ee", 836 | "y2": "0x75be3d6e94b8679b0d20fd6ada5f8004f19cd32b3763e9f91fa9c3f0" 837 | }, 838 | "output": { 839 | "x": "0x25981a20c0f6f8a0f4b77019303589ba3da831c7ec7697b5cf87c86c", 840 | "y": "0xb154fa1cd4cb1c42990ecab7882e67b635878dc818111351ada6124f" 841 | } 842 | }, 843 | { 844 | "description": "small scalar 1 xG plus big scalar 4 xG", 845 | "input": { 846 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 847 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 848 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 849 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 850 | }, 851 | "output": { 852 | "x": "0xebbf4a4adada3f707912bc92e0c00c8a27c48192ba3cf12256609c21", 853 | "y": "0x4e85d4ee0d89242b6f6d7835a0fd6620a919388649572ecc7b65785a" 854 | } 855 | }, 856 | { 857 | "description": "small scalar 2 xG plus big scalar 4 xG", 858 | "input": { 859 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 860 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 861 | "x2": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 862 | "y2": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb" 863 | }, 864 | "output": { 865 | "x": "0x6957fc9c1f3f40805fbaecbf60139b48bd20f4d695719dec919e136f", 866 | "y": "0xab989a84abf4e28a5df57bc9105e917dfe432d23d277fba506b3ae02" 867 | } 868 | }, 869 | { 870 | "description": "small scalar 3 xG plus big scalar 4 xG", 871 | "input": { 872 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 873 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 874 | "x2": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 875 | "y2": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925" 876 | }, 877 | "output": { 878 | "x": "0x94e4c0f2ac0396266f423967c7730d317730d7696f3e7720acc96b9b", 879 | "y": "0xc7ae92dbe6a9d78a502c6070234725eef7f099152f10acc2a8e0d5a4" 880 | } 881 | }, 882 | { 883 | "description": "small scalar 4 xG plus big scalar 4 xG", 884 | "input": { 885 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 886 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 887 | "x2": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 888 | "y2": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9" 889 | }, 890 | "output": { 891 | "x": "0x5b349327e0cc20ebdeb8bb6c25ccadb04a8761d10b190980abd862b2", 892 | "y": "0x8942813c24cc97299a58eb9667eb7986087a1757d69e1189fe1c4108" 893 | } 894 | }, 895 | { 896 | "description": "small scalar 5 xG plus big scalar 4 xG", 897 | "input": { 898 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 899 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 900 | "x2": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 901 | "y2": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b" 902 | }, 903 | "output": { 904 | "x": "0x43eaba370e2052e64c8e7b14e45eb72015f4e0507b4c0f188d2a33f4", 905 | "y": "0xdcd59302552d1119ea469c5fe7dc4ae024111fa45b597bbf9d97c766" 906 | } 907 | }, 908 | { 909 | "description": "small scalar 6 xG plus big scalar 4 xG", 910 | "input": { 911 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 912 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 913 | "x2": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 914 | "y2": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e" 915 | }, 916 | "output": { 917 | "x": "0xa38a55ed44ac9a5d4dc4114470b0dcba9f4e13e7b6b2262f40b96dbb", 918 | "y": "0xb1a29e79a3879c9db646992dd5eaf0e86052a9c580cc45def881893a" 919 | } 920 | }, 921 | { 922 | "description": "small scalar 7 xG plus big scalar 4 xG", 923 | "input": { 924 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 925 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 926 | "x2": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 927 | "y2": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963" 928 | }, 929 | "output": { 930 | "x": "0x299d75e6e4f18fc86d6315369e93d062f9c992878d3a755ba3e54c14", 931 | "y": "0x2048708df0929c0036be899201e66c7902bb474c53f1ea4ad4da064b" 932 | } 933 | }, 934 | { 935 | "description": "small scalar 8 xG plus big scalar 4 xG", 936 | "input": { 937 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 938 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 939 | "x2": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 940 | "y2": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a" 941 | }, 942 | "output": { 943 | "x": "0x97f256aa8e1b5b17dfbc8aa186a38e02d43fe7923cfcf1f3a51b9844", 944 | "y": "0xd49072d583f2229d06070b33164c73a0ad08c958ff91cf8d80624037" 945 | } 946 | }, 947 | { 948 | "description": "small scalar 9 xG plus big scalar 4 xG", 949 | "input": { 950 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 951 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 952 | "x2": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 953 | "y2": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463" 954 | }, 955 | "output": { 956 | "x": "0x86c2401095d104f82d3fac6dbf6e217e5a4d034923574b2165b7cd5f", 957 | "y": "0x3db93871ea279252a99be80b530e341ea946b9c49f760d35e517c211" 958 | } 959 | }, 960 | { 961 | "description": "small scalar 10 xG plus big scalar 4 xG", 962 | "input": { 963 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 964 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 965 | "x2": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 966 | "y2": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f" 967 | }, 968 | "output": { 969 | "x": "0x418b540969bc9b4e5d21893f4355f65b04fa127de999572169a8958d", 970 | "y": "0x4059e62a3ced6d3b4364537c9433aa36c4607f6c27e636be8d9c6f52" 971 | } 972 | }, 973 | { 974 | "description": "small scalar 11 xG plus big scalar 4 xG", 975 | "input": { 976 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 977 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 978 | "x2": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 979 | "y2": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da" 980 | }, 981 | "output": { 982 | "x": "0x408f278df530b751d08527d7e57e27a0ee18a07b5711d4521fb669ed", 983 | "y": "0xeea174f219d3c6489342668a4daeef12f486246ca0f812a47f8cd9d7" 984 | } 985 | }, 986 | { 987 | "description": "small scalar 12 xG plus big scalar 4 xG", 988 | "input": { 989 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 990 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 991 | "x2": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 992 | "y2": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13" 993 | }, 994 | "output": { 995 | "x": "0x5dbd3f9fd68d16385a058d0ed6dfbc8b324491a93c064a2fdaeceb51", 996 | "y": "0xd45844409ea2090884fb6b8321cee0e7143fd931e180c214f669778d" 997 | } 998 | }, 999 | { 1000 | "description": "small scalar 13 xG plus big scalar 4 xG", 1001 | "input": { 1002 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1003 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1004 | "x2": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 1005 | "y2": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767" 1006 | }, 1007 | "output": { 1008 | "x": "0x83457971ae964544882f13172f08608130879df2478660c4adbd8ff4", 1009 | "y": "0xc67d435042b8dad33cc9614f8ac261ec7877581e79b5395ffd92bc76" 1010 | } 1011 | }, 1012 | { 1013 | "description": "small scalar 14 xG plus big scalar 4 xG", 1014 | "input": { 1015 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1016 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1017 | "x2": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 1018 | "y2": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf" 1019 | }, 1020 | "output": { 1021 | "x": "0x80ee3e89c7f3043a692f3787b630216af55fae6dca4086a8427b92d9", 1022 | "y": "0x21314314c1c3c015050939e794440ba79ecc1f84b71e63c942cbca70" 1023 | } 1024 | }, 1025 | { 1026 | "description": "small scalar 15 xG plus big scalar 4 xG", 1027 | "input": { 1028 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1029 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1030 | "x2": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 1031 | "y2": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989" 1032 | }, 1033 | "output": { 1034 | "x": "0xaf12325bd961a7c71dcff63d636ea89d7dce3d8ad72f6967bea3f424", 1035 | "y": "0x40ef73372c93d67a48ae79b7501a0c8d4c3b56206cdf18b567f1b133" 1036 | } 1037 | }, 1038 | { 1039 | "description": "small scalar 16 xG plus big scalar 4 xG", 1040 | "input": { 1041 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1042 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1043 | "x2": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 1044 | "y2": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482" 1045 | }, 1046 | "output": { 1047 | "x": "0xac8c71fbc68aa682bbe155f8e3942154bce4ffed0bdaa2c40cb0e2bc", 1048 | "y": "0xf7681b3781d38a7aeedfa0a04fc5fe03363b1597f2b10e514fd7647d" 1049 | } 1050 | }, 1051 | { 1052 | "description": "small scalar 17 xG plus big scalar 4 xG", 1053 | "input": { 1054 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1055 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1056 | "x2": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 1057 | "y2": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26" 1058 | }, 1059 | "output": { 1060 | "x": "0xeaa9462a455a2ed184258ea43021814358a1de9e5fae898f5b46d8e", 1061 | "y": "0xc5b9b36e633fb4837eebe6aa742df82c0a4a0bc94f2687bcc51d6f16" 1062 | } 1063 | }, 1064 | { 1065 | "description": "small scalar 18 xG plus big scalar 4 xG", 1066 | "input": { 1067 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1068 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1069 | "x2": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 1070 | "y2": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002" 1071 | }, 1072 | "output": { 1073 | "x": "0x372d3f5f289ccb030e84225d424c266cf7df96a100a90fb194f477bd", 1074 | "y": "0xfde63f32b477442599692cba69223eb2458c9c78175c69fb8347068" 1075 | } 1076 | }, 1077 | { 1078 | "description": "small scalar 19 xG plus big scalar 4 xG", 1079 | "input": { 1080 | "x1": "0x8af4e39e11185181f9ca2a386b326cb8a2ee087b401efaf6994cc093", 1081 | "y1": "0x4eda87ef10316875b42bf8a9e7befdf5755accae057ec66cece5fa72", 1082 | "x2": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 1083 | "y2": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd" 1084 | }, 1085 | "output": { 1086 | "x": "0xe7f7b4538ca84dbe60ab9932ce58fd0ee9d8e5f6cb06562f5bf50c49", 1087 | "y": "0x8c9080949d23d1efa60f6ee68611c39aefae8af887f63c986fa337d4" 1088 | } 1089 | } 1090 | ], 1091 | "invalid": [] 1092 | }, 1093 | "subtraction": { 1094 | "valid": [ 1095 | { 1096 | "description": "small scalar 5 xG minus G", 1097 | "input": { 1098 | "x1": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 1099 | "y1": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb", 1100 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1101 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1102 | }, 1103 | "output": { 1104 | "x": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1105 | "y": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1106 | } 1107 | }, 1108 | { 1109 | "description": "small scalar 6 xG minus G", 1110 | "input": { 1111 | "x1": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 1112 | "y1": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925", 1113 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1114 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1115 | }, 1116 | "output": { 1117 | "x": "0x706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6", 1118 | "y": "0x1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb" 1119 | } 1120 | }, 1121 | { 1122 | "description": "small scalar 7 xG minus G", 1123 | "input": { 1124 | "x1": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 1125 | "y1": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9", 1126 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1127 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1128 | }, 1129 | "output": { 1130 | "x": "0xdf1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04", 1131 | "y": "0xa3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925" 1132 | } 1133 | }, 1134 | { 1135 | "description": "small scalar 8 xG minus G", 1136 | "input": { 1137 | "x1": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 1138 | "y1": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b", 1139 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1140 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1141 | }, 1142 | "output": { 1143 | "x": "0xae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301", 1144 | "y": "0x482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9" 1145 | } 1146 | }, 1147 | { 1148 | "description": "small scalar 9 xG minus G", 1149 | "input": { 1150 | "x1": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 1151 | "y1": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e", 1152 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1153 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1154 | }, 1155 | "output": { 1156 | "x": "0x31c49ae75bce7807cdff22055d94ee9021fedbb5ab51c57526f011aa", 1157 | "y": "0x27e8bff1745635ec5ba0c9f1c2ede15414c6507d29ffe37e790a079b" 1158 | } 1159 | }, 1160 | { 1161 | "description": "small scalar 10 xG minus G", 1162 | "input": { 1163 | "x1": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 1164 | "y1": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963", 1165 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1166 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1167 | }, 1168 | "output": { 1169 | "x": "0x1f2483f82572251fca975fea40db821df8ad82a3c002ee6c57112408", 1170 | "y": "0x89faf0ccb750d99b553c574fad7ecfb0438586eb3952af5b4b153c7e" 1171 | } 1172 | }, 1173 | { 1174 | "description": "small scalar 11 xG minus G", 1175 | "input": { 1176 | "x1": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 1177 | "y1": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a", 1178 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1179 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1180 | }, 1181 | "output": { 1182 | "x": "0xdb2f6be630e246a5cf7d99b85194b123d487e2d466b94b24a03c3e28", 1183 | "y": "0xf3a30085497f2f611ee2517b163ef8c53b715d18bb4e4808d02b963" 1184 | } 1185 | }, 1186 | { 1187 | "description": "small scalar 12 xG minus G", 1188 | "input": { 1189 | "x1": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 1190 | "y1": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463", 1191 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1192 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1193 | }, 1194 | "output": { 1195 | "x": "0x858e6f9cc6c12c31f5df124aa77767b05c8bc021bd683d2b55571550", 1196 | "y": "0x46dcd3ea5c43898c5c5fc4fdac7db39c2f02ebee4e3541d1e78047a" 1197 | } 1198 | }, 1199 | { 1200 | "description": "small scalar 13 xG minus G", 1201 | "input": { 1202 | "x1": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 1203 | "y1": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f", 1204 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1205 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1206 | }, 1207 | "output": { 1208 | "x": "0x2fdcccfee720a77ef6cb3bfbb447f9383117e3daa4a07e36ed15f78d", 1209 | "y": "0x371732e4f41bf4f7883035e6a79fcedc0e196eb07b48171697517463" 1210 | } 1211 | }, 1212 | { 1213 | "description": "small scalar 14 xG minus G", 1214 | "input": { 1215 | "x1": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 1216 | "y1": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da", 1217 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1218 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1219 | }, 1220 | "output": { 1221 | "x": "0xaea9e17a306517eb89152aa7096d2c381ec813c51aa880e7bee2c0fd", 1222 | "y": "0x39bb30eab337e0a521b6cba1abe4b2b3a3e524c14a3fe3eb116b655f" 1223 | } 1224 | }, 1225 | { 1226 | "description": "small scalar 15 xG minus G", 1227 | "input": { 1228 | "x1": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 1229 | "y1": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13", 1230 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1231 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1232 | }, 1233 | "output": { 1234 | "x": "0xef53b6294aca431f0f3c22dc82eb9050324f1d88d377e716448e507c", 1235 | "y": "0x20b510004092e96636cfb7e32efded8265c266dfb754fa6d6491a6da" 1236 | } 1237 | }, 1238 | { 1239 | "description": "small scalar 16 xG minus G", 1240 | "input": { 1241 | "x1": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 1242 | "y1": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767", 1243 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1244 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1245 | }, 1246 | "output": { 1247 | "x": "0x6e31ee1dc137f81b056752e4deab1443a481033e9b4c93a3044f4f7a", 1248 | "y": "0x207dddf0385bfdeab6e9acda8da06b3bbef224a93ab1e9e036109d13" 1249 | } 1250 | }, 1251 | { 1252 | "description": "small scalar 17 xG minus G", 1253 | "input": { 1254 | "x1": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 1255 | "y1": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf", 1256 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1257 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1258 | }, 1259 | "output": { 1260 | "x": "0x34e8e17a430e43289793c383fac9774247b40e9ebd3366981fcfaeca", 1261 | "y": "0x252819f71c7fb7fbcb159be337d37d3336d7feb963724fdfb0ecb767" 1262 | } 1263 | }, 1264 | { 1265 | "description": "small scalar 18 xG minus G", 1266 | "input": { 1267 | "x1": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 1268 | "y1": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989", 1269 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1270 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1271 | }, 1272 | "output": { 1273 | "x": "0xa53640c83dc208603ded83e4ecf758f24c357d7cf48088b2ce01e9fa", 1274 | "y": "0xd5814cd724199c4a5b974a43685fbf5b8bac69459c9469bc8f23ccaf" 1275 | } 1276 | }, 1277 | { 1278 | "description": "small scalar 19 xG minus G", 1279 | "input": { 1280 | "x1": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 1281 | "y1": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482", 1282 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1283 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1284 | }, 1285 | "output": { 1286 | "x": "0xbaa4d8635511a7d288aebeedd12ce529ff102c91f97f867e21916bf9", 1287 | "y": "0x979a5f4759f80f4fb4ec2e34f5566d595680a11735e7b61046127989" 1288 | } 1289 | }, 1290 | { 1291 | "description": "small scalar 20 xG minus G", 1292 | "input": { 1293 | "x1": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 1294 | "y1": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26", 1295 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1296 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1297 | }, 1298 | "output": { 1299 | "x": "0xb6ec4fe1777382404ef679997ba8d1cc5cd8e85349259f590c4c66d", 1300 | "y": "0x3399d464345906b11b00e363ef429221f2ec720d2f665d7dead5b482" 1301 | } 1302 | }, 1303 | { 1304 | "description": "small scalar 21 xG minus G", 1305 | "input": { 1306 | "x1": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 1307 | "y1": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002", 1308 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1309 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1310 | }, 1311 | "output": { 1312 | "x": "0xb8357c3a6ceef288310e17b8bfeff9200846ca8c1942497c484403bc", 1313 | "y": "0xff149efa6606a6bd20ef7d1b06bd92f6904639dce5174db6cc554a26" 1314 | } 1315 | }, 1316 | { 1317 | "description": "small scalar 22 xG minus G", 1318 | "input": { 1319 | "x1": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 1320 | "y1": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd", 1321 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1322 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1323 | }, 1324 | "output": { 1325 | "x": "0xc9ff61b040874c0568479216824a15eab1a838a797d189746226e4cc", 1326 | "y": "0xea98d60e5ffc9b8fcf999fab1df7e7ef7084f20ddb61bb045a6ce002" 1327 | } 1328 | }, 1329 | { 1330 | "description": "small scalar 23 xG minus G", 1331 | "input": { 1332 | "x1": "0xfcc7f2b45df1cd5a3c0c0731ca47a8af75cfb0347e8354eefe782455", 1333 | "y1": "0xd5d7110274cba7cdee90e1a8b0d394c376a5573db6be0bf2747f530", 1334 | "x2": "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", 1335 | "y2": "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" 1336 | }, 1337 | "output": { 1338 | "x": "0xa1e81c04f30ce201c7c9ace785ed44cc33b455a022f2acdbc6cae83c", 1339 | "y": "0xdcf1f6c3db09c70acc25391d492fe25b4a180babd6cea356c04719cd" 1340 | } 1341 | } 1342 | ], 1343 | "invalid": [] 1344 | }, 1345 | "mulAddMul": { 1346 | "valid": [], 1347 | "invalid": [] 1348 | }, 1349 | "decomposeScalar": { 1350 | "valid": [], 1351 | "invalid": [] 1352 | }, 1353 | "simMul": { 1354 | "valid": [], 1355 | "invalid": [] 1356 | } 1357 | } -------------------------------------------------------------------------------- /test/data/P256-aux.json: -------------------------------------------------------------------------------- 1 | { 2 | "params": { 3 | "gx": "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 4 | "gy": "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 5 | "pp": "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 6 | "nn": "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 7 | "aa": "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 8 | "bb": "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b" 9 | }, 10 | "toAffine": { 11 | "valid": [ 12 | { 13 | "input": { 14 | "x": "0x88E6BB871813A28C4E9AFDCD94B79D85DE4794A3C4695B311FB3C7EF1CECE619", 15 | "y": "0x3D709DD3A0B3293201BCEE8E02249399DB3C130F2642C8F954417DC639ADDD22", 16 | "z": "0xEEEAA21B71DA080527B358D3EE861B774FB5BCC79D304533C096F3A44F0E7A2" 17 | }, 18 | "output": { 19 | "x": "0xE2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", 20 | "y": "0xE0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6" 21 | } 22 | } 23 | ] 24 | }, 25 | "invMod": { 26 | "valid": [ 27 | { 28 | "description": "1, pp", 29 | "input": { 30 | "k": "1" 31 | }, 32 | "output": { 33 | "k": "1" 34 | } 35 | }, 36 | { 37 | "description": "k, pp", 38 | "input": { 39 | "k": "71131047696589954191631680573398728609344574897947288563661795659842666029638" 40 | }, 41 | "output": { 42 | "k": "75881117857300922090859164656390883038744552631631346740125228215921778111342" 43 | } 44 | }, 45 | { 46 | "description": "inv(k), pp", 47 | "input": { 48 | "k": "75881117857300922090859164656390883038744552631631346740125228215921778111342" 49 | }, 50 | "output": { 51 | "k": "71131047696589954191631680573398728609344574897947288563661795659842666029638" 52 | } 53 | } 54 | ], 55 | "invalid": [ 56 | { 57 | "description": "0, pp", 58 | "input": { 59 | "k": "0", 60 | "mod": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" 61 | }, 62 | "output": { 63 | "error": "Invalid number" 64 | } 65 | }, 66 | { 67 | "description": "pp, pp", 68 | "input": { 69 | "k": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 70 | "mod": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" 71 | }, 72 | "output": { 73 | "error": "Invalid number" 74 | } 75 | }, 76 | { 77 | "description": "pp, 0", 78 | "input": { 79 | "k": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 80 | "mod": "0" 81 | }, 82 | "output": { 83 | "error": "Invalid number" 84 | } 85 | } 86 | ] 87 | }, 88 | "expMod": { 89 | "valid": [ 90 | { 91 | "description": "base 0", 92 | "input": { 93 | "base": "0", 94 | "exp": "1" 95 | }, 96 | "output": { 97 | "k": "0" 98 | } 99 | }, 100 | { 101 | "description": "exp 0 and base not 0", 102 | "input": { 103 | "base": "1", 104 | "exp": "0" 105 | }, 106 | "output": { 107 | "k": "1" 108 | } 109 | } 110 | ] 111 | }, 112 | "deriveY": { 113 | "valid": [ 114 | { 115 | "input": { 116 | "sign": "0x03", 117 | "x": "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296" 118 | }, 119 | "output": { 120 | "y": "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" 121 | } 122 | } 123 | ] 124 | }, 125 | "isOnCurve": { 126 | "valid": [ 127 | { 128 | "input": { 129 | "x": "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 130 | "y": "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" 131 | }, 132 | "output": { 133 | "isOnCurve": true 134 | } 135 | }, 136 | { 137 | "input": { 138 | "x": "0x6B17D1F3E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 139 | "y": "0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" 140 | }, 141 | "output": { 142 | "isOnCurve": false 143 | } 144 | } 145 | ] 146 | }, 147 | "invertPoint": { 148 | "valid": [ 149 | { 150 | "input": { 151 | "x": "0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", 152 | "y": "0x07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1" 153 | }, 154 | "output": { 155 | "x": "0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", 156 | "y": "0xF888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E" 157 | } 158 | } 159 | ] 160 | } 161 | } -------------------------------------------------------------------------------- /test/data/secp256k1-aux.json: -------------------------------------------------------------------------------- 1 | { 2 | "params": { 3 | "gx": "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 4 | "gy": "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", 5 | "pp": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 6 | "nn": "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 7 | "aa": "0x0", 8 | "bb": "0x7", 9 | "lambda": "0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 10 | "beta": "0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee" 11 | }, 12 | "toAffine": { 13 | "valid": [ 14 | { 15 | "input": { 16 | "x": "0x7D152C041EA8E1DC2191843D1FA9DB55B68F88FEF695E2C791D40444B365AFC2", 17 | "y": "0x56915849F52CC8F76F5FD7E4BF60DB4A43BF633E1B1383F85FE89164BFADCBDB", 18 | "z": "0x9075B4EE4D4788CABB49F7F81C221151FA2F68914D0AA833388FA11FF621A970" 19 | }, 20 | "output": { 21 | "x": "0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5", 22 | "y": "0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A" 23 | } 24 | } 25 | ] 26 | }, 27 | "invMod": { 28 | "valid": [ 29 | { 30 | "description": "1, pp", 31 | "input": { 32 | "k": "1" 33 | }, 34 | "output": { 35 | "k": "1" 36 | } 37 | }, 38 | { 39 | "description": "k, pp", 40 | "input": { 41 | "k": "71131047696589954191631680573398728609344574897947288563661795659842666029638" 42 | }, 43 | "output": { 44 | "k": "57176992357862496962988842880061836337889463570480608132525303518135191486668" 45 | } 46 | }, 47 | { 48 | "description": "inv(k), pp", 49 | "input": { 50 | "k": "57176992357862496962988842880061836337889463570480608132525303518135191486668" 51 | }, 52 | "output": { 53 | "k": "71131047696589954191631680573398728609344574897947288563661795659842666029638" 54 | } 55 | } 56 | ], 57 | "invalid": [ 58 | { 59 | "description": "0, pp", 60 | "input": { 61 | "k": "0", 62 | "mod": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" 63 | }, 64 | "output": { 65 | "error": "Invalid number" 66 | } 67 | }, 68 | { 69 | "description": "pp, pp", 70 | "input": { 71 | "k": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 72 | "mod": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" 73 | }, 74 | "output": { 75 | "error": "Invalid number" 76 | } 77 | }, 78 | { 79 | "description": "pp, 0", 80 | "input": { 81 | "k": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 82 | "mod": "0" 83 | }, 84 | "output": { 85 | "error": "Invalid number" 86 | } 87 | } 88 | ] 89 | }, 90 | "expMod": { 91 | "valid": [ 92 | { 93 | "description": "base 0", 94 | "input": { 95 | "base": "0", 96 | "exp": "1" 97 | }, 98 | "output": { 99 | "k": "0" 100 | } 101 | }, 102 | { 103 | "description": "exp 0 and base not 0", 104 | "input": { 105 | "base": "1", 106 | "exp": "0" 107 | }, 108 | "output": { 109 | "k": "1" 110 | } 111 | } 112 | ] 113 | }, 114 | "deriveY": { 115 | "valid": [ 116 | { 117 | "input": { 118 | "sign": "0x03", 119 | "x": "0xc2704fed5dc41d3979235b85edda8f86f1806c17ce0a516a034c605d2b4f9a26" 120 | }, 121 | "output": { 122 | "y": "0x6970c3dd18910d09250143db08fed1065a522403df0c204ed240a07d123b29d5" 123 | } 124 | } 125 | ] 126 | }, 127 | "isOnCurve": { 128 | "valid": [ 129 | { 130 | "input": { 131 | "x": "0xe906a3b4379ddbff598994b2ff026766fb66424710776099b85111f23f8eebcc", 132 | "y": "0x7638965bf85f5f2b6641324389ef2ffb99576ba72ec19d8411a5ea1dd251b112" 133 | }, 134 | "output": { 135 | "isOnCurve": true 136 | } 137 | }, 138 | { 139 | "input": { 140 | "x": "0x3bf754f48bc7c5fb077736c7d2abe85354be649caa94971f907b3a81759e5b5e", 141 | "y": "0x6b936ce0a2a40016bbb2eb0a4a1347b5af76a41d44b56dec26108269a45bce78" 142 | }, 143 | "output": { 144 | "isOnCurve": false 145 | } 146 | }, 147 | { 148 | "input": { 149 | "x": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", 150 | "y": "0x7638965bf85f5f2b6641324389ef2ffb99576ba72ec19d8411a5ea1dd251b112" 151 | }, 152 | "output": { 153 | "isOnCurve": false 154 | } 155 | }, 156 | { 157 | "input": { 158 | "x": "0x3bf754f48bc7c5fb077736c7d2abe85354be649caa94971f907b3a81759e5b5e", 159 | "y": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30" 160 | }, 161 | "output": { 162 | "isOnCurve": false 163 | } 164 | }, 165 | { 166 | "input": { 167 | "x": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 168 | "y": "0x7638965bf85f5f2b6641324389ef2ffb99576ba72ec19d8411a5ea1dd251b112" 169 | }, 170 | "output": { 171 | "isOnCurve": false 172 | } 173 | }, 174 | { 175 | "input": { 176 | "x": "0x3bf754f48bc7c5fb077736c7d2abe85354be649caa94971f907b3a81759e5b5e", 177 | "y": "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" 178 | }, 179 | "output": { 180 | "isOnCurve": false 181 | } 182 | } 183 | ] 184 | }, 185 | "invertPoint": { 186 | "valid": [ 187 | { 188 | "input": { 189 | "x": "0x1c2a90c4c30f60e878d1fe317acf4f2e059300e3deaa1c949628096ecaf993b2", 190 | "y": "0x9d42bf0c35d765c2242712205e8f8b1ea588f470a6980b21bc9efb4ab33ae246" 191 | }, 192 | "output": { 193 | "x": "0x1c2a90c4c30f60e878d1fe317acf4f2e059300e3deaa1c949628096ecaf993b2", 194 | "y": "0x62bd40f3ca289a3ddbd8eddfa17074e15a770b8f5967f4de436104b44cc519e9" 195 | } 196 | } 197 | ] 198 | } 199 | } -------------------------------------------------------------------------------- /test/ellipticCurve.js: -------------------------------------------------------------------------------- 1 | const EllipticCurve = artifacts.require("./TestEllipticCurve") 2 | 3 | contract("EllipticCurve", accounts => { 4 | // /////////////////////////////////////////// // 5 | // Check auxiliary operations for given curves // 6 | // /////////////////////////////////////////// // 7 | const auxCurves = ["secp256k1", "P256"] 8 | 9 | for (const curve of auxCurves) { 10 | describe(`Aux. operations - Curve ${curve}`, () => { 11 | const curveData = require(`./data/${curve}-aux.json`) 12 | 13 | const pp = web3.utils.toBN(curveData.params.pp) 14 | const aa = web3.utils.toBN(curveData.params.aa) 15 | const bb = web3.utils.toBN(curveData.params.bb) 16 | 17 | let ecLib 18 | before(async () => { 19 | ecLib = await EllipticCurve.new() 20 | }) 21 | 22 | // toAffine 23 | for (const [index, test] of curveData.toAffine.valid.entries()) { 24 | it(`should convert a Jacobian point to affine (${index + 1})`, async () => { 25 | const affine = await ecLib.toAffine.call( 26 | web3.utils.toBN(test.input.x), 27 | web3.utils.toBN(test.input.y), 28 | web3.utils.toBN(test.input.z), 29 | pp 30 | ) 31 | const expectedX = web3.utils.toBN(test.output.x) 32 | const expectedY = web3.utils.toBN(test.output.y) 33 | assert.equal(affine[0].toString(), expectedX.toString()) 34 | assert.equal(affine[1].toString(), expectedY.toString()) 35 | }) 36 | } 37 | 38 | // invMod 39 | for (const [index, test] of curveData.invMod.valid.entries()) { 40 | it(`should invert a scalar (${index + 1}) - ${test.description}`, async () => { 41 | const inv = await ecLib.invMod.call( 42 | web3.utils.toBN(test.input.k), 43 | pp, 44 | ) 45 | assert.equal(inv.toString(), test.output.k) 46 | }) 47 | } 48 | 49 | // invMod - invalid inputs 50 | for (const [index, test] of curveData.invMod.invalid.entries()) { 51 | it(`should fail when inverting with invalid inputs (${index + 1}) - ${test.description}`, async () => { 52 | try { 53 | await ecLib.invMod.call( 54 | web3.utils.toBN(test.input.k), 55 | web3.utils.toBN(test.input.mod), 56 | ) 57 | } catch (error) { 58 | assert(error, test.output.error) 59 | } 60 | }) 61 | } 62 | 63 | // expMod 64 | for (const [index, test] of curveData.expMod.valid.entries()) { 65 | it(`should do an expMod with ${test.description} - (${index + 1})`, async () => { 66 | const exp = await ecLib.expMod.call( 67 | web3.utils.toBN(test.input.base), 68 | web3.utils.toBN(test.input.exp), 69 | pp, 70 | ) 71 | assert.equal(exp.toString(), test.output.k) 72 | }) 73 | } 74 | 75 | // deriveY 76 | for (const [index, test] of curveData.deriveY.valid.entries()) { 77 | it(`should decode coordinate y from compressed point (${index + 1})`, async () => { 78 | const coordY = await ecLib.deriveY.call( 79 | web3.utils.hexToBytes(test.input.sign), 80 | web3.utils.hexToBytes(test.input.x), 81 | aa, 82 | bb, 83 | pp 84 | ) 85 | assert.equal(web3.utils.numberToHex(coordY), test.output.y) 86 | }) 87 | } 88 | 89 | // isOnCurve 90 | for (const [index, test] of curveData.isOnCurve.valid.entries()) { 91 | it(`should identify if point is on the curve (${index + 1}) - ${test.output.isOnCurve}`, async () => { 92 | assert.equal( 93 | await ecLib.isOnCurve.call( 94 | web3.utils.hexToBytes(test.input.x), 95 | web3.utils.hexToBytes(test.input.y), 96 | aa, 97 | bb, 98 | pp), 99 | test.output.isOnCurve 100 | ) 101 | }) 102 | } 103 | 104 | // invertPoint 105 | for (const [index, test] of curveData.invertPoint.valid.entries()) { 106 | it(`should invert an EC point (${index + 1})`, async () => { 107 | const invertedPoint = await ecLib.ecInv.call( 108 | web3.utils.hexToBytes(test.input.x), 109 | web3.utils.hexToBytes(test.input.y), 110 | pp 111 | ) 112 | const expectedX = web3.utils.toBN(test.output.x) 113 | const expectedY = web3.utils.toBN(test.output.y) 114 | assert.equal(invertedPoint[0].toString(), expectedX.toString()) 115 | assert.equal(invertedPoint[1].toString(), expectedY.toString()) 116 | }) 117 | } 118 | }) 119 | } 120 | 121 | // /////////////////////////////////////////////// // 122 | // Check EC arithmetic operations for given curves // 123 | // /////////////////////////////////////////////// // 124 | const curves = ["secp256k1", "secp192k1", "secp224k1", "P256", "P192", "P224"] 125 | 126 | for (const curve of curves) { 127 | describe(`Arithmetic operations - Curve ${curve}`, () => { 128 | const curveData = require(`./data/${curve}.json`) 129 | 130 | const pp = web3.utils.toBN(curveData.params.pp) 131 | const aa = web3.utils.toBN(curveData.params.aa) 132 | 133 | let ecLib 134 | before(async () => { 135 | ecLib = await EllipticCurve.new() 136 | }) 137 | 138 | // Addition 139 | for (const [index, test] of curveData.addition.valid.entries()) { 140 | it(`should add two numbers (${index + 1}) - ${test.description}`, async () => { 141 | const res = await ecLib.ecAdd.call( 142 | web3.utils.toBN(test.input.x1), 143 | web3.utils.toBN(test.input.y1), 144 | web3.utils.toBN(test.input.x2), 145 | web3.utils.toBN(test.input.y2), 146 | aa, 147 | pp 148 | ) 149 | const expectedSumX = web3.utils.toBN(test.output.x) 150 | const expectedSumZ = web3.utils.toBN(test.output.y) 151 | assert.equal(res[0].toString(10), expectedSumX.toString()) 152 | assert.equal(res[1].toString(10), expectedSumZ.toString()) 153 | }) 154 | } 155 | 156 | // Subtraction 157 | for (const [index, test] of curveData.subtraction.valid.entries()) { 158 | it(`should subtract two numbers (${index + 1}) - ${test.description}`, async () => { 159 | const res = await ecLib.ecSub.call( 160 | web3.utils.toBN(test.input.x1), 161 | web3.utils.toBN(test.input.y1), 162 | web3.utils.toBN(test.input.x2), 163 | web3.utils.toBN(test.input.y2), 164 | aa, 165 | pp 166 | ) 167 | const expectedSubX = web3.utils.toBN(test.output.x) 168 | const expectedSubY = web3.utils.toBN(test.output.y) 169 | assert.equal(res[0].toString(10), expectedSubX.toString()) 170 | assert.equal(res[1].toString(10), expectedSubY.toString()) 171 | }) 172 | } 173 | 174 | // Multiplication 175 | for (const [index, test] of curveData.multiplication.valid.entries()) { 176 | it(`should multiply EC points (${index + 1}) - ${test.description}`, async () => { 177 | const res = await ecLib.ecMul.call( 178 | web3.utils.toBN(test.input.k), 179 | web3.utils.toBN(test.input.x), 180 | web3.utils.toBN(test.input.y), 181 | aa, 182 | pp 183 | ) 184 | const expectedMulX = web3.utils.toBN(test.output.x) 185 | const expectedMulY = web3.utils.toBN(test.output.y) 186 | assert.equal(res[0].toString(10), expectedMulX.toString()) 187 | assert.equal(res[1].toString(10), expectedMulY.toString()) 188 | }) 189 | } 190 | }) 191 | } 192 | }) 193 | -------------------------------------------------------------------------------- /test/fastEcMul.js: -------------------------------------------------------------------------------- 1 | const EllipticCurve = artifacts.require("./TestEllipticCurve") 2 | 3 | contract("FastEcMul", accounts => { 4 | const curves = ["secp256k1", "secp192k1", "secp224k1", "P256", "P192", "P224"] 5 | 6 | for (const curve of curves) { 7 | describe(`Arithmetic operations - Curve ${curve}`, () => { 8 | const curveData = require(`./data/${curve}.json`) 9 | 10 | const pp = web3.utils.toBN(curveData.params.pp) 11 | const nn = web3.utils.toBN(curveData.params.nn) 12 | const aa = web3.utils.toBN(curveData.params.aa) 13 | const lambda = web3.utils.toBN(curveData.params.lambda) 14 | const beta = web3.utils.toBN(curveData.params.beta) 15 | 16 | let fastEcMul 17 | before(async () => { 18 | fastEcMul = await EllipticCurve.new() 19 | }) 20 | 21 | // Scalar decomposition 22 | for (const [index, test] of curveData.decomposeScalar.valid.entries()) { 23 | it(`should decompose an scalar (${index + 1}) - ${test.description}`, async () => { 24 | const res = await fastEcMul.decomposeScalar.call( 25 | web3.utils.toBN(test.input.k), 26 | nn, 27 | lambda) 28 | const expectedK1 = web3.utils.toBN(test.output.k1) 29 | const expectedK2 = web3.utils.toBN(test.output.k2) 30 | assert.equal(res[0].toString(10), expectedK1.toString()) 31 | assert.equal(res[1].toString(10), expectedK2.toString()) 32 | }) 33 | } 34 | 35 | // Simultaneous multiplication 36 | for (const [index, test] of curveData.simMul.valid.entries()) { 37 | it(`should do a simultaneous multiplication (${index + 1}) - ${test.description}`, async () => { 38 | const res = await fastEcMul.ecSimMul.call( 39 | [ 40 | web3.utils.toBN(test.input.k1), 41 | web3.utils.toBN(test.input.k2), 42 | web3.utils.toBN(test.input.l1), 43 | web3.utils.toBN(test.input.l2), 44 | ], 45 | [ 46 | web3.utils.toBN(test.input.px), 47 | web3.utils.toBN(test.input.py), 48 | web3.utils.toBN(test.input.qx), 49 | web3.utils.toBN(test.input.qy), 50 | ], 51 | aa, 52 | beta, 53 | pp 54 | ) 55 | const expectedMulX = web3.utils.toBN(test.output.x) 56 | const expectedMulY = web3.utils.toBN(test.output.y) 57 | assert.equal(res[0].toString(10), expectedMulX.toString()) 58 | assert.equal(res[1].toString(10), expectedMulY.toString()) 59 | }) 60 | } 61 | 62 | // MulAddMul 63 | for (const [index, test] of curveData.mulAddMul.valid.entries()) { 64 | it(`should do decompose scalar and simult. multiplication (${index + 1}) - ${test.description}`, async () => { 65 | const k = await fastEcMul.decomposeScalar.call( 66 | web3.utils.toBN(test.input.k), 67 | nn, 68 | lambda) 69 | const l = await fastEcMul.decomposeScalar.call( 70 | web3.utils.toBN(test.input.l), 71 | nn, 72 | lambda) 73 | const res = await fastEcMul.ecSimMul.call( 74 | [ 75 | web3.utils.toBN(k[0]), 76 | web3.utils.toBN(k[1]), 77 | web3.utils.toBN(l[0]), 78 | web3.utils.toBN(l[1]), 79 | ], 80 | [ 81 | web3.utils.toBN(test.input.px), 82 | web3.utils.toBN(test.input.py), 83 | web3.utils.toBN(test.input.qx), 84 | web3.utils.toBN(test.input.qy), 85 | ], 86 | aa, 87 | beta, 88 | pp 89 | ) 90 | const expectedMulX = web3.utils.toBN(test.output.x) 91 | const expectedMulY = web3.utils.toBN(test.output.y) 92 | assert.equal(res[0].toString(), expectedMulX.toString()) 93 | assert.equal(res[1].toString(), expectedMulY.toString()) 94 | }) 95 | } 96 | }) 97 | } 98 | }) 99 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | local: { 4 | host: "127.0.0.1", 5 | port: 8545, 6 | network_id: "*", 7 | }, 8 | }, 9 | mocha: { 10 | reporter: "eth-gas-reporter", 11 | }, 12 | compilers: { 13 | solc: { 14 | settings: { 15 | optimizer: { 16 | enabled: true, 17 | runs: 200, 18 | }, 19 | }, 20 | version: "0.8.17", 21 | }, 22 | }, 23 | } 24 | --------------------------------------------------------------------------------