Merge pull request #5 from apache/update-code
update code
diff --git a/LICENSE-2.0.TXT b/LICENSE-2.0.TXT
index 9b5e401..7a4a3ea 100644
--- a/LICENSE-2.0.TXT
+++ b/LICENSE-2.0.TXT
@@ -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 [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
+
+ 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/NOTICE.txt b/NOTICE.txt
index 2e6c028..434d2bb 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
-Apache Milagro Crypto Libraries
-Copyright 2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
+Apache Milagro Crypto Libraries
+Copyright 2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/version3/amcl3.pdf b/version3/amcl3.pdf
index 3fb26e1..0908bcd 100644
--- a/version3/amcl3.pdf
+++ b/version3/amcl3.pdf
Binary files differ
diff --git a/version3/c/amcl.h b/version3/c/amcl.h
index 2558911..f72557d 100644
--- a/version3/c/amcl.h
+++ b/version3/c/amcl.h
@@ -57,6 +57,13 @@
#define D_TYPE 0
#define M_TYPE 1
+#define FP_ZERO 0
+#define FP_UNITY 1
+#define FP_SPARSER 2
+#define FP_SPARSE 3
+#define FP_DENSE 4
+
+
/**
* @brief SHA256 hash function instance */
typedef struct
diff --git a/version3/c/bls.c b/version3/c/bls.c
index 6706316..388bf2f 100644
--- a/version3/c/bls.c
+++ b/version3/c/bls.c
@@ -81,8 +81,20 @@
ECP2_ZZZ_generator(&G);
ECP2_ZZZ_fromOctet(&PK,W);
ECP_ZZZ_neg(&D);
- PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
- PAIR_ZZZ_fexp(&v);
+
+
+// Use new multi-pairing mechanism
+
+ FP12_YYY r[ATE_BITS_ZZZ];
+ PAIR_ZZZ_initmp(r);
+ PAIR_ZZZ_another(r,&G,&D);
+ PAIR_ZZZ_another(r,&PK,&HM);
+ PAIR_ZZZ_miller(&v,r);
+
+//.. or alternatively
+// PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
+
+ PAIR_ZZZ_fexp(&v);
if (FP12_YYY_isunity(&v)) return BLS_OK;
return BLS_FAIL;
}
diff --git a/version3/c/bls192.c b/version3/c/bls192.c
index 5eb8852..55d5373 100644
--- a/version3/c/bls192.c
+++ b/version3/c/bls192.c
@@ -81,7 +81,18 @@
ECP4_ZZZ_generator(&G);
ECP4_ZZZ_fromOctet(&PK,W);
ECP_ZZZ_neg(&D);
- PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
+
+// Use new multi-pairing mechanism
+
+ FP24_YYY r[ATE_BITS_ZZZ];
+ PAIR_ZZZ_initmp(r);
+ PAIR_ZZZ_another(r,&G,&D);
+ PAIR_ZZZ_another(r,&PK,&HM);
+ PAIR_ZZZ_miller(&v,r);
+
+//.. or alternatively
+// PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
+
PAIR_ZZZ_fexp(&v);
if (FP24_YYY_isunity(&v)) return BLS_OK;
return BLS_FAIL;
diff --git a/version3/c/bls256.c b/version3/c/bls256.c
index 8f228b2..09db152 100644
--- a/version3/c/bls256.c
+++ b/version3/c/bls256.c
@@ -81,7 +81,18 @@
ECP8_ZZZ_generator(&G);
ECP8_ZZZ_fromOctet(&PK,W);
ECP_ZZZ_neg(&D);
- PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
+
+// Use new multi-pairing mechanism
+
+ FP48_YYY r[ATE_BITS_ZZZ];
+ PAIR_ZZZ_initmp(r);
+ PAIR_ZZZ_another(r,&G,&D);
+ PAIR_ZZZ_another(r,&PK,&HM);
+ PAIR_ZZZ_miller(&v,r);
+
+//.. or alternatively
+// PAIR_ZZZ_double_ate(&v,&G,&D,&PK,&HM);
+
PAIR_ZZZ_fexp(&v);
if (FP48_YYY_isunity(&v)) return BLS_OK;
return BLS_FAIL;
diff --git a/version3/c/config16.py b/version3/c/config16.py
index ba77919..3854184 100644
--- a/version3/c/config16.py
+++ b/version3/c/config16.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("gcc -O3 -std=c99 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd=tb+"_"+base
fnameh="config_big_"+bd+".h"
os.system(copytext+" config_big.h "+fnameh)
@@ -107,6 +107,8 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
+
fnamec="big_"+bd+".c"
fnameh="big_"+bd+".h"
@@ -194,8 +196,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
fnamec="ecp2_"+tc+".c"
@@ -287,7 +291,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -297,21 +301,22 @@
# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# ate bits is number of bits in Ate parameter (from romgen program)
# if pairing friendly. M or D type twist, and sign of the family parameter x
if x==1:
- curveset("256","25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==4:
- curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
diff --git a/version3/c/config32.py b/version3/c/config32.py
index e848122..130f608 100644
--- a/version3/c/config32.py
+++ b/version3/c/config32.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("gcc -O3 -std=c99 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd=tb+"_"+base
fnameh="config_big_"+bd+".h"
@@ -112,6 +112,7 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
fnamec="big_"+bd+".c"
fnameh="big_"+bd+".h"
@@ -201,8 +202,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
fnamec="ecp2_"+tc+".c"
@@ -279,8 +282,10 @@
os.system(copytext+" fp24.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
fnamec="ecp4_"+tc+".c"
@@ -386,8 +391,10 @@
os.system(copytext+" fp48.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
@@ -490,7 +497,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -501,96 +508,97 @@
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
# if pairing friendly. M or D type twist, and sign of the family parameter x
+# ate bits is number of bits in Ate parameter (from romgen program)
# curve security is AES equiavlent, rounded up.
if x==1:
- curveset("256","25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+ curveset("256","25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==4:
- curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==5:
- curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==6:
- curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==7:
- curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==8:
- curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+ curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==9:
- curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==10:
- curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==11:
- curveset("256","256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("256","256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==12:
- curveset("256","256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==13:
- curveset("384","384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+ curveset("384","384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==14:
- curveset("384","384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("384","384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==15:
- curveset("512","512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("512","512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==16:
- curveset("512","512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("512","512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==17:
- curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==18:
- curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/c/config64.py b/version3/c/config64.py
index 22fc9b8..9f2ba6b 100644
--- a/version3/c/config64.py
+++ b/version3/c/config64.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("gcc -O3 -std=c99 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd=tb+"_"+base
fnameh="config_big_"+bd+".h"
os.system(copytext+" config_big.h "+fnameh)
@@ -107,6 +107,8 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
+
fnamec="big_"+bd+".c"
fnameh="big_"+bd+".h"
@@ -195,8 +197,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
fnamec="ecp2_"+tc+".c"
@@ -273,8 +277,10 @@
os.system(copytext+" fp24.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
fnamec="ecp4_"+tc+".c"
@@ -380,8 +386,10 @@
os.system(copytext+" fp48.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("gcc -O3 -std=c99 -c "+fnamec)
@@ -484,7 +492,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -495,96 +503,97 @@
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
# if pairing friendly. M or D type twist, and sign of the family parameter x
+# ate bits is number of bits in Ate parameter (from romgen program)
# curve security is AES equiavlent, rounded up.
if x==1:
- curveset("256","25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+ curveset("256","25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==4:
- curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==5:
- curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==6:
- curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==7:
- curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==8:
- curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==9:
- curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==10:
- curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==11:
- curveset("256","256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("256","256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==12:
- curveset("256","256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==13:
- curveset("384","384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("384","384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==14:
- curveset("384","384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("384","384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==15:
- curveset("512","512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("512","512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==16:
- curveset("512","512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("512","512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==17:
- curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==18:
- curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/c/config_curve.h b/version3/c/config_curve.h
index 58208df..458585b 100644
--- a/version3/c/config_curve.h
+++ b/version3/c/config_curve.h
@@ -22,6 +22,8 @@
#define SEXTIC_TWIST_ZZZ @ST@
#define SIGN_OF_X_ZZZ @SX@
+#define ATE_BITS_ZZZ @AB@
+
#endif
#if CURVE_SECURITY_ZZZ == 128
diff --git a/version3/c/fp12.c b/version3/c/fp12.c
index c103fb3..a6a7830 100644
--- a/version3/c/fp12.c
+++ b/version3/c/fp12.c
@@ -22,6 +22,7 @@
/* FP12 elements are of the form a+i.b+i^2.c */
#include "fp12_YYY.h"
+#include "config_curve_ZZZ.h"
/* return 1 if b==c, no branching */
static int teq(sign32 b,sign32 c)
@@ -81,6 +82,7 @@
FP4_YYY_copy(&(w->a),&(x->a));
FP4_YYY_copy(&(w->b),&(x->b));
FP4_YYY_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP12 w=1 */
@@ -90,6 +92,7 @@
FP4_YYY_one(&(w->a));
FP4_YYY_zero(&(w->b));
FP4_YYY_zero(&(w->c));
+ w->type=FP_UNITY;
}
/* return 1 if x==y, else 0 */
@@ -118,6 +121,7 @@
FP4_YYY_copy(&(w->a),a);
FP4_YYY_zero(&(w->b));
FP4_YYY_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP12 from 3 FP4's */
@@ -127,6 +131,7 @@
FP4_YYY_copy(&(w->a),a);
FP4_YYY_copy(&(w->b),b);
FP4_YYY_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -167,6 +172,7 @@
FP4_YYY_add(&(w->b),&B,&(w->b));
FP4_YYY_add(&(w->c),&C,&(w->c));
+ w->type=FP_DENSE;
FP12_YYY_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -178,6 +184,12 @@
FP4_YYY A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP12_YYY_copy(w,x);
+ return;
+ }
+
FP4_YYY_sqr(&A,&(x->a));
FP4_YYY_mul(&B,&(x->b),&(x->c));
FP4_YYY_add(&B,&B,&B);
@@ -209,6 +221,11 @@
FP4_YYY_add(&(w->b),&C,&D);
FP4_YYY_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
+
FP12_YYY_norm(w);
}
@@ -267,100 +284,287 @@
FP4_YYY_times_i(&z3);
FP4_YYY_add(&(w->a),&z0,&z3);
+ w->type=FP_DENSE;
+ FP12_YYY_norm(w);
+}
+
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void FP12_YYY_ssmul(FP12_YYY *w,FP12_YYY *y)
+{
+ FP4_YYY z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP12_YYY_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
+
+ if (y->type >= FP_SPARSE)
+ {
+ FP4_YYY_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP2_YYY_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP2_YYY_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP2_YYY_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP2_YYY_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP4_YYY_times_i(&z2);
+ }
+ else
+#endif
+ FP4_YYY_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP4_YYY_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP4_YYY_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP4_YYY_norm(&t0);
+ FP4_YYY_norm(&t1);
+
+ FP4_YYY_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP4_YYY_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP4_YYY_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP4_YYY_norm(&t0);
+ FP4_YYY_norm(&t1);
+
+ FP4_YYY_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP4_YYY_neg(&t0,&z0); // -(xa.ya)
+ FP4_YYY_neg(&t1,&z2); // -(xb.yb)
+
+ FP4_YYY_add(&z1,&z1,&t0);
+ FP4_YYY_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP4_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP4_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP4_YYY_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP4_YYY_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP4_YYY_norm(&t0);
+ FP4_YYY_norm(&t1);
+
+ FP4_YYY_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP4_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP2_YYY_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP2_YYY_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP2_YYY_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP2_YYY_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP4_YYY_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP4_YYY_neg(&t1,&t0); // -(xc.yc)
+
+ FP4_YYY_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP4_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP4_YYY_times_i(&t0); // i.(xc.yc)
+ FP4_YYY_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP4_YYY_norm(&z3);
+ FP4_YYY_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP4_YYY_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP12_YYY_smul(w,y);
+ return;
+ }
+ // dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP4_YYY_copy(&z3,&(w->b));
+ FP4_YYY_mul(&z0,&(w->a),&(y->a));
+
+ FP4_YYY_pmul(&z2,&(w->b),&(y->b).a);
+ FP4_YYY_add(&(w->b),&(w->a),&(w->b));
+ FP4_YYY_copy(&t1,&(y->a));
+ FP2_YYY_add(&t1.a,&t1.a,&(y->b).a);
+
+ FP4_YYY_norm(&t1);
+ FP4_YYY_norm(&(w->b));
+
+ FP4_YYY_mul(&(w->b),&(w->b),&t1);
+ FP4_YYY_add(&z3,&z3,&(w->c));
+ FP4_YYY_norm(&z3);
+ FP4_YYY_pmul(&z3,&z3,&(y->b).a);
+ FP4_YYY_neg(&t0,&z0);
+ FP4_YYY_neg(&t1,&z2);
+
+ FP4_YYY_add(&(w->b),&(w->b),&t0); // z1=z1-z0
+ FP4_YYY_add(&(w->b),&(w->b),&t1); // z1=z1-z2
+
+ FP4_YYY_add(&z3,&z3,&t1); // z3=z3-z2
+ FP4_YYY_add(&z2,&z2,&t0); // z2=z2-z0
+
+ FP4_YYY_add(&t0,&(w->a),&(w->c));
+ FP4_YYY_norm(&t0);
+ FP4_YYY_norm(&z3);
+
+ FP4_YYY_mul(&t0,&(y->a),&t0);
+ FP4_YYY_add(&(w->c),&z2,&t0);
+
+ FP4_YYY_times_i(&z3);
+ FP4_YYY_add(&(w->a),&z0,&z3);
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP4_YYY_mul(&z0,&(w->a),&(y->a));
+ FP4_YYY_add(&t0,&(w->a),&(w->b));
+ FP4_YYY_norm(&t0);
+
+ FP4_YYY_mul(&z1,&t0,&(y->a));
+ FP4_YYY_add(&t0,&(w->b),&(w->c));
+ FP4_YYY_norm(&t0);
+
+ FP4_YYY_pmul(&z3,&t0,&(y->c).b);
+ FP4_YYY_times_i(&z3);
+
+ FP4_YYY_neg(&t0,&z0);
+ FP4_YYY_add(&z1,&z1,&t0); // z1=z1-z0
+
+ FP4_YYY_copy(&(w->b),&z1);
+ FP4_YYY_copy(&z2,&t0);
+
+ FP4_YYY_add(&t0,&(w->a),&(w->c));
+ FP4_YYY_add(&t1,&(y->a),&(y->c));
+
+ FP4_YYY_norm(&t0);
+ FP4_YYY_norm(&t1);
+
+ FP4_YYY_mul(&t0,&t1,&t0);
+ FP4_YYY_add(&z2,&z2,&t0);
+
+ FP4_YYY_pmul(&t0,&(w->c),&(y->c).b);
+ FP4_YYY_times_i(&t0);
+ FP4_YYY_neg(&t1,&t0);
+ FP4_YYY_times_i(&t0);
+
+ FP4_YYY_add(&(w->c),&z2,&t1);
+ FP4_YYY_add(&z3,&z3,&t1);
+
+ FP4_YYY_add(&(w->b),&(w->b),&t0);
+ FP4_YYY_norm(&z3);
+ FP4_YYY_times_i(&z3);
+ FP4_YYY_add(&(w->a),&z0,&z3);
+
+#endif
+ }
+ w->type=FP_DENSE;
FP12_YYY_norm(w);
}
/* FP12 multiplication w=w*y */
-/* SU= 744 */
/* catering for special case that arises from special form of ATE pairing line function */
-void FP12_YYY_smul(FP12_YYY *w,FP12_YYY *y,int type)
+/* w and y are both sparser line functions - cost = 6m */
+void FP12_YYY_smul(FP12_YYY *w,FP12_YYY *y)
{
- FP4_YYY z0,z1,z2,z3,t0,t1;
+ FP2_YYY w1,w2,w3,ta,tb,tc,td,te,t;
- if (type==D_TYPE)
- {
- // y->c is 0
+// if (type==D_TYPE)
+// {
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP2_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP2_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP2_YYY_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
- FP4_YYY_copy(&z3,&(w->b));
- FP4_YYY_mul(&z0,&(w->a),&(y->a));
+ FP2_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP2_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP2_YYY_add(&t,&w1,&w2);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP2_YYY_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP2_YYY_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP2_YYY_add(&t,&w1,&w3);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
- FP4_YYY_pmul(&z2,&(w->b),&(y->b).a);
- FP4_YYY_add(&(w->b),&(w->a),&(w->b));
- FP4_YYY_copy(&t1,&(y->a));
- FP2_YYY_add(&t1.a,&t1.a,&(y->b).a);
+ FP2_YYY_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP2_YYY_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP2_YYY_add(&t,&w2,&w3);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
- FP4_YYY_norm(&t1);
- FP4_YYY_norm(&(w->b));
+ FP2_YYY_mul_ip(&w2);
+ FP2_YYY_add(&w1,&w1,&w2);
+ FP4_YYY_from_FP2s(&(w->a),&w1,&tc);
+ FP4_YYY_from_FP2s(&(w->b),&td,&te); // only norm these 2
+ FP4_YYY_from_FP2(&(w->c),&w3);
- FP4_YYY_mul(&(w->b),&(w->b),&t1);
- FP4_YYY_add(&z3,&z3,&(w->c));
- FP4_YYY_norm(&z3);
- FP4_YYY_pmul(&z3,&z3,&(y->b).a);
- FP4_YYY_neg(&t0,&z0);
- FP4_YYY_neg(&t1,&z2);
+ FP4_YYY_norm(&(w->a));
+ FP4_YYY_norm(&(w->b));
+#endif
+// } else {
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP2_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP2_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP2_YYY_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
- FP4_YYY_add(&(w->b),&(w->b),&t0); // z1=z1-z0
- FP4_YYY_add(&(w->b),&(w->b),&t1); // z1=z1-z2
+ FP2_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP2_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP2_YYY_add(&t,&w1,&w2);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP2_YYY_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP2_YYY_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP2_YYY_add(&t,&w1,&w3);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
- FP4_YYY_add(&z3,&z3,&t1); // z3=z3-z2
- FP4_YYY_add(&z2,&z2,&t0); // z2=z2-z0
+ FP2_YYY_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP2_YYY_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP2_YYY_norm(&ta);
+ FP2_YYY_norm(&tb);
+ FP2_YYY_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP2_YYY_add(&t,&w2,&w3);
+ FP2_YYY_neg(&t,&t);
+ FP2_YYY_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
- FP4_YYY_add(&t0,&(w->a),&(w->c));
+ FP2_YYY_mul_ip(&w2);
+ FP2_YYY_add(&w1,&w1,&w2);
+ FP4_YYY_from_FP2s(&(w->a),&w1,&tc);
- FP4_YYY_norm(&t0);
- FP4_YYY_norm(&z3);
+ FP2_YYY_mul_ip(&w3);
+ FP2_YYY_norm(&w3);
+ FP4_YYY_from_FP2H(&(w->b),&w3);
- FP4_YYY_mul(&t0,&(y->a),&t0);
- FP4_YYY_add(&(w->c),&z2,&t0);
+ FP2_YYY_norm(&te);
+ FP2_YYY_mul_ip(&te);
+ FP4_YYY_from_FP2s(&(w->c),&te,&td);
- FP4_YYY_times_i(&z3);
- FP4_YYY_add(&(w->a),&z0,&z3);
- }
+ FP4_YYY_norm(&(w->a));
+ FP4_YYY_norm(&(w->c));
+#endif
- if (type==M_TYPE)
- {
- // y->b is zero
- FP4_YYY_mul(&z0,&(w->a),&(y->a));
- FP4_YYY_add(&t0,&(w->a),&(w->b));
- FP4_YYY_norm(&t0);
-
- FP4_YYY_mul(&z1,&t0,&(y->a));
- FP4_YYY_add(&t0,&(w->b),&(w->c));
- FP4_YYY_norm(&t0);
-
- FP4_YYY_pmul(&z3,&t0,&(y->c).b);
- FP4_YYY_times_i(&z3);
-
- FP4_YYY_neg(&t0,&z0);
- FP4_YYY_add(&z1,&z1,&t0); // z1=z1-z0
-
- FP4_YYY_copy(&(w->b),&z1);
-
- FP4_YYY_copy(&z2,&t0);
-
- FP4_YYY_add(&t0,&(w->a),&(w->c));
- FP4_YYY_add(&t1,&(y->a),&(y->c));
-
- FP4_YYY_norm(&t0);
- FP4_YYY_norm(&t1);
-
- FP4_YYY_mul(&t0,&t1,&t0);
- FP4_YYY_add(&z2,&z2,&t0);
-
- FP4_YYY_pmul(&t0,&(w->c),&(y->c).b);
- FP4_YYY_times_i(&t0);
- FP4_YYY_neg(&t1,&t0);
- FP4_YYY_times_i(&t0);
-
- FP4_YYY_add(&(w->c),&z2,&t1);
- FP4_YYY_add(&z3,&z3,&t1);
-
- FP4_YYY_add(&(w->b),&(w->b),&t0);
- FP4_YYY_norm(&z3);
- FP4_YYY_times_i(&z3);
- FP4_YYY_add(&(w->a),&z0,&z3);
- }
- FP12_YYY_norm(w);
+// }
+ w->type=FP_SPARSE;
}
/* Set w=1/x */
@@ -401,7 +605,7 @@
FP4_YYY_mul(&(w->a),&f0,&f3);
FP4_YYY_mul(&(w->b),&f1,&f3);
FP4_YYY_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -611,6 +815,7 @@
FP4_YYY_pmul(&(w->b),&(w->b),f);
FP4_YYY_pmul(&(w->c),&(w->c),&f2);
+ w->type=FP_DENSE;
}
/* SU= 8 */
@@ -722,5 +927,7 @@
FP4_YYY_cmove(&(f->a),&(g->a),d);
FP4_YYY_cmove(&(f->b),&(g->b),d);
FP4_YYY_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
diff --git a/version3/c/fp12.h b/version3/c/fp12.h
index 99fed17..bf83a57 100644
--- a/version3/c/fp12.h
+++ b/version3/c/fp12.h
@@ -38,6 +38,7 @@
FP4_YYY a; /**< first part of FP12 */
FP4_YYY b; /**< second part of FP12 */
FP4_YYY c; /**< third part of FP12 */
+ int type;
} FP12_YYY;
extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
@@ -108,15 +109,23 @@
@param y FP12 instance
*/
extern void FP12_YYY_sqr(FP12_YYY *x,FP12_YYY *y);
-/** @brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+
+/** @brief Fast multiplication of two sparse FP12s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP12 instance, on exit = x*y
@param y FP12 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP12_YYY_smul(FP12_YYY *x,FP12_YYY *y,int t);
-/** @brief Multiplication of two FP12s
+extern void FP12_YYY_smul(FP12_YYY *x,FP12_YYY *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, of special form
+ */
+extern void FP12_YYY_ssmul(FP12_YYY *x,FP12_YYY *y);
+
+
+/** @brief Full unconditional Multiplication of two FP12s
*
@param x FP12 instance, on exit = x*y
@param y FP12 instance, the multiplier
diff --git a/version3/c/fp24.c b/version3/c/fp24.c
index 901d7a9..8951b22 100644
--- a/version3/c/fp24.c
+++ b/version3/c/fp24.c
@@ -79,6 +79,7 @@
FP8_YYY_copy(&(w->a),&(x->a));
FP8_YYY_copy(&(w->b),&(x->b));
FP8_YYY_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP24 w=1 */
@@ -88,6 +89,7 @@
FP8_YYY_one(&(w->a));
FP8_YYY_zero(&(w->b));
FP8_YYY_zero(&(w->c));
+ w->type=FP_UNITY;
}
/* return 1 if x==y, else 0 */
@@ -116,6 +118,7 @@
FP8_YYY_copy(&(w->a),a);
FP8_YYY_zero(&(w->b));
FP8_YYY_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP24 from 3 FP8's */
@@ -125,6 +128,7 @@
FP8_YYY_copy(&(w->a),a);
FP8_YYY_copy(&(w->b),b);
FP8_YYY_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -164,7 +168,7 @@
FP8_YYY_add(&(w->c),&(w->c),&(w->c));
FP8_YYY_add(&(w->b),&B,&(w->b));
FP8_YYY_add(&(w->c),&C,&(w->c));
-
+ w->type=FP_DENSE;
FP24_YYY_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -176,6 +180,12 @@
FP8_YYY A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP24_YYY_copy(w,x);
+ return;
+ }
+
FP8_YYY_sqr(&A,&(x->a));
FP8_YYY_mul(&B,&(x->b),&(x->c));
FP8_YYY_add(&B,&B,&B);
@@ -209,6 +219,11 @@
FP8_YYY_add(&(w->b),&C,&D);
FP8_YYY_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
+
FP24_YYY_norm(w);
}
@@ -266,20 +281,106 @@
FP8_YYY_norm(&z3);
FP8_YYY_times_i(&z3);
FP8_YYY_add(&(w->a),&z0,&z3);
-
+ w->type=FP_DENSE;
FP24_YYY_norm(w);
}
-/* FP24 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void FP24_YYY_smul(FP24_YYY *w,FP24_YYY *y,int type)
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void FP24_YYY_ssmul(FP24_YYY *w,FP24_YYY *y)
{
- FP8_YYY z0,z1,z2,z3,t0,t1;
+ FP8_YYY z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP24_YYY_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
- if (type==D_TYPE)
- { // y->c is 0
+ if (y->type >= FP_SPARSE)
+ {
+ FP8_YYY_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP4_YYY_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP4_YYY_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP4_YYY_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP4_YYY_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP8_YYY_times_i(&z2);
+ }
+ else
+#endif
+ FP8_YYY_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP8_YYY_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP8_YYY_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP8_YYY_norm(&t0);
+ FP8_YYY_norm(&t1);
+
+ FP8_YYY_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP8_YYY_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP8_YYY_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP8_YYY_norm(&t0);
+ FP8_YYY_norm(&t1);
+
+ FP8_YYY_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP8_YYY_neg(&t0,&z0); // -(xa.ya)
+ FP8_YYY_neg(&t1,&z2); // -(xb.yb)
+
+ FP8_YYY_add(&z1,&z1,&t0);
+ FP8_YYY_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP8_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP8_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP8_YYY_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP8_YYY_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP8_YYY_norm(&t0);
+ FP8_YYY_norm(&t1);
+
+ FP8_YYY_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP8_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP4_YYY_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP4_YYY_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP4_YYY_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP4_YYY_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP8_YYY_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP8_YYY_neg(&t1,&t0); // -(xc.yc)
+
+ FP8_YYY_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP8_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP8_YYY_times_i(&t0); // i.(xc.yc)
+ FP8_YYY_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP8_YYY_norm(&z3);
+ FP8_YYY_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP8_YYY_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP24_YYY_smul(w,y);
+ return;
+ }
+// dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
FP8_YYY_copy(&z3,&(w->b));
FP8_YYY_mul(&z0,&(w->a),&(y->a));
@@ -305,7 +406,6 @@
FP8_YYY_add(&z2,&z2,&t0); // z2=z2-z0
FP8_YYY_add(&t0,&(w->a),&(w->c));
-
FP8_YYY_norm(&t0);
FP8_YYY_norm(&z3);
@@ -314,10 +414,8 @@
FP8_YYY_times_i(&z3);
FP8_YYY_add(&(w->a),&z0,&z3);
- }
-
- if (type==M_TYPE)
- { // y->b is zero
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
FP8_YYY_mul(&z0,&(w->a),&(y->a));
FP8_YYY_add(&t0,&(w->a),&(w->b));
FP8_YYY_norm(&t0);
@@ -333,7 +431,6 @@
FP8_YYY_add(&z1,&z1,&t0); // z1=z1-z0
FP8_YYY_copy(&(w->b),&z1);
-
FP8_YYY_copy(&z2,&t0);
FP8_YYY_add(&t0,&(w->a),&(w->c));
@@ -357,10 +454,112 @@
FP8_YYY_norm(&z3);
FP8_YYY_times_i(&z3);
FP8_YYY_add(&(w->a),&z0,&z3);
+#endif
}
+ w->type=FP_DENSE;
FP24_YYY_norm(w);
}
+/* 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 */
+void FP24_YYY_smul(FP24_YYY *w,FP24_YYY *y)
+{
+ FP4_YYY w1,w2,w3,ta,tb,tc,td,te,t;
+
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP4_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP4_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP4_YYY_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
+
+ FP4_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP4_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP4_YYY_add(&t,&w1,&w2);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP4_YYY_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP4_YYY_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP4_YYY_add(&t,&w1,&w3);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
+
+ FP4_YYY_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP4_YYY_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP4_YYY_add(&t,&w2,&w3);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
+
+ FP4_YYY_times_i(&w2);
+ FP4_YYY_add(&w1,&w1,&w2);
+ FP8_YYY_from_FP4s(&(w->a),&w1,&tc);
+ FP8_YYY_from_FP4s(&(w->b),&td,&te); // only norm these 2
+ FP8_YYY_from_FP4(&(w->c),&w3);
+
+ FP8_YYY_norm(&(w->a));
+ FP8_YYY_norm(&(w->b));
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP4_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP4_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP4_YYY_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
+
+ FP4_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP4_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP4_YYY_add(&t,&w1,&w2);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP4_YYY_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP4_YYY_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP4_YYY_add(&t,&w1,&w3);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
+
+ FP4_YYY_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP4_YYY_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP4_YYY_norm(&ta);
+ FP4_YYY_norm(&tb);
+ FP4_YYY_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP4_YYY_add(&t,&w2,&w3);
+ FP4_YYY_neg(&t,&t);
+ FP4_YYY_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
+
+ FP4_YYY_times_i(&w2);
+ FP4_YYY_add(&w1,&w1,&w2);
+ FP8_YYY_from_FP4s(&(w->a),&w1,&tc);
+
+ FP4_YYY_times_i(&w3);
+ FP4_YYY_norm(&w3);
+ FP8_YYY_from_FP4H(&(w->b),&w3);
+
+ FP4_YYY_norm(&te);
+ FP4_YYY_times_i(&te);
+ FP8_YYY_from_FP4s(&(w->c),&te,&td);
+
+ FP8_YYY_norm(&(w->a));
+ FP8_YYY_norm(&(w->c));
+#endif
+
+ w->type=FP_SPARSE;
+}
+
/* Set w=1/x */
/* SU= 600 */
void FP24_YYY_inv(FP24_YYY *w,FP24_YYY *x)
@@ -398,7 +597,7 @@
FP8_YYY_mul(&(w->a),&f0,&f3);
FP8_YYY_mul(&(w->b),&f1,&f3);
FP8_YYY_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -657,6 +856,7 @@
FP8_YYY_qmul(&(w->b),&(w->b),f); FP8_YYY_times_i2(&(w->b));
FP8_YYY_qmul(&(w->c),&(w->c),&f2); FP8_YYY_times_i2(&(w->c)); FP8_YYY_times_i2(&(w->c));
}
+ w->type=FP_DENSE;
}
/* SU= 8 */
@@ -821,5 +1021,7 @@
FP8_YYY_cmove(&(f->a),&(g->a),d);
FP8_YYY_cmove(&(f->b),&(g->b),d);
FP8_YYY_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
diff --git a/version3/c/fp24.h b/version3/c/fp24.h
index 13ff25c..02e09fa 100644
--- a/version3/c/fp24.h
+++ b/version3/c/fp24.h
@@ -12,6 +12,7 @@
FP8_YYY a; /**< first part of FP12 */
FP8_YYY b; /**< second part of FP12 */
FP8_YYY c; /**< third part of FP12 */
+ int type;
} FP24_YYY;
extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
@@ -82,20 +83,26 @@
@param y FP24 instance
*/
extern void FP24_YYY_sqr(FP24_YYY *x,FP24_YYY *y);
-/** @brief Fast multiplication of an FP24 by an FP24 that arises from an ATE pairing line function
+/** @brief Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP24 instance, on exit = x*y
@param y FP24 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP24_YYY_smul(FP24_YYY *x,FP24_YYY *y,int t);
-/** @brief Multiplication of two FP24s
+extern void FP24_YYY_smul(FP24_YYY *x,FP24_YYY *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP24 instance, on exit = x*y
+ @param y FP24 instance, of special form
+ */
+extern void FP24_YYY_ssmul(FP24_YYY *x,FP24_YYY *y);
+/** @brief Full unconditional Multiplication of two FP24s
*
@param x FP24 instance, on exit = x*y
@param y FP24 instance, the multiplier
*/
extern void FP24_YYY_mul(FP24_YYY *x,FP24_YYY *y);
+
/** @brief Inverting an FP24
*
@param x FP24 instance, on exit = 1/y
diff --git a/version3/c/fp48.c b/version3/c/fp48.c
index 68f4ddd..88bf25b 100644
--- a/version3/c/fp48.c
+++ b/version3/c/fp48.c
@@ -80,6 +80,7 @@
FP16_YYY_copy(&(w->a),&(x->a));
FP16_YYY_copy(&(w->b),&(x->b));
FP16_YYY_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP48 w=1 */
@@ -89,6 +90,7 @@
FP16_YYY_one(&(w->a));
FP16_YYY_zero(&(w->b));
FP16_YYY_zero(&(w->c));
+ w->type=FP_UNITY;
}
/* return 1 if x==y, else 0 */
@@ -117,6 +119,7 @@
FP16_YYY_copy(&(w->a),a);
FP16_YYY_zero(&(w->b));
FP16_YYY_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP48 from 3 FP16's */
@@ -126,6 +129,7 @@
FP16_YYY_copy(&(w->a),a);
FP16_YYY_copy(&(w->b),b);
FP16_YYY_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -165,7 +169,7 @@
FP16_YYY_add(&(w->c),&(w->c),&(w->c));
FP16_YYY_add(&(w->b),&B,&(w->b));
FP16_YYY_add(&(w->c),&C,&(w->c));
-
+ w->type=FP_DENSE;
FP48_YYY_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -177,6 +181,12 @@
FP16_YYY A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP48_YYY_copy(w,x);
+ return;
+ }
+
FP16_YYY_sqr(&A,&(x->a));
FP16_YYY_mul(&B,&(x->b),&(x->c));
FP16_YYY_add(&B,&B,&B);
@@ -210,6 +220,11 @@
FP16_YYY_add(&(w->b),&C,&D);
FP16_YYY_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
+
FP48_YYY_norm(w);
}
@@ -267,20 +282,106 @@
FP16_YYY_norm(&z3);
FP16_YYY_times_i(&z3);
FP16_YYY_add(&(w->a),&z0,&z3);
-
+ w->type=FP_DENSE;
FP48_YYY_norm(w);
}
-/* FP48 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void FP48_YYY_smul(FP48_YYY *w,FP48_YYY *y,int type)
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void FP48_YYY_ssmul(FP48_YYY *w,FP48_YYY *y)
{
- FP16_YYY z0,z1,z2,z3,t0,t1;
+ FP16_YYY z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP48_YYY_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
- if (type==D_TYPE)
- { // y->c is 0
+ if (y->type >= FP_SPARSE)
+ {
+ FP16_YYY_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP8_YYY_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP8_YYY_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP8_YYY_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP8_YYY_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP16_YYY_times_i(&z2);
+ }
+ else
+#endif
+ FP16_YYY_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP16_YYY_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP16_YYY_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP16_YYY_norm(&t0);
+ FP16_YYY_norm(&t1);
+
+ FP16_YYY_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP16_YYY_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP16_YYY_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP16_YYY_norm(&t0);
+ FP16_YYY_norm(&t1);
+
+ FP16_YYY_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP16_YYY_neg(&t0,&z0); // -(xa.ya)
+ FP16_YYY_neg(&t1,&z2); // -(xb.yb)
+
+ FP16_YYY_add(&z1,&z1,&t0);
+ FP16_YYY_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP16_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP16_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP16_YYY_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP16_YYY_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP16_YYY_norm(&t0);
+ FP16_YYY_norm(&t1);
+
+ FP16_YYY_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP16_YYY_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP8_YYY_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP8_YYY_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP8_YYY_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP8_YYY_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP16_YYY_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP16_YYY_neg(&t1,&t0); // -(xc.yc)
+
+ FP16_YYY_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP16_YYY_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP16_YYY_times_i(&t0); // i.(xc.yc)
+ FP16_YYY_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP16_YYY_norm(&z3);
+ FP16_YYY_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP16_YYY_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP48_YYY_smul(w,y);
+ return;
+ }
+// dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
FP16_YYY_copy(&z3,&(w->b));
FP16_YYY_mul(&z0,&(w->a),&(y->a));
@@ -306,7 +407,6 @@
FP16_YYY_add(&z2,&z2,&t0); // z2=z2-z0
FP16_YYY_add(&t0,&(w->a),&(w->c));
-
FP16_YYY_norm(&t0);
FP16_YYY_norm(&z3);
@@ -315,10 +415,8 @@
FP16_YYY_times_i(&z3);
FP16_YYY_add(&(w->a),&z0,&z3);
- }
-
- if (type==M_TYPE)
- { // y->b is zero
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
FP16_YYY_mul(&z0,&(w->a),&(y->a));
FP16_YYY_add(&t0,&(w->a),&(w->b));
FP16_YYY_norm(&t0);
@@ -334,7 +432,6 @@
FP16_YYY_add(&z1,&z1,&t0); // z1=z1-z0
FP16_YYY_copy(&(w->b),&z1);
-
FP16_YYY_copy(&z2,&t0);
FP16_YYY_add(&t0,&(w->a),&(w->c));
@@ -358,10 +455,113 @@
FP16_YYY_norm(&z3);
FP16_YYY_times_i(&z3);
FP16_YYY_add(&(w->a),&z0,&z3);
+#endif
}
+ w->type=FP_DENSE;
FP48_YYY_norm(w);
}
+/* 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 */
+void FP48_YYY_smul(FP48_YYY *w,FP48_YYY *y)
+{
+ FP8_YYY w1,w2,w3,ta,tb,tc,td,te,t;
+
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP8_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP8_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP8_YYY_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
+
+ FP8_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP8_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP8_YYY_add(&t,&w1,&w2);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP8_YYY_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP8_YYY_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP8_YYY_add(&t,&w1,&w3);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
+
+ FP8_YYY_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP8_YYY_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP8_YYY_add(&t,&w2,&w3);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
+
+ FP8_YYY_times_i(&w2);
+ FP8_YYY_add(&w1,&w1,&w2);
+ FP16_YYY_from_FP8s(&(w->a),&w1,&tc);
+ FP16_YYY_from_FP8s(&(w->b),&td,&te); // only norm these 2
+ FP16_YYY_from_FP8(&(w->c),&w3);
+
+ FP16_YYY_norm(&(w->a));
+ FP16_YYY_norm(&(w->b));
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP8_YYY_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP8_YYY_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP8_YYY_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
+
+ FP8_YYY_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP8_YYY_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP8_YYY_add(&t,&w1,&w2);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP8_YYY_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP8_YYY_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP8_YYY_add(&t,&w1,&w3);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
+
+ FP8_YYY_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP8_YYY_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP8_YYY_norm(&ta);
+ FP8_YYY_norm(&tb);
+ FP8_YYY_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP8_YYY_add(&t,&w2,&w3);
+ FP8_YYY_neg(&t,&t);
+ FP8_YYY_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
+
+ FP8_YYY_times_i(&w2);
+ FP8_YYY_add(&w1,&w1,&w2);
+ FP16_YYY_from_FP8s(&(w->a),&w1,&tc);
+
+ FP8_YYY_times_i(&w3);
+ FP8_YYY_norm(&w3);
+ FP16_YYY_from_FP8H(&(w->b),&w3);
+
+ FP8_YYY_norm(&te);
+ FP8_YYY_times_i(&te);
+ FP16_YYY_from_FP8s(&(w->c),&te,&td);
+
+ FP16_YYY_norm(&(w->a));
+ FP16_YYY_norm(&(w->c));
+#endif
+
+ w->type=FP_SPARSE;
+}
+
+
/* Set w=1/x */
/* SU= 600 */
void FP48_YYY_inv(FP48_YYY *w,FP48_YYY *x)
@@ -399,7 +599,7 @@
FP16_YYY_mul(&(w->a),&f0,&f3);
FP16_YYY_mul(&(w->b),&f1,&f3);
FP16_YYY_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -724,8 +924,8 @@
FP16_YYY_qmul(&(w->b),&(w->b),f); FP16_YYY_times_i4(&(w->b)); FP16_YYY_times_i2(&(w->b));
FP16_YYY_qmul(&(w->c),&(w->c),&f2); FP16_YYY_times_i4(&(w->c)); FP16_YYY_times_i4(&(w->c)); FP16_YYY_times_i4(&(w->c));
-
}
+ w->type=FP_DENSE;
}
/* SU= 8 */
@@ -1028,4 +1228,6 @@
FP16_YYY_cmove(&(f->a),&(g->a),d);
FP16_YYY_cmove(&(f->b),&(g->b),d);
FP16_YYY_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
diff --git a/version3/c/fp48.h b/version3/c/fp48.h
index 75065b5..e0a1f80 100644
--- a/version3/c/fp48.h
+++ b/version3/c/fp48.h
@@ -12,6 +12,7 @@
FP16_YYY a; /**< first part of FP12 */
FP16_YYY b; /**< second part of FP12 */
FP16_YYY c; /**< third part of FP12 */
+ int type;
} FP48_YYY;
extern const BIG_XXX Fra_YYY; /**< real part of BN curve Frobenius Constant */
@@ -82,15 +83,20 @@
@param y FP48 instance
*/
extern void FP48_YYY_sqr(FP48_YYY *x,FP48_YYY *y);
-/** @brief Fast multiplication of an FP48 by an FP48 that arises from an ATE pairing line function
+/** @brief Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP48 instance, on exit = x*y
@param y FP48 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP48_YYY_smul(FP48_YYY *x,FP48_YYY *y,int t);
-/** @brief Multiplication of two FP48s
+extern void FP48_YYY_smul(FP48_YYY *x,FP48_YYY *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP48 instance, on exit = x*y
+ @param y FP48 instance, of special form
+ */
+extern void FP48_YYY_ssmul(FP48_YYY *x,FP48_YYY *y);
+/** @brief Full unconditional Multiplication of two FP24s
*
@param x FP48 instance, on exit = x*y
@param y FP48 instance, the multiplier
diff --git a/version3/c/pair.c b/version3/c/pair.c
index 57cad56..f88a3d5 100644
--- a/version3/c/pair.c
+++ b/version3/c/pair.c
@@ -131,6 +131,140 @@
}
FP12_YYY_from_FP4s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
+}
+
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n)
+{
+ BIG_XXX x;
+ BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+ BIG_XXX_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+ BIG_XXX_inc(n,2);
+#else
+ BIG_XXX_dec(n,2);
+#endif
+
+#else
+ BIG_XXX_copy(n,x);
+#endif
+
+ BIG_XXX_norm(n);
+ BIG_XXX_pmul(n3,n,3);
+ BIG_XXX_norm(n3);
+
+ return BIG_XXX_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP12 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void PAIR_ZZZ_initmp(FP12_YYY r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP12_YYY_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void PAIR_ZZZ_miller(FP12_YYY *res,FP12_YYY r[])
+{
+ int i;
+ FP12_YYY_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP12_YYY_sqr(res,res);
+ FP12_YYY_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP12_YYY_conj(res,res);
+#endif
+ FP12_YYY_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void PAIR_ZZZ_another(FP12_YYY r[],ECP2_ZZZ* PV,ECP_ZZZ* QV)
+{
+ int i,j,nb,bt;
+ BIG_XXX x,n,n3;
+ FP12_YYY lv,lv2;
+ ECP2_ZZZ A,NP,P;
+ ECP_ZZZ Q;
+ FP_YYY Qx,Qy;
+#if PAIRING_FRIENDLY_ZZZ==BN
+ ECP2_ZZZ K;
+ FP2_YYY X;
+ FP_YYY_rcopy(&Qx,Fra_YYY);
+ FP_YYY_rcopy(&Qy,Frb_YYY);
+ FP2_YYY_from_FPs(&X,&Qx,&Qy);
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+ FP2_YYY_inv(&X,&X);
+ FP2_YYY_norm(&X);
+#endif
+#endif
+
+ nb=PAIR_ZZZ_nbits(n3,n);
+
+ ECP2_ZZZ_copy(&P,PV);
+ ECP_ZZZ_copy(&Q,QV);
+
+ ECP2_ZZZ_affine(&P);
+ ECP_ZZZ_affine(&Q);
+
+ FP_YYY_copy(&Qx,&(Q.x));
+ FP_YYY_copy(&Qy,&(Q.y));
+
+ ECP2_ZZZ_copy(&A,&P);
+ ECP2_ZZZ_copy(&NP,&P); ECP2_ZZZ_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ }
+ FP12_YYY_ssmul(&r[i],&lv);
+ }
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ ECP2_ZZZ_neg(&A);
+#endif
+
+ ECP2_ZZZ_copy(&K,&P);
+ ECP2_ZZZ_frob(&K,&X);
+ PAIR_ZZZ_line(&lv,&A,&K,&Qx,&Qy);
+ ECP2_ZZZ_frob(&K,&X);
+ ECP2_ZZZ_neg(&K);
+ PAIR_ZZZ_line(&lv2,&A,&K,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(&r[0],&lv);
+
+#endif
}
/* Optimal R-ate pairing r=e(P,Q) */
@@ -142,7 +276,7 @@
int i,nb,bt;
ECP2_ZZZ A,NP,P;
ECP_ZZZ Q;
- FP12_YYY lv;
+ FP12_YYY lv,lv2;
#if PAIRING_FRIENDLY_ZZZ==BN
ECP2_ZZZ KA;
FP2_YYY X;
@@ -157,22 +291,7 @@
#endif
#endif
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
-
-#if PAIRING_FRIENDLY_ZZZ==BN
- BIG_XXX_pmul(n,x,6);
-#if SIGN_OF_X_ZZZ==POSITIVEX
- BIG_XXX_inc(n,2);
-#else
- BIG_XXX_dec(n,2);
-#endif
-#else
- BIG_XXX_copy(n,x);
-#endif
-
- BIG_XXX_norm(n);
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP2_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -187,26 +306,25 @@
ECP2_ZZZ_copy(&NP,&P); ECP2_ZZZ_neg(&NP);
FP12_YYY_one(r);
- nb=BIG_XXX_nbits(n3); //n
/* Main Miller Loop */
for (i=nb-2; i>=1; i--) //0
{
- FP12_YYY_sqr(r,r);
+ FP12_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
-
- PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
}
- if (bt==-1)
- {
- PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- }
+ if (bt==-1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ }
+ FP12_YYY_ssmul(r,&lv);
}
@@ -217,17 +335,19 @@
/* R-ate fixup required for BN curves */
#if PAIRING_FRIENDLY_ZZZ==BN
- ECP2_ZZZ_copy(&KA,&P);
- ECP2_ZZZ_frob(&KA,&X);
+
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_ZZZ_neg(&A);
#endif
+
+ ECP2_ZZZ_copy(&KA,&P);
+ ECP2_ZZZ_frob(&KA,&X);
PAIR_ZZZ_line(&lv,&A,&KA,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_ZZZ_frob(&KA,&X);
ECP2_ZZZ_neg(&KA);
- PAIR_ZZZ_line(&lv,&A,&KA,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&KA,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
#endif
}
@@ -239,7 +359,7 @@
int i,nb,bt;
ECP2_ZZZ A,B,NP,NR,P,R;
ECP_ZZZ Q,S;
- FP12_YYY lv;
+ FP12_YYY lv,lv2;
#if PAIRING_FRIENDLY_ZZZ==BN
FP2_YYY X;
ECP2_ZZZ K;
@@ -253,23 +373,7 @@
FP2_YYY_norm(&X);
#endif
#endif
-
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
-
-#if PAIRING_FRIENDLY_ZZZ==BN
- BIG_XXX_pmul(n,x,6);
-#if SIGN_OF_X_ZZZ==POSITIVEX
- BIG_XXX_inc(n,2);
-#else
- BIG_XXX_dec(n,2);
-#endif
-#else
- BIG_XXX_copy(n,x);
-#endif
-
- BIG_XXX_norm(n);
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP2_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -295,38 +399,32 @@
ECP2_ZZZ_copy(&NP,&P); ECP2_ZZZ_neg(&NP);
ECP2_ZZZ_copy(&NR,&R); ECP2_ZZZ_neg(&NR);
-
FP12_YYY_one(r);
- nb=BIG_XXX_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP12_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&B,&Sx,&Sy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
- PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&R,&Sx,&Sy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
}
-
- if (bt==-1)
- {
+ if (bt==-1)
+ {
PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- }
+ PAIR_ZZZ_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
+ }
}
@@ -346,24 +444,21 @@
ECP2_ZZZ_copy(&K,&P);
ECP2_ZZZ_frob(&K,&X);
-
PAIR_ZZZ_line(&lv,&A,&K,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_ZZZ_frob(&K,&X);
ECP2_ZZZ_neg(&K);
- PAIR_ZZZ_line(&lv,&A,&K,&Qx,&Qy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&K,&Qx,&Qy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
ECP2_ZZZ_copy(&K,&R);
ECP2_ZZZ_frob(&K,&X);
-
PAIR_ZZZ_line(&lv,&B,&K,&Sx,&Sy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_ZZZ_frob(&K,&X);
ECP2_ZZZ_neg(&K);
- PAIR_ZZZ_line(&lv,&B,&K,&Sx,&Sy);
- FP12_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
+ PAIR_ZZZ_line(&lv2,&B,&K,&Sx,&Sy);
+ FP12_YYY_smul(&lv,&lv2);
+ FP12_YYY_ssmul(r,&lv);
#endif
}
diff --git a/version3/c/pair.h b/version3/c/pair.h
index 81b710c..f03b329 100644
--- a/version3/c/pair.h
+++ b/version3/c/pair.h
@@ -42,6 +42,16 @@
extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
/* Pairing function prototypes */
+
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP12 products of line functions
+ @param PV ECP2 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_another(FP12_YYY r[],ECP2_ZZZ* PV,ECP_ZZZ* QV);
+
/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
*
@param r FP12 result of the pairing calculation e(P,Q)
@@ -98,6 +108,29 @@
*/
extern int PAIR_ZZZ_GTmember(FP12_YYY *x);
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+ */
+extern int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP12 array, to be initialised to 1
+
+ */
+extern void PAIR_ZZZ_initmp(FP12_YYY r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP12 result
+ @param r FP12 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_ZZZ_miller(FP12_YYY *res,FP12_YYY r[]);
#endif
diff --git a/version3/c/pair192.c b/version3/c/pair192.c
index 2e4f4e0..d543bbf 100644
--- a/version3/c/pair192.c
+++ b/version3/c/pair192.c
@@ -132,6 +132,100 @@
}
FP24_YYY_from_FP8s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n)
+{
+ BIG_XXX x;
+ BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+ BIG_XXX_copy(n,x);
+ BIG_XXX_norm(n);
+ BIG_XXX_pmul(n3,n,3);
+ BIG_XXX_norm(n3);
+
+ return BIG_XXX_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP24 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void PAIR_ZZZ_initmp(FP24_YYY r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP24_YYY_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void PAIR_ZZZ_miller(FP24_YYY *res,FP24_YYY r[])
+{
+ int i;
+ FP24_YYY_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP24_YYY_sqr(res,res);
+ FP24_YYY_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP24_YYY_conj(res,res);
+#endif
+ FP24_YYY_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void PAIR_ZZZ_another(FP24_YYY r[],ECP4_ZZZ* PV,ECP_ZZZ* QV)
+{
+ int i,j,nb,bt;
+ BIG_XXX x,n,n3;
+ FP24_YYY lv,lv2;
+ ECP4_ZZZ A,NP,P;
+ ECP_ZZZ Q;
+ FP_YYY Qx,Qy;
+
+ nb=PAIR_ZZZ_nbits(n3,n);
+
+ ECP4_ZZZ_copy(&P,PV);
+ ECP_ZZZ_copy(&Q,QV);
+
+ ECP4_ZZZ_affine(&P);
+ ECP_ZZZ_affine(&Q);
+
+ FP_YYY_copy(&Qx,&(Q.x));
+ FP_YYY_copy(&Qy,&(Q.y));
+
+ ECP4_ZZZ_copy(&A,&P);
+ ECP4_ZZZ_copy(&NP,&P); ECP4_ZZZ_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP24_YYY_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP24_YYY_smul(&lv,&lv2);
+ }
+ FP24_YYY_ssmul(&r[i],&lv);
+ }
}
/* Optimal R-ate pairing r=e(P,Q) */
@@ -139,17 +233,12 @@
{
BIG_XXX x,n,n3;
FP_YYY Qx,Qy;
- int i,j,nb,bt;
+ int i,nb,bt;
ECP4_ZZZ A,NP,P;
ECP_ZZZ Q;
- FP24_YYY lv;
+ FP24_YYY lv,lv2;
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
-
- BIG_XXX_copy(n,x);
-
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP4_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -165,29 +254,25 @@
ECP4_ZZZ_copy(&NP,&P); ECP4_ZZZ_neg(&NP);
FP24_YYY_one(r);
- nb=BIG_XXX_nbits(n3); // n3
- j=0;
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
- j++;
FP24_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+ bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // BIG_bit(n,i);
if (bt==1)
{
- PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP24_YYY_smul(&lv,&lv2);
}
if (bt==-1)
{
- PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP24_YYY_smul(&lv,&lv2);
}
-
+ FP24_YYY_ssmul(r,&lv);
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
@@ -204,13 +289,8 @@
int i,nb,bt;
ECP4_ZZZ A,B,NP,NR,P,R;
ECP_ZZZ Q,S;
- FP24_YYY lv;
-
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
- BIG_XXX_copy(n,x);
-
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ FP24_YYY lv,lv2;
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP4_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -224,7 +304,6 @@
ECP4_ZZZ_affine(&R);
ECP_ZZZ_affine(&S);
-
FP_YYY_copy(&Qx,&(Q.x));
FP_YYY_copy(&Qy,&(Q.y));
@@ -236,35 +315,31 @@
ECP4_ZZZ_copy(&NP,&P); ECP4_ZZZ_neg(&NP);
ECP4_ZZZ_copy(&NR,&R); ECP4_ZZZ_neg(&NR);
-
FP24_YYY_one(r);
- nb=BIG_XXX_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
- FP24_YYY_sqr(r,r);
+ FP24_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&B,&Sx,&Sy);
+ FP24_YYY_smul(&lv,&lv2);
+ FP24_YYY_ssmul(r,&lv);
- PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&R,&Sx,&Sy);
+ FP24_YYY_smul(&lv,&lv2);
+ FP24_YYY_ssmul(r,&lv);
}
if (bt==-1)
{
PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
- FP24_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP24_YYY_smul(&lv,&lv2);
+ FP24_YYY_ssmul(r,&lv);
}
}
diff --git a/version3/c/pair192.h b/version3/c/pair192.h
index 2e50d51..a4fa7d3 100644
--- a/version3/c/pair192.h
+++ b/version3/c/pair192.h
@@ -17,6 +17,16 @@
extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
/* Pairing function prototypes */
+
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP24 products of line functions
+ @param PV ECP4 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_another(FP24_YYY r[],ECP4_ZZZ* PV,ECP_ZZZ* QV);
+
/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
*
@param r FP24 result of the pairing calculation e(P,Q)
@@ -73,5 +83,30 @@
*/
extern int PAIR_ZZZ_GTmember(FP24_YYY *x);
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+
+ */
+extern int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP24 array, to be initialised to 1
+
+ */
+extern void PAIR_ZZZ_initmp(FP24_YYY r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP24 result
+ @param r FP24 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_ZZZ_miller(FP24_YYY *res,FP24_YYY r[]);
+
#endif
diff --git a/version3/c/pair256.c b/version3/c/pair256.c
index 2f71691..f378315 100644
--- a/version3/c/pair256.c
+++ b/version3/c/pair256.c
@@ -129,6 +129,100 @@
}
FP48_YYY_from_FP16s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n)
+{
+ BIG_XXX x;
+ BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
+
+ BIG_XXX_copy(n,x);
+ BIG_XXX_norm(n);
+ BIG_XXX_pmul(n3,n,3);
+ BIG_XXX_norm(n3);
+
+ return BIG_XXX_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP24 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void PAIR_ZZZ_initmp(FP48_YYY r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP48_YYY_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void PAIR_ZZZ_miller(FP48_YYY *res,FP48_YYY r[])
+{
+ int i;
+ FP48_YYY_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP48_YYY_sqr(res,res);
+ FP48_YYY_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP48_YYY_conj(res,res);
+#endif
+ FP48_YYY_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void PAIR_ZZZ_another(FP48_YYY r[],ECP8_ZZZ* PV,ECP_ZZZ* QV)
+{
+ int i,j,nb,bt;
+ BIG_XXX x,n,n3;
+ FP48_YYY lv,lv2;
+ ECP8_ZZZ A,NP,P;
+ ECP_ZZZ Q;
+ FP_YYY Qx,Qy;
+
+ nb=PAIR_ZZZ_nbits(n3,n);
+
+ ECP8_ZZZ_copy(&P,PV);
+ ECP_ZZZ_copy(&Q,QV);
+
+ ECP8_ZZZ_affine(&P);
+ ECP_ZZZ_affine(&Q);
+
+ FP_YYY_copy(&Qx,&(Q.x));
+ FP_YYY_copy(&Qy,&(Q.y));
+
+ ECP8_ZZZ_copy(&A,&P);
+ ECP8_ZZZ_copy(&NP,&P); ECP8_ZZZ_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP48_YYY_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP48_YYY_smul(&lv,&lv2);
+ }
+ FP48_YYY_ssmul(&r[i],&lv);
+ }
}
/* Optimal R-ate pairing r=e(P,Q) */
@@ -136,17 +230,12 @@
{
BIG_XXX x,n,n3;
FP_YYY Qx,Qy;
- int i,j,nb,bt;
+ int i,nb,bt;
ECP8_ZZZ A,NP,P;
ECP_ZZZ Q;
- FP48_YYY lv;
+ FP48_YYY lv,lv2;
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
-
- BIG_XXX_copy(n,x);
-
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP8_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -162,29 +251,25 @@
ECP8_ZZZ_copy(&NP,&P); ECP8_ZZZ_neg(&NP);
FP48_YYY_one(r);
- nb=BIG_XXX_nbits(n3); // n3
- j=0;
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
- j++;
FP48_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+ bt= BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // BIG_bit(n,i);
if (bt==1)
{
- PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&P,&Qx,&Qy);
+ FP48_YYY_smul(&lv,&lv2);
}
if (bt==-1)
{
- PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP48_YYY_smul(&lv,&lv2);
}
-
+ FP48_YYY_ssmul(r,&lv);
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
@@ -201,13 +286,9 @@
int i,nb,bt;
ECP8_ZZZ A,B,NP,NR,P,R;
ECP_ZZZ Q,S;
- FP48_YYY lv;
+ FP48_YYY lv,lv2;
- BIG_XXX_rcopy(x,CURVE_Bnx_ZZZ);
- BIG_XXX_copy(n,x);
-
- BIG_XXX_pmul(n3,n,3);
- BIG_XXX_norm(n3);
+ nb=PAIR_ZZZ_nbits(n3,n);
ECP8_ZZZ_copy(&P,P1);
ECP_ZZZ_copy(&Q,Q1);
@@ -232,35 +313,31 @@
ECP8_ZZZ_copy(&NP,&P); ECP8_ZZZ_neg(&NP);
ECP8_ZZZ_copy(&NR,&R); ECP8_ZZZ_neg(&NR);
-
FP48_YYY_one(r);
- nb=BIG_XXX_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP48_YYY_sqr(r,r);
PAIR_ZZZ_line(&lv,&A,&A,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&B,&Sx,&Sy);
+ FP48_YYY_smul(&lv,&lv2);
+ FP48_YYY_ssmul(r,&lv);
- PAIR_ZZZ_line(&lv,&B,&B,&Sx,&Sy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i);
+ bt=BIG_XXX_bit(n3,i)-BIG_XXX_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_ZZZ_line(&lv,&A,&P,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_ZZZ_line(&lv,&B,&R,&Sx,&Sy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&R,&Sx,&Sy);
+ FP48_YYY_smul(&lv,&lv2);
+ FP48_YYY_ssmul(r,&lv);
}
if (bt==-1)
{
PAIR_ZZZ_line(&lv,&A,&NP,&Qx,&Qy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- PAIR_ZZZ_line(&lv,&B,&NR,&Sx,&Sy);
- FP48_YYY_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_ZZZ_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP48_YYY_smul(&lv,&lv2);
+ FP48_YYY_ssmul(r,&lv);
}
}
diff --git a/version3/c/pair256.h b/version3/c/pair256.h
index d270f76..1971863 100644
--- a/version3/c/pair256.h
+++ b/version3/c/pair256.h
@@ -17,6 +17,16 @@
extern const BIG_XXX CURVE_BB_ZZZ[4][4]; /**< BN curve constant for GS decomposition */
/* Pairing function prototypes */
+
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP48 products of line functions
+ @param PV ECP8 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_ZZZ_another(FP48_YYY r[],ECP8_ZZZ* PV,ECP_ZZZ* QV);
+
/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
*
@param r FP48 result of the pairing calculation e(P,Q)
@@ -73,5 +83,28 @@
*/
extern int PAIR_ZZZ_GTmember(FP48_YYY *x);
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+ */
+extern int PAIR_ZZZ_nbits(BIG_XXX n3,BIG_XXX n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP48 array, to be initialised to 1
+
+ */
+extern void PAIR_ZZZ_initmp(FP48_YYY r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP48 result
+ @param r FP48 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_ZZZ_miller(FP48_YYY *res,FP48_YYY r[]);
#endif
diff --git a/version3/cpp/amcl.h b/version3/cpp/amcl.h
index b9cfea2..c05e0c1 100644
--- a/version3/cpp/amcl.h
+++ b/version3/cpp/amcl.h
@@ -52,6 +52,12 @@
#define D_TYPE 0
#define M_TYPE 1
+#define FP_ZERO 0
+#define FP_UNITY 1
+#define FP_SPARSER 2
+#define FP_SPARSE 3
+#define FP_DENSE 4
+
/**
* @brief SHA256 hash function instance */
typedef struct
diff --git a/version3/cpp/benchtest_all.cpp b/version3/cpp/benchtest_all.cpp
index 9589f98..6044068 100644
--- a/version3/cpp/benchtest_all.cpp
+++ b/version3/cpp/benchtest_all.cpp
@@ -949,7 +949,7 @@
RSA_KEY_PAIR(RNG,65537,&priv,&pub,NULL,NULL);
iterations++;
elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
- } while (elapsed<MIN_TIME || iterations<MIN_ITERS);
+ } while (elapsed<MIN_TIME || iterations<1);
elapsed=1000.0*elapsed/iterations;
printf("RSA gen - %8d iterations ",iterations);
printf(" %8.2lf ms per iteration\n",elapsed);
diff --git a/version3/cpp/bls.cpp b/version3/cpp/bls.cpp
index ded8b3c..2167e6d 100644
--- a/version3/cpp/bls.cpp
+++ b/version3/cpp/bls.cpp
@@ -73,7 +73,6 @@
}
/* Verify signature given message m, the signature SIG, and the public key W */
-
int ZZZ::BLS_VERIFY(octet *SIG,char *m,octet *W)
{
FP12 v;
@@ -84,8 +83,19 @@
ECP2_generator(&G);
ECP2_fromOctet(&PK,W);
ECP_neg(&D);
- PAIR_double_ate(&v,&G,&D,&PK,&HM);
- PAIR_fexp(&v);
+
+// Use new multi-pairing mechanism
+
+ FP12 r[ATE_BITS_ZZZ];
+ PAIR_initmp(r);
+ PAIR_another(r,&G,&D);
+ PAIR_another(r,&PK,&HM);
+ PAIR_miller(&v,r);
+
+//.. or alternatively
+// PAIR_double_ate(&v,&G,&D,&PK,&HM);
+
+ PAIR_fexp(&v);
if (FP12_isunity(&v)) return BLS_OK;
return BLS_FAIL;
}
diff --git a/version3/cpp/bls192.cpp b/version3/cpp/bls192.cpp
index 683405c..0a8a63c 100644
--- a/version3/cpp/bls192.cpp
+++ b/version3/cpp/bls192.cpp
@@ -73,7 +73,6 @@
}
/* Verify signature given message m, the signature SIG, and the public key W */
-
int ZZZ::BLS_VERIFY(octet *SIG,char *m,octet *W)
{
FP24 v;
@@ -84,7 +83,18 @@
ECP4_generator(&G);
ECP4_fromOctet(&PK,W);
ECP_neg(&D);
- PAIR_double_ate(&v,&G,&D,&PK,&HM);
+
+// Use new multi-pairing mechanism
+
+ FP24 r[ATE_BITS_ZZZ];
+ PAIR_initmp(r);
+ PAIR_another(r,&G,&D);
+ PAIR_another(r,&PK,&HM);
+ PAIR_miller(&v,r);
+
+//.. or alternatively
+// PAIR_double_ate(&v,&G,&D,&PK,&HM);
+
PAIR_fexp(&v);
if (FP24_isunity(&v)) return BLS_OK;
return BLS_FAIL;
diff --git a/version3/cpp/bls256.cpp b/version3/cpp/bls256.cpp
index 24aacc2..77afbc7 100644
--- a/version3/cpp/bls256.cpp
+++ b/version3/cpp/bls256.cpp
@@ -73,7 +73,6 @@
}
/* Verify signature of message m, the signature SIG, and the public key W */
-
int ZZZ::BLS_VERIFY(octet *SIG,char *m,octet *W)
{
FP48 v;
@@ -84,7 +83,16 @@
ECP8_generator(&G);
ECP8_fromOctet(&PK,W);
ECP_neg(&D);
- PAIR_double_ate(&v,&G,&D,&PK,&HM);
+// Use new multi-pairing mechanism
+
+ FP48 r[ATE_BITS_ZZZ];
+ PAIR_initmp(r);
+ PAIR_another(r,&G,&D);
+ PAIR_another(r,&PK,&HM);
+ PAIR_miller(&v,r);
+
+//.. or alternatively
+// PAIR_double_ate(&v,&G,&D,&PK,&HM);
PAIR_fexp(&v);
if (FP48_isunity(&v)) return BLS_OK;
return BLS_FAIL;
diff --git a/version3/cpp/config16.py b/version3/cpp/config16.py
index f683b38..4f842d5 100644
--- a/version3/cpp/config16.py
+++ b/version3/cpp/config16.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("g++ -O3 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd="B"+tb+"_"+base
fnameh="config_big_"+bd+".h"
os.system(copytext+" config_big.h "+fnameh)
@@ -108,6 +108,7 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
fnamec="big_"+bd+".cpp"
@@ -196,8 +197,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
fnamec="ecp2_"+tc+".cpp"
@@ -291,7 +294,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -301,22 +304,23 @@
# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
+# ate bits is number of bits in Ate parameter (from romgen program)
# if pairing friendly. M or D type twist, and sign of the family parameter x
if x==1:
- curveset("256","F25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F25519","ED25519","32","13","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","F256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F256PME","NUMS256E","32","13","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==4:
- curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","13","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
# rsaset(big,ring,big_length_bytes,bits_in_base,multiplier)
diff --git a/version3/cpp/config32.py b/version3/cpp/config32.py
index c4c1758..750cc95 100644
--- a/version3/cpp/config32.py
+++ b/version3/cpp/config32.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("g++ -O3 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd="B"+tb+"_"+base
fnameh="config_big_"+bd+".h"
os.system(copytext+" config_big.h "+fnameh)
@@ -108,6 +108,8 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
+
fnamec="big_"+bd+".cpp"
fnameh="big_"+bd+".h"
@@ -196,8 +198,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
fnamec="ecp2_"+tc+".cpp"
@@ -276,8 +280,10 @@
os.system(copytext+" fp24.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
fnamec="ecp4_"+tc+".cpp"
@@ -383,8 +389,10 @@
os.system(copytext+" fp48.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
@@ -489,7 +497,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -500,96 +508,97 @@
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
# if pairing friendly. M or D type twist, and sign of the family parameter x
+# ate bits is number of bits in Ate parameter (from romgen program)
# curve security is AES equiavlent, rounded up.
if x==1:
- curveset("256","F25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F25519","ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","F25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+ curveset("256","F25519","C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","NIST256","NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==4:
- curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","BRAINPOOL","BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==5:
- curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","ANSSI","ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==6:
- curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("336","HIFIVE","HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==7:
- curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("448","GOLDILOCKS","GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==8:
- curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+ curveset("384","NIST384","NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==9:
- curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("416","C41417","C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==10:
- curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("528","NIST521","NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==11:
- curveset("256","F256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("256","F256PMW","NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==12:
- curveset("256","F256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F256PME","NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==13:
- curveset("384","F384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+ curveset("384","F384PM","NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==14:
- curveset("384","F384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("384","F384PM","NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==15:
- curveset("512","F512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("512","F512PM","NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==16:
- curveset("512","F512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("512","F512PM","NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==17:
- curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","SECP256K1","SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==18:
- curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("384","BLS383","BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("384","BLS381","BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("256","FP256BN","FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("512","FP512BN","FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("464","BLS461","BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("480","BLS24","BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("560","BLS48","BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/cpp/config64.py b/version3/cpp/config64.py
index 7087427..630e23a 100644
--- a/version3/cpp/config64.py
+++ b/version3/cpp/config64.py
@@ -72,7 +72,7 @@
replace(fnameh,"XXX",bd)
os.system("g++ -O3 -c "+fnamec)
-def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tb,tf,tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
bd="B"+tb+"_"+base
fnameh="config_big_"+bd+".h"
os.system(copytext+" config_big.h "+fnameh)
@@ -108,6 +108,7 @@
replace(fnameh,"@ST@",stw)
replace(fnameh,"@SX@",sx)
replace(fnameh,"@CS@",cs)
+ replace(fnameh,"@AB@",ab)
fnamec="big_"+bd+".cpp"
@@ -197,8 +198,10 @@
os.system(copytext+" fp12.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
fnamec="ecp2_"+tc+".cpp"
@@ -278,8 +281,10 @@
os.system(copytext+" fp24.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
fnamec="ecp4_"+tc+".cpp"
@@ -385,8 +390,10 @@
os.system(copytext+" fp48.h "+fnameh)
replace(fnamec,"YYY",tf)
replace(fnamec,"XXX",bd)
+ replace(fnamec,"ZZZ",tc)
replace(fnameh,"YYY",tf)
replace(fnameh,"XXX",bd)
+ replace(fnameh,"ZZZ",tc)
os.system("g++ -O3 -c "+fnamec)
@@ -489,7 +496,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,curve security)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# for each curve give names for big, field and curve. In many cases the latter two will be the same.
# Typically "big" is the size in bits, always a multiple of 8, "field" describes the modulus, and "curve" is the common name for the elliptic curve
# big_length_bytes is "big" divided by 8
@@ -500,95 +507,96 @@
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly)
# if pairing friendly. M or D type twist, and sign of the family parameter x
-# curve security is AES equiavlent, rounded up.
+# ate bits is number of bits in Ate parameter (from romgen program)
+# curve security is AES equivalent, rounded up.
if x==1:
- curveset("256","F25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F25519","ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==2:
- curveset("256","F25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","128")
+ curveset("256","F25519","C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","","","","128")
curve_selected=True
if x==3:
- curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","NIST256","NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==4:
- curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","BRAINPOOL","BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==5:
- curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","ANSSI","ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==6:
- curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("336","HIFIVE","HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==7:
- curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("448","GOLDILOCKS","GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==8:
- curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","192")
+ curveset("384","NIST384","NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==9:
- curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("416","C41417","C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==10:
- curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("528","NIST521","NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==11:
- curveset("256","F256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","128")
+ curveset("256","F256PMW","NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==12:
- curveset("256","F256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","128")
+ curveset("256","F256PME","NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","128")
curve_selected=True
if x==13:
- curveset("384","F384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","192")
+ curveset("384","F384PM","NUMS384W","48","56","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","192")
curve_selected=True
if x==14:
- curveset("384","F384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","192")
+ curveset("384","F384PM","NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","","","","192")
curve_selected=True
if x==15:
- curveset("512","F512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","256")
+ curveset("512","F512PM","NUMS512W","64","56","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","","","","256")
curve_selected=True
if x==16:
- curveset("512","F512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","256")
+ curveset("512","F512PM","NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","","","","256")
curve_selected=True
if x==17:
- curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","128")
+ curveset("256","SECP256K1","SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","","","","128")
curve_selected=True
if x==18:
- curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254","BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("256","BN254CX","BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("384","BLS383","BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("384","BLS381","BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("256","FP256BN","FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("512","FP512BN","FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("464","BLS461","BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("480","BLS24","BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("560","BLS48","BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
@@ -604,6 +612,7 @@
if x==27:
#256 is slower but may allow reuse of 256-bit BIGs used for elliptic curve
#512 is faster.. but best is 1024
+ #rsaset("960","RSA15360","120","58","16")
rsaset("1024","RSA2048","128","58","2")
#rsaset("512","RSA2048","64","60","4")
#rsaset("256","RSA2048","32","56","8")
diff --git a/version3/cpp/config_curve.h b/version3/cpp/config_curve.h
index 4f905d5..d690d93 100644
--- a/version3/cpp/config_curve.h
+++ b/version3/cpp/config_curve.h
@@ -21,6 +21,8 @@
#define SEXTIC_TWIST_ZZZ @ST@
#define SIGN_OF_X_ZZZ @SX@
+#define ATE_BITS_ZZZ @AB@
+
#endif
@@ -40,7 +42,6 @@
#endif
-
namespace ZZZ_BIG=XXX;
namespace ZZZ_FP=YYY;
diff --git a/version3/cpp/fp12.cpp b/version3/cpp/fp12.cpp
index d7a3cb3..20ceea0 100644
--- a/version3/cpp/fp12.cpp
+++ b/version3/cpp/fp12.cpp
@@ -22,6 +22,7 @@
/* FP12 elements are of the form a+i.b+i^2.c */
#include "fp12_YYY.h"
+#include "config_curve_ZZZ.h"
using namespace XXX;
@@ -81,6 +82,7 @@
FP4_copy(&(w->a),&(x->a));
FP4_copy(&(w->b),&(x->b));
FP4_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP12 w=1 */
@@ -90,6 +92,7 @@
FP4_one(&(w->a));
FP4_zero(&(w->b));
FP4_zero(&(w->c));
+ w->type=FP_UNITY;
}
/* return 1 if x==y, else 0 */
@@ -118,6 +121,7 @@
FP4_copy(&(w->a),a);
FP4_zero(&(w->b));
FP4_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP12 from 3 FP4's */
@@ -127,6 +131,7 @@
FP4_copy(&(w->a),a);
FP4_copy(&(w->b),b);
FP4_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -167,6 +172,7 @@
FP4_add(&(w->b),&B,&(w->b));
FP4_add(&(w->c),&C,&(w->c));
+ w->type=FP_DENSE;
FP12_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -178,6 +184,12 @@
FP4 A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP12_copy(w,x);
+ return;
+ }
+
FP4_sqr(&A,&(x->a));
FP4_mul(&B,&(x->b),&(x->c));
FP4_add(&B,&B,&B);
@@ -209,78 +221,170 @@
FP4_add(&(w->b),&C,&D);
FP4_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
FP12_norm(w);
}
-/* FP12 full multiplication w=w*y */
+// Use FP12_mul when both multiplicands are dense
+// Use FP12smul when it is known that both multiplicands are line functions
+// Use FP12ssmul when it is suspected that one or both multiplicands could have some sparsity
-/* SU= 896 */
/* FP12 full multiplication w=w*y */
void YYY::FP12_mul(FP12 *w,FP12 *y)
{
- FP4 z0,z1,z2,z3,t0,t1;
+ FP4 z0,z1,z2,z3,t0,t1;
- FP4_mul(&z0,&(w->a),&(y->a));
- FP4_mul(&z2,&(w->b),&(y->b)); //
+ FP4_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
- FP4_add(&t0,&(w->a),&(w->b));
- FP4_add(&t1,&(y->a),&(y->b)); //
+ FP4_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP4_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP4_add(&t1,&(y->a),&(y->b)); // (ya+yb)
FP4_norm(&t0);
FP4_norm(&t1);
- FP4_mul(&z1,&t0,&t1);
- FP4_add(&t0,&(w->b),&(w->c));
- FP4_add(&t1,&(y->b),&(y->c)); //
+ FP4_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP4_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP4_add(&t1,&(y->b),&(y->c)); // (yb+yc)
FP4_norm(&t0);
FP4_norm(&t1);
- FP4_mul(&z3,&t0,&t1);
+ FP4_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP4_neg(&t0,&z0); // -(xa.ya)
+ FP4_neg(&t1,&z2); // -(xb.yb)
- FP4_neg(&t0,&z0);
- FP4_neg(&t1,&z2);
+ FP4_add(&z1,&z1,&t0);
+ FP4_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
- FP4_add(&z1,&z1,&t0); // z1=z1-z0
- FP4_add(&(w->b),&z1,&t1);
+ FP4_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP4_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
- FP4_add(&z3,&z3,&t1); // z3=z3-z2
- FP4_add(&z2,&z2,&t0); // z2=z2-z0
-
- FP4_add(&t0,&(w->a),&(w->c));
- FP4_add(&t1,&(y->a),&(y->c));
+ FP4_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP4_add(&t1,&(y->a),&(y->c)); // (ya+yc)
FP4_norm(&t0);
FP4_norm(&t1);
- FP4_mul(&t0,&t1,&t0);
- FP4_add(&z2,&z2,&t0);
+ FP4_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP4_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
- FP4_mul(&t0,&(w->c),&(y->c));
- FP4_neg(&t1,&t0);
+ FP4_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+ FP4_neg(&t1,&t0); // -(xc.yc)
- FP4_add(&(w->c),&z2,&t1);
- FP4_add(&z3,&z3,&t1);
- FP4_times_i(&t0);
- FP4_add(&(w->b),&(w->b),&t0);
+ FP4_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP4_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP4_times_i(&t0); // i.(xc.yc)
+ FP4_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
FP4_norm(&z3);
- FP4_times_i(&z3);
- FP4_add(&(w->a),&z0,&z3);
+ FP4_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP4_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
FP12_norm(w);
+ w->type=FP_DENSE;
}
-/* FP12 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void YYY::FP12_smul(FP12 *w,FP12 *y,int type)
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void YYY::FP12_ssmul(FP12 *w,FP12 *y)
{
- FP4 z0,z1,z2,z3,t0,t1;
+ FP4 z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP12_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
- if (type==D_TYPE)
- { // y->c is 0
+ if (y->type >= FP_SPARSE)
+ {
+ FP4_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP2_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP2_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP2_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP2_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP4_times_i(&z2);
+ }
+ else
+#endif
+ FP4_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP4_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP4_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP4_norm(&t0);
+ FP4_norm(&t1);
+
+ FP4_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP4_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP4_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP4_norm(&t0);
+ FP4_norm(&t1);
+
+ FP4_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP4_neg(&t0,&z0); // -(xa.ya)
+ FP4_neg(&t1,&z2); // -(xb.yb)
+
+ FP4_add(&z1,&z1,&t0);
+ FP4_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP4_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP4_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP4_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP4_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP4_norm(&t0);
+ FP4_norm(&t1);
+
+ FP4_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP4_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP2_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP2_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP2_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP2_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP4_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP4_neg(&t1,&t0); // -(xc.yc)
+
+ FP4_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP4_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP4_times_i(&t0); // i.(xc.yc)
+ FP4_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP4_norm(&z3);
+ FP4_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP4_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP12_smul(w,y);
+ return;
+ }
+ // dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
FP4_copy(&z3,&(w->b));
FP4_mul(&z0,&(w->a),&(y->a));
@@ -306,7 +410,6 @@
FP4_add(&z2,&z2,&t0); // z2=z2-z0
FP4_add(&t0,&(w->a),&(w->c));
-
FP4_norm(&t0);
FP4_norm(&z3);
@@ -315,10 +418,8 @@
FP4_times_i(&z3);
FP4_add(&(w->a),&z0,&z3);
- }
-
- if (type==M_TYPE)
- { // y->b is zero
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
FP4_mul(&z0,&(w->a),&(y->a));
FP4_add(&t0,&(w->a),&(w->b));
FP4_norm(&t0);
@@ -334,7 +435,6 @@
FP4_add(&z1,&z1,&t0); // z1=z1-z0
FP4_copy(&(w->b),&z1);
-
FP4_copy(&z2,&t0);
FP4_add(&t0,&(w->a),&(w->c));
@@ -358,10 +458,116 @@
FP4_norm(&z3);
FP4_times_i(&z3);
FP4_add(&(w->a),&z0,&z3);
+
+#endif
}
+ w->type=FP_DENSE;
FP12_norm(w);
}
+/* 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 */
+void YYY::FP12_smul(FP12 *w,FP12 *y)
+{
+ FP2 w1,w2,w3,ta,tb,tc,td,te,t;
+
+// if (type==D_TYPE)
+// {
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP2_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP2_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP2_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
+
+ FP2_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP2_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP2_add(&t,&w1,&w2);
+ FP2_neg(&t,&t);
+ FP2_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP2_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP2_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP2_add(&t,&w1,&w3);
+ FP2_neg(&t,&t);
+ FP2_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
+
+ FP2_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP2_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP2_add(&t,&w2,&w3);
+ FP2_neg(&t,&t);
+ FP2_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
+
+ FP2_mul_ip(&w2);
+ FP2_add(&w1,&w1,&w2);
+ FP4_from_FP2s(&(w->a),&w1,&tc);
+ FP4_from_FP2s(&(w->b),&td,&te); // only norm these 2
+ FP4_from_FP2(&(w->c),&w3);
+
+ FP4_norm(&(w->a));
+ FP4_norm(&(w->b));
+#endif
+// } else {
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP2_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP2_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP2_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
+
+ FP2_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP2_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP2_add(&t,&w1,&w2);
+ FP2_neg(&t,&t);
+ FP2_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP2_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP2_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP2_add(&t,&w1,&w3);
+ FP2_neg(&t,&t);
+ FP2_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
+
+ FP2_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP2_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP2_norm(&ta);
+ FP2_norm(&tb);
+ FP2_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP2_add(&t,&w2,&w3);
+ FP2_neg(&t,&t);
+ FP2_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
+
+ FP2_mul_ip(&w2);
+ FP2_add(&w1,&w1,&w2);
+ FP4_from_FP2s(&(w->a),&w1,&tc);
+
+ FP2_mul_ip(&w3);
+ FP2_norm(&w3);
+ FP4_from_FP2H(&(w->b),&w3);
+
+ FP2_norm(&te);
+ FP2_mul_ip(&te);
+ FP4_from_FP2s(&(w->c),&te,&td);
+
+ FP4_norm(&(w->a));
+ FP4_norm(&(w->c));
+#endif
+
+// }
+ w->type=FP_SPARSE;
+}
+
/* Set w=1/x */
/* SU= 600 */
void YYY::FP12_inv(FP12 *w,FP12 *x)
@@ -400,7 +606,7 @@
FP4_mul(&(w->a),&f0,&f3);
FP4_mul(&(w->b),&f1,&f3);
FP4_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -610,6 +816,7 @@
FP4_pmul(&(w->b),&(w->b),f);
FP4_pmul(&(w->c),&(w->c),&f2);
+ w->type=FP_DENSE;
}
/* SU= 8 */
@@ -715,11 +922,15 @@
FP_nres(&(g->c.b.b),b);
}
-/* Move b to a if d=1 */
+/* Move g to f
+if d=1 */
void YYY::FP12_cmove(FP12 *f,FP12 *g,int d)
{
FP4_cmove(&(f->a),&(g->a),d);
FP4_cmove(&(f->b),&(g->b),d);
FP4_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
+
diff --git a/version3/cpp/fp12.h b/version3/cpp/fp12.h
index 8157e8b..69bc87c 100644
--- a/version3/cpp/fp12.h
+++ b/version3/cpp/fp12.h
@@ -10,11 +10,19 @@
@brief FP12 Structure - towered over three FP4
*/
+#define FP12_ZERO 0
+#define FP12_ONE 1
+#define FP12_SPARSER 2
+#define FP12_SPARSE 3
+#define FP12_DENSE 4
+
+
typedef struct
{
FP4 a; /**< first part of FP12 */
FP4 b; /**< second part of FP12 */
FP4 c; /**< third part of FP12 */
+ int type;
} FP12;
extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
@@ -85,24 +93,33 @@
@param y FP12 instance
*/
extern void FP12_sqr(FP12 *x,FP12 *y);
-/** @brief Fast multiplication of an FP12 by an FP12 that arises from an ATE pairing line function
+/** @brief Fast multiplication of two sparse FP12s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP12 instance, on exit = x*y
@param y FP12 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP12_smul(FP12 *x,FP12 *y,int t);
-/** @brief Multiplication of two FP12s
+extern void FP12_smul(FP12 *x,FP12 *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP12 instance, on exit = x*y
+ @param y FP12 instance, of special form
+ */
+extern void FP12_ssmul(FP12 *x,FP12 *y);
+
+
+/** @brief Full unconditional Multiplication of two FP12s
*
@param x FP12 instance, on exit = x*y
@param y FP12 instance, the multiplier
*/
extern void FP12_mul(FP12 *x,FP12 *y);
+
/** @brief Inverting an FP12
*
@param x FP12 instance, on exit = 1/y
@param y FP12 instance
+ @param t D_TYPE or M_TYPE twist
*/
extern void FP12_inv(FP12 *x,FP12 *y);
/** @brief Raises an FP12 to the power of a BIG
diff --git a/version3/cpp/fp2.cpp b/version3/cpp/fp2.cpp
index 1eb2809..e8fcfaf 100644
--- a/version3/cpp/fp2.cpp
+++ b/version3/cpp/fp2.cpp
@@ -24,6 +24,11 @@
#include "fp2_YYY.h"
+//namespace YYY {
+//extern int fp2muls;
+//extern int fp2sqrs;
+//}
+
using namespace XXX;
/* test x==0 ? */
@@ -201,6 +206,8 @@
FP_norm(&(w->a));
FP_mul(&(w->a),&w1,&(w->a)); /* w->a#2 w->a=1 w1&w2=6 w1*w2=2 */
+
+// YYY::fp2sqrs++;
}
@@ -242,6 +249,7 @@
BIG_dnorm(A); FP_mod(w->a.g,A); w->a.XES=3;// may drift above 2p...
BIG_dnorm(E); FP_mod(w->b.g,E); w->b.XES=2;
+// YYY::fp2muls++;
}
/* output FP2 in hex format [a,b] */
diff --git a/version3/cpp/fp24.cpp b/version3/cpp/fp24.cpp
index 7c971e9..79cbdf8 100644
--- a/version3/cpp/fp24.cpp
+++ b/version3/cpp/fp24.cpp
@@ -17,11 +17,12 @@
under the License.
*/
-/* AMCL Fp^12 functions */
+/* AMCL Fp^24 functions */
/* SU=m, m is Stack Usage (no lazy )*/
/* FP24 elements are of the form a+i.b+i^2.c */
#include "fp24_YYY.h"
+#include "config_curve_ZZZ.h"
using namespace XXX;
@@ -81,6 +82,7 @@
FP8_copy(&(w->a),&(x->a));
FP8_copy(&(w->b),&(x->b));
FP8_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP24 w=1 */
@@ -89,7 +91,9 @@
{
FP8_one(&(w->a));
FP8_zero(&(w->b));
- FP8_zero(&(w->c));
+ FP8_zero(&(w->c));
+ w->type=FP_UNITY;
+
}
/* return 1 if x==y, else 0 */
@@ -118,6 +122,7 @@
FP8_copy(&(w->a),a);
FP8_zero(&(w->b));
FP8_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP24 from 3 FP8's */
@@ -127,6 +132,7 @@
FP8_copy(&(w->a),a);
FP8_copy(&(w->b),b);
FP8_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -166,6 +172,7 @@
FP8_add(&(w->c),&(w->c),&(w->c));
FP8_add(&(w->b),&B,&(w->b));
FP8_add(&(w->c),&C,&(w->c));
+ w->type=FP_DENSE;
FP24_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -178,6 +185,12 @@
FP8 A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP24_copy(w,x);
+ return;
+ }
+
FP8_sqr(&A,&(x->a));
FP8_mul(&B,&(x->b),&(x->c));
FP8_add(&B,&B,&B);
@@ -211,13 +224,19 @@
FP8_add(&(w->b),&C,&D);
FP8_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
+
FP24_norm(w);
}
-/* FP24 full multiplication w=w*y */
+// Use FP24_mul when both multiplicands are dense
+// Use FP24smul when it is known that both multiplicands are line functions
+// Use FP24ssmul when it is suspected that one or both multiplicands could have some sparsity
-/* SU= 896 */
/* FP24 full multiplication w=w*y */
void YYY::FP24_mul(FP24 *w,FP24 *y)
{
@@ -270,18 +289,105 @@
FP8_add(&(w->a),&z0,&z3);
FP24_norm(w);
+ w->type=FP_DENSE;
}
-/* FP24 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void YYY::FP24_smul(FP24 *w,FP24 *y,int type)
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void YYY::FP24_ssmul(FP24 *w,FP24 *y)
{
- FP8 z0,z1,z2,z3,t0,t1;
+ FP8 z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP24_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
- if (type==D_TYPE)
- { // y->c is 0
+ if (y->type >= FP_SPARSE)
+ {
+ FP8_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP4_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP4_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP4_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP4_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP8_times_i(&z2);
+ }
+ else
+#endif
+ FP8_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP8_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP8_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP8_norm(&t0);
+ FP8_norm(&t1);
+
+ FP8_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP8_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP8_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP8_norm(&t0);
+ FP8_norm(&t1);
+
+ FP8_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP8_neg(&t0,&z0); // -(xa.ya)
+ FP8_neg(&t1,&z2); // -(xb.yb)
+
+ FP8_add(&z1,&z1,&t0);
+ FP8_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP8_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP8_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP8_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP8_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP8_norm(&t0);
+ FP8_norm(&t1);
+
+ FP8_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP8_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP4_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP4_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP4_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP4_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP8_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP8_neg(&t1,&t0); // -(xc.yc)
+
+ FP8_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP8_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP8_times_i(&t0); // i.(xc.yc)
+ FP8_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP8_norm(&z3);
+ FP8_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP8_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP24_smul(w,y);
+ return;
+ }
+// dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
FP8_copy(&z3,&(w->b));
FP8_mul(&z0,&(w->a),&(y->a));
@@ -307,7 +413,6 @@
FP8_add(&z2,&z2,&t0); // z2=z2-z0
FP8_add(&t0,&(w->a),&(w->c));
-
FP8_norm(&t0);
FP8_norm(&z3);
@@ -316,10 +421,8 @@
FP8_times_i(&z3);
FP8_add(&(w->a),&z0,&z3);
- }
-
- if (type==M_TYPE)
- { // y->b is zero
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
FP8_mul(&z0,&(w->a),&(y->a));
FP8_add(&t0,&(w->a),&(w->b));
FP8_norm(&t0);
@@ -335,7 +438,6 @@
FP8_add(&z1,&z1,&t0); // z1=z1-z0
FP8_copy(&(w->b),&z1);
-
FP8_copy(&z2,&t0);
FP8_add(&t0,&(w->a),&(w->c));
@@ -359,10 +461,112 @@
FP8_norm(&z3);
FP8_times_i(&z3);
FP8_add(&(w->a),&z0,&z3);
+#endif
}
+ w->type=FP_DENSE;
FP24_norm(w);
}
+/* 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 */
+void YYY::FP24_smul(FP24 *w,FP24 *y)
+{
+ FP4 w1,w2,w3,ta,tb,tc,td,te,t;
+
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP4_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP4_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP4_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
+
+ FP4_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP4_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP4_add(&t,&w1,&w2);
+ FP4_neg(&t,&t);
+ FP4_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP4_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP4_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP4_add(&t,&w1,&w3);
+ FP4_neg(&t,&t);
+ FP4_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
+
+ FP4_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP4_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP4_add(&t,&w2,&w3);
+ FP4_neg(&t,&t);
+ FP4_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
+
+ FP4_times_i(&w2);
+ FP4_add(&w1,&w1,&w2);
+ FP8_from_FP4s(&(w->a),&w1,&tc);
+ FP8_from_FP4s(&(w->b),&td,&te); // only norm these 2
+ FP8_from_FP4(&(w->c),&w3);
+
+ FP8_norm(&(w->a));
+ FP8_norm(&(w->b));
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP4_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP4_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP4_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
+
+ FP4_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP4_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP4_add(&t,&w1,&w2);
+ FP4_neg(&t,&t);
+ FP4_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP4_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP4_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP4_add(&t,&w1,&w3);
+ FP4_neg(&t,&t);
+ FP4_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
+
+ FP4_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP4_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP4_norm(&ta);
+ FP4_norm(&tb);
+ FP4_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP4_add(&t,&w2,&w3);
+ FP4_neg(&t,&t);
+ FP4_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
+
+ FP4_times_i(&w2);
+ FP4_add(&w1,&w1,&w2);
+ FP8_from_FP4s(&(w->a),&w1,&tc);
+
+ FP4_times_i(&w3);
+ FP4_norm(&w3);
+ FP8_from_FP4H(&(w->b),&w3);
+
+ FP4_norm(&te);
+ FP4_times_i(&te);
+ FP8_from_FP4s(&(w->c),&te,&td);
+
+ FP8_norm(&(w->a));
+ FP8_norm(&(w->c));
+#endif
+
+ w->type=FP_SPARSE;
+}
+
/* Set w=1/x */
/* SU= 600 */
void YYY::FP24_inv(FP24 *w,FP24 *x)
@@ -400,7 +604,7 @@
FP8_mul(&(w->a),&f0,&f3);
FP8_mul(&(w->b),&f1,&f3);
FP8_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -659,6 +863,7 @@
FP8_qmul(&(w->b),&(w->b),f); FP8_times_i2(&(w->b));
FP8_qmul(&(w->c),&(w->c),&f2); FP8_times_i2(&(w->c)); FP8_times_i2(&(w->c));
}
+ w->type=FP_DENSE;
}
@@ -824,4 +1029,6 @@
FP8_cmove(&(f->a),&(g->a),d);
FP8_cmove(&(f->b),&(g->b),d);
FP8_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
diff --git a/version3/cpp/fp24.h b/version3/cpp/fp24.h
index d7a0fa0..41639f0 100644
--- a/version3/cpp/fp24.h
+++ b/version3/cpp/fp24.h
@@ -10,11 +10,19 @@
@brief FP12 Structure - towered over three FP8
*/
+#define FP24_ZERO 0
+#define FP24_ONE 1
+#define FP24_SPARSER 2
+#define FP24_SPARSE 3
+#define FP24_DENSE 4
+
+
typedef struct
{
FP8 a; /**< first part of FP12 */
FP8 b; /**< second part of FP12 */
FP8 c; /**< third part of FP12 */
+ int type;
} FP24;
extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
@@ -85,20 +93,27 @@
@param y FP24 instance
*/
extern void FP24_sqr(FP24 *x,FP24 *y);
-/** @brief Fast multiplication of an FP24 by an FP24 that arises from an ATE pairing line function
+
+/** @brief Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP24 instance, on exit = x*y
@param y FP24 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP24_smul(FP24 *x,FP24 *y,int t);
-/** @brief Multiplication of two FP24s
+extern void FP24_smul(FP24 *x,FP24 *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP24 instance, on exit = x*y
+ @param y FP24 instance, of special form
+ */
+extern void FP24_ssmul(FP24 *x,FP24 *y);
+/** @brief Full unconditional Multiplication of two FP24s
*
@param x FP24 instance, on exit = x*y
@param y FP24 instance, the multiplier
*/
extern void FP24_mul(FP24 *x,FP24 *y);
+
/** @brief Inverting an FP24
*
@param x FP24 instance, on exit = 1/y
diff --git a/version3/cpp/fp4.h b/version3/cpp/fp4.h
index ffd728c..d8cdc9d 100644
--- a/version3/cpp/fp4.h
+++ b/version3/cpp/fp4.h
@@ -127,6 +127,7 @@
*/
extern void FP4_pmul(FP4 *x,FP4 *y,FP2 *a);
+
/** @brief Multiplication of an FP4 by an FP
*
@param x FP4 instance, on exit = y*a
diff --git a/version3/cpp/fp48.cpp b/version3/cpp/fp48.cpp
index 0e66774..7f0ff85 100644
--- a/version3/cpp/fp48.cpp
+++ b/version3/cpp/fp48.cpp
@@ -22,6 +22,7 @@
/* FP48 elements are of the form a+i.b+i^2.c */
#include "fp48_YYY.h"
+#include "config_curve_ZZZ.h"
using namespace XXX;
@@ -82,6 +83,7 @@
FP16_copy(&(w->a),&(x->a));
FP16_copy(&(w->b),&(x->b));
FP16_copy(&(w->c),&(x->c));
+ w->type=x->type;
}
/* FP48 w=1 */
@@ -91,6 +93,7 @@
FP16_one(&(w->a));
FP16_zero(&(w->b));
FP16_zero(&(w->c));
+ w->type=FP_UNITY;
}
/* return 1 if x==y, else 0 */
@@ -119,6 +122,7 @@
FP16_copy(&(w->a),a);
FP16_zero(&(w->b));
FP16_zero(&(w->c));
+ w->type=FP_SPARSER;
}
/* Create FP48 from 3 FP16's */
@@ -128,6 +132,7 @@
FP16_copy(&(w->a),a);
FP16_copy(&(w->b),b);
FP16_copy(&(w->c),c);
+ w->type=FP_DENSE;
}
/* Granger-Scott Unitary Squaring. This does not benefit from lazy reduction */
@@ -167,6 +172,7 @@
FP16_add(&(w->c),&(w->c),&(w->c));
FP16_add(&(w->b),&B,&(w->b));
FP16_add(&(w->c),&C,&(w->c));
+ w->type=FP_DENSE;
FP48_reduce(w); /* reduce here as in pow function repeated squarings would trigger multiple reductions */
}
@@ -179,6 +185,12 @@
FP16 A,B,C,D;
+ if (x->type<=FP_UNITY)
+ {
+ FP48_copy(w,x);
+ return;
+ }
+
FP16_sqr(&A,&(x->a));
FP16_mul(&B,&(x->b),&(x->c));
FP16_add(&B,&B,&B);
@@ -212,6 +224,11 @@
FP16_add(&(w->b),&C,&D);
FP16_add(&(w->c),&(w->c),&A);
+ if (x->type==FP_SPARSER)
+ w->type=FP_SPARSE;
+ else
+ w->type=FP_DENSE;
+
FP48_norm(w);
}
@@ -271,18 +288,105 @@
FP16_add(&(w->a),&z0,&z3);
FP48_norm(w);
+ w->type=FP_DENSE;
}
-/* FP48 multiplication w=w*y */
-/* SU= 744 */
-/* catering for special case that arises from special form of ATE pairing line function */
-void YYY::FP48_smul(FP48 *w,FP48 *y,int type)
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+void YYY::FP48_ssmul(FP48 *w,FP48 *y)
{
- FP16 z0,z1,z2,z3,t0,t1;
+ FP16 z0,z1,z2,z3,t0,t1;
+ if (w->type==FP_UNITY)
+ {
+ FP48_copy(w,y);
+ return;
+ }
+ if (y->type==FP_UNITY)
+ return;
- if (type==D_TYPE)
- { // y->c is 0
+ if (y->type >= FP_SPARSE)
+ {
+ FP16_mul(&z0,&(w->a),&(y->a)); // xa.ya always 11x11
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP8_mul(&z2.b,&(w->b).b,&(y->b).b);
+ FP8_zero(&z2.a);
+ if (y->type!=FP_SPARSE)
+ FP8_mul(&z2.a,&(w->b).b,&(y->b).a);
+ if (w->type!=FP_SPARSE)
+ FP8_mul(&z2.a,&(w->b).a,&(y->b).b);
+ FP16_times_i(&z2);
+ }
+ else
+#endif
+ FP16_mul(&z2,&(w->b),&(y->b)); // xb.yb could be 00x00 or 01x01 or or 10x10 or 11x00 or 11x10 or 11x01 or 11x11
+
+ FP16_add(&t0,&(w->a),&(w->b)); // (xa+xb)
+ FP16_add(&t1,&(y->a),&(y->b)); // (ya+yb)
+
+ FP16_norm(&t0);
+ FP16_norm(&t1);
+
+ FP16_mul(&z1,&t0,&t1); // (xa+xb)(ya+yb) always 11x11
+ FP16_add(&t0,&(w->b),&(w->c)); // (xb+xc)
+ FP16_add(&t1,&(y->b),&(y->c)); // (yb+yc)
+
+ FP16_norm(&t0);
+ FP16_norm(&t1);
+
+ FP16_mul(&z3,&t0,&t1); // (xb+xc)(yb+yc) could be anything...
+ FP16_neg(&t0,&z0); // -(xa.ya)
+ FP16_neg(&t1,&z2); // -(xb.yb)
+
+ FP16_add(&z1,&z1,&t0);
+ FP16_add(&(w->b),&z1,&t1); // /wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) = xa.yb + xb.ya
+
+ FP16_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb)
+ FP16_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya)
+
+ FP16_add(&t0,&(w->a),&(w->c)); // (xa+xc)
+ FP16_add(&t1,&(y->a),&(y->c)); // (ya+yc)
+
+ FP16_norm(&t0);
+ FP16_norm(&t1);
+
+ FP16_mul(&t0,&t1,&t0); // (xa+xc)(ya+yc) always 11x11
+ FP16_add(&z2,&z2,&t0); // (xb.yb) - (xa.ya) + (xa+xc)(ya+yc)
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ if (y->type==FP_SPARSE || w->type==FP_SPARSE)
+ {
+ FP8_mul(&t0.a,&(w->c).a,&(y->c).a);
+ FP8_zero(&t0.b);
+ if (y->type!=FP_SPARSE)
+ FP8_mul(&t0.b,&(w->c).a,&(y->c).b);
+ if (w->type!=FP_SPARSE)
+ FP8_mul(&t0.b,&(w->c).b,&(y->c).a);
+ }
+ else
+#endif
+ FP16_mul(&t0,&(w->c),&(y->c)); // (xc.yc) could be anything
+
+ FP16_neg(&t1,&t0); // -(xc.yc)
+
+ FP16_add(&(w->c),&z2,&t1); // wc = (xb.yb) - (xa.ya) + (xa+xc)(ya+yc) - (xc.yc) = xb.yb + xc.ya + xa.yc
+ FP16_add(&z3,&z3,&t1); // (xb+xc)(yb+yc) -(xb.yb) - (xc.yc) = xb.yc + xc.yb
+ FP16_times_i(&t0); // i.(xc.yc)
+ FP16_add(&(w->b),&(w->b),&t0); // wb = (xa+xb)(ya+yb) -(xa.ya) -(xb.yb) +i(xc.yc)
+ FP16_norm(&z3);
+ FP16_times_i(&z3); // i[(xb+xc)(yb+yc) -(xb.yb) - (xc.yc)] = i(xb.yc + xc.yb)
+ FP16_add(&(w->a),&z0,&z3); // wa = xa.ya + i(xb.yc + xc.yb)
+ } else {
+ if (w->type==FP_SPARSER)
+ {
+ FP48_smul(w,y);
+ return;
+ }
+// dense by sparser - 13m
+#if SEXTIC_TWIST_ZZZ == D_TYPE
FP16_copy(&z3,&(w->b));
FP16_mul(&z0,&(w->a),&(y->a));
@@ -308,7 +412,6 @@
FP16_add(&z2,&z2,&t0); // z2=z2-z0
FP16_add(&t0,&(w->a),&(w->c));
-
FP16_norm(&t0);
FP16_norm(&z3);
@@ -317,10 +420,8 @@
FP16_times_i(&z3);
FP16_add(&(w->a),&z0,&z3);
- }
-
- if (type==M_TYPE)
- { // y->b is zero
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
FP16_mul(&z0,&(w->a),&(y->a));
FP16_add(&t0,&(w->a),&(w->b));
FP16_norm(&t0);
@@ -336,7 +437,6 @@
FP16_add(&z1,&z1,&t0); // z1=z1-z0
FP16_copy(&(w->b),&z1);
-
FP16_copy(&z2,&t0);
FP16_add(&t0,&(w->a),&(w->c));
@@ -360,10 +460,112 @@
FP16_norm(&z3);
FP16_times_i(&z3);
FP16_add(&(w->a),&z0,&z3);
+#endif
}
+ w->type=FP_DENSE;
FP48_norm(w);
}
+/* 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 */
+void YYY::FP48_smul(FP48 *w,FP48 *y)
+{
+ FP8 w1,w2,w3,ta,tb,tc,td,te,t;
+
+
+#if SEXTIC_TWIST_ZZZ == D_TYPE
+ FP8_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP8_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP8_mul(&w3,&(w->b).a,&(y->b).a); // C1.C2
+
+ FP8_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP8_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP8_add(&t,&w1,&w2);
+ FP8_neg(&t,&t);
+ FP8_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP8_add(&ta,&(w->a).a,&(w->b).a); // A1+C1
+ FP8_add(&tb,&(y->a).a,&(y->b).a); // A2+C2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&td,&ta,&tb); // (A1+C1)(A2+C2)
+ FP8_add(&t,&w1,&w3);
+ FP8_neg(&t,&t);
+ FP8_add(&td,&td,&t); // (A1+C1)(A2+C2)-A1.A2-C1*C2 = (A1.C2+A2.C1)
+
+ FP8_add(&ta,&(w->a).b,&(w->b).a); // B1+C1
+ FP8_add(&tb,&(y->a).b,&(y->b).a); // B2+C2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&te,&ta,&tb); // (B1+C1)(B2+C2)
+ FP8_add(&t,&w2,&w3);
+ FP8_neg(&t,&t);
+ FP8_add(&te,&te,&t); // (B1+C1)(B2+C2)-B1.B2-C1*C2 = (B1.C2+B2.C1)
+
+ FP8_times_i(&w2);
+ FP8_add(&w1,&w1,&w2);
+ FP16_from_FP8s(&(w->a),&w1,&tc);
+ FP16_from_FP8s(&(w->b),&td,&te); // only norm these 2
+ FP16_from_FP8(&(w->c),&w3);
+
+ FP16_norm(&(w->a));
+ FP16_norm(&(w->b));
+#endif
+#if SEXTIC_TWIST_ZZZ == M_TYPE
+ FP8_mul(&w1,&(w->a).a,&(y->a).a); // A1.A2
+ FP8_mul(&w2,&(w->a).b,&(y->a).b); // B1.B2
+ FP8_mul(&w3,&(w->c).b,&(y->c).b); // F1.F2
+
+ FP8_add(&ta,&(w->a).a,&(w->a).b); // A1+B1
+ FP8_add(&tb,&(y->a).a,&(y->a).b); // A2+B2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&tc,&ta,&tb); // (A1+B1)(A2+B2)
+ FP8_add(&t,&w1,&w2);
+ FP8_neg(&t,&t);
+ FP8_add(&tc,&tc,&t); // (A1+B1)(A2+B2)-A1.A2-B1*B2 = (A1.B2+A2.B1)
+
+ FP8_add(&ta,&(w->a).a,&(w->c).b); // A1+F1
+ FP8_add(&tb,&(y->a).a,&(y->c).b); // A2+F2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&td,&ta,&tb); // (A1+F1)(A2+F2)
+ FP8_add(&t,&w1,&w3);
+ FP8_neg(&t,&t);
+ FP8_add(&td,&td,&t); // (A1+F1)(A2+F2)-A1.A2-F1*F2 = (A1.F2+A2.F1)
+
+ FP8_add(&ta,&(w->a).b,&(w->c).b); // B1+F1
+ FP8_add(&tb,&(y->a).b,&(y->c).b); // B2+F2
+ FP8_norm(&ta);
+ FP8_norm(&tb);
+ FP8_mul(&te,&ta,&tb); // (B1+F1)(B2+F2)
+ FP8_add(&t,&w2,&w3);
+ FP8_neg(&t,&t);
+ FP8_add(&te,&te,&t); // (B1+F1)(B2+F2)-B1.B2-F1*F2 = (B1.F2+B2.F1)
+
+ FP8_times_i(&w2);
+ FP8_add(&w1,&w1,&w2);
+ FP16_from_FP8s(&(w->a),&w1,&tc);
+
+ FP8_times_i(&w3);
+ FP8_norm(&w3);
+ FP16_from_FP8H(&(w->b),&w3);
+
+ FP8_norm(&te);
+ FP8_times_i(&te);
+ FP16_from_FP8s(&(w->c),&te,&td);
+
+ FP16_norm(&(w->a));
+ FP16_norm(&(w->c));
+#endif
+
+ w->type=FP_SPARSE;
+}
+
/* Set w=1/x */
/* SU= 600 */
void YYY::FP48_inv(FP48 *w,FP48 *x)
@@ -401,7 +603,7 @@
FP16_mul(&(w->a),&f0,&f3);
FP16_mul(&(w->b),&f1,&f3);
FP16_mul(&(w->c),&f2,&f3);
-
+ w->type=FP_DENSE;
}
/* constant time powering by small integer of max length bts */
@@ -726,8 +928,8 @@
FP16_qmul(&(w->b),&(w->b),f); FP16_times_i4(&(w->b)); FP16_times_i2(&(w->b));
FP16_qmul(&(w->c),&(w->c),&f2); FP16_times_i4(&(w->c)); FP16_times_i4(&(w->c)); FP16_times_i4(&(w->c));
-
}
+ w->type=FP_DENSE;
}
/* SU= 8 */
@@ -1030,5 +1232,7 @@
FP16_cmove(&(f->a),&(g->a),d);
FP16_cmove(&(f->b),&(g->b),d);
FP16_cmove(&(f->c),&(g->c),d);
+ d=~(d-1);
+ f->type^=(f->type^g->type)&d;
}
diff --git a/version3/cpp/fp48.h b/version3/cpp/fp48.h
index 64be9e9..407ed17 100644
--- a/version3/cpp/fp48.h
+++ b/version3/cpp/fp48.h
@@ -10,11 +10,19 @@
@brief FP12 Structure - towered over three FP16
*/
+#define FP48_ZERO 0
+#define FP48_ONE 1
+#define FP48_SPARSER 2
+#define FP48_SPARSE 3
+#define FP48_DENSE 4
+
+
typedef struct
{
FP16 a; /**< first part of FP12 */
FP16 b; /**< second part of FP12 */
FP16 c; /**< third part of FP12 */
+ int type;
} FP48;
extern const XXX::BIG Fra; /**< real part of BN curve Frobenius Constant */
@@ -85,15 +93,20 @@
@param y FP48 instance
*/
extern void FP48_sqr(FP48 *x,FP48 *y);
-/** @brief Fast multiplication of an FP48 by an FP48 that arises from an ATE pairing line function
+/** @brief Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
*
- Here the multiplier has a special form that can be exploited
@param x FP48 instance, on exit = x*y
@param y FP48 instance, of special form
- @param t D_TYPE or M_TYPE twist
*/
-extern void FP48_smul(FP48 *x,FP48 *y,int t);
-/** @brief Multiplication of two FP48s
+extern void FP48_smul(FP48 *x,FP48 *y);
+
+/** @brief Fast multiplication of what may be sparse multiplicands
+ *
+ @param x FP48 instance, on exit = x*y
+ @param y FP48 instance, of special form
+ */
+extern void FP48_ssmul(FP48 *x,FP48 *y);
+/** @brief Full unconditional Multiplication of two FP24s
*
@param x FP48 instance, on exit = x*y
@param y FP48 instance, the multiplier
diff --git a/version3/cpp/pair.cpp b/version3/cpp/pair.cpp
index ff37216..3cad837 100644
--- a/version3/cpp/pair.cpp
+++ b/version3/cpp/pair.cpp
@@ -48,7 +48,7 @@
FP2_copy(&YZ,&YY); //FP2 YZ=new FP2(YY); //Y
- FP2_mul(&YZ,&YZ,&ZZ); //YZ.mul(ZZ); //YZ
+ FP2_mul(&YZ,&YZ,&ZZ); //YZ.mul(ZZ); //YZ
FP2_sqr(&XX,&XX); //XX.sqr(); //X^2
FP2_sqr(&YY,&YY); //YY.sqr(); //Y^2
FP2_sqr(&ZZ,&ZZ); //ZZ.sqr(); //Z^2
@@ -57,8 +57,8 @@
FP2_neg(&YZ,&YZ); //YZ.neg();
FP2_norm(&YZ); //YZ.norm(); //-4YZ
- FP2_imul(&XX,&XX,6); //6X^2
- FP2_pmul(&XX,&XX,Qx); //6X^2.Xs
+ FP2_imul(&XX,&XX,6); //6X^2
+ FP2_pmul(&XX,&XX,Qx); //6X^2.Xs
FP2_imul(&ZZ,&ZZ,3*CURVE_B_I); //3Bz^2
@@ -99,7 +99,7 @@
FP2_copy(&Y1,&(A->y)); //FP2 Y1=new FP2(A.gety()); // Y1
FP2_copy(&T1,&(A->z)); //FP2 T1=new FP2(A.getz()); // Z1
- FP2_copy(&T2,&T1); //FP2 T2=new FP2(A.getz()); // Z1
+ FP2_copy(&T2,&T1); //FP2 T2=new FP2(A.getz()); // Z1
FP2_mul(&T1,&T1,&(B->y)); //T1.mul(B.gety()); // T1=Z1.Y2
FP2_mul(&T2,&T2,&(B->x)); //T2.mul(B.getx()); // T2=Z1.X2
@@ -136,13 +136,146 @@
FP4_zero(&b);
FP4_from_FP2H(&c,&Y1); //b=new FP4(Y1);
#endif
- ECP2_add(A,B); //A.add(B);
+ ECP2_add(A,B); //A.add(B);
}
FP12_from_FP4s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
}
-/* Optimal R-ate pairing r=e(P,Q) */
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int ZZZ::PAIR_nbits(BIG n3,BIG n)
+{
+ BIG x;
+ BIG_rcopy(x,CURVE_Bnx);
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+ BIG_pmul(n,x,6);
+#if SIGN_OF_X_ZZZ==POSITIVEX
+ BIG_inc(n,2);
+#else
+ BIG_dec(n,2);
+#endif
+
+#else
+ BIG_copy(n,x);
+#endif
+
+ BIG_norm(n);
+ BIG_pmul(n3,n,3);
+ BIG_norm(n3);
+
+ return BIG_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP12 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void ZZZ::PAIR_initmp(FP12 r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP12_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void ZZZ::PAIR_miller(FP12 *res,FP12 r[])
+{
+ int i;
+ FP12_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP12_sqr(res,res);
+ FP12_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP12_conj(res,res);
+#endif
+ FP12_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void ZZZ::PAIR_another(FP12 r[],ECP2* PV,ECP* QV)
+{
+ int i,j,nb,bt;
+ BIG x,n,n3;
+ FP12 lv,lv2;
+ ECP2 A,NP,P;
+ ECP Q;
+ FP Qx,Qy;
+#if PAIRING_FRIENDLY_ZZZ==BN
+ ECP2 K;
+ FP2 X;
+ FP_rcopy(&Qx,Fra);
+ FP_rcopy(&Qy,Frb);
+ FP2_from_FPs(&X,&Qx,&Qy);
+#if SEXTIC_TWIST_ZZZ==M_TYPE
+ FP2_inv(&X,&X);
+ FP2_norm(&X);
+#endif
+#endif
+
+ nb=PAIR_nbits(n3,n);
+
+ ECP2_copy(&P,PV);
+ ECP_copy(&Q,QV);
+
+ ECP2_affine(&P);
+ ECP_affine(&Q);
+
+ FP_copy(&Qx,&(Q.x));
+ FP_copy(&Qy,&(Q.y));
+
+ ECP2_copy(&A,&P);
+ ECP2_copy(&NP,&P); ECP2_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
+ }
+ FP12_ssmul(&r[i],&lv);
+ }
+
+#if PAIRING_FRIENDLY_ZZZ==BN
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ ECP2_neg(&A);
+#endif
+
+ ECP2_copy(&K,&P);
+ ECP2_frob(&K,&X);
+ PAIR_line(&lv,&A,&K,&Qx,&Qy);
+ ECP2_frob(&K,&X);
+ ECP2_neg(&K);
+ PAIR_line(&lv2,&A,&K,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(&r[0],&lv);
+
+#endif
+}
+
+/* Optimal single R-ate pairing r=e(P,Q) */
void ZZZ::PAIR_ate(FP12 *r,ECP2 *P1,ECP *Q1)
{
BIG x,n,n3;
@@ -150,7 +283,7 @@
int i,nb,bt;
ECP2 A,NP,P;
ECP Q;
- FP12 lv;
+ FP12 lv,lv2;
#if PAIRING_FRIENDLY_ZZZ==BN
ECP2 KA;
FP2 X;
@@ -166,23 +299,7 @@
#endif
- BIG_rcopy(x,CURVE_Bnx);
-
-#if PAIRING_FRIENDLY_ZZZ==BN
- BIG_pmul(n,x,6);
-#if SIGN_OF_X_ZZZ==POSITIVEX
- BIG_inc(n,2);
-#else
- BIG_dec(n,2);
-#endif
-
-#else
- BIG_copy(n,x);
-#endif
-
- BIG_norm(n);
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ nb=PAIR_nbits(n3,n);
ECP2_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -190,56 +307,53 @@
ECP2_affine(&P);
ECP_affine(&Q);
-
FP_copy(&Qx,&(Q.x));
FP_copy(&Qy,&(Q.y));
ECP2_copy(&A,&P);
-
ECP2_copy(&NP,&P); ECP2_neg(&NP);
FP12_one(r);
- nb=BIG_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP12_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
- PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
}
if (bt==-1)
{
- //ECP2_neg(P);
- PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- //ECP2_neg(P);
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
}
-
+ FP12_ssmul(r,&lv);
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(r,r);
#endif
+
/* R-ate fixup required for BN curves */
#if PAIRING_FRIENDLY_ZZZ==BN
- ECP2_copy(&KA,&P);
- ECP2_frob(&KA,&X);
+
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&A);
#endif
+
+ ECP2_copy(&KA,&P);
+ ECP2_frob(&KA,&X);
PAIR_line(&lv,&A,&KA,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_frob(&KA,&X);
ECP2_neg(&KA);
- PAIR_line(&lv,&A,&KA,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&KA,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
#endif
}
@@ -252,7 +366,7 @@
int i,nb,bt;
ECP2 A,B,NP,NR,P,R;
ECP Q,S;
- FP12 lv;
+ FP12 lv,lv2;
#if PAIRING_FRIENDLY_ZZZ==BN
ECP2 K;
FP2 X;
@@ -267,22 +381,7 @@
#endif
#endif
- BIG_rcopy(x,CURVE_Bnx);
-
-#if PAIRING_FRIENDLY_ZZZ==BN
- BIG_pmul(n,x,6);
-#if SIGN_OF_X_ZZZ==POSITIVEX
- BIG_inc(n,2);
-#else
- BIG_dec(n,2);
-#endif
-#else
- BIG_copy(n,x);
-#endif
-
- BIG_norm(n);
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ nb=PAIR_nbits(n3,n);
ECP2_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -309,33 +408,30 @@
ECP2_copy(&NR,&R); ECP2_neg(&NR);
FP12_one(r);
- nb=BIG_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP12_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&B,&Sx,&Sy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&B,&Sx,&Sy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&R,&Sx,&Sy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&R,&Sx,&Sy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
}
if (bt==-1)
{
PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- PAIR_line(&lv,&B,&NR,&Sx,&Sy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
}
}
@@ -353,20 +449,20 @@
ECP2_copy(&K,&P);
ECP2_frob(&K,&X);
PAIR_line(&lv,&A,&K,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_frob(&K,&X);
ECP2_neg(&K);
- PAIR_line(&lv,&A,&K,&Qx,&Qy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&K,&Qx,&Qy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
+
ECP2_copy(&K,&R);
ECP2_frob(&K,&X);
-
PAIR_line(&lv,&B,&K,&Sx,&Sy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
ECP2_frob(&K,&X);
ECP2_neg(&K);
- PAIR_line(&lv,&B,&K,&Sx,&Sy);
- FP12_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&K,&Sx,&Sy);
+ FP12_smul(&lv,&lv2);
+ FP12_ssmul(r,&lv);
#endif
}
diff --git a/version3/cpp/pair.h b/version3/cpp/pair.h
index 0d6d179..9585597 100644
--- a/version3/cpp/pair.h
+++ b/version3/cpp/pair.h
@@ -19,6 +19,17 @@
extern const XXX::BIG CURVE_BB[4][4]; /**< BN curve constant for GS decomposition */
/* Pairing function prototypes */
+
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP12 products of line functions
+ @param PV ECP2 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_another(YYY::FP12 r[],ECP2* PV,ECP* QV);
+
+
/** @brief Calculate Miller loop for Optimal ATE pairing e(P,Q)
*
@param r FP12 result of the pairing calculation e(P,Q)
@@ -70,11 +81,35 @@
/** @brief Tests FP12 for membership of GT
*
@param x FP12 instance
- @return 1 if x is in GT, else return 0
*/
extern int PAIR_GTmember(YYY::FP12 *x);
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+
+ */
+extern int PAIR_nbits(XXX::BIG n3,XXX::BIG n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP12 array, to be initialised to 1
+
+ */
+extern void PAIR_initmp(YYY::FP12 r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP12 result
+ @param r FP12 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_miller(YYY::FP12 *res,YYY::FP12 r[]);
+
}
#endif
diff --git a/version3/cpp/pair192.cpp b/version3/cpp/pair192.cpp
index 4d6303c..2d673fd 100644
--- a/version3/cpp/pair192.cpp
+++ b/version3/cpp/pair192.cpp
@@ -140,6 +140,101 @@
}
FP24_from_FP8s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
+}
+
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int ZZZ::PAIR_nbits(BIG n3,BIG n)
+{
+ BIG x;
+ BIG_rcopy(x,CURVE_Bnx);
+
+ BIG_copy(n,x);
+ BIG_norm(n);
+ BIG_pmul(n3,n,3);
+ BIG_norm(n3);
+
+ return BIG_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP24 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void ZZZ::PAIR_initmp(FP24 r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP24_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void ZZZ::PAIR_miller(FP24 *res,FP24 r[])
+{
+ int i;
+ FP24_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP24_sqr(res,res);
+ FP24_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP24_conj(res,res);
+#endif
+ FP24_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void ZZZ::PAIR_another(FP24 r[],ECP4* PV,ECP* QV)
+{
+ int i,j,nb,bt;
+ BIG x,n,n3;
+ FP24 lv,lv2;
+ ECP4 A,NP,P;
+ ECP Q;
+ FP Qx,Qy;
+
+ nb=PAIR_nbits(n3,n);
+
+ ECP4_copy(&P,PV);
+ ECP_copy(&Q,QV);
+
+ ECP4_affine(&P);
+ ECP_affine(&Q);
+
+ FP_copy(&Qx,&(Q.x));
+ FP_copy(&Qy,&(Q.y));
+
+ ECP4_copy(&A,&P);
+ ECP4_copy(&NP,&P); ECP4_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP24_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP24_smul(&lv,&lv2);
+ }
+ FP24_ssmul(&r[i],&lv);
+ }
}
/* Optimal R-ate pairing r=e(P,Q) */
@@ -147,17 +242,12 @@
{
BIG x,n,n3;
FP Qx,Qy;
- int i,j,nb,bt;
+ int i,nb,bt;
ECP4 A,NP,P;
ECP Q;
- FP24 lv;
+ FP24 lv,lv2;
- BIG_rcopy(x,CURVE_Bnx);
-
- BIG_copy(n,x);
-
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ nb=PAIR_nbits(n3,n);
ECP4_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -169,32 +259,28 @@
FP_copy(&Qy,&(Q.y));
ECP4_copy(&A,&P);
-
ECP4_copy(&NP,&P); ECP4_neg(&NP);
FP24_one(r);
- nb=BIG_nbits(n3); // n3
- j=0;
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
- j++;
FP24_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
bt= BIG_bit(n3,i)-BIG_bit(n,i); // BIG_bit(n,i);
if (bt==1)
{
- PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP24_smul(&lv,&lv2);
}
if (bt==-1)
{
- PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP24_smul(&lv,&lv2);
}
+ FP24_ssmul(r,&lv);
}
@@ -212,13 +298,8 @@
int i,nb,bt;
ECP4 A,B,NP,NR,P,R;
ECP Q,S;
- FP24 lv;
-
- BIG_rcopy(x,CURVE_Bnx);
- BIG_copy(n,x);
-
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ FP24 lv,lv2;
+ nb=PAIR_nbits(n3,n);
ECP4_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -246,33 +327,30 @@
FP24_one(r);
- nb=BIG_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP24_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&B,&Sx,&Sy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&B,&Sx,&Sy);
+ FP24_smul(&lv,&lv2);
+ FP24_ssmul(r,&lv);
bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&R,&Sx,&Sy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&R,&Sx,&Sy);
+ FP24_smul(&lv,&lv2);
+ FP24_ssmul(r,&lv);
}
if (bt==-1)
{
PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- PAIR_line(&lv,&B,&NR,&Sx,&Sy);
- FP24_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP24_smul(&lv,&lv2);
+ FP24_ssmul(r,&lv);
}
}
diff --git a/version3/cpp/pair192.h b/version3/cpp/pair192.h
index 09baec4..df9792a 100644
--- a/version3/cpp/pair192.h
+++ b/version3/cpp/pair192.h
@@ -75,6 +75,41 @@
*/
extern int PAIR_GTmember(YYY::FP24 *x);
+
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP24 products of line functions
+ @param PV ECP4 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_another(YYY::FP24 r[],ECP4* PV,ECP* QV);
+
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+
+ */
+extern int PAIR_nbits(XXX::BIG n3,XXX::BIG n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP24 array, to be initialised to 1
+
+ */
+extern void PAIR_initmp(YYY::FP24 r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP24 result
+ @param r FP24 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_miller(YYY::FP24 *res,YYY::FP24 r[]);
+
}
#endif
diff --git a/version3/cpp/pair256.cpp b/version3/cpp/pair256.cpp
index ce07f29..e5719e4 100644
--- a/version3/cpp/pair256.cpp
+++ b/version3/cpp/pair256.cpp
@@ -139,6 +139,100 @@
}
FP48_from_FP16s(v,&a,&b,&c);
+ v->type=FP_SPARSER;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+int ZZZ::PAIR_nbits(BIG n3,BIG n)
+{
+ BIG x;
+ BIG_rcopy(x,CURVE_Bnx);
+
+ BIG_copy(n,x);
+ BIG_norm(n);
+ BIG_pmul(n3,n,3);
+ BIG_norm(n3);
+
+ return BIG_nbits(n3);
+}
+
+/*
+ For multi-pairing, product of n pairings
+ 1. Declare FP24 array of length number of bits in Ate parameter
+ 2. Initialise this array by calling PAIR_initmp()
+ 3. Accumulate each pairing by calling PAIR_another() n times
+ 4. Call PAIR_miller()
+ 5. Call final exponentiation PAIR_fexp()
+*/
+
+/* prepare for multi-pairing */
+void ZZZ::PAIR_initmp(FP48 r[])
+{
+ int i;
+ for (i=ATE_BITS_ZZZ-1; i>=0; i--)
+ FP48_one(&r[i]);
+ return;
+}
+
+/* basic Miller loop */
+void ZZZ::PAIR_miller(FP48 *res,FP48 r[])
+{
+ int i;
+ FP48_one(res);
+ for (i=ATE_BITS_ZZZ-1; i>=1; i--)
+ {
+ FP48_sqr(res,res);
+ FP48_ssmul(res,&r[i]);
+ }
+
+#if SIGN_OF_X_ZZZ==NEGATIVEX
+ FP48_conj(res,res);
+#endif
+ FP48_ssmul(res,&r[0]);
+ return;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+void ZZZ::PAIR_another(FP48 r[],ECP8* PV,ECP* QV)
+{
+ int i,j,nb,bt;
+ BIG x,n,n3;
+ FP48 lv,lv2;
+ ECP8 A,NP,P;
+ ECP Q;
+ FP Qx,Qy;
+
+ nb=PAIR_nbits(n3,n);
+
+ ECP8_copy(&P,PV);
+ ECP_copy(&Q,QV);
+
+ ECP8_affine(&P);
+ ECP_affine(&Q);
+
+ FP_copy(&Qx,&(Q.x));
+ FP_copy(&Qy,&(Q.y));
+
+ ECP8_copy(&A,&P);
+ ECP8_copy(&NP,&P); ECP8_neg(&NP);
+
+ for (i=nb-2; i>=1; i--)
+ {
+ PAIR_line(&lv,&A,&A,&Qx,&Qy);
+
+ bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
+ if (bt==1)
+ {
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP48_smul(&lv,&lv2);
+ }
+ if (bt==-1)
+ {
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP48_smul(&lv,&lv2);
+ }
+ FP48_ssmul(&r[i],&lv);
+ }
}
/* Optimal R-ate pairing r=e(P,Q) */
@@ -146,17 +240,12 @@
{
BIG x,n,n3;
FP Qx,Qy;
- int i,j,nb,bt;
+ int i,nb,bt;
ECP8 A,NP,P;
ECP Q;
- FP48 lv;
+ FP48 lv,lv2;
- BIG_rcopy(x,CURVE_Bnx);
-
- BIG_copy(n,x);
-
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ nb=PAIR_nbits(n3,n);
ECP8_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -169,32 +258,28 @@
FP_copy(&Qy,&(Q.y));
ECP8_copy(&A,&P);
-
ECP8_copy(&NP,&P); ECP8_neg(&NP);
FP48_one(r);
- nb=BIG_nbits(n3); // n3
- j=0;
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
- j++;
FP48_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
bt= BIG_bit(n3,i)-BIG_bit(n,i); // BIG_bit(n,i);
if (bt==1)
{
- PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&P,&Qx,&Qy);
+ FP48_smul(&lv,&lv2);
}
if (bt==-1)
{
- PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&A,&NP,&Qx,&Qy);
+ FP48_smul(&lv,&lv2);
}
+ FP48_ssmul(r,&lv);
}
@@ -212,13 +297,8 @@
int i,nb,bt;
ECP8 A,B,NP,NR,P,R;
ECP Q,S;
- FP48 lv;
-
- BIG_rcopy(x,CURVE_Bnx);
- BIG_copy(n,x);
-
- BIG_pmul(n3,n,3);
- BIG_norm(n3);
+ FP48 lv,lv2;
+ nb=PAIR_nbits(n3,n);
ECP8_copy(&P,P1);
ECP_copy(&Q,Q1);
@@ -245,33 +325,30 @@
ECP8_copy(&NR,&R); ECP8_neg(&NR);
FP48_one(r);
- nb=BIG_nbits(n3);
/* Main Miller Loop */
for (i=nb-2; i>=1; i--)
{
FP48_sqr(r,r);
PAIR_line(&lv,&A,&A,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&B,&Sx,&Sy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&B,&Sx,&Sy);
+ FP48_smul(&lv,&lv2);
+ FP48_ssmul(r,&lv);
bt=BIG_bit(n3,i)-BIG_bit(n,i); // bt=BIG_bit(n,i);
if (bt==1)
{
PAIR_line(&lv,&A,&P,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
-
- PAIR_line(&lv,&B,&R,&Sx,&Sy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&R,&Sx,&Sy);
+ FP48_smul(&lv,&lv2);
+ FP48_ssmul(r,&lv);
}
if (bt==-1)
{
PAIR_line(&lv,&A,&NP,&Qx,&Qy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
- PAIR_line(&lv,&B,&NR,&Sx,&Sy);
- FP48_smul(r,&lv,SEXTIC_TWIST_ZZZ);
+ PAIR_line(&lv2,&B,&NR,&Sx,&Sy);
+ FP48_smul(&lv,&lv2);
+ FP48_ssmul(r,&lv);
}
}
diff --git a/version3/cpp/pair256.h b/version3/cpp/pair256.h
index 353b30a..e5e5fc5 100644
--- a/version3/cpp/pair256.h
+++ b/version3/cpp/pair256.h
@@ -75,6 +75,40 @@
*/
extern int PAIR_GTmember(YYY::FP48 *x);
+/** @brief Precompute line functions for n-pairing
+ *
+ @param r array of precomputed FP48 products of line functions
+ @param PV ECP8 instance, an element of G2
+ @param QV ECP instance, an element of G1
+
+ */
+extern void PAIR_another(YYY::FP48 r[],ECP8* PV,ECP* QV);
+
+/** @brief Prepare Ate parameter
+ *
+ @param n BIG parameter
+ @param n3 BIG paramter = 3*n
+ @return number of nits in n3
+
+ */
+extern int PAIR_nbits(XXX::BIG n3,XXX::BIG n);
+
+/** @brief Initialise structure for multi-pairing
+ *
+ @param r FP48 array, to be initialised to 1
+
+ */
+extern void PAIR_initmp(YYY::FP48 r[]);
+
+
+/** @brief Miller loop
+ *
+ @param res FP48 result
+ @param r FP48 precomputed array of accumulated line functions
+
+ */
+extern void PAIR_miller(YYY::FP48 *res,YYY::FP48 r[]);
+
}
#endif
diff --git a/version3/cpp/rsa_support.h b/version3/cpp/rsa_support.h
index 3bec69f..3530c56 100644
--- a/version3/cpp/rsa_support.h
+++ b/version3/cpp/rsa_support.h
@@ -5,7 +5,7 @@
namespace amcl {
-#define MAX_RSA_BYTES 512 // Maximum of 4096
+#define MAX_RSA_BYTES 1920 // Maximum of 4096
/** @brief RSA Key Pair Generator
*
diff --git a/version3/cpp/testall.cpp b/version3/cpp/testall.cpp
index 51e9e6d..9f57b17 100644
--- a/version3/cpp/testall.cpp
+++ b/version3/cpp/testall.cpp
@@ -1567,8 +1567,9 @@
printf("Decrypting test string\n");
RSA_DECRYPT(&priv,&C,&ML); // ... and then decrypt it
-
+ printf("Decrypted\n");
OAEP_DECODE(HASH_TYPE_RSA_RSA2048,NULL,&ML); // decode it
+ printf("Decoded\n");
OCT_output_string(&ML);
printf("Signing message\n");
diff --git a/version3/go/BLS.go b/version3/go/BLS.go
index b9d5538..db4db41 100644
--- a/version3/go/BLS.go
+++ b/version3/go/BLS.go
@@ -74,7 +74,16 @@
G := ECP2_generator()
PK := ECP2_fromBytes(W)
D.neg()
- v := Ate2(G, D, PK, HM)
+
+// Use new multi-pairing mechanism
+ r:=initmp()
+ another(r,G,D)
+ another(r,PK,HM)
+ v:=miller(r)
+
+//.. or alternatively
+// v := Ate2(G, D, PK, HM)
+
v = Fexp(v)
if v.Isunity() {
return BLS_OK
diff --git a/version3/go/BLS192.go b/version3/go/BLS192.go
index a3898d1..999d0ae 100644
--- a/version3/go/BLS192.go
+++ b/version3/go/BLS192.go
@@ -74,7 +74,16 @@
G := ECP4_generator()
PK := ECP4_fromBytes(W)
D.neg()
- v := Ate2(G, D, PK, HM)
+
+// Use new multi-pairing mechanism
+ r:=initmp()
+ another(r,G,D)
+ another(r,PK,HM)
+ v:=miller(r)
+
+//.. or alternatively
+// v := Ate2(G, D, PK, HM)
+
v = Fexp(v)
if v.Isunity() {
return BLS_OK
diff --git a/version3/go/BLS256.go b/version3/go/BLS256.go
index e17a9d7..74519ad 100644
--- a/version3/go/BLS256.go
+++ b/version3/go/BLS256.go
@@ -74,7 +74,16 @@
G := ECP8_generator()
PK := ECP8_fromBytes(W)
D.neg()
- v := Ate2(G, D, PK, HM)
+
+// Use new multi-pairing mechanism
+ r:=initmp()
+ another(r,G,D)
+ another(r,PK,HM)
+ v:=miller(r)
+
+//.. or alternatively
+// v := Ate2(G, D, PK, HM)
+
v = Fexp(v)
if v.Isunity() {
return BLS_OK
diff --git a/version3/go/CONFIG_CURVE.go b/version3/go/CONFIG_CURVE.go
index 51edf40..794711e 100644
--- a/version3/go/CONFIG_CURVE.go
+++ b/version3/go/CONFIG_CURVE.go
@@ -14,6 +14,13 @@
const D_TYPE int = 0
const M_TYPE int = 1
+// Sparsity
+const FP_ZERO int = 0
+const FP_ONE int = 1
+const FP_SPARSER int = 2
+const FP_SPARSE int = 3
+const FP_DENSE int = 4
+
// Pairing x parameter sign
const POSITIVEX int = 0
const NEGATIVEX int = 1
@@ -27,6 +34,7 @@
const SEXTIC_TWIST int = @ST@
const SIGN_OF_X int = @SX@
+const ATE_BITS int = @AB@
// associated hash function and AES key size
diff --git a/version3/go/FP12.go b/version3/go/FP12.go
index d8a5b99..60af7c6 100644
--- a/version3/go/FP12.go
+++ b/version3/go/FP12.go
@@ -28,6 +28,7 @@
a *FP4
b *FP4
c *FP4
+ stype int
}
/* Constructors */
@@ -36,6 +37,7 @@
F.a = NewFP4copy(d)
F.b = NewFP4int(0)
F.c = NewFP4int(0)
+ F.stype=FP_SPARSER
return F
}
@@ -44,6 +46,11 @@
F.a = NewFP4int(d)
F.b = NewFP4int(0)
F.c = NewFP4int(0)
+// if d==1 {
+// F.stype=FP_ONE
+// } else {
+// F.stype=FP_SPARSER
+// }
return F
}
@@ -52,6 +59,7 @@
F.a = NewFP4copy(d)
F.b = NewFP4copy(e)
F.c = NewFP4copy(f)
+ F.stype=FP_DENSE
return F
}
@@ -60,6 +68,7 @@
F.a = NewFP4copy(x.a)
F.b = NewFP4copy(x.b)
F.c = NewFP4copy(x.c)
+ F.stype=x.stype
return F
}
@@ -87,6 +96,8 @@
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
F.c.cmove(g.c, d)
+ d=^(d-1)
+ F.stype^=(F.stype^g.stype)&d
}
/* Constant time select from pre-computed table */
@@ -142,6 +153,7 @@
F.a.copy(x.a)
F.b.copy(x.b)
F.c.copy(x.c)
+ F.stype=x.stype
}
/* set this=1 */
@@ -149,6 +161,7 @@
F.a.one()
F.b.zero()
F.c.zero()
+ F.stype=FP_ONE
}
/* this=conj(this) */
@@ -197,11 +210,16 @@
F.b.add(B)
F.c.add(C)
F.reduce()
+ F.stype=FP_DENSE
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
func (F *FP12) sqr() {
+ if F.stype==FP_ONE {
+ return
+ }
+
A := NewFP4copy(F.a)
B := NewFP4copy(F.b)
C := NewFP4copy(F.c)
@@ -237,6 +255,11 @@
F.b.copy(C)
F.b.add(D)
F.c.add(A)
+ if F.stype==FP_SPARSER {
+ F.stype=FP_SPARSE
+ } else {
+ F.stype=FP_DENSE
+ }
F.norm()
}
@@ -304,113 +327,303 @@
z3.times_i()
F.a.copy(z0)
F.a.add(z3)
+ F.stype=FP_DENSE
F.norm()
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
-func (F *FP12) smul(y *FP12, twist int) {
- if twist == D_TYPE {
- z0 := NewFP4copy(F.a)
- z2 := NewFP4copy(F.b)
- z3 := NewFP4copy(F.b)
- t0 := NewFP4int(0)
- t1 := NewFP4copy(y.a)
- z0.mul(y.a)
- z2.pmul(y.b.real())
- F.b.add(F.a)
- t1.real().add(y.b.real())
-
- t1.norm()
- F.b.norm()
- F.b.mul(t1)
- z3.add(F.c)
- z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0)
- t0.neg()
- t1.copy(z2)
- t1.neg()
-
- F.b.add(t0)
- F.b.add(t1)
- z3.add(t1)
- z3.norm()
- z2.add(t0)
-
- t0.copy(F.a)
- t0.add(F.c)
- t0.norm()
- t0.mul(y.a)
- F.c.copy(z2)
- F.c.add(t0)
-
- z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+func (F *FP12) ssmul(y *FP12) {
+ if F.stype==FP_ONE {
+ F.Copy(y)
+ return
}
- if twist == M_TYPE {
- z0 := NewFP4copy(F.a)
- z1 := NewFP4int(0)
- z2 := NewFP4int(0)
- z3 := NewFP4int(0)
- t0 := NewFP4copy(F.a)
- t1 := NewFP4int(0)
-
+ if y.stype==FP_ONE {
+ return
+ }
+ if y.stype>=FP_SPARSE {
+ z0:=NewFP4copy(F.a)
+ z1:=NewFP4int(0)
+ z2:=NewFP4int(0)
+ z3:=NewFP4int(0)
z0.mul(y.a)
- t0.add(F.b)
- t0.norm()
- z1.copy(t0)
- z1.mul(y.a)
- t0.copy(F.b)
- t0.add(F.c)
- t0.norm()
+ if SEXTIC_TWIST==M_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ z2.getb().copy(F.b.getb())
+ z2.getb().mul(y.b.getb())
+ z2.geta().zero()
+ if y.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.getb())
+ z2.geta().mul(y.b.geta())
+ }
+ if F.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.geta())
+ z2.geta().mul(y.b.getb())
+ }
+ z2.times_i()
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ t0:=NewFP4copy(F.a)
+ t1:=NewFP4copy(y.a)
+ t0.add(F.b); t0.norm();
+ t1.add(y.b); t1.norm()
- z3.copy(t0)
- z3.pmul(y.c.getb())
- z3.times_i()
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(F.b); t0.add(F.c); t0.norm()
+ t1.copy(y.b); t1.add(y.c); t1.norm()
- t0.copy(z0)
- t0.neg()
+ z3.copy(t0); z3.mul(t1)
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
z1.add(t0)
- F.b.copy(z1)
- z2.copy(t0)
+ F.b.copy(z1); F.b.add(t1)
- t0.copy(F.a)
- t0.add(F.c)
- t1.copy(y.a)
- t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
-
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
t0.mul(t1)
z2.add(t0)
- t0.copy(F.c)
+ if SEXTIC_TWIST==D_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ t0.geta().copy(F.c.geta())
+ t0.geta().mul(y.c.geta())
+ t0.getb().zero()
+ if y.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.geta())
+ t0.getb().mul(y.c.getb())
+ }
+ if F.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.getb())
+ t0.getb().mul(y.c.geta())
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ t1.copy(t0); t1.neg()
- t0.pmul(y.c.getb())
- t0.times_i()
-
- t1.copy(t0)
- t1.neg()
-
- F.c.copy(z2)
- F.c.add(t1)
+ F.c.copy(z2); F.c.add(t1)
z3.add(t1)
t0.times_i()
F.b.add(t0)
z3.norm()
z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+ F.a.copy(z0); F.a.add(z3);
+ } else {
+ if F.stype==FP_SPARSER {
+ F.smul(y)
+ return
+ }
+ if SEXTIC_TWIST==D_TYPE { // dense by sparser - 13m
+ z0:=NewFP4copy(F.a)
+ z2:=NewFP4copy(F.b)
+ z3:=NewFP4copy(F.b)
+ t0:=NewFP4int(0)
+ t1:=NewFP4copy(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ F.b.add(F.a)
+ t1.real().add(y.b.real())
+
+ t1.norm()
+ F.b.norm()
+ F.b.mul(t1)
+ z3.add(F.c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ F.b.add(t0)
+
+ F.b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ F.c.copy(z2); F.c.add(t0)
+
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
+ if SEXTIC_TWIST==M_TYPE {
+ z0:=NewFP4copy(F.a)
+ z1:=NewFP4int(0)
+ z2:=NewFP4int(0)
+ z3:=NewFP4int(0)
+ t0:=NewFP4copy(F.a)
+ t1:=NewFP4int(0)
+
+ z0.mul(y.a)
+ t0.add(F.b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(F.b); t0.add(F.c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ F.b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(F.c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ F.c.copy(z2); F.c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ F.b.add(t0)
+ z3.norm()
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
}
+ F.stype=FP_DENSE
F.norm()
}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP12) smul(y *FP12) {
+ if SEXTIC_TWIST==D_TYPE {
+ w1:=NewFP2copy(F.a.geta())
+ w2:=NewFP2copy(F.a.getb())
+ w3:=NewFP2copy(F.b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ ta:=NewFP2copy(F.a.geta())
+ tb:=NewFP2copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP2copy(ta)
+ tc.mul(tb);
+ t:=NewFP2copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ td:=NewFP2copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ te:=NewFP2copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.mul_ip()
+ w1.add(w2)
+
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+ F.b.geta().copy(td); F.b.getb().copy(te)
+ F.c.geta().copy(w3); F.c.getb().zero()
+
+ F.a.norm()
+ F.b.norm()
+ } else {
+ w1:=NewFP2copy(F.a.geta())
+ w2:=NewFP2copy(F.a.getb())
+ w3:=NewFP2copy(F.c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ ta:=NewFP2copy(F.a.geta())
+ tb:=NewFP2copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP2copy(ta)
+ tc.mul(tb);
+ t:=NewFP2copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ td:=NewFP2copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ te:=NewFP2copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.mul_ip()
+ w1.add(w2)
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+
+ w3.mul_ip()
+ w3.norm()
+ F.b.geta().zero(); F.b.getb().copy(w3)
+
+ te.norm()
+ te.mul_ip()
+ F.c.geta().copy(te)
+ F.c.getb().copy(td)
+
+ F.a.norm()
+ F.c.norm()
+
+ }
+ F.stype=FP_SPARSE;
+}
+
/* this=1/this */
func (F *FP12) Inverse() {
f0 := NewFP4copy(F.a)
@@ -456,6 +669,7 @@
F.b.mul(f3)
F.c.copy(f2)
F.c.mul(f3)
+ F.stype=FP_DENSE
}
/* this=this^p using Frobenius */
@@ -472,6 +686,7 @@
F.b.pmul(f)
F.c.pmul(f2)
+ F.stype=FP_DENSE
}
/* trace function */
diff --git a/version3/go/FP24.go b/version3/go/FP24.go
index da505ea..32bae65 100644
--- a/version3/go/FP24.go
+++ b/version3/go/FP24.go
@@ -28,6 +28,7 @@
a *FP8
b *FP8
c *FP8
+ stype int
}
/* Constructors */
@@ -36,6 +37,7 @@
F.a = NewFP8copy(d)
F.b = NewFP8int(0)
F.c = NewFP8int(0)
+ F.stype=FP_SPARSER
return F
}
@@ -44,6 +46,11 @@
F.a = NewFP8int(d)
F.b = NewFP8int(0)
F.c = NewFP8int(0)
+ if d==1 {
+ F.stype=FP_ONE
+ } else {
+ F.stype=FP_SPARSER
+ }
return F
}
@@ -52,6 +59,7 @@
F.a = NewFP8copy(d)
F.b = NewFP8copy(e)
F.c = NewFP8copy(f)
+ F.stype=FP_DENSE
return F
}
@@ -60,6 +68,7 @@
F.a = NewFP8copy(x.a)
F.b = NewFP8copy(x.b)
F.c = NewFP8copy(x.c)
+ F.stype=x.stype
return F
}
@@ -87,6 +96,8 @@
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
F.c.cmove(g.c, d)
+ d=^(d-1)
+ F.stype^=(F.stype^g.stype)&d
}
/* Constant time select from pre-computed table */
@@ -142,6 +153,7 @@
F.a.copy(x.a)
F.b.copy(x.b)
F.c.copy(x.c)
+ F.stype=x.stype
}
/* set this=1 */
@@ -149,6 +161,7 @@
F.a.one()
F.b.zero()
F.c.zero()
+ F.stype=FP_ONE
}
/* this=conj(this) */
@@ -197,11 +210,14 @@
F.b.add(B)
F.c.add(C)
F.reduce()
-
+ F.stype=FP_DENSE
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
func (F *FP24) sqr() {
+ if F.stype==FP_ONE {
+ return
+ }
A := NewFP8copy(F.a)
B := NewFP8copy(F.b)
C := NewFP8copy(F.c)
@@ -237,6 +253,11 @@
F.b.copy(C)
F.b.add(D)
F.c.add(A)
+ if F.stype==FP_SPARSER {
+ F.stype=FP_SPARSE
+ } else {
+ F.stype=FP_DENSE
+ }
F.norm()
}
@@ -305,114 +326,302 @@
z3.times_i()
F.a.copy(z0)
F.a.add(z3)
+ F.stype=FP_DENSE
F.norm()
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
-func (F *FP24) smul(y *FP24, twist int) {
- if twist == D_TYPE {
- z0 := NewFP8copy(F.a)
- z2 := NewFP8copy(F.b)
- z3 := NewFP8copy(F.b)
- t0 := NewFP8int(0)
- t1 := NewFP8copy(y.a)
-
- z0.mul(y.a)
- z2.pmul(y.b.real())
- F.b.add(F.a)
- t1.real().add(y.b.real())
-
- t1.norm()
- F.b.norm()
- F.b.mul(t1)
- z3.add(F.c)
- z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0)
- t0.neg()
- t1.copy(z2)
- t1.neg()
-
- F.b.add(t0)
-
- F.b.add(t1)
- z3.add(t1)
- z3.norm()
- z2.add(t0)
-
- t0.copy(F.a)
- t0.add(F.c)
- t0.norm()
- t0.mul(y.a)
- F.c.copy(z2)
- F.c.add(t0)
-
- z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+func (F *FP24) ssmul(y *FP24) {
+ if F.stype==FP_ONE {
+ F.Copy(y)
+ return
}
- if twist == M_TYPE {
- z0 := NewFP8copy(F.a)
- z1 := NewFP8int(0)
- z2 := NewFP8int(0)
- z3 := NewFP8int(0)
- t0 := NewFP8copy(F.a)
- t1 := NewFP8int(0)
-
+ if y.stype==FP_ONE {
+ return
+ }
+ if y.stype>=FP_SPARSE {
+ z0:=NewFP8copy(F.a)
+ z1:=NewFP8int(0)
+ z2:=NewFP8int(0)
+ z3:=NewFP8int(0)
z0.mul(y.a)
- t0.add(F.b)
- t0.norm()
- z1.copy(t0)
- z1.mul(y.a)
- t0.copy(F.b)
- t0.add(F.c)
- t0.norm()
+ if SEXTIC_TWIST==M_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ z2.getb().copy(F.b.getb())
+ z2.getb().mul(y.b.getb())
+ z2.geta().zero()
+ if y.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.getb())
+ z2.geta().mul(y.b.geta())
+ }
+ if F.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.geta())
+ z2.geta().mul(y.b.getb())
+ }
+ z2.times_i()
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ t0:=NewFP8copy(F.a)
+ t1:=NewFP8copy(y.a)
+ t0.add(F.b); t0.norm();
+ t1.add(y.b); t1.norm()
- z3.copy(t0)
- z3.pmul(y.c.getb())
- z3.times_i()
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(F.b); t0.add(F.c); t0.norm()
+ t1.copy(y.b); t1.add(y.c); t1.norm()
- t0.copy(z0)
- t0.neg()
+ z3.copy(t0); z3.mul(t1)
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
z1.add(t0)
- F.b.copy(z1)
- z2.copy(t0)
+ F.b.copy(z1); F.b.add(t1)
- t0.copy(F.a)
- t0.add(F.c)
- t1.copy(y.a)
- t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
-
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
t0.mul(t1)
z2.add(t0)
- t0.copy(F.c)
+ if SEXTIC_TWIST==D_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ t0.geta().copy(F.c.geta())
+ t0.geta().mul(y.c.geta())
+ t0.getb().zero()
+ if y.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.geta())
+ t0.getb().mul(y.c.getb())
+ }
+ if F.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.getb())
+ t0.getb().mul(y.c.geta())
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ t1.copy(t0); t1.neg()
- t0.pmul(y.c.getb())
- t0.times_i()
-
- t1.copy(t0)
- t1.neg()
-
- F.c.copy(z2)
- F.c.add(t1)
+ F.c.copy(z2); F.c.add(t1)
z3.add(t1)
t0.times_i()
F.b.add(t0)
z3.norm()
z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+ F.a.copy(z0); F.a.add(z3);
+ } else {
+ if F.stype==FP_SPARSER {
+ F.smul(y)
+ return
+ }
+ if SEXTIC_TWIST==D_TYPE { // dense by sparser - 13m
+ z0:=NewFP8copy(F.a)
+ z2:=NewFP8copy(F.b)
+ z3:=NewFP8copy(F.b)
+ t0:=NewFP8int(0)
+ t1:=NewFP8copy(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ F.b.add(F.a)
+ t1.real().add(y.b.real())
+
+ t1.norm()
+ F.b.norm()
+ F.b.mul(t1)
+ z3.add(F.c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ F.b.add(t0)
+
+ F.b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ F.c.copy(z2); F.c.add(t0)
+
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
+ if SEXTIC_TWIST==M_TYPE {
+ z0:=NewFP8copy(F.a)
+ z1:=NewFP8int(0)
+ z2:=NewFP8int(0)
+ z3:=NewFP8int(0)
+ t0:=NewFP8copy(F.a)
+ t1:=NewFP8int(0)
+
+ z0.mul(y.a)
+ t0.add(F.b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(F.b); t0.add(F.c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ F.b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(F.c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ F.c.copy(z2); F.c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ F.b.add(t0)
+ z3.norm()
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
}
+ F.stype=FP_DENSE
F.norm()
}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP24) smul(y *FP24) {
+ if SEXTIC_TWIST==D_TYPE {
+ w1:=NewFP4copy(F.a.geta())
+ w2:=NewFP4copy(F.a.getb())
+ w3:=NewFP4copy(F.b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ ta:=NewFP4copy(F.a.geta())
+ tb:=NewFP4copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP4copy(ta)
+ tc.mul(tb);
+ t:=NewFP4copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ td:=NewFP4copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ te:=NewFP4copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+ F.b.geta().copy(td); F.b.getb().copy(te)
+ F.c.geta().copy(w3); F.c.getb().zero()
+
+ F.a.norm()
+ F.b.norm()
+ } else {
+ w1:=NewFP4copy(F.a.geta())
+ w2:=NewFP4copy(F.a.getb())
+ w3:=NewFP4copy(F.c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ ta:=NewFP4copy(F.a.geta())
+ tb:=NewFP4copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP4copy(ta)
+ tc.mul(tb);
+ t:=NewFP4copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ td:=NewFP4copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ te:=NewFP4copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+
+ w3.times_i()
+ w3.norm()
+ F.b.geta().zero(); F.b.getb().copy(w3)
+
+ te.norm()
+ te.times_i()
+ F.c.geta().copy(te)
+ F.c.getb().copy(td)
+
+ F.a.norm()
+ F.c.norm()
+
+ }
+ F.stype=FP_SPARSE;
+}
+
/* this=1/this */
func (F *FP24) Inverse() {
f0 := NewFP8copy(F.a)
@@ -458,6 +667,7 @@
F.b.mul(f3)
F.c.copy(f2)
F.c.mul(f3)
+ F.stype=FP_DENSE
}
/* this=this^p using Frobenius */
@@ -482,6 +692,7 @@
F.c.times_i2()
F.c.times_i2()
}
+ F.stype=FP_DENSE
}
/* trace function */
diff --git a/version3/go/FP48.go b/version3/go/FP48.go
index 05517da..481e21a 100644
--- a/version3/go/FP48.go
+++ b/version3/go/FP48.go
@@ -28,6 +28,7 @@
a *FP16
b *FP16
c *FP16
+ stype int
}
/* Constructors */
@@ -36,6 +37,7 @@
F.a = NewFP16copy(d)
F.b = NewFP16int(0)
F.c = NewFP16int(0)
+ F.stype=FP_SPARSER
return F
}
@@ -44,6 +46,11 @@
F.a = NewFP16int(d)
F.b = NewFP16int(0)
F.c = NewFP16int(0)
+ if d==1 {
+ F.stype=FP_ONE
+ } else {
+ F.stype=FP_SPARSER
+ }
return F
}
@@ -52,6 +59,7 @@
F.a = NewFP16copy(d)
F.b = NewFP16copy(e)
F.c = NewFP16copy(f)
+ F.stype=FP_DENSE
return F
}
@@ -60,6 +68,7 @@
F.a = NewFP16copy(x.a)
F.b = NewFP16copy(x.b)
F.c = NewFP16copy(x.c)
+ F.stype=x.stype
return F
}
@@ -87,6 +96,8 @@
F.a.cmove(g.a, d)
F.b.cmove(g.b, d)
F.c.cmove(g.c, d)
+ d=^(d-1)
+ F.stype^=(F.stype^g.stype)&d
}
/* Constant time select from pre-computed table */
@@ -142,10 +153,12 @@
F.a.copy(x.a)
F.b.copy(x.b)
F.c.copy(x.c)
+ F.stype=x.stype
}
/* set this=1 */
func (F *FP48) one() {
+ F.stype=FP_ONE
F.a.one()
F.b.zero()
F.c.zero()
@@ -197,11 +210,14 @@
F.b.add(B)
F.c.add(C)
F.reduce()
-
+ F.stype=FP_DENSE
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
func (F *FP48) sqr() {
+ if F.stype==FP_ONE {
+ return
+ }
A := NewFP16copy(F.a)
B := NewFP16copy(F.b)
C := NewFP16copy(F.c)
@@ -237,6 +253,11 @@
F.b.copy(C)
F.b.add(D)
F.c.add(A)
+ if F.stype==FP_SPARSER {
+ F.stype=FP_SPARSE
+ } else {
+ F.stype=FP_DENSE
+ }
F.norm()
}
@@ -305,113 +326,302 @@
z3.times_i()
F.a.copy(z0)
F.a.add(z3)
+ F.stype=FP_DENSE
F.norm()
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
-func (F *FP48) smul(y *FP48, twist int) {
- if twist == D_TYPE {
- z0 := NewFP16copy(F.a)
- z2 := NewFP16copy(F.b)
- z3 := NewFP16copy(F.b)
- t0 := NewFP16int(0)
- t1 := NewFP16copy(y.a)
-
- z0.mul(y.a)
- z2.pmul(y.b.real())
- F.b.add(F.a)
- t1.real().add(y.b.real())
-
- t1.norm()
- F.b.norm()
- F.b.mul(t1)
- z3.add(F.c)
- z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0)
- t0.neg()
- t1.copy(z2)
- t1.neg()
-
- F.b.add(t0)
- F.b.add(t1)
- z3.add(t1)
- z3.norm()
- z2.add(t0)
-
- t0.copy(F.a)
- t0.add(F.c)
- t0.norm()
- t0.mul(y.a)
- F.c.copy(z2)
- F.c.add(t0)
-
- z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+func (F *FP48) ssmul(y *FP48) {
+ if F.stype==FP_ONE {
+ F.Copy(y)
+ return
}
- if twist == M_TYPE {
- z0 := NewFP16copy(F.a)
- z1 := NewFP16int(0)
- z2 := NewFP16int(0)
- z3 := NewFP16int(0)
- t0 := NewFP16copy(F.a)
- t1 := NewFP16int(0)
-
+ if y.stype==FP_ONE {
+ return
+ }
+ if y.stype>=FP_SPARSE {
+ z0:=NewFP16copy(F.a)
+ z1:=NewFP16int(0)
+ z2:=NewFP16int(0)
+ z3:=NewFP16int(0)
z0.mul(y.a)
- t0.add(F.b)
- t0.norm()
- z1.copy(t0)
- z1.mul(y.a)
- t0.copy(F.b)
- t0.add(F.c)
- t0.norm()
+ if SEXTIC_TWIST==M_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ z2.getb().copy(F.b.getb())
+ z2.getb().mul(y.b.getb())
+ z2.geta().zero()
+ if y.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.getb())
+ z2.geta().mul(y.b.geta())
+ }
+ if F.stype!=FP_SPARSE {
+ z2.geta().copy(F.b.geta())
+ z2.geta().mul(y.b.getb())
+ }
+ z2.times_i()
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(F.b)
+ z2.mul(y.b)
+ }
+ t0:=NewFP16copy(F.a)
+ t1:=NewFP16copy(y.a)
+ t0.add(F.b); t0.norm();
+ t1.add(y.b); t1.norm()
- z3.copy(t0)
- z3.pmul(y.c.getb())
- z3.times_i()
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(F.b); t0.add(F.c); t0.norm()
+ t1.copy(y.b); t1.add(y.c); t1.norm()
- t0.copy(z0)
- t0.neg()
+ z3.copy(t0); z3.mul(t1)
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
z1.add(t0)
- F.b.copy(z1)
- z2.copy(t0)
+ F.b.copy(z1); F.b.add(t1)
- t0.copy(F.a)
- t0.add(F.c)
- t1.copy(y.a)
- t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
-
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
t0.mul(t1)
z2.add(t0)
- t0.copy(F.c)
+ if SEXTIC_TWIST==D_TYPE {
+ if y.stype==FP_SPARSE || F.stype==FP_SPARSE {
+ t0.geta().copy(F.c.geta())
+ t0.geta().mul(y.c.geta())
+ t0.getb().zero()
+ if y.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.geta())
+ t0.getb().mul(y.c.getb())
+ }
+ if F.stype!=FP_SPARSE {
+ t0.getb().copy(F.c.getb())
+ t0.getb().mul(y.c.geta())
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(F.c)
+ t0.mul(y.c)
+ }
+ t1.copy(t0); t1.neg()
- t0.pmul(y.c.getb())
- t0.times_i()
-
- t1.copy(t0)
- t1.neg()
-
- F.c.copy(z2)
- F.c.add(t1)
+ F.c.copy(z2); F.c.add(t1)
z3.add(t1)
t0.times_i()
F.b.add(t0)
z3.norm()
z3.times_i()
- F.a.copy(z0)
- F.a.add(z3)
+ F.a.copy(z0); F.a.add(z3);
+ } else {
+ if F.stype==FP_SPARSER {
+ F.smul(y)
+ return
+ }
+ if SEXTIC_TWIST==D_TYPE { // dense by sparser - 13m
+ z0:=NewFP16copy(F.a)
+ z2:=NewFP16copy(F.b)
+ z3:=NewFP16copy(F.b)
+ t0:=NewFP16int(0)
+ t1:=NewFP16copy(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ F.b.add(F.a)
+ t1.real().add(y.b.real())
+
+ t1.norm()
+ F.b.norm()
+ F.b.mul(t1)
+ z3.add(F.c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ F.b.add(t0)
+
+ F.b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ F.c.copy(z2); F.c.add(t0)
+
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
+ if SEXTIC_TWIST==M_TYPE {
+ z0:=NewFP16copy(F.a)
+ z1:=NewFP16int(0)
+ z2:=NewFP16int(0)
+ z3:=NewFP16int(0)
+ t0:=NewFP16copy(F.a)
+ t1:=NewFP16int(0)
+
+ z0.mul(y.a)
+ t0.add(F.b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(F.b); t0.add(F.c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ F.b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(F.a); t0.add(F.c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(F.c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ F.c.copy(z2); F.c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ F.b.add(t0)
+ z3.norm()
+ z3.times_i()
+ F.a.copy(z0); F.a.add(z3)
+ }
}
+ F.stype=FP_DENSE
F.norm()
}
+
+/* Special case of multiplication arises from special form of ATE pairing line function */
+func (F *FP48) smul(y *FP48) {
+ if SEXTIC_TWIST==D_TYPE {
+ w1:=NewFP8copy(F.a.geta())
+ w2:=NewFP8copy(F.a.getb())
+ w3:=NewFP8copy(F.b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ ta:=NewFP8copy(F.a.geta())
+ tb:=NewFP8copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP8copy(ta)
+ tc.mul(tb);
+ t:=NewFP8copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ td:=NewFP8copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ te:=NewFP8copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+ F.b.geta().copy(td); F.b.getb().copy(te)
+ F.c.geta().copy(w3); F.c.getb().zero()
+
+ F.a.norm()
+ F.b.norm()
+ } else {
+ w1:=NewFP8copy(F.a.geta())
+ w2:=NewFP8copy(F.a.getb())
+ w3:=NewFP8copy(F.c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ ta:=NewFP8copy(F.a.geta())
+ tb:=NewFP8copy(y.a.geta())
+ ta.add(F.a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ tc:=NewFP8copy(ta)
+ tc.mul(tb);
+ t:=NewFP8copy(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(F.a.geta()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ td:=NewFP8copy(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(F.a.getb()); ta.add(F.c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ te:=NewFP8copy(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+ F.a.geta().copy(w1); F.a.getb().copy(tc)
+
+ w3.times_i()
+ w3.norm()
+ F.b.geta().zero(); F.b.getb().copy(w3)
+
+ te.norm()
+ te.times_i()
+ F.c.geta().copy(te)
+ F.c.getb().copy(td)
+
+ F.a.norm()
+ F.c.norm()
+
+ }
+ F.stype=FP_SPARSE;
+}
+
/* this=1/this */
func (F *FP48) Inverse() {
f0 := NewFP16copy(F.a)
@@ -457,6 +667,7 @@
F.b.mul(f3)
F.c.copy(f2)
F.c.mul(f3)
+ F.stype=FP_DENSE
}
/* this=this^p using Frobenius */
@@ -485,6 +696,7 @@
F.c.times_i4()
F.c.times_i4()
}
+ F.stype=FP_DENSE
}
/* trace function */
diff --git a/version3/go/PAIR.go b/version3/go/PAIR.go
index 35a3d8d..acacc69 100644
--- a/version3/go/PAIR.go
+++ b/version3/go/PAIR.go
@@ -123,38 +123,135 @@
A.Add(B)
}
- return NewFP12fp4s(a, b, c)
+ r:=NewFP12fp4s(a, b, c)
+ r.stype=FP_SPARSER
+ return r
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+func lbits(n3 *BIG,n *BIG) int {
+ n.copy(NewBIGints(CURVE_Bnx))
+ if CURVE_PAIRING_TYPE==BN {
+ n.pmul(6)
+ if SIGN_OF_X==POSITIVEX {
+ n.inc(2)
+ } else {
+ n.dec(2)
+ }
+ }
+
+ n.norm()
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+}
+
+/* prepare for multi-pairing */
+func initmp() []*FP12 {
+ var r []*FP12
+ for i:=ATE_BITS-1; i>=0; i-- {
+ r=append(r,NewFP12int(1))
+ }
+ return r
+}
+
+/* basic Miller loop */
+func miller(r []*FP12) *FP12 {
+ res:=NewFP12int(1);
+ for i:=ATE_BITS-1; i>=1; i-- {
+ res.sqr()
+ res.ssmul(r[i]);
+ }
+
+ if SIGN_OF_X==NEGATIVEX {
+ res.conj()
+ }
+ res.ssmul(r[0])
+ return res
+}
+
+/* Accumulate another set of line functions for n-pairing */
+func another(r []*FP12,P1 *ECP2,Q1 *ECP) {
+ f:=NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
+ n:=NewBIG()
+ n3:=NewBIG()
+ K:=NewECP2();
+ var lv,lv2 *FP12
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ P:=NewECP2()
+ P.Copy(P1)
+ Q:=NewECP()
+ Q.Copy(Q1)
+
+ P.Affine()
+ Q.Affine()
+
+ if CURVE_PAIRING_TYPE==BN {
+ if SEXTIC_TWIST==M_TYPE {
+ f.inverse()
+ f.norm()
+ }
+ }
+
+ Qx := NewFPcopy(Q.getx())
+ Qy := NewFPcopy(Q.gety())
+
+ A:=NewECP2()
+ A.Copy(P)
+
+ MP:=NewECP2()
+ MP.Copy(P); MP.neg()
+
+ nb:=lbits(n3,n)
+
+ for i:=nb-2;i>=1;i-- {
+ lv=line(A,A,Qx,Qy)
+
+ bt:=n3.bit(i)-n.bit(i)
+ if bt==1 {
+ lv2=line(A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt==-1 {
+ lv2=line(A,MP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
+
+/* R-ate fixup required for BN curves */
+ if CURVE_PAIRING_TYPE==BN {
+ if SIGN_OF_X==NEGATIVEX {
+ A.neg()
+ }
+ K.Copy(P)
+ K.frob(f)
+ lv=line(A,K,Qx,Qy)
+ K.frob(f)
+ K.neg()
+ lv2=line(A,K,Qx,Qy)
+ lv.smul(lv2)
+ r[0].ssmul(lv)
+ }
}
/* Optimal R-ate pairing */
func Ate(P1 *ECP2, Q1 *ECP) *FP12 {
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
+ n:=NewBIG()
+ n3:=NewBIG()
K := NewECP2()
- var lv *FP12
+ var lv,lv2 *FP12
if CURVE_PAIRING_TYPE == BN {
if SEXTIC_TWIST == M_TYPE {
f.inverse()
f.norm()
}
- n.pmul(6)
- if SIGN_OF_X == POSITIVEX {
- n.inc(2)
- } else {
- n.dec(2)
- }
- } else {
- n.copy(x)
}
- n.norm()
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
-
P := NewECP2()
P.Copy(P1)
P.Affine()
@@ -174,21 +271,21 @@
NP.Copy(P)
NP.neg()
- nb := n3.nbits()
+ nb:=lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
- lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, P, Qx, Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, NP, Qx, Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if SIGN_OF_X == NEGATIVEX {
@@ -205,11 +302,11 @@
K.Copy(P)
K.frob(f)
lv = line(A, K, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv = line(A, K, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, K, Qx, Qy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
return r
@@ -218,32 +315,18 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
func Ate2(P1 *ECP2, Q1 *ECP, R1 *ECP2, S1 *ECP) *FP12 {
f := NewFP2bigs(NewBIGints(Fra), NewBIGints(Frb))
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
+ n:=NewBIG()
+ n3:=NewBIG()
K := NewECP2()
- var lv *FP12
+ var lv,lv2 *FP12
if CURVE_PAIRING_TYPE == BN {
if SEXTIC_TWIST == M_TYPE {
f.inverse()
f.norm()
}
- n.pmul(6)
- if SIGN_OF_X == POSITIVEX {
- n.inc(2)
- } else {
- n.dec(2)
- }
- } else {
- n.copy(x)
}
- n.norm()
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
-
P := NewECP2()
P.Copy(P1)
P.Affine()
@@ -275,26 +358,26 @@
NR.Copy(R)
NR.neg()
- nb := n3.nbits()
+ nb:=lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, B, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, B, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, R, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, R, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, NR, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, NR, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
}
@@ -312,21 +395,19 @@
K.frob(f)
lv = line(A, K, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv = line(A, K, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
-
+ lv2 = line(A, K, Qx, Qy)
+ lv.smul(lv2)
+ r.ssmul(lv)
K.Copy(R)
K.frob(f)
-
lv = line(B, K, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv = line(B, K, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, K, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
return r
diff --git a/version3/go/PAIR192.go b/version3/go/PAIR192.go
index fe92256..a22877f 100644
--- a/version3/go/PAIR192.go
+++ b/version3/go/PAIR192.go
@@ -123,18 +123,92 @@
A.Add(B)
}
- return NewFP24fp8s(a, b, c)
+ r:=NewFP24fp8s(a, b, c)
+ r.stype=FP_SPARSER
+ return r
}
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+func lbits(n3 *BIG,n *BIG) int {
+ n.copy(NewBIGints(CURVE_Bnx))
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+}
+
+/* prepare for multi-pairing */
+func initmp() []*FP24 {
+ var r []*FP24
+ for i:=ATE_BITS-1; i>=0; i-- {
+ r=append(r,NewFP24int(1))
+ }
+ return r
+}
+
+/* basic Miller loop */
+func miller(r []*FP24) *FP24 {
+ res:=NewFP24int(1);
+ for i:=ATE_BITS-1; i>=1; i-- {
+ res.sqr()
+ res.ssmul(r[i]);
+ }
+
+ if SIGN_OF_X==NEGATIVEX {
+ res.conj()
+ }
+ res.ssmul(r[0])
+ return res
+}
+
+/* Accumulate another set of line functions for n-pairing */
+func another(r []*FP24,P1 *ECP4,Q1 *ECP) {
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP24
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ P:=NewECP4()
+ P.Copy(P1)
+ Q:=NewECP()
+ Q.Copy(Q1)
+
+ P.Affine()
+ Q.Affine()
+
+ Qx := NewFPcopy(Q.getx())
+ Qy := NewFPcopy(Q.gety())
+
+ A:=NewECP4()
+ A.Copy(P)
+
+ MP:=NewECP4()
+ MP.Copy(P); MP.neg()
+
+ nb:=lbits(n3,n)
+
+ for i:=nb-2;i>=1;i-- {
+ lv=line(A,A,Qx,Qy)
+
+ bt:=n3.bit(i)-n.bit(i)
+ if bt==1 {
+ lv2=line(A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt==-1 {
+ lv2=line(A,MP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
+}
+
+
/* Optimal R-ate pairing */
func Ate(P1 *ECP4, Q1 *ECP) *FP24 {
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
- var lv *FP24
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP24
P := NewECP4()
P.Copy(P1)
@@ -154,21 +228,22 @@
NP.Copy(P)
NP.neg()
- nb := n3.nbits()
+ nb:=lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
- lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, P, Qx, Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, NP, Qx, Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if SIGN_OF_X == NEGATIVEX {
@@ -180,13 +255,9 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
func Ate2(P1 *ECP4, Q1 *ECP, R1 *ECP4, S1 *ECP) *FP24 {
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
- var lv *FP24
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP24
P := NewECP4()
P.Copy(P1)
@@ -219,26 +290,26 @@
NR.Copy(R)
NR.neg()
- nb := n3.nbits()
+ nb := lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, B, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, B, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, R, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, R, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, NR, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, NR, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
}
diff --git a/version3/go/PAIR256.go b/version3/go/PAIR256.go
index 05e2c21..fcd8821 100644
--- a/version3/go/PAIR256.go
+++ b/version3/go/PAIR256.go
@@ -123,18 +123,91 @@
A.Add(B)
}
- return NewFP48fp16s(a, b, c)
+ r:=NewFP48fp16s(a, b, c)
+ r.stype=FP_SPARSER
+ return r
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+func lbits(n3 *BIG,n *BIG) int {
+ n.copy(NewBIGints(CURVE_Bnx))
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+}
+
+/* prepare for multi-pairing */
+func initmp() []*FP48 {
+ var r []*FP48
+ for i:=ATE_BITS-1; i>=0; i-- {
+ r=append(r,NewFP48int(1))
+ }
+ return r
+}
+
+/* basic Miller loop */
+func miller(r []*FP48) *FP48 {
+ res:=NewFP48int(1);
+ for i:=ATE_BITS-1; i>=1; i-- {
+ res.sqr()
+ res.ssmul(r[i]);
+ }
+
+ if SIGN_OF_X==NEGATIVEX {
+ res.conj()
+ }
+ res.ssmul(r[0])
+ return res
+}
+
+/* Accumulate another set of line functions for n-pairing */
+func another(r []*FP48,P1 *ECP8,Q1 *ECP) {
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP48
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ P:=NewECP8()
+ P.Copy(P1)
+ Q:=NewECP()
+ Q.Copy(Q1)
+
+ P.Affine()
+ Q.Affine()
+
+ Qx := NewFPcopy(Q.getx())
+ Qy := NewFPcopy(Q.gety())
+
+ A:=NewECP8()
+ A.Copy(P)
+
+ MP:=NewECP8()
+ MP.Copy(P); MP.neg()
+
+ nb:=lbits(n3,n)
+
+ for i:=nb-2;i>=1;i-- {
+ lv=line(A,A,Qx,Qy)
+
+ bt:=n3.bit(i)-n.bit(i)
+ if bt==1 {
+ lv2=line(A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt==-1 {
+ lv2=line(A,MP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
}
/* Optimal R-ate pairing */
func Ate(P1 *ECP8, Q1 *ECP) *FP48 {
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
- var lv *FP48
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP48
P := NewECP8()
P.Copy(P1)
@@ -154,21 +227,22 @@
NP.Copy(P)
NP.neg()
- nb := n3.nbits()
+ nb:=lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
- lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, P, Qx, Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(A, NP, Qx, Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if SIGN_OF_X == NEGATIVEX {
@@ -180,13 +254,9 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
func Ate2(P1 *ECP8, Q1 *ECP, R1 *ECP8, S1 *ECP) *FP48 {
- x := NewBIGints(CURVE_Bnx)
- n := NewBIGcopy(x)
- var lv *FP48
-
- n3 := NewBIGcopy(n)
- n3.pmul(3)
- n3.norm()
+ n:=NewBIG()
+ n3:=NewBIG()
+ var lv,lv2 *FP48
P := NewECP8()
P.Copy(P1)
@@ -219,26 +289,26 @@
NR.Copy(R)
NR.neg()
- nb := n3.nbits()
+ nb := lbits(n3,n)
for i := nb - 2; i >= 1; i-- {
r.sqr()
lv = line(A, A, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, B, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, B, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
bt := n3.bit(i) - n.bit(i)
if bt == 1 {
lv = line(A, P, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, R, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, R, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv = line(A, NP, Qx, Qy)
- r.smul(lv, SEXTIC_TWIST)
- lv = line(B, NR, Sx, Sy)
- r.smul(lv, SEXTIC_TWIST)
+ lv2 = line(B, NR, Sx, Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
}
diff --git a/version3/go/config32.py b/version3/go/config32.py
index 02d4fdb..3bb75ca 100644
--- a/version3/go/config32.py
+++ b/version3/go/config32.py
@@ -63,7 +63,7 @@
replace(fpath+"CONFIG_FF.go","@ML@",ml);
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -116,6 +116,7 @@
replace(fpath+"CONFIG_CURVE.go","@ST@",stw)
replace(fpath+"CONFIG_CURVE.go","@SX@",sx)
+ replace(fpath+"CONFIG_CURVE.go","@AB@",ab)
if cs == "128" :
replace(fpath+"CONFIG_CURVE.go","@HT@","32")
@@ -251,7 +252,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,ate_bits,curve security)
# where "curve" is the common name for the elliptic curve
# big_length_bytes is the modulus size rounded up to a number of bytes
# bits_in_base gives the number base used for 32 bit architectures, as n where the base is 2^n
@@ -260,95 +261,96 @@
# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# ate bits is number of bits in Ate parameter (from romgen program)
# curve security is AES equiavlent, rounded up.
if x==1:
- curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==4:
- curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==5:
- curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==6:
- curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==8:
- curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==9:
- curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==18:
- curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/go/config64.py b/version3/go/config64.py
index cec591d..2ceea37 100644
--- a/version3/go/config64.py
+++ b/version3/go/config64.py
@@ -63,7 +63,7 @@
replace(fpath+"CONFIG_FF.go","@ML@",ml);
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -116,6 +116,7 @@
replace(fpath+"CONFIG_CURVE.go","@ST@",stw)
replace(fpath+"CONFIG_CURVE.go","@SX@",sx)
+ replace(fpath+"CONFIG_CURVE.go","@AB@",ab)
if cs == "128" :
replace(fpath+"CONFIG_CURVE.go","@HT@","32")
@@ -251,7 +252,7 @@
selection.append(x)
ptr=ptr+1
-# curveset(curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,curve security)
+# curveset(big,field,curve,big_length_bytes,bits_in_base,modulus_bits,modulus_mod_8,modulus_type,curve_type,pairing_friendly,sextic twist,sign of x,ate bits,curve security)
# where "curve" is the common name for the elliptic curve
# big_length_bytes is the modulus size rounded up to a number of bytes
# bits_in_base gives the number base used for 64 bit architectures, as n where the base is 2^n
@@ -260,96 +261,97 @@
# modulus_type is NOT_SPECIAL, or PSEUDO_MERSENNE, or MONTGOMERY_Friendly, or GENERALISED_MERSENNE (supported for GOLDILOCKS only)
# curve_type is WEIERSTRASS, EDWARDS or MONTGOMERY
# pairing_friendly is BN, BLS or NOT (if not pairing friendly
+# ate bits is number of bits in Ate parameter (from romgen program)
# curve security is AES equiavlent, rounded up.
if x==1:
- curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==4:
- curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==5:
- curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==6:
- curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==8:
- curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==9:
- curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("NUMS512E","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("NUMS512E","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==18:
- curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","42","256")
pfcurve_selected=True
diff --git a/version3/java/BLS.java b/version3/java/BLS.java
index dd6f57e..ac4191b 100644
--- a/version3/java/BLS.java
+++ b/version3/java/BLS.java
@@ -79,7 +79,16 @@
ECP2 G=ECP2.generator();
ECP2 PK=ECP2.fromBytes(W);
D.neg();
- FP12 v=PAIR.ate2(G,D,PK,HM);
+
+// Use new multi-pairing mechanism
+ FP12[] r=PAIR.initmp();
+ PAIR.another(r,G,D);
+ PAIR.another(r,PK,HM);
+ FP12 v=PAIR.miller(r);
+
+//.. or alternatively
+// FP12 v=PAIR.ate2(G,D,PK,HM);
+
v=PAIR.fexp(v);
if (v.isunity())
return BLS_OK;
diff --git a/version3/java/BLS192.java b/version3/java/BLS192.java
index 0a2c463..a55d183 100644
--- a/version3/java/BLS192.java
+++ b/version3/java/BLS192.java
@@ -79,7 +79,16 @@
ECP4 G=ECP4.generator();
ECP4 PK=ECP4.fromBytes(W);
D.neg();
- FP24 v=PAIR192.ate2(G,D,PK,HM);
+
+// Use new multi-pairing mechanism
+ FP24[] r=PAIR192.initmp();
+ PAIR192.another(r,G,D);
+ PAIR192.another(r,PK,HM);
+ FP24 v=PAIR192.miller(r);
+
+//.. or alternatively
+// FP24 v=PAIR192.ate2(G,D,PK,HM);
+
v=PAIR192.fexp(v);
if (v.isunity())
return BLS_OK;
diff --git a/version3/java/BLS256.java b/version3/java/BLS256.java
index 8f2e444..8b902f4 100644
--- a/version3/java/BLS256.java
+++ b/version3/java/BLS256.java
@@ -79,7 +79,16 @@
ECP8 G=ECP8.generator();
ECP8 PK=ECP8.fromBytes(W);
D.neg();
- FP48 v=PAIR256.ate2(G,D,PK,HM);
+
+// Use new multi-pairing mechanism
+ FP48[] r=PAIR256.initmp();
+ PAIR256.another(r,G,D);
+ PAIR256.another(r,PK,HM);
+ FP48 v=PAIR256.miller(r);
+
+//.. or alternatively
+// FP48 v=PAIR256.ate2(G,D,PK,HM);
+
v=PAIR256.fexp(v);
if (v.isunity())
return BLS_OK;
diff --git a/version3/java/CONFIG_CURVE.java b/version3/java/CONFIG_CURVE.java
index 232e654..b6bd5ce 100644
--- a/version3/java/CONFIG_CURVE.java
+++ b/version3/java/CONFIG_CURVE.java
@@ -16,6 +16,8 @@
public static final int CURVE_PAIRING_TYPE=@PF@;
public static final int SEXTIC_TWIST=@ST@;
public static final int SIGN_OF_X=@SX@;
+ public static final int ATE_BITS= @AB@;
+
public static final int SHA256=32;
public static final int SHA384=48;
diff --git a/version3/java/FP12.java b/version3/java/FP12.java
index bc3b6a3..551037c 100644
--- a/version3/java/FP12.java
+++ b/version3/java/FP12.java
@@ -23,9 +23,26 @@
package org.apache.milagro.amcl.XXX;
public final class FP12 {
+ public static final int ZERO=0;
+ public static final int ONE=1;
+ public static final int SPARSER=2;
+ public static final int SPARSE=3;
+ public static final int DENSE=4;
+
private final FP4 a;
private final FP4 b;
private final FP4 c;
+ private int type;
+
+ public void settype(int a)
+ {
+ type=a;
+ }
+
+ public int gettype()
+ {
+ return type;
+ }
/* reduce all components of this mod Modulus */
public void reduce()
{
@@ -51,6 +68,8 @@
a.cmove(g.a,d);
b.cmove(g.b,d);
c.cmove(g.c,d);
+ d=~(d-1);
+ type^=(type^g.type)&d;
}
@@ -116,6 +135,7 @@
a.copy(x.a);
b.copy(x.b);
c.copy(x.c);
+ type=x.type;
}
/* set this=1 */
public void one()
@@ -123,6 +143,7 @@
a.one();
b.zero();
c.zero();
+ type=ONE;
}
/* this=conj(this) */
public void conj()
@@ -137,6 +158,7 @@
a=new FP4(d);
b=new FP4(0);
c=new FP4(0);
+ type=SPARSER;
}
public FP12(int d)
@@ -144,6 +166,10 @@
a=new FP4(d);
b=new FP4(0);
c=new FP4(0);
+ if (d==1)
+ type=ONE;
+ else
+ type=SPARSER;
}
public FP12(FP4 d,FP4 e,FP4 f)
@@ -151,6 +177,7 @@
a=new FP4(d);
b=new FP4(e);
c=new FP4(f);
+ type=DENSE;
}
public FP12(FP12 x)
@@ -158,6 +185,7 @@
a=new FP4(x.a);
b=new FP4(x.b);
c=new FP4(x.c);
+ type=x.type;
}
/* Granger-Scott Unitary Squaring */
@@ -196,12 +224,16 @@
c.add(c);
b.add(B);
c.add(C);
+ type=DENSE;
reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
public void sqr()
{
+ if (type==ONE)
+ return;
+
FP4 A=new FP4(a);
FP4 B=new FP4(b);
FP4 C=new FP4(c);
@@ -236,6 +268,10 @@
b.copy(C); b.add(D);
c.add(A);
+ if (type==SPARSER)
+ type=SPARSE;
+ else
+ type=DENSE;
norm();
}
@@ -297,9 +333,320 @@
z3.times_i();
a.copy(z0); a.add(z3);
norm();
+ type=DENSE;
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
+/* 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 */
+ public void smul(FP12 y)
+ {
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ FP2 w1=new FP2(a.geta());
+ FP2 w2=new FP2(a.getb());
+ FP2 w3=new FP2(b.geta());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ FP2 ta=new FP2(a.geta());
+ FP2 tb=new FP2(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP2 tc=new FP2(ta);
+ tc.mul(tb);
+ FP2 t=new FP2(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ FP2 td=new FP2(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ FP2 te=new FP2(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.mul_ip();
+ w1.add(w2);
+
+ a.geta().copy(w1); a.getb().copy(tc);
+ b.geta().copy(td); b.getb().copy(te);
+ c.geta().copy(w3); c.getb().zero();
+
+ a.norm();
+ b.norm();
+
+ } else {
+ FP2 w1=new FP2(a.geta());
+ FP2 w2=new FP2(a.getb());
+ FP2 w3=new FP2(c.getb());
+
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
+
+ FP2 ta=new FP2(a.geta());
+ FP2 tb=new FP2(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP2 tc=new FP2(ta);
+ tc.mul(tb);
+ FP2 t=new FP2(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ FP2 td=new FP2(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ FP2 te=new FP2(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.mul_ip();
+ w1.add(w2);
+ a.geta().copy(w1); a.getb().copy(tc);
+
+ w3.mul_ip();
+ w3.norm();
+ b.geta().zero(); b.getb().copy(w3);
+
+ te.norm();
+ te.mul_ip();
+ c.geta().copy(te);
+ c.getb().copy(td);
+
+ a.norm();
+ c.norm();
+
+ }
+ type=SPARSE;
+ }
+
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ public void ssmul(FP12 y)
+ {
+ if (type==ONE)
+ {
+ copy(y);
+ return;
+ }
+ if (y.type==ONE)
+ return;
+
+ if (y.type>=SPARSE)
+ {
+ FP4 z0=new FP4(a);
+ FP4 z1=new FP4(0);
+ FP4 z2=new FP4(0);
+ FP4 z3=new FP4(0);
+ z0.mul(y.a);
+
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ z2.getb().copy(b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.type!=SPARSE)
+ {
+ z2.geta().copy(b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (type!=SPARSE)
+ {
+ z2.geta().copy(b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ FP4 t0=new FP4(a);
+ FP4 t1=new FP4(y.a);
+ t0.add(b); t0.norm();
+ t1.add(y.b); t1.norm();
+
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(b); t0.add(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);
+ b.copy(z1); b.add(t1);
+
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ t0.geta().copy(c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.type!=SPARSE)
+ {
+ t0.getb().copy(c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (type!=SPARSE)
+ {
+ t0.getb().copy(c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
+ t1.copy(t0); t1.neg();
+
+ c.copy(z2); c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ b.add(t0);
+ z3.norm();
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ } else {
+ if (type==SPARSER)
+ {
+ smul(y);
+ return;
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ { // dense by sparser - 13m
+ FP4 z0=new FP4(a);
+ FP4 z2=new FP4(b);
+ FP4 z3=new FP4(b);
+ FP4 t0=new FP4(0);
+ FP4 t1=new FP4(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ b.add(a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ b.norm();
+ b.mul(t1);
+ z3.add(c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ b.add(t0);
+
+ b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ c.copy(z2); c.add(t0);
+
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ FP4 z0=new FP4(a);
+ FP4 z1=new FP4(0);
+ FP4 z2=new FP4(0);
+ FP4 z3=new FP4(0);
+ FP4 t0=new FP4(a);
+ FP4 t1=new FP4(0);
+
+ z0.mul(y.a);
+ t0.add(b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(b); t0.add(c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ c.copy(z2); c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ b.add(t0);
+ z3.norm();
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
+ }
+ type=DENSE;
+ norm();
+ }
+
+/* Special case of multiplication arises from special form of ATE pairing line function
public void smul(FP12 y,int type)
{
if (type==CONFIG_CURVE.D_TYPE)
@@ -392,7 +739,7 @@
}
norm();
}
-
+*/
/* this=1/this */
public void inverse()
{
@@ -432,6 +779,7 @@
a.copy(f0); a.mul(f3);
b.copy(f1); b.mul(f3);
c.copy(f2); c.mul(f3);
+ type=DENSE;
}
/* this=this^p using Frobenius */
@@ -449,6 +797,7 @@
b.pmul(f);
c.pmul(f2);
+ type=DENSE;
}
/* trace function */
diff --git a/version3/java/FP24.java b/version3/java/FP24.java
index c968d3c..9338ea6 100644
--- a/version3/java/FP24.java
+++ b/version3/java/FP24.java
@@ -23,9 +23,26 @@
package org.apache.milagro.amcl.XXX;
public final class FP24 {
+ public static final int ZERO=0;
+ public static final int ONE=1;
+ public static final int SPARSER=2;
+ public static final int SPARSE=3;
+ public static final int DENSE=4;
+
private final FP8 a;
private final FP8 b;
private final FP8 c;
+ private int type;
+
+ public void settype(int a)
+ {
+ type=a;
+ }
+
+ public int gettype()
+ {
+ return type;
+ }
/* reduce all components of this mod Modulus */
public void reduce()
{
@@ -51,6 +68,8 @@
a.cmove(g.a,d);
b.cmove(g.b,d);
c.cmove(g.c,d);
+ d=~(d-1);
+ type^=(type^g.type)&d;
}
@@ -115,6 +134,7 @@
a.copy(x.a);
b.copy(x.b);
c.copy(x.c);
+ type=x.type;
}
/* set this=1 */
public void one()
@@ -122,6 +142,7 @@
a.one();
b.zero();
c.zero();
+ type=ONE;
}
/* this=conj(this) */
public void conj()
@@ -136,6 +157,7 @@
a=new FP8(d);
b=new FP8(0);
c=new FP8(0);
+ type=SPARSER;
}
public FP24(int d)
@@ -143,6 +165,10 @@
a=new FP8(d);
b=new FP8(0);
c=new FP8(0);
+ if (d==1)
+ type=ONE;
+ else
+ type=SPARSER;
}
public FP24(FP8 d,FP8 e,FP8 f)
@@ -150,6 +176,7 @@
a=new FP8(d);
b=new FP8(e);
c=new FP8(f);
+ type=DENSE;
}
public FP24(FP24 x)
@@ -157,6 +184,7 @@
a=new FP8(x.a);
b=new FP8(x.b);
c=new FP8(x.c);
+ type=x.type;
}
/* Granger-Scott Unitary Squaring */
@@ -195,12 +223,16 @@
c.add(c);
b.add(B);
c.add(C);
+ type=DENSE;
reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
public void sqr()
{
+ if (type==ONE)
+ return;
+
FP8 A=new FP8(a);
FP8 B=new FP8(b);
FP8 C=new FP8(c);
@@ -235,7 +267,10 @@
b.copy(C); b.add(D);
c.add(A);
-
+ if (type==SPARSER)
+ type=SPARSE;
+ else
+ type=DENSE;
norm();
}
@@ -297,90 +332,220 @@
z3.times_i();
a.copy(z0); a.add(z3);
norm();
-
+ type=DENSE;
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
- public void smul(FP24 y,int type)
+
+/* 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 */
+ public void smul(FP24 y)
{
- if (type==CONFIG_CURVE.D_TYPE)
- {
- FP8 z0=new FP8(a);
- FP8 z2=new FP8(b);
- FP8 z3=new FP8(b);
- FP8 t0=new FP8(0);
- FP8 t1=new FP8(y.a);
- z0.mul(y.a);
- z2.pmul(y.b.real());
- b.add(a);
- t1.real().add(y.b.real());
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ FP4 w1=new FP4(a.geta());
+ FP4 w2=new FP4(a.getb());
+ FP4 w3=new FP4(b.geta());
- t1.norm();
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ FP4 ta=new FP4(a.geta());
+ FP4 tb=new FP4(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP4 tc=new FP4(ta);
+ tc.mul(tb);
+ FP4 t=new FP4(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ FP4 td=new FP4(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ FP4 te=new FP4(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+
+ a.geta().copy(w1); a.getb().copy(tc);
+ b.geta().copy(td); b.getb().copy(te);
+ c.geta().copy(w3); c.getb().zero();
+
+ a.norm();
b.norm();
- b.mul(t1);
- z3.add(c);
- z3.norm();
- z3.pmul(y.b.real());
- t0.copy(z0); t0.neg();
- t1.copy(z2); t1.neg();
+ } else {
+ FP4 w1=new FP4(a.geta());
+ FP4 w2=new FP4(a.getb());
+ FP4 w3=new FP4(c.getb());
- b.add(t0);
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
- b.add(t1);
- z3.add(t1);
- z2.add(t0);
+ FP4 ta=new FP4(a.geta());
+ FP4 tb=new FP4(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP4 tc=new FP4(ta);
+ tc.mul(tb);
+ FP4 t=new FP4(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
- t0.copy(a); t0.add(c);
- t0.norm();
- z3.norm();
- t0.mul(y.a);
- c.copy(z2); c.add(t0);
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ FP4 td=new FP4(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
- z3.times_i();
- a.copy(z0); a.add(z3);
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ FP4 te=new FP4(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+ a.geta().copy(w1); a.getb().copy(tc);
+
+ w3.times_i();
+ w3.norm();
+ b.geta().zero(); b.getb().copy(w3);
+
+ te.norm();
+ te.times_i();
+ c.geta().copy(te);
+ c.getb().copy(td);
+
+ a.norm();
+ c.norm();
+
}
- if (type==CONFIG_CURVE.M_TYPE)
+ type=SPARSE;
+ }
+
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ public void ssmul(FP24 y)
+ {
+ if (type==ONE)
+ {
+ copy(y);
+ return;
+ }
+ if (y.type==ONE)
+ return;
+
+ if (y.type>=SPARSE)
{
FP8 z0=new FP8(a);
FP8 z1=new FP8(0);
FP8 z2=new FP8(0);
FP8 z3=new FP8(0);
- FP8 t0=new FP8(a);
- FP8 t1=new FP8(0);
-
z0.mul(y.a);
- t0.add(b);
- t0.norm();
- z1.copy(t0); z1.mul(y.a);
- t0.copy(b); t0.add(c);
- t0.norm();
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ z2.getb().copy(b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.type!=SPARSE)
+ {
+ z2.geta().copy(b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (type!=SPARSE)
+ {
+ z2.geta().copy(b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ FP8 t0=new FP8(a);
+ FP8 t1=new FP8(y.a);
+ t0.add(b); t0.norm();
+ t1.add(y.b); t1.norm();
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(b); t0.add(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);
- b.copy(z1);
- z2.copy(t0);
+ b.copy(z1); b.add(t1);
- t0.copy(a); t0.add(c);
- t1.copy(y.a); t1.add(y.c);
+ z3.add(t1);
+ z2.add(t0);
- t0.norm();
- t1.norm();
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
t0.mul(t1);
z2.add(t0);
- t0.copy(c);
-
- t0.pmul(y.c.getb());
- t0.times_i();
-
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ t0.geta().copy(c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.type!=SPARSE)
+ {
+ t0.getb().copy(c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (type!=SPARSE)
+ {
+ t0.getb().copy(c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
t1.copy(t0); t1.neg();
c.copy(z2); c.add(t1);
@@ -390,7 +555,94 @@
z3.norm();
z3.times_i();
a.copy(z0); a.add(z3);
+ } else {
+ if (type==SPARSER)
+ {
+ smul(y);
+ return;
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ { // dense by sparser - 13m
+ FP8 z0=new FP8(a);
+ FP8 z2=new FP8(b);
+ FP8 z3=new FP8(b);
+ FP8 t0=new FP8(0);
+ FP8 t1=new FP8(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ b.add(a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ b.norm();
+ b.mul(t1);
+ z3.add(c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ b.add(t0);
+
+ b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ c.copy(z2); c.add(t0);
+
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ FP8 z0=new FP8(a);
+ FP8 z1=new FP8(0);
+ FP8 z2=new FP8(0);
+ FP8 z3=new FP8(0);
+ FP8 t0=new FP8(a);
+ FP8 t1=new FP8(0);
+
+ z0.mul(y.a);
+ t0.add(b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(b); t0.add(c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ c.copy(z2); c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ b.add(t0);
+ z3.norm();
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
}
+ type=DENSE;
norm();
}
@@ -433,6 +685,7 @@
a.copy(f0); a.mul(f3);
b.copy(f1); b.mul(f3);
c.copy(f2); c.mul(f3);
+ type=DENSE;
}
/* this=this^p using Frobenius */
@@ -455,6 +708,7 @@
b.qmul(f); b.times_i2();
c.qmul(f2); c.times_i2(); c.times_i2();
}
+ type=DENSE;
}
/* trace function */
@@ -467,7 +721,7 @@
return t;
}
-/* convert from byte array to FP12 */
+/* convert from byte array to FP24 */
public static FP24 fromBytes(byte[] w)
{
BIG a,b;
diff --git a/version3/java/FP48.java b/version3/java/FP48.java
index b1959bc..e0dc3c4 100644
--- a/version3/java/FP48.java
+++ b/version3/java/FP48.java
@@ -23,9 +23,27 @@
package org.apache.milagro.amcl.XXX;
public final class FP48 {
+ public static final int ZERO=0;
+ public static final int ONE=1;
+ public static final int SPARSER=2;
+ public static final int SPARSE=3;
+ public static final int DENSE=4;
+
private final FP16 a;
private final FP16 b;
private final FP16 c;
+ private int type;
+
+ public void settype(int a)
+ {
+ type=a;
+ }
+
+ public int gettype()
+ {
+ return type;
+ }
+
/* reduce all components of this mod Modulus */
public void reduce()
{
@@ -51,6 +69,8 @@
a.cmove(g.a,d);
b.cmove(g.b,d);
c.cmove(g.c,d);
+ d=~(d-1);
+ type^=(type^g.type)&d;
}
@@ -115,6 +135,7 @@
a.copy(x.a);
b.copy(x.b);
c.copy(x.c);
+ type=x.type;
}
/* set this=1 */
public void one()
@@ -122,6 +143,7 @@
a.one();
b.zero();
c.zero();
+ type=ONE;
}
/* this=conj(this) */
public void conj()
@@ -136,6 +158,7 @@
a=new FP16(d);
b=new FP16(0);
c=new FP16(0);
+ type=SPARSER;
}
public FP48(int d)
@@ -143,6 +166,10 @@
a=new FP16(d);
b=new FP16(0);
c=new FP16(0);
+ if (d==1)
+ type=ONE;
+ else
+ type=SPARSER;
}
public FP48(FP16 d,FP16 e,FP16 f)
@@ -150,6 +177,7 @@
a=new FP16(d);
b=new FP16(e);
c=new FP16(f);
+ type=DENSE;
}
public FP48(FP48 x)
@@ -157,6 +185,7 @@
a=new FP16(x.a);
b=new FP16(x.b);
c=new FP16(x.c);
+ type=x.type;
}
/* Granger-Scott Unitary Squaring */
@@ -195,12 +224,16 @@
c.add(c);
b.add(B);
c.add(C);
+ type=DENSE;
reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
public void sqr()
{
+ if (type==ONE)
+ return;
+
FP16 A=new FP16(a);
FP16 B=new FP16(b);
FP16 C=new FP16(c);
@@ -235,7 +268,10 @@
b.copy(C); b.add(D);
c.add(A);
-
+ if (type==SPARSER)
+ type=SPARSE;
+ else
+ type=DENSE;
norm();
}
@@ -297,90 +333,219 @@
z3.times_i();
a.copy(z0); a.add(z3);
norm();
-
+ type=DENSE;
}
-/* Special case of multiplication arises from special form of ATE pairing line function */
- public void smul(FP48 y,int type)
+/* 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 */
+ public void smul(FP48 y)
{
- if (type==CONFIG_CURVE.D_TYPE)
- {
- FP16 z0=new FP16(a);
- FP16 z2=new FP16(b);
- FP16 z3=new FP16(b);
- FP16 t0=new FP16(0);
- FP16 t1=new FP16(y.a);
- z0.mul(y.a);
- z2.pmul(y.b.real());
- b.add(a);
- t1.real().add(y.b.real());
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ FP8 w1=new FP8(a.geta());
+ FP8 w2=new FP8(a.getb());
+ FP8 w3=new FP8(b.geta());
- t1.norm();
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
+
+ FP8 ta=new FP8(a.geta());
+ FP8 tb=new FP8(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP8 tc=new FP8(ta);
+ tc.mul(tb);
+ FP8 t=new FP8(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm();
+ FP8 td=new FP8(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm();
+ FP8 te=new FP8(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+
+ a.geta().copy(w1); a.getb().copy(tc);
+ b.geta().copy(td); b.getb().copy(te);
+ c.geta().copy(w3); c.getb().zero();
+
+ a.norm();
b.norm();
- b.mul(t1);
- z3.add(c);
- z3.norm();
- z3.pmul(y.b.real());
- t0.copy(z0); t0.neg();
- t1.copy(z2); t1.neg();
+ } else {
+ FP8 w1=new FP8(a.geta());
+ FP8 w2=new FP8(a.getb());
+ FP8 w3=new FP8(c.getb());
- b.add(t0);
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
- b.add(t1);
- z3.add(t1);
- z2.add(t0);
+ FP8 ta=new FP8(a.geta());
+ FP8 tb=new FP8(y.a.geta());
+ ta.add(a.getb()); ta.norm();
+ tb.add(y.a.getb()); tb.norm();
+ FP8 tc=new FP8(ta);
+ tc.mul(tb);
+ FP8 t=new FP8(w1);
+ t.add(w2);
+ t.neg();
+ tc.add(t);
- t0.copy(a); t0.add(c);
- t0.norm();
- z3.norm();
- t0.mul(y.a);
- c.copy(z2); c.add(t0);
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm();
+ FP8 td=new FP8(ta);
+ td.mul(tb);
+ t.copy(w1);
+ t.add(w3);
+ t.neg();
+ td.add(t);
- z3.times_i();
- a.copy(z0); a.add(z3);
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm();
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm();
+ FP8 te=new FP8(ta);
+ te.mul(tb);
+ t.copy(w2);
+ t.add(w3);
+ t.neg();
+ te.add(t);
+
+ w2.times_i();
+ w1.add(w2);
+ a.geta().copy(w1); a.getb().copy(tc);
+
+ w3.times_i();
+ w3.norm();
+ b.geta().zero(); b.getb().copy(w3);
+
+ te.norm();
+ te.times_i();
+ c.geta().copy(te);
+ c.getb().copy(td);
+
+ a.norm();
+ c.norm();
+
}
- if (type==CONFIG_CURVE.M_TYPE)
+ type=SPARSE;
+ }
+
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ public void ssmul(FP48 y)
+ {
+ if (type==ONE)
+ {
+ copy(y);
+ return;
+ }
+ if (y.type==ONE)
+ return;
+
+ if (y.type>=SPARSE)
{
FP16 z0=new FP16(a);
FP16 z1=new FP16(0);
FP16 z2=new FP16(0);
FP16 z3=new FP16(0);
- FP16 t0=new FP16(a);
- FP16 t1=new FP16(0);
-
z0.mul(y.a);
- t0.add(b);
- t0.norm();
- z1.copy(t0); z1.mul(y.a);
- t0.copy(b); t0.add(c);
- t0.norm();
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ z2.getb().copy(b.getb());
+ z2.getb().mul(y.b.getb());
+ z2.geta().zero();
+ if (y.type!=SPARSE)
+ {
+ z2.geta().copy(b.getb());
+ z2.geta().mul(y.b.geta());
+ }
+ if (type!=SPARSE)
+ {
+ z2.geta().copy(b.geta());
+ z2.geta().mul(y.b.getb());
+ }
+ z2.times_i();
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ } else {
+ z2.copy(b);
+ z2.mul(y.b);
+ }
+ FP16 t0=new FP16(a);
+ FP16 t1=new FP16(y.a);
+ t0.add(b); t0.norm();
+ t1.add(y.b); t1.norm();
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
+ z1.copy(t0); z1.mul(t1);
+ t0.copy(b); t0.add(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);
- b.copy(z1);
- z2.copy(t0);
+ b.copy(z1); b.add(t1);
- t0.copy(a); t0.add(c);
- t1.copy(y.a); t1.add(y.c);
+ z3.add(t1);
+ z2.add(t0);
- t0.norm();
- t1.norm();
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
t0.mul(t1);
z2.add(t0);
- t0.copy(c);
-
- t0.pmul(y.c.getb());
- t0.times_i();
-
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ {
+ if (y.type==SPARSE || type==SPARSE)
+ {
+ t0.geta().copy(c.geta());
+ t0.geta().mul(y.c.geta());
+ t0.getb().zero();
+ if (y.type!=SPARSE)
+ {
+ t0.getb().copy(c.geta());
+ t0.getb().mul(y.c.getb());
+ }
+ if (type!=SPARSE)
+ {
+ t0.getb().copy(c.getb());
+ t0.getb().mul(y.c.geta());
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
+ } else {
+ t0.copy(c);
+ t0.mul(y.c);
+ }
t1.copy(t0); t1.neg();
c.copy(z2); c.add(t1);
@@ -390,10 +555,96 @@
z3.norm();
z3.times_i();
a.copy(z0); a.add(z3);
+ } else {
+ if (type==SPARSER)
+ {
+ smul(y);
+ return;
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.D_TYPE)
+ { // dense by sparser - 13m
+ FP16 z0=new FP16(a);
+ FP16 z2=new FP16(b);
+ FP16 z3=new FP16(b);
+ FP16 t0=new FP16(0);
+ FP16 t1=new FP16(y.a);
+ z0.mul(y.a);
+ z2.pmul(y.b.real());
+ b.add(a);
+ t1.real().add(y.b.real());
+
+ t1.norm();
+ b.norm();
+ b.mul(t1);
+ z3.add(c);
+ z3.norm();
+ z3.pmul(y.b.real());
+
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
+
+ b.add(t0);
+
+ b.add(t1);
+ z3.add(t1);
+ z2.add(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ z3.norm();
+ t0.mul(y.a);
+ c.copy(z2); c.add(t0);
+
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ FP16 z0=new FP16(a);
+ FP16 z1=new FP16(0);
+ FP16 z2=new FP16(0);
+ FP16 z3=new FP16(0);
+ FP16 t0=new FP16(a);
+ FP16 t1=new FP16(0);
+
+ z0.mul(y.a);
+ t0.add(b); t0.norm();
+
+ z1.copy(t0); z1.mul(y.a);
+ t0.copy(b); t0.add(c);
+ t0.norm();
+
+ z3.copy(t0);
+ z3.pmul(y.c.getb());
+ z3.times_i();
+
+ t0.copy(z0); t0.neg();
+ z1.add(t0);
+ b.copy(z1);
+ z2.copy(t0);
+
+ t0.copy(a); t0.add(c); t0.norm();
+ t1.copy(y.a); t1.add(y.c); t1.norm();
+
+ t0.mul(t1);
+ z2.add(t0);
+ t0.copy(c);
+
+ t0.pmul(y.c.getb());
+ t0.times_i();
+ t1.copy(t0); t1.neg();
+
+ c.copy(z2); c.add(t1);
+ z3.add(t1);
+ t0.times_i();
+ b.add(t0);
+ z3.norm();
+ z3.times_i();
+ a.copy(z0); a.add(z3);
+ }
}
+ type=DENSE;
norm();
}
-
/* this=1/this */
public void inverse()
{
@@ -433,6 +684,7 @@
a.copy(f0); a.mul(f3);
b.copy(f1); b.mul(f3);
c.copy(f2); c.mul(f3);
+ type=DENSE;
}
/* this=this^p using Frobenius */
@@ -456,6 +708,7 @@
b.qmul(f); b.times_i4(); b.times_i2();
c.qmul(f2); c.times_i4(); c.times_i4(); c.times_i4();
}
+ type=DENSE;
}
/* trace function */
@@ -468,7 +721,7 @@
return t;
}
-/* convert from byte array to FP12 */
+/* convert from byte array to FP48 */
public static FP48 fromBytes(byte[] w)
{
BIG a,b;
diff --git a/version3/java/PAIR.java b/version3/java/PAIR.java
index 9f79ad2..2ad5e7c 100644
--- a/version3/java/PAIR.java
+++ b/version3/java/PAIR.java
@@ -123,18 +123,68 @@
}
A.add(B);
}
-
- return new FP12(a,b,c);
+ FP12 r=new FP12(a,b,c);
+ r.settype(FP12.SPARSE);
+ return r;
}
-/* Optimal R-ate pairing */
- public static FP12 ate(ECP2 P1,ECP Q1)
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ public static int lbits(BIG n3,BIG n)
{
+ n.copy(new BIG(ROM.CURVE_Bnx));
+ if (CONFIG_CURVE.CURVE_PAIRING_TYPE==CONFIG_CURVE.BN)
+ {
+ n.pmul(6);
+ if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.POSITIVEX)
+ {
+ n.inc(2);
+ } else {
+ n.dec(2);
+ }
+ }
+
+ n.norm();
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ }
+
+/* prepare for multi-pairing */
+ public static FP12[] initmp()
+ {
+ FP12[] r=new FP12[CONFIG_CURVE.ATE_BITS];
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=0; i--)
+ r[i]=new FP12(1);
+ return r;
+ }
+
+/* basic Miller loop */
+ public static FP12 miller(FP12[] r)
+ {
+ FP12 res=new FP12(1);
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ public static void another(FP12[] r,ECP2 P1,ECP Q1)
+ {
+
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
ECP2 K=new ECP2();
- FP12 lv;
+ FP12 lv,lv2;
int bt;
// P is needed in affine form for line function, Q for (Qx,Qy) extraction
@@ -152,21 +202,81 @@
f.inverse();
f.norm();
}
- n.pmul(6);
- if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.POSITIVEX)
+ }
+
+ FP Qx=new FP(Q.getx());
+ FP Qy=new FP(Q.gety());
+
+ ECP2 A=new ECP2();
+ A.copy(P);
+
+ ECP2 MP=new ECP2();
+ MP.copy(P); MP.neg();
+
+ int nb=lbits(n3,n);
+
+ for (int i=nb-2;i>=1;i--)
+ {
+ lv=line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
{
- n.inc(2);
- } else {
- n.dec(2);
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+
+/* R-ate fixup required for BN curves */
+ if (CONFIG_CURVE.CURVE_PAIRING_TYPE==CONFIG_CURVE.BN)
+ {
+ if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
+ {
+ A.neg();
+ }
+ K.copy(P);
+ K.frob(f);
+ lv=line(A,K,Qx,Qy);
+ K.frob(f);
+ K.neg();
+ lv2=line(A,K,Qx,Qy);
+ lv.smul(lv2);
+ r[0].ssmul(lv);
+ }
+ }
+
+/* Optimal R-ate pairing */
+ public static FP12 ate(ECP2 P1,ECP Q1)
+ {
+ FP2 f;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ ECP2 K=new ECP2();
+ FP12 lv,lv2;
+ int bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ ECP2 P=new ECP2(P1);
+ ECP Q=new ECP(Q1);
+
+ P.affine();
+ Q.affine();
+
+ if (CONFIG_CURVE.CURVE_PAIRING_TYPE==CONFIG_CURVE.BN)
+ {
+ f=new FP2(new BIG(ROM.Fra),new BIG(ROM.Frb));
+ if (CONFIG_CURVE.SEXTIC_TWIST==CONFIG_CURVE.M_TYPE)
+ {
+ f.inverse();
+ f.norm();
}
}
- else
- n.copy(x);
- n.norm();
-
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
@@ -178,25 +288,25 @@
ECP2 MP=new ECP2();
MP.copy(P); MP.neg();
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
- lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
}
if (bt==-1)
{
- lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
@@ -214,11 +324,11 @@
K.copy(P);
K.frob(f);
lv=line(A,K,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv=line(A,K,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,K,Qx,Qy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
return r;
}
@@ -227,10 +337,10 @@
public static FP12 ate2(ECP2 P1,ECP Q1,ECP2 R1,ECP S1)
{
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
ECP2 K=new ECP2();
- FP12 lv;
+ FP12 lv,lv2;
int bt;
ECP2 P=new ECP2(P1);
@@ -253,21 +363,7 @@
f.inverse();
f.norm();
}
- n.pmul(6);
- if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.POSITIVEX)
- {
- n.inc(2);
- } else {
- n.dec(2);
- }
}
- else
- n.copy(x);
- n.norm();
-
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
@@ -286,32 +382,30 @@
ECP2 MR=new ECP2();
MR.copy(R); MR.neg();
-
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
-
- lv=line(B,B,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,B,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,R,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,R,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt==-1)
{
lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,MR,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,MR,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -334,19 +428,19 @@
K.frob(f);
lv=line(A,K,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv=line(A,K,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,K,Qx,Qy);
+ lv.smul(lv2);
+ r.ssmul(lv);
K.copy(R);
K.frob(f);
lv=line(B,K,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
K.frob(f);
K.neg();
- lv=line(B,K,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,K,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
return r;
}
diff --git a/version3/java/PAIR192.java b/version3/java/PAIR192.java
index d9ce24a..9b9f975 100644
--- a/version3/java/PAIR192.java
+++ b/version3/java/PAIR192.java
@@ -124,16 +124,101 @@
}
A.add(B);
}
- return new FP24(a,b,c);
+ FP24 r=new FP24(a,b,c);
+ r.settype(FP24.SPARSE);
+ return r;
+ }
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ public static int lbits(BIG n3,BIG n)
+ {
+ n.copy(new BIG(ROM.CURVE_Bnx));
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ }
+
+/* prepare for multi-pairing */
+ public static FP24[] initmp()
+ {
+ FP24[] r=new FP24[CONFIG_CURVE.ATE_BITS];
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=0; i--)
+ r[i]=new FP24(1);
+ return r;
+ }
+
+/* basic Miller loop */
+ public static FP24 miller(FP24[] r)
+ {
+ FP24 res=new FP24(1);
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ public static void another(FP24[] r,ECP4 P1,ECP Q1)
+ {
+ FP2 f;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP24 lv,lv2;
+ int bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ ECP4 P=new ECP4(P1);
+ ECP Q=new ECP(Q1);
+
+ P.affine();
+ Q.affine();
+
+ FP Qx=new FP(Q.getx());
+ FP Qy=new FP(Q.gety());
+
+ ECP4 A=new ECP4();
+ A.copy(P);
+
+ ECP4 MP=new ECP4();
+ MP.copy(P); MP.neg();
+
+ int nb=lbits(n3,n);
+
+ for (int i=nb-2;i>=1;i--)
+ {
+ lv=line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
+ {
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+
}
/* Optimal R-ate pairing */
public static FP24 ate(ECP4 P1,ECP Q1)
{
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
- FP24 lv;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP24 lv,lv2;
int bt;
ECP4 P=new ECP4(P1);
@@ -142,10 +227,6 @@
P.affine();
Q.affine();
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
-
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
@@ -156,25 +237,25 @@
ECP4 MP=new ECP4();
MP.copy(P); MP.neg();
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
- lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
}
if (bt==-1)
{
- lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
@@ -189,9 +270,9 @@
public static FP24 ate2(ECP4 P1,ECP Q1,ECP4 R1,ECP S1)
{
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
- FP24 lv;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP24 lv,lv2;
int bt;
ECP4 P=new ECP4(P1);
@@ -206,11 +287,6 @@
R.affine();
S.affine();
-
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
-
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
FP Sx=new FP(S.getx());
@@ -229,31 +305,30 @@
MR.copy(R); MR.neg();
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,B,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
- lv=line(B,B,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
-
- bt=n3.bit(i)-n.bit(i); // bt=n.bit(i);
+ bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,R,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,R,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt==-1)
{
lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,MR,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,MR,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
diff --git a/version3/java/PAIR256.java b/version3/java/PAIR256.java
index 33c5ceb..d327975 100644
--- a/version3/java/PAIR256.java
+++ b/version3/java/PAIR256.java
@@ -123,16 +123,102 @@
}
A.add(B);
}
- return new FP48(a,b,c);
+ FP48 r=new FP48(a,b,c);
+ r.settype(FP48.SPARSE);
+ return r;
}
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+ public static int lbits(BIG n3,BIG n)
+ {
+ n.copy(new BIG(ROM.CURVE_Bnx));
+ n3.copy(n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+ }
+
+/* prepare for multi-pairing */
+ public static FP48[] initmp()
+ {
+ FP48[] r=new FP48[CONFIG_CURVE.ATE_BITS];
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=0; i--)
+ r[i]=new FP48(1);
+ return r;
+ }
+
+/* basic Miller loop */
+ public static FP48 miller(FP48[] r)
+ {
+ FP48 res=new FP48(1);
+ for (int i=CONFIG_CURVE.ATE_BITS-1; i>=1; i--)
+ {
+ res.sqr();
+ res.ssmul(r[i]);
+ }
+
+ if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
+ res.conj();
+ res.ssmul(r[0]);
+
+ return res;
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ public static void another(FP48[] r,ECP8 P1,ECP Q1)
+ {
+ FP2 f;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP48 lv,lv2;
+ int bt;
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ ECP8 P=new ECP8(P1);
+ ECP Q=new ECP(Q1);
+
+ P.affine();
+ Q.affine();
+
+ FP Qx=new FP(Q.getx());
+ FP Qy=new FP(Q.gety());
+
+ ECP8 A=new ECP8();
+ A.copy(P);
+
+ ECP8 MP=new ECP8();
+ MP.copy(P); MP.neg();
+
+ int nb=lbits(n3,n);
+
+ for (int i=nb-2;i>=1;i--)
+ {
+ lv=line(A,A,Qx,Qy);
+
+ bt=n3.bit(i)-n.bit(i);
+ if (bt==1)
+ {
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
+ }
+ if (bt==-1)
+ {
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
+ }
+ r[i].ssmul(lv);
+ }
+
+ }
+
+
/* Optimal R-ate pairing */
public static FP48 ate(ECP8 P1,ECP Q1)
{
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
- FP48 lv;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP48 lv,lv2;
int bt;
ECP8 P=new ECP8(P1);
@@ -141,11 +227,6 @@
P.affine();
Q.affine();
-
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
-
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
@@ -156,25 +237,25 @@
ECP8 MP=new ECP8();
MP.copy(P); MP.neg();
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
- lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,P,Qx,Qy);
+ lv.smul(lv2);
}
if (bt==-1)
{
- lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(A,MP,Qx,Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX)
@@ -189,9 +270,9 @@
public static FP48 ate2(ECP8 P1,ECP Q1,ECP8 R1,ECP S1)
{
FP2 f;
- BIG x=new BIG(ROM.CURVE_Bnx);
- BIG n=new BIG(x);
- FP48 lv;
+ BIG n=new BIG(0);
+ BIG n3=new BIG(0);
+ FP48 lv,lv2;
int bt;
ECP8 P=new ECP8(P1);
@@ -206,10 +287,6 @@
R.affine();
S.affine();
- BIG n3=new BIG(n);
- n3.pmul(3);
- n3.norm();
-
FP Qx=new FP(Q.getx());
FP Qy=new FP(Q.gety());
FP Sx=new FP(S.getx());
@@ -227,32 +304,30 @@
ECP8 MR=new ECP8();
MR.copy(R); MR.neg();
-
- int nb=n3.nbits();
+ int nb=lbits(n3,n);
for (int i=nb-2;i>=1;i--)
{
r.sqr();
lv=line(A,A,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
-
- lv=line(B,B,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,B,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
bt=n3.bit(i)-n.bit(i);
if (bt==1)
{
lv=line(A,P,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,R,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,R,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
if (bt==-1)
{
lv=line(A,MP,Qx,Qy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
- lv=line(B,MR,Sx,Sy);
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST);
+ lv2=line(B,MR,Sx,Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
diff --git a/version3/java/config32.py b/version3/java/config32.py
index c599d59..847c694 100644
--- a/version3/java/config32.py
+++ b/version3/java/config32.py
@@ -77,7 +77,7 @@
replace(fpath+"CONFIG_FF.java","@ML@",ml);
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -133,6 +133,7 @@
replace(fpath+"CONFIG_CURVE.java","@ST@",stw)
replace(fpath+"CONFIG_CURVE.java","@SX@",sx)
+ replace(fpath+"CONFIG_CURVE.java","@AB@",ab)
if cs == "128" :
replace(fpath+"CONFIG_CURVE.java","@HT@","32")
@@ -297,91 +298,91 @@
if x==1:
- curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ED25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("C25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+ curveset("NIST256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128") # Change to 28
curve_selected=True
if x==4:
- curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+ curveset("BRAINPOOL","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128") # Change to 28
curve_selected=True
if x==5:
- curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+ curveset("ANSSI","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128") # Change to 28
curve_selected=True
if x==6:
- curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("HIFIVE","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("GOLDILOCKS","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==8:
- curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192") # change to 29
+ curveset("NIST384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192") # change to 29
curve_selected=True
if x==9:
- curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("C41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NIST521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NUMS256W","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("NUMS256E","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NUMS384W","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("NUMS384E","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NUMS512W","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("NUMS512E","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128") # Change to 28
+ curveset("SECP256K1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128") # Change to 28
curve_selected=True
if x==18:
- curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("BLS383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("FP256BN","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("FP512BN","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("BLS24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("BLS48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/java/config64.py b/version3/java/config64.py
index 96ffb76..7a8acb6 100644
--- a/version3/java/config64.py
+++ b/version3/java/config64.py
@@ -78,7 +78,7 @@
replace(fpath+"CONFIG_FF.java","@ML@",ml);
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -133,6 +133,7 @@
replace(fpath+"CONFIG_CURVE.java","@PF@",pf)
replace(fpath+"CONFIG_CURVE.java","@ST@",stw)
replace(fpath+"CONFIG_CURVE.java","@SX@",sx)
+ replace(fpath+"CONFIG_CURVE.java","@AB@",ab)
if cs == "128" :
replace(fpath+"CONFIG_CURVE.java","@HT@","32")
@@ -298,90 +299,90 @@
if x==1:
- curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ED25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("C25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NIST256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==4:
- curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("BRAINPOOL","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==5:
- curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("ANSSI","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==6:
- curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("HIFIVE","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256") # change to 58
+ curveset("GOLDILOCKS","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256") # change to 58
curve_selected=True
if x==8:
- curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NIST384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==9:
- curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("C41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NIST521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("NUMS256W","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("NUMS256E","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("NUMS384W","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("NUMS384E","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("NUMS512W","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("NUMS512E","64","56","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("SECP256K1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==18:
- curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("BN254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128") # change to 58
+ curveset("BLS383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128") # change to 58
pfcurve_selected=True
if x==21:
- curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128") # change to 58
+ curveset("BLS381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128") # change to 58
pfcurve_selected=True
if x==22:
- curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("FP256BN","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("FP512BN","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("BLS461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("BLS24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("BLS48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/js/bls.js b/version3/js/bls.js
index dec35d4..6346b1d 100644
--- a/version3/js/bls.js
+++ b/version3/js/bls.js
@@ -100,10 +100,20 @@
var G=ctx.ECP2.generator();
var PK=ctx.ECP2.fromBytes(W);
D.neg();
- var v=ctx.PAIR.ate2(G,D,PK,HM);
+
+// 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_OK;
+ return this.BLS_FAIL;
}
};
diff --git a/version3/js/bls192.js b/version3/js/bls192.js
index 6712348..5bb92c7 100644
--- a/version3/js/bls192.js
+++ b/version3/js/bls192.js
@@ -100,10 +100,19 @@
var G=ctx.ECP4.generator();
var PK=ctx.ECP4.fromBytes(W);
D.neg();
- var v=ctx.PAIR192.ate2(G,D,PK,HM);
+
+// 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_OK;
+ return this.BLS_FAIL;
}
};
diff --git a/version3/js/bls256.js b/version3/js/bls256.js
index fcf507c..9fa8f36 100644
--- a/version3/js/bls256.js
+++ b/version3/js/bls256.js
@@ -100,10 +100,20 @@
var G=ctx.ECP8.generator();
var PK=ctx.ECP8.fromBytes(W);
D.neg();
- var v=ctx.PAIR256.ate2(G,D,PK,HM);
+
+// 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_OK;
+ return this.BLS_FAIL;
}
};
diff --git a/version3/js/ctx.js b/version3/js/ctx.js
index 4588eec..d8cdbb0 100644
--- a/version3/js/ctx.js
+++ b/version3/js/ctx.js
@@ -38,6 +38,7 @@
"@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 */
@@ -56,6 +57,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 9,
"@AK": 16
@@ -75,6 +77,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -93,6 +96,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -111,6 +115,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
"@SH": 7,
"@AK": 24
@@ -129,6 +134,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -147,6 +153,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -165,6 +172,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
"@SH": 9,
"@AK": 24
@@ -183,6 +191,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
"@SH": 11,
"@AK": 32
@@ -201,6 +210,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
"@SH": 4,
"@AK": 32
@@ -219,6 +229,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
"@SH": 8,
"@AK": 32
@@ -237,6 +248,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -255,6 +267,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -273,6 +286,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
"@SH": 7,
"@AK": 24
@@ -291,6 +305,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 48,
"@SH": 7,
"@AK": 24
@@ -309,6 +324,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
"@SH": 11,
"@AK": 32
@@ -327,6 +343,7 @@
"@PF": 0,
"@ST": 0,
"@SX": 0,
+ "@AB": 0,
"@HT": 64,
"@SH": 11,
"@AK": 32
@@ -345,6 +362,7 @@
"@PF": 1,
"@ST": 1,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -363,6 +381,7 @@
"@PF": 1,
"@ST": 1,
"@SX": 0,
+ "@AB": 130,
"@HT": 32,
"@SH": 11,
"@AK": 16
@@ -381,6 +400,7 @@
"@PF": 1,
"@ST": 0,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
"@SH": 10,
"@AK": 16
@@ -399,6 +419,7 @@
"@PF": 1,
"@ST": 0,
"@SX": 1,
+ "@AB": 66,
"@HT": 32,
"@SH": 10,
"@AK": 16
@@ -417,6 +438,7 @@
"@PF": 2,
"@ST": 1,
"@SX": 0,
+ "@AB": 65,
"@HT": 32,
"@SH": 8,
"@AK": 16
@@ -435,6 +457,7 @@
"@PF": 3,
"@ST": 1,
"@SX": 0,
+ "@AB": 49,
"@HT": 48,
"@SH": 4,
"@AK": 24
@@ -453,6 +476,7 @@
"@PF": 4,
"@ST": 1,
"@SX": 0,
+ "@AB": 32,
"@HT": 64,
"@SH": 11,
"@AK": 32
@@ -471,6 +495,7 @@
"@PF": 2,
"@ST": 1,
"@SX": 1,
+ "@AB": 65,
"@HT": 32,
"@SH": 10,
"@AK": 16
@@ -489,6 +514,7 @@
"@PF": 2,
"@ST": 1,
"@SX": 1,
+ "@AB": 78,
"@HT": 32,
"@SH": 11,
"@AK": 16
@@ -543,7 +569,6 @@
prepareModule("HASH512");
prepareModule("SHA3");
prepareModule("RAND");
- //prepareModule("NewHope");
prepareModule("NHS");
if (typeof input_parameter === "undefined") {
diff --git a/version3/js/ecp.js b/version3/js/ecp.js
index 53d4605..c593e00 100644
--- a/version3/js/ecp.js
+++ b/version3/js/ecp.js
@@ -48,6 +48,7 @@
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"];
diff --git a/version3/js/fp.js b/version3/js/fp.js
index 588e551..2b939a2 100644
--- a/version3/js/fp.js
+++ b/version3/js/fp.js
@@ -39,6 +39,12 @@
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"];
diff --git a/version3/js/fp12.js b/version3/js/fp12.js
index f87c43e..e013e42 100644
--- a/version3/js/fp12.js
+++ b/version3/js/fp12.js
@@ -26,15 +26,27 @@
/* general purpose constructor */
var FP12 = function(d, e, f) {
- if (d instanceof FP12) {
- this.a = new ctx.FP4(d.a);
- this.b = new ctx.FP4(d.b);
- this.c = new ctx.FP4(d.c);
- } else {
- this.a = new ctx.FP4(d);
- this.b = new ctx.FP4(e);
- this.c = new ctx.FP4(f);
- }
+ if (!isNaN(d))
+ {
+ this.a = new ctx.FP4(d);
+ this.b = new ctx.FP4(0);
+ this.c = new ctx.FP4(0);
+ if (d==1) this.stype=ctx.FP.ONE;
+ else this.stype=ctx.FP.SPARSER;
+ }
+ else
+ {
+ if (d instanceof FP12) {
+ this.a = new ctx.FP4(d.a);
+ this.b = new ctx.FP4(d.b);
+ this.c = new ctx.FP4(d.c);
+ } else {
+ this.a = new ctx.FP4(d);
+ this.b = new ctx.FP4(e);
+ this.c = new ctx.FP4(f);
+ }
+ this.stype=ctx.FP.DENSE;
+ }
};
FP12.prototype = {
@@ -69,6 +81,8 @@
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;
},
@@ -95,6 +109,14 @@
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;
@@ -120,6 +142,7 @@
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -127,6 +150,7 @@
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
},
/* this=conj(this) */
@@ -141,6 +165,7 @@
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP4 */
@@ -148,6 +173,7 @@
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
@@ -185,11 +211,15 @@
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
+ if (this.stype==ctx.FP.ONE)
+ return;
+
var A = new ctx.FP4(this.a),
B = new ctx.FP4(this.b),
C = new ctx.FP4(this.c),
@@ -220,7 +250,10 @@
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();
},
@@ -291,111 +324,317 @@
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;
+/* 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());
- if (twist == ctx.ECP.D_TYPE) {
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
- 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);
+ 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);
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
+ 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);
- this.b.norm();
- t1.norm();
+ 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);
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
+ w2.mul_ip();
+ w1.add(w2);
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
+ 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.b.add(t0);
+ this.a.norm();
+ this.b.norm();
- this.b.add(t1);
- z3.add(t1);
- z2.add(t0);
+ } 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());
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
+ 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);
- 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);
+ 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);
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
+ 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);
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
+ w2.mul_ip();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
+ w3.mul_ip();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
- t0.copy(z0); t0.neg();
+ te.norm();
+ te.mul_ip();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
+ this.a.norm();
+ this.c.norm();
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
- t0.norm();
- t1.norm();
+/* 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;
- t0.mul(t1);
- z2.add(t0);
+ 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);
- t0.copy(this.c);
+ 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();
- t0.pmul(y.c.getb());
- t0.times_i();
+ 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();
- t1.copy(t0); t1.neg();
+ z3.copy(t0); z3.mul(t1);
- 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);
- }
+ t0.copy(z0); t0.neg();
+ t1.copy(z2); t1.neg();
- this.norm();
- },
+ 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() {
@@ -441,6 +680,7 @@
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 */
@@ -457,6 +697,7 @@
this.b.pmul(f);
this.c.pmul(f2);
+ this.stype=ctx.FP.DENSE;
},
/* trace function */
diff --git a/version3/js/fp24.js b/version3/js/fp24.js
index 28f424d..609d00e 100644
--- a/version3/js/fp24.js
+++ b/version3/js/fp24.js
@@ -26,15 +26,27 @@
/* 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 = {
@@ -68,6 +80,8 @@
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 */
@@ -92,7 +106,14 @@
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;
@@ -118,6 +139,7 @@
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -125,6 +147,7 @@
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
},
/* this=conj(this) */
@@ -139,6 +162,7 @@
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP8 */
@@ -146,6 +170,7 @@
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
@@ -183,11 +208,15 @@
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
+ if (this.stype==ctx.FP.ONE)
+ return;
+
var A = new ctx.FP8(this.a),
B = new ctx.FP8(this.b),
C = new ctx.FP8(this.c),
@@ -218,7 +247,10 @@
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();
},
@@ -290,110 +322,317 @@
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;
+/* 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());
- 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);
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
+ 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);
- this.b.norm();
- t1.norm();
+ 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);
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
+ 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);
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
+ w2.times_i();
+ w1.add(w2);
- this.b.add(t0);
+ 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.b.add(t1);
- z3.add(t1);
- z2.add(t0);
+ this.a.norm();
+ this.b.norm();
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
+ } 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());
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
- 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);
+ 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);
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
+ 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);
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
+ 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);
- z3.copy(t0);
- z3.pmul(y.c.getb());
- z3.times_i();
+ w2.times_i();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
- t0.copy(z0); t0.neg();
+ w3.times_i();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
+ te.norm();
+ te.times_i();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
+ this.a.norm();
+ this.c.norm();
- t0.norm();
- t1.norm();
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
- t0.mul(t1);
- z2.add(t0);
+/* 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;
- t0.copy(this.c);
+ 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);
- t0.pmul(y.c.getb());
- t0.times_i();
+ 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();
- t1.copy(t0); t1.neg();
+ 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();
- 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);
- }
+ z3.copy(t0); z3.mul(t1);
- this.norm();
- },
+ 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() {
@@ -439,6 +678,7 @@
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 +700,7 @@
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 */
diff --git a/version3/js/fp48.js b/version3/js/fp48.js
index 2aec58d..e5a4bea 100644
--- a/version3/js/fp48.js
+++ b/version3/js/fp48.js
@@ -26,15 +26,27 @@
/* 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 = {
@@ -68,6 +80,9 @@
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 */
@@ -93,6 +108,14 @@
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;
@@ -118,6 +141,7 @@
this.a.copy(x.a);
this.b.copy(x.b);
this.c.copy(x.c);
+ this.stype=x.stype;
},
/* set this=1 */
@@ -125,6 +149,7 @@
this.a.one();
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.ONE;
},
/* this=conj(this) */
@@ -139,6 +164,7 @@
this.a.copy(d);
this.b.copy(e);
this.c.copy(f);
+ this.stype=ctx.FP.DENSE;
},
/* set this from one ctx.FP16 */
@@ -146,6 +172,7 @@
this.a.copy(d);
this.b.zero();
this.c.zero();
+ this.stype=ctx.FP.SPARSER
},
/* Granger-Scott Unitary Squaring */
@@ -183,11 +210,15 @@
this.c.add(this.c);
this.b.add(B);
this.c.add(C);
+ this.stype=ctx.FP.DENSE;
this.reduce();
},
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
sqr: function() {
+ if (this.stype==ctx.FP.ONE)
+ return;
+
var A = new ctx.FP16(this.a),
B = new ctx.FP16(this.b),
C = new ctx.FP16(this.c),
@@ -218,7 +249,10 @@
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();
},
@@ -290,110 +324,318 @@
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;
+/* 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());
- 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);
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.b.geta());
- z0.mul(y.a);
- z2.pmul(y.b.real());
- this.b.add(this.a);
- t1.real().add(y.b.real());
+ 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);
- this.b.norm();
- t1.norm();
+ 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);
- this.b.mul(t1);
- z3.add(this.c);
- z3.norm();
- z3.pmul(y.b.real());
+ 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);
- t0.copy(z0);
- t0.neg();
- t1.copy(z2);
- t1.neg();
+ w2.times_i();
+ w1.add(w2);
- this.b.add(t0);
+ 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.b.add(t1);
- z3.add(t1);
- z2.add(t0);
+ this.a.norm();
+ this.b.norm();
- t0.copy(this.a);
- t0.add(this.c);
- t0.norm();
- t0.mul(y.a);
- this.c.copy(z2);
- this.c.add(t0);
+ } 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());
- z3.times_i();
- this.a.copy(z0);
- this.a.add(z3);
- }
+ w1.mul(y.a.geta());
+ w2.mul(y.a.getb());
+ w3.mul(y.c.getb());
- 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);
+ 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);
- z0.mul(y.a);
- t0.add(this.b);
- t0.norm();
+ 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);
- z1.copy(t0); z1.mul(y.a);
- t0.copy(this.b); t0.add(this.c);
- t0.norm();
+ 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);
- z3.copy(t0); //z3.mul(y.c);
- z3.pmul(y.c.getb());
- z3.times_i();
+ w2.times_i();
+ w1.add(w2);
+ this.a.geta().copy(w1); this.a.getb().copy(tc);
- t0.copy(z0); t0.neg();
+ w3.times_i();
+ w3.norm();
+ this.b.geta().zero(); this.b.getb().copy(w3);
- z1.add(t0);
- this.b.copy(z1);
- z2.copy(t0);
+ te.norm();
+ te.times_i();
+ this.c.geta().copy(te);
+ this.c.getb().copy(td);
- t0.copy(this.a); t0.add(this.c);
- t1.copy(y.a); t1.add(y.c);
+ this.a.norm();
+ this.c.norm();
- t0.norm();
- t1.norm();
+ }
+ this.stype=ctx.FP.SPARSE;
+ },
- t0.mul(t1);
- z2.add(t0);
+/* 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;
- t0.copy(this.c);
+ 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);
- t0.pmul(y.c.getb());
- t0.times_i();
+ 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();
- t1.copy(t0); t1.neg();
+ 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();
- 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);
- }
+ z3.copy(t0); z3.mul(t1);
- this.norm();
- },
+ 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();
+ },
+
/* this=1/this */
inverse: function() {
@@ -439,6 +681,7 @@
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 */
@@ -461,6 +704,7 @@
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 */
diff --git a/version3/js/pair.js b/version3/js/pair.js
index 6e0c08e..1c229b1 100644
--- a/version3/js/pair.js
+++ b/version3/js/pair.js
@@ -122,19 +122,121 @@
}
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(P1, Q1) {
- var fa, fb, f, x, n, n3, K, lv,
+ 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) {
@@ -149,21 +251,7 @@
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();
@@ -179,24 +267,22 @@
NP.copy(P);
NP.neg();
- nb = n3.nbits();
+ 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) {
- lv = PAIR.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -213,27 +299,25 @@
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(P1, Q1, R1, S1) {
- var fa, fb, f, x, n, n3, K, lv,
+ 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) {
@@ -247,21 +331,7 @@
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();
@@ -289,28 +359,28 @@
NR.copy(R);
NR.neg();
- nb = n3.nbits();
+ 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) {
lv = PAIR.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR.line(B, NR, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -319,7 +389,7 @@
}
- /* 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();
@@ -329,21 +399,21 @@
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;
@@ -491,6 +561,28 @@
}
};
+/* 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 = [],
diff --git a/version3/js/pair192.js b/version3/js/pair192.js
index ee33fb9..f915991 100644
--- a/version3/js/pair192.js
+++ b/version3/js/pair192.js
@@ -121,23 +121,89 @@
}
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(P1, Q1) {
- var x, n, n3, lv,
+ 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);
-
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ 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();
@@ -154,24 +220,22 @@
NP.neg();
- nb = n3.nbits();
+ 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) {
- lv = PAIR192.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR192.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -183,18 +247,13 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
ate2: function(P1, Q1, R1, S1) {
- var x, n, n3, lv,
+ 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(x);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ 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();
@@ -221,29 +280,28 @@
NR.copy(R);
NR.neg();
-
- nb = n3.nbits();
+ 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) {
lv = PAIR192.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR192.line(B, NR, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR192.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -353,6 +411,16 @@
}
};
+/* 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 = [],
diff --git a/version3/js/pair256.js b/version3/js/pair256.js
index 2408fc0..9891a88 100644
--- a/version3/js/pair256.js
+++ b/version3/js/pair256.js
@@ -121,23 +121,89 @@
}
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(P1, Q1) {
- var x, n, n3, lv,
+ 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);
-
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
var P=new ctx.ECP8(); P.copy(P1); P.affine();
var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
@@ -154,24 +220,22 @@
NP.neg();
- nb = n3.nbits();
+ 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) {
- lv = PAIR256.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR256.line(A, NP, Qx, Qy);
+ lv.smul(lv2);
}
+ r.ssmul(lv);
}
if (ctx.ECP.SIGN_OF_X == ctx.ECP.NEGATIVEX) {
@@ -183,18 +247,12 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
ate2: function(P1, Q1, R1, S1) {
- var x, n, n3, lv,
+ 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(x);
- n3 = new ctx.BIG(n);
- n3.pmul(3);
- n3.norm();
+ n = new ctx.BIG(0);
+ n3 = new ctx.BIG(0);
var P=new ctx.ECP8(); P.copy(P1); P.affine();
var Q=new ctx.ECP(); Q.copy(Q1); Q.affine();
@@ -222,28 +280,28 @@
NR.neg();
- nb = n3.nbits();
+ 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) {
lv = PAIR256.line(A, NP, Qx, Qy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
- lv = PAIR256.line(B, NR, Sx, Sy);
- r.smul(lv,ctx.ECP.SEXTIC_TWIST);
+ lv2 = PAIR256.line(B, NR, Sx, Sy);
+ lv.smul(lv2);
+ r.ssmul(lv);
}
}
@@ -424,6 +482,16 @@
}
};
+/* 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 = [],
diff --git a/version3/python/bls.py b/version3/python/bls.py
index 4f3672d..55d9181 100644
--- a/version3/python/bls.py
+++ b/version3/python/bls.py
@@ -53,9 +53,17 @@
PK=ECp2()
PK.fromBytes(W)
D=-D
- v = pair.double_miller(G, D, PK, HM)
- v = pair.fexp(v)
+# Use new multi-pairing mechanism
+ r=pair.initmp()
+ pair.another(r,G,D)
+ pair.another(r,PK,HM)
+ v=pair.miller(r)
+
+#.. or alternatively
+# v = pair.double_ate(G, D, PK, HM)
+
+ v = pair.fexp(v)
if v.isone():
return True
return False
diff --git a/version3/python/fp12.py b/version3/python/fp12.py
index 11bfa81..dbc5cf3 100644
--- a/version3/python/fp12.py
+++ b/version3/python/fp12.py
@@ -5,6 +5,7 @@
#
import copy
+from constants import *
from XXX import curve
from XXX.fp4 import *
@@ -105,6 +106,8 @@
# regular squaring
def sqr(self): # mutable
+ if self.isone() :
+ return
A = self.a.copy()
A.sqr()
B = self.b * self.c
@@ -165,6 +168,62 @@
R *= other
return R
+# multiply line functions
+ def smul(self,other) :
+ if curve.SexticTwist == D_TYPE :
+ w1=self.a.a*other.a.a
+ w2=self.a.b*other.a.b
+ w3=self.b.a*other.b.a
+
+ ta=self.a.a+self.a.b
+ tb=other.a.a+other.a.b
+ tc=ta*tb
+ tc-=(w1+w2)
+
+ ta=self.a.a+self.b.a
+ tb=other.a.a+other.b.a
+ td=ta*tb
+ td-=(w1+w3)
+
+ ta=self.a.b+self.b.a
+ tb=other.a.b+other.b.a
+ te=ta*tb
+ te-=(w2+w3)
+
+ w1+=w2.mulQNR()
+ self.a=Fp4(w1,tc)
+ self.b=Fp4(td,te)
+ self.c=Fp4(w3)
+ else :
+ w1=self.a.a*other.a.a
+ w2=self.a.b*other.a.b
+ w3=self.c.b*other.c.b
+
+ ta=self.a.a+self.a.b
+ tb=other.a.a+other.a.b
+ tc=ta*tb
+ tc-=(w1+w2)
+
+ ta=self.a.a+self.c.b
+ tb=other.a.a+other.c.b
+ td=ta*tb
+ td-=(w1+w3)
+
+ ta=self.a.b+self.c.b
+ tb=other.a.b+other.c.b
+ te=ta*tb
+ te-=(w2+w3)
+
+ w1+=w2.mulQNR()
+ self.a=Fp4(w1,tc)
+
+ self.b=Fp4(w3.mulQNR())
+ self.b.times_i()
+
+ self.c=Fp4(te.mulQNR(),td)
+
+ return self
+
def muls(self, other): # multiple Fp12 by Fp4
R = Fp12(self.a * other, self.b * other, self.c * other)
return R
diff --git a/version3/python/mpin.py b/version3/python/mpin.py
index 4fbec4c..a6c7783 100644
--- a/version3/python/mpin.py
+++ b/version3/python/mpin.py
@@ -133,7 +133,7 @@
TU.add(P)
# TU.affine()
- r = pair.double_miller(Q, TV, sQ, TU)
+ r = pair.double_ate(Q, TV, sQ, TU)
r = pair.fexp(r)
if r.isone():
diff --git a/version3/python/pair.py b/version3/python/pair.py
index e8a5323..6ab1190 100644
--- a/version3/python/pair.py
+++ b/version3/python/pair.py
@@ -16,7 +16,6 @@
# line function
-
def g(A, B, Qx, Qy):
if A == B:
XX, YY, ZZ = A.getxyz()
@@ -63,13 +62,7 @@
# full pairing - miller loop followed by final exponentiation
-
-def e(P, Q):
- r = miller(P, Q)
- return fexp(r)
-
-
-def miller(P1, Q1):
+def lbits() :
x = curve.x
if curve.PairingFriendly == BN:
n = 6 * x
@@ -80,7 +73,66 @@
else:
n = x
n3 = 3 * n
+ return n3.bit_length(),n3,n
+def initmp() :
+ nb,n3,n=lbits()
+ r=[]
+ for i in range (nb-1,-1,-1) :
+ r.append(Fp12.one())
+ return r
+
+def miller(r) :
+ nb,n3,n=lbits()
+ res=Fp12.one()
+ for i in range (nb-1,0,-1) :
+ res.sqr()
+ res *= r[i]
+ if curve.SignOfX == NEGATIVEX:
+ res.conj()
+ res *= r[0]
+ return res
+
+def another(r,P1,Q1) :
+ nb,n3,n=lbits()
+ P = P1.copy()
+ Q = Q1.copy()
+
+ P.affine()
+ Q.affine()
+ A = P.copy()
+ Qx, Qy = Q.getxy()
+ for i in range(nb - 2, 0, -1):
+ lv=g(A, A, Qx, Qy)
+
+ if big.bit(n3, i) == 1 and big.bit(n, i) == 0:
+ lv2 = g(A, P, Qx, Qy)
+ lv.smul(lv2)
+ if big.bit(n3, i) == 0 and big.bit(n, i) == 1:
+ lv2 = g(A, -P, Qx, Qy)
+ lv.smul(lv2)
+ r[i] *= lv
+
+ if curve.PairingFriendly == BN:
+ KA = P.copy()
+ KA.frobenius()
+ if curve.SignOfX == NEGATIVEX:
+ A = -A
+ lv = g(A, KA, Qx, Qy)
+ KA.frobenius()
+ KA = -KA
+ lv2 = g(A, KA, Qx, Qy)
+ lv.smul(lv2)
+ r[0] *= lv
+
+def e(P, Q):
+ r = miller(P, Q)
+ return fexp(r)
+
+
+def ate(P1, Q1):
+ nb,n3,n=lbits()
+
P = P1.copy()
Q = Q1.copy()
@@ -88,17 +140,19 @@
Q.affine()
A = P.copy()
Qx, Qy = Q.getxy()
- nb = n3.bit_length()
r = Fp12.one()
# miller loop
for i in range(nb - 2, 0, -1):
r.sqr()
- r *= g(A, A, Qx, Qy)
+ lv=g(A, A, Qx, Qy)
if big.bit(n3, i) == 1 and big.bit(n, i) == 0:
- r *= g(A, P, Qx, Qy)
+ lv2 = g(A, P, Qx, Qy)
+ lv.smul(lv2)
if big.bit(n3, i) == 0 and big.bit(n, i) == 1:
- r *= g(A, -P, Qx, Qy)
+ lv2 = g(A, -P, Qx, Qy)
+ lv.smul(lv2)
+ r *= lv
# adjustment
if curve.SignOfX == NEGATIVEX:
@@ -109,27 +163,19 @@
KA.frobenius()
if curve.SignOfX == NEGATIVEX:
A = -A
- r *= g(A, KA, Qx, Qy)
+ lv = g(A, KA, Qx, Qy)
KA.frobenius()
KA = -KA
- r *= g(A, KA, Qx, Qy)
+ lv2 = g(A, KA, Qx, Qy)
+ lv.smul(lv2)
+ r *= lv
return r
-def double_miller(P1, Q1, U1, V1):
- x = curve.x
+def double_ate(P1, Q1, U1, V1):
- if curve.PairingFriendly == BN:
- n = 6 * x
- if curve.SignOfX == POSITIVEX:
- n += 2
- else:
- n -= 2
- else:
- n = x
-
- n3 = 3 * n
+ nb,n3,n=lbits()
P = P1.copy()
Q = Q1.copy()
@@ -144,19 +190,26 @@
Qx, Qy = Q.getxy()
B = U.copy()
Wx, Wy = V.getxy()
- nb = n3.bit_length()
r = Fp12.one()
# miller loop
for i in range(nb - 2, 0, -1):
r.sqr()
- r *= g(A, A, Qx, Qy)
- r *= g(B, B, Wx, Wy)
+ lv = g(A, A, Qx, Qy)
+ lv2 = g(B, B, Wx, Wy)
+ lv.smul(lv2)
+ r *= lv
+ #r *= g(A, A, Qx, Qy)
+ #r *= g(B, B, Wx, Wy)
if big.bit(n3, i) == 1 and big.bit(n, i) == 0:
- r *= g(A, P, Qx, Qy)
- r *= g(B, U, Wx, Wy)
+ lv = g(A, P, Qx, Qy)
+ lv2 = g(B, U, Wx, Wy)
+ lv.smul(lv2)
+ r *= lv
if big.bit(n3, i) == 0 and big.bit(n, i) == 1:
- r *= g(A, -P, Qx, Qy)
- r *= g(B, -U, Wx, Wy)
+ lv = g(A, -P, Qx, Qy)
+ lv2 = g(B, -U, Wx, Wy)
+ lv.smul(lv2)
+ r *= lv
# adjustment
if curve.SignOfX == NEGATIVEX:
r.conj()
@@ -167,18 +220,22 @@
if curve.SignOfX == NEGATIVEX:
A = -A
B = -B
- r *= g(A, KA, Qx, Qy)
+ lv = g(A, KA, Qx, Qy)
KA.frobenius()
KA = -KA
- r *= g(A, KA, Qx, Qy)
+ lv2 = g(A, KA, Qx, Qy)
+ lv.smul(lv2)
+ r *= lv
KB = U.copy()
KB.frobenius()
- r *= g(B, KB, Wx, Wy)
+ lv = g(B, KB, Wx, Wy)
KB.frobenius()
KB = -KB
- r *= g(B, KB, Wx, Wy)
+ lv2 = g(B, KB, Wx, Wy)
+ lv.smul(lv2)
+ r *= lv
return r
diff --git a/version3/readme.txt b/version3/readme.txt
index 0726b16..e648fc1 100644
--- a/version3/readme.txt
+++ b/version3/readme.txt
@@ -1,61 +1,17 @@
-The Apache Milagro Cryptographic Library
+**New** August 2018. A Python version of the library is now available.
-Note that the AMCL currently comes in two versions, version 2.2
-and version 3.2
+Several helper programs are provided to assist with the addition of
+new elliptic curves. Note that these programs will not be needed if using
+one of the supported curves. These programs must be build using the MIRACL
+library. See source code for compilation instructions
----------------------------------------
+bigtobig.cpp - converts to BIG number format
-AMCL v2.2 is presented in what might be called a pre-library state.
+check.cpp - checks for optimal choice of number base
-In the various supported languages the source code is made available,
-but it is not organised into rigid packages/crates/jars/whatever
-It is expected that the consumer will themselves take this final step,
-depending on the exact requirements of their project.
+bestpair.cpp - finds best BN, BLS12 and BLS24 pairing-friendly curves
+(Note - the library does not currently support BLS24 curves)
-Note that version 2.2 is no longer supported.
+romgen.cpp - rough-and-ready program used to help generate ROM files for
+all of the different languages.
------------------------------------
-
-AMCL v3.2 incorporates many minor improvements
-
-Python version
-Web Assembly support
-Improved side channel resistance
-Faster Swift code
-Better Rust build system
-Improved modular inversion algorithm
-General speed optimizations
-Improved Javascript testbed
-More curves supported
-New BLS signature API
-Post quantum New Hope Implementation
-
------------------------------------
-
-AMCL v3.1 uses a standard Python 3 script to build libraries in all
-supported languages. New users should use this version.
-
-The main improvement is that AMCL v3 can optionally simultaneously support
-multiple elliptic curves and RSA key sizes within a single appliction.
-
-Note that AMCL is largely configured at compile time. In version 3 this
-configuration is handled by the Python script.
-
-AMCL is available in 32-bit and 64-bit versions in most languages. Limited
-support for 16-bit processors is provided by the C version.
-
-Now languages like to remain "standard" irrespective of the underlying
-hardware. However when it comes to optimal performance, it is impossible
-to remain architecture-agnostic. If a processor supports 64-bit
-instructions that operate on 64-bit registers, it will be a waste not to
-use them. Therefore the 64-bit language versions should always be used
-on 64-bit processors.
-
-Version 3.1 is a major "under the hood" upgrade. Field arithmetic is
-performed using ideas from http://eprint.iacr.org/2017/437 to ensure
-that critical calculations are performed in constant time. This strongly
-mitigates against side-channel attacks. Exception-free formulae are
-now used for Weierstrass elliptic curves. A new standardised script
-builds for the same set of curves across all languages.
-
----------------------------------------------
diff --git a/version3/rust/BenchtestALL.rs b/version3/rust/BenchtestALL.rs
index fff4e0d..55961be 100644
--- a/version3/rust/BenchtestALL.rs
+++ b/version3/rust/BenchtestALL.rs
@@ -715,7 +715,7 @@
println!("BN Pairing-Friendly Curve");
}
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BLS {
- println!("BLS24 Pairing-Friendly Curve");
+ println!("BLS48 Pairing-Friendly Curve");
}
println!("Modulus size {:} bits", fp::MODBITS);
diff --git a/version3/rust/src/bls.rs b/version3/rust/src/bls.rs
index 24381b4..7e7fd7a 100644
--- a/version3/rust/src/bls.rs
+++ b/version3/rust/src/bls.rs
@@ -78,7 +78,16 @@
let g = ECP2::generator();
let pk = ECP2::frombytes(&w);
d.neg();
- let mut v = pair::ate2(&g, &d, &pk, &hm);
+
+// Use new multi-pairing mechanism
+ let mut r=pair::initmp();
+ pair::another(&mut r,&g,&d);
+ pair::another(&mut r,&pk,&hm);
+ let mut v=pair::miller(&r);
+
+//.. or alternatively
+// let mut v = pair::ate2(&g, &d, &pk, &hm);
+
v = pair::fexp(&v);
if v.isunity() {
return BLS_OK;
diff --git a/version3/rust/src/bls192.rs b/version3/rust/src/bls192.rs
index 20dd579..20ee92e 100644
--- a/version3/rust/src/bls192.rs
+++ b/version3/rust/src/bls192.rs
@@ -78,7 +78,16 @@
let g = ECP4::generator();
let pk = ECP4::frombytes(&w);
d.neg();
- let mut v = pair192::ate2(&g, &d, &pk, &hm);
+
+// Use new multi-pairing mechanism
+ let mut r=pair192::initmp();
+ pair192::another(&mut r,&g,&d);
+ pair192::another(&mut r,&pk,&hm);
+ let mut v=pair192::miller(&r);
+
+//.. or alternatively
+// let mut v = pair192::ate2(&g, &d, &pk, &hm);
+
v = pair192::fexp(&v);
if v.isunity() {
return BLS_OK;
diff --git a/version3/rust/src/bls256.rs b/version3/rust/src/bls256.rs
index e9a00fb..cdb553d 100644
--- a/version3/rust/src/bls256.rs
+++ b/version3/rust/src/bls256.rs
@@ -78,7 +78,16 @@
let g = ECP8::generator();
let pk = ECP8::frombytes(&w);
d.neg();
- let mut v = pair256::ate2(&g, &d, &pk, &hm);
+
+// Use new multi-pairing mechanism
+ let mut r=pair256::initmp();
+ pair256::another(&mut r,&g,&d);
+ pair256::another(&mut r,&pk,&hm);
+ let mut v=pair256::miller(&r);
+
+//.. or alternatively
+// let mut v = pair256::ate2(&g, &d, &pk, &hm);
+
v = pair256::fexp(&v);
if v.isunity() {
return BLS_OK;
diff --git a/version3/rust/src/ecp4.rs b/version3/rust/src/ecp4.rs
index 79f3ee9..d34b0fd 100644
--- a/version3/rust/src/ecp4.rs
+++ b/version3/rust/src/ecp4.rs
@@ -24,7 +24,7 @@
use super::fp4::FP4;
use super::big::BIG;
use types::{SexticTwist, SignOfX};
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
pub struct ECP4 {
x: FP4,
diff --git a/version3/rust/src/ff.rs b/version3/rust/src/ff.rs
index 9a6611b..4737ee8 100644
--- a/version3/rust/src/ff.rs
+++ b/version3/rust/src/ff.rs
@@ -29,7 +29,7 @@
/* RSA/DH modulus length as multiple of BIGBITS */
pub use super::rom::FFLEN;
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
pub const FF_BITS: usize = (big::BIGBITS * FFLEN); /* Finite Field Size in bits - must be 256.2^n */
pub const HFLEN: usize = (FFLEN / 2); /* Useful for half-size RSA private key operations */
diff --git a/version3/rust/src/fp12.rs b/version3/rust/src/fp12.rs
index 98e6d31..4e5bfe5 100644
--- a/version3/rust/src/fp12.rs
+++ b/version3/rust/src/fp12.rs
@@ -24,12 +24,20 @@
use super::rom;
use types::SexticTwist;
use std::str::SplitWhitespace;
+use super::ecp;
+
+pub const ZERO: usize=0;
+pub const ONE: usize=1;
+pub const SPARSER: usize=2;
+pub const SPARSE: usize=3;
+pub const DENSE: usize=4;
#[derive(Copy, Clone)]
pub struct FP12 {
a: FP4,
b: FP4,
c: FP4,
+ stype: usize,
}
impl PartialEq for FP12 {
@@ -44,14 +52,28 @@
a: FP4::new(),
b: FP4::new(),
c: FP4::new(),
+ stype: ZERO,
}
}
+ pub fn settype(&mut self,t: usize) {
+ self.stype = t;
+ }
+
+ pub fn gettype(&self) -> usize {
+ return self.stype;
+ }
+
pub fn new_int(a: isize) -> FP12 {
let mut f = FP12::new();
f.a.copy(&FP4::new_int(a));
f.b.zero();
f.c.zero();
+ if a == 1 {
+ f.stype=ONE;
+ } else {
+ f.stype=SPARSER;
+ }
return f;
}
@@ -60,6 +82,7 @@
f.a.copy(&x.a);
f.b.copy(&x.b);
f.c.copy(&x.c);
+ f.stype=x.stype;
return f;
}
@@ -68,6 +91,7 @@
g.a.copy(d);
g.b.copy(e);
g.c.copy(f);
+ g.stype=DENSE;
return g;
}
@@ -76,6 +100,7 @@
g.a.copy(d);
g.b.zero();
g.c.zero();
+ g.stype=SPARSER;
return g;
}
@@ -104,6 +129,9 @@
self.a.cmove(&g.a, d);
self.b.cmove(&g.b, d);
self.c.cmove(&g.c, d);
+ let mut u=d as usize;
+ u=!(u-1);
+ self.stype^=(self.stype^g.stype)&u;
}
/* return 1 if b==c, no branching */
@@ -146,18 +174,21 @@
}
pub fn geta(&mut self) -> FP4 {
- let f = FP4::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP4::new_copy(&self.a);
+// return f;
}
pub fn getb(&mut self) -> FP4 {
- let f = FP4::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP4::new_copy(&self.b);
+// return f;
}
pub fn getc(&mut self) -> FP4 {
- let f = FP4::new_copy(&self.c);
- return f;
+ return self.c;
+// let f = FP4::new_copy(&self.c);
+// return f;
}
/* copy self=x */
@@ -165,6 +196,7 @@
self.a.copy(&x.a);
self.b.copy(&x.b);
self.c.copy(&x.c);
+ self.stype=x.stype;
}
/* set self=1 */
@@ -172,6 +204,7 @@
self.a.one();
self.b.zero();
self.c.zero();
+ self.stype=ONE;
}
/* this=conj(this) */
@@ -219,11 +252,16 @@
self.c.dbl();
self.b.add(&b);
self.c.add(&c);
+ self.stype=DENSE;
self.reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
pub fn sqr(&mut self) {
+ if self.stype==ONE {
+ return;
+ }
+
let mut a = FP4::new_copy(&self.a);
let mut b = FP4::new_copy(&self.b);
let mut c = FP4::new_copy(&self.c);
@@ -258,6 +296,11 @@
self.b.copy(&c);
self.b.add(&d);
self.c.add(&a);
+ if self.stype==SPARSER {
+ self.stype=SPARSE;
+ } else {
+ self.stype=DENSE;
+ }
self.norm();
}
@@ -328,114 +371,310 @@
z3.times_i();
self.a.copy(&z0);
self.a.add(&z3);
+ self.stype=DENSE;
+ self.norm();
+ }
+
+
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ pub fn ssmul(&mut self, y: &FP12) {
+ if self.stype==ONE {
+ self.copy(&y);
+ return;
+ }
+ if y.stype==ONE {
+ return;
+ }
+ if y.stype>=SPARSE {
+ let mut z0=FP4::new_copy(&self.a);
+ let mut z1=FP4::new_int(0);
+ let mut z2=FP4::new_int(0);
+ let mut z3=FP4::new_int(0);
+ z0.mul(&y.a);
+
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
+
+ let mut ga=FP2::new_int(0);
+ let mut gb=FP2::new_int(0);
+
+ gb.copy(&self.b.getb());
+ gb.mul(&y.b.getb());
+ ga.zero();
+ if y.stype!=SPARSE {
+ ga.copy(&self.b.getb());
+ ga.mul(&y.b.geta());
+ }
+ if self.stype!=SPARSE {
+ ga.copy(&self.b.geta());
+ ga.mul(&y.b.getb());
+ }
+ z2.set_fp2s(&ga,&gb);
+ z2.times_i();
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ let mut t0=FP4::new_copy(&self.a);
+ let mut t1=FP4::new_copy(&y.a);
+ t0.add(&self.b); t0.norm();
+ t1.add(&y.b); t1.norm();
+
+ z1.copy(&t0); z1.mul(&t1);
+ t0.copy(&self.b); t0.add(&self.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);
+ self.b.copy(&z1); self.b.add(&t1);
+
+ z3.add(&t1);
+ z2.add(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
+ t0.mul(&t1);
+ z2.add(&t0);
+
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
+
+ let mut ga=FP2::new_int(0);
+ let mut gb=FP2::new_int(0);
+
+ ga.copy(&self.c.geta());
+ ga.mul(&y.c.geta());
+ gb.zero();
+ if y.stype!=SPARSE {
+ gb.copy(&self.c.geta());
+ gb.mul(&y.c.getb());
+ }
+ if self.stype!=SPARSE {
+ gb.copy(&self.c.getb());
+ gb.mul(&y.c.geta());
+ }
+ t0.set_fp2s(&ga,&gb);
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ t1.copy(&t0); t1.neg();
+
+ self.c.copy(&z2); self.c.add(&t1);
+ z3.add(&t1);
+ t0.times_i();
+ self.b.add(&t0);
+ z3.norm();
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ } else {
+ if self.stype==SPARSER {
+ self.smul(&y);
+ return;
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE { // dense by sparser - 13m
+ let mut z0=FP4::new_copy(&self.a);
+ let mut z2=FP4::new_copy(&self.b);
+ let mut z3=FP4::new_copy(&self.b);
+ let mut t0=FP4::new_int(0);
+ let mut t1=FP4::new_copy(&y.a);
+
+ z0.mul(&y.a);
+ z2.pmul(&y.b.geta());
+ self.b.add(&self.a);
+ t1.padd(&y.b.geta());
+
+ t1.norm();
+ self.b.norm();
+ self.b.mul(&t1);
+ z3.add(&self.c);
+ z3.norm();
+ z3.pmul(&y.b.geta());
+
+ t0.copy(&z0); t0.neg();
+ t1.copy(&z2); t1.neg();
+
+ self.b.add(&t0);
+
+ self.b.add(&t1);
+ z3.add(&t1);
+ z2.add(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ z3.norm();
+ t0.mul(&y.a);
+ self.c.copy(&z2); self.c.add(&t0);
+
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+
+ let mut z0 = FP4::new_copy(&self.a);
+ let mut z1 = FP4::new();
+ let mut z2 = FP4::new();
+ let mut z3 = FP4::new();
+ let mut t0 = FP4::new_copy(&self.a);
+ let mut t1 = FP4::new();
+
+ z0.mul(&y.a);
+ t0.add(&self.b); t0.norm();
+
+ z1.copy(&t0); z1.mul(&y.a);
+ t0.copy(&self.b); t0.add(&self.c);
+ t0.norm();
+
+ z3.copy(&t0);
+ z3.pmul(&y.c.getb());
+ z3.times_i();
+
+ t0.copy(&z0); t0.neg();
+ z1.add(&t0);
+ self.b.copy(&z1);
+ z2.copy(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
+ t0.mul(&t1);
+ z2.add(&t0);
+ t0.copy(&self.c);
+
+ t0.pmul(&y.c.getb());
+ t0.times_i();
+ t1.copy(&t0); t1.neg();
+
+ self.c.copy(&z2); self.c.add(&t1);
+ z3.add(&t1);
+ t0.times_i();
+ self.b.add(&t0);
+ z3.norm();
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
+ }
+ self.stype=DENSE;
self.norm();
}
/* Special case of multiplication arises from special form of ATE pairing line function */
- pub fn smul(&mut self, y: &FP12, twist: usize) {
- if twist == SexticTwist::D_TYPE.into() {
- let mut z0 = FP4::new_copy(&self.a);
- let mut z2 = FP4::new_copy(&self.b);
- let mut z3 = FP4::new_copy(&self.b);
- let mut t0 = FP4::new();
- let mut t1 = FP4::new_copy(&y.a);
+ pub fn smul(&mut self, y: &FP12) {
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ let mut w1=FP2::new_copy(&self.a.geta());
+ let mut w2=FP2::new_copy(&self.a.getb());
+ let mut w3=FP2::new_copy(&self.b.geta());
- z0.mul(&y.a);
- z2.pmul(&y.b.real());
- self.b.add(&self.a);
- t1.padd(&y.b.real());
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.b.geta());
+ let mut ta=FP2::new_copy(&self.a.geta());
+ let mut tb=FP2::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP2::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP2::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
+
+ ta.copy(&self.a.geta()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.b.geta()); tb.norm();
+ let mut td=FP2::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
+
+ ta.copy(&self.a.getb()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.b.geta()); tb.norm();
+ let mut te=FP2::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
+
+ w2.mul_ip();
+ w1.add(&w2);
+
+ self.a.set_fp2s(&w1,&tc);
+ self.b.set_fp2s(&td,&te);
+ self.c.set_fp2(&w3);
+
+ self.a.norm();
self.b.norm();
- t1.norm();
+ } else {
+ let mut w1=FP2::new_copy(&self.a.geta());
+ let mut w2=FP2::new_copy(&self.a.getb());
+ let mut w3=FP2::new_copy(&self.c.getb());
- self.b.mul(&t1);
- z3.add(&self.c);
- z3.norm();
- z3.pmul(&y.b.real());
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.c.getb());
- t0.copy(&z0);
- t0.neg();
- t1.copy(&z2);
- t1.neg();
+ let mut ta=FP2::new_copy(&self.a.geta());
+ let mut tb=FP2::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP2::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP2::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
- self.b.add(&t0);
+ ta.copy(&self.a.geta()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.c.getb()); tb.norm();
+ let mut td=FP2::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
- self.b.add(&t1);
- z3.add(&t1);
- z2.add(&t0);
+ ta.copy(&self.a.getb()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.c.getb()); tb.norm();
+ let mut te=FP2::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
- t0.copy(&self.a);
- t0.add(&self.c);
- t0.norm();
- z3.norm();
+ w2.mul_ip();
+ w1.add(&w2);
+ self.a.set_fp2s(&w1,&tc);
- t0.mul(&y.a);
- self.c.copy(&z2);
- self.c.add(&t0);
+ w3.mul_ip();
+ w3.norm();
+ self.b.set_fp2h(&w3);
- z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
- }
- if twist == SexticTwist::M_TYPE.into() {
- let mut z0 = FP4::new_copy(&self.a);
- let mut z1 = FP4::new();
- let mut z2 = FP4::new();
- let mut z3 = FP4::new();
- let mut t0 = FP4::new_copy(&self.a);
- let mut t1 = FP4::new();
+ te.norm();
+ te.mul_ip();
+ self.c.set_fp2s(&te,&td);
- z0.mul(&y.a);
- t0.add(&self.b);
- t0.norm();
-
- z1.copy(&t0);
- z1.mul(&y.a);
- t0.copy(&self.b);
- t0.add(&self.c);
- t0.norm();
-
- z3.copy(&t0); //z3.mul(y.c);
- z3.pmul(&y.c.getb());
- z3.times_i();
-
- t0.copy(&z0);
- t0.neg();
-
- z1.add(&t0);
- self.b.copy(&z1);
- z2.copy(&t0);
-
- t0.copy(&self.a);
- t0.add(&self.c);
- t1.copy(&y.a);
- t1.add(&y.c);
-
- t0.norm();
- t1.norm();
-
- t0.mul(&t1);
- z2.add(&t0);
-
- t0.copy(&self.c);
-
- t0.pmul(&y.c.getb());
- t0.times_i();
-
- t1.copy(&t0);
- t1.neg();
-
- self.c.copy(&z2);
- self.c.add(&t1);
- z3.add(&t1);
- t0.times_i();
- self.b.add(&t0);
- z3.norm();
- z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
- }
- self.norm();
+ self.a.norm();
+ self.c.norm();
+ }
+ self.stype=SPARSE;
}
/* self=1/self */
@@ -483,6 +722,7 @@
self.b.mul(&f3);
self.c.copy(&f2);
self.c.mul(&f3);
+ self.stype=DENSE;
}
/* self=self^p using Frobenius */
@@ -499,6 +739,7 @@
self.b.pmul(f);
self.c.pmul(&f2);
+ self.stype=DENSE;
}
/* trace function */
@@ -660,7 +901,8 @@
FP12 {
a: FP4::from_hex_iter(iter),
b: FP4::from_hex_iter(iter),
- c: FP4::from_hex_iter(iter)
+ c: FP4::from_hex_iter(iter),
+ stype: DENSE
}
}
diff --git a/version3/rust/src/fp16.rs b/version3/rust/src/fp16.rs
index 0cbc348..c579db4 100644
--- a/version3/rust/src/fp16.rs
+++ b/version3/rust/src/fp16.rs
@@ -20,7 +20,7 @@
use super::fp2::FP2;
use super::fp8::FP8;
use super::big::BIG;
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
#[derive(Copy, Clone)]
pub struct FP16 {
@@ -64,6 +64,21 @@
return f;
}
+ pub fn set_fp8s(&mut self,c: &FP8, d: &FP8) {
+ self.a.copy(&c);
+ self.b.copy(&d);
+ }
+
+ pub fn set_fp8(&mut self,c: &FP8) {
+ self.a.copy(&c);
+ self.b.zero();
+ }
+
+ pub fn set_fp8h(&mut self,c: &FP8) {
+ self.b.copy(&c);
+ self.a.zero();
+ }
+
/* reduce components mod Modulus */
pub fn reduce(&mut self) {
self.a.reduce();
@@ -103,13 +118,15 @@
}
pub fn geta(&self) -> FP8 {
- let f = FP8::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP8::new_copy(&self.a);
+// return f;
}
/* extract imaginary part b */
pub fn getb(&self) -> FP8 {
- let f = FP8::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP8::new_copy(&self.b);
+// return f;
}
/* test self=x */
diff --git a/version3/rust/src/fp24.rs b/version3/rust/src/fp24.rs
index a7067bf..20149c8 100644
--- a/version3/rust/src/fp24.rs
+++ b/version3/rust/src/fp24.rs
@@ -25,13 +25,20 @@
use super::big::BIG;
use super::rom;
use types::{SexticTwist};
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
+
+pub const ZERO: usize=0;
+pub const ONE: usize=1;
+pub const SPARSER: usize=2;
+pub const SPARSE: usize=3;
+pub const DENSE: usize=4;
#[derive(Copy, Clone)]
pub struct FP24 {
a: FP8,
b: FP8,
c: FP8,
+ stype: usize,
}
impl FP24 {
@@ -40,14 +47,28 @@
a: FP8::new(),
b: FP8::new(),
c: FP8::new(),
+ stype: ZERO,
}
}
+ pub fn settype(&mut self,t: usize) {
+ self.stype = t;
+ }
+
+ pub fn gettype(&self) -> usize {
+ return self.stype;
+ }
+
pub fn new_int(a: isize) -> FP24 {
let mut f = FP24::new();
f.a.copy(&FP8::new_int(a));
f.b.zero();
f.c.zero();
+ if a == 1 {
+ f.stype=ONE;
+ } else {
+ f.stype=SPARSER;
+ }
return f;
}
@@ -56,6 +77,7 @@
f.a.copy(&x.a);
f.b.copy(&x.b);
f.c.copy(&x.c);
+ f.stype=x.stype;
return f;
}
@@ -64,6 +86,7 @@
g.a.copy(d);
g.b.copy(e);
g.c.copy(f);
+ g.stype=DENSE;
return g;
}
@@ -72,6 +95,7 @@
g.a.copy(d);
g.b.zero();
g.c.zero();
+ g.stype=SPARSER;
return g;
}
@@ -99,6 +123,9 @@
self.a.cmove(&g.a, d);
self.b.cmove(&g.b, d);
self.c.cmove(&g.c, d);
+ let mut u=d as usize;
+ u=!(u-1);
+ self.stype^=(self.stype^g.stype)&u;
}
/* return 1 if b==c, no branching */
@@ -141,18 +168,21 @@
}
pub fn geta(&mut self) -> FP8 {
- let f = FP8::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP8::new_copy(&self.a);
+// return f;
}
pub fn getb(&mut self) -> FP8 {
- let f = FP8::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP8::new_copy(&self.b);
+// return f;
}
pub fn getc(&mut self) -> FP8 {
- let f = FP8::new_copy(&self.c);
- return f;
+ return self.c;
+// let f = FP8::new_copy(&self.c);
+// return f;
}
/* copy self=x */
@@ -160,6 +190,7 @@
self.a.copy(&x.a);
self.b.copy(&x.b);
self.c.copy(&x.c);
+ self.stype=x.stype;
}
/* set self=1 */
@@ -167,6 +198,7 @@
self.a.one();
self.b.zero();
self.c.zero();
+ self.stype=ONE;
}
/* this=conj(this) */
@@ -214,11 +246,15 @@
self.c.dbl();
self.b.add(&b);
self.c.add(&c);
+ self.stype=DENSE;
self.reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
pub fn sqr(&mut self) {
+ if self.stype==ONE {
+ return;
+ }
let mut a = FP8::new_copy(&self.a);
let mut b = FP8::new_copy(&self.b);
let mut c = FP8::new_copy(&self.c);
@@ -253,6 +289,11 @@
self.b.copy(&c);
self.b.add(&d);
self.c.add(&a);
+ if self.stype==SPARSER {
+ self.stype=SPARSE;
+ } else {
+ self.stype=DENSE;
+ }
self.norm();
}
@@ -324,116 +365,312 @@
z3.times_i();
self.a.copy(&z0);
self.a.add(&z3);
+ self.stype=DENSE;
self.norm();
}
- /* Special case of multiplication arises from special form of ATE pairing line function */
- pub fn smul(&mut self, y: &FP24, twist: usize) {
- if twist == SexticTwist::D_TYPE.into() {
- let mut z0 = FP8::new_copy(&self.a);
- let mut z2 = FP8::new_copy(&self.b);
- let mut z3 = FP8::new_copy(&self.b);
- let mut t0 = FP8::new();
- let mut t1 = FP8::new_copy(&y.a);
-
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ pub fn ssmul(&mut self, y: &FP24) {
+ if self.stype==ONE {
+ self.copy(&y);
+ return;
+ }
+ if y.stype==ONE {
+ return;
+ }
+ if y.stype>=SPARSE {
+ let mut z0=FP8::new_copy(&self.a);
+ let mut z1=FP8::new_int(0);
+ let mut z2=FP8::new_int(0);
+ let mut z3=FP8::new_int(0);
z0.mul(&y.a);
- z2.pmul(&y.b.real());
- self.b.add(&self.a);
- t1.padd(&y.b.real());
- self.b.norm();
- t1.norm();
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
- self.b.mul(&t1);
- z3.add(&self.c);
- z3.norm();
- z3.pmul(&y.b.real());
+ let mut ga=FP4::new_int(0);
+ let mut gb=FP4::new_int(0);
- t0.copy(&z0);
- t0.neg();
- t1.copy(&z2);
- t1.neg();
+ gb.copy(&self.b.getb());
+ gb.mul(&y.b.getb());
+ ga.zero();
+ if y.stype!=SPARSE {
+ ga.copy(&self.b.getb());
+ ga.mul(&y.b.geta());
+ }
+ if self.stype!=SPARSE {
+ ga.copy(&self.b.geta());
+ ga.mul(&y.b.getb());
+ }
+ z2.set_fp4s(&ga,&gb);
+ z2.times_i();
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ let mut t0=FP8::new_copy(&self.a);
+ let mut t1=FP8::new_copy(&y.a);
+ t0.add(&self.b); t0.norm();
+ t1.add(&y.b); t1.norm();
- self.b.add(&t0);
+ z1.copy(&t0); z1.mul(&t1);
+ t0.copy(&self.b); t0.add(&self.c); t0.norm();
+ t1.copy(&y.b); t1.add(&y.c); t1.norm();
- self.b.add(&t1);
+ z3.copy(&t0); z3.mul(&t1);
+
+ t0.copy(&z0); t0.neg();
+ t1.copy(&z2); t1.neg();
+
+ z1.add(&t0);
+ self.b.copy(&z1); self.b.add(&t1);
+
z3.add(&t1);
z2.add(&t0);
- t0.copy(&self.a);
- t0.add(&self.c);
- t0.norm();
- z3.norm();
-
- t0.mul(&y.a);
- self.c.copy(&z2);
- self.c.add(&t0);
-
- z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
- }
- if twist == SexticTwist::M_TYPE.into() {
- let mut z0 = FP8::new_copy(&self.a);
- let mut z1 = FP8::new();
- let mut z2 = FP8::new();
- let mut z3 = FP8::new();
- let mut t0 = FP8::new_copy(&self.a);
- let mut t1 = FP8::new();
-
- z0.mul(&y.a);
- t0.add(&self.b);
- t0.norm();
-
- z1.copy(&t0);
- z1.mul(&y.a);
- t0.copy(&self.b);
- t0.add(&self.c);
- t0.norm();
-
- z3.copy(&t0);
- z3.pmul(&y.c.getb());
- z3.times_i();
-
- t0.copy(&z0);
- t0.neg();
-
- z1.add(&t0);
- self.b.copy(&z1);
- z2.copy(&t0);
-
- t0.copy(&self.a);
- t0.add(&self.c);
- t1.copy(&y.a);
- t1.add(&y.c);
-
- t0.norm();
- t1.norm();
-
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
t0.mul(&t1);
z2.add(&t0);
- t0.copy(&self.c);
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
- t0.pmul(&y.c.getb());
- t0.times_i();
+ let mut ga=FP4::new_int(0);
+ let mut gb=FP4::new_int(0);
- t1.copy(&t0);
- t1.neg();
+ ga.copy(&self.c.geta());
+ ga.mul(&y.c.geta());
+ gb.zero();
+ if y.stype!=SPARSE {
+ gb.copy(&self.c.geta());
+ gb.mul(&y.c.getb());
+ }
+ if self.stype!=SPARSE {
+ gb.copy(&self.c.getb());
+ gb.mul(&y.c.geta());
+ }
+ t0.set_fp4s(&ga,&gb);
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ t1.copy(&t0); t1.neg();
- self.c.copy(&z2);
- self.c.add(&t1);
+ self.c.copy(&z2); self.c.add(&t1);
z3.add(&t1);
t0.times_i();
self.b.add(&t0);
z3.norm();
z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
+ self.a.copy(&z0); self.a.add(&z3);
+ } else {
+ if self.stype==SPARSER {
+ self.smul(&y);
+ return;
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE { // dense by sparser - 13m
+ let mut z0=FP8::new_copy(&self.a);
+ let mut z2=FP8::new_copy(&self.b);
+ let mut z3=FP8::new_copy(&self.b);
+ let mut t0=FP8::new_int(0);
+ let mut t1=FP8::new_copy(&y.a);
+
+ z0.mul(&y.a);
+ z2.pmul(&y.b.geta());
+ self.b.add(&self.a);
+ t1.padd(&y.b.geta());
+
+ t1.norm();
+ self.b.norm();
+ self.b.mul(&t1);
+ z3.add(&self.c);
+ z3.norm();
+ z3.pmul(&y.b.geta());
+
+ t0.copy(&z0); t0.neg();
+ t1.copy(&z2); t1.neg();
+
+ self.b.add(&t0);
+
+ self.b.add(&t1);
+ z3.add(&t1);
+ z2.add(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ z3.norm();
+ t0.mul(&y.a);
+ self.c.copy(&z2); self.c.add(&t0);
+
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+
+ let mut z0 = FP8::new_copy(&self.a);
+ let mut z1 = FP8::new();
+ let mut z2 = FP8::new();
+ let mut z3 = FP8::new();
+ let mut t0 = FP8::new_copy(&self.a);
+ let mut t1 = FP8::new();
+
+ z0.mul(&y.a);
+ t0.add(&self.b); t0.norm();
+
+ z1.copy(&t0); z1.mul(&y.a);
+ t0.copy(&self.b); t0.add(&self.c);
+ t0.norm();
+
+ z3.copy(&t0);
+ z3.pmul(&y.c.getb());
+ z3.times_i();
+
+ t0.copy(&z0); t0.neg();
+ z1.add(&t0);
+ self.b.copy(&z1);
+ z2.copy(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
+ t0.mul(&t1);
+ z2.add(&t0);
+ t0.copy(&self.c);
+
+ t0.pmul(&y.c.getb());
+ t0.times_i();
+ t1.copy(&t0); t1.neg();
+
+ self.c.copy(&z2); self.c.add(&t1);
+ z3.add(&t1);
+ t0.times_i();
+ self.b.add(&t0);
+ z3.norm();
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
}
+ self.stype=DENSE;
self.norm();
}
+
+ /* Special case of multiplication arises from special form of ATE pairing line function */
+ pub fn smul(&mut self, y: &FP24) {
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ let mut w1=FP4::new_copy(&self.a.geta());
+ let mut w2=FP4::new_copy(&self.a.getb());
+ let mut w3=FP4::new_copy(&self.b.geta());
+
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.b.geta());
+
+ let mut ta=FP4::new_copy(&self.a.geta());
+ let mut tb=FP4::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP4::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP4::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
+
+ ta.copy(&self.a.geta()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.b.geta()); tb.norm();
+ let mut td=FP4::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
+
+ ta.copy(&self.a.getb()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.b.geta()); tb.norm();
+ let mut te=FP4::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
+
+ w2.times_i();
+ w1.add(&w2);
+
+ self.a.set_fp4s(&w1,&tc);
+ self.b.set_fp4s(&td,&te);
+ self.c.set_fp4(&w3);
+
+ self.a.norm();
+ self.b.norm();
+ } else {
+ let mut w1=FP4::new_copy(&self.a.geta());
+ let mut w2=FP4::new_copy(&self.a.getb());
+ let mut w3=FP4::new_copy(&self.c.getb());
+
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.c.getb());
+
+ let mut ta=FP4::new_copy(&self.a.geta());
+ let mut tb=FP4::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP4::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP4::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
+
+ ta.copy(&self.a.geta()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.c.getb()); tb.norm();
+ let mut td=FP4::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
+
+ ta.copy(&self.a.getb()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.c.getb()); tb.norm();
+ let mut te=FP4::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
+
+ w2.times_i();
+ w1.add(&w2);
+ self.a.set_fp4s(&w1,&tc);
+
+ w3.times_i();
+ w3.norm();
+ self.b.set_fp4h(&w3);
+
+ te.norm();
+ te.times_i();
+ self.c.set_fp4s(&te,&td);
+
+ self.a.norm();
+ self.c.norm();
+ }
+ self.stype=SPARSE;
+ }
+
/* self=1/self */
pub fn inverse(&mut self) {
let mut f0 = FP8::new_copy(&self.a);
@@ -479,6 +716,7 @@
self.b.mul(&f3);
self.c.copy(&f2);
self.c.mul(&f3);
+ self.stype=DENSE;
}
/* self=self^p using Frobenius */
@@ -503,6 +741,7 @@
self.c.times_i2();
self.c.times_i2();
}
+ self.stype=DENSE;
}
/* trace function */
diff --git a/version3/rust/src/fp4.rs b/version3/rust/src/fp4.rs
index 97193ba..1db4b73 100644
--- a/version3/rust/src/fp4.rs
+++ b/version3/rust/src/fp4.rs
@@ -69,6 +69,21 @@
f.b.zero();
return f;
}
+
+ pub fn set_fp2s(&mut self,c: &FP2, d: &FP2) {
+ self.a.copy(&c);
+ self.b.copy(&d);
+ }
+
+ pub fn set_fp2(&mut self,c: &FP2) {
+ self.a.copy(&c);
+ self.b.zero();
+ }
+
+ pub fn set_fp2h(&mut self,c: &FP2) {
+ self.b.copy(&c);
+ self.a.zero();
+ }
/* reduce components mod Modulus */
pub fn reduce(&mut self) {
@@ -109,13 +124,15 @@
}
pub fn geta(&self) -> FP2 {
- let f = FP2::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP2::new_copy(&self.a);
+// return f;
}
/* extract imaginary part b */
pub fn getb(&self) -> FP2 {
- let f = FP2::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP2::new_copy(&self.b);
+// return f;
}
/* test self=x */
diff --git a/version3/rust/src/fp48.rs b/version3/rust/src/fp48.rs
index 7b57e2b..bda42e0 100644
--- a/version3/rust/src/fp48.rs
+++ b/version3/rust/src/fp48.rs
@@ -26,13 +26,20 @@
use super::big::BIG;
use super::rom;
use types::SexticTwist;
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
+
+pub const ZERO: usize=0;
+pub const ONE: usize=1;
+pub const SPARSER: usize=2;
+pub const SPARSE: usize=3;
+pub const DENSE: usize=4;
#[derive(Copy, Clone)]
pub struct FP48 {
a: FP16,
b: FP16,
c: FP16,
+ stype: usize,
}
impl FP48 {
@@ -41,14 +48,28 @@
a: FP16::new(),
b: FP16::new(),
c: FP16::new(),
+ stype: ZERO,
}
}
+ pub fn settype(&mut self,t: usize) {
+ self.stype = t;
+ }
+
+ pub fn gettype(&self) -> usize {
+ return self.stype;
+ }
+
pub fn new_int(a: isize) -> FP48 {
let mut f = FP48::new();
f.a.copy(&FP16::new_int(a));
f.b.zero();
f.c.zero();
+ if a == 1 {
+ f.stype=ONE;
+ } else {
+ f.stype=SPARSER;
+ }
return f;
}
@@ -57,6 +78,7 @@
f.a.copy(&x.a);
f.b.copy(&x.b);
f.c.copy(&x.c);
+ f.stype=x.stype;
return f;
}
@@ -65,6 +87,7 @@
g.a.copy(d);
g.b.copy(e);
g.c.copy(f);
+ g.stype=DENSE;
return g;
}
@@ -73,6 +96,7 @@
g.a.copy(d);
g.b.zero();
g.c.zero();
+ g.stype=SPARSER;
return g;
}
@@ -100,6 +124,9 @@
self.a.cmove(&g.a, d);
self.b.cmove(&g.b, d);
self.c.cmove(&g.c, d);
+ let mut u=d as usize;
+ u=!(u-1);
+ self.stype^=(self.stype^g.stype)&u;
}
/* return 1 if b==c, no branching */
@@ -142,18 +169,21 @@
}
pub fn geta(&mut self) -> FP16 {
- let f = FP16::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP16::new_copy(&self.a);
+// return f;
}
pub fn getb(&mut self) -> FP16 {
- let f = FP16::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP16::new_copy(&self.b);
+// return f;
}
pub fn getc(&mut self) -> FP16 {
- let f = FP16::new_copy(&self.c);
- return f;
+ return self.c;
+// let f = FP16::new_copy(&self.c);
+// return f;
}
/* copy self=x */
@@ -161,6 +191,7 @@
self.a.copy(&x.a);
self.b.copy(&x.b);
self.c.copy(&x.c);
+ self.stype=x.stype;
}
/* set self=1 */
@@ -168,6 +199,7 @@
self.a.one();
self.b.zero();
self.c.zero();
+ self.stype=ONE;
}
/* this=conj(this) */
@@ -215,11 +247,15 @@
self.c.dbl();
self.b.add(&b);
self.c.add(&c);
+ self.stype=DENSE;
self.reduce();
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
pub fn sqr(&mut self) {
+ if self.stype==ONE {
+ return;
+ }
let mut a = FP16::new_copy(&self.a);
let mut b = FP16::new_copy(&self.b);
let mut c = FP16::new_copy(&self.c);
@@ -254,6 +290,11 @@
self.b.copy(&c);
self.b.add(&d);
self.c.add(&a);
+ if self.stype==SPARSER {
+ self.stype=SPARSE;
+ } else {
+ self.stype=DENSE;
+ }
self.norm();
}
@@ -324,115 +365,312 @@
z3.times_i();
self.a.copy(&z0);
self.a.add(&z3);
+ self.stype=DENSE;
self.norm();
}
- /* Special case of multiplication arises from special form of ATE pairing line function */
- pub fn smul(&mut self, y: &FP48, twist: usize) {
- if twist == SexticTwist::D_TYPE.into() {
- let mut z0 = FP16::new_copy(&self.a);
- let mut z2 = FP16::new_copy(&self.b);
- let mut z3 = FP16::new_copy(&self.b);
- let mut t0 = FP16::new();
- let mut t1 = FP16::new_copy(&y.a);
-
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ pub fn ssmul(&mut self, y: &FP48) {
+ if self.stype==ONE {
+ self.copy(&y);
+ return;
+ }
+ if y.stype==ONE {
+ return;
+ }
+ if y.stype>=SPARSE {
+ let mut z0=FP16::new_copy(&self.a);
+ let mut z1=FP16::new_int(0);
+ let mut z2=FP16::new_int(0);
+ let mut z3=FP16::new_int(0);
z0.mul(&y.a);
- z2.pmul(&y.b.real());
- self.b.add(&self.a);
- t1.padd(&y.b.real());
- self.b.norm();
- t1.norm();
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
- self.b.mul(&t1);
- z3.add(&self.c);
- z3.norm();
- z3.pmul(&y.b.real());
+ let mut ga=FP8::new_int(0);
+ let mut gb=FP8::new_int(0);
- t0.copy(&z0);
- t0.neg();
- t1.copy(&z2);
- t1.neg();
+ gb.copy(&self.b.getb());
+ gb.mul(&y.b.getb());
+ ga.zero();
+ if y.stype!=SPARSE {
+ ga.copy(&self.b.getb());
+ ga.mul(&y.b.geta());
+ }
+ if self.stype!=SPARSE {
+ ga.copy(&self.b.geta());
+ ga.mul(&y.b.getb());
+ }
+ z2.set_fp8s(&ga,&gb);
+ z2.times_i();
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ } else {
+ z2.copy(&self.b);
+ z2.mul(&y.b);
+ }
+ let mut t0=FP16::new_copy(&self.a);
+ let mut t1=FP16::new_copy(&y.a);
+ t0.add(&self.b); t0.norm();
+ t1.add(&y.b); t1.norm();
- self.b.add(&t0);
- self.b.add(&t1);
+ z1.copy(&t0); z1.mul(&t1);
+ t0.copy(&self.b); t0.add(&self.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);
+ self.b.copy(&z1); self.b.add(&t1);
+
z3.add(&t1);
z2.add(&t0);
- t0.copy(&self.a);
- t0.add(&self.c);
- t0.norm();
- z3.norm();
-
- t0.mul(&y.a);
- self.c.copy(&z2);
- self.c.add(&t0);
-
- z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
- }
- if twist == SexticTwist::M_TYPE.into() {
- let mut z0 = FP16::new_copy(&self.a);
- let mut z1 = FP16::new();
- let mut z2 = FP16::new();
- let mut z3 = FP16::new();
- let mut t0 = FP16::new_copy(&self.a);
- let mut t1 = FP16::new();
-
- z0.mul(&y.a);
- t0.add(&self.b);
- t0.norm();
-
- z1.copy(&t0);
- z1.mul(&y.a);
- t0.copy(&self.b);
- t0.add(&self.c);
- t0.norm();
-
- z3.copy(&t0);
- z3.pmul(&y.c.getb());
- z3.times_i();
-
- t0.copy(&z0);
- t0.neg();
-
- z1.add(&t0);
- self.b.copy(&z1);
- z2.copy(&t0);
-
- t0.copy(&self.a);
- t0.add(&self.c);
- t1.copy(&y.a);
- t1.add(&y.c);
-
- t0.norm();
- t1.norm();
-
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
t0.mul(&t1);
z2.add(&t0);
- t0.copy(&self.c);
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ if y.stype==SPARSE || self.stype==SPARSE {
- t0.pmul(&y.c.getb());
- t0.times_i();
+ let mut ga=FP8::new_int(0);
+ let mut gb=FP8::new_int(0);
- t1.copy(&t0);
- t1.neg();
+ ga.copy(&self.c.geta());
+ ga.mul(&y.c.geta());
+ gb.zero();
+ if y.stype!=SPARSE {
+ gb.copy(&self.c.geta());
+ gb.mul(&y.c.getb());
+ }
+ if self.stype!=SPARSE {
+ gb.copy(&self.c.getb());
+ gb.mul(&y.c.geta());
+ }
+ t0.set_fp8s(&ga,&gb);
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ } else {
+ t0.copy(&self.c);
+ t0.mul(&y.c);
+ }
+ t1.copy(&t0); t1.neg();
- self.c.copy(&z2);
- self.c.add(&t1);
+ self.c.copy(&z2); self.c.add(&t1);
z3.add(&t1);
t0.times_i();
self.b.add(&t0);
z3.norm();
z3.times_i();
- self.a.copy(&z0);
- self.a.add(&z3);
+ self.a.copy(&z0); self.a.add(&z3);
+ } else {
+ if self.stype==SPARSER {
+ self.smul(&y);
+ return;
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE { // dense by sparser - 13m
+ let mut z0=FP16::new_copy(&self.a);
+ let mut z2=FP16::new_copy(&self.b);
+ let mut z3=FP16::new_copy(&self.b);
+ let mut t0=FP16::new_int(0);
+ let mut t1=FP16::new_copy(&y.a);
+
+ z0.mul(&y.a);
+ z2.pmul(&y.b.geta());
+ self.b.add(&self.a);
+ t1.padd(&y.b.geta());
+
+ t1.norm();
+ self.b.norm();
+ self.b.mul(&t1);
+ z3.add(&self.c);
+ z3.norm();
+ z3.pmul(&y.b.geta());
+
+ t0.copy(&z0); t0.neg();
+ t1.copy(&z2); t1.neg();
+
+ self.b.add(&t0);
+
+ self.b.add(&t1);
+ z3.add(&t1);
+ z2.add(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ z3.norm();
+ t0.mul(&y.a);
+ self.c.copy(&z2); self.c.add(&t0);
+
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+
+ let mut z0 = FP16::new_copy(&self.a);
+ let mut z1 = FP16::new();
+ let mut z2 = FP16::new();
+ let mut z3 = FP16::new();
+ let mut t0 = FP16::new_copy(&self.a);
+ let mut t1 = FP16::new();
+
+ z0.mul(&y.a);
+ t0.add(&self.b); t0.norm();
+
+ z1.copy(&t0); z1.mul(&y.a);
+ t0.copy(&self.b); t0.add(&self.c);
+ t0.norm();
+
+ z3.copy(&t0);
+ z3.pmul(&y.c.getb());
+ z3.times_i();
+
+ t0.copy(&z0); t0.neg();
+ z1.add(&t0);
+ self.b.copy(&z1);
+ z2.copy(&t0);
+
+ t0.copy(&self.a); t0.add(&self.c); t0.norm();
+ t1.copy(&y.a); t1.add(&y.c); t1.norm();
+
+ t0.mul(&t1);
+ z2.add(&t0);
+ t0.copy(&self.c);
+
+ t0.pmul(&y.c.getb());
+ t0.times_i();
+ t1.copy(&t0); t1.neg();
+
+ self.c.copy(&z2); self.c.add(&t1);
+ z3.add(&t1);
+ t0.times_i();
+ self.b.add(&t0);
+ z3.norm();
+ z3.times_i();
+ self.a.copy(&z0); self.a.add(&z3);
+ }
}
+ self.stype=DENSE;
self.norm();
}
+
+ /* Special case of multiplication arises from special form of ATE pairing line function */
+ pub fn smul(&mut self, y: &FP48) {
+ if ecp::SEXTIC_TWIST==SexticTwist::D_TYPE {
+ let mut w1=FP8::new_copy(&self.a.geta());
+ let mut w2=FP8::new_copy(&self.a.getb());
+ let mut w3=FP8::new_copy(&self.b.geta());
+
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.b.geta());
+
+ let mut ta=FP8::new_copy(&self.a.geta());
+ let mut tb=FP8::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP8::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP8::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
+
+ ta.copy(&self.a.geta()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.b.geta()); tb.norm();
+ let mut td=FP8::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
+
+ ta.copy(&self.a.getb()); ta.add(&self.b.geta()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.b.geta()); tb.norm();
+ let mut te=FP8::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
+
+ w2.times_i();
+ w1.add(&w2);
+
+ self.a.set_fp8s(&w1,&tc);
+ self.b.set_fp8s(&td,&te);
+ self.c.set_fp8(&w3);
+
+ self.a.norm();
+ self.b.norm();
+ } else {
+ let mut w1=FP8::new_copy(&self.a.geta());
+ let mut w2=FP8::new_copy(&self.a.getb());
+ let mut w3=FP8::new_copy(&self.c.getb());
+
+ w1.mul(&y.a.geta());
+ w2.mul(&y.a.getb());
+ w3.mul(&y.c.getb());
+
+ let mut ta=FP8::new_copy(&self.a.geta());
+ let mut tb=FP8::new_copy(&y.a.geta());
+ ta.add(&self.a.getb()); ta.norm();
+ tb.add(&y.a.getb()); tb.norm();
+ let mut tc=FP8::new_copy(&ta);
+ tc.mul(&tb);
+ let mut t=FP8::new_copy(&w1);
+ t.add(&w2);
+ t.neg();
+ tc.add(&t);
+
+ ta.copy(&self.a.geta()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.geta()); tb.add(&y.c.getb()); tb.norm();
+ let mut td=FP8::new_copy(&ta);
+ td.mul(&tb);
+ t.copy(&w1);
+ t.add(&w3);
+ t.neg();
+ td.add(&t);
+
+ ta.copy(&self.a.getb()); ta.add(&self.c.getb()); ta.norm();
+ tb.copy(&y.a.getb()); tb.add(&y.c.getb()); tb.norm();
+ let mut te=FP8::new_copy(&ta);
+ te.mul(&tb);
+ t.copy(&w2);
+ t.add(&w3);
+ t.neg();
+ te.add(&t);
+
+ w2.times_i();
+ w1.add(&w2);
+ self.a.set_fp8s(&w1,&tc);
+
+ w3.times_i();
+ w3.norm();
+ self.b.set_fp8h(&w3);
+
+ te.norm();
+ te.times_i();
+ self.c.set_fp8s(&te,&td);
+
+ self.a.norm();
+ self.c.norm();
+ }
+ self.stype=SPARSE;
+ }
+
/* self=1/self */
pub fn inverse(&mut self) {
let mut f0 = FP16::new_copy(&self.a);
@@ -478,6 +716,7 @@
self.b.mul(&f3);
self.c.copy(&f2);
self.c.mul(&f3);
+ self.stype=DENSE;
}
/* self=self^p using Frobenius */
@@ -506,6 +745,7 @@
self.c.times_i4();
self.c.times_i4();
}
+ self.stype=DENSE;
}
/* trace function */
diff --git a/version3/rust/src/fp8.rs b/version3/rust/src/fp8.rs
index 5ceac43..dfc84d1 100644
--- a/version3/rust/src/fp8.rs
+++ b/version3/rust/src/fp8.rs
@@ -21,7 +21,7 @@
use super::fp2::FP2;
use super::fp4::FP4;
use super::big::BIG;
-use std::str::SplitWhitespace;
+//use std::str::SplitWhitespace;
#[derive(Copy, Clone)]
pub struct FP8 {
@@ -65,6 +65,22 @@
return f;
}
+ pub fn set_fp4s(&mut self,c: &FP4, d: &FP4) {
+ self.a.copy(&c);
+ self.b.copy(&d);
+ }
+
+ pub fn set_fp4(&mut self,c: &FP4) {
+ self.a.copy(&c);
+ self.b.zero();
+ }
+
+ pub fn set_fp4h(&mut self,c: &FP4) {
+ self.b.copy(&c);
+ self.a.zero();
+ }
+
+
/* reduce components mod Modulus */
pub fn reduce(&mut self) {
self.a.reduce();
@@ -104,13 +120,15 @@
}
pub fn geta(&self) -> FP4 {
- let f = FP4::new_copy(&self.a);
- return f;
+ return self.a;
+// let f = FP4::new_copy(&self.a);
+// return f;
}
/* extract imaginary part b */
pub fn getb(&self) -> FP4 {
- let f = FP4::new_copy(&self.b);
- return f;
+ return self.b;
+// let f = FP4::new_copy(&self.b);
+// return f;
}
/* test self=x */
diff --git a/version3/rust/src/pair.rs b/version3/rust/src/pair.rs
index 7aeb493..876c385 100644
--- a/version3/rust/src/pair.rs
+++ b/version3/rust/src/pair.rs
@@ -23,6 +23,7 @@
use super::fp2::FP2;
use super::ecp2::ECP2;
use super::fp4::FP4;
+use super::fp12;
use super::fp12::FP12;
use super::big::BIG;
use super::dbig::DBIG;
@@ -80,7 +81,9 @@
c.times_i();
}
A.dbl();
- return FP12::new_fp4s(&a, &b, &c);
+ let mut res= FP12::new_fp4s(&a, &b, &c);
+ res.settype(fp12::SPARSER);
+ return res;
}
#[allow(non_snake_case)]
@@ -129,15 +132,123 @@
}
A.add(B);
- return FP12::new_fp4s(&a, &b, &c);
+ let mut res= FP12::new_fp4s(&a, &b, &c);
+ res.settype(fp12::SPARSER);
+ return res;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+#[allow(non_snake_case)]
+fn lbits(n3: &mut BIG,n: &mut BIG) -> usize {
+ n.copy(&BIG::new_ints(&rom::CURVE_BNX));
+ if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
+ n.pmul(6);
+ if ecp::SIGN_OF_X==SignOfX::POSITIVEX {
+ n.inc(2);
+ } else {
+ n.dec(2);
+ }
+ }
+ n.norm();
+ n3.copy(&n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+}
+
+/* prepare for multi-pairing */
+pub fn initmp() -> [FP12; rom::ATE_BITS] {
+ let r: [FP12; rom::ATE_BITS] = [FP12::new_int(1); rom::ATE_BITS];
+ return r
+}
+
+/* basic Miller loop */
+pub fn miller(r:&[FP12]) -> FP12 {
+ let mut res=FP12::new_int(1);
+ for i in (1..rom::ATE_BITS).rev() {
+ res.sqr();
+ res.ssmul(&r[i]);
+ }
+
+ if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(&r[0]);
+ return res;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+#[allow(non_snake_case)]
+pub fn another(r:&mut [FP12],P1: &ECP2,Q1: &ECP) {
+ let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
+ let mut K = ECP2::new();
+
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ let mut P = ECP2::new();
+ P.copy(P1);
+ P.affine();
+ let mut Q = ECP::new();
+ Q.copy(Q1);
+ Q.affine();
+
+ if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
+ if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
+ f.inverse();
+ f.norm();
+ }
+ }
+
+ let qx = FP::new_copy(&Q.getpx());
+ let qy = FP::new_copy(&Q.getpy());
+ let mut A = ECP2::new();
+
+ A.copy(&P);
+ let mut NP = ECP2::new();
+ NP.copy(&P);
+ NP.neg();
+
+ let nb=lbits(&mut n3,&mut n);
+
+ for i in (1..nb-1).rev() {
+ let mut lv=linedbl(&mut A,&qx,&qy);
+
+ let bt=n3.bit(i)-n.bit(i);
+ if bt==1 {
+ let lv2=lineadd(&mut A,&P,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ if bt==-1 {
+ let lv2=lineadd(&mut A,&NP,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ r[i].ssmul(&lv);
+ }
+
+/* R-ate fixup required for BN curves */
+ if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
+ if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
+ A.neg();
+ }
+ K.copy(&P);
+ K.frob(&f);
+ let mut lv=lineadd(&mut A,&K,&qx,&qy);
+ K.frob(&f);
+ K.neg();
+ let lv2=lineadd(&mut A,&K,&qx,&qy);
+ lv.smul(&lv2);
+ r[0].ssmul(&lv);
+ }
}
#[allow(non_snake_case)]
/* Optimal R-ate pairing */
pub fn ate(P1: &ECP2, Q1: &ECP) -> FP12 {
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let mut n = BIG::new_copy(&x);
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut K = ECP2::new();
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
@@ -145,21 +256,7 @@
f.inverse();
f.norm();
}
- n.pmul(6);
- if ecp::SIGN_OF_X == SignOfX::POSITIVEX {
- n.inc(2);
- } else {
- n.dec(2);
- }
- } else {
- n.copy(&x)
- }
-
- n.norm();
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
-
+ }
let mut P = ECP2::new();
P.copy(P1);
P.affine();
@@ -178,22 +275,21 @@
NP.copy(&P);
NP.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
-
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
- lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &P, &qx, &qy);
+ lv.smul(&lv2);
}
if bt == -1 {
- lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &NP, &qx, &qy);
+ lv.smul(&lv2);
}
+ r.ssmul(&lv);
}
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
@@ -211,11 +307,11 @@
K.frob(&f);
let mut lv = lineadd(&mut A, &K, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
K.frob(&f);
K.neg();
- lv = lineadd(&mut A, &K, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &K, &qx, &qy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
return r;
@@ -225,8 +321,8 @@
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
pub fn ate2(P1: &ECP2, Q1: &ECP, R1: &ECP2, S1: &ECP) -> FP12 {
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let mut n = BIG::new_copy(&x);
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut K = ECP2::new();
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
@@ -234,20 +330,7 @@
f.inverse();
f.norm();
}
- n.pmul(6);
- if ecp::SIGN_OF_X == SignOfX::POSITIVEX {
- n.inc(2);
- } else {
- n.dec(2);
- }
- } else {
- n.copy(&x)
- }
-
- n.norm();
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
+ }
let mut P = ECP2::new();
P.copy(P1);
@@ -282,26 +365,26 @@
NR.copy(&R);
NR.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = linedbl(&mut B, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = linedbl(&mut B, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &R, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &R, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
if bt == -1 {
lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &NR, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &NR, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
}
@@ -319,21 +402,22 @@
K.frob(&f);
let mut lv = lineadd(&mut A, &K, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
K.frob(&f);
K.neg();
- lv = lineadd(&mut A, &K, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let mut lv2 = lineadd(&mut A, &K, &qx, &qy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
K.copy(&R);
K.frob(&f);
lv = lineadd(&mut B, &K, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
K.frob(&f);
K.neg();
- lv = lineadd(&mut B, &K, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ lv2 = lineadd(&mut B, &K, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
+
}
return r;
diff --git a/version3/rust/src/pair192.rs b/version3/rust/src/pair192.rs
index f47e294..4d2e769 100644
--- a/version3/rust/src/pair192.rs
+++ b/version3/rust/src/pair192.rs
@@ -24,6 +24,7 @@
use super::ecp4::ECP4;
use super::fp4::FP4;
use super::fp8::FP8;
+use super::fp24;
use super::fp24::FP24;
use super::big::BIG;
use super::ecp;
@@ -79,7 +80,9 @@
c.times_i();
}
A.dbl();
- return FP24::new_fp8s(&a, &b, &c);
+ let mut res= FP24::new_fp8s(&a, &b, &c);
+ res.settype(fp24::SPARSER);
+ return res;
}
#[allow(non_snake_case)]
@@ -127,18 +130,88 @@
}
A.add(B);
- return FP24::new_fp8s(&a, &b, &c);
+ let mut res= FP24::new_fp8s(&a, &b, &c);
+ res.settype(fp24::SPARSER);
+ return res;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+#[allow(non_snake_case)]
+fn lbits(n3: &mut BIG,n: &mut BIG) -> usize {
+ n.copy(&BIG::new_ints(&rom::CURVE_BNX));
+ n3.copy(&n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+}
+
+/* prepare for multi-pairing */
+pub fn initmp() -> [FP24; rom::ATE_BITS] {
+ let r: [FP24; rom::ATE_BITS] = [FP24::new_int(1); rom::ATE_BITS];
+ return r
+}
+
+/* basic Miller loop */
+pub fn miller(r:&[FP24]) -> FP24 {
+ let mut res=FP24::new_int(1);
+ for i in (1..rom::ATE_BITS).rev() {
+ res.sqr();
+ res.ssmul(&r[i]);
+ }
+
+ if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(&r[0]);
+ return res;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+#[allow(non_snake_case)]
+pub fn another(r:&mut [FP24],P1: &ECP4,Q1: &ECP) {
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ let mut P = ECP4::new();
+ P.copy(P1);
+ P.affine();
+ let mut Q = ECP::new();
+ Q.copy(Q1);
+ Q.affine();
+
+ let qx = FP::new_copy(&Q.getpx());
+ let qy = FP::new_copy(&Q.getpy());
+ let mut A = ECP4::new();
+
+ A.copy(&P);
+ let mut NP = ECP4::new();
+ NP.copy(&P);
+ NP.neg();
+
+ let nb=lbits(&mut n3,&mut n);
+
+ for i in (1..nb-1).rev() {
+ let mut lv=linedbl(&mut A,&qx,&qy);
+
+ let bt=n3.bit(i)-n.bit(i);
+ if bt==1 {
+ let lv2=lineadd(&mut A,&P,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ if bt==-1 {
+ let lv2=lineadd(&mut A,&NP,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ r[i].ssmul(&lv);
+ }
}
#[allow(non_snake_case)]
/* Optimal R-ate pairing */
pub fn ate(P1: &ECP4, Q1: &ECP) -> FP24 {
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let n = BIG::new_copy(&x);
-
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut P = ECP4::new();
P.copy(P1);
@@ -158,21 +231,23 @@
NP.copy(&P);
NP.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
+
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
- lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &P, &qx, &qy);
+ lv.smul(&lv2);
}
if bt == -1 {
- lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &NP, &qx, &qy);
+ lv.smul(&lv2);
}
+ r.ssmul(&lv);
}
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
@@ -185,12 +260,8 @@
#[allow(non_snake_case)]
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
pub fn ate2(P1: &ECP4, Q1: &ECP, R1: &ECP4, S1: &ECP) -> FP24 {
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let n = BIG::new_copy(&x);
-
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut P = ECP4::new();
P.copy(P1);
@@ -225,26 +296,26 @@
NR.copy(&R);
NR.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = linedbl(&mut B, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = linedbl(&mut B, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &R, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &R, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
if bt == -1 {
lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &NR, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &NR, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
}
diff --git a/version3/rust/src/pair256.rs b/version3/rust/src/pair256.rs
index 92b4099..bdf2e5b 100644
--- a/version3/rust/src/pair256.rs
+++ b/version3/rust/src/pair256.rs
@@ -24,6 +24,7 @@
use super::ecp8::ECP8;
use super::fp8::FP8;
use super::fp16::FP16;
+use super::fp48;
use super::fp48::FP48;
use super::big::BIG;
use super::ecp;
@@ -79,7 +80,9 @@
c.times_i();
}
A.dbl();
- return FP48::new_fp16s(&a, &b, &c);
+ let mut res= FP48::new_fp16s(&a, &b, &c);
+ res.settype(fp48::SPARSER);
+ return res;
}
#[allow(non_snake_case)]
@@ -127,18 +130,88 @@
}
A.add(B);
- return FP48::new_fp16s(&a, &b, &c);
+ let mut res= FP48::new_fp16s(&a, &b, &c);
+ res.settype(fp48::SPARSER);
+ return res;
+}
+
+/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+#[allow(non_snake_case)]
+fn lbits(n3: &mut BIG,n: &mut BIG) -> usize {
+ n.copy(&BIG::new_ints(&rom::CURVE_BNX));
+ n3.copy(&n);
+ n3.pmul(3);
+ n3.norm();
+ return n3.nbits();
+}
+
+/* prepare for multi-pairing */
+pub fn initmp() -> [FP48; rom::ATE_BITS] {
+ let r: [FP48; rom::ATE_BITS] = [FP48::new_int(1); rom::ATE_BITS];
+ return r
+}
+
+/* basic Miller loop */
+pub fn miller(r:&[FP48]) -> FP48 {
+ let mut res=FP48::new_int(1);
+ for i in (1..rom::ATE_BITS).rev() {
+ res.sqr();
+ res.ssmul(&r[i]);
+ }
+
+ if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(&r[0]);
+ return res;
+}
+
+/* Accumulate another set of line functions for n-pairing */
+#[allow(non_snake_case)]
+pub fn another(r:&mut [FP48],P1: &ECP8,Q1: &ECP) {
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ let mut P = ECP8::new();
+ P.copy(P1);
+ P.affine();
+ let mut Q = ECP::new();
+ Q.copy(Q1);
+ Q.affine();
+
+ let qx = FP::new_copy(&Q.getpx());
+ let qy = FP::new_copy(&Q.getpy());
+ let mut A = ECP8::new();
+
+ A.copy(&P);
+ let mut NP = ECP8::new();
+ NP.copy(&P);
+ NP.neg();
+
+ let nb=lbits(&mut n3,&mut n);
+
+ for i in (1..nb-1).rev() {
+ let mut lv=linedbl(&mut A,&qx,&qy);
+
+ let bt=n3.bit(i)-n.bit(i);
+ if bt==1 {
+ let lv2=lineadd(&mut A,&P,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ if bt==-1 {
+ let lv2=lineadd(&mut A,&NP,&qx,&qy);
+ lv.smul(&lv2);
+ }
+ r[i].ssmul(&lv);
+ }
}
#[allow(non_snake_case)]
/* Optimal R-ate pairing */
pub fn ate(P1: &ECP8, Q1: &ECP) -> FP48 {
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let n = BIG::new_copy(&x);
-
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut P = ECP8::new();
P.copy(P1);
@@ -158,21 +231,21 @@
NP.copy(&P);
NP.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
- lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &P, &qx, &qy);
+ lv.smul(&lv2);
}
if bt == -1 {
- lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut A, &NP, &qx, &qy);
+ lv.smul(&lv2);
}
+ r.ssmul(&lv);
}
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
@@ -185,12 +258,8 @@
#[allow(non_snake_case)]
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
pub fn ate2(P1: &ECP8, Q1: &ECP, R1: &ECP8, S1: &ECP) -> FP48 {
- let x = BIG::new_ints(&rom::CURVE_BNX);
- let n = BIG::new_copy(&x);
-
- let mut n3 = BIG::new_copy(&n);
- n3.pmul(3);
- n3.norm();
+ let mut n = BIG::new();
+ let mut n3 = BIG::new();
let mut P = ECP8::new();
P.copy(P1);
@@ -225,26 +294,26 @@
NR.copy(&R);
NR.neg();
- let nb = n3.nbits();
+ let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = linedbl(&mut B, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = linedbl(&mut B, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
lv = lineadd(&mut A, &P, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &R, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &R, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
if bt == -1 {
lv = lineadd(&mut A, &NP, &qx, &qy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
- lv = lineadd(&mut B, &NR, &sx, &sy);
- r.smul(&lv, ecp::SEXTIC_TWIST.into());
+ let lv2 = lineadd(&mut B, &NR, &sx, &sy);
+ lv.smul(&lv2);
+ r.ssmul(&lv);
}
}
diff --git a/version3/rust/src/roms/rom_anssi_32.rs b/version3/rust/src/roms/rom_anssi_32.rs
index c041396..403fb04 100644
--- a/version3/rust/src/roms/rom_anssi_32.rs
+++ b/version3/rust/src/roms/rom_anssi_32.rs
@@ -67,6 +67,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_anssi_64.rs b/version3/rust/src/roms/rom_anssi_64.rs
index c65e7f7..b0add0f 100644
--- a/version3/rust/src/roms/rom_anssi_64.rs
+++ b/version3/rust/src/roms/rom_anssi_64.rs
@@ -85,6 +85,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls24_32.rs b/version3/rust/src/roms/rom_bls24_32.rs
index 2f4c424..72afe58 100644
--- a/version3/rust/src/roms/rom_bls24_32.rs
+++ b/version3/rust/src/roms/rom_bls24_32.rs
@@ -234,6 +234,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 49;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_bls24_64.rs b/version3/rust/src/roms/rom_bls24_64.rs
index 8378e28..0c500da 100644
--- a/version3/rust/src/roms/rom_bls24_64.rs
+++ b/version3/rust/src/roms/rom_bls24_64.rs
@@ -282,6 +282,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 49;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_bls381_32.rs b/version3/rust/src/roms/rom_bls381_32.rs
index a6ca0fd..1ba0fe5 100644
--- a/version3/rust/src/roms/rom_bls381_32.rs
+++ b/version3/rust/src/roms/rom_bls381_32.rs
@@ -203,6 +203,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 65;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls381_64.rs b/version3/rust/src/roms/rom_bls381_64.rs
index 3c97727..08df12c 100644
--- a/version3/rust/src/roms/rom_bls381_64.rs
+++ b/version3/rust/src/roms/rom_bls381_64.rs
@@ -205,6 +205,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 65;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls383_32.rs b/version3/rust/src/roms/rom_bls383_32.rs
index 6c3453e..0ccb42d 100644
--- a/version3/rust/src/roms/rom_bls383_32.rs
+++ b/version3/rust/src/roms/rom_bls383_32.rs
@@ -201,6 +201,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 65;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls383_64.rs b/version3/rust/src/roms/rom_bls383_64.rs
index 88efdb1..71bef66 100644
--- a/version3/rust/src/roms/rom_bls383_64.rs
+++ b/version3/rust/src/roms/rom_bls383_64.rs
@@ -212,6 +212,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 65;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls461_32.rs b/version3/rust/src/roms/rom_bls461_32.rs
index 3490811..c452a9f 100644
--- a/version3/rust/src/roms/rom_bls461_32.rs
+++ b/version3/rust/src/roms/rom_bls461_32.rs
@@ -203,6 +203,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 78;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls461_64.rs b/version3/rust/src/roms/rom_bls461_64.rs
index 042b8dc..500ef04 100644
--- a/version3/rust/src/roms/rom_bls461_64.rs
+++ b/version3/rust/src/roms/rom_bls461_64.rs
@@ -226,6 +226,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 78;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bls48_32.rs b/version3/rust/src/roms/rom_bls48_32.rs
index ddb836c..83517a8 100644
--- a/version3/rust/src/roms/rom_bls48_32.rs
+++ b/version3/rust/src/roms/rom_bls48_32.rs
@@ -303,6 +303,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 32;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_bls48_64.rs b/version3/rust/src/roms/rom_bls48_64.rs
index d47d835..129c776 100644
--- a/version3/rust/src/roms/rom_bls48_64.rs
+++ b/version3/rust/src/roms/rom_bls48_64.rs
@@ -395,6 +395,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BLS;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 32;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_bn254CX_32.rs b/version3/rust/src/roms/rom_bn254CX_32.rs
index bb99a41..e1cff0d 100644
--- a/version3/rust/src/roms/rom_bn254CX_32.rs
+++ b/version3/rust/src/roms/rom_bn254CX_32.rs
@@ -177,6 +177,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::D_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bn254CX_64.rs b/version3/rust/src/roms/rom_bn254CX_64.rs
index efc622c..7f6d274 100644
--- a/version3/rust/src/roms/rom_bn254CX_64.rs
+++ b/version3/rust/src/roms/rom_bn254CX_64.rs
@@ -236,6 +236,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::D_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bn254_32.rs b/version3/rust/src/roms/rom_bn254_32.rs
index 2488208..c9ae5ec 100644
--- a/version3/rust/src/roms/rom_bn254_32.rs
+++ b/version3/rust/src/roms/rom_bn254_32.rs
@@ -165,6 +165,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::D_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_bn254_64.rs b/version3/rust/src/roms/rom_bn254_64.rs
index d33d631..f61b542 100644
--- a/version3/rust/src/roms/rom_bn254_64.rs
+++ b/version3/rust/src/roms/rom_bn254_64.rs
@@ -202,6 +202,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::D_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
\ No newline at end of file
diff --git a/version3/rust/src/roms/rom_brainpool_32.rs b/version3/rust/src/roms/rom_brainpool_32.rs
index f4d33db..b788632 100644
--- a/version3/rust/src/roms/rom_brainpool_32.rs
+++ b/version3/rust/src/roms/rom_brainpool_32.rs
@@ -68,6 +68,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_brainpool_64.rs b/version3/rust/src/roms/rom_brainpool_64.rs
index de754c0..8191561 100644
--- a/version3/rust/src/roms/rom_brainpool_64.rs
+++ b/version3/rust/src/roms/rom_brainpool_64.rs
@@ -87,5 +87,6 @@
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
+pub const ATE_BITS: usize = 0;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_c25519_32.rs b/version3/rust/src/roms/rom_c25519_32.rs
index f975cb4..6da6a05 100644
--- a/version3/rust/src/roms/rom_c25519_32.rs
+++ b/version3/rust/src/roms/rom_c25519_32.rs
@@ -53,6 +53,7 @@
pub const CURVETYPE: CurveType = CurveType::MONTGOMERY;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_c25519_64.rs b/version3/rust/src/roms/rom_c25519_64.rs
index 8954b0f..9a8c59f 100644
--- a/version3/rust/src/roms/rom_c25519_64.rs
+++ b/version3/rust/src/roms/rom_c25519_64.rs
@@ -55,6 +55,7 @@
pub const CURVETYPE: CurveType = CurveType::MONTGOMERY;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_c41417_32.rs b/version3/rust/src/roms/rom_c41417_32.rs
index 11e61db..a8330cb 100644
--- a/version3/rust/src/roms/rom_c41417_32.rs
+++ b/version3/rust/src/roms/rom_c41417_32.rs
@@ -65,6 +65,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_c41417_64.rs b/version3/rust/src/roms/rom_c41417_64.rs
index b61f883..52b51b1 100644
--- a/version3/rust/src/roms/rom_c41417_64.rs
+++ b/version3/rust/src/roms/rom_c41417_64.rs
@@ -72,6 +72,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_ed25519_32.rs b/version3/rust/src/roms/rom_ed25519_32.rs
index ceff788..be1d156 100644
--- a/version3/rust/src/roms/rom_ed25519_32.rs
+++ b/version3/rust/src/roms/rom_ed25519_32.rs
@@ -62,6 +62,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_ed25519_64.rs b/version3/rust/src/roms/rom_ed25519_64.rs
index b118e30..cf23672 100644
--- a/version3/rust/src/roms/rom_ed25519_64.rs
+++ b/version3/rust/src/roms/rom_ed25519_64.rs
@@ -73,6 +73,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_fp256bn_32.rs b/version3/rust/src/roms/rom_fp256bn_32.rs
index 6743b1b..e3cabe1 100644
--- a/version3/rust/src/roms/rom_fp256bn_32.rs
+++ b/version3/rust/src/roms/rom_fp256bn_32.rs
@@ -174,6 +174,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_fp256bn_64.rs b/version3/rust/src/roms/rom_fp256bn_64.rs
index c70465c..bde7639 100644
--- a/version3/rust/src/roms/rom_fp256bn_64.rs
+++ b/version3/rust/src/roms/rom_fp256bn_64.rs
@@ -227,6 +227,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 66;
pub const SIGN_OF_X: SignOfX = SignOfX::NEGATIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_fp512bn_32.rs b/version3/rust/src/roms/rom_fp512bn_32.rs
index 15246ef..cdc44af 100644
--- a/version3/rust/src/roms/rom_fp512bn_32.rs
+++ b/version3/rust/src/roms/rom_fp512bn_32.rs
@@ -243,6 +243,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 130;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_fp512bn_64.rs b/version3/rust/src/roms/rom_fp512bn_64.rs
index d291cd8..54d85c4 100644
--- a/version3/rust/src/roms/rom_fp512bn_64.rs
+++ b/version3/rust/src/roms/rom_fp512bn_64.rs
@@ -476,6 +476,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::BN;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::M_TYPE;
+pub const ATE_BITS: usize = 130;
pub const SIGN_OF_X: SignOfX = SignOfX::POSITIVEX;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_goldilocks_32.rs b/version3/rust/src/roms/rom_goldilocks_32.rs
index 7a8a71e..5d5f8bb 100644
--- a/version3/rust/src/roms/rom_goldilocks_32.rs
+++ b/version3/rust/src/roms/rom_goldilocks_32.rs
@@ -67,6 +67,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_goldilocks_64.rs b/version3/rust/src/roms/rom_goldilocks_64.rs
index 9ae100e..d6cadf1 100644
--- a/version3/rust/src/roms/rom_goldilocks_64.rs
+++ b/version3/rust/src/roms/rom_goldilocks_64.rs
@@ -93,6 +93,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_hifive_32.rs b/version3/rust/src/roms/rom_hifive_32.rs
index da119e3..cfa9f59 100644
--- a/version3/rust/src/roms/rom_hifive_32.rs
+++ b/version3/rust/src/roms/rom_hifive_32.rs
@@ -62,6 +62,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_hifive_64.rs b/version3/rust/src/roms/rom_hifive_64.rs
index 54b03bd..b2eebb9 100644
--- a/version3/rust/src/roms/rom_hifive_64.rs
+++ b/version3/rust/src/roms/rom_hifive_64.rs
@@ -71,6 +71,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nist256_32.rs b/version3/rust/src/roms/rom_nist256_32.rs
index 1900c3b..6859da5 100644
--- a/version3/rust/src/roms/rom_nist256_32.rs
+++ b/version3/rust/src/roms/rom_nist256_32.rs
@@ -68,6 +68,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nist256_64.rs b/version3/rust/src/roms/rom_nist256_64.rs
index 259eefb..015bbb3 100644
--- a/version3/rust/src/roms/rom_nist256_64.rs
+++ b/version3/rust/src/roms/rom_nist256_64.rs
@@ -80,6 +80,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nist384_32.rs b/version3/rust/src/roms/rom_nist384_32.rs
index 50a3976..48d7826 100644
--- a/version3/rust/src/roms/rom_nist384_32.rs
+++ b/version3/rust/src/roms/rom_nist384_32.rs
@@ -70,6 +70,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nist384_64.rs b/version3/rust/src/roms/rom_nist384_64.rs
index b8fe79a..f0f5c69 100644
--- a/version3/rust/src/roms/rom_nist384_64.rs
+++ b/version3/rust/src/roms/rom_nist384_64.rs
@@ -98,6 +98,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nist521_32.rs b/version3/rust/src/roms/rom_nist521_32.rs
index 1d37cbf..55cbf30 100644
--- a/version3/rust/src/roms/rom_nist521_32.rs
+++ b/version3/rust/src/roms/rom_nist521_32.rs
@@ -73,6 +73,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_nist521_64.rs b/version3/rust/src/roms/rom_nist521_64.rs
index f019d98..bf241b2 100644
--- a/version3/rust/src/roms/rom_nist521_64.rs
+++ b/version3/rust/src/roms/rom_nist521_64.rs
@@ -98,6 +98,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_nums256e_32.rs b/version3/rust/src/roms/rom_nums256e_32.rs
index fd994e5..45506bd 100644
--- a/version3/rust/src/roms/rom_nums256e_32.rs
+++ b/version3/rust/src/roms/rom_nums256e_32.rs
@@ -64,6 +64,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nums256e_64.rs b/version3/rust/src/roms/rom_nums256e_64.rs
index 4d4aa68..4382924 100644
--- a/version3/rust/src/roms/rom_nums256e_64.rs
+++ b/version3/rust/src/roms/rom_nums256e_64.rs
@@ -73,6 +73,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nums256w_32.rs b/version3/rust/src/roms/rom_nums256w_32.rs
index 9439232..b768380 100644
--- a/version3/rust/src/roms/rom_nums256w_32.rs
+++ b/version3/rust/src/roms/rom_nums256w_32.rs
@@ -60,6 +60,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nums256w_64.rs b/version3/rust/src/roms/rom_nums256w_64.rs
index 78fa6c5..5b5d491 100644
--- a/version3/rust/src/roms/rom_nums256w_64.rs
+++ b/version3/rust/src/roms/rom_nums256w_64.rs
@@ -72,6 +72,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_nums384e_32.rs b/version3/rust/src/roms/rom_nums384e_32.rs
index 05fd563..eaad1c8 100644
--- a/version3/rust/src/roms/rom_nums384e_32.rs
+++ b/version3/rust/src/roms/rom_nums384e_32.rs
@@ -67,6 +67,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nums384e_64.rs b/version3/rust/src/roms/rom_nums384e_64.rs
index 535026d..08d83c2 100644
--- a/version3/rust/src/roms/rom_nums384e_64.rs
+++ b/version3/rust/src/roms/rom_nums384e_64.rs
@@ -88,6 +88,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nums384w_32.rs b/version3/rust/src/roms/rom_nums384w_32.rs
index c733516..92181a6 100644
--- a/version3/rust/src/roms/rom_nums384w_32.rs
+++ b/version3/rust/src/roms/rom_nums384w_32.rs
@@ -67,6 +67,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nums384w_64.rs b/version3/rust/src/roms/rom_nums384w_64.rs
index 532cdc5..3f51d94 100644
--- a/version3/rust/src/roms/rom_nums384w_64.rs
+++ b/version3/rust/src/roms/rom_nums384w_64.rs
@@ -87,6 +87,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 48;
pub const AESKEY: usize = 24;
diff --git a/version3/rust/src/roms/rom_nums512e_32.rs b/version3/rust/src/roms/rom_nums512e_32.rs
index 897b27b..8d53f9f 100644
--- a/version3/rust/src/roms/rom_nums512e_32.rs
+++ b/version3/rust/src/roms/rom_nums512e_32.rs
@@ -73,6 +73,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_nums512e_64.rs b/version3/rust/src/roms/rom_nums512e_64.rs
index 4c11a9f..298f3cc 100644
--- a/version3/rust/src/roms/rom_nums512e_64.rs
+++ b/version3/rust/src/roms/rom_nums512e_64.rs
@@ -98,6 +98,7 @@
pub const CURVETYPE: CurveType = CurveType::EDWARDS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_nums512w_32.rs b/version3/rust/src/roms/rom_nums512w_32.rs
index df06a06..785070c 100644
--- a/version3/rust/src/roms/rom_nums512w_32.rs
+++ b/version3/rust/src/roms/rom_nums512w_32.rs
@@ -71,6 +71,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_nums512w_64.rs b/version3/rust/src/roms/rom_nums512w_64.rs
index e666a88..6868c87 100644
--- a/version3/rust/src/roms/rom_nums512w_64.rs
+++ b/version3/rust/src/roms/rom_nums512w_64.rs
@@ -88,6 +88,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 64;
pub const AESKEY: usize = 32;
diff --git a/version3/rust/src/roms/rom_secp256k1_32.rs b/version3/rust/src/roms/rom_secp256k1_32.rs
index 15184a9..94bbbaa 100644
--- a/version3/rust/src/roms/rom_secp256k1_32.rs
+++ b/version3/rust/src/roms/rom_secp256k1_32.rs
@@ -64,6 +64,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/roms/rom_secp256k1_64.rs b/version3/rust/src/roms/rom_secp256k1_64.rs
index d9746ec..b22d875 100644
--- a/version3/rust/src/roms/rom_secp256k1_64.rs
+++ b/version3/rust/src/roms/rom_secp256k1_64.rs
@@ -75,6 +75,7 @@
pub const CURVETYPE: CurveType = CurveType::WEIERSTRASS;
pub const CURVE_PAIRING_TYPE: CurvePairingType = CurvePairingType::NOT;
pub const SEXTIC_TWIST: SexticTwist = SexticTwist::NOT;
+pub const ATE_BITS: usize = 0;
pub const SIGN_OF_X: SignOfX = SignOfX::NOT;
pub const HASH_TYPE: usize = 32;
pub const AESKEY: usize = 16;
diff --git a/version3/rust/src/types.rs b/version3/rust/src/types.rs
index be66c92..ea310d7 100644
--- a/version3/rust/src/types.rs
+++ b/version3/rust/src/types.rs
@@ -41,4 +41,5 @@
NOT,
POSITIVEX,
NEGATIVEX,
-}
\ No newline at end of file
+}
+
diff --git a/version3/swift/bls.swift b/version3/swift/bls.swift
index 6ebba98..cac62a6 100644
--- a/version3/swift/bls.swift
+++ b/version3/swift/bls.swift
@@ -82,7 +82,16 @@
let G=ECP2.generator()
let PK=ECP2.fromBytes(W)
D.neg()
- var v=PAIR.ate2(G,D,PK,HM)
+
+// Use new multi-pairing mechanism
+ var r=PAIR.initmp()
+ PAIR.another(&r,G,D)
+ PAIR.another(&r,PK,HM)
+ var v=PAIR.miller(r)
+
+//.. or alternatively
+// var v=PAIR.ate2(G,D,PK,HM)
+
v=PAIR.fexp(v)
if v.isunity() {
diff --git a/version3/swift/bls192.swift b/version3/swift/bls192.swift
index 950c8c0..54a31cd 100644
--- a/version3/swift/bls192.swift
+++ b/version3/swift/bls192.swift
@@ -82,7 +82,17 @@
let G=ECP4.generator()
let PK=ECP4.fromBytes(W)
D.neg()
- var v=PAIR192.ate2(G,D,PK,HM)
+
+
+// Use new multi-pairing mechanism
+ var r=PAIR192.initmp()
+ PAIR192.another(&r,G,D)
+ PAIR192.another(&r,PK,HM)
+ var v=PAIR192.miller(r)
+
+//.. or alternatively
+// var v=PAIR192.ate2(G,D,PK,HM)
+
v=PAIR192.fexp(v)
if v.isunity() {
diff --git a/version3/swift/bls256.swift b/version3/swift/bls256.swift
index f60470e..07fd817 100644
--- a/version3/swift/bls256.swift
+++ b/version3/swift/bls256.swift
@@ -82,7 +82,16 @@
let G=ECP8.generator()
let PK=ECP8.fromBytes(W)
D.neg()
- var v=PAIR256.ate2(G,D,PK,HM)
+
+// Use new multi-pairing mechanism
+ var r=PAIR256.initmp()
+ PAIR256.another(&r,G,D)
+ PAIR256.another(&r,PK,HM)
+ var v=PAIR256.miller(r)
+
+//.. or alternatively
+// var v=PAIR256.ate2(G,D,PK,HM)
+
v=PAIR256.fexp(v)
if v.isunity() {
diff --git a/version3/swift/config32.py b/version3/swift/config32.py
index 9eaa7cf..9b69e35 100644
--- a/version3/swift/config32.py
+++ b/version3/swift/config32.py
@@ -56,7 +56,7 @@
os.system("rmdir amcl"+slashtext+tb)
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -97,6 +97,7 @@
replace(fpath+"config_curve.swift","@ST@",stw)
replace(fpath+"config_curve.swift","@SX@",sx)
+ replace(fpath+"config_curve.swift","@AB@",ab)
if cs == "128" :
replace(fpath+"config_curve.swift","@HT@","32")
@@ -225,93 +226,93 @@
if x==1:
- curveset("ed25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ed25519","32","29","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("c25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("c25519","32","29","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("nist256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("nist256","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==4:
- curveset("brainpool","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("brainpool","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==5:
- curveset("anssi","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("anssi","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==6:
- curveset("hifive","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("hifive","42","29","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("goldilocks","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("goldilocks","56","29","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==8:
- curveset("nist384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("nist384","48","29","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==9:
- curveset("c41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("c41417","52","29","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("nist521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("nist521","66","28","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("nums256w","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("nums256w","32","28","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("nums256e","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("nums256e","32","29","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("nums384w","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("nums384w","48","29","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("nums384e","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("nums384e","48","29","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("nums512w","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("nums512w","64","29","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("nums512e","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("nums512e","64","29","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("secp256k1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("secp256k1","32","28","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==18:
- curveset("bn254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("bn254","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("bn254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("bn254CX","32","28","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("bls383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("bls383","48","29","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("bls381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("bls381","48","29","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("fp256bn","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("fp256bn","32","28","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("fp512bn","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("fp512bn","64","29","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("bls461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("bls461","58","28","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("bls24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("bls24","60","29","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("bls48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("bls48","70","29","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
diff --git a/version3/swift/config64.py b/version3/swift/config64.py
index 133726f..9a17880 100644
--- a/version3/swift/config64.py
+++ b/version3/swift/config64.py
@@ -57,7 +57,7 @@
os.system("rmdir amcl"+slashtext+tb)
-def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,cs) :
+def curveset(tc,nb,base,nbt,m8,mt,ct,pf,stw,sx,ab,cs) :
global deltext,slashtext,copytext
global cptr,chosen
@@ -97,6 +97,7 @@
replace(fpath+"config_curve.swift","@ST@",stw)
replace(fpath+"config_curve.swift","@SX@",sx)
+ replace(fpath+"config_curve.swift","@AB@",ab)
if cs == "128" :
replace(fpath+"config_curve.swift","@HT@","32")
@@ -225,92 +226,92 @@
if x==1:
- curveset("ed25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("ed25519","32","56","255","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==2:
- curveset("c25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","128")
+ curveset("c25519","32","56","255","5","PSEUDO_MERSENNE","MONTGOMERY","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==3:
- curveset("nist256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("nist256","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==4:
- curveset("brainpool","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("brainpool","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==5:
- curveset("anssi","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("anssi","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==6:
- curveset("hifive","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("hifive","42","60","336","5","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==7:
- curveset("goldilocks","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("goldilocks","56","58","448","7","GENERALISED_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==8:
- curveset("nist384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("nist384","48","56","384","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==9:
- curveset("c41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("c41417","52","60","414","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==10:
- curveset("nist521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("nist521","66","60","521","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==11:
- curveset("nums256w","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("nums256w","32","56","256","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==12:
- curveset("nums256e","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","128")
+ curveset("nums256e","32","56","256","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==13:
- curveset("nums384w","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","192")
+ curveset("nums384w","48","58","384","3","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==14:
- curveset("nums384e","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","192")
+ curveset("nums384e","48","56","384","3","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","192")
curve_selected=True
if x==15:
- curveset("nums512w","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","256")
+ curveset("nums512w","64","60","512","7","PSEUDO_MERSENNE","WEIERSTRASS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==16:
- curveset("nums512e","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","256")
+ curveset("nums512e","64","60","512","7","PSEUDO_MERSENNE","EDWARDS","NOT","NOT","NOT","NOT","256")
curve_selected=True
if x==17:
- curveset("secp256k1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","128")
+ curveset("secp256k1","32","56","256","7","NOT_SPECIAL","WEIERSTRASS","NOT","NOT","NOT","NOT","128")
curve_selected=True
if x==18:
- curveset("bn254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("bn254","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==19:
- curveset("bn254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","128")
+ curveset("bn254CX","32","56","254","3","NOT_SPECIAL","WEIERSTRASS","BN","D_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==20:
- curveset("bls383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","128")
+ curveset("bls383","48","58","383","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","65","128")
pfcurve_selected=True
if x==21:
- curveset("bls381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("bls381","48","58","381","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","65","128")
pfcurve_selected=True
if x==22:
- curveset("fp256bn","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","128")
+ curveset("fp256bn","32","56","256","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","NEGATIVEX","66","128")
pfcurve_selected=True
if x==23:
- curveset("fp512bn","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","128")
+ curveset("fp512bn","64","60","512","3","NOT_SPECIAL","WEIERSTRASS","BN","M_TYPE","POSITIVEX","130","128")
pfcurve_selected=True
# https://eprint.iacr.org/2017/334.pdf
if x==24:
- curveset("bls461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","128")
+ curveset("bls461","58","60","461","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","NEGATIVEX","78","128")
pfcurve_selected=True
if x==25:
- curveset("bls24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","192")
+ curveset("bls24","60","56","479","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","49","192")
pfcurve_selected=True
if x==26:
- curveset("bls48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","256")
+ curveset("bls48","70","58","556","3","NOT_SPECIAL","WEIERSTRASS","BLS","M_TYPE","POSITIVEX","32","256")
pfcurve_selected=True
# rsaset(rsaname,big_length_bytes,bits_in_base,multiplier)
diff --git a/version3/swift/config_curve.swift b/version3/swift/config_curve.swift
index f5da8e2..66c64da 100644
--- a/version3/swift/config_curve.swift
+++ b/version3/swift/config_curve.swift
@@ -14,6 +14,7 @@
static public let CURVE_PAIRING_TYPE = @PF@
static public let SEXTIC_TWIST = @ST@
static public let SIGN_OF_X = @SX@
+ static public let ATE_BITS = @AB@
static public let HASH_TYPE = @HT@
static public let AESKEY = @AK@
diff --git a/version3/swift/fp12.swift b/version3/swift/fp12.swift
index 5733402..88a24ed 100644
--- a/version3/swift/fp12.swift
+++ b/version3/swift/fp12.swift
@@ -29,9 +29,16 @@
public struct FP12
{
+ static public let ZERO:Int=0
+ static public let ONE:Int=1
+ static public let SPARSER:Int=2
+ static public let SPARSE:Int=3
+ static public let DENSE:Int=4
+
private var a:FP4
private var b:FP4
private var c:FP4
+ private var stype:Int
/* reduce all components of this mod Modulus */
mutating func reduce()
@@ -43,16 +50,28 @@
/* normalise all components of this */
mutating func norm()
{
- a.norm();
- b.norm();
- c.norm();
+ a.norm()
+ b.norm()
+ c.norm()
}
+
+ mutating func settype(_ t:Int)
+ {
+ stype=t
+ }
+
+ mutating func gettype() -> Int
+ {
+ return stype
+ }
+
/* Constructors */
init(_ d:FP4)
{
a=FP4(d)
b=FP4(0)
c=FP4(0)
+ stype=FP12.SPARSER
}
init(_ d:Int)
@@ -60,6 +79,8 @@
a=FP4(d)
b=FP4(0)
c=FP4(0)
+ if (d==1) {stype=FP12.ONE}
+ else {stype=FP12.SPARSER}
}
init(_ d:FP4,_ e:FP4,_ f:FP4)
@@ -67,6 +88,7 @@
a=FP4(d)
b=FP4(e)
c=FP4(f)
+ stype=FP12.DENSE
}
init(_ x:FP12)
@@ -74,6 +96,7 @@
a=FP4(x.a)
b=FP4(x.b)
c=FP4(x.c)
+ stype=x.stype
}
/* test x==0 ? */
func iszilch() -> Bool
@@ -86,6 +109,8 @@
a.cmove(g.a,d)
b.cmove(g.b,d)
c.cmove(g.c,d)
+ let u = ~(d-1)
+ stype^=(stype^g.stype)&u
}
/* return 1 if b==c, no branching */
@@ -150,6 +175,7 @@
a.copy(x.a)
b.copy(x.b)
c.copy(x.c)
+ stype=x.stype
}
/* set self=1 */
mutating func one()
@@ -157,6 +183,7 @@
a.one()
b.zero()
c.zero()
+ stype=FP12.ONE
}
/* self=conj(self) */
mutating func conj()
@@ -201,12 +228,14 @@
c.add(c)
b.add(B)
c.add(C)
+ stype=FP12.DENSE
reduce()
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
mutating func sqr()
{
+ if (stype==FP12.ONE) {return}
var A=FP4(a)
var B=FP4(b)
var C=FP4(c)
@@ -239,7 +268,11 @@
b.copy(C); b.add(D)
c.add(A)
-
+ if (stype==FP12.SPARSER) {
+ stype=FP12.SPARSE
+ } else {
+ stype=FP12.DENSE
+ }
norm()
}
@@ -298,88 +331,106 @@
z3.norm()
z3.times_i()
a.copy(z0); a.add(z3)
-
+ stype=FP12.DENSE
norm()
}
- /* Special case of multiplication arises from special form of ATE pairing line function */
- mutating func smul(_ y:FP12,_ twist:Int)
+/* FP12 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ mutating func ssmul(_ y:FP12)
{
- if twist == CONFIG_CURVE.D_TYPE {
- var z0=FP4(a)
- var z2=FP4(b)
- var z3=FP4(b)
- var t0=FP4(0)
- var t1=FP4(y.a)
-
- z0.mul(y.a)
- z2.pmul(y.b.real())
- b.add(a)
- t1.adds(y.b.real())
-
- b.norm(); t1.norm()
-
- b.mul(t1)
- z3.add(c); z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0); t0.neg()
- t1.copy(z2); t1.neg()
-
- b.add(t0)
-
- b.add(t1)
- z3.add(t1)
- z2.add(t0)
-
- t0.copy(a); t0.add(c)
- t0.norm(); z3.norm()
- t0.mul(y.a)
- c.copy(z2); c.add(t0)
-
- z3.times_i()
- a.copy(z0); a.add(z3)
+ if stype==FP12.ONE {
+ copy(y)
+ return
}
- if twist == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP12.ONE {
+ return
+ }
+ if y.stype>=FP12.SPARSE {
var z0=FP4(a)
var z1=FP4(0)
var z2=FP4(0)
var z3=FP4(0)
- var t0=FP4(a)
- var t1=FP4(0)
-
z0.mul(y.a)
- t0.add(b)
- t0.norm()
- z1.copy(t0); z1.mul(y.a)
- t0.copy(b); t0.add(c)
- t0.norm()
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP12.SPARSE || stype==FP12.SPARSE {
+ var ga=FP2(0)
+ var gb=FP2(0)
- z3.copy(t0)
- z3.pmul(y.c.getb())
- z3.times_i()
+ gb.copy(b.getb())
+ gb.mul(y.b.getb())
+ ga.zero()
+ if y.stype != FP12.SPARSE {
+ ga.copy(b.getb())
+ ga.mul(y.b.geta())
+ }
+ if stype != FP12.SPARSE {
+ ga.copy(b.geta())
+ ga.mul(y.b.getb())
+ }
+ z2.set_fp2s(ga,gb)
+ z2.times_i()
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ var t0=FP4(a)
+ var t1=FP4(y.a)
+ t0.add(b); t0.norm()
+ t1.add(y.b); t1.norm()
+
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(b); t0.add(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)
- b.copy(z1)
- z2.copy(t0)
+ b.copy(z1); b.add(t1)
- t0.copy(a); t0.add(c)
- t1.copy(y.a); t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
t0.mul(t1)
z2.add(t0)
- t0.copy(c)
-
- t0.pmul(y.c.getb())
- t0.times_i()
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ if y.stype==FP12.SPARSE || stype==FP12.SPARSE {
+ var ga=FP2(0)
+ var gb=FP2(0)
+ ga.copy(c.geta())
+ ga.mul(y.c.geta())
+ gb.zero()
+ if y.stype != FP12.SPARSE {
+ gb.copy(c.geta())
+ gb.mul(y.c.getb())
+ }
+ if stype != FP12.SPARSE {
+ gb.copy(c.getb())
+ gb.mul(y.c.geta())
+ }
+ t0.set_fp2s(ga,gb)
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
t1.copy(t0); t1.neg()
c.copy(z2); c.add(t1)
@@ -388,9 +439,200 @@
b.add(t0)
z3.norm()
z3.times_i()
- a.copy(z0); a.add(z3)
+ a.copy(z0); a.add(z3);
+ } else {
+ if stype==FP12.SPARSER {
+ smul(y)
+ return
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE { // dense by sparser - 13m
+ var z0=FP4(a)
+ var z2=FP4(b)
+ var z3=FP4(b)
+ var t0=FP4(0)
+ var t1=FP4(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ b.add(a)
+ t1.adds(y.b.real())
+
+ t1.norm()
+ b.norm()
+ b.mul(t1)
+ z3.add(c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ b.add(t0)
+
+ b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ c.copy(z2); c.add(t0)
+
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ var z0=FP4(a)
+ var z1=FP4(0)
+ var z2=FP4(0)
+ var z3=FP4(0)
+ var t0=FP4(a)
+ var t1=FP4(0)
+
+ z0.mul(y.a)
+ t0.add(b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(b); t0.add(c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ c.copy(z2); c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ b.add(t0)
+ z3.norm()
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
}
- norm()
+ stype=FP12.DENSE
+ norm()
+ }
+
+ /* Special case of multiplication arises from special form of ATE pairing line function */
+ mutating func smul(_ y:FP12)
+ {
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ var w1=FP2(a.geta())
+ var w2=FP2(a.getb())
+ var w3=FP2(b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ var ta=FP2(a.geta())
+ var tb=FP2(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP2(ta)
+ tc.mul(tb)
+ var t=FP2(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ var td=FP2(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ var te=FP2(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.mul_ip()
+ w1.add(w2)
+
+ a.set_fp2s(w1,tc)
+ b.set_fp2s(td,te)
+ c.set_fp2(w3)
+
+ a.norm()
+ b.norm()
+ } else {
+ var w1=FP2(a.geta())
+ var w2=FP2(a.getb())
+ var w3=FP2(c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ var ta=FP2(a.geta())
+ var tb=FP2(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP2(ta)
+ tc.mul(tb)
+ var t=FP2(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ var td=FP2(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ var te=FP2(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.mul_ip()
+ w1.add(w2)
+ a.set_fp2s(w1,tc);
+
+ w3.mul_ip()
+ w3.norm()
+ b.set_fp2h(w3);
+
+ te.norm()
+ te.mul_ip()
+ c.set_fp2s(te,td)
+
+ a.norm()
+ c.norm()
+
+ }
+ stype=FP12.SPARSE
}
/* self=1/self */
mutating func inverse()
@@ -427,6 +669,7 @@
a.copy(f0); a.mul(f3)
b.copy(f1); b.mul(f3)
c.copy(f2); c.mul(f3)
+ stype=FP12.DENSE
}
/* self=self^p using Frobenius */
@@ -444,6 +687,7 @@
b.pmul(f)
c.pmul(f2)
+ stype=FP12.DENSE
}
/* trace function */
diff --git a/version3/swift/fp16.swift b/version3/swift/fp16.swift
index 766ee55..196f7c5 100644
--- a/version3/swift/fp16.swift
+++ b/version3/swift/fp16.swift
@@ -108,7 +108,21 @@
{
return b;
}
-
+ mutating func set_fp8s(_ c: FP8,_ d: FP8)
+ {
+ a.copy(c)
+ b.copy(d)
+ }
+ mutating func set_fp8(_ c: FP8)
+ {
+ a.copy(c)
+ b.zero()
+ }
+ mutating func set_fp8h(_ c: FP8)
+ {
+ b.copy(c)
+ a.zero()
+ }
/* test self=x? */
func equals(_ x:FP16) -> Bool
{
diff --git a/version3/swift/fp24.swift b/version3/swift/fp24.swift
index 735c508..f780cf2 100644
--- a/version3/swift/fp24.swift
+++ b/version3/swift/fp24.swift
@@ -29,9 +29,16 @@
public struct FP24
{
+ static public let ZERO:Int=0
+ static public let ONE:Int=1
+ static public let SPARSER:Int=2
+ static public let SPARSE:Int=3
+ static public let DENSE:Int=4
+
private var a:FP8
private var b:FP8
private var c:FP8
+ private var stype:Int
/* reduce all components of this mod Modulus */
mutating func reduce()
@@ -47,12 +54,24 @@
b.norm();
c.norm();
}
+
+ mutating func settype(_ t:Int)
+ {
+ stype=t
+ }
+
+ mutating func gettype() -> Int
+ {
+ return stype
+ }
+
/* Constructors */
init(_ d:FP8)
{
a=FP8(d)
b=FP8(0)
c=FP8(0)
+ stype=FP24.SPARSER
}
init(_ d:Int)
@@ -60,6 +79,8 @@
a=FP8(d)
b=FP8(0)
c=FP8(0)
+ if (d==1) {stype=FP24.ONE}
+ else {stype=FP24.SPARSER}
}
init(_ d:FP8,_ e:FP8,_ f:FP8)
@@ -67,6 +88,7 @@
a=FP8(d)
b=FP8(e)
c=FP8(f)
+ stype=FP24.DENSE
}
init(_ x:FP24)
@@ -74,6 +96,7 @@
a=FP8(x.a)
b=FP8(x.b)
c=FP8(x.c)
+ stype=x.stype
}
/* test x==0 ? */
func iszilch() -> Bool
@@ -86,6 +109,8 @@
a.cmove(g.a,d)
b.cmove(g.b,d)
c.cmove(g.c,d)
+ let u = ~(d-1)
+ stype^=(stype^g.stype)&u
}
/* return 1 if b==c, no branching */
@@ -150,6 +175,7 @@
a.copy(x.a)
b.copy(x.b)
c.copy(x.c)
+ stype=x.stype
}
/* set self=1 */
mutating func one()
@@ -157,6 +183,7 @@
a.one()
b.zero()
c.zero()
+ stype=FP24.ONE
}
/* self=conj(self) */
mutating func conj()
@@ -202,6 +229,7 @@
c.add(c)
b.add(B)
c.add(C)
+ stype=FP24.DENSE
reduce()
}
@@ -209,6 +237,7 @@
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
mutating func sqr()
{
+ if (stype==FP24.ONE) {return}
var A=FP8(a)
var B=FP8(b)
var C=FP8(c)
@@ -241,7 +270,11 @@
b.copy(C); b.add(D)
c.add(A)
-
+ if (stype==FP24.SPARSER) {
+ stype=FP24.SPARSE
+ } else {
+ stype=FP24.DENSE
+ }
norm()
}
@@ -300,99 +333,308 @@
z3.norm()
z3.times_i()
a.copy(z0); a.add(z3)
-
+ stype=FP24.DENSE
norm()
}
- /* Special case of multiplication arises from special form of ATE pairing line function */
- mutating func smul(_ y:FP24,_ twist:Int)
+/* FP24 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ mutating func ssmul(_ y:FP24)
{
- if twist == CONFIG_CURVE.D_TYPE {
- var z0=FP8(a)
- var z2=FP8(b)
- var z3=FP8(b)
- var t0=FP8(0)
- var t1=FP8(y.a)
-
- z0.mul(y.a)
- z2.pmul(y.b.real())
- b.add(a)
- t1.adds(y.b.real())
-
- b.norm(); t1.norm()
-
- b.mul(t1)
- z3.add(c); z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0); t0.neg()
- t1.copy(z2); t1.neg()
-
- b.add(t0)
-
- b.add(t1)
- z3.add(t1)
- z2.add(t0)
-
- t0.copy(a); t0.add(c)
- t0.norm(); z3.norm()
- t0.mul(y.a)
- c.copy(z2); c.add(t0)
-
- z3.times_i()
- a.copy(z0); a.add(z3)
+ if stype==FP24.ONE {
+ copy(y)
+ return
}
- if twist == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP24.ONE {
+ return
+ }
+ if y.stype>=FP24.SPARSE {
var z0=FP8(a)
var z1=FP8(0)
var z2=FP8(0)
var z3=FP8(0)
- var t0=FP8(a)
- var t1=FP8(0)
-
z0.mul(y.a)
- t0.add(b)
- t0.norm()
- z1.copy(t0); z1.mul(y.a)
- t0.copy(b); t0.add(c)
- t0.norm();
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP24.SPARSE || stype==FP24.SPARSE {
+ var ga=FP4(0)
+ var gb=FP4(0)
- z3.copy(t0); //z3.mul(y.c);
- z3.pmul(y.c.getb())
- z3.times_i()
+ gb.copy(b.getb())
+ gb.mul(y.b.getb())
+ ga.zero()
+ if y.stype != FP24.SPARSE {
+ ga.copy(b.getb())
+ ga.mul(y.b.geta())
+ }
+ if stype != FP24.SPARSE {
+ ga.copy(b.geta())
+ ga.mul(y.b.getb())
+ }
+ z2.set_fp4s(ga,gb)
+ z2.times_i()
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ var t0=FP8(a)
+ var t1=FP8(y.a)
+ t0.add(b); t0.norm()
+ t1.add(y.b); t1.norm()
+
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(b); t0.add(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)
- b.copy(z1);
- z2.copy(t0)
+ b.copy(z1); b.add(t1)
- t0.copy(a); t0.add(c)
- t1.copy(y.a); t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
t0.mul(t1)
z2.add(t0)
- t0.copy(c)
-
- t0.pmul(y.c.getb())
- t0.times_i()
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ if y.stype==FP24.SPARSE || stype==FP24.SPARSE {
+ var ga=FP4(0)
+ var gb=FP4(0)
+ ga.copy(c.geta())
+ ga.mul(y.c.geta())
+ gb.zero()
+ if y.stype != FP24.SPARSE {
+ gb.copy(c.geta())
+ gb.mul(y.c.getb())
+ }
+ if stype != FP24.SPARSE {
+ gb.copy(c.getb())
+ gb.mul(y.c.geta())
+ }
+ t0.set_fp4s(ga,gb)
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
t1.copy(t0); t1.neg()
c.copy(z2); c.add(t1)
z3.add(t1)
t0.times_i()
b.add(t0)
- z3.norm();
+ z3.norm()
z3.times_i()
- a.copy(z0); a.add(z3)
+ a.copy(z0); a.add(z3);
+ } else {
+ if stype==FP24.SPARSER {
+ smul(y)
+ return
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE { // dense by sparser - 13m
+ var z0=FP8(a)
+ var z2=FP8(b)
+ var z3=FP8(b)
+ var t0=FP8(0)
+ var t1=FP8(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ b.add(a)
+ t1.adds(y.b.real())
+
+ t1.norm()
+ b.norm()
+ b.mul(t1)
+ z3.add(c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ b.add(t0)
+
+ b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ c.copy(z2); c.add(t0)
+
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ var z0=FP8(a)
+ var z1=FP8(0)
+ var z2=FP8(0)
+ var z3=FP8(0)
+ var t0=FP8(a)
+ var t1=FP8(0)
+
+ z0.mul(y.a)
+ t0.add(b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(b); t0.add(c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ c.copy(z2); c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ b.add(t0)
+ z3.norm()
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
}
- norm()
+ stype=FP24.DENSE
+ norm()
+ }
+
+ /* Special case of multiplication arises from special form of ATE pairing line function */
+ mutating func smul(_ y:FP24)
+ {
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ var w1=FP4(a.geta())
+ var w2=FP4(a.getb())
+ var w3=FP4(b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ var ta=FP4(a.geta())
+ var tb=FP4(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP4(ta)
+ tc.mul(tb)
+ var t=FP4(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ var td=FP4(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ var te=FP4(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+
+ a.set_fp4s(w1,tc)
+ b.set_fp4s(td,te)
+ c.set_fp4(w3)
+
+ a.norm()
+ b.norm()
+ } else {
+ var w1=FP4(a.geta())
+ var w2=FP4(a.getb())
+ var w3=FP4(c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ var ta=FP4(a.geta())
+ var tb=FP4(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP4(ta)
+ tc.mul(tb)
+ var t=FP4(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ var td=FP4(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ var te=FP4(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+ a.set_fp4s(w1,tc);
+
+ w3.times_i()
+ w3.norm()
+ b.set_fp4h(w3);
+
+ te.norm()
+ te.times_i()
+ c.set_fp4s(te,td)
+
+ a.norm()
+ c.norm()
+
+ }
+ stype=FP24.SPARSE
}
/* self=1/self */
@@ -430,6 +672,7 @@
a.copy(f0); a.mul(f3)
b.copy(f1); b.mul(f3)
c.copy(f2); c.mul(f3)
+ stype=FP24.DENSE
}
/* self=self^p using Frobenius */
@@ -451,7 +694,7 @@
b.qmul(f); b.times_i2()
c.qmul(f2); c.times_i2(); c.times_i2()
}
-
+ stype=FP24.DENSE
}
/* trace function */
diff --git a/version3/swift/fp4.swift b/version3/swift/fp4.swift
index bbfd02b..90132a6 100644
--- a/version3/swift/fp4.swift
+++ b/version3/swift/fp4.swift
@@ -112,6 +112,21 @@
{
return a.equals(x.a) && b.equals(x.b)
}
+ mutating func set_fp2s(_ c: FP2,_ d: FP2)
+ {
+ a.copy(c)
+ b.copy(d)
+ }
+ mutating func set_fp2(_ c: FP2)
+ {
+ a.copy(c)
+ b.zero()
+ }
+ mutating func set_fp2h(_ c: FP2)
+ {
+ b.copy(c)
+ a.zero()
+ }
/* copy self=x */
mutating func copy(_ x:FP4)
{
diff --git a/version3/swift/fp48.swift b/version3/swift/fp48.swift
index 2620388..4ac17de 100644
--- a/version3/swift/fp48.swift
+++ b/version3/swift/fp48.swift
@@ -29,9 +29,16 @@
public struct FP48
{
+ static public let ZERO:Int=0
+ static public let ONE:Int=1
+ static public let SPARSER:Int=2
+ static public let SPARSE:Int=3
+ static public let DENSE:Int=4
+
private var a:FP16
private var b:FP16
private var c:FP16
+ private var stype:Int
/* reduce all components of this mod Modulus */
mutating func reduce()
@@ -47,12 +54,24 @@
b.norm();
c.norm();
}
+
+ mutating func settype(_ t:Int)
+ {
+ stype=t
+ }
+
+ mutating func gettype() -> Int
+ {
+ return stype
+ }
+
/* Constructors */
init(_ d:FP16)
{
a=FP16(d)
b=FP16(0)
c=FP16(0)
+ stype=FP48.SPARSER
}
init(_ d:Int)
@@ -60,6 +79,8 @@
a=FP16(d)
b=FP16(0)
c=FP16(0)
+ if (d==1) {stype=FP48.ONE}
+ else {stype=FP48.SPARSER}
}
init(_ d:FP16,_ e:FP16,_ f:FP16)
@@ -67,6 +88,7 @@
a=FP16(d)
b=FP16(e)
c=FP16(f)
+ stype=FP48.DENSE
}
init(_ x:FP48)
@@ -74,6 +96,7 @@
a=FP16(x.a)
b=FP16(x.b)
c=FP16(x.c)
+ stype=x.stype
}
/* test x==0 ? */
func iszilch() -> Bool
@@ -86,6 +109,8 @@
a.cmove(g.a,d)
b.cmove(g.b,d)
c.cmove(g.c,d)
+ let u = ~(d-1)
+ stype^=(stype^g.stype)&u
}
/* return 1 if b==c, no branching */
@@ -151,6 +176,7 @@
a.copy(x.a)
b.copy(x.b)
c.copy(x.c)
+ stype=x.stype
}
/* set self=1 */
mutating func one()
@@ -158,6 +184,7 @@
a.one()
b.zero()
c.zero()
+ stype=FP48.ONE
}
/* self=conj(self) */
mutating func conj()
@@ -203,13 +230,14 @@
c.add(c)
b.add(B)
c.add(C)
+ stype=FP48.DENSE
reduce()
-
}
/* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
mutating func sqr()
{
+ if (stype==FP48.ONE) {return}
var A=FP16(a)
var B=FP16(b)
var C=FP16(c)
@@ -242,7 +270,11 @@
b.copy(C); b.add(D)
c.add(A)
-
+ if (stype==FP48.SPARSER) {
+ stype=FP48.SPARSE
+ } else {
+ stype=FP48.DENSE
+ }
norm()
}
@@ -301,100 +333,311 @@
z3.norm()
z3.times_i()
a.copy(z0); a.add(z3)
-
+ stype=FP48.DENSE
norm()
}
- /* Special case of multiplication arises from special form of ATE pairing line function */
- mutating func smul(_ y:FP48,_ twist:Int)
+/* FP48 full multiplication w=w*y */
+/* Supports sparse multiplicands */
+/* Usually w is denser than y */
+ mutating func ssmul(_ y:FP48)
{
- if twist == CONFIG_CURVE.D_TYPE {
- var z0=FP16(a)
- var z2=FP16(b)
- var z3=FP16(b)
- var t0=FP16(0)
- var t1=FP16(y.a)
-
- z0.mul(y.a)
- z2.pmul(y.b.real())
- b.add(a)
- t1.adds(y.b.real())
-
- b.norm(); t1.norm()
-
- b.mul(t1)
- z3.add(c); z3.norm()
- z3.pmul(y.b.real())
-
- t0.copy(z0); t0.neg()
- t1.copy(z2); t1.neg()
-
- b.add(t0)
-
- b.add(t1)
- z3.add(t1)
- z2.add(t0)
-
- t0.copy(a); t0.add(c)
- t0.norm(); z3.norm()
- t0.mul(y.a)
- c.copy(z2); c.add(t0)
-
- z3.times_i()
- a.copy(z0); a.add(z3)
+ if stype==FP48.ONE {
+ copy(y)
+ return
}
- if twist == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP48.ONE {
+ return
+ }
+ if y.stype>=FP48.SPARSE {
var z0=FP16(a)
var z1=FP16(0)
var z2=FP16(0)
var z3=FP16(0)
- var t0=FP16(a)
- var t1=FP16(0)
-
z0.mul(y.a)
- t0.add(b)
- t0.norm()
- z1.copy(t0); z1.mul(y.a)
- t0.copy(b); t0.add(c)
- t0.norm();
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ if y.stype==FP48.SPARSE || stype==FP48.SPARSE {
+ var ga=FP8(0)
+ var gb=FP8(0)
- z3.copy(t0);
- z3.pmul(y.c.getb())
- z3.times_i()
+ gb.copy(b.getb())
+ gb.mul(y.b.getb())
+ ga.zero()
+ if y.stype != FP48.SPARSE {
+ ga.copy(b.getb())
+ ga.mul(y.b.geta())
+ }
+ if stype != FP48.SPARSE {
+ ga.copy(b.geta())
+ ga.mul(y.b.getb())
+ }
+ z2.set_fp8s(ga,gb)
+ z2.times_i()
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ } else {
+ z2.copy(b)
+ z2.mul(y.b)
+ }
+ var t0=FP16(a)
+ var t1=FP16(y.a)
+ t0.add(b); t0.norm()
+ t1.add(y.b); t1.norm()
+
+ z1.copy(t0); z1.mul(t1)
+ t0.copy(b); t0.add(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)
- b.copy(z1);
- z2.copy(t0)
+ b.copy(z1); b.add(t1)
- t0.copy(a); t0.add(c)
- t1.copy(y.a); t1.add(y.c)
+ z3.add(t1)
+ z2.add(t0)
- t0.norm()
- t1.norm()
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
t0.mul(t1)
z2.add(t0)
- t0.copy(c)
-
- t0.pmul(y.c.getb())
- t0.times_i()
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ if y.stype==FP48.SPARSE || stype==FP48.SPARSE {
+ var ga=FP8(0)
+ var gb=FP8(0)
+ ga.copy(c.geta())
+ ga.mul(y.c.geta())
+ gb.zero()
+ if y.stype != FP48.SPARSE {
+ gb.copy(c.geta())
+ gb.mul(y.c.getb())
+ }
+ if stype != FP48.SPARSE {
+ gb.copy(c.getb())
+ gb.mul(y.c.geta())
+ }
+ t0.set_fp8s(ga,gb)
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
+ } else {
+ t0.copy(c)
+ t0.mul(y.c)
+ }
t1.copy(t0); t1.neg()
c.copy(z2); c.add(t1)
z3.add(t1)
t0.times_i()
b.add(t0)
- z3.norm();
+ z3.norm()
z3.times_i()
- a.copy(z0); a.add(z3)
+ a.copy(z0); a.add(z3);
+ } else {
+ if stype==FP48.SPARSER {
+ smul(y)
+ return
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE { // dense by sparser - 13m
+ var z0=FP16(a)
+ var z2=FP16(b)
+ var z3=FP16(b)
+ var t0=FP16(0)
+ var t1=FP16(y.a)
+ z0.mul(y.a)
+ z2.pmul(y.b.real())
+ b.add(a)
+ t1.adds(y.b.real())
+
+ t1.norm()
+ b.norm()
+ b.mul(t1)
+ z3.add(c)
+ z3.norm()
+ z3.pmul(y.b.real())
+
+ t0.copy(z0); t0.neg()
+ t1.copy(z2); t1.neg()
+
+ b.add(t0)
+
+ b.add(t1)
+ z3.add(t1)
+ z2.add(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ z3.norm()
+ t0.mul(y.a)
+ c.copy(z2); c.add(t0)
+
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ var z0=FP16(a)
+ var z1=FP16(0)
+ var z2=FP16(0)
+ var z3=FP16(0)
+ var t0=FP16(a)
+ var t1=FP16(0)
+
+ z0.mul(y.a)
+ t0.add(b); t0.norm()
+
+ z1.copy(t0); z1.mul(y.a)
+ t0.copy(b); t0.add(c)
+ t0.norm()
+
+ z3.copy(t0)
+ z3.pmul(y.c.getb())
+ z3.times_i()
+
+ t0.copy(z0); t0.neg()
+ z1.add(t0)
+ b.copy(z1)
+ z2.copy(t0)
+
+ t0.copy(a); t0.add(c); t0.norm()
+ t1.copy(y.a); t1.add(y.c); t1.norm()
+
+ t0.mul(t1)
+ z2.add(t0)
+ t0.copy(c)
+
+ t0.pmul(y.c.getb())
+ t0.times_i()
+ t1.copy(t0); t1.neg()
+
+ c.copy(z2); c.add(t1)
+ z3.add(t1)
+ t0.times_i()
+ b.add(t0)
+ z3.norm()
+ z3.times_i()
+ a.copy(z0); a.add(z3)
+ }
}
- norm()
+ stype=FP48.DENSE
+ norm()
}
+
+
+ /* Special case of multiplication arises from special form of ATE pairing line function */
+ mutating func smul(_ y:FP48)
+ {
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.D_TYPE {
+ var w1=FP8(a.geta())
+ var w2=FP8(a.getb())
+ var w3=FP8(b.geta())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.b.geta())
+
+ var ta=FP8(a.geta())
+ var tb=FP8(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP8(ta)
+ tc.mul(tb)
+ var t=FP8(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.b.geta()); tb.norm()
+ var td=FP8(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(b.geta()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.b.geta()); tb.norm()
+ var te=FP8(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+
+ a.set_fp8s(w1,tc)
+ b.set_fp8s(td,te)
+ c.set_fp8(w3)
+
+ a.norm()
+ b.norm()
+ } else {
+ var w1=FP8(a.geta())
+ var w2=FP8(a.getb())
+ var w3=FP8(c.getb())
+
+ w1.mul(y.a.geta())
+ w2.mul(y.a.getb())
+ w3.mul(y.c.getb())
+
+ var ta=FP8(a.geta())
+ var tb=FP8(y.a.geta())
+ ta.add(a.getb()); ta.norm()
+ tb.add(y.a.getb()); tb.norm()
+ var tc=FP8(ta)
+ tc.mul(tb)
+ var t=FP8(w1)
+ t.add(w2)
+ t.neg()
+ tc.add(t)
+
+ ta.copy(a.geta()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.geta()); tb.add(y.c.getb()); tb.norm()
+ var td=FP8(ta)
+ td.mul(tb)
+ t.copy(w1)
+ t.add(w3)
+ t.neg()
+ td.add(t)
+
+ ta.copy(a.getb()); ta.add(c.getb()); ta.norm()
+ tb.copy(y.a.getb()); tb.add(y.c.getb()); tb.norm()
+ var te=FP8(ta)
+ te.mul(tb)
+ t.copy(w2)
+ t.add(w3)
+ t.neg()
+ te.add(t)
+
+ w2.times_i()
+ w1.add(w2)
+ a.set_fp8s(w1,tc);
+
+ w3.times_i()
+ w3.norm()
+ b.set_fp8h(w3);
+
+ te.norm()
+ te.times_i()
+ c.set_fp8s(te,td)
+
+ a.norm()
+ c.norm()
+
+ }
+ stype=FP48.SPARSE
+ }
+
/* self=1/self */
mutating func inverse()
{
@@ -430,6 +673,7 @@
a.copy(f0); a.mul(f3)
b.copy(f1); b.mul(f3)
c.copy(f2); c.mul(f3)
+ stype=FP48.DENSE
}
/* self=self^p using Frobenius */
@@ -453,7 +697,7 @@
b.qmul(f); b.times_i4(); b.times_i2()
c.qmul(f2); c.times_i4(); c.times_i4(); c.times_i4()
}
-
+ stype=FP48.DENSE
}
/* trace function */
diff --git a/version3/swift/fp8.swift b/version3/swift/fp8.swift
index a60dd41..7f64073 100644
--- a/version3/swift/fp8.swift
+++ b/version3/swift/fp8.swift
@@ -109,7 +109,21 @@
{
return b;
}
-
+ mutating func set_fp4s(_ c: FP4,_ d: FP4)
+ {
+ a.copy(c)
+ b.copy(d)
+ }
+ mutating func set_fp4(_ c: FP4)
+ {
+ a.copy(c)
+ b.zero()
+ }
+ mutating func set_fp4h(_ c: FP4)
+ {
+ b.copy(c)
+ a.zero()
+ }
/* test self=x? */
func equals(_ x:FP8) -> Bool
{
diff --git a/version3/swift/pair.swift b/version3/swift/pair.swift
index 94af78c..06044e7 100644
--- a/version3/swift/pair.swift
+++ b/version3/swift/pair.swift
@@ -78,7 +78,9 @@
}
A.dbl()
- return FP12(a,b,c)
+ var res=FP12(a,b,c)
+ res.settype(FP12.SPARSER)
+ return res
}
@@ -122,7 +124,111 @@
c=FP4(Y1); c.times_i()
}
A.add(B)
- return FP12(a,b,c)
+ var res=FP12(a,b,c)
+ res.settype(FP12.SPARSER)
+ return res
+ }
+
+ static private func lbits(_ n3:inout BIG,_ n:inout BIG) -> Int
+ {
+ n.copy(BIG(ROM.CURVE_Bnx))
+ if CONFIG_CURVE.CURVE_PAIRING_TYPE == CONFIG_CURVE.BN {
+ n.pmul(6)
+ if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.POSITIVEX {
+ n.inc(2)
+ } else {
+ n.dec(2)
+ }
+ }
+ n.norm()
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+ }
+
+ static public func initmp() -> [FP12]
+ {
+ var r=[FP12]();
+ for _ in (0...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ r.append(FP12(1))
+ }
+ return r
+ }
+
+/* basic Miller loop */
+ static public func miller(_ r: [FP12]) -> FP12 {
+ var res=FP12(1)
+ for i in (1...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ res.sqr()
+ res.ssmul(r[i])
+ }
+
+ if CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(r[0])
+ return res
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ static public func another(_ r: inout [FP12],_ P1: ECP2,_ Q1: ECP) {
+ var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
+ var n = BIG();
+ var n3 = BIG();
+ var K = ECP2()
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=ECP2(); P.copy(P1); P.affine()
+ var Q=ECP(); Q.copy(Q1); Q.affine()
+
+ if CONFIG_CURVE.CURVE_PAIRING_TYPE == CONFIG_CURVE.BN {
+ if CONFIG_CURVE.SEXTIC_TWIST == CONFIG_CURVE.M_TYPE {
+ f.inverse()
+ f.norm()
+ }
+ }
+
+ let Qx=FP(Q.getx())
+ let Qy=FP(Q.gety())
+
+ var A=ECP2()
+ A.copy(P)
+ var NP=ECP2()
+ NP.copy(P)
+ NP.neg()
+
+ let nb=lbits(&n3,&n)
+
+ for i in (1...nb-2).reversed() {
+ var lv=linedbl(&A,Qx,Qy)
+
+ let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+ if bt == 1 {
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt == -1 {
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
+
+/* R-ate fixup required for BN curves */
+ if CONFIG_CURVE.CURVE_PAIRING_TYPE == CONFIG_CURVE.BN {
+ if CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX {
+ A.neg()
+ }
+ K.copy(P)
+ K.frob(f)
+ var lv=lineadd(&A,K,Qx,Qy)
+ K.frob(f)
+ K.neg()
+ let lv2=lineadd(&A,K,Qx,Qy)
+ lv.smul(lv2)
+ r[0].ssmul(lv)
+ }
}
@@ -130,8 +236,8 @@
static public func ate(_ P1:ECP2,_ Q1:ECP) -> FP12
{
var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
- let x=BIG(ROM.CURVE_Bnx)
- var n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var K=ECP2()
var lv:FP12
@@ -141,19 +247,7 @@
f.inverse()
f.norm()
}
- n.pmul(6);
- if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
- n.dec(2)
- } else {
- n.inc(2)
- }
- } else {n.copy(x)}
-
- n.norm()
-
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
+ }
var P=ECP2(); P.copy(P1); P.affine()
var Q=ECP(); Q.copy(Q1); Q.affine()
@@ -170,23 +264,24 @@
NP.neg()
var r=FP12(1)
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
//for var i=nb-2;i>=1;i--
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
- lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
@@ -203,11 +298,11 @@
K.frob(f)
lv=lineadd(&A,K,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv=lineadd(&A,K,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,K,Qx,Qy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
return r
}
@@ -215,8 +310,8 @@
static public func ate2(_ P1:ECP2,_ Q1:ECP,_ R1:ECP2,_ S1:ECP) -> FP12
{
var f=FP2(BIG(ROM.Fra),BIG(ROM.Frb))
- let x=BIG(ROM.CURVE_Bnx)
- var n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var K=ECP2()
var lv:FP12
@@ -225,24 +320,12 @@
f.inverse()
f.norm()
}
- n.pmul(6);
- if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
- n.dec(2)
- } else {
- n.inc(2)
- }
- } else {n.copy(x)}
-
- n.norm()
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
+ }
- var P=ECP2(); P.copy(P1); P.affine()
- var Q=ECP(); Q.copy(Q1); Q.affine()
- var R=ECP2(); R.copy(R1); R.affine()
- var S=ECP(); S.copy(S1); S.affine()
-
+ var P=ECP2(); P.copy(P1); P.affine()
+ var Q=ECP(); Q.copy(Q1); Q.affine()
+ var R=ECP2(); R.copy(R1); R.affine()
+ var S=ECP(); S.copy(S1); S.affine()
let Qx=FP(Q.getx())
let Qy=FP(Q.gety())
@@ -262,30 +345,29 @@
NR.copy(R)
NR.neg()
-
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=linedbl(&B,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ var lv2=linedbl(&B,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,R,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,R,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,NR,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,NR,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
}
@@ -305,21 +387,21 @@
K.frob(f)
lv=lineadd(&A,K,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv=lineadd(&A,K,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ var lv2=lineadd(&A,K,Qx,Qy)
+ lv.smul(lv2)
+ r.ssmul(lv)
K.copy(R)
K.frob(f)
lv=lineadd(&B,K,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
K.frob(f)
K.neg()
- lv=lineadd(&B,K,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,K,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
return r
}
diff --git a/version3/swift/pair192.swift b/version3/swift/pair192.swift
index 39488db..d066198 100644
--- a/version3/swift/pair192.swift
+++ b/version3/swift/pair192.swift
@@ -76,7 +76,9 @@
}
A.dbl()
- return FP24(a,b,c)
+ var res=FP24(a,b,c)
+ res.settype(FP24.SPARSER)
+ return res
}
static func lineadd(_ A: inout ECP4,_ B:ECP4,_ Qx:FP,_ Qy:FP) -> FP24
@@ -118,22 +120,89 @@
}
A.add(B)
- return FP24(a,b,c)
+ var res=FP24(a,b,c)
+ res.settype(FP24.SPARSER)
+ return res
+ }
+
+ static private func lbits(_ n3:inout BIG,_ n:inout BIG) -> Int
+ {
+ n.copy(BIG(ROM.CURVE_Bnx))
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+ }
+
+ static public func initmp() -> [FP24]
+ {
+ var r=[FP24]();
+ for _ in (0...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ r.append(FP24(1))
+ }
+ return r
+ }
+
+/* basic Miller loop */
+ static public func miller(_ r: [FP24]) -> FP24 {
+ var res=FP24(1)
+ for i in (1...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ res.sqr()
+ res.ssmul(r[i])
+ }
+
+ if CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(r[0])
+ return res
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ static public func another(_ r: inout [FP24],_ P1: ECP4,_ Q1: ECP) {
+ var n = BIG();
+ var n3 = BIG();
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=ECP4(); P.copy(P1); P.affine()
+ var Q=ECP(); Q.copy(Q1); Q.affine()
+
+ let Qx=FP(Q.getx())
+ let Qy=FP(Q.gety())
+
+ var A=ECP4()
+ A.copy(P)
+ var NP=ECP4()
+ NP.copy(P)
+ NP.neg()
+
+ let nb=lbits(&n3,&n)
+
+ for i in (1...nb-2).reversed() {
+ var lv=linedbl(&A,Qx,Qy)
+
+ let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+ if bt == 1 {
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt == -1 {
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
}
// Optimal R-ate pairing
static public func ate(_ P1:ECP4,_ Q1:ECP) -> FP24
{
- let x=BIG(ROM.CURVE_Bnx)
- let n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var lv:FP24
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
-
var P=ECP4(); P.copy(P1); P.affine()
var Q=ECP(); Q.copy(Q1); Q.affine()
@@ -149,22 +218,23 @@
NP.copy(P)
NP.neg()
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
- lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
@@ -177,13 +247,9 @@
// Optimal R-ate double pairing e(P,Q).e(R,S)
static public func ate2(_ P1:ECP4,_ Q1:ECP,_ R1:ECP4,_ S1:ECP) -> FP24
{
- let x=BIG(ROM.CURVE_Bnx)
- let n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var lv:FP24
-
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
var P=ECP4(); P.copy(P1); P.affine()
var Q=ECP(); Q.copy(Q1); Q.affine()
@@ -209,31 +275,30 @@
NR.copy(R)
NR.neg()
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=linedbl(&B,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ var lv2=linedbl(&B,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,R,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,R,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,NR,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,NR,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
-
}
if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
diff --git a/version3/swift/pair256.swift b/version3/swift/pair256.swift
index e9f1517..1289e94 100644
--- a/version3/swift/pair256.swift
+++ b/version3/swift/pair256.swift
@@ -76,7 +76,9 @@
}
A.dbl()
- return FP48(a,b,c)
+ var res=FP48(a,b,c)
+ res.settype(FP48.SPARSER)
+ return res
}
static func lineadd(_ A: inout ECP8,_ B:ECP8,_ Qx:FP,_ Qy:FP) -> FP48
@@ -118,22 +120,88 @@
}
A.add(B)
- return FP48(a,b,c)
+ var res=FP48(a,b,c)
+ res.settype(FP48.SPARSER)
+ return res
}
+ static private func lbits(_ n3:inout BIG,_ n:inout BIG) -> Int
+ {
+ n.copy(BIG(ROM.CURVE_Bnx))
+ n3.copy(n)
+ n3.pmul(3)
+ n3.norm()
+ return n3.nbits()
+ }
+
+ static public func initmp() -> [FP48]
+ {
+ var r=[FP48]();
+ for _ in (0...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ r.append(FP48(1))
+ }
+ return r
+ }
+
+/* basic Miller loop */
+ static public func miller(_ r: [FP48]) -> FP48 {
+ var res=FP48(1)
+ for i in (1...CONFIG_CURVE.ATE_BITS-1).reversed() {
+ res.sqr()
+ res.ssmul(r[i])
+ }
+
+ if CONFIG_CURVE.SIGN_OF_X==CONFIG_CURVE.NEGATIVEX {
+ res.conj();
+ }
+ res.ssmul(r[0])
+ return res
+ }
+
+/* Accumulate another set of line functions for n-pairing */
+ static public func another(_ r: inout [FP48],_ P1: ECP8,_ Q1: ECP) {
+ var n = BIG();
+ var n3 = BIG();
+
+// P is needed in affine form for line function, Q for (Qx,Qy) extraction
+ var P=ECP8(); P.copy(P1); P.affine()
+ var Q=ECP(); Q.copy(Q1); Q.affine()
+
+ let Qx=FP(Q.getx())
+ let Qy=FP(Q.gety())
+
+ var A=ECP8()
+ A.copy(P)
+ var NP=ECP8()
+ NP.copy(P)
+ NP.neg()
+
+ let nb=lbits(&n3,&n)
+
+ for i in (1...nb-2).reversed() {
+ var lv=linedbl(&A,Qx,Qy)
+
+ let bt=n3.bit(UInt(i))-n.bit(UInt(i))
+ if bt == 1 {
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
+ }
+ if bt == -1 {
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
+ }
+ r[i].ssmul(lv)
+ }
+ }
// Optimal R-ate pairing
static public func ate(_ P1:ECP8,_ Q1:ECP) -> FP48
{
- let x=BIG(ROM.CURVE_Bnx)
- let n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var lv:FP48
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
-
var P=ECP8(); P.copy(P1); P.affine()
var Q=ECP(); Q.copy(Q1); Q.affine()
@@ -148,22 +216,23 @@
NP.copy(P)
NP.neg()
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
- lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,P,Qx,Qy)
+ lv.smul(lv2)
}
if bt == -1 {
- lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ let lv2=lineadd(&A,NP,Qx,Qy)
+ lv.smul(lv2)
}
+ r.ssmul(lv)
}
if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {
@@ -176,20 +245,15 @@
// Optimal R-ate double pairing e(P,Q).e(R,S)
static public func ate2(_ P1:ECP8,_ Q1:ECP,_ R1:ECP8,_ S1:ECP) -> FP48
{
- let x=BIG(ROM.CURVE_Bnx)
- let n=BIG(x)
+ var n = BIG();
+ var n3 = BIG();
var lv:FP48
-
- var n3=BIG(n)
- n3.pmul(3)
- n3.norm()
var P=ECP8(); P.copy(P1); P.affine()
var Q=ECP(); Q.copy(Q1); Q.affine()
var R=ECP8(); R.copy(R1); R.affine()
var S=ECP(); S.copy(S1); S.affine()
-
let Qx=FP(Q.getx())
let Qy=FP(Q.gety())
let Sx=FP(S.getx())
@@ -208,31 +272,30 @@
NR.copy(R)
NR.neg()
- let nb=n3.nbits()
+ let nb=lbits(&n3,&n)
for i in (1...nb-2).reversed()
{
r.sqr()
lv=linedbl(&A,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=linedbl(&B,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ var lv2=linedbl(&B,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
let bt=n3.bit(UInt(i))-n.bit(UInt(i))
if bt == 1 {
lv=lineadd(&A,P,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,R,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,R,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
if bt == -1 {
lv=lineadd(&A,NP,Qx,Qy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
- lv=lineadd(&B,NR,Sx,Sy)
- r.smul(lv,CONFIG_CURVE.SEXTIC_TWIST)
+ lv2=lineadd(&B,NR,Sx,Sy)
+ lv.smul(lv2)
+ r.ssmul(lv)
}
-
}
if CONFIG_CURVE.SIGN_OF_X == CONFIG_CURVE.NEGATIVEX {