You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by km...@apache.org on 2019/06/18 18:12:16 UTC
[incubator-milagro-crypto-js] branch update created (now f33178a)
This is an automated email from the ASF dual-hosted git repository.
kmccusker pushed a change to branch update
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-js.git.
at f33178a resync code to golden repo
This branch includes the following new commits:
new f33178a resync code to golden repo
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[incubator-milagro-crypto-js] 01/01: resync code to golden repo
Posted by km...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kmccusker pushed a commit to branch update
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-js.git
commit f33178ad58b8380d47dbc9151b69ebab09e50e40
Author: Kealan McCusker <ke...@gmail.com>
AuthorDate: Tue Jun 18 19:11:57 2019 +0100
resync code to golden repo
---
.travis.yml | 22 +-
LICENSE | 404 +++++++-------
README.md | 59 +-
VERSION | 2 +-
examples/browser/example_BLS.html | 249 +++++++++
...le_DVS_BN254CX.html => example_DVS_BLS383.html} | 4 +-
...IST521.html => example_ECC_BLS383_NIST521.html} | 4 +-
..._MPIN_BN254CX.html => example_MPIN_BLS383.html} | 4 +-
..._BN254CX.html => example_MPIN_FULL_BLS383.html} | 4 +-
...54CX.html => example_MPIN_ONE_PASS_BLS383.html} | 4 +-
...TP_BN254CX.html => example_MPIN_TP_BLS383.html} | 4 +-
...xample_DVS_BN254CX.js => example_DVS_BLS383.js} | 2 +-
...54_NIST521.js => example_ECC_BLS383_NIST521.js} | 4 +-
...mple_MPIN_BN254CX.js => example_MPIN_BLS383.js} | 2 +-
...FULL_BN254CX.js => example_MPIN_FULL_BLS383.js} | 2 +-
..._BN254CX.js => example_MPIN_ONE_PASS_BLS383.js} | 2 +-
examples/node/example_MPIN_TP_BN254CX.js | 173 ------
package.json | 11 +-
src/aes.js | 47 +-
src/big.js | 73 ++-
src/bls.js | 127 +++++
src/bls192.js | 126 +++++
src/bls256.js | 129 +++++
src/ctx.js | 94 +++-
src/ecdh.js | 44 +-
src/ecp.js | 206 ++++---
src/ecp2.js | 90 +--
src/ecp4.js | 84 +--
src/ecp8.js | 96 ++--
src/ff.js | 21 +-
src/fp.js | 249 +++++++--
src/fp12.js | 554 ++++++++++++++-----
src/fp16.js | 77 +--
src/fp2.js | 11 +-
src/fp24.js | 583 ++++++++++++++------
src/fp4.js | 84 +--
src/fp48.js | 609 +++++++++++++++------
src/fp8.js | 76 +--
src/gcm.js | 50 +-
src/hash256.js | 19 +-
src/hash384.js | 19 +-
src/hash512.js | 18 +-
src/mpin.js | 34 +-
src/mpin192.js | 9 +-
src/mpin256.js | 9 +-
src/pair.js | 300 ++++++----
src/pair192.js | 191 +++++--
src/pair256.js | 199 +++++--
src/rand.js | 28 +-
src/rsa.js | 3 +-
src/sha3.js | 28 +-
test/test_BIG.js | 4 +-
test/test_DVS.js | 5 +-
test/test_FP12_js | 206 +++++++
test/test_FP16_js | 249 +++++++++
test/test_FP24_js | 235 ++++++++
test/test_FP2_js | 164 ++++++
test/test_FP48_js | 246 +++++++++
test/test_FP4_js | 257 +++++++++
test/test_FP8_js | 291 ++++++++++
test/test_FP_js | 146 +++++
test/test_MPIN.js | 4 +-
test/test_RSA2048.js | 4 +-
test/test_RSA3072.js | 4 +-
test/test_RSA4096.js | 4 +-
65 files changed, 5296 insertions(+), 1766 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 7673e7b..152fd6b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,26 +1,16 @@
language: node_js
node_js:
- - "node"
+ - "8"
-sudo: required
-dist: trusty
+before_install:
+ - npm update
-group: edge
-
-branches:
- except:
- - release
-
-before_script:
- - npm install chai
- - npm install -g mocha
- - npm install -g coveralls
- - npm install -g istanbul
- - npm install -g nyc
+install:
+ - npm install
script:
- npm run coverage
after_success:
- - npm run report
\ No newline at end of file
+ - npm run report
diff --git a/LICENSE b/LICENSE
index 19efef5..9b5e401 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,202 +1,202 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2016 MIRACL UK Ltd
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/README.md b/README.md
index 3a422fd..2f9d191 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,39 @@
# MCJS - *Milagro Crypto JavaScript*
-[](https://github.com/milagro-crypto/milagro-crypto-js/tree/master)
-[](https://travis-ci.org/milagro-crypto/milagro-crypto-js?branch=master)
-[](https://coveralls.io/github/milagro-crypto/milagro-crypto-js?branch=master)
+[](https://github.com/apache/incubator-milagro-crypto-js/tree/master)
+[](https://travis-ci.org/apache/incubator-milagro-crypto-js?branch=master)
+[](https://coveralls.io/github/apache/incubator-milagro-crypto-js?branch=master)
+
+[](https://github.com/apache/incubator-milagro-crypto-js/tree/develop)
+[](https://travis-ci.org/apache/incubator-milagro-crypto-js?branch=develop)
+[](https://coveralls.io/github/apache/incubator-milagro-crypto-js?branch=develop)
* **category**: Library
* **copyright**: 2019 The Apache Software Foundation
* **license**: ASL 2.0 - http://www.apache.org/licenses/LICENSE-2.0
-* **link**: https://github.com/apache/incubator-milagro-javascript
-* **introduction**: [AMCL.pdf](doc/AMCL.pdf)
+* **link**: https://github.com/apache/incubator-milagro-crypto-js
## Description
*MCJS - Milagro Crypto JavaScript*
-* MCJS is a standards compliant JavaScript cryptographic library with no external dependencies except for the random seed source.
-
-* MCJS is a refactor of the *JavaScript* code of [AMCL](https://github.com/miracl/amcl). For a detailed explanation about this library please read: [doc/AMCL.pdf](doc/AMCL.pdf). For info about the refactoring process contact support@miracl.com.
+* MCJS is a standards compliant JavaScript cryptographic library with no
+external dependencies except for the random seed source.
-* MCJS supports the standards for RSA, ECDH, ECIES, ECDSA and M-PIN, AES-GCM encryption/decryption, SHA256, SHA384, SHA512 and SHA3 hash functions and a cryptographically secure random number generator. Furthermore we recently added New Hope, a post-quantum key exchange.
+* MCJS supports the standards for RSA, ECDH, ECIES, ECDSA and M-PIN, AES-GCM
+encryption/decryption, SHA256, SHA384, SHA512 and SHA3 hash functions and a
+cryptographically secure random number generator. Furthermore we recently
+added New Hope, a post-quantum key exchange.
-* MCJS is [Node.js](https://nodejs.org/en/) compatible and browser compatible (see some examples below).
+* MCJS is [Node.js](https://nodejs.org/en/) compatible and browser compatible
+(see some examples below).
## Install and run tests
-[Node.js](https://nodejs.org/en/) (minimum v6.9.5) and [npm](https://www.npmjs.com/) are required in order to build the library and run the tests. Install also the node.js modules required with the command
+[Node.js](https://nodejs.org/en/) (minimum v6.9.5) and
+[npm](https://www.npmjs.com/) are required in order to build the library and
+run the tests. Install also the node.js modules required with the command
```
npm install
@@ -39,7 +47,8 @@ npm test
## Quick Start
#### Elliptic Curves
-Suppose you want to implement ECDH with NIST256 elliptic curve. First you need to initialize the context:
+Suppose you want to implement ECDH with NIST256 elliptic curve. First you need
+to initialize the context:
```
var CTX = require("milagro-crypto-js");
@@ -51,7 +60,8 @@ then you can call the functions as follows:
ctx.ECDH.KEY_PAIR_GENERATE(...);
ctx.ECDH.ECPSVDP_DH(...);
```
-If you need to use more than one elliptic curve in the same script you only need to initialize two different contexts, for example
+If you need to use more than one elliptic curve in the same script you only
+need to initialize two different contexts, for example
```
var ctx1 = new CTX("NIST256");
var ctx2 = new CTX("C25519");
@@ -86,7 +96,8 @@ var ctx = new CTX();
## Run examples
-[Node.js](https://nodejs.org/en/) examples are provided - please see `./examples/node`. Use the following command to run an example
+[Node.js](https://nodejs.org/en/) examples are provided - please see
+`./examples/node`. Use the following command to run an example
```
node ./examples/node/example_ECC_NIST256.js
@@ -94,15 +105,27 @@ node ./examples/node/example_ECC_NIST256.js
#### Browsers
-The library source code is browser compatible. The browser examples are locates in `./examples/browser`.
+The library source code is browser compatible. The browser examples are locates
+in `./examples/browser`.
-## Contributors ##
+## Contributors
-The following people have contributed to milagro-crypto-c
+The following people have contributed to milagro-crypto-js
- Mike Scott
- Kealan McCusker
- Alessandro Budroni
- Samuele Andreoli
-Please add yourself here if you make or have made a contribution.
\ No newline at end of file
+Please add yourself here if you make or have made a contribution.
+
+## Making a Contribution
+
+1. [Check for open issues](https://github.com/apache/incubator-milagro-crypto-js/issues) or start a discussion around a feature idea or a bug by sending a
+mail to dev@milagro.incubator.apache.org
+2. Fork the repository to start making your changes. Please use the
+"development" branch as a basis.
+3. Write a test which shows that the bug was fixed or that the feature works
+as expected.
+4. Make a pull request with a reference to the issue
+
diff --git a/VERSION b/VERSION
index 9575d51..6e8bf73 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.6.1
+0.1.0
diff --git a/examples/browser/example_BLS.html b/examples/browser/example_BLS.html
new file mode 100644
index 0000000..5c19a78
--- /dev/null
+++ b/examples/browser/example_BLS.html
@@ -0,0 +1,249 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>JavaScript Test BLS</title>
+</head>
+<body>
+<h1>JavaScript Test BLS Example</h1>
+<script src="src/rand.js"></script>
+<script src="src/rom_curve.js"></script>
+<script src="src/rom_field.js"></script>
+<script src="src/uint64.js"></script>
+<script src="src/aes.js"></script>
+<script src="src/big.js"></script>
+<script src="src/gcm.js"></script>
+<script src="src/hash256.js"></script>
+<script src="src/hash384.js"></script>
+<script src="src/hash512.js"></script>
+<script src="src/sha3.js"></script>
+<script src="src/nhs.js"></script>
+<script src="src/fp.js"></script>
+<script src="src/fp2.js"></script>
+<script src="src/fp4.js"></script>
+<script src="src/fp12.js"></script>
+<script src="src/ff.js"></script>
+<script src="src/rsa.js"></script>
+<script src="src/ecp.js"></script>
+<script src="src/ecp2.js"></script>
+<script src="src/ecdh.js"></script>
+<script src="src/pair.js"></script>
+<script src="src/bls.js"></script>
+<script src="src/mpin.js"></script>
+<script src="src/ctx.js"></script>
+
+<script src="src/fp8.js"></script>
+<script src="src/fp16.js"></script>
+<script src="src/fp24.js"></script>
+<script src="src/fp48.js"></script>
+<script src="src/ecp4.js"></script>
+<script src="src/ecp8.js"></script>
+<script src="src/pair192.js"></script>
+<script src="src/pair256.js"></script>
+<script src="src/mpin192.js"></script>
+<script src="src/mpin256.js"></script>
+<script src="src/bls192.js"></script>
+<script src="src/bls256.js"></script>
+
+
+<p><a id="myLink4" href="#" onclick="location.reload(false);bn254();">BN254 254-bit k=12 Pairing-Friendly BN Curve Boneh-Lynn-Shacham</a></p>
+<p><a id="myLink5" href="#" onclick="location.reload(false);bls383();">BLS383 383-bit k=12 Pairing-Friendly BLS Curve Boneh-Lynn-Shacham</a></p>
+<p><a id="myLink6" href="#" onclick="location.reload(false);bls24();">BLS24 479-bit k=24 Pairing-Friendly BLS Curve Boneh-Lynn-Shacham</a></p>
+<p><a id="myLink7" href="#" onclick="location.reload(false);bls48();">BLS48 556-bit k=48 Pairing-Friendly BLS Curve Boneh-Lynn-Shacham</a></p>
+
+
+<script>
+
+
+/* Test BLS signature */
+
+// BN254 context
+function bn254() {
+ var ctx = new CTX('BN254');
+ mywindow=window.open();
+
+ mywindow.document.write("<br> BN254 Pairing-Friendly Curve "+ "<br>");
+
+ var i,res;
+ var result;
+
+ var BGS=ctx.BLS.BGS;
+ var BFS=ctx.BLS.BFS;
+
+ var G1S=BFS+1; // Group 1 Size
+ var G2S=4*BFS; // Group 2 Size
+
+ var S=[];
+ var W=[];
+ var SIG=[];
+
+ var RAW=[];
+ var rng=new ctx.RAND();
+
+ rng.clean();
+ for (i=0;i<100;i++) RAW[i]=i;
+
+ rng.seed(100,RAW);
+
+ mywindow.document.write ("Testing BLS code <br>");
+ var mess="This is a test message";
+
+ ctx.BLS.KeyPairGenerate(rng,S,W);
+ mywindow.document.write("Private key : 0x"+ctx.BLS.bytestostring(S) + "<br>");
+ mywindow.document.write("Public key : 0x"+ctx.BLS.bytestostring(W) + "<br>");
+
+ ctx.BLS.sign(SIG,mess,S);
+ mywindow.document.write("Signature : 0x"+ctx.BLS.bytestostring(SIG) + "<br>");
+
+ var res=ctx.BLS.verify(SIG,mess,W);
+
+ if (res==0)
+ mywindow.document.write("Signature is OK" + "<br>");
+ else
+ mywindow.document.write("Signature is *NOT* OK" + "<br>");
+
+}
+
+// BLS383 context
+function bls383() {
+ var ctx = new CTX('BLS383');
+ mywindow=window.open();
+
+ mywindow.document.write("<br> BLS383 Pairing-Friendly Curve "+ "<br>");
+
+ var i,res;
+ var result;
+
+ var BGS=ctx.BLS.BGS;
+ var BFS=ctx.BLS.BFS;
+
+ var G1S=BFS+1; /* Group 1 Size */
+ var G2S=4*BFS; /* Group 2 Size */
+
+ var S=[];
+ var W=[];
+ var SIG=[];
+
+ var RAW=[];
+ var rng=new ctx.RAND();
+
+ rng.clean();
+ for (i=0;i<100;i++) RAW[i]=i;
+
+ rng.seed(100,RAW);
+
+ mywindow.document.write ("Testing BLS code <br>");
+ var mess="This is a test message";
+
+ ctx.BLS.KeyPairGenerate(rng,S,W);
+ mywindow.document.write("Private key : 0x"+ctx.BLS.bytestostring(S) + "<br>");
+ mywindow.document.write("Public key : 0x"+ctx.BLS.bytestostring(W) + "<br>");
+
+ ctx.BLS.sign(SIG,mess,S);
+ mywindow.document.write("Signature : 0x"+ctx.BLS.bytestostring(SIG) + "<br>");
+
+ var res=ctx.BLS.verify(SIG,mess,W);
+
+ if (res==0)
+ mywindow.document.write("Signature is OK" + "<br>");
+ else
+ mywindow.document.write("Signature is *NOT* OK" + "<br>");
+
+}
+
+// BLS24 context
+function bls24() {
+ var ctx = new CTX('BLS24');
+ mywindow=window.open();
+
+ mywindow.document.write("<br> BLS24 Pairing-Friendly Curve "+ "<br>");
+
+ var i,res;
+ var result;
+
+ var BGS=ctx.BLS192.BGS;
+ var BFS=ctx.BLS192.BFS;
+
+ var G1S=BFS+1; /* Group 1 Size */
+ var G2S=4*BFS; /* Group 2 Size */
+
+ var S=[];
+ var W=[];
+ var SIG=[];
+
+ var RAW=[];
+ var rng=new ctx.RAND();
+
+ rng.clean();
+ for (i=0;i<100;i++) RAW[i]=i;
+
+ rng.seed(100,RAW);
+
+ mywindow.document.write ("Testing BLS code <br>");
+ var mess="This is a test message";
+
+ ctx.BLS192.KeyPairGenerate(rng,S,W);
+ mywindow.document.write("Private key : 0x"+ctx.BLS192.bytestostring(S) + "<br>");
+ mywindow.document.write("Public key : 0x"+ctx.BLS192.bytestostring(W) + "<br>");
+
+ ctx.BLS192.sign(SIG,mess,S);
+ mywindow.document.write("Signature : 0x"+ctx.BLS192.bytestostring(SIG) + "<br>");
+
+ var res=ctx.BLS192.verify(SIG,mess,W);
+
+ if (res==0)
+ mywindow.document.write("Signature is OK" + "<br>");
+ else
+ mywindow.document.write("Signature is *NOT* OK" + "<br>");
+
+}
+
+// BLS48 context
+function bls48() {
+ var ctx = new CTX('BLS48');
+ mywindow=window.open();
+
+ mywindow.document.write("<br> BLS48 Pairing-Friendly Curve "+ "<br>");
+
+ var i,res;
+ var result;
+
+ var BGS=ctx.BLS256.BGS;
+ var BFS=ctx.BLS256.BFS;
+
+ var G1S=BFS+1; /* Group 1 Size */
+ var G2S=4*BFS; /* Group 2 Size */
+
+ var S=[];
+ var W=[];
+ var SIG=[];
+
+ var RAW=[];
+ var rng=new ctx.RAND();
+
+ rng.clean();
+ for (i=0;i<100;i++) RAW[i]=i;
+
+ rng.seed(100,RAW);
+
+ mywindow.document.write ("Testing BLS code <br>");
+ var mess="This is a test message";
+
+ ctx.BLS256.KeyPairGenerate(rng,S,W);
+ mywindow.document.write("Private key : 0x"+ctx.BLS256.bytestostring(S) + "<br>");
+ mywindow.document.write("Public key : 0x"+ctx.BLS256.bytestostring(W) + "<br>");
+
+ ctx.BLS256.sign(SIG,mess,S);
+ mywindow.document.write("Signature : 0x"+ctx.BLS256.bytestostring(SIG) + "<br>");
+
+ var res=ctx.BLS256.verify(SIG,mess,W);
+
+ if (res==0)
+ mywindow.document.write("Signature is OK" + "<br>");
+ else
+ mywindow.document.write("Signature is *NOT* OK" + "<br>");
+
+}
+
+</script>
+</body>
+</html>
diff --git a/examples/browser/example_DVS_BN254CX.html b/examples/browser/example_DVS_BLS383.html
similarity index 98%
rename from examples/browser/example_DVS_BN254CX.html
rename to examples/browser/example_DVS_BLS383.html
index c8d6322..d5c0183 100644
--- a/examples/browser/example_DVS_BN254CX.html
+++ b/examples/browser/example_DVS_BLS383.html
@@ -55,7 +55,7 @@ under the License.
/* Test DVS - test driver and function exerciser for Designated Verifier Signature API Functions */
-var ctx = new CTX("BN254CX");
+var ctx = new CTX("BLS383");
var RAW = [];
var rng = new ctx.RAND();
@@ -87,7 +87,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testuser@miracl.com";
+var IDstr = "testuser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
console.log("Client ID= " + ctx.MPIN.bytestostring(CLIENT_ID));
diff --git a/examples/browser/example_ECC_BN254_NIST521.html b/examples/browser/example_ECC_BLS383_NIST521.html
similarity index 98%
rename from examples/browser/example_ECC_BN254_NIST521.html
rename to examples/browser/example_ECC_BLS383_NIST521.html
index b46d2f8..ea61f8e 100644
--- a/examples/browser/example_ECC_BN254_NIST521.html
+++ b/examples/browser/example_ECC_BLS383_NIST521.html
@@ -56,10 +56,10 @@ under the License.
/* Test ECC - test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
-var ctx1 = new CTX("BN254");
+var ctx1 = new CTX("BLS383");
var ctx2 = new CTX("NIST521");
-console.log("Start testing BN254");
+console.log("Start testing BLS383");
var pp = "M0ng00se",
res,
diff --git a/examples/browser/example_MPIN_BN254CX.html b/examples/browser/example_MPIN_BLS383.html
similarity index 99%
rename from examples/browser/example_MPIN_BN254CX.html
rename to examples/browser/example_MPIN_BLS383.html
index d1e9fa5..6ca6b73 100644
--- a/examples/browser/example_MPIN_BN254CX.html
+++ b/examples/browser/example_MPIN_BLS383.html
@@ -55,7 +55,7 @@ under the License.
/* Test MPIN - test driver and function exerciser for MPIN API Functions */
-var ctx = new CTX("BN254CX");
+var ctx = new CTX("BLS383");
/* Test M-Pin */
@@ -95,7 +95,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/browser/example_MPIN_FULL_BN254CX.html b/examples/browser/example_MPIN_FULL_BLS383.html
similarity index 99%
rename from examples/browser/example_MPIN_FULL_BN254CX.html
rename to examples/browser/example_MPIN_FULL_BLS383.html
index b6b82bf..9a572bb 100644
--- a/examples/browser/example_MPIN_FULL_BN254CX.html
+++ b/examples/browser/example_MPIN_FULL_BLS383.html
@@ -55,7 +55,7 @@ under the License.
/* Test MPIN - test driver and function exerciser for MPIN API Functions */
-var ctx = new CTX("BN254CX");
+var ctx = new CTX("BLS383");
/* Test M-Pin */
@@ -107,7 +107,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/browser/example_MPIN_ONE_PASS_BN254CX.html b/examples/browser/example_MPIN_ONE_PASS_BLS383.html
similarity index 98%
rename from examples/browser/example_MPIN_ONE_PASS_BN254CX.html
rename to examples/browser/example_MPIN_ONE_PASS_BLS383.html
index 24163e2..a798a31 100644
--- a/examples/browser/example_MPIN_ONE_PASS_BN254CX.html
+++ b/examples/browser/example_MPIN_ONE_PASS_BLS383.html
@@ -55,7 +55,7 @@ under the License.
/* Test MPIN - test driver and function exerciser for MPIN API Functions */
-var ctx = new CTX("BN254CX");
+var ctx = new CTX("BLS383");
/* Test M-Pin */
@@ -106,7 +106,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/browser/example_MPIN_TP_BN254CX.html b/examples/browser/example_MPIN_TP_BLS383.html
similarity index 98%
rename from examples/browser/example_MPIN_TP_BN254CX.html
rename to examples/browser/example_MPIN_TP_BLS383.html
index 1bed73b..8f8c1d2 100644
--- a/examples/browser/example_MPIN_TP_BN254CX.html
+++ b/examples/browser/example_MPIN_TP_BLS383.html
@@ -55,7 +55,7 @@ under the License.
/* Test MPIN - test driver and function exerciser for MPIN API Functions */
-var ctx = new CTX("BN254CX");
+var ctx = new CTX("BLS383");
/* Test M-Pin */
@@ -95,7 +95,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/node/example_DVS_BN254CX.js b/examples/node/example_DVS_BLS383.js
similarity index 99%
rename from examples/node/example_DVS_BN254CX.js
rename to examples/node/example_DVS_BLS383.js
index c33c68f..da1c66d 100644
--- a/examples/node/example_DVS_BN254CX.js
+++ b/examples/node/example_DVS_BLS383.js
@@ -53,7 +53,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testuser@miracl.com";
+var IDstr = "testuser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
console.log("Client ID= " + ctx.MPIN.bytestostring(CLIENT_ID));
diff --git a/examples/node/example_ECC_BN254_NIST521.js b/examples/node/example_ECC_BLS383_NIST521.js
similarity index 98%
rename from examples/node/example_ECC_BN254_NIST521.js
rename to examples/node/example_ECC_BLS383_NIST521.js
index 10d812f..6a5e82f 100644
--- a/examples/node/example_ECC_BN254_NIST521.js
+++ b/examples/node/example_ECC_BLS383_NIST521.js
@@ -22,10 +22,10 @@ under the License.
var CTX = require("../../index");
-var ctx1 = new CTX("BN254");
+var ctx1 = new CTX("BLS383");
var ctx2 = new CTX("NIST521");
-console.log("Start testing BN254");
+console.log("Start testing BLS383");
var pp = "M0ng00se",
res,
diff --git a/examples/node/example_MPIN_BN254CX.js b/examples/node/example_MPIN_BLS383.js
similarity index 99%
rename from examples/node/example_MPIN_BN254CX.js
rename to examples/node/example_MPIN_BLS383.js
index f4defdc..26acda7 100644
--- a/examples/node/example_MPIN_BN254CX.js
+++ b/examples/node/example_MPIN_BLS383.js
@@ -61,7 +61,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/node/example_MPIN_FULL_BN254CX.js b/examples/node/example_MPIN_FULL_BLS383.js
similarity index 99%
rename from examples/node/example_MPIN_FULL_BN254CX.js
rename to examples/node/example_MPIN_FULL_BLS383.js
index 7788672..7e689b3 100644
--- a/examples/node/example_MPIN_FULL_BN254CX.js
+++ b/examples/node/example_MPIN_FULL_BLS383.js
@@ -73,7 +73,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/node/example_MPIN_ONE_PASS_BN254CX.js b/examples/node/example_MPIN_ONE_PASS_BLS383.js
similarity index 99%
rename from examples/node/example_MPIN_ONE_PASS_BN254CX.js
rename to examples/node/example_MPIN_ONE_PASS_BLS383.js
index a4b999b..c6f6b9f 100644
--- a/examples/node/example_MPIN_ONE_PASS_BN254CX.js
+++ b/examples/node/example_MPIN_ONE_PASS_BLS383.js
@@ -72,7 +72,7 @@ ctx.MPIN.RANDOM_GENERATE(rng, S);
console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
+var IDstr = "testUser@milagro.com";
var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
diff --git a/examples/node/example_MPIN_TP_BN254CX.js b/examples/node/example_MPIN_TP_BN254CX.js
deleted file mode 100644
index 43bae9e..0000000
--- a/examples/node/example_MPIN_TP_BN254CX.js
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-
-/* Test MPIN - test driver and function exerciser for MPIN API Functions */
-
-var CTX = require("../../index");
-
-var ctx = new CTX("BN254CX");
-
-/* Test M-Pin */
-
-var RAW = [];
-var i;
-
-var rng = new ctx.RAND();
-rng.clean();
-for (i = 0; i < 100; i++) {
- RAW[i] = i;
-}
-
-rng.seed(100, RAW);
-
-var sha = ctx.ECP.HASH_TYPE;
-
-var S = [];
-var SST = [];
-var TOKEN = [];
-var PERMIT = [];
-var SEC = [];
-var xID = [];
-var xCID = [];
-var X = [];
-var Y = [];
-var E = [];
-var F = [];
-var HCID = [];
-var HID = [];
-var HTID = [];
-
-/* Set configuration */
-var PINERROR = true;
-
-/* Trusted Authority set-up */
-ctx.MPIN.RANDOM_GENERATE(rng, S);
-console.log("M-Pin Master Secret s: 0x" + ctx.MPIN.bytestostring(S));
-
-/* Create Client Identity */
-var IDstr = "testUser@miracl.com";
-var CLIENT_ID = ctx.MPIN.stringtobytes(IDstr);
-HCID = ctx.MPIN.HASH_ID(sha, CLIENT_ID); /* Either Client or TA calculates Hash(ID) - you decide! */
-
-console.log("Client ID= " + ctx.MPIN.bytestostring(CLIENT_ID));
-
-/* Client and Server are issued secrets by DTA */
-ctx.MPIN.GET_SERVER_SECRET(S, SST);
-console.log("Server Secret SS: 0x" + ctx.MPIN.bytestostring(SST));
-
-ctx.MPIN.GET_CLIENT_SECRET(S, HCID, TOKEN);
-console.log("Client Secret CS: 0x" + ctx.MPIN.bytestostring(TOKEN));
-
-/* Client extracts PIN from secret to create Token */
-var pin = 1234;
-console.log("Client extracts PIN= " + pin);
-var rtn = ctx.MPIN.EXTRACT_PIN(sha, CLIENT_ID, pin, TOKEN);
-if (rtn != 0) {
- console.log("Failed to extract PIN ");
-}
-
-console.log("Client Token TK: 0x" + ctx.MPIN.bytestostring(TOKEN));
-
-var date = ctx.MPIN.today();
-/* Client gets "Time Token" permit from DTA */
-ctx.MPIN.GET_CLIENT_PERMIT(sha, date, S, HCID, PERMIT);
-console.log("Time Permit TP: 0x" + ctx.MPIN.bytestostring(PERMIT));
-
-/* This encoding makes Time permit look ctx.RANDom - Elligator squared */
-ctx.MPIN.ENCODING(rng, PERMIT);
-console.log("Encoded Time Permit TP: 0x" + ctx.MPIN.bytestostring(PERMIT));
-ctx.MPIN.DECODING(PERMIT);
-console.log("Decoded Time Permit TP: 0x" + ctx.MPIN.bytestostring(PERMIT));
-
-pin = 1234;
-
-/* Set date=0 and PERMIT=null if time permits not in use
-
-Client First pass: Inputs CLIENT_ID, optional RNG, pin, TOKEN and PERMIT. Output xID = x.H(CLIENT_ID) and re-combined secret SEC
-If PERMITS are is use, then date!=0 and PERMIT is added to secret and xCID = x.(H(CLIENT_ID)+H_T(date|H(CLIENT_ID)))
-ctx.RANDom value x is supplied externally if RNG=null, otherwise generated and passed out by RNG
-
-If Time Permits OFF set xCID = null, HTID=null and use xID and HID only
-If Time permits are ON, AND pin error detection is required then all of xID, xCID, HID and HTID are required
-If Time permits are ON, AND pin error detection is NOT required, set xID=null, HID=null and use xCID and HTID only.
-
-
-*/
-var pxID = xID;
-var pxCID = xCID;
-var pHID = HID;
-var pHTID = HTID;
-var pE = E;
-var pF = F;
-var pPERMIT = PERMIT;
-
-if (date != 0) {
- if (!PINERROR) {
- pxID = null;
- // pHID=null;
- }
-} else {
- pPERMIT = null;
- pxCID = null;
- pHTID = null;
-}
-if (!PINERROR) {
- pE = null;
- pF = null;
-}
-
-console.log("MPIN Multi Pass ");
-rtn = ctx.MPIN.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, pxID, pxCID, pPERMIT);
-if (rtn != 0) {
- console.error("FAILURE: CLIENT_1 rtn: " + rtn);
- process.exit(-1);
-}
-/* Server calculates H(ID) and H(T|H(ID)) (if time permits enabled), and maps them to points on the curve HID and HTID resp. */
-ctx.MPIN.SERVER_1(sha, date, CLIENT_ID, pHID, pHTID);
-
-/* Server generates ctx.RANDom number Y and sends it to Client */
-ctx.MPIN.RANDOM_GENERATE(rng, Y);
-
-/* Client Second Pass: Inputs Client secret SEC, x and y. Outputs -(x+y)*SEC */
-rtn = ctx.MPIN.CLIENT_2(X, Y, SEC);
-if (rtn != 0) {
- console.error("FAILURE: CLIENT_2 rtn: " + rtn);
- process.exit(-1);
-}
-/* Server Second pass. Inputs hashed client id, ctx.RANDom Y, -(x+y)*SEC, xID and xCID and Server secret SST. E and F help kangaroos to find error. */
-/* If PIN error not required, set E and F = NULL */
-rtn = ctx.MPIN.SERVER_2(date, pHID, pHTID, Y, SST, pxID, pxCID, SEC, pE, pF);
-
-if (rtn != 0) {
- console.error("FAILURE: SERVER_1 rtn: " + rtn);
- process.exit(-1);
-}
-if (rtn == ctx.MPIN.BAD_PIN) {
- console.log("Server says - Bad Pin.");
- if (PINERROR) {
- var err = ctx.MPIN.KANGAROO(E, F);
- if (err != 0) {
- console.log("(Client PIN is out by " + err + ")");
- }
- }
-} else {
- console.log("Server says - PIN is good! You really are " + IDstr);
-}
-
-console.log("SUCCESS");
diff --git a/package.json b/package.json
index cc80f77..1894815 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,9 @@
{
"name": "milagro-crypto-js",
- "version": "3.6.0",
- "description": "Crypto Library in Javascript - Refact of Apache Milagro Crypto Library",
+ "version": "0.1.0",
+ "description": "Apache Milagro Crypto Javascript Library",
"main": "index.js",
"directories": {
- "doc": "doc",
"example": "examples",
"test": "test"
},
@@ -16,7 +15,7 @@
},
"repository": {
"type": "git",
- "url": "git+https://github.com/miracl/milagro-crypto-js.git"
+ "url": "git+https://github.com/apache/incubator-milagro-crypto-js.git"
},
"keywords": [
"pairing",
@@ -27,9 +26,9 @@
"author": "Michael Scott, Alessandro Budroni, Kealan McCusker",
"license": "Apache-2.0",
"bugs": {
- "url": "https://github.com/miracl/milagro-crypto-js/issues"
+ "url": "https://github.com/apache/incubator-milagro-crypto-js/issues"
},
- "homepage": "https://github.com/miracl/milagro-crypto-js#readme",
+ "homepage": "https://github.com/apache/incubator-milagro-crypto-js#readme",
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^3.0.2",
diff --git a/src/aes.js b/src/aes.js
index 43fe9aa..73f8425 100644
--- a/src/aes.js
+++ b/src/aes.js
@@ -47,8 +47,8 @@ var AES = function() {
AES.CTR16 = 45;
AES.prototype = {
- /* reset cipher - mode or iv */
- reset: function(m, iv) {
+ /* reset cipher */
+ reset: function(m, iv) { /* reset mode, or reset iv */
var i;
this.mode = m;
@@ -88,7 +88,7 @@ var AES = function() {
},
/* Initialise cipher */
- init: function(m, nk, key, iv) {
+ init: function(m, nk, key, iv) { /* Key=16 bytes */
/* Key Scheduler. Create expanded encryption key */
var CipherKey = [],
b = [],
@@ -122,11 +122,26 @@ var AES = function() {
for (j = nk, k = 0; j < N; j += nk, k++) {
this.fkey[j] = this.fkey[j - nk] ^ AES.SubByte(AES.ROTL24(this.fkey[j - 1])) ^ (AES.rco[k]) & 0xff;
- for (i = 1; i < nk && (i + j) < N; i++) {
- this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
- }
+
+ if (nk<=6)
+ {
+ for (i = 1; i < nk && (i + j) < N; i++) {
+ this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
+ }
+ } else {
+ for (i = 1; i < 4 && (i + j) < N; i++) {
+ this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
+ }
+ if ((j + 4) < N) {
+ this.fkey[j + 4] = this.fkey[j + 4 - nk] ^ AES.SubByte(this.fkey[j + 3]);
+ }
+ for (i = 5; i < nk && (i + j) < N; i++) {
+ this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
+ }
+ }
}
+
/* now for the expanded decrypt key in reverse order */
for (j = 0; j < 4; j++) {
@@ -447,7 +462,7 @@ var AES = function() {
},
/* Clean up and delete left-overs */
- end: function() {
+ end: function() { // clean up
var i;
for (i = 0; i < 4 * (this.Nr + 1); i++) {
@@ -474,13 +489,11 @@ var AES = function() {
return (((x) << 24) | ((x) >>> 8));
};
- /* pack 4 bytes into a 32-bit Word */
- AES.pack = function(b) {
+ AES.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
};
- /* unpack bytes from a word */
- AES.unpack = function(a) {
+ AES.unpack = function(a) { /* unpack bytes from a word */
var b = [];
b[0] = (a & 0xff);
b[1] = ((a >>> 8) & 0xff);
@@ -489,8 +502,7 @@ var AES = function() {
return b;
};
- /* x.y= AntiLog(Log(x) + Log(y)) */
- AES.bmul = function(x, y) {
+ AES.bmul = function(x, y) { /* x.y= AntiLog(Log(x) + Log(y)) */
var ix = (x & 0xff),
iy = (y & 0xff),
lx = (AES.ltab[ix]) & 0xff,
@@ -514,16 +526,14 @@ var AES = function() {
return AES.pack(b);
};
- /* dot product of two 4-byte arrays */
- AES.product = function(x, y) {
+ AES.product = function(x, y) { /* dot product of two 4-byte arrays */
var xb = AES.unpack(x),
yb = AES.unpack(y);
return (AES.bmul(xb[0], yb[0]) ^ AES.bmul(xb[1], yb[1]) ^ AES.bmul(xb[2], yb[2]) ^ AES.bmul(xb[3], yb[3])) & 0xff;
};
- /* matrix Multiplication */
- AES.InvMixCol = function(x) {
+ AES.InvMixCol = function(x) { /* matrix Multiplication */
var b = [],
y, m;
@@ -540,8 +550,7 @@ var AES = function() {
return y;
};
- /* Inverse Coefficients */
- AES.InCo = [0xB, 0xD, 0x9, 0xE];
+ AES.InCo = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */
AES.rco = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47];
AES.ptab = [
diff --git a/src/big.js b/src/big.js
index 0cf67b6..f680841 100644
--- a/src/big.js
+++ b/src/big.js
@@ -202,8 +202,7 @@ BIG = function(ctx) {
fshr: function(k) {
var r, i;
- /* shifted out part */
- r = this.w[0] & ((1 << k) - 1);
+ r = this.w[0] & ((1 << k) - 1); /* shifted out part */
for (i = 0; i < BIG.NLEN - 1; i++) {
this.w[i] = (this.w[i] >> k) | ((this.w[i + 1] << (BIG.BASEBITS - k)) & BIG.BMASK);
@@ -245,8 +244,7 @@ BIG = function(ctx) {
this.w[0] = (this.w[0] << k) & BIG.BMASK;
- /* return excess - only used in ff.js */
- return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS));
+ return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS)); /* return excess - only used in FF.java */
},
/* General shift left by k bits */
@@ -279,9 +277,10 @@ BIG = function(ctx) {
var k = BIG.NLEN - 1,
bts, c;
- this.norm();
+ var t=new BIG(0); t.copy(this);
+ t.norm();
- while (k >= 0 && this.w[k] === 0) {
+ while (k >= 0 && t.w[k] === 0) {
k--;
}
@@ -290,7 +289,7 @@ BIG = function(ctx) {
}
bts = BIG.BASEBITS * k;
- c = this.w[k];
+ c = t.w[k];
while (c !== 0) {
c = Math.floor(c / 2);
@@ -427,8 +426,8 @@ BIG = function(ctx) {
var c = new BIG(0),
i;
- this.norm();
c.copy(this);
+ c.norm();
for (i = BIG.MODBYTES - 1; i >= 0; i--) {
b[i + n] = c.w[0] & 0xff;
@@ -550,9 +549,10 @@ BIG = function(ctx) {
},
/* reduce this mod m */
- mod: function(m) {
+ mod: function(m1) {
var k = 0,
r = new BIG(0);
+ var m=new BIG(0); m.copy(m1);
this.norm();
@@ -577,12 +577,13 @@ BIG = function(ctx) {
}
},
/* this/=m */
- div: function(m) {
+ div: function(m1) {
var k = 0,
d = 0,
e = new BIG(1),
b = new BIG(0),
r = new BIG(0);
+ var m=new BIG(0); m.copy(m1);
this.norm();
b.copy(this);
@@ -761,12 +762,13 @@ BIG = function(ctx) {
},
/* return this^e mod m */
- powmod: function(e, m) {
+ powmod: function(e1, m) {
var a = new BIG(1),
z = new BIG(0),
s = new BIG(0),
bt;
+ var e=new BIG(0); e.copy(e1);
this.norm();
e.norm();
z.copy(e);
@@ -790,6 +792,23 @@ BIG = function(ctx) {
}
};
+ BIG.ssn = function(r,a,m) {
+ var n=BIG.NLEN-1;
+ m.w[0]=(m.w[0]>>1)|((m.w[1]<<(BIG.BASEBITS-1))&BIG.BMASK);
+ r.w[0]=a.w[0]-m.w[0];
+ var carry=r.w[0]>>BIG.BASEBITS;
+ r.w[0]&=BIG.BMASK;
+ for (var i=1;i<n;i++) {
+ m.w[i]=(m.w[i]>>1)|((m.w[i+1]<<(BIG.BASEBITS-1))&BIG.BMASK);
+ r.w[i]=a.w[i]-m.w[i]+carry;
+ carry=r.w[i]>>BIG.BASEBITS;
+ r.w[i]&=BIG.BMASK;
+ }
+ m.w[n]>>=1;
+ r.w[n]=a.w[n]-m.w[n]+carry;
+ return ((r.w[n]>>(BIG.CHUNK-1))&1);
+ };
+
/* convert from byte array to BIG */
BIG.frombytearray = function(b, n) {
var m = new BIG(0),
@@ -861,7 +880,7 @@ BIG = function(ctx) {
b = r & 1;
m.shl(1);
- m.w[0] += b;
+ m.w[0] += b; // m.inc(b);
j++;
j &= 7;
}
@@ -897,7 +916,7 @@ BIG = function(ctx) {
/* return a*b as ctx.DBIG */
BIG.mul = function(a, b) {
var c = new ctx.DBIG(0),
- d = [],
+ d = new Array(BIG.NLEN), //[],
n, s, t, i, k, co;
for (i = 0; i < BIG.NLEN; i++) {
@@ -940,7 +959,7 @@ BIG = function(ctx) {
BIG.sqr = function(a) {
var c = new ctx.DBIG(0),
n, t, j, i, co;
-
+
c.w[0] = a.w[0] * a.w[0];
for (j = 1; j < BIG.NLEN - 1;) {
@@ -999,8 +1018,8 @@ BIG = function(ctx) {
BIG.monty = function(m, nd, d) {
var b = new BIG(0),
- v = [],
- dd = [],
+ v = new Array(BIG.NLEN),
+ dd = new Array(BIG.NLEN),
s, c, t, i, k;
t = d.w[0];
@@ -1039,9 +1058,10 @@ BIG = function(ctx) {
};
/* return a*b mod m */
- BIG.modmul = function(a, b, m) {
+ BIG.modmul = function(a1, b1, m) {
var d;
-
+ var a=new BIG(0); a.copy(a1);
+ var b=new BIG(0); b.copy(b1);
a.mod(m);
b.mod(m);
d = BIG.mul(a, b);
@@ -1050,9 +1070,9 @@ BIG = function(ctx) {
};
/* return a^2 mod m */
- BIG.modsqr = function(a, m) {
+ BIG.modsqr = function(a1, m) {
var d;
-
+ var a=new BIG(0); a.copy(a1);
a.mod(m);
d = BIG.sqr(a);
@@ -1060,7 +1080,8 @@ BIG = function(ctx) {
};
/* return -a mod m */
- BIG.modneg = function(a, m) {
+ BIG.modneg = function(a1, m) {
+ var a=new BIG(0); a.copy(a1);
a.mod(m);
return m.minus(a);
};
@@ -1114,7 +1135,7 @@ DBIG = function(ctx) {
/* constructor */
var DBIG = function(x) {
- this.w = [];
+ this.w = new Array(BIG.DNLEN);
this.zero();
this.w[0] = x;
};
@@ -1266,9 +1287,10 @@ DBIG = function(ctx) {
var k = ctx.BIG.DNLEN - 1,
bts, c;
- this.norm();
+ var t=new DBIG(0); t.copy(this);
+ t.norm();
- while (k >= 0 && this.w[k] === 0) {
+ while (k >= 0 && t.w[k] === 0) {
k--;
}
@@ -1277,7 +1299,7 @@ DBIG = function(ctx) {
}
bts = ctx.BIG.BASEBITS * k;
- c = this.w[k];
+ c = t.w[k];
while (c !== 0) {
c = Math.floor(c / 2);
@@ -1337,7 +1359,6 @@ DBIG = function(ctx) {
dr.sub(m);
dr.norm();
this.cmove(dr, (1 - ((dr.w[ctx.BIG.DNLEN - 1] >> (ctx.BIG.CHUNK - 1)) & 1)));
-
k--;
}
diff --git a/src/bls.js b/src/bls.js
new file mode 100644
index 0000000..8149915
--- /dev/null
+++ b/src/bls.js
@@ -0,0 +1,127 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* BLS API Functions */
+
+var BLS = function(ctx) {
+ "use strict";
+
+ var BLS = {
+ BLS_OK: 0,
+ BLS_FAIL: -1,
+
+ BFS: ctx.BIG.MODBYTES,
+ BGS: ctx.BIG.MODBYTES,
+
+ bytestostring: function(b) {
+ var s = "",
+ len = b.length,
+ ch, i;
+
+ for (i = 0; i < len; i++) {
+ ch = b[i];
+ s += ((ch >>> 4) & 15).toString(16);
+ s += (ch & 15).toString(16);
+
+ }
+
+ return s;
+ },
+
+ stringtobytes: function(s) {
+ var b = [],
+ i;
+
+ for (i = 0; i < s.length; i++) {
+ b.push(s.charCodeAt(i));
+ }
+
+ return b;
+ },
+
+/* hash a message to an ECP point, using SHA3 */
+
+ bls_hashit: function(m) {
+ var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+ var hm = [];
+ var t=this.stringtobytes(m);
+ for (var i=0;i<t.length;i++)
+ sh.process(t[i]);
+ sh.shake(hm,this.BFS);
+ var P=ctx.ECP.mapit(hm);
+ return P;
+ },
+
+/* generate key pair, private key S, public key W */
+
+ KeyPairGenerate(rng,S,W) {
+ var G=ctx.ECP2.generator();
+ var q=new ctx.BIG(0);
+ q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+ var s=ctx.BIG.randomnum(q,rng);
+ s.toBytes(S);
+ G = ctx.PAIR.G2mul(G,s);
+
+ G.toBytes(W); // To use point compression on public keys, change to true
+ return this.BLS_OK;
+ },
+
+/* Sign message m using private key S to produce signature SIG */
+
+ sign(SIG,m,S) {
+ var D=this.bls_hashit(m);
+ var s=ctx.BIG.fromBytes(S);
+ D=ctx.PAIR.G1mul(D,s);
+ D.toBytes(SIG,true);
+ return this.BLS_OK;
+ },
+
+/* Verify signature given message m, the signature SIG, and the public key W */
+
+ verify(SIG,m,W) {
+ var HM=this.bls_hashit(m);
+ var D=ctx.ECP.fromBytes(SIG);
+ var G=ctx.ECP2.generator();
+ var PK=ctx.ECP2.fromBytes(W);
+ D.neg();
+
+// Use new multi-pairing mechanism
+ var r=ctx.PAIR.initmp();
+ ctx.PAIR.another(r,G,D);
+ ctx.PAIR.another(r,PK,HM);
+ var v=ctx.PAIR.miller(r);
+
+//.. or alternatively
+// var v=ctx.PAIR.ate2(G,D,PK,HM);
+
+ v=ctx.PAIR.fexp(v);
+ if (v.isunity())
+ return this.BLS_OK;
+ return this.BLS_FAIL;
+ }
+ };
+
+ return BLS;
+};
+
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
+ module.exports = {
+ BLS: BLS
+ };
+}
diff --git a/src/bls192.js b/src/bls192.js
new file mode 100644
index 0000000..64dbd3c
--- /dev/null
+++ b/src/bls192.js
@@ -0,0 +1,126 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* BLS API Functions */
+
+var BLS192 = function(ctx) {
+ "use strict";
+
+ var BLS192 = {
+ BLS_OK: 0,
+ BLS_FAIL: -1,
+
+ BFS: ctx.BIG.MODBYTES,
+ BGS: ctx.BIG.MODBYTES,
+
+ bytestostring: function(b) {
+ var s = "",
+ len = b.length,
+ ch, i;
+
+ for (i = 0; i < len; i++) {
+ ch = b[i];
+ s += ((ch >>> 4) & 15).toString(16);
+ s += (ch & 15).toString(16);
+
+ }
+
+ return s;
+ },
+
+ stringtobytes: function(s) {
+ var b = [],
+ i;
+
+ for (i = 0; i < s.length; i++) {
+ b.push(s.charCodeAt(i));
+ }
+
+ return b;
+ },
+
+/* hash a message to an ECP point, using SHA3 */
+
+ bls_hashit: function(m) {
+ var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+ var hm = [];
+ var t=this.stringtobytes(m);
+ for (var i=0;i<t.length;i++)
+ sh.process(t[i]);
+ sh.shake(hm,this.BFS);
+ var P=ctx.ECP.mapit(hm);
+ return P;
+ },
+
+/* generate key pair, private key S, public key W */
+
+ KeyPairGenerate(rng,S,W) {
+ var G=ctx.ECP4.generator();
+ var q=new ctx.BIG(0);
+ q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+ var s=ctx.BIG.randomnum(q,rng);
+ s.toBytes(S);
+ G = ctx.PAIR192.G2mul(G,s);
+ G.toBytes(W); // To use point compression on public keys, change to true
+ return this.BLS_OK;
+
+ },
+
+/* Sign message m using private key S to produce signature SIG */
+
+ sign(SIG,m,S) {
+ var D=this.bls_hashit(m);
+ var s=ctx.BIG.fromBytes(S);
+ D=ctx.PAIR192.G1mul(D,s);
+ D.toBytes(SIG,true);
+ return this.BLS_OK;
+ },
+
+/* Verify signature given message m, the signature SIG, and the public key W */
+
+ verify(SIG,m,W) {
+ var HM=this.bls_hashit(m);
+ var D=ctx.ECP.fromBytes(SIG);
+ var G=ctx.ECP4.generator();
+ var PK=ctx.ECP4.fromBytes(W);
+ D.neg();
+
+// Use new multi-pairing mechanism
+ var r=ctx.PAIR192.initmp();
+ ctx.PAIR192.another(r,G,D);
+ ctx.PAIR192.another(r,PK,HM);
+ var v=ctx.PAIR192.miller(r);
+
+//.. or alternatively
+// var v=ctx.PAIR192.ate2(G,D,PK,HM);
+ v=ctx.PAIR192.fexp(v);
+ if (v.isunity())
+ return this.BLS_OK;
+ return this.BLS_FAIL;
+ }
+ };
+
+ return BLS192;
+};
+
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
+ module.exports = {
+ BLS192: BLS192
+ };
+}
diff --git a/src/bls256.js b/src/bls256.js
new file mode 100644
index 0000000..a154fe4
--- /dev/null
+++ b/src/bls256.js
@@ -0,0 +1,129 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* BLS API Functions */
+
+var BLS256 = function(ctx) {
+ "use strict";
+
+ var BLS256 = {
+ BLS_OK: 0,
+ BLS_FAIL: -1,
+
+ BFS: ctx.BIG.MODBYTES,
+ BGS: ctx.BIG.MODBYTES,
+
+ bytestostring: function(b) {
+ var s = "",
+ len = b.length,
+ ch, i;
+
+ for (i = 0; i < len; i++) {
+ ch = b[i];
+ s += ((ch >>> 4) & 15).toString(16);
+ s += (ch & 15).toString(16);
+
+ }
+
+ return s;
+ },
+
+ stringtobytes: function(s) {
+ var b = [],
+ i;
+
+ for (i = 0; i < s.length; i++) {
+ b.push(s.charCodeAt(i));
+ }
+
+ return b;
+ },
+
+/* hash a message to an ECP point, using SHA3 */
+
+ bls_hashit: function(m) {
+ var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+ var hm = [];
+ var t=this.stringtobytes(m);
+ for (var i=0;i<t.length;i++)
+ sh.process(t[i]);
+ sh.shake(hm,this.BFS);
+ var P=ctx.ECP.mapit(hm);
+ return P;
+ },
+
+/* generate key pair, private key S, public key W */
+
+ KeyPairGenerate(rng,S,W) {
+ var G=ctx.ECP8.generator();
+ var q=new ctx.BIG(0);
+ q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+ var s=ctx.BIG.randomnum(q,rng);
+ s.toBytes(S);
+ G = ctx.PAIR256.G2mul(G,s);
+ G.toBytes(W); // To use point compression on public keys, change to true
+ return this.BLS_OK;
+
+ },
+
+/* Sign message m using private key S to produce signature SIG */
+
+ sign(SIG,m,S) {
+ var D=this.bls_hashit(m);
+ var s=ctx.BIG.fromBytes(S);
+ D=ctx.PAIR256.G1mul(D,s);
+ D.toBytes(SIG,true);
+ return this.BLS_OK;
+ },
+
+/* Verify signature given message m, the signature SIG, and the public key W */
+
+ verify(SIG,m,W) {
+ var HM=this.bls_hashit(m);
+ var D=ctx.ECP.fromBytes(SIG);
+ var G=ctx.ECP8.generator();
+ var PK=ctx.ECP8.fromBytes(W);
+ D.neg();
+
+// Use new multi-pairing mechanism
+ var r=ctx.PAIR256.initmp();
+ ctx.PAIR256.another(r,G,D);
+ ctx.PAIR256.another(r,PK,HM);
+ var v=ctx.PAIR256.miller(r);
+
+//.. or alternatively
+// var v=ctx.PAIR256.ate2(G,D,PK,HM);
+
+ v=ctx.PAIR256.fexp(v);
+ if (v.isunity())
+ return this.BLS_OK;
+ return this.BLS_FAIL;
+ }
+ };
+
+ return BLS256;
+};
+
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
+ module.exports = {
+ BLS256: BLS256
+ };
+}
+
+
diff --git a/src/ctx.js b/src/ctx.js
index 0513b31..3af2784 100644
--- a/src/ctx.js
+++ b/src/ctx.js
@@ -24,37 +24,24 @@ var CTX = function(input_parameter) {
CTXLIST,
prepareModule;
- /**
- * Config fields:
- * NB : Number of bytes in Modulus
- * BASE : Number base as power of 2
- * NBT : Number of bits in Modulus
- * M8 : Modulus mod 8
- * MT : Modulus Type (Pseudo-Mersenne,...)
- * CT : Curve Type (Weierstrass,...)
- * PF : Pairing Friendly
- * ST : Sextic Twist Type
- * SX : Sign of x parameter
- * HT : Hash output size
- * AK : AES key size
- */
-
CTXLIST = {
"ED25519": {
"BITS": "256",
"FIELD": "25519",
"CURVE": "ED25519",
- "@NB": 32,
- "@BASE": 24,
- "@NBT": 255,
- "@M8": 5,
- "@MT": 1,
- "@CT": 1,
- "@PF": 0,
- "@ST": 0,
- "@SX": 0,
- "@HT": 32,
- "@AK": 16
+ "@NB": 32, /* Number of bytes in Modulus */
+ "@BASE": 24, /* Number base as power of 2 */
+ "@NBT": 255, /* Number of bits in modulus */
+ "@M8": 5, /* Modulus mod 8 */
+ "@MT": 1, /* Modulus Type (pseudo-mersenne,...) */
+ "@CT": 1, /* Curve Type (Weierstrass,...) */
+ "@PF": 0, /* Pairing Friendly */
+ "@ST": 0, /* Sextic Twist Type */
+ "@SX": 0, /* Sign of x parameter */
+ "@AB": 0, /* ATE parameter size */
+ "@HT": 32, /* Hash output size */
+ "@SH": 9, /* Maximum field excess */
+ "@AK": 16 /* AES key size */
},
"C25519": {
@@ -70,7 +57,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 9,
"@AK": 16
},
@@ -88,7 +77,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -105,7 +96,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -122,7 +115,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
+ "@SH": 7,
"@AK": 24
},
@@ -139,7 +134,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -156,7 +153,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -173,7 +172,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
+ "@SH": 9,
"@AK": 24
},
@@ -190,7 +191,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
+ "@SH": 11,
"@AK": 32
},
@@ -207,7 +210,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
+ "@SH": 4,
"@AK": 32
},
@@ -224,7 +229,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
+ "@SH": 8,
"@AK": 32
},
@@ -241,7 +248,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -258,7 +267,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -275,7 +286,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
+ "@SH": 7,
"@AK": 24
},
@@ -292,7 +305,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
+ "@SH": 7,
"@AK": 24
},
@@ -309,7 +324,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
+ "@SH": 11,
"@AK": 32
},
@@ -326,7 +343,9 @@ var CTX = function(input_parameter) {
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
+ "@SH": 11,
"@AK": 32
},
@@ -343,7 +362,9 @@ var CTX = function(input_parameter) {
"@PF": 1,
"@ST": 1,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -360,7 +381,9 @@ var CTX = function(input_parameter) {
"@PF": 1,
"@ST": 1,
"@SX": 0,
+ "@AB": 130,
"@HT": 32,
+ "@SH": 11,
"@AK": 16
},
@@ -377,7 +400,9 @@ var CTX = function(input_parameter) {
"@PF": 1,
"@ST": 0,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
+ "@SH": 10,
"@AK": 16
},
@@ -394,7 +419,9 @@ var CTX = function(input_parameter) {
"@PF": 1,
"@ST": 0,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
+ "@SH": 10,
"@AK": 16
},
@@ -411,7 +438,9 @@ var CTX = function(input_parameter) {
"@PF": 2,
"@ST": 1,
"@SX": 0,
+ "@AB": 65,
"@HT": 32,
+ "@SH": 8,
"@AK": 16
},
@@ -428,7 +457,9 @@ var CTX = function(input_parameter) {
"@PF": 3,
"@ST": 1,
"@SX": 0,
+ "@AB": 49,
"@HT": 48,
+ "@SH": 4,
"@AK": 24
},
@@ -445,7 +476,9 @@ var CTX = function(input_parameter) {
"@PF": 4,
"@ST": 1,
"@SX": 0,
+ "@AB": 32,
"@HT": 64,
+ "@SH": 11,
"@AK": 32
},
@@ -462,7 +495,9 @@ var CTX = function(input_parameter) {
"@PF": 2,
"@ST": 1,
"@SX": 1,
+ "@AB": 65,
"@HT": 32,
+ "@SH": 10,
"@AK": 16
},
@@ -479,7 +514,9 @@ var CTX = function(input_parameter) {
"@PF": 2,
"@ST": 1,
"@SX": 1,
+ "@AB": 78,
"@HT": 32,
+ "@SH": 11,
"@AK": 16
},
@@ -532,7 +569,6 @@ var CTX = function(input_parameter) {
prepareModule("HASH512");
prepareModule("SHA3");
prepareModule("RAND");
- prepareModule("NHS");
if (typeof input_parameter === "undefined") {
return;
@@ -570,6 +606,8 @@ var CTX = function(input_parameter) {
prepareModule("ECP2");
prepareModule("PAIR");
prepareModule("MPIN");
+ prepareModule("BLS");
+
}
if (ctx.config["@PF"] == 3) {
@@ -580,6 +618,7 @@ var CTX = function(input_parameter) {
prepareModule("ECP4");
prepareModule("PAIR192");
prepareModule("MPIN192");
+ prepareModule("BLS192");
}
if (ctx.config["@PF"] == 4) {
@@ -591,6 +630,7 @@ var CTX = function(input_parameter) {
prepareModule("ECP8");
prepareModule("PAIR256");
prepareModule("MPIN256");
+ prepareModule("BLS256");
}
return;
diff --git a/src/ecdh.js b/src/ecdh.js
index 6abba53..416c74c 100644
--- a/src/ecdh.js
+++ b/src/ecdh.js
@@ -57,7 +57,8 @@ var ECDH = function(ctx) {
for (i = 0; i < len; i++) {
ch = b[i];
- s += String.fromCharCode(ch);
+ s += ((ch >>> 4) & 15).toString(16);
+ s += (ch & 15).toString(16);
}
return s;
@@ -76,7 +77,7 @@ var ECDH = function(ctx) {
hashit: function(sha, A, n, B, pad) {
var R = [],
- H, W, i;
+ H, W, i, len;
if (sha == this.SHA256) {
H = new ctx.HASH256();
@@ -104,16 +105,18 @@ var ECDH = function(ctx) {
W = [];
- if (sha >= pad) {
- for (i = 0; i < pad; i++) {
+ len = pad;
+
+ if (sha >= len) {
+ for (i = 0; i < len; i++) {
W[i] = R[i];
}
} else {
for (i = 0; i < sha; i++) {
- W[i + pad - sha] = R[i];
+ W[i + len - sha] = R[i];
}
- for (i = 0; i < pad - sha; i++) {
+ for (i = 0; i < len - sha; i++) {
W[i] = 0;
}
}
@@ -261,6 +264,7 @@ var ECDH = function(ctx) {
K0 = new Array(b);
+ //b=K0.length;
if (olen < 4) {
return 0;
}
@@ -424,6 +428,7 @@ var ECDH = function(ctx) {
KEY_PAIR_GENERATE: function(RNG, S, W) {
var res = 0,
r, s, G, WP;
+ // var T=[];
G = ctx.ECP.generator();
@@ -440,7 +445,7 @@ var ECDH = function(ctx) {
s.toBytes(S);
WP = G.mul(s);
- WP.toBytes(W,false);
+ WP.toBytes(W,false); // To use point compression on public keys, change to true
return res;
},
@@ -536,7 +541,7 @@ var ECDH = function(ctx) {
do {
u = ctx.BIG.randomnum(r, RNG);
- w = ctx.BIG.randomnum(r, RNG);
+ w = ctx.BIG.randomnum(r, RNG); /* side channel masking */
V.copy(G);
V = V.mul(u);
vx = V.getX();
@@ -666,6 +671,16 @@ var ECDH = function(ctx) {
return C;
},
+ ncomp: function(T1,T2,n) {
+ var res=0;
+ for (var i=0;i<n;i++)
+ {
+ res|=(T1[i]^T2[i]);
+ }
+ if (res==0) return true;
+ return false;
+ },
+
ECIES_DECRYPT: function(sha, P1, P2, V, C, T, U) {
var Z = [],
VZ = [],
@@ -716,16 +731,9 @@ var ECDH = function(ctx) {
this.HMAC(sha, AC, K2, TAG);
- same = true;
- for (i = 0; i < T.length; i++) {
- if (T[i] != TAG[i]) {
- same = false;
- }
- }
-
- if (!same) {
- return [];
- }
+ if (!this.ncomp(T,TAG,T.length)) {
+ return [];
+ }
return M;
}
diff --git a/src/ecp.js b/src/ecp.js
index ba045fd..97c2918 100644
--- a/src/ecp.js
+++ b/src/ecp.js
@@ -48,6 +48,7 @@ var ECP = function(ctx) {
ECP.CURVE_PAIRING_TYPE = ctx.config["@PF"];
ECP.SEXTIC_TWIST = ctx.config["@ST"];
ECP.SIGN_OF_X = ctx.config["@SX"];
+ ECP.ATE_BITS = ctx.config["@AB"];
ECP.HASH_TYPE = ctx.config["@HT"];
ECP.AESKEY = ctx.config["@AK"];
@@ -55,11 +56,14 @@ var ECP = function(ctx) {
ECP.prototype = {
/* test this=O point-at-infinity */
is_infinity: function() {
+
this.x.reduce();
this.z.reduce();
if (ECP.CURVETYPE == ECP.EDWARDS) {
+
this.y.reduce();
+
return (this.x.iszilch() && this.y.equals(this.z));
} else if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
this.y.reduce();
@@ -73,20 +77,24 @@ var ECP = function(ctx) {
/* conditional swap of this and Q dependant on d */
cswap: function(Q, d) {
+
this.x.cswap(Q.x, d);
if (ECP.CURVETYPE != ECP.MONTGOMERY) {
this.y.cswap(Q.y, d);
}
this.z.cswap(Q.z, d);
+
},
/* conditional move of Q to P dependant on d */
cmove: function(Q, d) {
+
this.x.cmove(Q.x, d);
if (ECP.CURVETYPE != ECP.MONTGOMERY) {
this.y.cmove(Q.y, d);
}
this.z.cmove(Q.z, d);
+
},
/* Constant time select from pre-computed table */
@@ -191,12 +199,14 @@ var ECP = function(ctx) {
this.y = new ctx.FP(0);
this.y.bcopy(iy);
this.z = new ctx.FP(1);
+ this.x.norm();
rhs = ECP.RHS(this.x);
if (ECP.CURVETYPE == ECP.MONTGOMERY) {
if (rhs.jacobi() != 1) {
this.inf();
}
+
} else {
y2 = new ctx.FP(0);
y2.copy(this.y);
@@ -214,6 +224,7 @@ var ECP = function(ctx) {
this.x = new ctx.FP(0);
this.x.bcopy(ix);
+ this.x.norm();
rhs = ECP.RHS(this.x);
this.z = new ctx.FP(1);
@@ -234,6 +245,7 @@ var ECP = function(ctx) {
this.x = new ctx.FP(0);
this.x.bcopy(ix);
+ this.x.norm();
rhs = ECP.RHS(this.x);
this.z = new ctx.FP(1);
@@ -278,19 +290,18 @@ var ECP = function(ctx) {
/* extract x as ctx.BIG */
getX: function() {
- this.affine();
- return this.x.redc();
+ var W=new ECP(); W.copy(this); W.affine();
+ return W.x.redc();
},
/* extract y as ctx.BIG */
getY: function() {
- this.affine();
- return this.y.redc();
+ var W=new ECP(); W.copy(this); W.affine();
+ return W.y.redc();
},
/* get sign of Y */
getS: function() {
- this.affine();
var y = this.getY();
return y.parity();
},
@@ -311,42 +322,50 @@ var ECP = function(ctx) {
},
/* convert to byte array */
- toBytes: function(b) {
+ toBytes: function(b,compress) {
var t = [],
i;
-
- if (ECP.CURVETYPE != ECP.MONTGOMERY) {
- b[0] = 0x04;
- } else {
- b[0] = 0x02;
- }
-
- this.affine();
- this.x.redc().toBytes(t);
+ var W=new ECP(); W.copy(this);
+ W.affine();
+ W.x.redc().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 1] = t[i];
}
- if (ECP.CURVETYPE != ECP.MONTGOMERY) {
- this.y.redc().toBytes(t);
- for (i = 0; i < ctx.BIG.MODBYTES; i++) {
- b[i + ctx.BIG.MODBYTES + 1] = t[i];
+ if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+ b[0] = 0x06;
+ return;
+ }
+
+ if (compress) {
+ b[0]=0x02;
+ if (W.y.redc().parity()==1) {
+ b[0]=0x03;
}
+ return;
+ }
+
+ b[0]=0x04;
+
+ W.y.redc().toBytes(t);
+ for (i = 0; i < ctx.BIG.MODBYTES; i++) {
+ b[i + ctx.BIG.MODBYTES + 1] = t[i];
}
},
/* convert to hex string */
toString: function() {
- if (this.is_infinity()) {
+ var W=new ECP(); W.copy(this);
+ if (W.is_infinity()) {
return "infinity";
}
- this.affine();
+ W.affine();
if (ECP.CURVETYPE == ECP.MONTGOMERY) {
- return "(" + this.x.redc().toString() + ")";
+ return "(" + W.x.redc().toString() + ")";
} else {
- return "(" + this.x.redc().toString() + "," + this.y.redc().toString() + ")";
+ return "(" + W.x.redc().toString() + "," + W.y.redc().toString() + ")";
}
},
@@ -360,13 +379,13 @@ var ECP = function(ctx) {
if (ctx.ROM_CURVE.CURVE_A == 0) {
t0 = new ctx.FP(0);
- t0.copy(this.y);
+ t0.copy(this.y);
t0.sqr();
t1 = new ctx.FP(0);
- t1.copy(this.y);
+ t1.copy(this.y);
t1.mul(this.z);
t2 = new ctx.FP(0);
- t2.copy(this.z);
+ t2.copy(this.z);
t2.sqr();
this.z.copy(t0);
@@ -379,10 +398,10 @@ var ECP = function(ctx) {
t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
x3 = new ctx.FP(0);
- x3.copy(t2);
+ x3.copy(t2);
x3.mul(this.z);
y3 = new ctx.FP(0);
- y3.copy(t0);
+ y3.copy(t0);
y3.add(t2);
y3.norm();
this.z.mul(t1);
@@ -405,21 +424,23 @@ var ECP = function(ctx) {
this.y.norm();
} else {
t0 = new ctx.FP(0);
- t0.copy(this.x);
+ t0.copy(this.x);
t1 = new ctx.FP(0);
- t1.copy(this.y);
+ t1.copy(this.y);
t2 = new ctx.FP(0);
- t2.copy(this.z);
+ t2.copy(this.z);
t3 = new ctx.FP(0);
- t3.copy(this.x);
+ t3.copy(this.x);
z3 = new ctx.FP(0);
- z3.copy(this.z);
- y3 = new ctx.FP(0);
- x3 = new ctx.FP(0);
- b = new ctx.FP(0);
+ z3.copy(this.z);
+ y3 = new ctx.FP(0);
+ x3 = new ctx.FP(0);
+ b = new ctx.FP(0);
+
if (ctx.ROM_CURVE.CURVE_B_I == 0) {
b.rcopy(ctx.ROM_CURVE.CURVE_B);
}
+
t0.sqr(); //1 x^2
t1.sqr(); //2 y^2
t2.sqr(); //3
@@ -452,8 +473,8 @@ var ECP = function(ctx) {
y3.mul(x3); //14
x3.mul(t3); //15
t3.copy(t2);
- t3.add(t2); //16
- t2.add(t3); //17
+ t3.add(t2); //16
+ t2.add(t3); //17
if (ctx.ROM_CURVE.CURVE_B_I == 0) {
z3.mul(b); //18
@@ -489,6 +510,7 @@ var ECP = function(ctx) {
t1.norm(); //33
z3.copy(t0);
z3.mul(t1); //34
+
this.x.copy(x3);
this.x.norm();
this.y.copy(y3);
@@ -500,12 +522,13 @@ var ECP = function(ctx) {
if (ECP.CURVETYPE == ECP.EDWARDS) {
C = new ctx.FP(0);
- C.copy(this.x);
+ C.copy(this.x);
D = new ctx.FP(0);
- D.copy(this.y);
+ D.copy(this.y);
H = new ctx.FP(0);
- H.copy(this.z);
- J = new ctx.FP(0);
+ H.copy(this.z);
+ J = new ctx.FP(0);
+
this.x.mul(this.y);
this.x.add(this.x);
this.x.norm();
@@ -536,12 +559,12 @@ var ECP = function(ctx) {
if (ECP.CURVETYPE == ECP.MONTGOMERY) {
A = new ctx.FP(0);
- A.copy(this.x);
+ A.copy(this.x);
B = new ctx.FP(0);
- B.copy(this.x);
- AA = new ctx.FP(0);
- BB = new ctx.FP(0);
- C = new ctx.FP(0);
+ B.copy(this.x);
+ AA = new ctx.FP(0);
+ BB = new ctx.FP(0);
+ C = new ctx.FP(0);
A.add(this.z);
A.norm();
@@ -579,20 +602,20 @@ var ECP = function(ctx) {
b = 3 * ctx.ROM_CURVE.CURVE_B_I;
t0 = new ctx.FP(0);
- t0.copy(this.x);
+ t0.copy(this.x);
t0.mul(Q.x);
t1 = new ctx.FP(0);
- t1.copy(this.y);
+ t1.copy(this.y);
t1.mul(Q.y);
t2 = new ctx.FP(0);
- t2.copy(this.z);
+ t2.copy(this.z);
t2.mul(Q.z);
t3 = new ctx.FP(0);
- t3.copy(this.x);
+ t3.copy(this.x);
t3.add(this.y);
t3.norm();
t4 = new ctx.FP(0);
- t4.copy(Q.x);
+ t4.copy(Q.x);
t4.add(Q.y);
t4.norm();
t3.mul(t4);
@@ -605,7 +628,7 @@ var ECP = function(ctx) {
t4.add(this.z);
t4.norm();
x3 = new ctx.FP(0);
- x3.copy(Q.y);
+ x3.copy(Q.y);
x3.add(Q.z);
x3.norm();
@@ -619,7 +642,7 @@ var ECP = function(ctx) {
x3.add(this.z);
x3.norm();
y3 = new ctx.FP(0);
- y3.copy(Q.x);
+ y3.copy(Q.x);
y3.add(Q.z);
y3.norm();
x3.mul(y3);
@@ -634,7 +657,7 @@ var ECP = function(ctx) {
t2.imul(b);
z3 = new ctx.FP(0);
- z3.copy(t1);
+ z3.copy(t1);
z3.add(t2);
z3.norm();
t1.sub(t2);
@@ -661,21 +684,21 @@ var ECP = function(ctx) {
this.z.norm();
} else {
t0 = new ctx.FP(0);
- t0.copy(this.x);
+ t0.copy(this.x);
t1 = new ctx.FP(0);
- t1.copy(this.y);
+ t1.copy(this.y);
t2 = new ctx.FP(0);
- t2.copy(this.z);
+ t2.copy(this.z);
t3 = new ctx.FP(0);
- t3.copy(this.x);
+ t3.copy(this.x);
t4 = new ctx.FP(0);
- t4.copy(Q.x);
- z3 = new ctx.FP(0);
+ t4.copy(Q.x);
+ z3 = new ctx.FP(0);
y3 = new ctx.FP(0);
- y3.copy(Q.x);
+ y3.copy(Q.x);
x3 = new ctx.FP(0);
- x3.copy(Q.y);
- b = new ctx.FP(0);
+ x3.copy(Q.y);
+ b = new ctx.FP(0);
if (ctx.ROM_CURVE.CURVE_B_I == 0) {
b.rcopy(ctx.ROM_CURVE.CURVE_B);
@@ -690,7 +713,7 @@ var ECP = function(ctx) {
t4.norm(); //5
t3.mul(t4); //6
t4.copy(t0);
- t4.add(t1); //7
+ t4.add(t1); //7
t3.sub(t4);
t3.norm(); //8
t4.copy(this.y);
@@ -728,9 +751,9 @@ var ECP = function(ctx) {
x3.sub(z3);
x3.norm(); //20
z3.copy(x3);
- z3.add(x3); //21
+ z3.add(x3); //21
- x3.add(z3); //22
+ x3.add(z3); //22
z3.copy(t1);
z3.sub(x3);
z3.norm(); //23
@@ -747,7 +770,7 @@ var ECP = function(ctx) {
t1.add(t2); //26
t2.add(t1); //27
- y3.sub(t2); //28
+ y3.sub(t2); //28
y3.sub(t0);
y3.norm(); //29
@@ -773,7 +796,8 @@ var ECP = function(ctx) {
z3.mul(t4); //41
t1.copy(t3);
t1.mul(t0); //42
- z3.add(t1);
+ z3.add(t1);
+
this.x.copy(x3);
this.x.norm();
this.y.copy(y3);
@@ -785,15 +809,15 @@ var ECP = function(ctx) {
if (ECP.CURVETYPE == ECP.EDWARDS) {
A = new ctx.FP(0);
- A.copy(this.z);
- B = new ctx.FP(0);
+ A.copy(this.z);
+ B = new ctx.FP(0);
C = new ctx.FP(0);
- C.copy(this.x);
+ C.copy(this.x);
D = new ctx.FP(0);
- D.copy(this.y);
- E = new ctx.FP(0);
- F = new ctx.FP(0);
- G = new ctx.FP(0);
+ D.copy(this.y);
+ E = new ctx.FP(0);
+ F = new ctx.FP(0);
+ G = new ctx.FP(0);
A.mul(Q.z); //A=2
B.copy(A);
@@ -900,13 +924,15 @@ var ECP = function(ctx) {
this.x.copy(A);
this.z.copy(W.x);
this.z.mul(B);
+
+ // this.x.norm();
},
/* this-=Q */
sub: function(Q) {
- Q.neg();
- this.add(Q);
- Q.neg();
+ var NQ = new ECP(); NQ.copy(Q);
+ NQ.neg();
+ this.add(NQ);
},
/* constant time multiply by small integer of length bts - use ladder */
@@ -947,12 +973,10 @@ var ECP = function(ctx) {
}
if (cf==4) {
this.dbl(); this.dbl();
- this.affine();
return;
}
if (cf==8) {
this.dbl(); this.dbl(); this.dbl();
- this.affine();
return;
}
c.rcopy(ctx.ROM_CURVE.CURVE_Cof);
@@ -1001,8 +1025,6 @@ var ECP = function(ctx) {
W = [];
w = [];
- this.affine();
-
// precompute table
Q.copy(this);
Q.dbl();
@@ -1070,9 +1092,6 @@ var ECP = function(ctx) {
i, s, ns, nb,
a, b;
- this.affine();
- Q.affine();
-
te.copy(e);
tf.copy(f);
@@ -1205,6 +1224,11 @@ var ECP = function(ctx) {
return P;
}
+ if (ECP.CURVETYPE == ECP.MONTGOMERY) {
+ P.setx(px);
+ return P;
+ }
+
if (b[0] == 0x04) {
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = b[i + ctx.BIG.MODBYTES + 1];
@@ -1219,10 +1243,14 @@ var ECP = function(ctx) {
P.setxy(px, py);
return P;
- } else {
- P.setx(px);
+ }
+
+ if (b[0]==0x02 || b[0]==0x03) {
+ P.setxi(px,b[0]&1);
return P;
}
+
+ return P;
};
/* Calculate RHS of curve equation */
@@ -1230,7 +1258,7 @@ var ECP = function(ctx) {
var r = new ctx.FP(0),
b, cx, one, x3;
- x.norm();
+ //x.norm();
r.copy(x);
r.sqr();
diff --git a/src/ecp2.js b/src/ecp2.js
index 77ef534..b8ce9af 100644
--- a/src/ecp2.js
+++ b/src/ecp2.js
@@ -32,6 +32,7 @@ var ECP2 = function(ctx) {
ECP2.prototype = {
/* Test this=O? */
is_infinity: function() {
+
this.x.reduce();
this.y.reduce();
this.z.reduce();
@@ -149,14 +150,14 @@ var ECP2 = function(ctx) {
/* extract affine x as ctx.FP2 */
getX: function() {
- this.affine();
- return this.x;
+ var W=new ECP2(); W.copy(this); W.affine();
+ return W.x;
},
/* extract affine y as ctx.FP2 */
getY: function() {
- this.affine();
- return this.y;
+ var W=new ECP2(); W.copy(this); W.affine();
+ return W.y;
},
/* extract projective x */
@@ -178,22 +179,22 @@ var ECP2 = function(ctx) {
toBytes: function(b) {
var t = [],
i;
-
- this.affine();
- this.x.getA().toBytes(t);
+ var W=new ECP2(); W.copy(this);
+ W.affine();
+ W.x.getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i] = t[i];
}
- this.x.getB().toBytes(t);
+ W.x.getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + ctx.BIG.MODBYTES] = t[i];
}
- this.y.getA().toBytes(t);
+ W.y.getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 2 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getB().toBytes(t);
+ W.y.getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 3 * ctx.BIG.MODBYTES] = t[i];
}
@@ -201,11 +202,12 @@ var ECP2 = function(ctx) {
/* convert this to hex string */
toString: function() {
- if (this.is_infinity()) {
+ var W=new ECP2(); W.copy(this);
+ if (W.is_infinity()) {
return "infinity";
}
- this.affine();
- return "(" + this.x.toString() + "," + this.y.toString() + ")";
+ W.affine();
+ return "(" + W.x.toString() + "," + W.y.toString() + ")";
},
/* set this=(x,y) */
@@ -215,10 +217,11 @@ var ECP2 = function(ctx) {
this.x.copy(ix);
this.y.copy(iy);
this.z.one();
+ this.x.norm();
rhs = ECP2.RHS(this.x);
- y2 = new ctx.FP2(this.y);
+ y2 = new ctx.FP2(this.y);
y2.sqr();
if (!y2.equals(rhs)) {
@@ -232,6 +235,7 @@ var ECP2 = function(ctx) {
this.x.copy(ix);
this.z.one();
+ this.x.norm();
rhs = ECP2.RHS(this.x);
@@ -246,7 +250,7 @@ var ECP2 = function(ctx) {
frob: function(X) {
var X2;
- X2 = new ctx.FP2(X);
+ X2 = new ctx.FP2(X); //X2.copy(X);
X2.sqr();
this.x.conj();
this.y.conj();
@@ -262,20 +266,20 @@ var ECP2 = function(ctx) {
var iy, t0, t1, t2, x3, y3;
iy = new ctx.FP2(0);
- iy.copy(this.y);
+ iy.copy(this.y);
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
iy.mul_ip();
iy.norm();
}
t0 = new ctx.FP2(0);
- t0.copy(this.y);
+ t0.copy(this.y);
t0.sqr();
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
t0.mul_ip();
}
t1 = new ctx.FP2(0);
- t1.copy(iy);
+ t1.copy(iy);
t1.mul(this.z);
t2 = new ctx.FP2(0);
t2.copy(this.z);
@@ -295,11 +299,11 @@ var ECP2 = function(ctx) {
}
x3 = new ctx.FP2(0);
- x3.copy(t2);
+ x3.copy(t2);
x3.mul(this.z);
y3 = new ctx.FP2(0);
- y3.copy(t0);
+ y3.copy(t0);
y3.add(t2);
y3.norm();
@@ -313,7 +317,7 @@ var ECP2 = function(ctx) {
y3.mul(t0);
y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
t1.copy(this.x);
- t1.mul(iy);
+ t1.mul(iy); //
this.x.copy(t0);
this.x.norm();
this.x.mul(t1);
@@ -333,21 +337,21 @@ var ECP2 = function(ctx) {
b = 3 * ctx.ROM_CURVE.CURVE_B_I;
t0 = new ctx.FP2(0);
- t0.copy(this.x);
+ t0.copy(this.x);
t0.mul(Q.x); // x.Q.x
t1 = new ctx.FP2(0);
- t1.copy(this.y);
+ t1.copy(this.y);
t1.mul(Q.y); // y.Q.y
t2 = new ctx.FP2(0);
- t2.copy(this.z);
+ t2.copy(this.z);
t2.mul(Q.z);
t3 = new ctx.FP2(0);
- t3.copy(this.x);
+ t3.copy(this.x);
t3.add(this.y);
t3.norm(); //t3=X1+Y1
t4 = new ctx.FP2(0);
- t4.copy(Q.x);
+ t4.copy(Q.x);
t4.add(Q.y);
t4.norm(); //t4=X2+Y2
t3.mul(t4); //t3=(X1+Y1)(X2+Y2)
@@ -365,7 +369,7 @@ var ECP2 = function(ctx) {
t4.add(this.z);
t4.norm(); //t4=Y1+Z1
x3 = new ctx.FP2(0);
- x3.copy(Q.y);
+ x3.copy(Q.y);
x3.add(Q.z);
x3.norm(); //x3=Y2+Z2
@@ -384,7 +388,7 @@ var ECP2 = function(ctx) {
x3.add(this.z);
x3.norm(); // x3=X1+Z1
y3 = new ctx.FP2(0);
- y3.copy(Q.x);
+ y3.copy(Q.x);
y3.add(Q.z);
y3.norm(); // y3=X2+Z2
x3.mul(y3); // x3=(X1+Z1)(X2+Z2)
@@ -406,11 +410,11 @@ var ECP2 = function(ctx) {
t0.norm();
t2.imul(b);
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
- t2.mul_ip();
+ t2.mul_ip(); t2.norm();
}
z3 = new ctx.FP2(0);
- z3.copy(t1);
+ z3.copy(t1);
z3.add(t2);
z3.norm();
t1.sub(t2);
@@ -446,11 +450,9 @@ var ECP2 = function(ctx) {
/* this-=Q */
sub: function(Q) {
var D;
-
- Q.neg();
- D = this.add(Q);
- Q.neg();
-
+ var NQ=new ECP2(); NQ.copy(Q);
+ NQ.neg();
+ D = this.add(NQ);
return D;
},
@@ -470,8 +472,6 @@ var ECP2 = function(ctx) {
return new ECP2();
}
- this.affine();
-
// precompute table
Q.copy(this);
Q.dbl();
@@ -557,7 +557,7 @@ var ECP2 = function(ctx) {
}
rb = ctx.BIG.fromBytes(t);
- rx = new ctx.FP2(ra, rb);
+ rx = new ctx.FP2(ra, rb); //rx.bset(ra,rb);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = b[i + 2 * ctx.BIG.MODBYTES];
@@ -568,7 +568,7 @@ var ECP2 = function(ctx) {
}
rb = ctx.BIG.fromBytes(t);
- ry = new ctx.FP2(ra, rb);
+ ry = new ctx.FP2(ra, rb); //ry.bset(ra,rb);
P = new ECP2();
P.setxy(rx, ry);
@@ -580,13 +580,13 @@ var ECP2 = function(ctx) {
ECP2.RHS = function(x) {
var r, c, b;
- x.norm();
- r = new ctx.FP2(x);
+ //x.norm();
+ r = new ctx.FP2(x); //r.copy(x);
r.sqr();
c = new ctx.BIG(0);
c.rcopy(ctx.ROM_CURVE.CURVE_B);
- b = new ctx.FP2(c);
+ b = new ctx.FP2(c); //b.bseta(c);
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
b.div_ip();
@@ -621,7 +621,7 @@ var ECP2 = function(ctx) {
for (i = 0; i < 4; i++) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
- Q[i].affine();
+ //Q[i].affine();
}
T[0] = new ECP2(); T[0].copy(Q[0]); // Q[0]
@@ -683,6 +683,7 @@ var ECP2 = function(ctx) {
return P;
};
+
/* return 1 if b==c, no branching */
ECP2.teq = function(b, c) {
var x = b ^ c;
@@ -734,7 +735,7 @@ var ECP2 = function(ctx) {
K = new ECP2();
K.copy(T);
K.dbl();
- K.add(T);
+ K.add(T); //K.affine();
K.frob(X);
Q.frob(X);
@@ -748,6 +749,7 @@ var ECP2 = function(ctx) {
}
if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BLS) {
+
xQ = Q.mul(x);
x2Q = xQ.mul(x);
diff --git a/src/ecp4.js b/src/ecp4.js
index 1292aea..82fbce3 100644
--- a/src/ecp4.js
+++ b/src/ecp4.js
@@ -57,6 +57,7 @@ var ECP4 = function(ctx) {
this.x.cmove(Q.x, d);
this.y.cmove(Q.y, d);
this.z.cmove(Q.z, d);
+
},
/* Constant time select from pre-computed table */
@@ -140,14 +141,14 @@ var ECP4 = function(ctx) {
/* extract affine x as ctx.FP4 */
getX: function() {
- this.affine();
- return this.x;
+ var W=new ECP4(); W.copy(this); W.affine();
+ return W.x;
},
/* extract affine y as ctx.FP4 */
getY: function() {
- this.affine();
- return this.y;
+ var W=new ECP4(); W.copy(this); W.affine();
+ return W.y;
},
/* extract projective x */
@@ -169,39 +170,39 @@ var ECP4 = function(ctx) {
toBytes: function(b) {
var t = [],
i;
-
- this.affine();
- this.x.geta().getA().toBytes(t);
+ var W=new ECP4(); W.copy(this);
+ W.affine();
+ W.x.geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i] = t[i];
}
- this.x.geta().getB().toBytes(t);
+ W.x.geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().getA().toBytes(t);
+ W.x.getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 2*ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().getB().toBytes(t);
+ W.x.getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 3*ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().getA().toBytes(t);
+ W.y.geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 4 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().getB().toBytes(t);
+ W.y.geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 5 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().getA().toBytes(t);
+ W.y.getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 6 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().getB().toBytes(t);
+ W.y.getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 7 * ctx.BIG.MODBYTES] = t[i];
}
@@ -209,11 +210,12 @@ var ECP4 = function(ctx) {
/* convert this to hex string */
toString: function() {
- if (this.is_infinity()) {
+ var W=new ECP4(); W.copy(this);
+ if (W.is_infinity()) {
return "infinity";
}
- this.affine();
- return "(" + this.x.toString() + "," + this.y.toString() + ")";
+ W.affine();
+ return "(" + W.x.toString() + "," + W.y.toString() + ")";
},
/* set this=(x,y) */
@@ -223,15 +225,17 @@ var ECP4 = function(ctx) {
this.x.copy(ix);
this.y.copy(iy);
this.z.one();
+ this.x.norm();
rhs = ECP4.RHS(this.x);
- y2 = new ctx.FP4(this.y);
+ y2 = new ctx.FP4(this.y); //y2.copy(this.y);
y2.sqr();
if (!y2.equals(rhs)) {
this.inf();
}
+
},
/* set this=(x,.) */
@@ -240,7 +244,7 @@ var ECP4 = function(ctx) {
this.x.copy(ix);
this.z.one();
-
+ this.x.norm();
rhs = ECP4.RHS(this.x);
if (rhs.sqrt()) {
@@ -313,7 +317,7 @@ var ECP4 = function(ctx) {
y3.mul(t0);
y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
t1.copy(this.x);
- t1.mul(iy);
+ t1.mul(iy); //
this.x.copy(t0);
this.x.norm();
this.x.mul(t1);
@@ -362,7 +366,7 @@ var ECP4 = function(ctx) {
x3.norm(); //x3=Y2+Z2
t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
- x3.copy(t1);
+ x3.copy(t1); //
x3.add(t2); //X3=Y1.Y2+Z1.Z2
t4.sub(x3);
@@ -432,11 +436,9 @@ var ECP4 = function(ctx) {
/* this-=Q */
sub: function(Q) {
var D;
-
- Q.neg();
- D = this.add(Q);
- Q.neg();
-
+ var NQ=new ECP4(); NQ.copy(Q);
+ NQ.neg();
+ D = this.add(NQ);
return D;
},
@@ -456,8 +458,6 @@ var ECP4 = function(ctx) {
return new ECP4();
}
- this.affine();
-
// precompute table
Q.copy(this);
Q.dbl();
@@ -567,7 +567,7 @@ var ECP4 = function(ctx) {
rb = ctx.BIG.fromBytes(t);
rb4=new ctx.FP2(ra,rb);
- rx = new ctx.FP4(ra4, rb4);
+ rx = new ctx.FP4(ra4, rb4); //rx.bset(ra,rb);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = b[i + 4 * ctx.BIG.MODBYTES];
@@ -590,7 +590,7 @@ var ECP4 = function(ctx) {
rb4=new ctx.FP2(ra,rb);
- ry = new ctx.FP4(ra4, rb4);
+ ry = new ctx.FP4(ra4, rb4); //ry.bset(ra,rb);
P = new ECP4();
P.setxy(rx, ry);
@@ -602,13 +602,13 @@ var ECP4 = function(ctx) {
ECP4.RHS = function(x) {
var r, c, b;
- x.norm();
- r = new ctx.FP4(x);
+ //x.norm();
+ r = new ctx.FP4(x); //r.copy(x);
r.sqr();
c = new ctx.BIG(0);
c.rcopy(ctx.ROM_CURVE.CURVE_B);
- b = new ctx.FP4(c);
+ b = new ctx.FP4(c); //b.bseta(c);
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
b.div_i();
@@ -644,17 +644,17 @@ var ECP4 = function(ctx) {
for (i = 0; i < 8; i++) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
- Q[i].affine();
+ //Q[i].affine();
}
- T1[0] = new ECP4(); T1[0].copy(Q[0]);
- T1[1] = new ECP4(); T1[1].copy(T1[0]); T1[1].add(Q[1]);
- T1[2] = new ECP4(); T1[2].copy(T1[0]); T1[2].add(Q[2]);
- T1[3] = new ECP4(); T1[3].copy(T1[1]); T1[3].add(Q[2]);
- T1[4] = new ECP4(); T1[4].copy(T1[0]); T1[4].add(Q[3]);
- T1[5] = new ECP4(); T1[5].copy(T1[1]); T1[5].add(Q[3]);
- T1[6] = new ECP4(); T1[6].copy(T1[2]); T1[6].add(Q[3]);
- T1[7] = new ECP4(); T1[7].copy(T1[3]); T1[7].add(Q[3]);
+ T1[0] = new ECP4(); T1[0].copy(Q[0]); // Q[0]
+ T1[1] = new ECP4(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1]
+ T1[2] = new ECP4(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2]
+ T1[3] = new ECP4(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
+ T1[4] = new ECP4(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3]
+ T1[5] = new ECP4(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
+ T1[6] = new ECP4(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
+ T1[7] = new ECP4(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
// Use Frobenius
for (i=0;i<8;i++) {
diff --git a/src/ecp8.js b/src/ecp8.js
index 9ba464c..593f739 100644
--- a/src/ecp8.js
+++ b/src/ecp8.js
@@ -27,12 +27,12 @@ var ECP8 = function(ctx) {
this.x = new ctx.FP8(0);
this.y = new ctx.FP8(1);
this.z = new ctx.FP8(0);
- // this.INF = true;
};
ECP8.prototype = {
/* Test this=O? */
is_infinity: function() {
+
this.x.reduce();
this.y.reduce();
this.z.reduce();
@@ -140,14 +140,14 @@ var ECP8 = function(ctx) {
/* extract affine x as ctx.FP8 */
getX: function() {
- this.affine();
- return this.x;
+ var W=new ECP8(); W.copy(this); W.affine();
+ return W.x;
},
/* extract affine y as ctx.FP8 */
getY: function() {
- this.affine();
- return this.y;
+ var W=new ECP8(); W.copy(this); W.affine();
+ return W.y;
},
/* extract projective x */
@@ -169,72 +169,72 @@ var ECP8 = function(ctx) {
toBytes: function(b) {
var t = [],
i;
-
- this.affine();
- this.x.geta().geta().getA().toBytes(t);
+ var W=new ECP8(); W.copy(this);
+ W.affine();
+ W.x.geta().geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i] = t[i];
}
- this.x.geta().geta().getB().toBytes(t);
+ W.x.geta().geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + ctx.BIG.MODBYTES] = t[i];
}
- this.x.geta().getb().getA().toBytes(t);
+ W.x.geta().getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 2*ctx.BIG.MODBYTES] = t[i];
}
- this.x.geta().getb().getB().toBytes(t);
+ W.x.geta().getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 3*ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().geta().getA().toBytes(t);
+ W.x.getb().geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 4*ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().geta().getB().toBytes(t);
+ W.x.getb().geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 5*ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().getb().getA().toBytes(t);
+ W.x.getb().getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 6*ctx.BIG.MODBYTES] = t[i];
}
- this.x.getb().getb().getB().toBytes(t);
+ W.x.getb().getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 7*ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().geta().getA().toBytes(t);
+ W.y.geta().geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 8 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().geta().getB().toBytes(t);
+ W.y.geta().geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 9 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().getb().getA().toBytes(t);
+ W.y.geta().getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 10 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.geta().getb().getB().toBytes(t);
+ W.y.geta().getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 11 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().geta().getA().toBytes(t);
+ W.y.getb().geta().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 12 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().geta().getB().toBytes(t);
+ W.y.getb().geta().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 13 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().getb().getA().toBytes(t);
+ W.y.getb().getb().getA().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 14 * ctx.BIG.MODBYTES] = t[i];
}
- this.y.getb().getb().getB().toBytes(t);
+ W.y.getb().getb().getB().toBytes(t);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
b[i + 15 * ctx.BIG.MODBYTES] = t[i];
}
@@ -242,11 +242,12 @@ var ECP8 = function(ctx) {
/* convert this to hex string */
toString: function() {
- if (this.is_infinity()) {
+ var W=new ECP8(); W.copy(this);
+ if (W.is_infinity()) {
return "infinity";
}
- this.affine();
- return "(" + this.x.toString() + "," + this.y.toString() + ")";
+ W.affine();
+ return "(" + W.x.toString() + "," + W.y.toString() + ")";
},
/* set this=(x,y) */
@@ -256,10 +257,11 @@ var ECP8 = function(ctx) {
this.x.copy(ix);
this.y.copy(iy);
this.z.one();
+ this.x.norm();
rhs = ECP8.RHS(this.x);
- y2 = new ctx.FP8(this.y);
+ y2 = new ctx.FP8(this.y); //y2.copy(this.y);
y2.sqr();
if (!y2.equals(rhs)) {
@@ -273,7 +275,7 @@ var ECP8 = function(ctx) {
this.x.copy(ix);
this.z.one();
-
+ this.x.norm();
rhs = ECP8.RHS(this.x);
if (rhs.sqrt()) {
@@ -357,7 +359,7 @@ var ECP8 = function(ctx) {
y3.mul(t0);
y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
t1.copy(this.x);
- t1.mul(iy);
+ t1.mul(iy); //
this.x.copy(t0);
this.x.norm();
this.x.mul(t1);
@@ -406,7 +408,7 @@ var ECP8 = function(ctx) {
x3.norm(); //x3=Y2+Z2
t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
- x3.copy(t1);
+ x3.copy(t1); //
x3.add(t2); //X3=Y1.Y2+Z1.Z2
t4.sub(x3);
@@ -476,11 +478,9 @@ var ECP8 = function(ctx) {
/* this-=Q */
sub: function(Q) {
var D;
-
- Q.neg();
- D = this.add(Q);
- Q.neg();
-
+ var NQ=new ECP8(); NQ.copy(Q);
+ NQ.neg();
+ D = this.add(NQ);
return D;
},
@@ -500,8 +500,6 @@ var ECP8 = function(ctx) {
return new ECP8();
}
- this.affine();
-
// precompute table
Q.copy(this);
Q.dbl();
@@ -661,7 +659,7 @@ var ECP8 = function(ctx) {
rb8=new ctx.FP4(ra4,rb4);
- rx = new ctx.FP8(ra8, rb8);
+ rx = new ctx.FP8(ra8, rb8); //rx.bset(ra,rb);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
@@ -708,7 +706,7 @@ var ECP8 = function(ctx) {
rb8=new ctx.FP4(ra4,rb4);
- ry = new ctx.FP8(ra8, rb8);
+ ry = new ctx.FP8(ra8, rb8); //ry.bset(ra,rb);
P = new ECP8();
P.setxy(rx, ry);
@@ -720,7 +718,7 @@ var ECP8 = function(ctx) {
ECP8.RHS = function(x) {
var r, c, b;
- x.norm();
+ //x.norm();
r = new ctx.FP8(x); //r.copy(x);
r.sqr();
@@ -768,17 +766,17 @@ var ECP8 = function(ctx) {
for (i = 0; i < 16; i++) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
- Q[i].affine();
+ //Q[i].affine();
}
- T1[0] = new ECP8(); T1[0].copy(Q[0]);
- T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]);
- T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]);
- T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]);
- T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]);
- T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]);
- T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]);
- T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]);
+ T1[0] = new ECP8(); T1[0].copy(Q[0]); // Q[0]
+ T1[1] = new ECP8(); T1[1].copy(T1[0]); T1[1].add(Q[1]); // Q[0]+Q[1]
+ T1[2] = new ECP8(); T1[2].copy(T1[0]); T1[2].add(Q[2]); // Q[0]+Q[2]
+ T1[3] = new ECP8(); T1[3].copy(T1[1]); T1[3].add(Q[2]); // Q[0]+Q[1]+Q[2]
+ T1[4] = new ECP8(); T1[4].copy(T1[0]); T1[4].add(Q[3]); // Q[0]+Q[3]
+ T1[5] = new ECP8(); T1[5].copy(T1[1]); T1[5].add(Q[3]); // Q[0]+Q[1]+Q[3]
+ T1[6] = new ECP8(); T1[6].copy(T1[2]); T1[6].add(Q[3]); // Q[0]+Q[2]+Q[3]
+ T1[7] = new ECP8(); T1[7].copy(T1[3]); T1[7].add(Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
// Use Frobenius
for (i=0;i<8;i++) {
diff --git a/src/ff.js b/src/ff.js
index b62592e..8bcd3c4 100644
--- a/src/ff.js
+++ b/src/ff.js
@@ -37,8 +37,7 @@ var FF = function(ctx) {
FF.P_FEXCESS = (1 << (ctx.BIG.BASEBITS * ctx.BIG.NLEN - FF.P_MBITS - 1));
FF.P_TBITS = (FF.P_MBITS % ctx.BIG.BASEBITS);
FF.FF_BITS = (ctx.BIG.BIGBITS * FF.FFLEN);
- /* Useful for half-size RSA private key operations */
- FF.HFLEN = (FF.FFLEN / 2);
+ FF.HFLEN = (FF.FFLEN / 2); /* Useful for half-size RSA private key operations */
FF.prototype = {
/* set to zero */
@@ -205,8 +204,7 @@ var FF = function(ctx) {
var trunc = false,
i, carry;
- /* -v n signals to do truncation */
- if (n < 0) {
+ if (n < 0) { /* -v n signals to do truncation */
n = -n;
trunc = true;
}
@@ -328,12 +326,10 @@ var FF = function(ctx) {
this.rnorm(vp + nd2, n);
},
- /* Calculates Least Significant bottom half of x*y */
- karmul_lower: function(vp, x, xp, y, yp, t, tp, n) {
+ karmul_lower: function(vp, x, xp, y, yp, t, tp, n) { /* Calculates Least Significant bottom half of x*y */
var nd2;
- /* only calculate bottom half of product */
- if (n === 1) {
+ if (n === 1) { /* only calculate bottom half of product */
this.v[vp].copy(ctx.BIG.smul(x.v[xp], y.v[yp]));
return;
@@ -350,8 +346,7 @@ var FF = function(ctx) {
this.rnorm(vp + nd2, -nd2); /* truncate it */
},
- /* Calculates Most Significant upper half of x*y, given lower part */
- karmul_upper: function(x, y, t, n) {
+ karmul_upper: function(x, y, t, n) { /* Calculates Most Significant upper half of x*y, given lower part */
var nd2;
nd2 = n / 2;
@@ -409,9 +404,8 @@ var FF = function(ctx) {
}
},
- /* /Fast Karatsuba Montgomery reduction
- * return This mod modulus, N is modulus, ND is Montgomery Constant */
- reduce: function(N, ND) {
+ /* return This mod modulus, N is modulus, ND is Montgomery Constant */
+ reduce: function(N, ND) { /* fast karatsuba Montgomery reduction */
var n = N.length,
t = new FF(2 * n),
r = new FF(n),
@@ -1006,6 +1000,7 @@ var FF = function(ctx) {
return FF;
};
+
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
module.exports = {
FF: FF
diff --git a/src/fp.js b/src/fp.js
index 05beedb..ebb0d74 100644
--- a/src/fp.js
+++ b/src/fp.js
@@ -30,7 +30,9 @@ var FP = function(ctx) {
this.XES = x.XES;
} else {
this.f = new ctx.BIG(x);
- this.nres();
+ this.XES = 1;
+ if (!this.f.iszilch())
+ this.nres();
}
};
@@ -39,11 +41,17 @@ var FP = function(ctx) {
FP.GENERALISED_MERSENNE = 2;
FP.MONTGOMERY_FRIENDLY = 3;
+ FP.ZERO = 0;
+ FP.ONE = 1;
+ FP.SPARSER = 2;
+ FP.SPARSE = 3;
+ FP.DENSE= 4;
+
FP.MODBITS = ctx.config["@NBT"];
FP.MOD8 = ctx.config["@M8"];
FP.MODTYPE = ctx.config["@MT"];
- FP.FEXCESS = (1 << ctx.config["@SH"]); // 2^(BASEBITS*NLEN-MODBITS)
+ FP.FEXCESS = ((1 << ctx.config["@SH"])-1); // 2^(BASEBITS*NLEN-MODBITS)-1
FP.OMASK = (-1) << FP.TBITS;
FP.TBITS = FP.MODBITS % ctx.BIG.BASEBITS;
FP.TMASK = (1 << FP.TBITS) - 1;
@@ -136,22 +144,48 @@ var FP = function(ctx) {
/* test this=0 */
iszilch: function() {
- this.reduce();
- return this.f.iszilch();
+ var c=new FP(0); c.copy(this);
+ c.reduce();
+ return c.f.iszilch();
},
/* reduce this mod Modulus */
reduce: function() {
- var p = new ctx.BIG(0);
- p.rcopy(ctx.ROM_FIELD.Modulus);
- this.f.mod(p);
+ var q,carry,sr,sb,m = new ctx.BIG(0);
+ m.rcopy(ctx.ROM_FIELD.Modulus);
+ var r = new ctx.BIG(0);
+ r.rcopy(ctx.ROM_FIELD.Modulus);
+ this.f.norm();
+
+ if (this.XES>16)
+ {
+ q=FP.quo(this.f,m);
+ carry=r.pmul(q);
+ r.w[ctx.BIG.NLEN-1]+=(carry<<ctx.BIG.BASEBITS); // correction - put any carry out back in again
+ this.f.sub(r);
+ this.f.norm();
+ sb=2;
+ }
+ else {
+ sb=FP.logb2(this.XES-1);
+ }
+ m.fshl(sb);
+
+ while (sb>0)
+ {
+// constant time...
+ sr=ctx.BIG.ssn(r,this.f,m); // optimized combined shift, subtract and norm
+ this.f.cmove(r,1-sr);
+ sb--;
+ }
+
this.XES = 1;
},
/* set this=1 */
one: function() {
this.f.one();
- return this.nres();
+ this.nres();
},
/* normalise this */
@@ -242,7 +276,7 @@ var FP = function(ctx) {
sb = FP.logb2(this.XES - 1);
m.fshl(sb);
- this.XES = (1 << sb);
+ this.XES = (1 << sb)+1;
this.f.rsub(m);
if (this.XES > FP.FEXCESS) {
@@ -290,23 +324,144 @@ var FP = function(ctx) {
return this;
},
+// return this^(p-3)/4 or this^(p-5)/8
+// See https://eprint.iacr.org/2018/1038
+ fpow: function() {
+ var i,j,k,bw,w,c,nw,lo,m,n;
+ var xp=[];
+ var ac=[1,2,3,6,12,15,30,60,120,240,255];
+// phase 1
+
+ xp[0]=new FP(this); // 1
+ xp[1]=new FP(this); xp[1].sqr(); // 2
+ xp[2]=new FP(xp[1]); xp[2].mul(this); //3
+ xp[3]=new FP(xp[2]); xp[3].sqr(); // 6
+ xp[4]=new FP(xp[3]); xp[4].sqr(); // 12
+ xp[5]=new FP(xp[4]); xp[5].mul(xp[2]); // 15
+ xp[6]=new FP(xp[5]); xp[6].sqr(); // 30
+ xp[7]=new FP(xp[6]); xp[7].sqr(); // 60
+ xp[8]=new FP(xp[7]); xp[8].sqr(); // 120
+ xp[9]=new FP(xp[8]); xp[9].sqr(); // 240
+ xp[10]=new FP(xp[9]); xp[10].mul(xp[5]); // 255
+
+
+ n=FP.MODBITS;
+ if (FP.MODTYPE == FP.GENERALISED_MERSENNE) // Goldilocks ONLY
+ n/=2;
+ if (FP.MOD8==5)
+ {
+ n-=3;
+ c=(ctx.ROM_FIELD.MConst+5)/8;
+ } else {
+ n-=2;
+ c=(ctx.ROM_FIELD.MConst+3)/4;
+ }
+
+ bw=0; w=1; while (w<c) {w*=2; bw+=1;}
+ k=w-c;
+
+ i=10; var key=new FP(0);
+ if (k!=0)
+ {
+ while (ac[i]>k) i--;
+ key.copy(xp[i]);
+ k-=ac[i];
+ }
+ while (k!=0)
+ {
+ i--;
+ if (ac[i]>k) continue;
+ key.mul(xp[i]);
+ k-=ac[i];
+ }
+
+// phase 2
+ xp[1].copy(xp[2]);
+ xp[2].copy(xp[5]);
+ xp[3].copy(xp[10]);
+
+ j=3; m=8;
+ nw=n-bw;
+ var t=new FP(0);
+ while (2*m<nw)
+ {
+ t.copy(xp[j++]);
+ for (i=0;i<m;i++)
+ t.sqr();
+ xp[j].copy(xp[j-1]);
+ xp[j].mul(t);
+ m*=2;
+ }
+ lo=nw-m;
+ var r=new FP(xp[j]);
+
+ while (lo!=0)
+ {
+ m/=2; j--;
+ if (lo<m) continue;
+ lo-=m;
+ t.copy(r);
+ for (i=0;i<m;i++)
+ t.sqr();
+ r.copy(t);
+ r.mul(xp[j]);
+ }
+
+// phase 3
+ if (bw!=0)
+ {
+ for (i=0;i<bw;i++ )
+ r.sqr();
+ r.mul(key);
+ }
+
+ if (FP.MODTYPE == FP.GENERALISED_MERSENNE) // Goldilocks ONLY
+ {
+ key.copy(r);
+ r.sqr();
+ r.mul(this);
+ for (i=0;i<n+1;i++)
+ r.sqr();
+ r.mul(key);
+ }
+ return r;
+ },
+
/* this=1/this mod Modulus */
inverse: function() {
- var m2=new ctx.BIG(0);
-
- m2.rcopy(ctx.ROM_FIELD.Modulus);
- m2.dec(2); m2.norm();
- this.copy(this.pow(m2));
- return this;
+ if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE)
+ {
+ var y=this.fpow();
+ if (FP.MOD8==5)
+ {
+ var t=new FP(this);
+ t.sqr();
+ this.mul(t);
+ y.sqr();
+
+ }
+ y.sqr();
+ y.sqr();
+ this.mul(y);
+ return this;
+ } else {
+ var m2=new ctx.BIG(0);
+ m2.rcopy(ctx.ROM_FIELD.Modulus);
+ m2.dec(2); m2.norm();
+ this.copy(this.pow(m2));
+ return this;
+ }
},
/* return TRUE if this==a */
equals: function(a) {
- a.reduce();
- this.reduce();
+ var ft=new FP(0); ft.copy(this);
+ var sd=new FP(0); sd.copy(a);
+ ft.reduce();
+ sd.reduce();
- if (ctx.BIG.comp(a.f, this.f) === 0) {
+ if (ctx.BIG.comp(ft.f, sd.f) === 0) {
return true;
}
@@ -319,7 +474,7 @@ var FP = function(ctx) {
tb=[],
t=new ctx.BIG(e),
nb, lsbs, r;
-
+ this.norm();
t.norm();
nb= 1 + Math.floor((t.nbits() + 3) / 4);
@@ -360,21 +515,23 @@ var FP = function(ctx) {
/* return sqrt(this) mod Modulus */
sqrt: function() {
- var b = new ctx.BIG(0),
- i, v, r;
+ var i, v, r;
this.reduce();
-
- b.rcopy(ctx.ROM_FIELD.Modulus);
-
if (FP.MOD8 == 5) {
- b.dec(5);
- b.norm();
- b.shr(3);
i = new FP(0);
i.copy(this);
i.f.shl(1);
- v = i.pow(b);
+ if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE) {
+ v=i.fpow();
+ } else {
+ var b = new ctx.BIG(0);
+ b.rcopy(ctx.ROM_FIELD.Modulus);
+ b.dec(5);
+ b.norm();
+ b.shr(3);
+ v = i.pow(b);
+ }
i.mul(v);
i.mul(v);
i.f.dec(1);
@@ -386,11 +543,18 @@ var FP = function(ctx) {
return r;
} else {
- b.inc(1);
- b.norm();
- b.shr(2);
-
- return this.pow(b);
+ if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE) {
+ var r=this.fpow();
+ r.mul(this);
+ return r;
+ } else {
+ var b = new ctx.BIG(0);
+ b.rcopy(ctx.ROM_FIELD.Modulus);
+ b.inc(1);
+ b.norm();
+ b.shr(2);
+ return this.pow(b);
+ }
}
}
@@ -412,6 +576,20 @@ var FP = function(ctx) {
return r;
};
+ FP.quo = function(n,m) {
+ var num,den,hb=ctx.BIG.CHUNK>>1;
+ if (FP.TBITS<hb)
+ {
+ var sh=hb-FP.TBITS;
+ num=(n.w[ctx.BIG.NLEN-1]<<sh)|(n.w[ctx.BIG.NLEN-2]>>(ctx.BIG.BASEBITS-sh));
+ den=(m.w[ctx.BIG.NLEN-1]<<sh)|(m.w[ctx.BIG.NLEN-2]>>(ctx.BIG.BASEBITS-sh));
+ } else {
+ num=n.w[ctx.BIG.NLEN-1];
+ den=m.w[ctx.BIG.NLEN-1];
+ }
+ return Math.floor(num/(den+1))
+ };
+
/* reduce a ctx.DBIG to a ctx.BIG using a "special" modulus */
FP.mod = function(d) {
var b = new ctx.BIG(0),
@@ -433,6 +611,7 @@ var FP = function(ctx) {
tw = t.w[ctx.BIG.NLEN - 1];
t.w[ctx.BIG.NLEN - 1] &= FP.TMASK;
t.inc(ctx.ROM_FIELD.MConst * ((tw >> FP.TBITS) + (v << (ctx.BIG.BASEBITS - FP.TBITS))));
+ // b.add(t);
t.norm();
return t;
@@ -450,8 +629,7 @@ var FP = function(ctx) {
b.norm();
}
- // GoldiLocks Only
- if (FP.MODTYPE == FP.GENERALISED_MERSENNE) {
+ if (FP.MODTYPE == FP.GENERALISED_MERSENNE) { // GoldiLocks Only
t = d.split(FP.MODBITS);
b.hcopy(d);
b.add(t);
@@ -465,6 +643,7 @@ var FP = function(ctx) {
b.add(tt);
b.add(lo);
+ //b.norm();
tt.shl(FP.MODBITS / 2);
b.add(tt);
diff --git a/src/fp12.js b/src/fp12.js
index 8955650..aa29a39 100644
--- a/src/fp12.js
+++ b/src/fp12.js
@@ -27,13 +27,30 @@ var FP12 = function(ctx) {
/* general purpose constructor */
var FP12 = function(d, e, f) {
if (d instanceof FP12) {
+ // ignore e, d, which are assumed be undefined in this case
this.a = new ctx.FP4(d.a);
this.b = new ctx.FP4(d.b);
this.c = new ctx.FP4(d.c);
- } else {
+ this.stype=ctx.FP.DENSE;
+ } else if (typeof d !== "undefined" && typeof e !== "undefined" && typeof f !== "undefined") {
+ // all 3 components set to (can be anything that the FP4 constructor supports)
this.a = new ctx.FP4(d);
this.b = new ctx.FP4(e);
this.c = new ctx.FP4(f);
+ this.stype=ctx.FP.DENSE;
+ } else if (typeof d === "number") {
+ // first component is number
+ this.a = new ctx.FP4(d);
+ this.b = new ctx.FP4(0);
+ this.c = new ctx.FP4(0);
+ if (d==1) this.stype=ctx.FP.ONE;
+ else this.stype=ctx.FP.SPARSER;
+ } else {
+ // other cases, including `new ctx.FP12()` fall back to zero
+ this.a = new ctx.FP4(0);
+ this.b = new ctx.FP4(0);
+ this.c = new ctx.FP4(0);
+ this.stype=ctx.FP.ZERO;
}
};
@@ -54,7 +71,6 @@ var FP12 = function(ctx) {
/* test x==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
},
@@ -70,6 +86,8 @@ var FP12 = function(ctx) {
this.a.cmove(g.a, d);
this.b.cmove(g.b, d);
this.c.cmove(g.c, d);
+ d=~(d-1);
+ this.stype^=(this.stype^g.stype)&d;
},
@@ -82,7 +100,7 @@ var FP12 = function(ctx) {
babs = (b ^ m) - m;
babs = (babs - 1) / 2;
- this.cmove(g[0], FP12.teq(babs, 0));
+ this.cmove(g[0], FP12.teq(babs, 0)); // conditional move
this.cmove(g[1], FP12.teq(babs, 1));
this.cmove(g[2], FP12.teq(babs, 2));
this.cmove(g[3], FP12.teq(babs, 3));
@@ -96,6 +114,14 @@ var FP12 = function(ctx) {
this.cmove(invf, (m & 1));
},
+ settype: function(w) {
+ this.stype=w;
+ },
+
+ gettype: function() {
+ return this.stype;
+ },
+
/* extract a from this */
geta: function() {
return this.a;
@@ -121,6 +147,7 @@ var FP12 = function(ctx) {
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -128,6 +155,15 @@ var FP12 = function(ctx) {
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
+ },
+
+ /* set this=0 */
+ zero: function() {
+ this.a.zero();
+ this.b.zero();
+ this.c.zero();
+ this.stype=ctx.FP.ZERO;
},
/* this=conj(this) */
@@ -142,6 +178,7 @@ var FP12 = function(ctx) {
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP4 */
@@ -149,13 +186,14 @@ var FP12 = function(ctx) {
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
usqr: function() {
- var A = new ctx.FP4(this.a),
- B = new ctx.FP4(this.c),
- C = new ctx.FP4(this.b),
+ var A = new ctx.FP4(this.a),
+ B = new ctx.FP4(this.c),
+ C = new ctx.FP4(this.b),
D = new ctx.FP4(0);
this.a.sqr();
@@ -186,19 +224,23 @@ var FP12 = function(ctx) {
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
- var A = new ctx.FP4(this.a),
- B = new ctx.FP4(this.b),
- C = new ctx.FP4(this.c),
- D = new ctx.FP4(this.a);
+ if (this.stype==ctx.FP.ONE)
+ return;
+
+ var A = new ctx.FP4(this.a),
+ B = new ctx.FP4(this.b),
+ C = new ctx.FP4(this.c),
+ D = new ctx.FP4(this.a);
A.sqr();
B.mul(this.c);
- B.add(B);
+ B.add(B);
C.sqr();
D.mul(this.b);
D.add(D);
@@ -221,18 +263,21 @@ var FP12 = function(ctx) {
this.b.copy(C);
this.b.add(D);
this.c.add(A);
-
+ if (this.stype==ctx.FP.SPARSER)
+ this.stype=ctx.FP.SPARSE;
+ else
+ this.stype=ctx.FP.DENSE;
this.norm();
},
/* FP12 full multiplication this=this*y */
mul: function(y) {
- var z0 = new ctx.FP4(this.a),
+ var z0 = new ctx.FP4(this.a),
z1 = new ctx.FP4(0),
- z2 = new ctx.FP4(this.b),
+ z2 = new ctx.FP4(this.b),
z3 = new ctx.FP4(0),
- t0 = new ctx.FP4(this.a),
- t1 = new ctx.FP4(y.a);
+ t0 = new ctx.FP4(this.a),
+ t1 = new ctx.FP4(y.a);
z0.mul(y.a);
z2.mul(y.b);
@@ -292,117 +337,323 @@ var FP12 = function(ctx) {
z3.times_i();
this.a.copy(z0);
this.a.add(z3);
-
+ this.stype=ctx.FP.DENSE;
this.norm();
},
- /* Special case this*=y that arises from special form of ATE pairing line function */
- smul: function(y, twist) {
- var z0, z1, z2, z3, t0, t1;
-
- if (twist == ctx.ECP.D_TYPE) {
-
- z0 = new ctx.FP4(this.a);
- z2 = new ctx.FP4(this.b);
- z3 = new ctx.FP4(this.b);
- t0 = new ctx.FP4(0);
- t1 = new ctx.FP4(y.a);
-
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
-
- this.b.norm();
- t1.norm();
-
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
-
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
-
- this.b.add(t0);
-
- this.b.add(t1);
- z3.add(t1);
- z2.add(t0);
-
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
-
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
-
- if (twist == ctx.ECP.M_TYPE) {
- z0=new ctx.FP4(this.a);
- z1=new ctx.FP4(0);
- z2=new ctx.FP4(0);
- z3=new ctx.FP4(0);
- t0=new ctx.FP4(this.a);
- t1=new ctx.FP4(0);
-
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
-
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
-
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
-
- t0.copy(z0); t0.neg();
-
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
-
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
-
- t0.norm();
- t1.norm();
-
- t0.mul(t1);
- z2.add(t0);
-
- t0.copy(this.c);
-
- t0.pmul(y.c.getb());
- t0.times_i();
-
- t1.copy(t0); t1.neg();
-
- this.c.copy(z2); this.c.add(t1);
- z3.add(t1);
- t0.times_i();
- this.b.add(t0);
- z3.norm();
- z3.times_i();
- this.a.copy(z0); this.a.add(z3);
- }
-
- this.norm();
- },
+/* FP12 multiplication w=w*y */
+/* catering for special case that arises from special form of ATE pairing line function */
+/* w and y are both sparser line functions - cost = 6m */
+ smul: function(y) {
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ var w1=new ctx.FP2(this.a.geta());
+ var w2=new ctx.FP2(this.a.getb());
+ var w3=new ctx.FP2(this.b.geta());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ var ta=new ctx.FP2(this.a.geta());
+ var tb=new ctx.FP2(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP2(ta);
+ tc.mul(tb);
+ var t=new ctx.FP2(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ var td=new ctx.FP2(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ var te=new ctx.FP2(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.mul_ip();
+ w1.add(w2);
+
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+ this.b.geta().copy(td); this.b.getb().copy(te);
+ this.c.geta().copy(w3); this.c.getb().zero();
+
+ this.a.norm();
+ this.b.norm();
+
+ } else {
+ var w1=new ctx.FP2(this.a.geta());
+ var w2=new ctx.FP2(this.a.getb());
+ var w3=new ctx.FP2(this.c.getb());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
+
+ var ta=new ctx.FP2(this.a.geta());
+ var tb=new ctx.FP2(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP2(ta);
+ tc.mul(tb);
+ var t=new ctx.FP2(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ var td=new ctx.FP2(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ var te=new ctx.FP2(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.mul_ip();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+
+ w3.mul_ip();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
+
+ te.norm();
+ te.mul_ip();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
+
+ this.a.norm();
+ this.c.norm();
+
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
+
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ ssmul: function(y) {
+ if (this.stype==ctx.FP.ONE)
+ {
+ this.copy(y);
+ return;
+ }
+ if (y.stype==ctx.FP.ONE)
+ return;
+
+ if (y.stype>=ctx.FP.SPARSE)
+ {
+ var z0=new ctx.FP4(this.a);
+ var z1=new ctx.FP4(0);
+ var z2=new ctx.FP4(0);
+ var z3=new ctx.FP4(0);
+ z0.mul(y.a);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ z2.getb().copy(this.b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ var t0=new ctx.FP4(this.a);
+ var t1=new ctx.FP4(y.a);
+ t0.add(this.b); t0.norm();
+ t1.add(y.b); t1.norm();
+
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(this.b); t0.add(this.c); t0.norm();
+ t1.copy(y.b); t1.add(y.c); t1.norm();
+
+ z3.copy(t0); z3.mul(t1);
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ z1.add(t0);
+ this.b.copy(z1); this.b.add(t1);
+
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ t0.geta().copy(this.c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ } else {
+ if (this.stype==ctx.FP.SPARSER)
+ {
+ this.smul(y);
+ return;
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ { // dense by sparser - 13m
+ var z0=new ctx.FP4(this.a);
+ var z2=new ctx.FP4(this.b);
+ var z3=new ctx.FP4(this.b);
+ var t0=new ctx.FP4(0);
+ var t1=new ctx.FP4(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ this.b.add(this.a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ this.b.norm();
+ this.b.mul(t1);
+ z3.add(this.c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ this.b.add(t0);
+
+ this.b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ this.c.copy(z2); this.c.add(t0);
+
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ var z0=new ctx.FP4(this.a);
+ var z1=new ctx.FP4(0);
+ var z2=new ctx.FP4(0);
+ var z3=new ctx.FP4(0);
+ var t0=new ctx.FP4(this.a);
+ var t1=new ctx.FP4(0);
+
+ z0.mul(y.a);
+ t0.add(this.b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(this.b); t0.add(this.c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ this.b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(this.c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ }
+ this.stype=ctx.FP.DENSE;
+ this.norm();
+ },
/* this=1/this */
inverse: function() {
- var f0 = new ctx.FP4(this.a),
- f1 = new ctx.FP4(this.b),
- f2 = new ctx.FP4(this.a),
+ var f0 = new ctx.FP4(this.a),
+ f1 = new ctx.FP4(this.b),
+ f2 = new ctx.FP4(this.a),
f3 = new ctx.FP4(0);
f0.sqr();
@@ -442,6 +693,7 @@ var FP12 = function(ctx) {
this.b.mul(f3);
this.c.copy(f2);
this.c.mul(f3);
+ this.stype=ctx.FP.DENSE;
},
/* this=this^p, where p=Modulus, using Frobenius */
@@ -458,6 +710,7 @@ var FP12 = function(ctx) {
this.b.pmul(f);
this.c.pmul(f2);
+ this.stype=ctx.FP.DENSE;
},
/* trace function */
@@ -535,29 +788,29 @@ var FP12 = function(ctx) {
/* set this=this^e */
pow: function(e) {
- var e3, w, nb, i, bt;
-
- this.norm();
- e.norm();
-
- e3 = new ctx.BIG(e);
+ var e1, e3, w, nb, i, bt, sf;
+ e1 = new ctx.BIG(e);
+ e1.norm();
+ e3 = new ctx.BIG(e1);
e3.pmul(3);
e3.norm();
- w = new FP12(this);
+ sf = new FP12(this);
+ sf.norm();
+ w = new FP12(sf);
nb = e3.nbits();
for (i = nb - 2; i >= 1; i--) {
w.usqr();
- bt = e3.bit(i) - e.bit(i);
+ bt = e3.bit(i) - e1.bit(i);
if (bt == 1) {
- w.mul(this);
+ w.mul(sf);
}
if (bt == -1) {
- this.conj();
- w.mul(this);
- this.conj();
+ sf.conj();
+ w.mul(sf);
+ sf.conj();
}
}
w.reduce();
@@ -642,7 +895,7 @@ var FP12 = function(ctx) {
t[i] = w[i + ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 2 * ctx.BIG.MODBYTES];
@@ -652,9 +905,9 @@ var FP12 = function(ctx) {
t[i] = w[i + 3 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b);
- e = new ctx.FP4(c, d);
+ e = new ctx.FP4(c, d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 4 * ctx.BIG.MODBYTES];
@@ -664,7 +917,7 @@ var FP12 = function(ctx) {
t[i] = w[i + 5 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 6 * ctx.BIG.MODBYTES];
@@ -676,7 +929,7 @@ var FP12 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- f = new ctx.FP4(c, d);
+ f = new ctx.FP4(c, d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 8 * ctx.BIG.MODBYTES];
@@ -686,7 +939,7 @@ var FP12 = function(ctx) {
t[i] = w[i + 9 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 10 * ctx.BIG.MODBYTES];
@@ -696,11 +949,11 @@ var FP12 = function(ctx) {
t[i] = w[i + 11 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b);
- g = new ctx.FP4(c, d);
+ g = new ctx.FP4(c, d);
- r = new FP12(e, f, g);
+ r = new FP12(e, f, g);
return r;
};
@@ -731,14 +984,14 @@ var FP12 = function(ctx) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
}
- g[0] = new FP12(q[0]);
- g[1] = new FP12(g[0]); g[1].mul(q[1]);
- g[2] = new FP12(g[0]); g[2].mul(q[2]);
- g[3] = new FP12(g[1]); g[3].mul(q[2]);
- g[4] = new FP12(q[0]); g[4].mul(q[3]);
- g[5] = new FP12(g[1]); g[5].mul(q[3]);
- g[6] = new FP12(g[2]); g[6].mul(q[3]);
- g[7] = new FP12(g[3]); g[7].mul(q[3]);
+ g[0] = new FP12(q[0]); // q[0]
+ g[1] = new FP12(g[0]); g[1].mul(q[1]); // q[0].q[1]
+ g[2] = new FP12(g[0]); g[2].mul(q[2]); // q[0].q[2]
+ g[3] = new FP12(g[1]); g[3].mul(q[2]); // q[0].q[1].q[2]
+ g[4] = new FP12(q[0]); g[4].mul(q[3]); // q[0].q[3]
+ g[5] = new FP12(g[1]); g[5].mul(q[3]); // q[0].q[1].q[3]
+ g[6] = new FP12(g[2]); g[6].mul(q[3]); // q[0].q[2].q[3]
+ g[7] = new FP12(g[3]); g[7].mul(q[3]); // q[0].q[1].q[2].q[3]
// Make it odd
pb=1-t[0].parity();
@@ -794,6 +1047,7 @@ var FP12 = function(ctx) {
return FP12;
};
+
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
module.exports = {
FP12: FP12
diff --git a/src/fp16.js b/src/fp16.js
index d700dfc..14d10e8 100644
--- a/src/fp16.js
+++ b/src/fp16.js
@@ -50,7 +50,6 @@ var FP16 = function(ctx) {
/* test this==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch());
},
@@ -122,13 +121,13 @@ var FP16 = function(ctx) {
/* this=-this */
neg: function() {
- var m = new ctx.FP8(this.a),
+ var m = new ctx.FP8(this.a),
t = new ctx.FP8(0);
this.norm();
-
m.add(this.b);
m.neg();
+
t.copy(m);
t.add(this.b);
this.b.copy(m);
@@ -157,7 +156,7 @@ var FP16 = function(ctx) {
/* this-=x */
sub: function(x) {
- var m = new FP16(x);
+ var m = new FP16(x);
m.neg();
this.add(m);
},
@@ -182,9 +181,9 @@ var FP16 = function(ctx) {
/* this*=this */
sqr: function() {
- var t1 = new ctx.FP8(this.a),
- t2 = new ctx.FP8(this.b),
- t3 = new ctx.FP8(this.a);
+ var t1 = new ctx.FP8(this.a),
+ t2 = new ctx.FP8(this.b),
+ t3 = new ctx.FP8(this.a);
t3.mul(this.b);
t1.add(this.b);
@@ -214,10 +213,10 @@ var FP16 = function(ctx) {
/* this*=y */
mul: function(y) {
- var t1 = new ctx.FP8(this.a),
- t2 = new ctx.FP8(this.b),
+ var t1 = new ctx.FP8(this.a),
+ t2 = new ctx.FP8(this.b),
t3 = new ctx.FP8(0),
- t4 = new ctx.FP8(this.b);
+ t4 = new ctx.FP8(this.b);
t1.mul(y.a);
t2.mul(y.b);
@@ -253,10 +252,10 @@ var FP16 = function(ctx) {
/* this=1/this */
inverse: function() {
- this.norm();
+ //this.norm();
- var t1 = new ctx.FP8(this.a),
- t2 = new ctx.FP8(this.b);
+ var t1 = new ctx.FP8(this.a),
+ t2 = new ctx.FP8(this.b);
t1.sqr();
t2.sqr();
@@ -304,14 +303,13 @@ var FP16 = function(ctx) {
/* this=this^e */
pow: function(e) {
- this.norm();
- e.norm();
-
- var w = new FP16(this),
- z = new ctx.BIG(e),
+
+ var w = new FP16(this),
+ z = new ctx.BIG(e),
r = new FP16(1),
bt;
-
+ w.norm();
+ z.norm();
for (;;) {
bt = z.parity();
z.fshr(1);
@@ -333,8 +331,8 @@ var FP16 = function(ctx) {
/* XTR xtr_a function */
xtr_A: function(w, y, z) {
- var r = new FP16(w),
- t = new FP16(w);
+ var r = new FP16(w),
+ t = new FP16(w);
r.sub(y);
r.norm();
@@ -353,18 +351,20 @@ var FP16 = function(ctx) {
/* XTR xtr_d function */
xtr_D: function() {
- var w = new FP16(this);
+ var w = new FP16(this);
this.sqr();
w.conj();
- w.add(w);
+ w.add(w);
this.sub(w);
this.reduce();
},
/* r=x^n using XTR method on traces of FP12s */
xtr_pow: function(n) {
+ var sf = new FP16(this);
+ sf.norm();
var a = new FP16(3),
- b = new FP16(this),
+ b = new FP16(sf),
c = new FP16(b),
t = new FP16(0),
r = new FP16(0),
@@ -372,10 +372,10 @@ var FP16 = function(ctx) {
c.xtr_D();
- n.norm();
+
par = n.parity();
v = new ctx.BIG(n);
-
+ v.norm();
v.fshr(1);
if (par === 0) {
@@ -387,10 +387,10 @@ var FP16 = function(ctx) {
for (i = nb - 1; i >= 0; i--) {
if (v.bit(i) != 1) {
t.copy(b);
- this.conj();
+ sf.conj();
c.conj();
- b.xtr_A(a, this, c);
- this.conj();
+ b.xtr_A(a, sf, c);
+ sf.conj();
c.copy(t);
c.xtr_D();
a.xtr_D();
@@ -399,7 +399,7 @@ var FP16 = function(ctx) {
t.conj();
a.copy(b);
a.xtr_D();
- b.xtr_A(c, this, t);
+ b.xtr_A(c, sf, t);
c.xtr_D();
}
}
@@ -416,21 +416,22 @@ var FP16 = function(ctx) {
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
xtr_pow2: function(ck, ckml, ckm2l, a, b) {
- a.norm();
- b.norm();
- var e = new ctx.BIG(a),
- d = new ctx.BIG(b),
+ var e = new ctx.BIG(a),
+ d = new ctx.BIG(b),
w = new ctx.BIG(0),
- cu = new FP16(ck),
- cv = new FP16(this),
- cumv = new FP16(ckml),
- cum2v = new FP16(ckm2l),
+ cu = new FP16(ck),
+ cv = new FP16(this),
+ cumv = new FP16(ckml),
+ cum2v = new FP16(ckm2l),
r = new FP16(0),
t = new FP16(0),
f2 = 0,
i;
+ d.norm();
+ e.norm();
+
while (d.parity() === 0 && e.parity() === 0) {
d.fshr(1);
e.fshr(1);
diff --git a/src/fp2.js b/src/fp2.js
index 695fa9d..d2d1a50 100644
--- a/src/fp2.js
+++ b/src/fp2.js
@@ -50,7 +50,6 @@ var FP2 = function(ctx) {
/* test this=0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch());
},
@@ -151,7 +150,7 @@ var FP2 = function(ctx) {
/* this-=x */
sub: function(x) {
- var m = new FP2(x);
+ var m = new FP2(x);
m.neg();
this.add(m);
},
@@ -180,7 +179,6 @@ var FP2 = function(ctx) {
mb = new ctx.FP(this.b);
w1.add(this.b);
-
w3.add(this.a);
w3.norm();
this.b.mul(w3);
@@ -317,7 +315,7 @@ var FP2 = function(ctx) {
/* this*=sqrt(-1) */
times_i: function() {
- var z = new ctx.FP(this.a);
+ var z = new ctx.FP(this.a); //z.copy(this.a);
this.a.copy(this.b);
this.a.neg();
this.b.copy(z);
@@ -326,13 +324,14 @@ var FP2 = function(ctx) {
/* w*=(1+sqrt(-1)) */
/* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
mul_ip: function() {
- var t = new FP2(this),
+ var t = new FP2(this),
z = new ctx.FP(this.a);
this.a.copy(this.b);
this.a.neg();
this.b.copy(z);
this.add(t);
+ // this.norm();
},
div_ip2: function() {
@@ -364,7 +363,7 @@ var FP2 = function(ctx) {
this.norm();
var r = new FP2(1),
- x = new FP2(this),
+ x = new FP2(this),
bt;
e.norm();
diff --git a/src/fp24.js b/src/fp24.js
index 43bc85a..50cd3d2 100644
--- a/src/fp24.js
+++ b/src/fp24.js
@@ -26,15 +26,27 @@ var FP24 = function(ctx) {
/* general purpose constructor */
var FP24 = function(d, e, f) {
- if (d instanceof FP24) {
- this.a = new ctx.FP8(d.a);
- this.b = new ctx.FP8(d.b);
- this.c = new ctx.FP8(d.c);
- } else {
- this.a = new ctx.FP8(d);
- this.b = new ctx.FP8(e);
- this.c = new ctx.FP8(f);
- }
+ if (!isNaN(d))
+ {
+ this.a = new ctx.FP8(d);
+ this.b = new ctx.FP8(0);
+ this.c = new ctx.FP8(0);
+ if (d==1) this.stype=ctx.FP.ONE;
+ else this.stype=ctx.FP.SPARSER;
+ }
+ else
+ {
+ if (d instanceof FP24) {
+ this.a = new ctx.FP8(d.a);
+ this.b = new ctx.FP8(d.b);
+ this.c = new ctx.FP8(d.c);
+ } else {
+ this.a = new ctx.FP8(d);
+ this.b = new ctx.FP8(e);
+ this.c = new ctx.FP8(f);
+ }
+ this.stype=ctx.FP.DENSE;
+ }
};
FP24.prototype = {
@@ -54,7 +66,6 @@ var FP24 = function(ctx) {
/* test x==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
},
@@ -69,6 +80,8 @@ var FP24 = function(ctx) {
this.a.cmove(g.a, d);
this.b.cmove(g.b, d);
this.c.cmove(g.c, d);
+ d=~(d-1);
+ this.stype^=(this.stype^g.stype)&d;
},
/* Constant time select from pre-computed table */
@@ -80,7 +93,7 @@ var FP24 = function(ctx) {
babs = (b ^ m) - m;
babs = (babs - 1) / 2;
- this.cmove(g[0], FP24.teq(babs, 0));
+ this.cmove(g[0], FP24.teq(babs, 0)); // conditional move
this.cmove(g[1], FP24.teq(babs, 1));
this.cmove(g[2], FP24.teq(babs, 2));
this.cmove(g[3], FP24.teq(babs, 3));
@@ -93,7 +106,14 @@ var FP24 = function(ctx) {
invf.conj();
this.cmove(invf, (m & 1));
},
-
+
+ settype: function(w) {
+ this.stype=w;
+ },
+
+ gettype: function() {
+ return this.stype;
+ },
/* extract a from this */
geta: function() {
return this.a;
@@ -119,6 +139,7 @@ var FP24 = function(ctx) {
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -126,6 +147,15 @@ var FP24 = function(ctx) {
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
+ },
+
+ /* set this=0 */
+ zero: function() {
+ this.a.zero();
+ this.b.zero();
+ this.c.zero();
+ this.stype=ctx.FP.ZERO;
},
/* this=conj(this) */
@@ -140,6 +170,7 @@ var FP24 = function(ctx) {
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP8 */
@@ -147,13 +178,14 @@ var FP24 = function(ctx) {
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
usqr: function() {
- var A = new ctx.FP8(this.a),
- B = new ctx.FP8(this.c),
- C = new ctx.FP8(this.b),
+ var A = new ctx.FP8(this.a),
+ B = new ctx.FP8(this.c),
+ C = new ctx.FP8(this.b),
D = new ctx.FP8(0);
this.a.sqr();
@@ -184,19 +216,23 @@ var FP24 = function(ctx) {
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
- var A = new ctx.FP8(this.a),
- B = new ctx.FP8(this.b),
- C = new ctx.FP8(this.c),
- D = new ctx.FP8(this.a);
+ if (this.stype==ctx.FP.ONE)
+ return;
+
+ var A = new ctx.FP8(this.a),
+ B = new ctx.FP8(this.b),
+ C = new ctx.FP8(this.c),
+ D = new ctx.FP8(this.a);
A.sqr();
B.mul(this.c);
- B.add(B);
+ B.add(B);
C.sqr();
D.mul(this.b);
D.add(D);
@@ -219,18 +255,21 @@ var FP24 = function(ctx) {
this.b.copy(C);
this.b.add(D);
this.c.add(A);
-
+ if (this.stype==ctx.FP.SPARSER)
+ this.stype=ctx.FP.SPARSE;
+ else
+ this.stype=ctx.FP.DENSE;
this.norm();
},
/* FP24 full multiplication this=this*y */
mul: function(y) {
- var z0 = new ctx.FP8(this.a),
+ var z0 = new ctx.FP8(this.a),
z1 = new ctx.FP8(0),
- z2 = new ctx.FP8(this.b),
+ z2 = new ctx.FP8(this.b),
z3 = new ctx.FP8(0),
- t0 = new ctx.FP8(this.a),
- t1 = new ctx.FP8(y.a);
+ t0 = new ctx.FP8(this.a),
+ t1 = new ctx.FP8(y.a);
z0.mul(y.a);
z2.mul(y.b);
@@ -287,119 +326,327 @@ var FP24 = function(ctx) {
z3.add(t1);
t0.times_i();
this.b.add(t0);
+ // z3.norm();
z3.times_i();
this.a.copy(z0);
this.a.add(z3);
-
+ this.stype=ctx.FP.DENSE;
this.norm();
},
- /* Special case this*=y that arises from special form of ATE pairing line function */
- smul: function(y, twist) {
- var z0, z1, z2, z3, t0, t1;
-
- if (twist == ctx.ECP.D_TYPE) {
- z0 = new ctx.FP8(this.a);
- z2 = new ctx.FP8(this.b);
- z3 = new ctx.FP8(this.b);
- t0 = new ctx.FP8(0);
- t1 = new ctx.FP8(y.a);
-
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
-
- this.b.norm();
- t1.norm();
-
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
-
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
-
- this.b.add(t0);
-
- this.b.add(t1);
- z3.add(t1);
- z2.add(t0);
-
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
-
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
-
- if (twist == ctx.ECP.M_TYPE) {
- z0=new ctx.FP8(this.a);
- z1=new ctx.FP8(0);
- z2=new ctx.FP8(0);
- z3=new ctx.FP8(0);
- t0=new ctx.FP8(this.a);
- t1=new ctx.FP8(0);
-
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
-
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
-
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
-
- t0.copy(z0); t0.neg();
-
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
-
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
-
- t0.norm();
- t1.norm();
-
- t0.mul(t1);
- z2.add(t0);
-
- t0.copy(this.c);
-
- t0.pmul(y.c.getb());
- t0.times_i();
-
- t1.copy(t0); t1.neg();
-
- this.c.copy(z2); this.c.add(t1);
- z3.add(t1);
- t0.times_i();
- this.b.add(t0);
- z3.norm();
- z3.times_i();
- this.a.copy(z0); this.a.add(z3);
- }
-
- this.norm();
- },
+/* FP24 multiplication w=w*y */
+/* catering for special case that arises from special form of ATE pairing line function */
+/* w and y are both sparser line functions - cost = 6m */
+ smul: function(y) {
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ var w1=new ctx.FP4(this.a.geta());
+ var w2=new ctx.FP4(this.a.getb());
+ var w3=new ctx.FP4(this.b.geta());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ var ta=new ctx.FP4(this.a.geta());
+ var tb=new ctx.FP4(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP4(ta);
+ tc.mul(tb);
+ var t=new ctx.FP4(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ var td=new ctx.FP4(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ var te=new ctx.FP4(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+ this.b.geta().copy(td); this.b.getb().copy(te);
+ this.c.geta().copy(w3); this.c.getb().zero();
+
+ this.a.norm();
+ this.b.norm();
+
+ } else {
+ var w1=new ctx.FP4(this.a.geta());
+ var w2=new ctx.FP4(this.a.getb());
+ var w3=new ctx.FP4(this.c.getb());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
+
+ var ta=new ctx.FP4(this.a.geta());
+ var tb=new ctx.FP4(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP4(ta);
+ tc.mul(tb);
+ var t=new ctx.FP4(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ var td=new ctx.FP4(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ var te=new ctx.FP4(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+
+ w3.times_i();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
+
+ te.norm();
+ te.times_i();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
+
+ this.a.norm();
+ this.c.norm();
+
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
+
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ ssmul: function(y) {
+ if (this.stype==ctx.FP.ONE)
+ {
+ this.copy(y);
+ return;
+ }
+ if (y.stype==ctx.FP.ONE)
+ return;
+
+ if (y.stype>=ctx.FP.SPARSE)
+ {
+ var z0=new ctx.FP8(this.a);
+ var z1=new ctx.FP8(0);
+ var z2=new ctx.FP8(0);
+ var z3=new ctx.FP8(0);
+ z0.mul(y.a);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ z2.getb().copy(this.b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ var t0=new ctx.FP8(this.a);
+ var t1=new ctx.FP8(y.a);
+ t0.add(this.b); t0.norm();
+ t1.add(y.b); t1.norm();
+
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(this.b); t0.add(this.c); t0.norm();
+ t1.copy(y.b); t1.add(y.c); t1.norm();
+
+ z3.copy(t0); z3.mul(t1);
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ z1.add(t0);
+ this.b.copy(z1); this.b.add(t1);
+
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ t0.geta().copy(this.c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ } else {
+ if (this.stype==ctx.FP.SPARSER)
+ {
+ this.smul(y);
+ return;
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ { // dense by sparser - 13m
+ var z0=new ctx.FP8(this.a);
+ var z2=new ctx.FP8(this.b);
+ var z3=new ctx.FP8(this.b);
+ var t0=new ctx.FP8(0);
+ var t1=new ctx.FP8(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ this.b.add(this.a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ this.b.norm();
+ this.b.mul(t1);
+ z3.add(this.c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ this.b.add(t0);
+
+ this.b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ this.c.copy(z2); this.c.add(t0);
+
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ var z0=new ctx.FP8(this.a);
+ var z1=new ctx.FP8(0);
+ var z2=new ctx.FP8(0);
+ var z3=new ctx.FP8(0);
+ var t0=new ctx.FP8(this.a);
+ var t1=new ctx.FP8(0);
+
+ z0.mul(y.a);
+ t0.add(this.b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(this.b); t0.add(this.c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ this.b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(this.c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ }
+ this.stype=ctx.FP.DENSE;
+ this.norm();
+ },
/* this=1/this */
inverse: function() {
- var f0 = new ctx.FP8(this.a),
- f1 = new ctx.FP8(this.b),
- f2 = new ctx.FP8(this.a),
+ var f0 = new ctx.FP8(this.a),
+ f1 = new ctx.FP8(this.b),
+ f2 = new ctx.FP8(this.a),
f3 = new ctx.FP8(0);
f0.sqr();
@@ -439,6 +686,7 @@ var FP24 = function(ctx) {
this.b.mul(f3);
this.c.copy(f2);
this.c.mul(f3);
+ this.stype=ctx.FP.DENSE;
},
/* this=this^p, where p=Modulus, using Frobenius */
@@ -460,6 +708,7 @@ var FP24 = function(ctx) {
this.b.qmul(f); this.b.times_i2();
this.c.qmul(f2); this.c.times_i2(); this.c.times_i2();
}
+ this.stype=ctx.FP.DENSE;
},
/* trace function */
@@ -588,29 +837,31 @@ var FP24 = function(ctx) {
/* set this=this^e */
pow: function(e) {
- var e3, w, nb, i, bt;
+ var e1, e3, w, nb, i, bt, sf;
- this.norm();
- e.norm();
+ sf = new FP24(this);
+ sf.norm();
+ e1 = new ctx.BIG(e);
+ e1.norm();
- e3 = new ctx.BIG(e);
+ e3 = new ctx.BIG(e1);
e3.pmul(3);
e3.norm();
- w = new FP24(this);
+ w = new FP24(sf);
nb = e3.nbits();
for (i = nb - 2; i >= 1; i--) {
w.usqr();
- bt = e3.bit(i) - e.bit(i);
+ bt = e3.bit(i) - e1.bit(i);
if (bt == 1) {
- w.mul(this);
+ w.mul(sf);
}
if (bt == -1) {
- this.conj();
- w.mul(this);
- this.conj();
+ sf.conj();
+ w.mul(sf);
+ sf.conj();
}
}
w.reduce();
@@ -695,7 +946,7 @@ var FP24 = function(ctx) {
t[i] = w[i + ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 2 * ctx.BIG.MODBYTES];
@@ -705,9 +956,9 @@ var FP24 = function(ctx) {
t[i] = w[i + 3 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 4 * ctx.BIG.MODBYTES];
@@ -717,7 +968,7 @@ var FP24 = function(ctx) {
t[i] = w[i + 5 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 6 * ctx.BIG.MODBYTES];
@@ -727,9 +978,9 @@ var FP24 = function(ctx) {
t[i] = w[i + 7 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
e = new ctx.FP8(ea,eb);
@@ -741,7 +992,7 @@ var FP24 = function(ctx) {
t[i] = w[i + 9 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 10 * ctx.BIG.MODBYTES];
@@ -753,7 +1004,7 @@ var FP24 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 12 * ctx.BIG.MODBYTES];
@@ -763,7 +1014,7 @@ var FP24 = function(ctx) {
t[i] = w[i + 13 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 14 * ctx.BIG.MODBYTES];
@@ -775,9 +1026,9 @@ var FP24 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
- f = new ctx.FP8(ea, eb);
+ f = new ctx.FP8(ea, eb); //f.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 16 * ctx.BIG.MODBYTES];
@@ -787,7 +1038,7 @@ var FP24 = function(ctx) {
t[i] = w[i + 17 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 18 * ctx.BIG.MODBYTES];
@@ -797,9 +1048,9 @@ var FP24 = function(ctx) {
t[i] = w[i + 19 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 20 * ctx.BIG.MODBYTES];
@@ -809,7 +1060,7 @@ var FP24 = function(ctx) {
t[i] = w[i + 21 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 22 * ctx.BIG.MODBYTES];
@@ -819,13 +1070,13 @@ var FP24 = function(ctx) {
t[i] = w[i + 23 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
- g = new ctx.FP8(ea, eb);
+ g = new ctx.FP8(ea, eb); //g.set(c,d);
- r = new FP24(e, f, g);
+ r = new FP24(e, f, g); //r.set(e,f,g);
return r;
};
@@ -860,14 +1111,14 @@ var FP24 = function(ctx) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
}
- g1[0] = new FP24(q[0]);
- g1[1] = new FP24(g1[0]); g1[1].mul(q[1]);
- g1[2] = new FP24(g1[0]); g1[2].mul(q[2]);
- g1[3] = new FP24(g1[1]); g1[3].mul(q[2]);
- g1[4] = new FP24(q[0]); g1[4].mul(q[3]);
- g1[5] = new FP24(g1[1]); g1[5].mul(q[3]);
- g1[6] = new FP24(g1[2]); g1[6].mul(q[3]);
- g1[7] = new FP24(g1[3]); g1[7].mul(q[3]);
+ g1[0] = new FP24(q[0]); // q[0]
+ g1[1] = new FP24(g1[0]); g1[1].mul(q[1]); // q[0].q[1]
+ g1[2] = new FP24(g1[0]); g1[2].mul(q[2]); // q[0].q[2]
+ g1[3] = new FP24(g1[1]); g1[3].mul(q[2]); // q[0].q[1].q[2]
+ g1[4] = new FP24(q[0]); g1[4].mul(q[3]); // q[0].q[3]
+ g1[5] = new FP24(g1[1]); g1[5].mul(q[3]); // q[0].q[1].q[3]
+ g1[6] = new FP24(g1[2]); g1[6].mul(q[3]); // q[0].q[2].q[3]
+ g1[7] = new FP24(g1[3]); g1[7].mul(q[3]); // q[0].q[1].q[2].q[3]
// Use Frobenius
fa.rcopy(ctx.ROM_FIELD.Fra);
diff --git a/src/fp4.js b/src/fp4.js
index 5fda45b..12c7c97 100644
--- a/src/fp4.js
+++ b/src/fp4.js
@@ -50,7 +50,6 @@ var FP4 = function(ctx) {
/* test this==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch());
},
@@ -123,7 +122,7 @@ var FP4 = function(ctx) {
/* this=-this */
neg: function() {
this.norm();
- var m = new ctx.FP2(this.a),
+ var m = new ctx.FP2(this.a),
t = new ctx.FP2(0);
m.add(this.b);
@@ -156,7 +155,7 @@ var FP4 = function(ctx) {
/* this-=x */
sub: function(x) {
- var m = new FP4(x);
+ var m = new FP4(x);
m.neg();
this.add(m);
},
@@ -180,9 +179,11 @@ var FP4 = function(ctx) {
/* this*=this */
sqr: function() {
- var t1 = new ctx.FP2(this.a),
- t2 = new ctx.FP2(this.b),
- t3 = new ctx.FP2(this.a);
+ // this.norm();
+
+ var t1 = new ctx.FP2(this.a),
+ t2 = new ctx.FP2(this.b),
+ t3 = new ctx.FP2(this.a);
t3.mul(this.b);
t1.add(this.b);
@@ -212,10 +213,12 @@ var FP4 = function(ctx) {
/* this*=y */
mul: function(y) {
- var t1 = new ctx.FP2(this.a),
- t2 = new ctx.FP2(this.b),
+ // this.norm();
+
+ var t1 = new ctx.FP2(this.a),
+ t2 = new ctx.FP2(this.b),
t3 = new ctx.FP2(0),
- t4 = new ctx.FP2(this.b);
+ t4 = new ctx.FP2(this.b);
t1.mul(y.a);
t2.mul(y.b);
@@ -253,8 +256,8 @@ var FP4 = function(ctx) {
inverse: function() {
this.norm();
- var t1 = new ctx.FP2(this.a),
- t2 = new ctx.FP2(this.b);
+ var t1 = new ctx.FP2(this.a),
+ t2 = new ctx.FP2(this.b);
t1.sqr();
t2.sqr();
@@ -270,8 +273,8 @@ var FP4 = function(ctx) {
/* this*=i where i = sqrt(-1+sqrt(-1)) */
times_i: function() {
- var s = new ctx.FP2(this.b),
- t = new ctx.FP2(this.b);
+ var s = new ctx.FP2(this.b), //s.copy(this.b);
+ t = new ctx.FP2(this.b); //t.copy(this.b);
s.times_i();
t.add(s);
@@ -289,14 +292,12 @@ var FP4 = function(ctx) {
/* this=this^e */
pow: function(e) {
- this.norm();
- e.norm();
-
- var w = new FP4(this),
- z = new ctx.BIG(e),
+ var w = new FP4(this),
+ z = new ctx.BIG(e),
r = new FP4(1),
bt;
-
+ w.norm();
+ z.norm();
for (;;) {
bt = z.parity();
z.fshr(1);
@@ -318,9 +319,10 @@ var FP4 = function(ctx) {
/* XTR xtr_a function */
xtr_A: function(w, y, z) {
- var r = new FP4(w),
- t = new FP4(w);
+ var r = new FP4(w),
+ t = new FP4(w);
+ //y.norm(); // ??
r.sub(y);
r.norm();
r.pmul(this.a);
@@ -338,29 +340,32 @@ var FP4 = function(ctx) {
/* XTR xtr_d function */
xtr_D: function() {
- var w = new FP4(this);
+ var w = new FP4(this);
this.sqr();
w.conj();
- w.add(w);
+ w.add(w);
this.sub(w);
this.reduce();
},
/* r=x^n using XTR method on traces of FP12s */
xtr_pow: function(n) {
+ var sf = new FP4(this);
+ sf.norm();
var a = new FP4(3),
- b = new FP4(this),
+ b = new FP4(sf),
c = new FP4(b),
t = new FP4(0),
r = new FP4(0),
par, v, nb, i;
+
c.xtr_D();
- n.norm();
+ //n.norm();
par = n.parity();
v = new ctx.BIG(n);
-
+ v.norm();
v.fshr(1);
if (par === 0) {
@@ -372,10 +377,10 @@ var FP4 = function(ctx) {
for (i = nb - 1; i >= 0; i--) {
if (v.bit(i) != 1) {
t.copy(b);
- this.conj();
+ sf.conj();
c.conj();
- b.xtr_A(a, this, c);
- this.conj();
+ b.xtr_A(a, sf, c);
+ sf.conj();
c.copy(t);
c.xtr_D();
a.xtr_D();
@@ -384,7 +389,7 @@ var FP4 = function(ctx) {
t.conj();
a.copy(b);
a.xtr_D();
- b.xtr_A(c, this, t);
+ b.xtr_A(c, sf, t);
c.xtr_D();
}
}
@@ -401,21 +406,22 @@ var FP4 = function(ctx) {
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
xtr_pow2: function(ck, ckml, ckm2l, a, b) {
- a.norm();
- b.norm();
-
- var e = new ctx.BIG(a),
- d = new ctx.BIG(b),
+
+ var e = new ctx.BIG(a),
+ d = new ctx.BIG(b),
w = new ctx.BIG(0),
- cu = new FP4(ck),
- cv = new FP4(this),
- cumv = new FP4(ckml),
- cum2v = new FP4(ckm2l),
+ cu = new FP4(ck),
+ cv = new FP4(this),
+ cumv = new FP4(ckml),
+ cum2v = new FP4(ckm2l),
r = new FP4(0),
t = new FP4(0),
f2 = 0,
i;
+ e.norm();
+ d.norm();
+
while (d.parity() === 0 && e.parity() === 0) {
d.fshr(1);
e.fshr(1);
diff --git a/src/fp48.js b/src/fp48.js
index 68b3f4e..58ac47b 100644
--- a/src/fp48.js
+++ b/src/fp48.js
@@ -26,15 +26,27 @@ var FP48 = function(ctx) {
/* general purpose constructor */
var FP48 = function(d, e, f) {
- if (d instanceof FP48) {
- this.a = new ctx.FP16(d.a);
- this.b = new ctx.FP16(d.b);
- this.c = new ctx.FP16(d.c);
- } else {
- this.a = new ctx.FP16(d);
- this.b = new ctx.FP16(e);
- this.c = new ctx.FP16(f);
- }
+ if (!isNaN(d))
+ {
+ this.a = new ctx.FP16(d);
+ this.b = new ctx.FP16(0);
+ this.c = new ctx.FP16(0);
+ if (d==1) this.stype=ctx.FP.ONE;
+ else this.stype=ctx.FP.SPARSER;
+ }
+ else
+ {
+ if (d instanceof FP48) {
+ this.a = new ctx.FP16(d.a);
+ this.b = new ctx.FP16(d.b);
+ this.c = new ctx.FP16(d.c);
+ } else {
+ this.a = new ctx.FP16(d);
+ this.b = new ctx.FP16(e);
+ this.c = new ctx.FP16(f);
+ }
+ this.stype=ctx.FP.DENSE;
+ }
};
FP48.prototype = {
@@ -54,7 +66,6 @@ var FP48 = function(ctx) {
/* test x==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
},
@@ -69,6 +80,9 @@ var FP48 = function(ctx) {
this.a.cmove(g.a, d);
this.b.cmove(g.b, d);
this.c.cmove(g.c, d);
+ d=~(d-1);
+ this.stype^=(this.stype^g.stype)&d;
+
},
/* Constant time select from pre-computed table */
@@ -94,6 +108,14 @@ var FP48 = function(ctx) {
this.cmove(invf, (m & 1));
},
+ settype: function(w) {
+ this.stype=w;
+ },
+
+ gettype: function() {
+ return this.stype;
+ },
+
/* extract a from this */
geta: function() {
return this.a;
@@ -119,6 +141,7 @@ var FP48 = function(ctx) {
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -126,6 +149,15 @@ var FP48 = function(ctx) {
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
+ },
+
+ /* set this=0 */
+ zero: function() {
+ this.a.zero();
+ this.b.zero();
+ this.c.zero();
+ this.stype=ctx.FP.ZERO;
},
/* this=conj(this) */
@@ -140,6 +172,7 @@ var FP48 = function(ctx) {
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP16 */
@@ -147,11 +180,12 @@ var FP48 = function(ctx) {
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
usqr: function() {
- var A = new ctx.FP16(this.a),
+ var A = new ctx.FP16(this.a),
B = new ctx.FP16(this.c),
C = new ctx.FP16(this.b),
D = new ctx.FP16(0);
@@ -184,19 +218,23 @@ var FP48 = function(ctx) {
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
- var A = new ctx.FP16(this.a),
- B = new ctx.FP16(this.b),
- C = new ctx.FP16(this.c),
- D = new ctx.FP16(this.a);
+ if (this.stype==ctx.FP.ONE)
+ return;
+
+ var A = new ctx.FP16(this.a),
+ B = new ctx.FP16(this.b),
+ C = new ctx.FP16(this.c),
+ D = new ctx.FP16(this.a);
A.sqr();
B.mul(this.c);
- B.add(B);
+ B.add(B);
C.sqr();
D.mul(this.b);
D.add(D);
@@ -219,18 +257,21 @@ var FP48 = function(ctx) {
this.b.copy(C);
this.b.add(D);
this.c.add(A);
-
+ if (this.stype==ctx.FP.SPARSER)
+ this.stype=ctx.FP.SPARSE;
+ else
+ this.stype=ctx.FP.DENSE;
this.norm();
},
/* FP48 full multiplication this=this*y */
mul: function(y) {
- var z0 = new ctx.FP16(this.a),
+ var z0 = new ctx.FP16(this.a),
z1 = new ctx.FP16(0),
- z2 = new ctx.FP16(this.b),
+ z2 = new ctx.FP16(this.b),
z3 = new ctx.FP16(0),
- t0 = new ctx.FP16(this.a),
- t1 = new ctx.FP16(y.a);
+ t0 = new ctx.FP16(this.a),
+ t1 = new ctx.FP16(y.a);
z0.mul(y.a);
z2.mul(y.b);
@@ -287,120 +328,328 @@ var FP48 = function(ctx) {
z3.add(t1);
t0.times_i();
this.b.add(t0);
- // z3.norm();
+
z3.times_i();
this.a.copy(z0);
this.a.add(z3);
-
+ this.stype=ctx.FP.DENSE;
this.norm();
},
- /* Special case this*=y that arises from special form of ATE pairing line function */
- smul: function(y, twist) {
- var z0, z1, z2, z3, t0, t1;
-
- if (twist == ctx.ECP.D_TYPE) {
- z0 = new ctx.FP16(this.a),
- z2 = new ctx.FP16(this.b),
- z3 = new ctx.FP16(this.b),
- t0 = new ctx.FP16(0),
- t1 = new ctx.FP16(y.a);
-
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
-
- this.b.norm();
- t1.norm();
-
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
-
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
-
- this.b.add(t0);
-
- this.b.add(t1);
- z3.add(t1);
- z2.add(t0);
-
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
-
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
-
- if (twist == ctx.ECP.M_TYPE) {
- z0=new ctx.FP16(this.a);
- z1=new ctx.FP16(0);
- z2=new ctx.FP16(0);
- z3=new ctx.FP16(0);
- t0=new ctx.FP16(this.a);
- t1=new ctx.FP16(0);
-
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
-
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
-
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
-
- t0.copy(z0); t0.neg();
-
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
+/* FP48 multiplication w=w*y */
+/* catering for special case that arises from special form of ATE pairing line function */
+/* w and y are both sparser line functions - cost = 6m */
+ smul: function(y) {
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ var w1=new ctx.FP8(this.a.geta());
+ var w2=new ctx.FP8(this.a.getb());
+ var w3=new ctx.FP8(this.b.geta());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ var ta=new ctx.FP8(this.a.geta());
+ var tb=new ctx.FP8(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP8(ta);
+ tc.mul(tb);
+ var t=new ctx.FP8(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ var td=new ctx.FP8(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ var te=new ctx.FP8(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+ this.b.geta().copy(td); this.b.getb().copy(te);
+ this.c.geta().copy(w3); this.c.getb().zero();
+
+ this.a.norm();
+ this.b.norm();
+
+ } else {
+ var w1=new ctx.FP8(this.a.geta());
+ var w2=new ctx.FP8(this.a.getb());
+ var w3=new ctx.FP8(this.c.getb());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
+
+ var ta=new ctx.FP8(this.a.geta());
+ var tb=new ctx.FP8(y.a.geta());
+ ta.add(this.a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ var tc=new ctx.FP8(ta);
+ tc.mul(tb);
+ var t=new ctx.FP8(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(this.a.geta()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ var td=new ctx.FP8(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(this.a.getb()); ta.add(this.c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ var te=new ctx.FP8(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
+
+ w3.times_i();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
+
+ te.norm();
+ te.times_i();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
+
+ this.a.norm();
+ this.c.norm();
+
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
+
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ ssmul: function(y) {
+ if (this.stype==ctx.FP.ONE)
+ {
+ this.copy(y);
+ return;
+ }
+ if (y.stype==ctx.FP.ONE)
+ return;
+
+ if (y.stype>=ctx.FP.SPARSE)
+ {
+ var z0=new ctx.FP16(this.a);
+ var z1=new ctx.FP16(0);
+ var z2=new ctx.FP16(0);
+ var z3=new ctx.FP16(0);
+ z0.mul(y.a);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ z2.getb().copy(this.b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ z2.geta().copy(this.b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(this.b);
+ z2.mul(y.b);
+ }
+ var t0=new ctx.FP16(this.a);
+ var t1=new ctx.FP16(y.a);
+ t0.add(this.b); t0.norm();
+ t1.add(y.b); t1.norm();
+
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(this.b); t0.add(this.c); t0.norm();
+ t1.copy(y.b); t1.add(y.c); t1.norm();
+
+ z3.copy(t0); z3.mul(t1);
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ z1.add(t0);
+ this.b.copy(z1); this.b.add(t1);
+
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ {
+ if (y.stype==ctx.FP.SPARSE || this.stype==ctx.FP.SPARSE)
+ {
+ t0.geta().copy(this.c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (this.stype!=ctx.FP.SPARSE)
+ {
+ t0.getb().copy(this.c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(this.c);
+ t0.mul(y.c);
+ }
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ } else {
+ if (this.stype==ctx.FP.SPARSER)
+ {
+ this.smul(y);
+ return;
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
+ { // dense by sparser - 13m
+ var z0=new ctx.FP16(this.a);
+ var z2=new ctx.FP16(this.b);
+ var z3=new ctx.FP16(this.b);
+ var t0=new ctx.FP16(0);
+ var t1=new ctx.FP16(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ this.b.add(this.a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ this.b.norm();
+ this.b.mul(t1);
+ z3.add(this.c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ this.b.add(t0);
+
+ this.b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ this.c.copy(z2); this.c.add(t0);
+
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ var z0=new ctx.FP16(this.a);
+ var z1=new ctx.FP16(0);
+ var z2=new ctx.FP16(0);
+ var z3=new ctx.FP16(0);
+ var t0=new ctx.FP16(this.a);
+ var t1=new ctx.FP16(0);
+
+ z0.mul(y.a);
+ t0.add(this.b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(this.b); t0.add(this.c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ this.b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(this.a); t0.add(this.c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(this.c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ this.c.copy(z2); this.c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ this.b.add(t0);
+ z3.norm();
+ z3.times_i();
+ this.a.copy(z0); this.a.add(z3);
+ }
+ }
+ this.stype=ctx.FP.DENSE;
+ this.norm();
+ },
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
-
- t0.norm();
- t1.norm();
-
- t0.mul(t1);
- z2.add(t0);
-
- t0.copy(this.c);
-
- t0.pmul(y.c.getb());
- t0.times_i();
-
- t1.copy(t0); t1.neg();
-
- this.c.copy(z2); this.c.add(t1);
- z3.add(t1);
- t0.times_i();
- this.b.add(t0);
- z3.norm();
- z3.times_i();
- this.a.copy(z0); this.a.add(z3);
- }
-
- this.norm();
- },
/* this=1/this */
inverse: function() {
- var f0 = new ctx.FP16(this.a),
- f1 = new ctx.FP16(this.b),
- f2 = new ctx.FP16(this.a),
+ var f0 = new ctx.FP16(this.a),
+ f1 = new ctx.FP16(this.b),
+ f2 = new ctx.FP16(this.a),
f3 = new ctx.FP16(0);
f0.sqr();
@@ -440,6 +689,7 @@ var FP48 = function(ctx) {
this.b.mul(f3);
this.c.copy(f2);
this.c.mul(f3);
+ this.stype=ctx.FP.DENSE;
},
/* this=this^p, where p=Modulus, using Frobenius */
@@ -462,6 +712,7 @@ var FP48 = function(ctx) {
this.b.qmul(f); this.b.times_i4(); this.b.times_i2();
this.c.qmul(f2); this.c.times_i4(); this.c.times_i4(); this.c.times_i4();
}
+ this.stype=ctx.FP.DENSE;
},
/* trace function */
@@ -692,29 +943,31 @@ var FP48 = function(ctx) {
/* set this=this^e */
pow: function(e) {
- var e3, w, nb, i, bt;
+ var e1, e3, w, nb, i, bt, sf;
- this.norm();
- e.norm();
+ sf = new FP48(this);
+ sf.norm();
+ e1 = new ctx.BIG(e);
+ e1.norm();
- e3 = new ctx.BIG(e);
+ e3 = new ctx.BIG(e1);
e3.pmul(3);
e3.norm();
- w = new FP48(this);
+ w = new FP48(sf); //w.copy(this);
nb = e3.nbits();
for (i = nb - 2; i >= 1; i--) {
w.usqr();
- bt = e3.bit(i) - e.bit(i);
+ bt = e3.bit(i) - e1.bit(i);
if (bt == 1) {
- w.mul(this);
+ w.mul(sf);
}
if (bt == -1) {
- this.conj();
- w.mul(this);
- this.conj();
+ sf.conj();
+ w.mul(sf);
+ sf.conj();
}
}
w.reduce();
@@ -799,7 +1052,7 @@ var FP48 = function(ctx) {
t[i] = w[i + ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 2 * ctx.BIG.MODBYTES];
@@ -809,9 +1062,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 3 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 4 * ctx.BIG.MODBYTES];
@@ -821,7 +1074,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 5 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 6 * ctx.BIG.MODBYTES];
@@ -831,9 +1084,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 7 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fa = new ctx.FP8(ea,eb);
@@ -845,7 +1098,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 9 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 10 * ctx.BIG.MODBYTES];
@@ -855,9 +1108,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 11 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 12 * ctx.BIG.MODBYTES];
@@ -867,7 +1120,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 13 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 14 * ctx.BIG.MODBYTES];
@@ -877,9 +1130,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 15 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fb = new ctx.FP8(ea,eb);
@@ -893,7 +1146,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 17 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 18 * ctx.BIG.MODBYTES];
@@ -905,7 +1158,7 @@ var FP48 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 20 * ctx.BIG.MODBYTES];
@@ -915,7 +1168,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 21 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 22 * ctx.BIG.MODBYTES];
@@ -927,7 +1180,7 @@ var FP48 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fa = new ctx.FP8(ea,eb);
@@ -939,7 +1192,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 25 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 26 * ctx.BIG.MODBYTES];
@@ -951,7 +1204,7 @@ var FP48 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 28 * ctx.BIG.MODBYTES];
@@ -961,7 +1214,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 29 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 30 * ctx.BIG.MODBYTES];
@@ -973,11 +1226,11 @@ var FP48 = function(ctx) {
b = ctx.BIG.fromBytes(t);
d = new ctx.FP2(a, b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fb = new ctx.FP8(ea,eb);
- f = new ctx.FP16(fa, fb);
+ f = new ctx.FP16(fa, fb); //f.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 32 * ctx.BIG.MODBYTES];
@@ -987,7 +1240,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 33 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 34 * ctx.BIG.MODBYTES];
@@ -997,9 +1250,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 35 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 36 * ctx.BIG.MODBYTES];
@@ -1009,7 +1262,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 37 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 38 * ctx.BIG.MODBYTES];
@@ -1019,9 +1272,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 39 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fa = new ctx.FP8(ea,eb);
@@ -1033,7 +1286,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 41 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 42 * ctx.BIG.MODBYTES];
@@ -1043,9 +1296,9 @@ var FP48 = function(ctx) {
t[i] = w[i + 43 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- ea = new ctx.FP4(c, d);
+ ea = new ctx.FP4(c, d); //e.set(c,d);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 44 * ctx.BIG.MODBYTES];
@@ -1055,7 +1308,7 @@ var FP48 = function(ctx) {
t[i] = w[i + 45 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- c = new ctx.FP2(a, b);
+ c = new ctx.FP2(a, b); //c.bset(a,b);
for (i = 0; i < ctx.BIG.MODBYTES; i++) {
t[i] = w[i + 46 * ctx.BIG.MODBYTES];
@@ -1065,15 +1318,15 @@ var FP48 = function(ctx) {
t[i] = w[i + 47 * ctx.BIG.MODBYTES];
}
b = ctx.BIG.fromBytes(t);
- d = new ctx.FP2(a, b);
+ d = new ctx.FP2(a, b); //d.bset(a,b);
- eb = new ctx.FP4(c, d);
+ eb = new ctx.FP4(c, d); //e.set(c,d);
fb = new ctx.FP8(ea,eb);
- g = new ctx.FP16(fa, fb);
+ g = new ctx.FP16(fa, fb); //g.set(c,d);
- r = new FP48(e, f, g);
+ r = new FP48(e, f, g); //r.set(e,f,g);
return r;
};
@@ -1114,14 +1367,14 @@ var FP48 = function(ctx) {
t[i] = new ctx.BIG(u[i]); t[i].norm();
}
- g1[0] = new FP48(q[0]);
- g1[1] = new FP48(g1[0]); g1[1].mul(q[1]);
- g1[2] = new FP48(g1[0]); g1[2].mul(q[2]);
- g1[3] = new FP48(g1[1]); g1[3].mul(q[2]);
- g1[4] = new FP48(q[0]); g1[4].mul(q[3]);
- g1[5] = new FP48(g1[1]); g1[5].mul(q[3]);
- g1[6] = new FP48(g1[2]); g1[6].mul(q[3]);
- g1[7] = new FP48(g1[3]); g1[7].mul(q[3]);
+ g1[0] = new FP48(q[0]); // q[0]
+ g1[1] = new FP48(g1[0]); g1[1].mul(q[1]); // q[0].q[1]
+ g1[2] = new FP48(g1[0]); g1[2].mul(q[2]); // q[0].q[2]
+ g1[3] = new FP48(g1[1]); g1[3].mul(q[2]); // q[0].q[1].q[2]
+ g1[4] = new FP48(q[0]); g1[4].mul(q[3]); // q[0].q[3]
+ g1[5] = new FP48(g1[1]); g1[5].mul(q[3]); // q[0].q[1].q[3]
+ g1[6] = new FP48(g1[2]); g1[6].mul(q[3]); // q[0].q[2].q[3]
+ g1[7] = new FP48(g1[3]); g1[7].mul(q[3]); // q[0].q[1].q[2].q[3]
// Use Frobenius
fa.rcopy(ctx.ROM_FIELD.Fra);
diff --git a/src/fp8.js b/src/fp8.js
index 371d253..21aa7bd 100644
--- a/src/fp8.js
+++ b/src/fp8.js
@@ -50,7 +50,6 @@ var FP8 = function(ctx) {
/* test this==0 ? */
iszilch: function() {
- this.reduce();
return (this.a.iszilch() && this.b.iszilch());
},
@@ -123,7 +122,7 @@ var FP8 = function(ctx) {
/* this=-this */
neg: function() {
this.norm();
- var m = new ctx.FP4(this.a),
+ var m = new ctx.FP4(this.a),
t = new ctx.FP4(0);
m.add(this.b);
@@ -156,7 +155,7 @@ var FP8 = function(ctx) {
/* this-=x */
sub: function(x) {
- var m = new FP8(x);
+ var m = new FP8(x);
m.neg();
this.add(m);
},
@@ -180,9 +179,9 @@ var FP8 = function(ctx) {
/* this*=this */
sqr: function() {
- var t1 = new ctx.FP4(this.a),
- t2 = new ctx.FP4(this.b),
- t3 = new ctx.FP4(this.a);
+ var t1 = new ctx.FP4(this.a),
+ t2 = new ctx.FP4(this.b),
+ t3 = new ctx.FP4(this.a);
t3.mul(this.b);
t1.add(this.b);
@@ -211,10 +210,10 @@ var FP8 = function(ctx) {
/* this*=y */
mul: function(y) {
- var t1 = new ctx.FP4(this.a),
- t2 = new ctx.FP4(this.b),
+ var t1 = new ctx.FP4(this.a),
+ t2 = new ctx.FP4(this.b),
t3 = new ctx.FP4(0),
- t4 = new ctx.FP4(this.b);
+ t4 = new ctx.FP4(this.b);
t1.mul(y.a);
t2.mul(y.b);
@@ -230,7 +229,7 @@ var FP8 = function(ctx) {
t3.copy(t1);
t3.neg();
t4.add(t3);
-
+
t3.copy(t2);
t3.neg();
this.b.copy(t4);
@@ -252,8 +251,8 @@ var FP8 = function(ctx) {
inverse: function() {
this.norm();
- var t1 = new ctx.FP4(this.a),
- t2 = new ctx.FP4(this.b);
+ var t1 = new ctx.FP4(this.a),
+ t2 = new ctx.FP4(this.b);
t1.sqr();
t2.sqr();
@@ -295,14 +294,12 @@ var FP8 = function(ctx) {
/* this=this^e */
pow: function(e) {
- this.norm();
- e.norm();
-
- var w = new FP8(this),
- z = new ctx.BIG(e),
+ var w = new FP8(this),
+ z = new ctx.BIG(e),
r = new FP8(1),
bt;
-
+ w.norm();
+ z.norm();
for (;;) {
bt = z.parity();
z.fshr(1);
@@ -324,8 +321,8 @@ var FP8 = function(ctx) {
/* XTR xtr_a function */
xtr_A: function(w, y, z) {
- var r = new FP8(w),
- t = new FP8(w);
+ var r = new FP8(w),
+ t = new FP8(w);
r.sub(y);
r.norm();
@@ -344,29 +341,31 @@ var FP8 = function(ctx) {
/* XTR xtr_d function */
xtr_D: function() {
- var w = new FP8(this);
+ var w = new FP8(this); //w.copy(this);
this.sqr();
w.conj();
- w.add(w);
+ w.add(w);
this.sub(w);
this.reduce();
},
/* r=x^n using XTR method on traces of FP12s */
xtr_pow: function(n) {
+ var sf = new FP8(this);
+ sf.norm();
var a = new FP8(3),
- b = new FP8(this),
+ b = new FP8(sf),
c = new FP8(b),
t = new FP8(0),
r = new FP8(0),
par, v, nb, i;
-
+
c.xtr_D();
- n.norm();
+
par = n.parity();
v = new ctx.BIG(n);
-
+ v.norm();
v.fshr(1);
if (par === 0) {
@@ -378,10 +377,10 @@ var FP8 = function(ctx) {
for (i = nb - 1; i >= 0; i--) {
if (v.bit(i) != 1) {
t.copy(b);
- this.conj();
+ sf.conj();
c.conj();
- b.xtr_A(a, this, c);
- this.conj();
+ b.xtr_A(a, sf, c);
+ sf.conj();
c.copy(t);
c.xtr_D();
a.xtr_D();
@@ -390,7 +389,7 @@ var FP8 = function(ctx) {
t.conj();
a.copy(b);
a.xtr_D();
- b.xtr_A(c, this, t);
+ b.xtr_A(c, sf, t);
c.xtr_D();
}
}
@@ -407,21 +406,22 @@ var FP8 = function(ctx) {
/* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
xtr_pow2: function(ck, ckml, ckm2l, a, b) {
- a.norm();
- b.norm();
- var e = new ctx.BIG(a),
- d = new ctx.BIG(b),
+ var e = new ctx.BIG(a),
+ d = new ctx.BIG(b),
w = new ctx.BIG(0),
- cu = new FP8(ck),
- cv = new FP8(this),
- cumv = new FP8(ckml),
- cum2v = new FP8(ckm2l),
+ cu = new FP8(ck),
+ cv = new FP8(this),
+ cumv = new FP8(ckml),
+ cum2v = new FP8(ckm2l),
r = new FP8(0),
t = new FP8(0),
f2 = 0,
i;
+ e.norm();
+ d.norm();
+
while (d.parity() === 0 && e.parity() === 0) {
d.fshr(1);
e.fshr(1);
diff --git a/src/gcm.js b/src/gcm.js
index 1e67c71..0591972 100644
--- a/src/gcm.js
+++ b/src/gcm.js
@@ -41,9 +41,8 @@ var GCM = function(ctx) {
var GCM = function() {
this.table = new Array(128);
- /* 2k bytes */
for (var i = 0; i < 128; i++) {
- this.table[i] = new Array(4);
+ this.table[i] = new Array(4); /* 2k bytes */
}
this.stateX = [];
this.Y_0 = [];
@@ -83,14 +82,12 @@ var GCM = function(ctx) {
}
if (c !== 0) {
- /* irreducible polynomial */
- this.table[i][0] ^= 0xE1000000;
+ this.table[i][0] ^= 0xE1000000; /* irreducible polynomial */
}
}
},
- /* gf2m mul - Z=H*X mod 2^128 */
- gf2mul: function() {
+ gf2mul: function() { /* gf2m mul - Z=H*X mod 2^128 */
var P = [],
b = [],
i, j, m, k, c;
@@ -124,8 +121,7 @@ var GCM = function(ctx) {
}
},
- /* Finish off GHASH */
- wrap: function() {
+ wrap: function() { /* Finish off GHASH */
var F = [],
L = [],
b = [],
@@ -153,8 +149,7 @@ var GCM = function(ctx) {
},
/* Initialize GCM mode */
- /* iv size niv is usually 12 bytes (96 bits). ctx.AES key size nk can be 16,24 or 32 bytes */
- init: function(nk, key, niv, iv) {
+ init: function(nk, key, niv, iv) { /* iv size niv is usually 12 bytes (96 bits). ctx.AES key size nk can be 16,24 or 32 bytes */
var H = [],
b = [],
i;
@@ -165,13 +160,11 @@ var GCM = function(ctx) {
}
this.a.init(ctx.AES.ECB, nk, key, iv);
- /* E(K,0) */
- this.a.ecb_encrypt(H);
+ this.a.ecb_encrypt(H); /* E(K,0) */
this.precompute(H);
this.lenA[0] = this.lenC[0] = this.lenA[1] = this.lenC[1] = 0;
- /* initialize IV */
if (niv == 12) {
for (i = 0; i < 12; i++) {
this.a.f[i] = iv[i];
@@ -181,15 +174,14 @@ var GCM = function(ctx) {
this.a.f[12] = b[0];
this.a.f[13] = b[1];
this.a.f[14] = b[2];
- this.a.f[15] = b[3];
+ this.a.f[15] = b[3]; /* initialise IV */
for (i = 0; i < 16; i++) {
this.Y_0[i] = this.a.f[i];
}
} else {
this.status = GCM.ACCEPTING_CIPHER;
- /* GHASH(H,0,IV) */
- this.ghash(iv, niv);
+ this.ghash(iv, niv); /* GHASH(H,0,IV) */
this.wrap();
for (i = 0; i < 16; i++) {
@@ -205,8 +197,7 @@ var GCM = function(ctx) {
},
/* Add Header data - included but not encrypted */
- /* len is length of header */
- add_header: function(header, len) {
+ add_header: function(header, len) { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
var i, j = 0;
if (this.status != GCM.ACCEPTING_HEADER) {
@@ -281,7 +272,6 @@ var GCM = function(ctx) {
}
while (j < len) {
- /* increment counter */
b[0] = this.a.f[12];
b[1] = this.a.f[13];
b[2] = this.a.f[14];
@@ -292,14 +282,13 @@ var GCM = function(ctx) {
this.a.f[12] = b[0];
this.a.f[13] = b[1];
this.a.f[14] = b[2];
- this.a.f[15] = b[3];
+ this.a.f[15] = b[3]; /* increment counter */
for (i = 0; i < 16; i++) {
B[i] = this.a.f[i];
}
- /* encrypt it */
- this.a.ecb_encrypt(B);
+ this.a.ecb_encrypt(B); /* encrypt it */
for (i = 0; i < 16 && j < len; i++) {
cipher[j] = (plain[j] ^ B[i]);
@@ -339,7 +328,6 @@ var GCM = function(ctx) {
}
while (j < len) {
- /* increment counter */
b[0] = this.a.f[12];
b[1] = this.a.f[13];
b[2] = this.a.f[14];
@@ -350,14 +338,13 @@ var GCM = function(ctx) {
this.a.f[12] = b[0];
this.a.f[13] = b[1];
this.a.f[14] = b[2];
- this.a.f[15] = b[3];
+ this.a.f[15] = b[3]; /* increment counter */
for (i = 0; i < 16; i++) {
B[i] = this.a.f[i];
}
- /* encrypt it */
- this.a.ecb_encrypt(B);
+ this.a.ecb_encrypt(B); /* encrypt it */
for (i = 0; i < 16 && j < len; i++) {
oc = cipher[j];
@@ -383,15 +370,14 @@ var GCM = function(ctx) {
},
/* Finish and extract Tag */
- finish: function(extract) {
+ finish: function(extract) { /* Finish off GHASH and extract tag (MAC) */
var tag = [],
i;
this.wrap();
/* extract tag */
if (extract) {
- /* E(K,Y0) */
- this.a.ecb_encrypt(this.Y_0);
+ this.a.ecb_encrypt(this.Y_0); /* E(K,Y0) */
for (i = 0; i < 16; i++) {
this.Y_0[i] ^= this.stateX[i];
@@ -411,13 +397,11 @@ var GCM = function(ctx) {
};
- /* pack 4 bytes into a 32-bit Word */
- GCM.pack = function(b) {
+ GCM.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
return (((b[0]) & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff);
};
- /* unpack bytes from a word */
- GCM.unpack = function(a) {
+ GCM.unpack = function(a) { /* unpack bytes from a word */
var b = [];
b[3] = (a & 0xff);
diff --git a/src/hash256.js b/src/hash256.js
index f08016c..99b36f2 100644
--- a/src/hash256.js
+++ b/src/hash256.js
@@ -28,9 +28,7 @@ var HASH256 = function() {
};
HASH256.prototype = {
-
- /* basic transformation step */
- transform: function() {
+ transform: function() { /* basic transformation step */
var a, b, c, d, e, f, g, hh, t1, t2, j;
for (j = 16; j < 64; j++) {
@@ -46,8 +44,7 @@ var HASH256 = function() {
g = this.h[6];
hh = this.h[7];
- /* 64 times - mush it up */
- for (j = 0; j < 64; j++) {
+ for (j = 0; j < 64; j++) { /* 64 times - mush it up */
t1 = (hh + HASH256.Sig1(e) + HASH256.Ch(e, f, g) + HASH256.HK[j] + this.w[j]) | 0;
t2 = (HASH256.Sig0(a) + HASH256.Maj(a, b, c)) | 0;
hh = g;
@@ -71,8 +68,8 @@ var HASH256 = function() {
},
- /* Initialize Hash function */
- init: function() {
+ /* Initialise Hash function */
+ init: function() { /* initialise */
var i;
for (i = 0; i < 64; i++) {
@@ -90,7 +87,7 @@ var HASH256 = function() {
},
/* process a single byte */
- process: function(byt) {
+ process: function(byt) { /* process the next message byte */
var cnt;
cnt = (this.length[0] >>> 5) % 16;
@@ -123,8 +120,7 @@ var HASH256 = function() {
this.process(n & 0xff);
},
- /* pad message and finish - supply digest */
- hash: function() {
+ hash: function() { /* pad message and finish - supply digest */
var digest = [],
len0, len1, i;
@@ -140,8 +136,7 @@ var HASH256 = function() {
this.w[15] = len0;
this.transform();
- /* convert to bytes */
- for (i = 0; i < HASH256.len; i++) {
+ for (i = 0; i < HASH256.len; i++) { /* convert to bytes */
digest[i] = ((this.h[i >>> 2] >> (8 * (3 - i % 4))) & 0xff);
}
this.init();
diff --git a/src/hash384.js b/src/hash384.js
index 95c2c3e..9c2941d 100644
--- a/src/hash384.js
+++ b/src/hash384.js
@@ -28,9 +28,7 @@ var HASH384 = function(ctx) {
};
HASH384.prototype = {
-
- /* basic transformation step */
- transform: function() {
+ transform: function() { /* basic transformation step */
var a, b, c, d, e, f, g, hh, t1, t2, j;
for (j = 16; j < 80; j++) {
@@ -46,8 +44,7 @@ var HASH384 = function(ctx) {
g = this.h[6].copy();
hh = this.h[7].copy();
- /* 80 times - mush it up */
- for (j = 0; j < 80; j++) {
+ for (j = 0; j < 80; j++) { /* 80 times - mush it up */
t1 = hh.copy();
t1.add(HASH384.Sig1(e)).add(HASH384.Ch(e, f, g)).add(HASH384.HK[j]).add(this.w[j]);
@@ -76,8 +73,8 @@ var HASH384 = function(ctx) {
this.h[7].add(hh);
},
- /* Initialize Hash function */
- init: function() {
+ /* Initialise Hash function */
+ init: function() { /* initialise */
var i;
for (i = 0; i < 80; i++) {
@@ -96,7 +93,7 @@ var HASH384 = function(ctx) {
},
/* process a single byte */
- process: function(byt) {
+ process: function(byt) { /* process the next message byte */
var cnt, e;
cnt = (this.length[0].bot >>> 6) % 16;
@@ -131,8 +128,7 @@ var HASH384 = function(ctx) {
this.process(n & 0xff);
},
- /* pad message and finish - supply digest */
- hash: function() {
+ hash: function() { /* pad message and finish - supply digest */
var digest = [],
len0, len1,
i;
@@ -148,8 +144,7 @@ var HASH384 = function(ctx) {
this.w[15] = len0;
this.transform();
- /* convert to bytes */
- for (i = 0; i < HASH384.len; i++) {
+ for (i = 0; i < HASH384.len; i++) { /* convert to bytes */
digest[i] = HASH384.R(8 * (7 - i % 8), this.h[i >>> 3]).bot & 0xff;
}
diff --git a/src/hash512.js b/src/hash512.js
index 39d58fa..eb468a6 100644
--- a/src/hash512.js
+++ b/src/hash512.js
@@ -29,8 +29,7 @@ var HASH512 = function(ctx) {
HASH512.prototype = {
- /* basic transformation step */
- transform: function() {
+ transform: function() { /* basic transformation step */
var a, b, c, d, e, f, g, hh, t1, t2, j;
for (j = 16; j < 80; j++) {
@@ -46,8 +45,7 @@ var HASH512 = function(ctx) {
g = this.h[6].copy();
hh = this.h[7].copy();
- /* 80 times - mush it up */
- for (j = 0; j < 80; j++) {
+ for (j = 0; j < 80; j++) { /* 80 times - mush it up */
t1 = hh.copy();
t1.add(HASH512.Sig1(e)).add(HASH512.Ch(e, f, g)).add(HASH512.HK[j]).add(this.w[j]);
@@ -76,8 +74,8 @@ var HASH512 = function(ctx) {
this.h[7].add(hh);
},
- /* Initialize Hash function */
- init: function() {
+ /* Initialise Hash function */
+ init: function() { /* initialise */
var i;
for (i = 0; i < 80; i++) {
@@ -97,7 +95,7 @@ var HASH512 = function(ctx) {
},
/* process a single byte */
- process: function(byt) {
+ process: function(byt) { /* process the next message byte */
var cnt, e;
cnt = (this.length[0].bot >>> 6) % 16;
@@ -132,8 +130,7 @@ var HASH512 = function(ctx) {
this.process(n & 0xff);
},
- /* pad message and finish - supply digest */
- hash: function() {
+ hash: function() { /* pad message and finish - supply digest */
var digest = [],
len0, len1, i;
@@ -149,8 +146,7 @@ var HASH512 = function(ctx) {
this.w[15] = len0;
this.transform();
- /* convert to bytes */
- for (i = 0; i < HASH512.len; i++) {
+ for (i = 0; i < HASH512.len; i++) { /* convert to bytes */
digest[i] = HASH512.R(8 * (7 - i % 8), this.h[i >>> 3]).bot & 0xff;
}
diff --git a/src/mpin.js b/src/mpin.js
index f439773..8988cc5 100644
--- a/src/mpin.js
+++ b/src/mpin.js
@@ -223,7 +223,7 @@ var MPIN = function(ctx) {
u.dec(1);
u.norm();
r++;
- R.setxi(u, s);
+ R.setxi(u, s);
if (!R.is_infinity()) {
break;
}
@@ -336,7 +336,7 @@ var MPIN = function(ctx) {
P.add(Q);
- P.toBytes(R);
+ P.toBytes(R,false);
return 0;
},
@@ -395,7 +395,7 @@ var MPIN = function(ctx) {
R = R.pinmul(factor, facbits);
P.sub(R);
- P.toBytes(TOKEN);
+ P.toBytes(TOKEN,false);
return 0;
},
@@ -416,7 +416,7 @@ var MPIN = function(ctx) {
R = R.pinmul(factor, facbits);
P.add(R);
- P.toBytes(TOKEN);
+ P.toBytes(TOKEN,false);
return 0;
},
@@ -462,7 +462,7 @@ var MPIN = function(ctx) {
P = ctx.ECP.mapit(G);
}
- ctx.PAIR.G1mul(P, x).toBytes(W);
+ ctx.PAIR.G1mul(P, x).toBytes(W,false);
return 0;
},
@@ -480,7 +480,7 @@ var MPIN = function(ctx) {
s = ctx.BIG.fromBytes(S);
P = ctx.PAIR.G1mul(P, s);
- P.toBytes(CTT);
+ P.toBytes(CTT,false);
return 0;
},
@@ -491,8 +491,6 @@ var MPIN = function(ctx) {
x, P, T, W, h;
r.rcopy(ctx.ROM_CURVE.CURVE_Order);
-
- // var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
if (rng !== null) {
x = ctx.BIG.randomnum(r, rng);
x.toBytes(X);
@@ -524,7 +522,7 @@ var MPIN = function(ctx) {
if (xID != null) {
P = ctx.PAIR.G1mul(P, x);
- P.toBytes(xID);
+ P.toBytes(xID,false);
W = ctx.PAIR.G1mul(W, x);
P.add(W);
} else {
@@ -533,16 +531,16 @@ var MPIN = function(ctx) {
}
if (xCID != null) {
- P.toBytes(xCID);
+ P.toBytes(xCID,false);
}
} else {
if (xID != null) {
P = ctx.PAIR.G1mul(P, x);
- P.toBytes(xID);
+ P.toBytes(xID,false);
}
}
- T.toBytes(SEC);
+ T.toBytes(SEC,false);
return 0;
},
@@ -566,8 +564,7 @@ var MPIN = function(ctx) {
P = ctx.PAIR.G1mul(P, px);
P.neg();
- P.toBytes(SEC);
-
+ P.toBytes(SEC,false);
return 0;
},
@@ -577,12 +574,12 @@ var MPIN = function(ctx) {
P = ctx.ECP.mapit(h),
R;
- P.toBytes(HID);
+ P.toBytes(HID,false);
if (date !== 0) {
h = this.hashit(sha, date, h);
R = ctx.ECP.mapit(h);
P.add(R);
- P.toBytes(HTID);
+ P.toBytes(HTID,false);
}
},
@@ -635,7 +632,6 @@ var MPIN = function(ctx) {
P = ctx.PAIR.G1mul(P, y);
P.add(R);
- P.affine();
R = ctx.ECP.fromBytes(mSEC);
if (R.is_infinity()) {
return this.INVALID_POINT;
@@ -661,7 +657,6 @@ var MPIN = function(ctx) {
P = ctx.PAIR.G1mul(P, y);
P.add(R);
- P.affine();
}
g = ctx.PAIR.ate(Q, P);
g = ctx.PAIR.fexp(g);
@@ -671,7 +666,6 @@ var MPIN = function(ctx) {
return this.BAD_PIN;
}
-
return 0;
},
@@ -960,7 +954,7 @@ var MPIN = function(ctx) {
h = ctx.BIG.fromBytes(H);
A = ctx.PAIR.G1mul(A, h);
R.add(A);
- R.affine();
+ //R.affine();
U = ctx.PAIR.G1mul(U, w);
g = ctx.PAIR.ate(sQ, R);
diff --git a/src/mpin192.js b/src/mpin192.js
index a6b0e06..c198a46 100644
--- a/src/mpin192.js
+++ b/src/mpin192.js
@@ -129,6 +129,7 @@ var MPIN192 = function(ctx) {
t[i] = w[i - 7 * this.EFS];
}
+
U.getX().toBytes(w);
for (i = 8 * this.EFS; i < 9 * this.EFS; i++) {
t[i] = w[i - 8 * this.EFS];
@@ -240,7 +241,7 @@ var MPIN192 = function(ctx) {
u.dec(1);
u.norm();
r++;
- R.setxi(u, s);
+ R.setxi(u, s);
if (!R.is_infinity()) {
break;
}
@@ -508,8 +509,6 @@ var MPIN192 = function(ctx) {
x, P, T, W, h;
r.rcopy(ctx.ROM_CURVE.CURVE_Order);
-
- // var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
if (rng !== null) {
x = ctx.BIG.randomnum(r, rng);
x.toBytes(X);
@@ -652,7 +651,7 @@ var MPIN192 = function(ctx) {
P = ctx.PAIR192.G1mul(P, y);
P.add(R);
- P.affine();
+ //P.affine();
R = ctx.ECP.fromBytes(mSEC);
if (R.is_infinity()) {
return this.INVALID_POINT;
@@ -678,7 +677,6 @@ var MPIN192 = function(ctx) {
P = ctx.PAIR192.G1mul(P, y);
P.add(R);
- P.affine();
}
g = ctx.PAIR192.ate(Q, P);
g = ctx.PAIR192.fexp(g);
@@ -977,7 +975,6 @@ var MPIN192 = function(ctx) {
h = ctx.BIG.fromBytes(H);
A = ctx.PAIR192.G1mul(A, h);
R.add(A);
- R.affine();
U = ctx.PAIR192.G1mul(U, w);
g = ctx.PAIR192.ate(sQ, R);
diff --git a/src/mpin256.js b/src/mpin256.js
index 15b1041..bf985f7 100644
--- a/src/mpin256.js
+++ b/src/mpin256.js
@@ -275,7 +275,7 @@ var MPIN256 = function(ctx) {
u.dec(1);
u.norm();
r++;
- R.setxi(u, s); //=new ECP(u,s);
+ R.setxi(u, s);
if (!R.is_infinity()) {
break;
}
@@ -544,7 +544,6 @@ var MPIN256 = function(ctx) {
r.rcopy(ctx.ROM_CURVE.CURVE_Order);
- // var q=new ctx.BIG(0); q.rcopy(ctx.ROM_FIELD.Modulus);
if (rng !== null) {
x = ctx.BIG.randomnum(r, rng);
x.toBytes(X);
@@ -619,7 +618,7 @@ var MPIN256 = function(ctx) {
P = ctx.PAIR256.G1mul(P, px);
P.neg();
P.toBytes(SEC,false);
-
+
return 0;
},
@@ -687,7 +686,6 @@ var MPIN256 = function(ctx) {
P = ctx.PAIR256.G1mul(P, y);
P.add(R);
- P.affine();
R = ctx.ECP.fromBytes(mSEC);
if (R.is_infinity()) {
return this.INVALID_POINT;
@@ -713,7 +711,6 @@ var MPIN256 = function(ctx) {
P = ctx.PAIR256.G1mul(P, y);
P.add(R);
- P.affine();
}
g = ctx.PAIR256.ate(Q, P);
g = ctx.PAIR256.fexp(g);
@@ -958,7 +955,6 @@ var MPIN256 = function(ctx) {
r = new ctx.BIG(0);
r.rcopy(ctx.ROM_CURVE.CURVE_Order);
-
z.add(h);
z.mod(r);
@@ -1012,7 +1008,6 @@ var MPIN256 = function(ctx) {
h = ctx.BIG.fromBytes(H);
A = ctx.PAIR256.G1mul(A, h);
R.add(A);
- R.affine();
U = ctx.PAIR256.G1mul(U, w);
g = ctx.PAIR256.ate(sQ, R);
diff --git a/src/pair.js b/src/pair.js
index 1a55e54..36e60d0 100644
--- a/src/pair.js
+++ b/src/pair.js
@@ -29,8 +29,7 @@ var PAIR = function(ctx) {
X1, Y1, T1, T2,
a, b;
- if (A == B) {
- /* Doubling */
+ if (A == B) { /* Doubling */
XX = new ctx.FP2(A.getx());
YY = new ctx.FP2(A.gety());
ZZ = new ctx.FP2(A.getz());
@@ -77,8 +76,7 @@ var PAIR = function(ctx) {
}
A.dbl();
- } else {
- /* Addition */
+ } else { /* Addition */
X1 = new ctx.FP2(A.getx()); // X1
Y1 = new ctx.FP2(A.gety()); // Y1
T1 = new ctx.FP2(A.getz()); // Z1
@@ -124,19 +122,121 @@ var PAIR = function(ctx) {
}
r.set(a, b, c);
+ r.settype(ctx.FP.SPARSER);
return r;
},
+/* prepare for multi-pairing */
+ initmp: function() {
+ var r=[];
+ for (var i=0;i<ctx.ECP.ATE_BITS;i++)
+ r[i] = new ctx.FP12(1);
+ return r;
+ },
+
+/* basic Miller loop */
+ miller: function(r) {
+ var res=new ctx.FP12(1);
+ for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ },
+
+/* Accumulate another set of line functions for n-pairing */
+ another: function(r,P1,Q1) {
+
+ var f;
+ var n=new ctx.BIG(0);
+ var n3=new ctx.BIG(0);
+ var K=new ctx.ECP2();
+ var lv,lv2;
+ var bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=new ctx.ECP2(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+ P.affine();
+ Q.affine();
+
+ if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+ {
+ var fa = new ctx.BIG(0);
+ fa.rcopy(ctx.ROM_FIELD.Fra);
+ var fb = new ctx.BIG(0);
+ fb.rcopy(ctx.ROM_FIELD.Frb);
+ f = new ctx.FP2(fa, fb);
+ if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.M_TYPE)
+ {
+ f.inverse();
+ f.norm();
+ }
+ }
+
+ var Qx=new ctx.FP(Q.getx());
+ var Qy=new ctx.FP(Q.gety());
+
+ var A=new ctx.ECP2();
+ A.copy(P);
+
+ var MP=new ctx.ECP2();
+ MP.copy(P); MP.neg();
+
+ var nb=PAIR.lbits(n3,n);
+
+ for (var i=nb-2;i>=1;i--)
+ {
+ lv=PAIR.line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
+ {
+ lv2=PAIR.line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=PAIR.line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+
+/* R-ate fixup required for BN curves */
+ if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+ {
+ if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX)
+ {
+ A.neg();
+ }
+ K.copy(P);
+ K.frob(f);
+ lv=PAIR.line(A,K,Qx,Qy);
+ K.frob(f);
+ K.neg();
+ lv2=PAIR.line(A,K,Qx,Qy);
+ lv.smul(lv2);
+ r[0].ssmul(lv);
+ }
+ },
+
/* Optimal R-ate pairing */
- ate: function(P, Q) {
- var fa, fb, f, x, n, n3, K, lv,
- Qx, Qy, A, r, nb, bt,
+ ate: function(P1, Q1) {
+ var fa, fb, f, x, n, n3, K, lv, lv2,
+ Qx, Qy, A, NP, r, nb, bt,
i;
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
- n = new ctx.BIG(x);
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
K = new ctx.ECP2();
if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
@@ -145,55 +245,44 @@ var PAIR = function(ctx) {
fa.rcopy(ctx.ROM_FIELD.Fra);
fb = new ctx.BIG(0);
fb.rcopy(ctx.ROM_FIELD.Frb);
- f = new ctx.FP2(fa, fb);
+ f = new ctx.FP2(fa, fb);
if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
f.inverse();
f.norm();
}
-
- n.pmul(6);
- if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
- n.inc(2);
- } else {
- n.dec(2);
- }
- } else {
- n.copy(x);
}
- n.norm();
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ var P=new ctx.ECP2(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
- Qx = new ctx.FP(Q.getx());
- Qy = new ctx.FP(Q.gety());
+ Qx = new ctx.FP(Q.getx());
+ Qy = new ctx.FP(Q.gety());
A = new ctx.ECP2();
r = new ctx.FP12(1);
-
A.copy(P);
- nb = n3.nbits();
+
+ NP = new ctx.ECP2();
+ NP.copy(P);
+ NP.neg();
+
+ nb = PAIR.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR.line(A, A, Qx, Qy);
-
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
-
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
- lv = PAIR.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(A, P, Qx, Qy);
+ lv.smul(lv2);
}
if (bt == -1) {
- P.neg();
- lv = PAIR.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
+ lv2 = PAIR.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -210,27 +299,25 @@ var PAIR = function(ctx) {
K.frob(f);
lv = PAIR.line(A, K, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv = PAIR.line(A, K, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(A, K, Qx, Qy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
return r;
},
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
- ate2: function(P, Q, R, S) {
- var fa, fb, f, x, n, n3, K, lv,
- Qx, Qy, Sx, Sy, A, B, r, nb, bt,
+
+ ate2: function(P1, Q1, R1, S1) {
+ var fa, fb, f, x, n, n3, K, lv, lv2,
+ Qx, Qy, Sx, Sy, A, B, NP,NR,r, nb, bt,
i;
-
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
-
- n = new ctx.BIG(x);
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
K = new ctx.ECP2();
if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
@@ -244,27 +331,19 @@ var PAIR = function(ctx) {
f.inverse();
f.norm();
}
+ }
- n.pmul(6);
- if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
- n.inc(2);
- } else {
- n.dec(2);
- }
- } else {
- n.copy(x);
- }
- n.norm();
+ var P=new ctx.ECP2(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+ var R=new ctx.ECP2(); R.copy(R1); R.affine();
+ var S=new ctx.ECP(); S.copy(S1); S.affine();
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
- Qx = new ctx.FP(Q.getx());
- Qy = new ctx.FP(Q.gety());
+ Qx = new ctx.FP(Q.getx());
+ Qy = new ctx.FP(Q.gety());
- Sx = new ctx.FP(S.getx());
- Sy = new ctx.FP(S.gety());
+ Sx = new ctx.FP(S.getx());
+ Sy = new ctx.FP(S.gety());
A = new ctx.ECP2();
B = new ctx.ECP2();
@@ -272,32 +351,36 @@ var PAIR = function(ctx) {
A.copy(P);
B.copy(R);
- nb = n3.nbits();
+
+ NP = new ctx.ECP2();
+ NP.copy(P);
+ NP.neg();
+ NR = new ctx.ECP2();
+ NR.copy(R);
+ NR.neg();
+
+ nb = PAIR.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR.line(A, A, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR.line(B, B, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(B, B, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
lv = PAIR.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(B, R, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt == -1) {
- P.neg();
- lv = PAIR.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
- R.neg();
- lv = PAIR.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- R.neg();
+ lv = PAIR.line(A, NP, Qx, Qy);
+ lv2 = PAIR.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -306,7 +389,7 @@ var PAIR = function(ctx) {
}
- /* R-ate fixup required for BN curves */
+ // R-ate fixup required for BN curves
if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
A.neg();
@@ -316,21 +399,21 @@ var PAIR = function(ctx) {
K.frob(f);
lv = PAIR.line(A, K, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv = PAIR.line(A, K, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(A, K, Qx, Qy);
+ lv.smul(lv2);
+ r.ssmul(lv);
K.copy(R);
K.frob(f);
lv = PAIR.line(B, K, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv = PAIR.line(B, K, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(B, K, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
return r;
@@ -361,17 +444,21 @@ var PAIR = function(ctx) {
r.frob(f);
r.frob(f);
r.mul(lv);
-
+ if (r.isunity())
+ {
+ r.zero();
+ return r;
+ }
/* Hard part of final exp */
if (ctx.ECP.CURVE_PAIRING_TYPE == ctx.ECP.BN) {
lv.copy(r);
lv.frob(f);
- x0 = new ctx.FP12(lv);
+ x0 = new ctx.FP12(lv); //x0.copy(lv);
x0.frob(f);
lv.mul(r);
x0.mul(lv);
x0.frob(f);
- x1 = new ctx.FP12(r);
+ x1 = new ctx.FP12(r); //x1.copy(r);
x1.conj();
x4 = r.pow(x);
@@ -379,13 +466,13 @@ var PAIR = function(ctx) {
x4.conj();
}
- x3 = new ctx.FP12(x4);
+ x3 = new ctx.FP12(x4); //x3.copy(x4);
x3.frob(f);
x2 = x4.pow(x);
if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
x2.conj();
}
- x5 = new ctx.FP12(x2);
+ x5 = new ctx.FP12(x2); /*x5.copy(x2);*/
x5.conj();
lv = x2.pow(x);
if (ctx.ECP.SIGN_OF_X == ctx.ECP.POSITIVEX) {
@@ -478,6 +565,28 @@ var PAIR = function(ctx) {
}
};
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ PAIR.lbits = function(n3,n)
+ {
+ n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+ if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
+ {
+ n.pmul(6);
+ if (ctx.ECP.SIGN_OF_X==ctx.ECP.POSITIVEX)
+ {
+ n.inc(2);
+ } else {
+ n.dec(2);
+ }
+ }
+
+ n.norm();
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ },
+
/* GLV method */
PAIR.glv = function(e) {
var u = [],
@@ -508,8 +617,7 @@ var PAIR = function(ctx) {
u[i].mod(q);
}
}
- } else {
- // -(x^2).P = (Beta.x,y)
+ } else { // -(x^2).P = (Beta.x,y)
q = new ctx.BIG(0);
q.rcopy(ctx.ROM_CURVE.CURVE_Order);
x = new ctx.BIG(0);
@@ -583,11 +691,10 @@ var PAIR = function(ctx) {
var R, Q, q, bcru, cru, t, u, np, nn;
if (ctx.ROM_CURVE.USE_GLV) {
- P.affine();
R = new ctx.ECP();
R.copy(P);
Q = new ctx.ECP();
- Q.copy(P);
+ Q.copy(P); Q.affine();
q = new ctx.BIG(0);
q.rcopy(ctx.ROM_CURVE.CURVE_Order);
bcru = new ctx.BIG(0);
@@ -645,7 +752,6 @@ var PAIR = function(ctx) {
u = PAIR.gs(e);
t = new ctx.BIG(0);
- P.affine();
Q[0] = new ctx.ECP2();
Q[0].copy(P);
diff --git a/src/pair192.js b/src/pair192.js
index 3439804..74e9c72 100644
--- a/src/pair192.js
+++ b/src/pair192.js
@@ -121,51 +121,121 @@ var PAIR192 = function(ctx) {
}
r.set(a, b, c);
-
+ r.settype(ctx.FP.SPARSER);
return r;
},
+/* prepare for multi-pairing */
+ initmp: function() {
+ var r=[];
+ for (var i=0;i<ctx.ECP.ATE_BITS;i++)
+ r[i] = new ctx.FP24(1);
+ return r;
+ },
+
+/* basic Miller loop */
+ miller: function(r) {
+ var res=new ctx.FP24(1);
+ for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ },
+
+/* Accumulate another set of line functions for n-pairing */
+ another: function(r,P1,Q1) {
+
+ var f;
+ var n=new ctx.BIG(0);
+ var n3=new ctx.BIG(0);
+ var lv,lv2;
+ var bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=new ctx.ECP4(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+ P.affine();
+ Q.affine();
+
+ var Qx=new ctx.FP(Q.getx());
+ var Qy=new ctx.FP(Q.gety());
+
+ var A=new ctx.ECP4();
+ A.copy(P);
+
+ var MP=new ctx.ECP4();
+ MP.copy(P); MP.neg();
+
+ var nb=PAIR192.lbits(n3,n);
+
+ for (var i=nb-2;i>=1;i--)
+ {
+ lv=PAIR192.line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
+ {
+ lv2=PAIR192.line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=PAIR192.line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+ },
+
+
/* Optimal R-ate pairing */
- ate: function(P, Q) {
- var x, n, n3, lv,
- Qx, Qy, A, r, nb, bt,
+ ate: function(P1, Q1) {
+ var x, n, n3, lv, lv2,
+ Qx, Qy, A, NP, r, nb, bt,
i;
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
- n = new ctx.BIG(x);
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ var P=new ctx.ECP4(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
- Qx = new ctx.FP(Q.getx());
- Qy = new ctx.FP(Q.gety());
+ Qx = new ctx.FP(Q.getx());
+ Qy = new ctx.FP(Q.gety());
A = new ctx.ECP4();
r = new ctx.FP24(1);
A.copy(P);
- nb = n3.nbits();
+ NP = new ctx.ECP4();
+ NP.copy(P);
+ NP.neg();
+
+
+ nb = PAIR192.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR192.line(A, A, Qx, Qy);
-
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
-
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
- lv = PAIR192.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR192.line(A, P, Qx, Qy);
+ lv.smul(lv2);
}
if (bt == -1) {
- P.neg();
- lv = PAIR192.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
+ lv2 = PAIR192.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -176,19 +246,20 @@ var PAIR192 = function(ctx) {
},
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
- ate2: function(P, Q, R, S) {
- var x, n, n3, lv,
- Qx, Qy, Sx, Sy, A, B, r, nb, bt,
+ ate2: function(P1, Q1, R1, S1) {
+ var x, n, n3, lv, lv2,
+ Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
i;
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
+
+ var P=new ctx.ECP4(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+ var R=new ctx.ECP4(); R.copy(R1); R.affine();
+ var S=new ctx.ECP(); S.copy(S1); S.affine();
- n = new ctx.BIG(x);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
Qx = new ctx.FP(Q.getx());
Qy = new ctx.FP(Q.gety());
@@ -202,32 +273,35 @@ var PAIR192 = function(ctx) {
A.copy(P);
B.copy(R);
- nb = n3.nbits();
+ NP = new ctx.ECP4();
+ NP.copy(P);
+ NP.neg();
+ NR = new ctx.ECP4();
+ NR.copy(R);
+ NR.neg();
+
+ nb = PAIR192.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR192.line(A, A, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR192.line(B, B, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR192.line(B, B, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
lv = PAIR192.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR192.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR192.line(B, R, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt == -1) {
- P.neg();
- lv = PAIR192.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
- R.neg();
- lv = PAIR192.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- R.neg();
+ lv = PAIR192.line(A, NP, Qx, Qy);
+ lv2 = PAIR192.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -251,17 +325,21 @@ var PAIR192 = function(ctx) {
x = new ctx.BIG(0);
x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
- r = new ctx.FP24(m);
+ r = new ctx.FP24(m); //r.copy(m);
/* Easy part of final exp */
- lv = new ctx.FP24(r);
+ lv = new ctx.FP24(r); //lv.copy(r);
lv.inverse();
r.conj();
r.mul(lv);
lv.copy(r);
r.frob(f,4);
r.mul(lv);
-
+ if (r.isunity())
+ {
+ r.zero();
+ return r;
+ }
/* Hard part of final exp */
// Ghamman & Fouotsa Method
t7=new ctx.FP24(r); t7.usqr();
@@ -337,6 +415,16 @@ var PAIR192 = function(ctx) {
}
};
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ PAIR192.lbits = function(n3,n)
+ {
+ n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ },
+
/* GLV method */
PAIR192.glv = function(e) {
var u = [],
@@ -391,11 +479,10 @@ var PAIR192 = function(ctx) {
var R, Q, q, bcru, cru, t, u, np, nn;
if (ctx.ROM_CURVE.USE_GLV) {
- P.affine();
R = new ctx.ECP();
R.copy(P);
Q = new ctx.ECP();
- Q.copy(P);
+ Q.copy(P); Q.affine();
q = new ctx.BIG(0);
q.rcopy(ctx.ROM_CURVE.CURVE_Order);
bcru = new ctx.BIG(0);
@@ -444,7 +531,7 @@ var PAIR192 = function(ctx) {
u = PAIR192.gs(e);
t = new ctx.BIG(0);
- P.affine();
+
Q[0] = new ctx.ECP4();
Q[0].copy(P);
diff --git a/src/pair256.js b/src/pair256.js
index f80234d..5dca245 100644
--- a/src/pair256.js
+++ b/src/pair256.js
@@ -121,51 +121,121 @@ var PAIR256 = function(ctx) {
}
r.set(a, b, c);
-
+ r.settype(ctx.FP.SPARSER);
return r;
},
+/* prepare for multi-pairing */
+ initmp: function() {
+ var r=[];
+ for (var i=0;i<ctx.ECP.ATE_BITS;i++)
+ r[i] = new ctx.FP48(1);
+ return r;
+ },
+
+/* basic Miller loop */
+ miller: function(r) {
+ var res=new ctx.FP48(1);
+ for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (ctx.ECP.SIGN_OF_X==ctx.ECP.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ },
+
+/* Accumulate another set of line functions for n-pairing */
+ another: function(r,P1,Q1) {
+
+ var f;
+ var n=new ctx.BIG(0);
+ var n3=new ctx.BIG(0);
+ var lv,lv2;
+ var bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=new ctx.ECP8(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+
+ P.affine();
+ Q.affine();
+
+ var Qx=new ctx.FP(Q.getx());
+ var Qy=new ctx.FP(Q.gety());
+
+ var A=new ctx.ECP8();
+ A.copy(P);
+
+ var MP=new ctx.ECP8();
+ MP.copy(P); MP.neg();
+
+ var nb=PAIR256.lbits(n3,n);
+
+ for (var i=nb-2;i>=1;i--)
+ {
+ lv=PAIR256.line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
+ {
+ lv2=PAIR256.line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=PAIR256.line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+ },
+
+
/* Optimal R-ate pairing */
- ate: function(P, Q) {
- var x, n, n3, lv,
- Qx, Qy, A, r, nb, bt,
+ ate: function(P1, Q1) {
+ var x, n, n3, lv, lv2,
+ Qx, Qy, A, NP, r, nb, bt,
i;
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
- n = new ctx.BIG(x);
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ var P=new ctx.ECP8(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
- Qx = new ctx.FP(Q.getx());
- Qy = new ctx.FP(Q.gety());
+ Qx = new ctx.FP(Q.getx());
+ Qy = new ctx.FP(Q.gety());
A = new ctx.ECP8();
r = new ctx.FP48(1);
A.copy(P);
- nb = n3.nbits();
+ NP = new ctx.ECP8();
+ NP.copy(P);
+ NP.neg();
+
+
+ nb = PAIR256.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR256.line(A, A, Qx, Qy);
-
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
-
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
- lv = PAIR256.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR256.line(A, P, Qx, Qy);
+ lv.smul(lv2);
}
if (bt == -1) {
- P.neg();
- lv = PAIR256.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
+ lv2 = PAIR256.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -176,25 +246,25 @@ var PAIR256 = function(ctx) {
},
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
- ate2: function(P, Q, R, S) {
- var x, n, n3, lv,
- Qx, Qy, Sx, Sy, A, B, r, nb, bt,
+ ate2: function(P1, Q1, R1, S1) {
+ var x, n, n3, lv, lv2,
+ Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
i;
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
- x = new ctx.BIG(0);
- x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+ var P=new ctx.ECP8(); P.copy(P1); P.affine();
+ var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
+ var R=new ctx.ECP8(); R.copy(R1); R.affine();
+ var S=new ctx.ECP(); S.copy(S1); S.affine();
- n = new ctx.BIG(x);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
- Qx = new ctx.FP(Q.getx());
- Qy = new ctx.FP(Q.gety());
+ Qx = new ctx.FP(Q.getx());
+ Qy = new ctx.FP(Q.gety());
- Sx = new ctx.FP(S.getx());
- Sy = new ctx.FP(S.gety());
+ Sx = new ctx.FP(S.getx());
+ Sy = new ctx.FP(S.gety());
A = new ctx.ECP8();
B = new ctx.ECP8();
@@ -202,32 +272,36 @@ var PAIR256 = function(ctx) {
A.copy(P);
B.copy(R);
- nb = n3.nbits();
+ NP = new ctx.ECP8();
+ NP.copy(P);
+ NP.neg();
+ NR = new ctx.ECP8();
+ NR.copy(R);
+ NR.neg();
+
+
+ nb = PAIR256.lbits(n3,n);
for (i = nb - 2; i >= 1; i--) {
r.sqr();
lv = PAIR256.line(A, A, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR256.line(B, B, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR256.line(B, B, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
bt=n3.bit(i)-n.bit(i);
if (bt == 1) {
lv = PAIR256.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR256.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR256.line(B, R, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt == -1) {
- P.neg();
- lv = PAIR256.line(A, P, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- P.neg();
- R.neg();
- lv = PAIR256.line(B, R, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- R.neg();
+ lv = PAIR256.line(A, NP, Qx, Qy);
+ lv2 = PAIR256.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -251,17 +325,21 @@ var PAIR256 = function(ctx) {
x = new ctx.BIG(0);
x.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
- r = new ctx.FP48(m);
+ r = new ctx.FP48(m); //r.copy(m);
/* Easy part of final exp */
- lv = new ctx.FP48(r);
+ lv = new ctx.FP48(r); //lv.copy(r);
lv.inverse();
r.conj();
r.mul(lv);
lv.copy(r);
r.frob(f,8);
r.mul(lv);
-
+ if (r.isunity())
+ {
+ r.zero();
+ return r;
+ }
/* Hard part of final exp */
// Ghamman & Fouotsa Method
t7=new ctx.FP48(r); t7.usqr();
@@ -408,6 +486,16 @@ var PAIR256 = function(ctx) {
}
};
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ PAIR256.lbits = function(n3,n)
+ {
+ n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ },
+
/* GLV method */
PAIR256.glv = function(e) {
var u = [],
@@ -468,11 +556,10 @@ var PAIR256 = function(ctx) {
var R, Q, q, bcru, cru, t, u, np, nn;
if (ctx.ROM_CURVE.USE_GLV) {
- P.affine();
R = new ctx.ECP();
R.copy(P);
Q = new ctx.ECP();
- Q.copy(P);
+ Q.copy(P); Q.affine();
q = new ctx.BIG(0);
q.rcopy(ctx.ROM_CURVE.CURVE_Order);
bcru = new ctx.BIG(0);
@@ -521,7 +608,7 @@ var PAIR256 = function(ctx) {
u = PAIR256.gs(e);
t = new ctx.BIG(0);
- P.affine();
+
Q[0] = new ctx.ECP8();
Q[0].copy(P);
diff --git a/src/rand.js b/src/rand.js
index 2b4c4fa..db110b0 100644
--- a/src/rand.js
+++ b/src/rand.js
@@ -33,14 +33,11 @@ var RAND = function(ctx) {
var RAND = function() {
/* Cryptographically strong pseudo-random number generator */
- /* random number... */
- this.ira = [];
- /* ...array & pointer */
- this.rndptr = 0;
+ this.ira = []; /* random number... */
+ this.rndptr = 0; /* ...array & pointer */
this.borrow = 0;
this.pool_ptr = 0;
- /* random pool */
- this.pool = [];
+ this.pool = []; /* random pool */
this.clean();
};
@@ -76,16 +73,14 @@ var RAND = function(ctx) {
this.rndptr = 0;
- /* calculate next NK values */
- for (i = 0, k = this.NK - this.NJ; i < this.NK; i++, k++) {
+ for (i = 0, k = this.NK - this.NJ; i < this.NK; i++, k++) { /* calculate next NK values */
if (k == this.NK) {
k = 0;
}
t = this.ira[k] >>> 0;
pdiff = (t - this.ira[i] - this.borrow) | 0;
- /* This is seriously weird stuff. I got to do this to get a proper unsigned comparison... */
- pdiff >>>= 0;
+ pdiff >>>= 0; /* This is seriously weird shit. I got to do this to get a proper unsigned comparison... */
if (pdiff < t) {
this.borrow = 0;
@@ -110,11 +105,9 @@ var RAND = function(ctx) {
seed >>>= 0;
this.ira[0] ^= seed;
- /* fill initialisation vector */
- for (i = 1; i < this.NK; i++) {
+ for (i = 1; i < this.NK; i++) { /* fill initialisation vector */
inn = (this.NV * i) % this.NK;
- /* note XOR */
- this.ira[inn] ^= m;
+ this.ira[inn] ^= m; /* note XOR */
t = m;
m = (seed - m) | 0;
seed = t;
@@ -138,8 +131,8 @@ var RAND = function(ctx) {
this.pool_ptr = 0;
},
- /* Initialize RNG with some real entropy from some external source - at least 128 byte string */
- seed: function(rawlen, raw) {
+ /* Initialize RNG with some real entropy from some external source */
+ seed: function(rawlen, raw) { /* initialise from at least 128 byte string of raw random entropy */
var sh = new ctx.HASH256(),
digest = [],
b = [],
@@ -183,8 +176,7 @@ var RAND = function(ctx) {
}
};
- /* pack 4 bytes into a 32-bit Word */
- RAND.pack = function(b) {
+ RAND.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
};
diff --git a/src/rsa.js b/src/rsa.js
index 3e4bf9d..d04ba30 100644
--- a/src/rsa.js
+++ b/src/rsa.js
@@ -119,8 +119,7 @@ RSA = function(ctx) {
return R;
},
- /* IEEE1363 A16.11/A16.12 more or less */
- KEY_PAIR: function(rng, e, PRIV, PUB) {
+ KEY_PAIR: function(rng, e, PRIV, PUB) { /* IEEE1363 A16.11/A16.12 more or less */
var n = PUB.n.length >> 1,
t = new ctx.FF(n),
p1 = new ctx.FF(n),
diff --git a/src/sha3.js b/src/sha3.js
index 5150750..345de82 100644
--- a/src/sha3.js
+++ b/src/sha3.js
@@ -106,8 +106,8 @@ var SHA3 = function(ctx) {
}
},
- /* Initialize Hash function */
- init: function(olen) {
+ /* Initialise Hash function */
+ init: function(olen) { /* initialise */
var i, j;
for (i = 0; i < 5; i++) {
this.S[i] = [];
@@ -121,15 +121,14 @@ var SHA3 = function(ctx) {
},
/* process a single byte */
- process: function(byt) {
+ process: function(byt) { /* process the next message byte */
var i, j, k, b, cnt, el;
cnt = (this.length % this.rate);
b = cnt % 8;
cnt >>= 3;
i = cnt % 5;
- /* process by columns! */
- j = Math.floor(cnt / 5);
+ j = Math.floor(cnt / 5); /* process by columns! */
el = new ctx.UInt64(0, byt);
for (k = 0; k < b; k++) {
@@ -183,36 +182,31 @@ var SHA3 = function(ctx) {
this.transform();
}
},
- /* pad message and finish - supply digest */
- hash: function(buff) {
+
+ hash: function(buff) { /* pad message and finish - supply digest */
var q = this.rate - (this.length % this.rate);
if (q == 1) {
this.process(0x86);
} else {
- /* 0x06 for SHA-3 */
- this.process(0x06);
+ this.process(0x06); /* 0x06 for SHA-3 */
while (this.length % this.rate != this.rate - 1) {
this.process(0x00);
}
- /* this will force a final transform */
- this.process(0x80);
+ this.process(0x80); /* this will force a final transform */
}
this.squeeze(buff, this.len);
},
- /* pad message and finish - supply digest */
- shake: function(buff, olen) {
+ shake: function(buff, olen) { /* pad message and finish - supply digest */
var q = this.rate - (this.length % this.rate);
if (q == 1) {
this.process(0x9f);
} else {
- /* 0x06 for SHA-3 */
- this.process(0x1f);
+ this.process(0x1f); /* 0x06 for SHA-3 */
while (this.length % this.rate != this.rate - 1) {
this.process(0x00);
}
- /* this will force a final transform */
- this.process(0x80);
+ this.process(0x80); /* this will force a final transform */
}
this.squeeze(buff, olen);
}
diff --git a/test/test_BIG.js b/test/test_BIG.js
index 1146b01..0ba368e 100644
--- a/test/test_BIG.js
+++ b/test/test_BIG.js
@@ -250,7 +250,7 @@ all_curves.forEach(function(curve){
done();
});
-
+ /*
it('test sum', function(done) {
vectors.forEach(function(vector) {
var BIG1 = readBIG(vector.BIG1,ctx),
@@ -276,7 +276,7 @@ all_curves.forEach(function(curve){
done();
});
-
+ */
it('test modulus this > m', function(done) {
vectors.forEach(function(vector) {
if(vectors.BIGmod2 !== undefined){
diff --git a/test/test_DVS.js b/test/test_DVS.js
index 2a48373..3f9eeea 100644
--- a/test/test_DVS.js
+++ b/test/test_DVS.js
@@ -23,6 +23,7 @@ var chai = require('chai');
var CTX = require("../index");
+// Curves for test
pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];
var expect = chai.expect;
@@ -38,7 +39,7 @@ pf_curves.forEach(function(curve) {
MPIN, EGS, EFS, G1S, G2S,
pin = 1234,
pin2 = 2345,
- IDstr = "testuser@miracl.com",
+ IDstr = "testuser@milagro.com",
message = "Message to sign",
S = [],
SST = [],
@@ -134,4 +135,4 @@ pf_curves.forEach(function(curve) {
done();
});
});
-});
\ No newline at end of file
+});
diff --git a/test/test_FP12_js b/test/test_FP12_js
new file mode 100644
index 0000000..49ea61c
--- /dev/null
+++ b/test/test_FP12_js
@@ -0,0 +1,206 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+/* Test FP12 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN'];
+
+var readBIG = function(string, ctx) {
+ while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+ return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP2 = function(string, ctx) {
+ string = string.split(",");
+ var cox = string[0].slice(1);
+ var coy = string[1].slice(0,-1);
+
+ var x = readBIG(cox,ctx);
+ var y = readBIG(coy,ctx);
+
+ return new ctx.FP2(x,y);;
+}
+
+var readFP4 = function(string, ctx) {
+ var X, Y;
+
+ string = string.split("],[");
+ var cox = string[0].slice(1) + "]";
+ var coy = "[" + string[1].slice(0,-1);
+
+ X = readFP2(cox,ctx);
+ Y = readFP2(coy,ctx);
+
+ return new ctx.FP4(X,Y);
+}
+
+var readFP12= function(string, ctx) {
+ var X,Y,Z;
+
+ string = string.split("]],[[");
+ var cox = string[0].slice(1) + "]]";
+ var coy = "[[" + string[1] + "]]";
+ var coz = "[[" + string[2].slice(0,-1);
+
+ X = readFP4(cox,ctx);
+ Y = readFP4(coy,ctx);
+ Z = readFP4(coz,ctx);
+
+ return new ctx.FP12(X,Y,Z);
+}
+
+describe('TEST FP12 ARITHMETIC', function() {
+
+ pf_curves.forEach(function(curve){
+
+ it('test '+ curve, function(done) {
+ this.timeout(0);
+
+ var ctx = new CTX(curve);
+ var vectors = require('../testVectors/fp12/'+ curve +'.json');
+
+ var Fra = new ctx.FP(0),
+ Frb = new ctx.FP(0),
+ Fr;
+ Fra.rcopy(ctx.ROM_FIELD.Fra);
+ Frb.rcopy(ctx.ROM_FIELD.Frb);
+ Fr = new ctx.FP2(Fra,Frb);
+
+ var i = 0;
+ vectors.forEach(function(vector) {
+ // Generate/read the necessary FP12 and BIGs
+ var fp121,fp122,fp123,fp124,fp12c;
+ fp121 = readFP12(vector.FP121, ctx);
+ fp122 = readFP12(vector.FP122, ctx);
+ if (i===0){
+ fp123 = readFP12(vector.FP123, ctx);
+ fp124 = readFP12(vector.FP124, ctx);
+ }
+ fp12c = readFP12(vector.FP12c, ctx);
+ var BIGsc1,BIGsc2,BIGsc3,BIGsc4,BIGscs,BIGsco;
+ BIGsc1 = readBIG(vector.BIGsc1, ctx);
+ if (i===0){
+ BIGsc2 = readBIG(vector.BIGsc2, ctx);
+ BIGsc3 = readBIG(vector.BIGsc3, ctx);
+ BIGsc4 = readBIG(vector.BIGsc4, ctx);
+ }
+ BIGscs = readBIG(vector.BIGscs, ctx);
+ BIGsco = readBIG(vector.BIGsco, ctx);
+ var a1 = new ctx.FP12(0);
+ var a2 = new ctx.FP12(0);
+
+ // test conjugate of a FP4
+ var fp12conj = readFP12(vector.FP12conj, ctx);
+ a1.copy(fp121);
+ a1.conj();
+ expect(a1.toString()).to.equal(fp12conj.toString());
+
+ // test multiplication and commutativity
+ var fp12mul = readFP12(vector.FP12mul, ctx);
+ a1.copy(fp121);
+ a2.copy(fp122);
+ a1.mul(fp122);
+ a2.mul(fp121);
+ expect(a1.toString()).to.equal(fp12mul.toString());
+ expect(a2.toString()).to.equal(fp12mul.toString());
+
+ // test square
+ var fp12sqr = readFP12(vector.FP12square, ctx);
+ a1.copy(fp121);
+ a1.sqr();
+ expect(a1.toString()).to.equal(fp12sqr.toString());
+
+ // test unitary square
+ var fp12usqr = readFP12(vector.FP12usquare, ctx);
+ a1.copy(fp121);
+ a1.usqr();
+ expect(a1.toString()).to.equal(fp12usqr.toString());
+
+ // test inverse
+ var fp12inv = readFP12(vector.FP12inv, ctx);
+ a1.copy(fp121);
+ a1.inverse();
+ expect(a1.toString()).to.equal(fp12inv.toString());
+
+ // test smultiplication for D-TYPE
+ var fp12smulydtype = readFP12(vector.FP12smulydtype,ctx);
+ var fp12smuldtype = readFP12(vector.FP12smuldtype,ctx);
+ a1.copy(fp121);
+ a1.smul(fp12smulydtype, ctx.ECP.D_TYPE);
+ expect(a1.toString()).to.equal(fp12smuldtype.toString());
+
+ // test smultiplication for M-TYPE
+ var fp12smulymtype = readFP12(vector.FP12smulymtype,ctx);
+ var fp12smulmtype = readFP12(vector.FP12smulmtype,ctx);
+ a1.copy(fp121);
+ a1.smul(fp12smulymtype, ctx.ECP.M_TYPE);
+ expect(a1.toString()).to.equal(fp12smulmtype.toString());
+
+ // test power
+ var fp12pow = readFP12(vector.FP12pow, ctx);
+ a1 = fp121.pow(BIGsc1);
+ expect(a1.toString()).to.equal(fp12pow.toString());
+
+ // test power by small integer
+ var fp12pinpow = readFP12(vector.FP12pinpow, ctx);
+ a1.copy(fp121);
+ a1.pinpow(i+1,10);
+ expect(a1.toString()).to.equal(fp12pinpow.toString());
+ i++;
+
+ // test frobenius
+ var fp12frob = readFP12(vector.FP12frob, ctx);
+ a1.copy(fp121);
+ a1.frob(Fr);
+ expect(a1.toString()).to.equal(fp12frob.toString());
+
+ // test compressed power with big integer
+ var fp12compow = readFP4(vector.FP12compow, ctx);
+ a1 = fp12c.compow(BIGsc1,BIGsco);
+ expect(a1.toString()).to.equal(fp12compow.toString());
+
+ // test compressed power with small integer
+ var fp12compows = readFP4(vector.FP12compows, ctx);
+ a1 = fp12c.compow(BIGscs,BIGsco);
+ expect(a1.toString()).to.equal(fp12compows.toString());
+
+ // test pow4
+ // Executed only once for timing reasons
+ if (i===0) {
+ var fp12pow4 = readFP12(vector.FP12pow4, ctx);
+ a1 = ctx.FP12.pow4([fp121,fp122,fp123,fp124],[BIGsc1,BIGsc2,BIGsc3,BIGsc4]);
+ expect(a1.toString()).to.equal(fp12pow4.toString());
+ }
+
+ //test trace
+ var fp4trace = readFP4(vector.FP4trace, ctx);
+ a1 = fp121.trace();
+ expect(a1.toString()).to.equal(fp4trace.toString());
+ });
+ done();
+ });
+ });
+});
diff --git a/test/test_FP16_js b/test/test_FP16_js
new file mode 100644
index 0000000..7ff7511
--- /dev/null
+++ b/test/test_FP16_js
@@ -0,0 +1,249 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+/* Test FP16 ARITHMETICS - test driver and function exerciser for FP16 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BLS48'];
+
+var readBIG = function(string, ctx) {
+ while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+ return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP2 = function(string, ctx) {
+ string = string.split(",");
+ var cox = string[0].slice(1);
+ var coy = string[1].slice(0,-1);
+
+ var x = readBIG(cox,ctx);
+ var y = readBIG(coy,ctx);
+
+ return new ctx.FP2(x,y);;
+}
+
+var readFP4 = function(string, ctx) {
+ var X, Y;
+
+ string = string.split("],[");
+ var cox = string[0].slice(1) + "]";
+ var coy = "[" + string[1].slice(0,-1);
+
+ X = readFP2(cox,ctx);
+ Y = readFP2(coy,ctx);
+
+ return new ctx.FP4(X,Y);
+}
+
+var readFP8 = function(string, ctx) {
+ var X, Y;
+
+ string = string.split("]],[[");
+ var cox = string[0].slice(1) + "]]";
+ var coy = "[[" + string[1].slice(0,-1);
+
+ X = readFP4(cox,ctx);
+ Y = readFP4(coy,ctx);
+
+ return new ctx.FP8(X,Y);
+}
+
+var readFP16 = function(string, ctx) {
+ var X, Y;
+
+ string = string.split("]]],[[[");
+ var cox = string[0].slice(1) + "]]]";
+ var coy = "[[[" + string[1].slice(0,-1);
+
+ X = readFP8(cox,ctx);
+ Y = readFP8(coy,ctx);
+
+ return new ctx.FP16(X,Y);
+}
+
+describe('TEST FP16 ARITHMETIC', function() {
+
+ pf_curves.forEach(function(curve){
+
+ it('test '+ curve, function(done) {
+ this.timeout(0);
+
+ var ctx = new CTX(curve);
+ var vectors = require('../testVectors/fp16/'+curve+'.json');
+
+ var a1 = new ctx.FP16(0),
+ a2 = new ctx.FP16(0),
+ one = new ctx.FP16(1),
+ zero = new ctx.FP16(0),
+ fp8one = new ctx.FP8(1),
+ fp8zero = new ctx.FP8(0);
+
+ // Test iszilch and isunity
+ expect(zero.iszilch()).to.be.true;
+ expect(one.iszilch()).to.be.false;
+ expect(zero.isunity()).to.be.false;
+ expect(one.isunity()).to.be.true;
+
+ // Test real/isreal
+ expect(one.isreal()).to.be.true;
+ expect(one.real().toString()).to.be.equal(fp8one.toString());
+ one.times_i();
+ expect(one.isreal()).to.be.false;
+ expect(one.real().toString()).to.be.equal(fp8zero.toString());
+
+ // Test set using FP8
+ one.set(fp8one,fp8zero);
+ expect(one.isunity()).to.be.true;
+ one.seta(fp8one);
+ expect(one.isunity()).to.be.true;
+
+ var i=0;
+ vectors.forEach(function(vector){
+
+ // test commutativity of addition
+ var fp161 = readFP16(vector.FP161,ctx);
+ var fp162 = readFP16(vector.FP162,ctx);
+ var fp16add = readFP16(vector.FP16add,ctx);
+
+ a1.copy(fp161);
+ a1.add(fp162);
+ expect(a1.toString()).to.equal(fp16add.toString());
+ a2.copy(fp162);
+ a2.add(fp161);
+ expect(a2.toString()).to.equal(fp16add.toString());
+
+ // test associativity of addition
+ a2.add(fp16add);
+ a1.copy(fp161);
+ a1.add(fp16add);
+ a1.add(fp162);
+ expect(a1.toString()).to.equal(a2.toString());
+
+ // test subtraction
+ var fp16sub = readFP16(vector.FP16sub, ctx);
+ a1.copy(fp161);
+ a1.sub(fp162);
+ expect(a1.toString()).to.equal(fp16sub.toString());
+
+ // test negative of a FP16
+ var fp16neg = readFP16(vector.FP16neg, ctx);
+ a1.copy(fp161);
+ a1.neg();
+ expect(a1.toString()).to.equal(fp16neg.toString());
+
+ // test conjugate of a FP16
+ var fp16conj = readFP16(vector.FP16conj, ctx);
+ a1.copy(fp161);
+ a1.conj();
+ expect(a1.toString()).to.equal(fp16conj.toString());
+
+ // test negative conjugate of a FP16
+ var fp16nconj = readFP16(vector.FP16nconj, ctx);
+ a1.copy(fp161);
+ a1.nconj();
+ expect(a1.toString()).to.equal(fp16nconj.toString());
+
+ // test multiplication by FP2
+ var fp16qmul = readFP16(vector.FP16qmul, ctx);
+ var fp2sc = readFP2(vector.FP2sc, ctx);
+ a1.copy(fp161);
+ a1.qmul(fp2sc);
+ expect(a1.toString()).to.equal(fp16qmul.toString());
+
+ // test multiplication by FP8
+ var fp16pmul = readFP16(vector.FP16pmul, ctx);
+ var fp8sc = readFP8(vector.FP8sc, ctx);
+ a1.copy(fp161);
+ a1.pmul(fp8sc);
+ expect(a1.toString()).to.equal(fp16pmul.toString());
+
+ // test small scalar multiplication
+ var fp16imul = readFP16(vector.FP16imul, ctx);
+ a1.copy(fp161);
+ a1.imul(i);
+ expect(a1.toString()).to.equal(fp16imul.toString());
+ i++;
+
+ // test square
+ var fp16sqr = readFP16(vector.FP16sqr, ctx);
+ a1.copy(fp161);
+ a1.sqr();
+ expect(a1.toString()).to.equal(fp16sqr.toString());
+
+ // test multiplication
+ var fp16mul = readFP16(vector.FP16mul, ctx);
+ a1.copy(fp161);
+ a1.mul(fp162);
+ expect(a1.toString()).to.equal(fp16mul.toString());
+
+ // test power
+ var fp16pow = readFP16(vector.FP16pow, ctx);
+ var BIGsc1 = readBIG(vector.BIGsc1, ctx);
+ a1 = fp161.pow(BIGsc1);
+ expect(a1.toString()).to.equal(fp16pow.toString());
+
+ // test inverse
+ var fp16inv = readFP16(vector.FP16inv, ctx);
+ a1.copy(fp161);
+ a1.inverse();
+ expect(a1.toString()).to.equal(fp16inv.toString());
+
+ // test multiplication by sqrt(1+sqrt(-1))
+ var fp16mulj = readFP16(vector.FP16mulj, ctx);
+ a1.copy(fp161);
+ a1.times_i();
+ expect(a1.toString()).to.equal(fp16mulj.toString());
+
+ // // test the XTR addition function r=w*x-conj(x)*y+z
+ var fp16xtrA = readFP16(vector.FP16xtrA, ctx);
+ a1.copy(fp162);
+ a1.xtr_A(fp161,fp16add,fp16sub);
+ expect(a1.toString()).to.equal(fp16xtrA.toString());
+
+ // test the XTR addition function r=w*x-conj(x)*y+z
+ var fp16xtrD = readFP16(vector.FP16xtrD, ctx);
+ a1.copy(fp161);
+ a1.xtr_D();
+ expect(a1.toString()).to.equal(fp16xtrD.toString());
+
+ // test the XTR single power r=Tr(x^e)
+ var fp16xtrpow = readFP16(vector.FP16xtrpow, ctx);
+ var fp481 = readFP16(vector.FP481, ctx);
+ a1 = fp481.xtr_pow(BIGsc1);
+ expect(a1.toString()).to.equal(fp16xtrpow.toString());
+
+ // test the XTR double power r=Tr(x^e)
+ var fp16xtrpow2 = readFP16(vector.FP16xtrpow2, ctx);
+ var fp482 = readFP16(vector.FP482, ctx);
+ var fp483 = readFP16(vector.FP483, ctx);
+ var fp484 = readFP16(vector.FP484, ctx);
+ var BIGsc2 = readBIG(vector.BIGsc2, ctx);
+ a1 = fp481.xtr_pow2(fp482,fp483,fp484,BIGsc2,BIGsc1);
+ expect(a1.toString()).to.equal(fp16xtrpow2.toString());
+ });
+ done();
+ });
+ });
+});
diff --git a/test/test_FP24_js b/test/test_FP24_js
new file mode 100644
index 0000000..da76b0f
--- /dev/null
+++ b/test/test_FP24_js
@@ -0,0 +1,235 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+
+/* Test FP24 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BLS24'];
+
+var readBIG = function(string, ctx) {
+ while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+ return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP2 = function(string, ctx) {
+ string = string.split(",");
+ var cox = string[0].slice(1);
+ var coy = string[1].slice(0,-1);
+
+ var x = readBIG(cox,ctx);
+ var y = readBIG(coy,ctx);
+
+ return new ctx.FP2(x,y);;
+}
+
+var readFP4 = function(string, ctx) {
+ var X, Y;
+
+ string = string.split("],[");
+ var cox = string[0].slice(1) + "]";
+ var coy = "[" + string[1].slice(0,-1);
+
+ X = readFP2(cox,ctx);
+ Y = readFP2(coy,ctx);
+
+ return new ctx.FP4(X,Y);
+}
+
+var readFP8 = function(string, ctx) {
+ var X, Y;
... 1392 lines suppressed ...