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:17 UTC
[incubator-milagro-crypto-js] 01/01: resync code to golden repo
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*
-[![Master Branch](https://img.shields.io/badge/-master:-gray.svg)](https://github.com/milagro-crypto/milagro-crypto-js/tree/master)
-[![Master Build Status](https://secure.travis-ci.org/milagro-crypto/milagro-crypto-js.png?branch=master)](https://travis-ci.org/milagro-crypto/milagro-crypto-js?branch=master)
-[![Coverage Status](https://coveralls.io/repos/github/milagro-crypto/milagro-crypto-js/badge.svg?branch=master)](https://coveralls.io/github/milagro-crypto/milagro-crypto-js?branch=master)
+[![Master Branch](https://img.shields.io/badge/-master:-gray.svg)](https://github.com/apache/incubator-milagro-crypto-js/tree/master)
+[![Master Build Status](https://secure.travis-ci.org/apache/incubator-milagro-crypto-js.png?branch=master)](https://travis-ci.org/apache/incubator-milagro-crypto-js?branch=master)
+[![Master Coverage Status](https://coveralls.io/repos/github/apache/incubator-milagro-crypto-js/badge.svg?branch=master)](https://coveralls.io/github/apache/incubator-milagro-crypto-js?branch=master)
+
+[![Develop Branch](https://img.shields.io/badge/-develop:-gray.svg)](https://github.com/apache/incubator-milagro-crypto-js/tree/develop)
+[![Develop Build Status](https://secure.travis-ci.org/apache/incubator-milagro-crypto-js.png?branch=develop)](https://travis-ci.org/apache/incubator-milagro-crypto-js?branch=develop)
+[![Develop Coverage Status](https://coveralls.io/repos/github/apache/incubator-milagro-crypto-js/badge.svg?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 ...