ed25519 1.0.0-jruby → 1.1.0-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGES.md +13 -0
  4. data/README.md +9 -9
  5. data/Rakefile +3 -3
  6. data/ext/ed25519_jruby/LICENSE.txt +123 -0
  7. data/ext/ed25519_jruby/README.md +77 -0
  8. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/EdDSAEngine.java +491 -0
  9. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/EdDSAKey.java +31 -0
  10. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/EdDSAPrivateKey.java +338 -0
  11. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/EdDSAPublicKey.java +275 -0
  12. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/EdDSASecurityProvider.java +59 -0
  13. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/KeyFactory.java +75 -0
  14. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/KeyPairGenerator.java +97 -0
  15. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/Utils.java +103 -0
  16. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Constants.java +23 -0
  17. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Curve.java +100 -0
  18. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Encoding.java +54 -0
  19. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/Field.java +99 -0
  20. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/FieldElement.java +76 -0
  21. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/GroupElement.java +1034 -0
  22. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ScalarOps.java +34 -0
  23. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerFieldElement.java +131 -0
  24. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerLittleEndianEncoding.java +102 -0
  25. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/BigIntegerScalarOps.java +37 -0
  26. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/bigint/package.html +6 -0
  27. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ed25519/Ed25519FieldElement.java +988 -0
  28. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ed25519/Ed25519LittleEndianEncoding.java +256 -0
  29. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/math/ed25519/Ed25519ScalarOps.java +693 -0
  30. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAGenParameterSpec.java +32 -0
  31. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSANamedCurveSpec.java +35 -0
  32. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSANamedCurveTable.java +71 -0
  33. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAParameterSpec.java +97 -0
  34. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAPrivateKeySpec.java +133 -0
  35. data/ext/ed25519_jruby/net/i2p/crypto/eddsa/spec/EdDSAPublicKeySpec.java +61 -0
  36. data/ext/ed25519_jruby/org/cryptosphere/Ed25519Provider.java +95 -0
  37. data/lib/ed25519.rb +8 -8
  38. data/lib/ed25519/signing_key.rb +9 -0
  39. data/lib/ed25519/version.rb +1 -1
  40. data/lib/ed25519_java.jar +0 -0
  41. metadata +32 -3
  42. data/ext/ed25519_java/org/cryptosphere/ed25519.java +0 -228
  43. data/lib/ed25519/provider/jruby.rb +0 -39
@@ -0,0 +1,34 @@
1
+ /**
2
+ * EdDSA-Java by str4d
3
+ *
4
+ * To the extent possible under law, the person who associated CC0 with
5
+ * EdDSA-Java has waived all copyright and related or neighboring rights
6
+ * to EdDSA-Java.
7
+ *
8
+ * You should have received a copy of the CC0 legalcode along with this
9
+ * work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
10
+ *
11
+ */
12
+ package net.i2p.crypto.eddsa.math;
13
+
14
+ public interface ScalarOps {
15
+ /**
16
+ * Reduce the given scalar mod $l$.
17
+ * <p>
18
+ * From the Ed25519 paper:<br>
19
+ * Here we interpret $2b$-bit strings in little-endian form as integers in
20
+ * $\{0, 1,..., 2^{(2b)}-1\}$.
21
+ * @param s the scalar to reduce
22
+ * @return $s \bmod l$
23
+ */
24
+ public byte[] reduce(byte[] s);
25
+
26
+ /**
27
+ * $r = (a * b + c) \bmod l$
28
+ * @param a a scalar
29
+ * @param b a scalar
30
+ * @param c a scalar
31
+ * @return $(a*b + c) \bmod l$
32
+ */
33
+ public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c);
34
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * EdDSA-Java by str4d
3
+ *
4
+ * To the extent possible under law, the person who associated CC0 with
5
+ * EdDSA-Java has waived all copyright and related or neighboring rights
6
+ * to EdDSA-Java.
7
+ *
8
+ * You should have received a copy of the CC0 legalcode along with this
9
+ * work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
10
+ *
11
+ */
12
+ package net.i2p.crypto.eddsa.math.bigint;
13
+
14
+ import java.io.Serializable;
15
+ import java.math.BigInteger;
16
+
17
+ import net.i2p.crypto.eddsa.math.Field;
18
+ import net.i2p.crypto.eddsa.math.FieldElement;
19
+
20
+ /**
21
+ * A particular element of the field \Z/(2^255-19).
22
+ * @author str4d
23
+ *
24
+ */
25
+ public class BigIntegerFieldElement extends FieldElement implements Serializable {
26
+ private static final long serialVersionUID = 4890398908392808L;
27
+ /**
28
+ * Variable is package private for encoding.
29
+ */
30
+ final BigInteger bi;
31
+
32
+ public BigIntegerFieldElement(Field f, BigInteger bi) {
33
+ super(f);
34
+ this.bi = bi;
35
+ }
36
+
37
+ public boolean isNonZero() {
38
+ return !bi.equals(BigInteger.ZERO);
39
+ }
40
+
41
+ public FieldElement add(FieldElement val) {
42
+ return new BigIntegerFieldElement(f, bi.add(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
43
+ }
44
+
45
+ @Override
46
+ public FieldElement addOne() {
47
+ return new BigIntegerFieldElement(f, bi.add(BigInteger.ONE)).mod(f.getQ());
48
+ }
49
+
50
+ public FieldElement subtract(FieldElement val) {
51
+ return new BigIntegerFieldElement(f, bi.subtract(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
52
+ }
53
+
54
+ @Override
55
+ public FieldElement subtractOne() {
56
+ return new BigIntegerFieldElement(f, bi.subtract(BigInteger.ONE)).mod(f.getQ());
57
+ }
58
+
59
+ public FieldElement negate() {
60
+ return f.getQ().subtract(this);
61
+ }
62
+
63
+ @Override
64
+ public FieldElement divide(FieldElement val) {
65
+ return divide(((BigIntegerFieldElement)val).bi);
66
+ }
67
+
68
+ public FieldElement divide(BigInteger val) {
69
+ return new BigIntegerFieldElement(f, bi.divide(val)).mod(f.getQ());
70
+ }
71
+
72
+ public FieldElement multiply(FieldElement val) {
73
+ return new BigIntegerFieldElement(f, bi.multiply(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
74
+ }
75
+
76
+ public FieldElement square() {
77
+ return multiply(this);
78
+ }
79
+
80
+ public FieldElement squareAndDouble() {
81
+ FieldElement sq = square();
82
+ return sq.add(sq);
83
+ }
84
+
85
+ public FieldElement invert() {
86
+ // Euler's theorem
87
+ //return modPow(f.getQm2(), f.getQ());
88
+ return new BigIntegerFieldElement(f, bi.modInverse(((BigIntegerFieldElement)f.getQ()).bi));
89
+ }
90
+
91
+ public FieldElement mod(FieldElement m) {
92
+ return new BigIntegerFieldElement(f, bi.mod(((BigIntegerFieldElement)m).bi));
93
+ }
94
+
95
+ public FieldElement modPow(FieldElement e, FieldElement m) {
96
+ return new BigIntegerFieldElement(f, bi.modPow(((BigIntegerFieldElement)e).bi, ((BigIntegerFieldElement)m).bi));
97
+ }
98
+
99
+ public FieldElement pow(FieldElement e){
100
+ return modPow(e, f.getQ());
101
+ }
102
+
103
+ public FieldElement pow22523(){
104
+ return pow(f.getQm5d8());
105
+ }
106
+
107
+ @Override
108
+ public FieldElement cmov(FieldElement val, int b) {
109
+ // Not constant-time, but it doesn't really matter because none of the underlying BigInteger operations
110
+ // are either, so there's not much point in trying hard here ...
111
+ return b == 0 ? this : val;
112
+ }
113
+
114
+ @Override
115
+ public int hashCode() {
116
+ return bi.hashCode();
117
+ }
118
+
119
+ @Override
120
+ public boolean equals(Object obj) {
121
+ if (!(obj instanceof BigIntegerFieldElement))
122
+ return false;
123
+ BigIntegerFieldElement fe = (BigIntegerFieldElement) obj;
124
+ return bi.equals(fe.bi);
125
+ }
126
+
127
+ @Override
128
+ public String toString() {
129
+ return "[BigIntegerFieldElement val="+bi+"]";
130
+ }
131
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * EdDSA-Java by str4d
3
+ *
4
+ * To the extent possible under law, the person who associated CC0 with
5
+ * EdDSA-Java has waived all copyright and related or neighboring rights
6
+ * to EdDSA-Java.
7
+ *
8
+ * You should have received a copy of the CC0 legalcode along with this
9
+ * work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
10
+ *
11
+ */
12
+ package net.i2p.crypto.eddsa.math.bigint;
13
+
14
+ import java.io.Serializable;
15
+ import java.math.BigInteger;
16
+
17
+ import net.i2p.crypto.eddsa.math.Encoding;
18
+ import net.i2p.crypto.eddsa.math.Field;
19
+ import net.i2p.crypto.eddsa.math.FieldElement;
20
+
21
+ public class BigIntegerLittleEndianEncoding extends Encoding implements Serializable {
22
+ private static final long serialVersionUID = 3984579843759837L;
23
+ /**
24
+ * Mask where only the first b-1 bits are set.
25
+ */
26
+ private BigInteger mask;
27
+
28
+ @Override
29
+ public synchronized void setField(Field f) {
30
+ super.setField(f);
31
+ mask = BigInteger.ONE.shiftLeft(f.getb()-1).subtract(BigInteger.ONE);
32
+ }
33
+
34
+ public byte[] encode(FieldElement x) {
35
+ return encode(((BigIntegerFieldElement)x).bi.and(mask));
36
+ }
37
+
38
+ /**
39
+ * Convert $x$ to little endian.
40
+ * Constant time.
41
+ *
42
+ * @param x the BigInteger value to encode
43
+ * @return array of length $b/8$
44
+ * @throws IllegalStateException if field not set
45
+ */
46
+ public byte[] encode(BigInteger x) {
47
+ if (f == null)
48
+ throw new IllegalStateException("field not set");
49
+ byte[] in = x.toByteArray();
50
+ byte[] out = new byte[f.getb()/8];
51
+ for (int i = 0; i < in.length; i++) {
52
+ out[i] = in[in.length-1-i];
53
+ }
54
+ for (int i = in.length; i < out.length; i++) {
55
+ out[i] = 0;
56
+ }
57
+ return out;
58
+ }
59
+
60
+ /**
61
+ * Decode a FieldElement from its $(b-1)$-bit encoding.
62
+ * The highest bit is masked out.
63
+ *
64
+ * @param in the $(b-1)$-bit encoding of a FieldElement.
65
+ * @return the FieldElement represented by 'val'.
66
+ * @throws IllegalStateException if field not set
67
+ * @throws IllegalArgumentException if encoding is invalid
68
+ */
69
+ public FieldElement decode(byte[] in) {
70
+ if (f == null)
71
+ throw new IllegalStateException("field not set");
72
+ if (in.length != f.getb()/8)
73
+ throw new IllegalArgumentException("Not a valid encoding");
74
+ return new BigIntegerFieldElement(f, toBigInteger(in).and(mask));
75
+ }
76
+
77
+ /**
78
+ * Convert in to big endian
79
+ *
80
+ * @param in the $(b-1)$-bit encoding of a FieldElement.
81
+ * @return the decoded value as a BigInteger
82
+ */
83
+ public BigInteger toBigInteger(byte[] in) {
84
+ byte[] out = new byte[in.length];
85
+ for (int i = 0; i < in.length; i++) {
86
+ out[i] = in[in.length-1-i];
87
+ }
88
+ return new BigInteger(1, out);
89
+ }
90
+
91
+ /**
92
+ * From the Ed25519 paper:<br>
93
+ * $x$ is negative if the $(b-1)$-bit encoding of $x$ is lexicographically larger
94
+ * than the $(b-1)$-bit encoding of $-x$. If $q$ is an odd prime and the encoding
95
+ * is the little-endian representation of $\{0, 1,\dots, q-1\}$ then the negative
96
+ * elements of $F_q$ are $\{1, 3, 5,\dots, q-2\}$.
97
+ * @return true if negative
98
+ */
99
+ public boolean isNegative(FieldElement x) {
100
+ return ((BigIntegerFieldElement)x).bi.testBit(0);
101
+ }
102
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * EdDSA-Java by str4d
3
+ *
4
+ * To the extent possible under law, the person who associated CC0 with
5
+ * EdDSA-Java has waived all copyright and related or neighboring rights
6
+ * to EdDSA-Java.
7
+ *
8
+ * You should have received a copy of the CC0 legalcode along with this
9
+ * work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
10
+ *
11
+ */
12
+ package net.i2p.crypto.eddsa.math.bigint;
13
+
14
+ import java.math.BigInteger;
15
+
16
+ import net.i2p.crypto.eddsa.math.Field;
17
+ import net.i2p.crypto.eddsa.math.ScalarOps;
18
+
19
+ public class BigIntegerScalarOps implements ScalarOps {
20
+ private final BigInteger l;
21
+ private final BigIntegerLittleEndianEncoding enc;
22
+
23
+ public BigIntegerScalarOps(Field f, BigInteger l) {
24
+ this.l = l;
25
+ enc = new BigIntegerLittleEndianEncoding();
26
+ enc.setField(f);
27
+ }
28
+
29
+ public byte[] reduce(byte[] s) {
30
+ return enc.encode(enc.toBigInteger(s).mod(l));
31
+ }
32
+
33
+ public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c) {
34
+ return enc.encode(enc.toBigInteger(a).multiply(enc.toBigInteger(b)).add(enc.toBigInteger(c)).mod(l));
35
+ }
36
+
37
+ }
@@ -0,0 +1,6 @@
1
+ <html><body>
2
+ <p>
3
+ Low-level, non-optimized implementation using BigIntegers for any curve.
4
+ See the <a href="../ed25519/package-summary.html">ed25519</a> implementation for Curve 25519.
5
+ </p>
6
+ </body></html>
@@ -0,0 +1,988 @@
1
+ /**
2
+ * EdDSA-Java by str4d
3
+ *
4
+ * To the extent possible under law, the person who associated CC0 with
5
+ * EdDSA-Java has waived all copyright and related or neighboring rights
6
+ * to EdDSA-Java.
7
+ *
8
+ * You should have received a copy of the CC0 legalcode along with this
9
+ * work. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
10
+ *
11
+ */
12
+ package net.i2p.crypto.eddsa.math.ed25519;
13
+
14
+ import net.i2p.crypto.eddsa.Utils;
15
+ import net.i2p.crypto.eddsa.math.*;
16
+
17
+ import java.util.Arrays;
18
+
19
+ /**
20
+ * Class to represent a field element of the finite field $p = 2^{255} - 19$ elements.
21
+ * <p>
22
+ * An element $t$, entries $t[0] \dots t[9]$, represents the integer
23
+ * $t[0]+2^{26} t[1]+2^{51} t[2]+2^{77} t[3]+2^{102} t[4]+\dots+2^{230} t[9]$.
24
+ * Bounds on each $t[i]$ vary depending on context.
25
+ * <p>
26
+ * Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
27
+ */
28
+ public class Ed25519FieldElement extends FieldElement {
29
+ /**
30
+ * Variable is package private for encoding.
31
+ */
32
+ final int[] t;
33
+
34
+ /**
35
+ * Creates a field element.
36
+ *
37
+ * @param f The underlying field, must be the finite field with $p = 2^{255} - 19$ elements
38
+ * @param t The $2^{25.5}$ bit representation of the field element.
39
+ */
40
+ public Ed25519FieldElement(Field f, int[] t) {
41
+ super(f);
42
+ if (t.length != 10)
43
+ throw new IllegalArgumentException("Invalid radix-2^51 representation");
44
+ this.t = t;
45
+ }
46
+
47
+ private static final byte[] ZERO = new byte[32];
48
+
49
+ /**
50
+ * Gets a value indicating whether or not the field element is non-zero.
51
+ *
52
+ * @return 1 if it is non-zero, 0 otherwise.
53
+ */
54
+ public boolean isNonZero() {
55
+ final byte[] s = toByteArray();
56
+ return Utils.equal(s, ZERO) == 0;
57
+ }
58
+
59
+ /**
60
+ * $h = f + g$
61
+ * <p>
62
+ * TODO-CR BR: $h$ is allocated via new, probably not a good idea. Do we need the copying into temp variables if we do that?
63
+ * <p>
64
+ * Preconditions:
65
+ * </p><ul>
66
+ * <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
67
+ * <li>$|g|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
68
+ * </ul><p>
69
+ * Postconditions:
70
+ * </p><ul>
71
+ * <li>$|h|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25},$ etc.
72
+ * </ul>
73
+ *
74
+ * @param val The field element to add.
75
+ * @return The field element this + val.
76
+ */
77
+ public FieldElement add(FieldElement val) {
78
+ int[] g = ((Ed25519FieldElement)val).t;
79
+ int[] h = new int[10];
80
+ for (int i = 0; i < 10; i++) {
81
+ h[i] = t[i] + g[i];
82
+ }
83
+ return new Ed25519FieldElement(f, h);
84
+ }
85
+
86
+ /**
87
+ * $h = f - g$
88
+ * <p>
89
+ * Can overlap $h$ with $f$ or $g$.
90
+ * <p>
91
+ * TODO-CR BR: See above.
92
+ * <p>
93
+ * Preconditions:
94
+ * </p><ul>
95
+ * <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
96
+ * <li>$|g|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
97
+ * </ul><p>
98
+ * Postconditions:
99
+ * </p><ul>
100
+ * <li>$|h|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25},$ etc.
101
+ * </ul>
102
+ *
103
+ * @param val The field element to subtract.
104
+ * @return The field element this - val.
105
+ **/
106
+ public FieldElement subtract(FieldElement val) {
107
+ int[] g = ((Ed25519FieldElement)val).t;
108
+ int[] h = new int[10];
109
+ for (int i = 0; i < 10; i++) {
110
+ h[i] = t[i] - g[i];
111
+ }
112
+ return new Ed25519FieldElement(f, h);
113
+ }
114
+
115
+ /**
116
+ * $h = -f$
117
+ * <p>
118
+ * TODO-CR BR: see above.
119
+ * <p>
120
+ * Preconditions:
121
+ * </p><ul>
122
+ * <li>$|f|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
123
+ * </ul><p>
124
+ * Postconditions:
125
+ * </p><ul>
126
+ * <li>$|h|$ bounded by $1.1*2^{25},1.1*2^{24},1.1*2^{25},1.1*2^{24},$ etc.
127
+ * </ul>
128
+ *
129
+ * @return The field element (-1) * this.
130
+ */
131
+ public FieldElement negate() {
132
+ int[] h = new int[10];
133
+ for (int i = 0; i < 10; i++) {
134
+ h[i] = - t[i];
135
+ }
136
+ return new Ed25519FieldElement(f, h);
137
+ }
138
+
139
+ /**
140
+ * $h = f * g$
141
+ * <p>
142
+ * Can overlap $h$ with $f$ or $g$.
143
+ * <p>
144
+ * Preconditions:
145
+ * </p><ul>
146
+ * <li>$|f|$ bounded by
147
+ * $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
148
+ * <li>$|g|$ bounded by
149
+ * $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
150
+ * </ul><p>
151
+ * Postconditions:
152
+ * </p><ul>
153
+ * <li>$|h|$ bounded by
154
+ * $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
155
+ * </ul><p>
156
+ * Notes on implementation strategy:
157
+ * <p>
158
+ * Using schoolbook multiplication. Karatsuba would save a little in some
159
+ * cost models.
160
+ * <p>
161
+ * Most multiplications by 2 and 19 are 32-bit precomputations; cheaper than
162
+ * 64-bit postcomputations.
163
+ * <p>
164
+ * There is one remaining multiplication by 19 in the carry chain; one *19
165
+ * precomputation can be merged into this, but the resulting data flow is
166
+ * considerably less clean.
167
+ * <p>
168
+ * There are 12 carries below. 10 of them are 2-way parallelizable and
169
+ * vectorizable. Can get away with 11 carries, but then data flow is much
170
+ * deeper.
171
+ * <p>
172
+ * With tighter constraints on inputs can squeeze carries into int32.
173
+ *
174
+ * @param val The field element to multiply.
175
+ * @return The (reasonably reduced) field element this * val.
176
+ */
177
+ public FieldElement multiply(FieldElement val) {
178
+ int[] g = ((Ed25519FieldElement)val).t;
179
+ int g1_19 = 19 * g[1]; /* 1.959375*2^29 */
180
+ int g2_19 = 19 * g[2]; /* 1.959375*2^30; still ok */
181
+ int g3_19 = 19 * g[3];
182
+ int g4_19 = 19 * g[4];
183
+ int g5_19 = 19 * g[5];
184
+ int g6_19 = 19 * g[6];
185
+ int g7_19 = 19 * g[7];
186
+ int g8_19 = 19 * g[8];
187
+ int g9_19 = 19 * g[9];
188
+ int f1_2 = 2 * t[1];
189
+ int f3_2 = 2 * t[3];
190
+ int f5_2 = 2 * t[5];
191
+ int f7_2 = 2 * t[7];
192
+ int f9_2 = 2 * t[9];
193
+ long f0g0 = t[0] * (long) g[0];
194
+ long f0g1 = t[0] * (long) g[1];
195
+ long f0g2 = t[0] * (long) g[2];
196
+ long f0g3 = t[0] * (long) g[3];
197
+ long f0g4 = t[0] * (long) g[4];
198
+ long f0g5 = t[0] * (long) g[5];
199
+ long f0g6 = t[0] * (long) g[6];
200
+ long f0g7 = t[0] * (long) g[7];
201
+ long f0g8 = t[0] * (long) g[8];
202
+ long f0g9 = t[0] * (long) g[9];
203
+ long f1g0 = t[1] * (long) g[0];
204
+ long f1g1_2 = f1_2 * (long) g[1];
205
+ long f1g2 = t[1] * (long) g[2];
206
+ long f1g3_2 = f1_2 * (long) g[3];
207
+ long f1g4 = t[1] * (long) g[4];
208
+ long f1g5_2 = f1_2 * (long) g[5];
209
+ long f1g6 = t[1] * (long) g[6];
210
+ long f1g7_2 = f1_2 * (long) g[7];
211
+ long f1g8 = t[1] * (long) g[8];
212
+ long f1g9_38 = f1_2 * (long) g9_19;
213
+ long f2g0 = t[2] * (long) g[0];
214
+ long f2g1 = t[2] * (long) g[1];
215
+ long f2g2 = t[2] * (long) g[2];
216
+ long f2g3 = t[2] * (long) g[3];
217
+ long f2g4 = t[2] * (long) g[4];
218
+ long f2g5 = t[2] * (long) g[5];
219
+ long f2g6 = t[2] * (long) g[6];
220
+ long f2g7 = t[2] * (long) g[7];
221
+ long f2g8_19 = t[2] * (long) g8_19;
222
+ long f2g9_19 = t[2] * (long) g9_19;
223
+ long f3g0 = t[3] * (long) g[0];
224
+ long f3g1_2 = f3_2 * (long) g[1];
225
+ long f3g2 = t[3] * (long) g[2];
226
+ long f3g3_2 = f3_2 * (long) g[3];
227
+ long f3g4 = t[3] * (long) g[4];
228
+ long f3g5_2 = f3_2 * (long) g[5];
229
+ long f3g6 = t[3] * (long) g[6];
230
+ long f3g7_38 = f3_2 * (long) g7_19;
231
+ long f3g8_19 = t[3] * (long) g8_19;
232
+ long f3g9_38 = f3_2 * (long) g9_19;
233
+ long f4g0 = t[4] * (long) g[0];
234
+ long f4g1 = t[4] * (long) g[1];
235
+ long f4g2 = t[4] * (long) g[2];
236
+ long f4g3 = t[4] * (long) g[3];
237
+ long f4g4 = t[4] * (long) g[4];
238
+ long f4g5 = t[4] * (long) g[5];
239
+ long f4g6_19 = t[4] * (long) g6_19;
240
+ long f4g7_19 = t[4] * (long) g7_19;
241
+ long f4g8_19 = t[4] * (long) g8_19;
242
+ long f4g9_19 = t[4] * (long) g9_19;
243
+ long f5g0 = t[5] * (long) g[0];
244
+ long f5g1_2 = f5_2 * (long) g[1];
245
+ long f5g2 = t[5] * (long) g[2];
246
+ long f5g3_2 = f5_2 * (long) g[3];
247
+ long f5g4 = t[5] * (long) g[4];
248
+ long f5g5_38 = f5_2 * (long) g5_19;
249
+ long f5g6_19 = t[5] * (long) g6_19;
250
+ long f5g7_38 = f5_2 * (long) g7_19;
251
+ long f5g8_19 = t[5] * (long) g8_19;
252
+ long f5g9_38 = f5_2 * (long) g9_19;
253
+ long f6g0 = t[6] * (long) g[0];
254
+ long f6g1 = t[6] * (long) g[1];
255
+ long f6g2 = t[6] * (long) g[2];
256
+ long f6g3 = t[6] * (long) g[3];
257
+ long f6g4_19 = t[6] * (long) g4_19;
258
+ long f6g5_19 = t[6] * (long) g5_19;
259
+ long f6g6_19 = t[6] * (long) g6_19;
260
+ long f6g7_19 = t[6] * (long) g7_19;
261
+ long f6g8_19 = t[6] * (long) g8_19;
262
+ long f6g9_19 = t[6] * (long) g9_19;
263
+ long f7g0 = t[7] * (long) g[0];
264
+ long f7g1_2 = f7_2 * (long) g[1];
265
+ long f7g2 = t[7] * (long) g[2];
266
+ long f7g3_38 = f7_2 * (long) g3_19;
267
+ long f7g4_19 = t[7] * (long) g4_19;
268
+ long f7g5_38 = f7_2 * (long) g5_19;
269
+ long f7g6_19 = t[7] * (long) g6_19;
270
+ long f7g7_38 = f7_2 * (long) g7_19;
271
+ long f7g8_19 = t[7] * (long) g8_19;
272
+ long f7g9_38 = f7_2 * (long) g9_19;
273
+ long f8g0 = t[8] * (long) g[0];
274
+ long f8g1 = t[8] * (long) g[1];
275
+ long f8g2_19 = t[8] * (long) g2_19;
276
+ long f8g3_19 = t[8] * (long) g3_19;
277
+ long f8g4_19 = t[8] * (long) g4_19;
278
+ long f8g5_19 = t[8] * (long) g5_19;
279
+ long f8g6_19 = t[8] * (long) g6_19;
280
+ long f8g7_19 = t[8] * (long) g7_19;
281
+ long f8g8_19 = t[8] * (long) g8_19;
282
+ long f8g9_19 = t[8] * (long) g9_19;
283
+ long f9g0 = t[9] * (long) g[0];
284
+ long f9g1_38 = f9_2 * (long) g1_19;
285
+ long f9g2_19 = t[9] * (long) g2_19;
286
+ long f9g3_38 = f9_2 * (long) g3_19;
287
+ long f9g4_19 = t[9] * (long) g4_19;
288
+ long f9g5_38 = f9_2 * (long) g5_19;
289
+ long f9g6_19 = t[9] * (long) g6_19;
290
+ long f9g7_38 = f9_2 * (long) g7_19;
291
+ long f9g8_19 = t[9] * (long) g8_19;
292
+ long f9g9_38 = f9_2 * (long) g9_19;
293
+
294
+ /**
295
+ * Remember: 2^255 congruent 19 modulo p.
296
+ * h = h0 * 2^0 + h1 * 2^26 + h2 * 2^(26+25) + h3 * 2^(26+25+26) + ... + h9 * 2^(5*26+5*25).
297
+ * So to get the real number we would have to multiply the coefficients with the corresponding powers of 2.
298
+ * To get an idea what is going on below, look at the calculation of h0:
299
+ * h0 is the coefficient to the power 2^0 so it collects (sums) all products that have the power 2^0.
300
+ * f0 * g0 really is f0 * 2^0 * g0 * 2^0 = (f0 * g0) * 2^0.
301
+ * f1 * g9 really is f1 * 2^26 * g9 * 2^230 = f1 * g9 * 2^256 = 2 * f1 * g9 * 2^255 congruent 2 * 19 * f1 * g9 * 2^0 modulo p.
302
+ * f2 * g8 really is f2 * 2^51 * g8 * 2^204 = f2 * g8 * 2^255 congruent 19 * f2 * g8 * 2^0 modulo p.
303
+ * and so on...
304
+ */
305
+ long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
306
+ long h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
307
+ long h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
308
+ long h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
309
+ long h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
310
+ long h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
311
+ long h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
312
+ long h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
313
+ long h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
314
+ long h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
315
+ long carry0;
316
+ long carry1;
317
+ long carry2;
318
+ long carry3;
319
+ long carry4;
320
+ long carry5;
321
+ long carry6;
322
+ long carry7;
323
+ long carry8;
324
+ long carry9;
325
+
326
+ /*
327
+ |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
328
+ i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
329
+ |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
330
+ i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
331
+ */
332
+
333
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
334
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
335
+ /* |h0| <= 2^25 */
336
+ /* |h4| <= 2^25 */
337
+ /* |h1| <= 1.71*2^59 */
338
+ /* |h5| <= 1.71*2^59 */
339
+
340
+ carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
341
+ carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
342
+ /* |h1| <= 2^24; from now on fits into int32 */
343
+ /* |h5| <= 2^24; from now on fits into int32 */
344
+ /* |h2| <= 1.41*2^60 */
345
+ /* |h6| <= 1.41*2^60 */
346
+
347
+ carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
348
+ carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
349
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
350
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
351
+ /* |h3| <= 1.71*2^59 */
352
+ /* |h7| <= 1.71*2^59 */
353
+
354
+ carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
355
+ carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
356
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
357
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
358
+ /* |h4| <= 1.72*2^34 */
359
+ /* |h8| <= 1.41*2^60 */
360
+
361
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
362
+ carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
363
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
364
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
365
+ /* |h5| <= 1.01*2^24 */
366
+ /* |h9| <= 1.71*2^59 */
367
+
368
+ carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
369
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
370
+ /* |h0| <= 1.1*2^39 */
371
+
372
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
373
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
374
+ /* |h1| <= 1.01*2^24 */
375
+
376
+ int[] h = new int[10];
377
+ h[0] = (int) h0;
378
+ h[1] = (int) h1;
379
+ h[2] = (int) h2;
380
+ h[3] = (int) h3;
381
+ h[4] = (int) h4;
382
+ h[5] = (int) h5;
383
+ h[6] = (int) h6;
384
+ h[7] = (int) h7;
385
+ h[8] = (int) h8;
386
+ h[9] = (int) h9;
387
+ return new Ed25519FieldElement(f, h);
388
+ }
389
+
390
+ /**
391
+ * $h = f * f$
392
+ * <p>
393
+ * Can overlap $h$ with $f$.
394
+ * <p>
395
+ * Preconditions:
396
+ * </p><ul>
397
+ * <li>$|f|$ bounded by $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
398
+ * </ul><p>
399
+ * Postconditions:
400
+ * </p><ul>
401
+ * <li>$|h|$ bounded by $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
402
+ * </ul><p>
403
+ * See {@link #multiply(FieldElement)} for discussion
404
+ * of implementation strategy.
405
+ *
406
+ * @return The (reasonably reduced) square of this field element.
407
+ */
408
+ public FieldElement square() {
409
+ int f0 = t[0];
410
+ int f1 = t[1];
411
+ int f2 = t[2];
412
+ int f3 = t[3];
413
+ int f4 = t[4];
414
+ int f5 = t[5];
415
+ int f6 = t[6];
416
+ int f7 = t[7];
417
+ int f8 = t[8];
418
+ int f9 = t[9];
419
+ int f0_2 = 2 * f0;
420
+ int f1_2 = 2 * f1;
421
+ int f2_2 = 2 * f2;
422
+ int f3_2 = 2 * f3;
423
+ int f4_2 = 2 * f4;
424
+ int f5_2 = 2 * f5;
425
+ int f6_2 = 2 * f6;
426
+ int f7_2 = 2 * f7;
427
+ int f5_38 = 38 * f5; /* 1.959375*2^30 */
428
+ int f6_19 = 19 * f6; /* 1.959375*2^30 */
429
+ int f7_38 = 38 * f7; /* 1.959375*2^30 */
430
+ int f8_19 = 19 * f8; /* 1.959375*2^30 */
431
+ int f9_38 = 38 * f9; /* 1.959375*2^30 */
432
+ long f0f0 = f0 * (long) f0;
433
+ long f0f1_2 = f0_2 * (long) f1;
434
+ long f0f2_2 = f0_2 * (long) f2;
435
+ long f0f3_2 = f0_2 * (long) f3;
436
+ long f0f4_2 = f0_2 * (long) f4;
437
+ long f0f5_2 = f0_2 * (long) f5;
438
+ long f0f6_2 = f0_2 * (long) f6;
439
+ long f0f7_2 = f0_2 * (long) f7;
440
+ long f0f8_2 = f0_2 * (long) f8;
441
+ long f0f9_2 = f0_2 * (long) f9;
442
+ long f1f1_2 = f1_2 * (long) f1;
443
+ long f1f2_2 = f1_2 * (long) f2;
444
+ long f1f3_4 = f1_2 * (long) f3_2;
445
+ long f1f4_2 = f1_2 * (long) f4;
446
+ long f1f5_4 = f1_2 * (long) f5_2;
447
+ long f1f6_2 = f1_2 * (long) f6;
448
+ long f1f7_4 = f1_2 * (long) f7_2;
449
+ long f1f8_2 = f1_2 * (long) f8;
450
+ long f1f9_76 = f1_2 * (long) f9_38;
451
+ long f2f2 = f2 * (long) f2;
452
+ long f2f3_2 = f2_2 * (long) f3;
453
+ long f2f4_2 = f2_2 * (long) f4;
454
+ long f2f5_2 = f2_2 * (long) f5;
455
+ long f2f6_2 = f2_2 * (long) f6;
456
+ long f2f7_2 = f2_2 * (long) f7;
457
+ long f2f8_38 = f2_2 * (long) f8_19;
458
+ long f2f9_38 = f2 * (long) f9_38;
459
+ long f3f3_2 = f3_2 * (long) f3;
460
+ long f3f4_2 = f3_2 * (long) f4;
461
+ long f3f5_4 = f3_2 * (long) f5_2;
462
+ long f3f6_2 = f3_2 * (long) f6;
463
+ long f3f7_76 = f3_2 * (long) f7_38;
464
+ long f3f8_38 = f3_2 * (long) f8_19;
465
+ long f3f9_76 = f3_2 * (long) f9_38;
466
+ long f4f4 = f4 * (long) f4;
467
+ long f4f5_2 = f4_2 * (long) f5;
468
+ long f4f6_38 = f4_2 * (long) f6_19;
469
+ long f4f7_38 = f4 * (long) f7_38;
470
+ long f4f8_38 = f4_2 * (long) f8_19;
471
+ long f4f9_38 = f4 * (long) f9_38;
472
+ long f5f5_38 = f5 * (long) f5_38;
473
+ long f5f6_38 = f5_2 * (long) f6_19;
474
+ long f5f7_76 = f5_2 * (long) f7_38;
475
+ long f5f8_38 = f5_2 * (long) f8_19;
476
+ long f5f9_76 = f5_2 * (long) f9_38;
477
+ long f6f6_19 = f6 * (long) f6_19;
478
+ long f6f7_38 = f6 * (long) f7_38;
479
+ long f6f8_38 = f6_2 * (long) f8_19;
480
+ long f6f9_38 = f6 * (long) f9_38;
481
+ long f7f7_38 = f7 * (long) f7_38;
482
+ long f7f8_38 = f7_2 * (long) f8_19;
483
+ long f7f9_76 = f7_2 * (long) f9_38;
484
+ long f8f8_19 = f8 * (long) f8_19;
485
+ long f8f9_38 = f8 * (long) f9_38;
486
+ long f9f9_38 = f9 * (long) f9_38;
487
+
488
+ /**
489
+ * Same procedure as in multiply, but this time we have a higher symmetry leading to less summands.
490
+ * e.g. f1f9_76 really stands for f1 * 2^26 * f9 * 2^230 + f9 * 2^230 + f1 * 2^26 congruent 2 * 2 * 19 * f1 * f9 2^0 modulo p.
491
+ */
492
+ long h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
493
+ long h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
494
+ long h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
495
+ long h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
496
+ long h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
497
+ long h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
498
+ long h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
499
+ long h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
500
+ long h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
501
+ long h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
502
+ long carry0;
503
+ long carry1;
504
+ long carry2;
505
+ long carry3;
506
+ long carry4;
507
+ long carry5;
508
+ long carry6;
509
+ long carry7;
510
+ long carry8;
511
+ long carry9;
512
+
513
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
514
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
515
+
516
+ carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
517
+ carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
518
+
519
+ carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
520
+ carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
521
+
522
+ carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
523
+ carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
524
+
525
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
526
+ carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
527
+
528
+ carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
529
+
530
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
531
+
532
+ int[] h = new int[10];
533
+ h[0] = (int) h0;
534
+ h[1] = (int) h1;
535
+ h[2] = (int) h2;
536
+ h[3] = (int) h3;
537
+ h[4] = (int) h4;
538
+ h[5] = (int) h5;
539
+ h[6] = (int) h6;
540
+ h[7] = (int) h7;
541
+ h[8] = (int) h8;
542
+ h[9] = (int) h9;
543
+ return new Ed25519FieldElement(f, h);
544
+ }
545
+
546
+ /**
547
+ * $h = 2 * f * f$
548
+ * <p>
549
+ * Can overlap $h$ with $f$.
550
+ * <p>
551
+ * Preconditions:
552
+ * </p><ul>
553
+ * <li>$|f|$ bounded by $1.65*2^{26},1.65*2^{25},1.65*2^{26},1.65*2^{25},$ etc.
554
+ * </ul><p>
555
+ * Postconditions:
556
+ * </p><ul>
557
+ * <li>$|h|$ bounded by $1.01*2^{25},1.01*2^{24},1.01*2^{25},1.01*2^{24},$ etc.
558
+ * </ul><p>
559
+ * See {@link #multiply(FieldElement)} for discussion
560
+ * of implementation strategy.
561
+ *
562
+ * @return The (reasonably reduced) square of this field element times 2.
563
+ */
564
+ public FieldElement squareAndDouble() {
565
+ int f0 = t[0];
566
+ int f1 = t[1];
567
+ int f2 = t[2];
568
+ int f3 = t[3];
569
+ int f4 = t[4];
570
+ int f5 = t[5];
571
+ int f6 = t[6];
572
+ int f7 = t[7];
573
+ int f8 = t[8];
574
+ int f9 = t[9];
575
+ int f0_2 = 2 * f0;
576
+ int f1_2 = 2 * f1;
577
+ int f2_2 = 2 * f2;
578
+ int f3_2 = 2 * f3;
579
+ int f4_2 = 2 * f4;
580
+ int f5_2 = 2 * f5;
581
+ int f6_2 = 2 * f6;
582
+ int f7_2 = 2 * f7;
583
+ int f5_38 = 38 * f5; /* 1.959375*2^30 */
584
+ int f6_19 = 19 * f6; /* 1.959375*2^30 */
585
+ int f7_38 = 38 * f7; /* 1.959375*2^30 */
586
+ int f8_19 = 19 * f8; /* 1.959375*2^30 */
587
+ int f9_38 = 38 * f9; /* 1.959375*2^30 */
588
+ long f0f0 = f0 * (long) f0;
589
+ long f0f1_2 = f0_2 * (long) f1;
590
+ long f0f2_2 = f0_2 * (long) f2;
591
+ long f0f3_2 = f0_2 * (long) f3;
592
+ long f0f4_2 = f0_2 * (long) f4;
593
+ long f0f5_2 = f0_2 * (long) f5;
594
+ long f0f6_2 = f0_2 * (long) f6;
595
+ long f0f7_2 = f0_2 * (long) f7;
596
+ long f0f8_2 = f0_2 * (long) f8;
597
+ long f0f9_2 = f0_2 * (long) f9;
598
+ long f1f1_2 = f1_2 * (long) f1;
599
+ long f1f2_2 = f1_2 * (long) f2;
600
+ long f1f3_4 = f1_2 * (long) f3_2;
601
+ long f1f4_2 = f1_2 * (long) f4;
602
+ long f1f5_4 = f1_2 * (long) f5_2;
603
+ long f1f6_2 = f1_2 * (long) f6;
604
+ long f1f7_4 = f1_2 * (long) f7_2;
605
+ long f1f8_2 = f1_2 * (long) f8;
606
+ long f1f9_76 = f1_2 * (long) f9_38;
607
+ long f2f2 = f2 * (long) f2;
608
+ long f2f3_2 = f2_2 * (long) f3;
609
+ long f2f4_2 = f2_2 * (long) f4;
610
+ long f2f5_2 = f2_2 * (long) f5;
611
+ long f2f6_2 = f2_2 * (long) f6;
612
+ long f2f7_2 = f2_2 * (long) f7;
613
+ long f2f8_38 = f2_2 * (long) f8_19;
614
+ long f2f9_38 = f2 * (long) f9_38;
615
+ long f3f3_2 = f3_2 * (long) f3;
616
+ long f3f4_2 = f3_2 * (long) f4;
617
+ long f3f5_4 = f3_2 * (long) f5_2;
618
+ long f3f6_2 = f3_2 * (long) f6;
619
+ long f3f7_76 = f3_2 * (long) f7_38;
620
+ long f3f8_38 = f3_2 * (long) f8_19;
621
+ long f3f9_76 = f3_2 * (long) f9_38;
622
+ long f4f4 = f4 * (long) f4;
623
+ long f4f5_2 = f4_2 * (long) f5;
624
+ long f4f6_38 = f4_2 * (long) f6_19;
625
+ long f4f7_38 = f4 * (long) f7_38;
626
+ long f4f8_38 = f4_2 * (long) f8_19;
627
+ long f4f9_38 = f4 * (long) f9_38;
628
+ long f5f5_38 = f5 * (long) f5_38;
629
+ long f5f6_38 = f5_2 * (long) f6_19;
630
+ long f5f7_76 = f5_2 * (long) f7_38;
631
+ long f5f8_38 = f5_2 * (long) f8_19;
632
+ long f5f9_76 = f5_2 * (long) f9_38;
633
+ long f6f6_19 = f6 * (long) f6_19;
634
+ long f6f7_38 = f6 * (long) f7_38;
635
+ long f6f8_38 = f6_2 * (long) f8_19;
636
+ long f6f9_38 = f6 * (long) f9_38;
637
+ long f7f7_38 = f7 * (long) f7_38;
638
+ long f7f8_38 = f7_2 * (long) f8_19;
639
+ long f7f9_76 = f7_2 * (long) f9_38;
640
+ long f8f8_19 = f8 * (long) f8_19;
641
+ long f8f9_38 = f8 * (long) f9_38;
642
+ long f9f9_38 = f9 * (long) f9_38;
643
+ long h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
644
+ long h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
645
+ long h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
646
+ long h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
647
+ long h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
648
+ long h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
649
+ long h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
650
+ long h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
651
+ long h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
652
+ long h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
653
+ long carry0;
654
+ long carry1;
655
+ long carry2;
656
+ long carry3;
657
+ long carry4;
658
+ long carry5;
659
+ long carry6;
660
+ long carry7;
661
+ long carry8;
662
+ long carry9;
663
+
664
+ h0 += h0;
665
+ h1 += h1;
666
+ h2 += h2;
667
+ h3 += h3;
668
+ h4 += h4;
669
+ h5 += h5;
670
+ h6 += h6;
671
+ h7 += h7;
672
+ h8 += h8;
673
+ h9 += h9;
674
+
675
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
676
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
677
+
678
+ carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
679
+ carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
680
+
681
+ carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
682
+ carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
683
+
684
+ carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
685
+ carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
686
+
687
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
688
+ carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
689
+
690
+ carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
691
+
692
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
693
+
694
+ int[] h = new int[10];
695
+ h[0] = (int) h0;
696
+ h[1] = (int) h1;
697
+ h[2] = (int) h2;
698
+ h[3] = (int) h3;
699
+ h[4] = (int) h4;
700
+ h[5] = (int) h5;
701
+ h[6] = (int) h6;
702
+ h[7] = (int) h7;
703
+ h[8] = (int) h8;
704
+ h[9] = (int) h9;
705
+ return new Ed25519FieldElement(f, h);
706
+ }
707
+
708
+ /**
709
+ * Invert this field element.
710
+ * <p>
711
+ * The inverse is found via Fermat's little theorem:<br>
712
+ * $a^p \cong a \mod p$ and therefore $a^{(p-2)} \cong a^{-1} \mod p$
713
+ *
714
+ * @return The inverse of this field element.
715
+ */
716
+ public FieldElement invert() {
717
+ FieldElement t0, t1, t2, t3;
718
+
719
+ // 2 == 2 * 1
720
+ t0 = square();
721
+
722
+ // 4 == 2 * 2
723
+ t1 = t0.square();
724
+
725
+ // 8 == 2 * 4
726
+ t1 = t1.square();
727
+
728
+ // 9 == 8 + 1
729
+ t1 = multiply(t1);
730
+
731
+ // 11 == 9 + 2
732
+ t0 = t0.multiply(t1);
733
+
734
+ // 22 == 2 * 11
735
+ t2 = t0.square();
736
+
737
+ // 31 == 22 + 9
738
+ t1 = t1.multiply(t2);
739
+
740
+ // 2^6 - 2^1
741
+ t2 = t1.square();
742
+
743
+ // 2^10 - 2^5
744
+ for (int i = 1; i < 5; ++i) {
745
+ t2 = t2.square();
746
+ }
747
+
748
+ // 2^10 - 2^0
749
+ t1 = t2.multiply(t1);
750
+
751
+ // 2^11 - 2^1
752
+ t2 = t1.square();
753
+
754
+ // 2^20 - 2^10
755
+ for (int i = 1; i < 10; ++i) {
756
+ t2 = t2.square();
757
+ }
758
+
759
+ // 2^20 - 2^0
760
+ t2 = t2.multiply(t1);
761
+
762
+ // 2^21 - 2^1
763
+ t3 = t2.square();
764
+
765
+ // 2^40 - 2^20
766
+ for (int i = 1; i < 20; ++i) {
767
+ t3 = t3.square();
768
+ }
769
+
770
+ // 2^40 - 2^0
771
+ t2 = t3.multiply(t2);
772
+
773
+ // 2^41 - 2^1
774
+ t2 = t2.square();
775
+
776
+ // 2^50 - 2^10
777
+ for (int i = 1; i < 10; ++i) {
778
+ t2 = t2.square();
779
+ }
780
+
781
+ // 2^50 - 2^0
782
+ t1 = t2.multiply(t1);
783
+
784
+ // 2^51 - 2^1
785
+ t2 = t1.square();
786
+
787
+ // 2^100 - 2^50
788
+ for (int i = 1; i < 50; ++i) {
789
+ t2 = t2.square();
790
+ }
791
+
792
+ // 2^100 - 2^0
793
+ t2 = t2.multiply(t1);
794
+
795
+ // 2^101 - 2^1
796
+ t3 = t2.square();
797
+
798
+ // 2^200 - 2^100
799
+ for (int i = 1; i < 100; ++i) {
800
+ t3 = t3.square();
801
+ }
802
+
803
+ // 2^200 - 2^0
804
+ t2 = t3.multiply(t2);
805
+
806
+ // 2^201 - 2^1
807
+ t2 = t2.square();
808
+
809
+ // 2^250 - 2^50
810
+ for (int i = 1; i < 50; ++i) {
811
+ t2 = t2.square();
812
+ }
813
+
814
+ // 2^250 - 2^0
815
+ t1 = t2.multiply(t1);
816
+
817
+ // 2^251 - 2^1
818
+ t1 = t1.square();
819
+
820
+ // 2^255 - 2^5
821
+ for (int i = 1; i < 5; ++i) {
822
+ t1 = t1.square();
823
+ }
824
+
825
+ // 2^255 - 21
826
+ return t1.multiply(t0);
827
+ }
828
+
829
+ /**
830
+ * Gets this field element to the power of $(2^{252} - 3)$.
831
+ * This is a helper function for calculating the square root.
832
+ * <p>
833
+ * TODO-CR BR: I think it makes sense to have a sqrt function.
834
+ *
835
+ * @return This field element to the power of $(2^{252} - 3)$.
836
+ */
837
+ public FieldElement pow22523() {
838
+ FieldElement t0, t1, t2;
839
+
840
+ // 2 == 2 * 1
841
+ t0 = square();
842
+
843
+ // 4 == 2 * 2
844
+ t1 = t0.square();
845
+
846
+ // 8 == 2 * 4
847
+ t1 = t1.square();
848
+
849
+ // z9 = z1*z8
850
+ t1 = multiply(t1);
851
+
852
+ // 11 == 9 + 2
853
+ t0 = t0.multiply(t1);
854
+
855
+ // 22 == 2 * 11
856
+ t0 = t0.square();
857
+
858
+ // 31 == 22 + 9
859
+ t0 = t1.multiply(t0);
860
+
861
+ // 2^6 - 2^1
862
+ t1 = t0.square();
863
+
864
+ // 2^10 - 2^5
865
+ for (int i = 1; i < 5; ++i) {
866
+ t1 = t1.square();
867
+ }
868
+
869
+ // 2^10 - 2^0
870
+ t0 = t1.multiply(t0);
871
+
872
+ // 2^11 - 2^1
873
+ t1 = t0.square();
874
+
875
+ // 2^20 - 2^10
876
+ for (int i = 1; i < 10; ++i) {
877
+ t1 = t1.square();
878
+ }
879
+
880
+ // 2^20 - 2^0
881
+ t1 = t1.multiply(t0);
882
+
883
+ // 2^21 - 2^1
884
+ t2 = t1.square();
885
+
886
+ // 2^40 - 2^20
887
+ for (int i = 1; i < 20; ++i) {
888
+ t2 = t2.square();
889
+ }
890
+
891
+ // 2^40 - 2^0
892
+ t1 = t2.multiply(t1);
893
+
894
+ // 2^41 - 2^1
895
+ t1 = t1.square();
896
+
897
+ // 2^50 - 2^10
898
+ for (int i = 1; i < 10; ++i) {
899
+ t1 = t1.square();
900
+ }
901
+
902
+ // 2^50 - 2^0
903
+ t0 = t1.multiply(t0);
904
+
905
+ // 2^51 - 2^1
906
+ t1 = t0.square();
907
+
908
+ // 2^100 - 2^50
909
+ for (int i = 1; i < 50; ++i) {
910
+ t1 = t1.square();
911
+ }
912
+
913
+ // 2^100 - 2^0
914
+ t1 = t1.multiply(t0);
915
+
916
+ // 2^101 - 2^1
917
+ t2 = t1.square();
918
+
919
+ // 2^200 - 2^100
920
+ for (int i = 1; i < 100; ++i) {
921
+ t2 = t2.square();
922
+ }
923
+
924
+ // 2^200 - 2^0
925
+ t1 = t2.multiply(t1);
926
+
927
+ // 2^201 - 2^1
928
+ t1 = t1.square();
929
+
930
+ // 2^250 - 2^50
931
+ for (int i = 1; i < 50; ++i) {
932
+ t1 = t1.square();
933
+ }
934
+
935
+ // 2^250 - 2^0
936
+ t0 = t1.multiply(t0);
937
+
938
+ // 2^251 - 2^1
939
+ t0 = t0.square();
940
+
941
+ // 2^252 - 2^2
942
+ t0 = t0.square();
943
+
944
+ // 2^252 - 3
945
+ return multiply(t0);
946
+ }
947
+
948
+ /**
949
+ * Constant-time conditional move. Well, actually it is a conditional copy.
950
+ * Logic is inspired by the SUPERCOP implementation at:
951
+ * https://github.com/floodyberry/supercop/blob/master/crypto_sign/ed25519/ref10/fe_cmov.c
952
+ *
953
+ * @param val the other field element.
954
+ * @param b must be 0 or 1, otherwise results are undefined.
955
+ * @return a copy of this if $b == 0$, or a copy of val if $b == 1$.
956
+ */
957
+ @Override
958
+ public FieldElement cmov(FieldElement val, int b) {
959
+ Ed25519FieldElement that = (Ed25519FieldElement) val;
960
+ b = -b;
961
+ int[] result = new int[10];
962
+ for (int i = 0; i < 10; i++) {
963
+ result[i] = this.t[i];
964
+ int x = this.t[i] ^ that.t[i];
965
+ x &= b;
966
+ result[i] ^= x;
967
+ }
968
+ return new Ed25519FieldElement(this.f, result);
969
+ }
970
+
971
+ @Override
972
+ public int hashCode() {
973
+ return Arrays.hashCode(t);
974
+ }
975
+
976
+ @Override
977
+ public boolean equals(Object obj) {
978
+ if (!(obj instanceof Ed25519FieldElement))
979
+ return false;
980
+ Ed25519FieldElement fe = (Ed25519FieldElement) obj;
981
+ return 1==Utils.equal(toByteArray(), fe.toByteArray());
982
+ }
983
+
984
+ @Override
985
+ public String toString() {
986
+ return "[Ed25519FieldElement val="+Utils.bytesToHex(toByteArray())+"]";
987
+ }
988
+ }