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,256 @@
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.math.*;
15
+
16
+ /**
17
+ * Helper class for encoding/decoding from/to the 32 byte representation.
18
+ * <p>
19
+ * Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
20
+ */
21
+ public class Ed25519LittleEndianEncoding extends Encoding {
22
+ /**
23
+ * Encodes a given field element in its 32 byte representation. This is done in two steps:
24
+ * <ol>
25
+ * <li>Reduce the value of the field element modulo $p$.
26
+ * <li>Convert the field element to the 32 byte representation.
27
+ * </ol><p>
28
+ * The idea for the modulo $p$ reduction algorithm is as follows:
29
+ * </p>
30
+ * <h2>Assumption:</h2>
31
+ * <ul>
32
+ * <li>$p = 2^{255} - 19$
33
+ * <li>$h = h_0 + 2^{25} * h_1 + 2^{(26+25)} * h_2 + \dots + 2^{230} * h_9$ where $0 \le |h_i| \lt 2^{27}$ for all $i=0,\dots,9$.
34
+ * <li>$h \cong r \mod p$, i.e. $h = r + q * p$ for some suitable $0 \le r \lt p$ and an integer $q$.
35
+ * </ul><p>
36
+ * Then $q = [2^{-255} * (h + 19 * 2^{-25} * h_9 + 1/2)]$ where $[x] = floor(x)$.
37
+ * </p>
38
+ * <h2>Proof:</h2>
39
+ * <p>
40
+ * We begin with some very raw estimation for the bounds of some expressions:
41
+ * <p>
42
+ * $$
43
+ * \begin{equation}
44
+ * |h| \lt 2^{230} * 2^{30} = 2^{260} \Rightarrow |r + q * p| \lt 2^{260} \Rightarrow |q| \lt 2^{10}. \\
45
+ * \Rightarrow -1/4 \le a := 19^2 * 2^{-255} * q \lt 1/4. \\
46
+ * |h - 2^{230} * h_9| = |h_0 + \dots + 2^{204} * h_8| \lt 2^{204} * 2^{30} = 2^{234}. \\
47
+ * \Rightarrow -1/4 \le b := 19 * 2^{-255} * (h - 2^{230} * h_9) \lt 1/4
48
+ * \end{equation}
49
+ * $$
50
+ * <p>
51
+ * Therefore $0 \lt 1/2 - a - b \lt 1$.
52
+ * <p>
53
+ * Set $x := r + 19 * 2^{-255} * r + 1/2 - a - b$. Then:
54
+ * <p>
55
+ * $$
56
+ * 0 \le x \lt 255 - 20 + 19 + 1 = 2^{255} \\
57
+ * \Rightarrow 0 \le 2^{-255} * x \lt 1.
58
+ * $$
59
+ * <p>
60
+ * Since $q$ is an integer we have
61
+ * <p>
62
+ * $$
63
+ * [q + 2^{-255} * x] = q \quad (1)
64
+ * $$
65
+ * <p>
66
+ * Have a closer look at $x$:
67
+ * <p>
68
+ * $$
69
+ * \begin{align}
70
+ * x &amp;= h - q * (2^{255} - 19) + 19 * 2^{-255} * (h - q * (2^{255} - 19)) + 1/2 - 19^2 * 2^{-255} * q - 19 * 2^{-255} * (h - 2^{230} * h_9) \\
71
+ * &amp;= h - q * 2^{255} + 19 * q + 19 * 2^{-255} * h - 19 * q + 19^2 * 2^{-255} * q + 1/2 - 19^2 * 2^{-255} * q - 19 * 2^{-255} * h + 19 * 2^{-25} * h_9 \\
72
+ * &amp;= h + 19 * 2^{-25} * h_9 + 1/2 - q^{255}.
73
+ * \end{align}
74
+ * $$
75
+ * <p>
76
+ * Inserting the expression for $x$ into $(1)$ we get the desired expression for $q$.
77
+ */
78
+ public byte[] encode(FieldElement x) {
79
+ int[] h = ((Ed25519FieldElement)x).t;
80
+ int h0 = h[0];
81
+ int h1 = h[1];
82
+ int h2 = h[2];
83
+ int h3 = h[3];
84
+ int h4 = h[4];
85
+ int h5 = h[5];
86
+ int h6 = h[6];
87
+ int h7 = h[7];
88
+ int h8 = h[8];
89
+ int h9 = h[9];
90
+ int q;
91
+ int carry0;
92
+ int carry1;
93
+ int carry2;
94
+ int carry3;
95
+ int carry4;
96
+ int carry5;
97
+ int carry6;
98
+ int carry7;
99
+ int carry8;
100
+ int carry9;
101
+
102
+ // Step 1:
103
+ // Calculate q
104
+ q = (19 * h9 + (1 << 24)) >> 25;
105
+ q = (h0 + q) >> 26;
106
+ q = (h1 + q) >> 25;
107
+ q = (h2 + q) >> 26;
108
+ q = (h3 + q) >> 25;
109
+ q = (h4 + q) >> 26;
110
+ q = (h5 + q) >> 25;
111
+ q = (h6 + q) >> 26;
112
+ q = (h7 + q) >> 25;
113
+ q = (h8 + q) >> 26;
114
+ q = (h9 + q) >> 25;
115
+
116
+ // r = h - q * p = h - 2^255 * q + 19 * q
117
+ // First add 19 * q then discard the bit 255
118
+ h0 += 19 * q;
119
+
120
+ carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
121
+ carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
122
+ carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
123
+ carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
124
+ carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
125
+ carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
126
+ carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
127
+ carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
128
+ carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
129
+ carry9 = h9 >> 25; h9 -= carry9 << 25;
130
+
131
+ // Step 2 (straight forward conversion):
132
+ byte[] s = new byte[32];
133
+ s[0] = (byte) h0;
134
+ s[1] = (byte) (h0 >> 8);
135
+ s[2] = (byte) (h0 >> 16);
136
+ s[3] = (byte) ((h0 >> 24) | (h1 << 2));
137
+ s[4] = (byte) (h1 >> 6);
138
+ s[5] = (byte) (h1 >> 14);
139
+ s[6] = (byte) ((h1 >> 22) | (h2 << 3));
140
+ s[7] = (byte) (h2 >> 5);
141
+ s[8] = (byte) (h2 >> 13);
142
+ s[9] = (byte) ((h2 >> 21) | (h3 << 5));
143
+ s[10] = (byte) (h3 >> 3);
144
+ s[11] = (byte) (h3 >> 11);
145
+ s[12] = (byte) ((h3 >> 19) | (h4 << 6));
146
+ s[13] = (byte) (h4 >> 2);
147
+ s[14] = (byte) (h4 >> 10);
148
+ s[15] = (byte) (h4 >> 18);
149
+ s[16] = (byte) h5;
150
+ s[17] = (byte) (h5 >> 8);
151
+ s[18] = (byte) (h5 >> 16);
152
+ s[19] = (byte) ((h5 >> 24) | (h6 << 1));
153
+ s[20] = (byte) (h6 >> 7);
154
+ s[21] = (byte) (h6 >> 15);
155
+ s[22] = (byte) ((h6 >> 23) | (h7 << 3));
156
+ s[23] = (byte) (h7 >> 5);
157
+ s[24] = (byte) (h7 >> 13);
158
+ s[25] = (byte) ((h7 >> 21) | (h8 << 4));
159
+ s[26] = (byte) (h8 >> 4);
160
+ s[27] = (byte) (h8 >> 12);
161
+ s[28] = (byte) ((h8 >> 20) | (h9 << 6));
162
+ s[29] = (byte) (h9 >> 2);
163
+ s[30] = (byte) (h9 >> 10);
164
+ s[31] = (byte) (h9 >> 18);
165
+ return s;
166
+ }
167
+
168
+ static int load_3(byte[] in, int offset) {
169
+ int result = in[offset++] & 0xff;
170
+ result |= (in[offset++] & 0xff) << 8;
171
+ result |= (in[offset] & 0xff) << 16;
172
+ return result;
173
+ }
174
+
175
+ static long load_4(byte[] in, int offset) {
176
+ int result = in[offset++] & 0xff;
177
+ result |= (in[offset++] & 0xff) << 8;
178
+ result |= (in[offset++] & 0xff) << 16;
179
+ result |= in[offset] << 24;
180
+ return ((long)result) & 0xffffffffL;
181
+ }
182
+
183
+ /**
184
+ * Decodes a given field element in its 10 byte $2^{25.5}$ representation.
185
+ *
186
+ * @param in The 32 byte representation.
187
+ * @return The field element in its $2^{25.5}$ bit representation.
188
+ */
189
+ public FieldElement decode(byte[] in) {
190
+ long h0 = load_4(in, 0);
191
+ long h1 = load_3(in, 4) << 6;
192
+ long h2 = load_3(in, 7) << 5;
193
+ long h3 = load_3(in, 10) << 3;
194
+ long h4 = load_3(in, 13) << 2;
195
+ long h5 = load_4(in, 16);
196
+ long h6 = load_3(in, 20) << 7;
197
+ long h7 = load_3(in, 23) << 5;
198
+ long h8 = load_3(in, 26) << 4;
199
+ long h9 = (load_3(in, 29) & 0x7FFFFF) << 2;
200
+ long carry0;
201
+ long carry1;
202
+ long carry2;
203
+ long carry3;
204
+ long carry4;
205
+ long carry5;
206
+ long carry6;
207
+ long carry7;
208
+ long carry8;
209
+ long carry9;
210
+
211
+ // Remember: 2^255 congruent 19 modulo p
212
+ carry9 = (h9 + (long) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
213
+ carry1 = (h1 + (long) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
214
+ carry3 = (h3 + (long) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
215
+ carry5 = (h5 + (long) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
216
+ carry7 = (h7 + (long) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
217
+
218
+ carry0 = (h0 + (long) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
219
+ carry2 = (h2 + (long) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
220
+ carry4 = (h4 + (long) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
221
+ carry6 = (h6 + (long) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
222
+ carry8 = (h8 + (long) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
223
+
224
+ int[] h = new int[10];
225
+ h[0] = (int) h0;
226
+ h[1] = (int) h1;
227
+ h[2] = (int) h2;
228
+ h[3] = (int) h3;
229
+ h[4] = (int) h4;
230
+ h[5] = (int) h5;
231
+ h[6] = (int) h6;
232
+ h[7] = (int) h7;
233
+ h[8] = (int) h8;
234
+ h[9] = (int) h9;
235
+ return new Ed25519FieldElement(f, h);
236
+ }
237
+
238
+ /**
239
+ * Is the FieldElement negative in this encoding?
240
+ * <p>
241
+ * Return true if $x$ is in $\{1,3,5,\dots,q-2\}$<br>
242
+ * Return false if $x$ is in $\{0,2,4,\dots,q-1\}$
243
+ * <p>
244
+ * Preconditions:
245
+ * </p><ul>
246
+ * <li>$|x|$ bounded by $1.1*2^{26},1.1*2^{25},1.1*2^{26},1.1*2^{25}$, etc.
247
+ * </ul>
248
+ *
249
+ * @return true if $x$ is in $\{1,3,5,\dots,q-2\}$, false otherwise.
250
+ */
251
+ public boolean isNegative(FieldElement x) {
252
+ byte[] s = encode(x);
253
+ return (s[0] & 1) != 0;
254
+ }
255
+
256
+ }
@@ -0,0 +1,693 @@
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.math.ScalarOps;
15
+ import static net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding.load_3;
16
+ import static net.i2p.crypto.eddsa.math.ed25519.Ed25519LittleEndianEncoding.load_4;
17
+
18
+ /**
19
+ * Class for reducing a huge integer modulo the group order q and
20
+ * doing a combined multiply plus add plus reduce operation.
21
+ * <p>
22
+ * $q = 2^{252} + 27742317777372353535851937790883648493$.
23
+ * <p>
24
+ * Reviewed/commented by Bloody Rookie (nemproject@gmx.de)
25
+ */
26
+ public class Ed25519ScalarOps implements ScalarOps {
27
+
28
+ /**
29
+ * Reduction modulo the group order $q$.
30
+ * <p>
31
+ * Input:
32
+ * $s[0]+256*s[1]+\dots+256^{63}*s[63] = s$
33
+ * <p>
34
+ * Output:
35
+ * $s[0]+256*s[1]+\dots+256^{31}*s[31] = s \bmod q$
36
+ * where $q = 2^{252} + 27742317777372353535851937790883648493$.
37
+ */
38
+ public byte[] reduce(byte[] s) {
39
+ // s0,..., s22 have 21 bits, s23 has 29 bits
40
+ long s0 = 0x1FFFFF & load_3(s, 0);
41
+ long s1 = 0x1FFFFF & (load_4(s, 2) >> 5);
42
+ long s2 = 0x1FFFFF & (load_3(s, 5) >> 2);
43
+ long s3 = 0x1FFFFF & (load_4(s, 7) >> 7);
44
+ long s4 = 0x1FFFFF & (load_4(s, 10) >> 4);
45
+ long s5 = 0x1FFFFF & (load_3(s, 13) >> 1);
46
+ long s6 = 0x1FFFFF & (load_4(s, 15) >> 6);
47
+ long s7 = 0x1FFFFF & (load_3(s, 18) >> 3);
48
+ long s8 = 0x1FFFFF & load_3(s, 21);
49
+ long s9 = 0x1FFFFF & (load_4(s, 23) >> 5);
50
+ long s10 = 0x1FFFFF & (load_3(s, 26) >> 2);
51
+ long s11 = 0x1FFFFF & (load_4(s, 28) >> 7);
52
+ long s12 = 0x1FFFFF & (load_4(s, 31) >> 4);
53
+ long s13 = 0x1FFFFF & (load_3(s, 34) >> 1);
54
+ long s14 = 0x1FFFFF & (load_4(s, 36) >> 6);
55
+ long s15 = 0x1FFFFF & (load_3(s, 39) >> 3);
56
+ long s16 = 0x1FFFFF & load_3(s, 42);
57
+ long s17 = 0x1FFFFF & (load_4(s, 44) >> 5);
58
+ long s18 = 0x1FFFFF & (load_3(s, 47) >> 2);
59
+ long s19 = 0x1FFFFF & (load_4(s, 49) >> 7);
60
+ long s20 = 0x1FFFFF & (load_4(s, 52) >> 4);
61
+ long s21 = 0x1FFFFF & (load_3(s, 55) >> 1);
62
+ long s22 = 0x1FFFFF & (load_4(s, 57) >> 6);
63
+ long s23 = (load_4(s, 60) >> 3);
64
+ long carry0;
65
+ long carry1;
66
+ long carry2;
67
+ long carry3;
68
+ long carry4;
69
+ long carry5;
70
+ long carry6;
71
+ long carry7;
72
+ long carry8;
73
+ long carry9;
74
+ long carry10;
75
+ long carry11;
76
+ long carry12;
77
+ long carry13;
78
+ long carry14;
79
+ long carry15;
80
+ long carry16;
81
+
82
+ /**
83
+ * Lots of magic numbers :)
84
+ * To understand what's going on below, note that
85
+ *
86
+ * (1) q = 2^252 + q0 where q0 = 27742317777372353535851937790883648493.
87
+ * (2) s11 is the coefficient of 2^(11*21), s23 is the coefficient of 2^(^23*21) and 2^252 = 2^((23-11) * 21)).
88
+ * (3) 2^252 congruent -q0 modulo q.
89
+ * (4) -q0 = 666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) - 997805 * 2^(3*21) + 136657 * 2^(4*21) - 683901 * 2^(5*21)
90
+ *
91
+ * Thus
92
+ * s23 * 2^(23*11) = s23 * 2^(12*21) * 2^(11*21) = s3 * 2^252 * 2^(11*21) congruent
93
+ * s23 * (666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) - 997805 * 2^(3*21) + 136657 * 2^(4*21) - 683901 * 2^(5*21)) * 2^(11*21) modulo q =
94
+ * s23 * (666643 * 2^(11*21) + 470296 * 2^(12*21) + 654183 * 2^(13*21) - 997805 * 2^(14*21) + 136657 * 2^(15*21) - 683901 * 2^(16*21)).
95
+ *
96
+ * The same procedure is then applied for s22,...,s18.
97
+ */
98
+ s11 += s23 * 666643;
99
+ s12 += s23 * 470296;
100
+ s13 += s23 * 654183;
101
+ s14 -= s23 * 997805;
102
+ s15 += s23 * 136657;
103
+ s16 -= s23 * 683901;
104
+ // not used again
105
+ //s23 = 0;
106
+
107
+ s10 += s22 * 666643;
108
+ s11 += s22 * 470296;
109
+ s12 += s22 * 654183;
110
+ s13 -= s22 * 997805;
111
+ s14 += s22 * 136657;
112
+ s15 -= s22 * 683901;
113
+ // not used again
114
+ //s22 = 0;
115
+
116
+ s9 += s21 * 666643;
117
+ s10 += s21 * 470296;
118
+ s11 += s21 * 654183;
119
+ s12 -= s21 * 997805;
120
+ s13 += s21 * 136657;
121
+ s14 -= s21 * 683901;
122
+ // not used again
123
+ //s21 = 0;
124
+
125
+ s8 += s20 * 666643;
126
+ s9 += s20 * 470296;
127
+ s10 += s20 * 654183;
128
+ s11 -= s20 * 997805;
129
+ s12 += s20 * 136657;
130
+ s13 -= s20 * 683901;
131
+ // not used again
132
+ //s20 = 0;
133
+
134
+ s7 += s19 * 666643;
135
+ s8 += s19 * 470296;
136
+ s9 += s19 * 654183;
137
+ s10 -= s19 * 997805;
138
+ s11 += s19 * 136657;
139
+ s12 -= s19 * 683901;
140
+ // not used again
141
+ //s19 = 0;
142
+
143
+ s6 += s18 * 666643;
144
+ s7 += s18 * 470296;
145
+ s8 += s18 * 654183;
146
+ s9 -= s18 * 997805;
147
+ s10 += s18 * 136657;
148
+ s11 -= s18 * 683901;
149
+ // not used again
150
+ //s18 = 0;
151
+
152
+ /**
153
+ * Time to reduce the coefficient in order not to get an overflow.
154
+ */
155
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
156
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
157
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
158
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
159
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
160
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
161
+
162
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
163
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
164
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
165
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
166
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
167
+
168
+ /**
169
+ * Continue with above procedure.
170
+ */
171
+ s5 += s17 * 666643;
172
+ s6 += s17 * 470296;
173
+ s7 += s17 * 654183;
174
+ s8 -= s17 * 997805;
175
+ s9 += s17 * 136657;
176
+ s10 -= s17 * 683901;
177
+ // not used again
178
+ //s17 = 0;
179
+
180
+ s4 += s16 * 666643;
181
+ s5 += s16 * 470296;
182
+ s6 += s16 * 654183;
183
+ s7 -= s16 * 997805;
184
+ s8 += s16 * 136657;
185
+ s9 -= s16 * 683901;
186
+ // not used again
187
+ //s16 = 0;
188
+
189
+ s3 += s15 * 666643;
190
+ s4 += s15 * 470296;
191
+ s5 += s15 * 654183;
192
+ s6 -= s15 * 997805;
193
+ s7 += s15 * 136657;
194
+ s8 -= s15 * 683901;
195
+ // not used again
196
+ //s15 = 0;
197
+
198
+ s2 += s14 * 666643;
199
+ s3 += s14 * 470296;
200
+ s4 += s14 * 654183;
201
+ s5 -= s14 * 997805;
202
+ s6 += s14 * 136657;
203
+ s7 -= s14 * 683901;
204
+ // not used again
205
+ //s14 = 0;
206
+
207
+ s1 += s13 * 666643;
208
+ s2 += s13 * 470296;
209
+ s3 += s13 * 654183;
210
+ s4 -= s13 * 997805;
211
+ s5 += s13 * 136657;
212
+ s6 -= s13 * 683901;
213
+ // not used again
214
+ //s13 = 0;
215
+
216
+ s0 += s12 * 666643;
217
+ s1 += s12 * 470296;
218
+ s2 += s12 * 654183;
219
+ s3 -= s12 * 997805;
220
+ s4 += s12 * 136657;
221
+ s5 -= s12 * 683901;
222
+ // set below
223
+ //s12 = 0;
224
+
225
+ /**
226
+ * Reduce coefficients again.
227
+ */
228
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
229
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
230
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
231
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
232
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
233
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
234
+
235
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
236
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
237
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
238
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
239
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
240
+ //carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
241
+ carry11 = (s11 + (1<<20)) >> 21; s12 = carry11; s11 -= carry11 << 21;
242
+
243
+ s0 += s12 * 666643;
244
+ s1 += s12 * 470296;
245
+ s2 += s12 * 654183;
246
+ s3 -= s12 * 997805;
247
+ s4 += s12 * 136657;
248
+ s5 -= s12 * 683901;
249
+ // set below
250
+ //s12 = 0;
251
+
252
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
253
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
254
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
255
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
256
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
257
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
258
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
259
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
260
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
261
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
262
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
263
+ //carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
264
+ carry11 = s11 >> 21; s12 = carry11; s11 -= carry11 << 21;
265
+
266
+ // TODO-CR BR: Is it really needed to do it TWO times? (it doesn't hurt, just a question).
267
+ s0 += s12 * 666643;
268
+ s1 += s12 * 470296;
269
+ s2 += s12 * 654183;
270
+ s3 -= s12 * 997805;
271
+ s4 += s12 * 136657;
272
+ s5 -= s12 * 683901;
273
+ // not used again
274
+ //s12 = 0;
275
+
276
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
277
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
278
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
279
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
280
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
281
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
282
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
283
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
284
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
285
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
286
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
287
+
288
+ // s0, ..., s11 got 21 bits each.
289
+ byte[] result = new byte[32];
290
+ result[0] = (byte) s0;
291
+ result[1] = (byte) (s0 >> 8);
292
+ result[2] = (byte) ((s0 >> 16) | (s1 << 5));
293
+ result[3] = (byte) (s1 >> 3);
294
+ result[4] = (byte) (s1 >> 11);
295
+ result[5] = (byte) ((s1 >> 19) | (s2 << 2));
296
+ result[6] = (byte) (s2 >> 6);
297
+ result[7] = (byte) ((s2 >> 14) | (s3 << 7));
298
+ result[8] = (byte) (s3 >> 1);
299
+ result[9] = (byte) (s3 >> 9);
300
+ result[10] = (byte) ((s3 >> 17) | (s4 << 4));
301
+ result[11] = (byte) (s4 >> 4);
302
+ result[12] = (byte) (s4 >> 12);
303
+ result[13] = (byte) ((s4 >> 20) | (s5 << 1));
304
+ result[14] = (byte) (s5 >> 7);
305
+ result[15] = (byte) ((s5 >> 15) | (s6 << 6));
306
+ result[16] = (byte) (s6 >> 2);
307
+ result[17] = (byte) (s6 >> 10);
308
+ result[18] = (byte) ((s6 >> 18) | (s7 << 3));
309
+ result[19] = (byte) (s7 >> 5);
310
+ result[20] = (byte) (s7 >> 13);
311
+ result[21] = (byte) s8;
312
+ result[22] = (byte) (s8 >> 8);
313
+ result[23] = (byte) ((s8 >> 16) | (s9 << 5));
314
+ result[24] = (byte) (s9 >> 3);
315
+ result[25] = (byte) (s9 >> 11);
316
+ result[26] = (byte) ((s9 >> 19) | (s10 << 2));
317
+ result[27] = (byte) (s10 >> 6);
318
+ result[28] = (byte) ((s10 >> 14) | (s11 << 7));
319
+ result[29] = (byte) (s11 >> 1);
320
+ result[30] = (byte) (s11 >> 9);
321
+ result[31] = (byte) (s11 >> 17);
322
+ return result;
323
+ }
324
+
325
+
326
+ /**
327
+ * $(ab+c) \bmod q$
328
+ * <p>
329
+ * Input:
330
+ * </p><ul>
331
+ * <li>$a[0]+256*a[1]+\dots+256^{31}*a[31] = a$
332
+ * <li>$b[0]+256*b[1]+\dots+256^{31}*b[31] = b$
333
+ * <li>$c[0]+256*c[1]+\dots+256^{31}*c[31] = c$
334
+ * </ul><p>
335
+ * Output:
336
+ * $result[0]+256*result[1]+\dots+256^{31}*result[31] = (ab+c) \bmod q$
337
+ * where $q = 2^{252} + 27742317777372353535851937790883648493$.
338
+ * <p>
339
+ * See the comments in {@link #reduce(byte[])} for an explanation of the algorithm.
340
+ */
341
+ public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c) {
342
+ long a0 = 0x1FFFFF & load_3(a, 0);
343
+ long a1 = 0x1FFFFF & (load_4(a, 2) >> 5);
344
+ long a2 = 0x1FFFFF & (load_3(a, 5) >> 2);
345
+ long a3 = 0x1FFFFF & (load_4(a, 7) >> 7);
346
+ long a4 = 0x1FFFFF & (load_4(a, 10) >> 4);
347
+ long a5 = 0x1FFFFF & (load_3(a, 13) >> 1);
348
+ long a6 = 0x1FFFFF & (load_4(a, 15) >> 6);
349
+ long a7 = 0x1FFFFF & (load_3(a, 18) >> 3);
350
+ long a8 = 0x1FFFFF & load_3(a, 21);
351
+ long a9 = 0x1FFFFF & (load_4(a, 23) >> 5);
352
+ long a10 = 0x1FFFFF & (load_3(a, 26) >> 2);
353
+ long a11 = (load_4(a, 28) >> 7);
354
+ long b0 = 0x1FFFFF & load_3(b, 0);
355
+ long b1 = 0x1FFFFF & (load_4(b, 2) >> 5);
356
+ long b2 = 0x1FFFFF & (load_3(b, 5) >> 2);
357
+ long b3 = 0x1FFFFF & (load_4(b, 7) >> 7);
358
+ long b4 = 0x1FFFFF & (load_4(b, 10) >> 4);
359
+ long b5 = 0x1FFFFF & (load_3(b, 13) >> 1);
360
+ long b6 = 0x1FFFFF & (load_4(b, 15) >> 6);
361
+ long b7 = 0x1FFFFF & (load_3(b, 18) >> 3);
362
+ long b8 = 0x1FFFFF & load_3(b, 21);
363
+ long b9 = 0x1FFFFF & (load_4(b, 23) >> 5);
364
+ long b10 = 0x1FFFFF & (load_3(b, 26) >> 2);
365
+ long b11 = (load_4(b, 28) >> 7);
366
+ long c0 = 0x1FFFFF & load_3(c, 0);
367
+ long c1 = 0x1FFFFF & (load_4(c, 2) >> 5);
368
+ long c2 = 0x1FFFFF & (load_3(c, 5) >> 2);
369
+ long c3 = 0x1FFFFF & (load_4(c, 7) >> 7);
370
+ long c4 = 0x1FFFFF & (load_4(c, 10) >> 4);
371
+ long c5 = 0x1FFFFF & (load_3(c, 13) >> 1);
372
+ long c6 = 0x1FFFFF & (load_4(c, 15) >> 6);
373
+ long c7 = 0x1FFFFF & (load_3(c, 18) >> 3);
374
+ long c8 = 0x1FFFFF & load_3(c, 21);
375
+ long c9 = 0x1FFFFF & (load_4(c, 23) >> 5);
376
+ long c10 = 0x1FFFFF & (load_3(c, 26) >> 2);
377
+ long c11 = (load_4(c, 28) >> 7);
378
+ long s0;
379
+ long s1;
380
+ long s2;
381
+ long s3;
382
+ long s4;
383
+ long s5;
384
+ long s6;
385
+ long s7;
386
+ long s8;
387
+ long s9;
388
+ long s10;
389
+ long s11;
390
+ long s12;
391
+ long s13;
392
+ long s14;
393
+ long s15;
394
+ long s16;
395
+ long s17;
396
+ long s18;
397
+ long s19;
398
+ long s20;
399
+ long s21;
400
+ long s22;
401
+ long s23;
402
+ long carry0;
403
+ long carry1;
404
+ long carry2;
405
+ long carry3;
406
+ long carry4;
407
+ long carry5;
408
+ long carry6;
409
+ long carry7;
410
+ long carry8;
411
+ long carry9;
412
+ long carry10;
413
+ long carry11;
414
+ long carry12;
415
+ long carry13;
416
+ long carry14;
417
+ long carry15;
418
+ long carry16;
419
+ long carry17;
420
+ long carry18;
421
+ long carry19;
422
+ long carry20;
423
+ long carry21;
424
+ long carry22;
425
+
426
+ s0 = c0 + a0*b0;
427
+ s1 = c1 + a0*b1 + a1*b0;
428
+ s2 = c2 + a0*b2 + a1*b1 + a2*b0;
429
+ s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0;
430
+ s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0;
431
+ s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0;
432
+ s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0;
433
+ s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0;
434
+ s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0;
435
+ s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0;
436
+ s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0;
437
+ s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0;
438
+ s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1;
439
+ s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2;
440
+ s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3;
441
+ s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4;
442
+ s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5;
443
+ s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6;
444
+ s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7;
445
+ s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8;
446
+ s20 = a9*b11 + a10*b10 + a11*b9;
447
+ s21 = a10*b11 + a11*b10;
448
+ s22 = a11*b11;
449
+ // set below
450
+ //s23 = 0;
451
+
452
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
453
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
454
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
455
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
456
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
457
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
458
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
459
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
460
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
461
+ carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21;
462
+ carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21;
463
+ //carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21;
464
+ carry22 = (s22 + (1<<20)) >> 21; s23 = carry22; s22 -= carry22 << 21;
465
+
466
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
467
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
468
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
469
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
470
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
471
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
472
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
473
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
474
+ carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21;
475
+ carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21;
476
+ carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21;
477
+
478
+ s11 += s23 * 666643;
479
+ s12 += s23 * 470296;
480
+ s13 += s23 * 654183;
481
+ s14 -= s23 * 997805;
482
+ s15 += s23 * 136657;
483
+ s16 -= s23 * 683901;
484
+ // not used again
485
+ //s23 = 0;
486
+
487
+ s10 += s22 * 666643;
488
+ s11 += s22 * 470296;
489
+ s12 += s22 * 654183;
490
+ s13 -= s22 * 997805;
491
+ s14 += s22 * 136657;
492
+ s15 -= s22 * 683901;
493
+ // not used again
494
+ //s22 = 0;
495
+
496
+ s9 += s21 * 666643;
497
+ s10 += s21 * 470296;
498
+ s11 += s21 * 654183;
499
+ s12 -= s21 * 997805;
500
+ s13 += s21 * 136657;
501
+ s14 -= s21 * 683901;
502
+ // not used again
503
+ //s21 = 0;
504
+
505
+ s8 += s20 * 666643;
506
+ s9 += s20 * 470296;
507
+ s10 += s20 * 654183;
508
+ s11 -= s20 * 997805;
509
+ s12 += s20 * 136657;
510
+ s13 -= s20 * 683901;
511
+ // not used again
512
+ //s20 = 0;
513
+
514
+ s7 += s19 * 666643;
515
+ s8 += s19 * 470296;
516
+ s9 += s19 * 654183;
517
+ s10 -= s19 * 997805;
518
+ s11 += s19 * 136657;
519
+ s12 -= s19 * 683901;
520
+ // not used again
521
+ //s19 = 0;
522
+
523
+ s6 += s18 * 666643;
524
+ s7 += s18 * 470296;
525
+ s8 += s18 * 654183;
526
+ s9 -= s18 * 997805;
527
+ s10 += s18 * 136657;
528
+ s11 -= s18 * 683901;
529
+ // not used again
530
+ //s18 = 0;
531
+
532
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
533
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
534
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
535
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
536
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
537
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
538
+
539
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
540
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
541
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
542
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
543
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
544
+
545
+ s5 += s17 * 666643;
546
+ s6 += s17 * 470296;
547
+ s7 += s17 * 654183;
548
+ s8 -= s17 * 997805;
549
+ s9 += s17 * 136657;
550
+ s10 -= s17 * 683901;
551
+ // not used again
552
+ //s17 = 0;
553
+
554
+ s4 += s16 * 666643;
555
+ s5 += s16 * 470296;
556
+ s6 += s16 * 654183;
557
+ s7 -= s16 * 997805;
558
+ s8 += s16 * 136657;
559
+ s9 -= s16 * 683901;
560
+ // not used again
561
+ //s16 = 0;
562
+
563
+ s3 += s15 * 666643;
564
+ s4 += s15 * 470296;
565
+ s5 += s15 * 654183;
566
+ s6 -= s15 * 997805;
567
+ s7 += s15 * 136657;
568
+ s8 -= s15 * 683901;
569
+ // not used again
570
+ //s15 = 0;
571
+
572
+ s2 += s14 * 666643;
573
+ s3 += s14 * 470296;
574
+ s4 += s14 * 654183;
575
+ s5 -= s14 * 997805;
576
+ s6 += s14 * 136657;
577
+ s7 -= s14 * 683901;
578
+ // not used again
579
+ //s14 = 0;
580
+
581
+ s1 += s13 * 666643;
582
+ s2 += s13 * 470296;
583
+ s3 += s13 * 654183;
584
+ s4 -= s13 * 997805;
585
+ s5 += s13 * 136657;
586
+ s6 -= s13 * 683901;
587
+ // not used again
588
+ //s13 = 0;
589
+
590
+ s0 += s12 * 666643;
591
+ s1 += s12 * 470296;
592
+ s2 += s12 * 654183;
593
+ s3 -= s12 * 997805;
594
+ s4 += s12 * 136657;
595
+ s5 -= s12 * 683901;
596
+ // set below
597
+ //s12 = 0;
598
+
599
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
600
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
601
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
602
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
603
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
604
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
605
+
606
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
607
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
608
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
609
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
610
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
611
+ //carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
612
+ carry11 = (s11 + (1<<20)) >> 21; s12 = carry11; s11 -= carry11 << 21;
613
+
614
+ s0 += s12 * 666643;
615
+ s1 += s12 * 470296;
616
+ s2 += s12 * 654183;
617
+ s3 -= s12 * 997805;
618
+ s4 += s12 * 136657;
619
+ s5 -= s12 * 683901;
620
+ // set below
621
+ //s12 = 0;
622
+
623
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
624
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
625
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
626
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
627
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
628
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
629
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
630
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
631
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
632
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
633
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
634
+ //carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21;
635
+ carry11 = s11 >> 21; s12 = carry11; s11 -= carry11 << 21;
636
+
637
+ s0 += s12 * 666643;
638
+ s1 += s12 * 470296;
639
+ s2 += s12 * 654183;
640
+ s3 -= s12 * 997805;
641
+ s4 += s12 * 136657;
642
+ s5 -= s12 * 683901;
643
+ // not used again
644
+ //s12 = 0;
645
+
646
+ carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
647
+ carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
648
+ carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
649
+ carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
650
+ carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
651
+ carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21;
652
+ carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21;
653
+ carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21;
654
+ carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21;
655
+ carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21;
656
+ carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21;
657
+
658
+ byte[] result = new byte[32];
659
+ result[0] = (byte) s0;
660
+ result[1] = (byte) (s0 >> 8);
661
+ result[2] = (byte) ((s0 >> 16) | (s1 << 5));
662
+ result[3] = (byte) (s1 >> 3);
663
+ result[4] = (byte) (s1 >> 11);
664
+ result[5] = (byte) ((s1 >> 19) | (s2 << 2));
665
+ result[6] = (byte) (s2 >> 6);
666
+ result[7] = (byte) ((s2 >> 14) | (s3 << 7));
667
+ result[8] = (byte) (s3 >> 1);
668
+ result[9] = (byte) (s3 >> 9);
669
+ result[10] = (byte) ((s3 >> 17) | (s4 << 4));
670
+ result[11] = (byte) (s4 >> 4);
671
+ result[12] = (byte) (s4 >> 12);
672
+ result[13] = (byte) ((s4 >> 20) | (s5 << 1));
673
+ result[14] = (byte) (s5 >> 7);
674
+ result[15] = (byte) ((s5 >> 15) | (s6 << 6));
675
+ result[16] = (byte) (s6 >> 2);
676
+ result[17] = (byte) (s6 >> 10);
677
+ result[18] = (byte) ((s6 >> 18) | (s7 << 3));
678
+ result[19] = (byte) (s7 >> 5);
679
+ result[20] = (byte) (s7 >> 13);
680
+ result[21] = (byte) s8;
681
+ result[22] = (byte) (s8 >> 8);
682
+ result[23] = (byte) ((s8 >> 16) | (s9 << 5));
683
+ result[24] = (byte) (s9 >> 3);
684
+ result[25] = (byte) (s9 >> 11);
685
+ result[26] = (byte) ((s9 >> 19) | (s10 << 2));
686
+ result[27] = (byte) (s10 >> 6);
687
+ result[28] = (byte) ((s10 >> 14) | (s11 << 7));
688
+ result[29] = (byte) (s11 >> 1);
689
+ result[30] = (byte) (s11 >> 9);
690
+ result[31] = (byte) (s11 >> 17);
691
+ return result;
692
+ }
693
+ }