1 // Copyright 2017 Google Inc.
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
15 ////////////////////////////////////////////////////////////////////////////////
\r
17 package com.google.crypto.tink.subtle;
\r
19 import static com.google.crypto.tink.subtle.Ed25519Constants.B2;
\r
20 import static com.google.crypto.tink.subtle.Ed25519Constants.B_TABLE;
\r
21 import static com.google.crypto.tink.subtle.Ed25519Constants.D;
\r
22 import static com.google.crypto.tink.subtle.Ed25519Constants.D2;
\r
23 import static com.google.crypto.tink.subtle.Ed25519Constants.SQRTM1;
\r
24 import static com.google.crypto.tink.subtle.Field25519.FIELD_LEN;
\r
25 import static com.google.crypto.tink.subtle.Field25519.LIMB_CNT;
\r
27 import java.security.GeneralSecurityException;
\r
28 import java.security.MessageDigest;
\r
29 import java.util.Arrays;
\r
32 * This implementation is based on the ed25519/ref10 implementation in NaCl.
\r
34 * <p>It implements this twisted Edwards curve:
\r
37 * -x^2 + y^2 = 1 + (-121665 / 121666 mod 2^255-19)*x^2*y^2
\r
40 * @see <a href="https://eprint.iacr.org/2008/013.pdf">Bernstein D.J., Birkner P., Joye M., Lange
\r
41 * T., Peters C. (2008) Twisted Edwards Curves</a>
\r
42 * @see <a href="https://eprint.iacr.org/2008/522.pdf">Hisil H., Wong K.KH., Carter G., Dawson E.
\r
43 * (2008) Twisted Edwards Curves Revisited</a>
\r
45 public final class Ed25519 {
\r
47 public static final int SECRET_KEY_LEN = FIELD_LEN;
\r
48 public static final int PUBLIC_KEY_LEN = FIELD_LEN;
\r
49 public static final int SIGNATURE_LEN = FIELD_LEN * 2;
\r
51 // (x = 0, y = 1) point
\r
52 private static final CachedXYT CACHED_NEUTRAL = new CachedXYT(
\r
53 new long[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
54 new long[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
55 new long[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
\r
56 private static final PartialXYZT NEUTRAL = new PartialXYZT(
\r
57 new XYZ(new long[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
58 new long[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
59 new long[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
\r
60 new long[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0});
\r
63 * Projective point representation (X:Y:Z) satisfying x = X/Z, y = Y/Z
\r
65 * Note that this is referred as ge_p2 in ref10 impl.
\r
66 * Also note that x = X, y = Y and z = Z below following Java coding style.
\r
69 * Koyama K., Tsuruoka Y. (1993) Speeding up Elliptic Cryptosystems by Using a Signed Binary
\r
72 * https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
\r
74 private static class XYZ {
\r
81 this(new long[LIMB_CNT], new long[LIMB_CNT], new long[LIMB_CNT]);
\r
84 XYZ(long[] x, long[] y, long[] z) {
\r
91 x = Arrays.copyOf(xyz.x, LIMB_CNT);
\r
92 y = Arrays.copyOf(xyz.y, LIMB_CNT);
\r
93 z = Arrays.copyOf(xyz.z, LIMB_CNT);
\r
96 XYZ(PartialXYZT partialXYZT) {
\r
98 fromPartialXYZT(this, partialXYZT);
\r
104 static XYZ fromPartialXYZT(XYZ out, PartialXYZT in) {
\r
105 Field25519.mult(out.x, in.xyz.x, in.t);
\r
106 Field25519.mult(out.y, in.xyz.y, in.xyz.z);
\r
107 Field25519.mult(out.z, in.xyz.z, in.t);
\r
112 * Encodes this point to bytes.
\r
115 long[] recip = new long[LIMB_CNT];
\r
116 long[] x = new long[LIMB_CNT];
\r
117 long[] y = new long[LIMB_CNT];
\r
118 Field25519.inverse(recip, z);
\r
119 Field25519.mult(x, this.x, recip);
\r
120 Field25519.mult(y, this.y, recip);
\r
121 byte[] s = Field25519.contract(y);
\r
122 s[31] = (byte) (s[31] ^ (getLsb(x) << 7));
\r
127 * Checks that the point is on curve
\r
129 boolean isOnCurve() {
\r
130 long[] x2 = new long[LIMB_CNT];
\r
131 Field25519.square(x2, x);
\r
132 long[] y2 = new long[LIMB_CNT];
\r
133 Field25519.square(y2, y);
\r
134 long[] z2 = new long[LIMB_CNT];
\r
135 Field25519.square(z2, z);
\r
136 long[] z4 = new long[LIMB_CNT];
\r
137 Field25519.square(z4, z2);
\r
138 long[] lhs = new long[LIMB_CNT];
\r
140 Field25519.sub(lhs, y2, x2);
\r
141 // lhs = z^2 * (y2 - x2)
\r
142 Field25519.mult(lhs, lhs, z2);
\r
143 long[] rhs = new long[LIMB_CNT];
\r
145 Field25519.mult(rhs, x2, y2);
\r
146 // rhs = D * x^2 * y^2
\r
147 Field25519.mult(rhs, rhs, D);
\r
148 // rhs = z^4 + D * x^2 * y^2
\r
149 Field25519.sum(rhs, z4);
\r
150 // z^2 (y^2 - x^2) == z^4 + D * x^2 * y^2
\r
151 return Bytes.equal(Field25519.contract(lhs), Field25519.contract(rhs));
\r
156 * Represents extended projective point representation (X:Y:Z:T) satisfying x = X/Z, y = Y/Z,
\r
159 * Note that this is referred as ge_p3 in ref10 impl.
\r
160 * Also note that t = T below following Java coding style.
\r
163 * Hisil H., Wong K.KH., Carter G., Dawson E. (2008) Twisted Edwards Curves Revisited.
\r
165 * https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html
\r
167 private static class XYZT {
\r
173 this(new XYZ(), new long[LIMB_CNT]);
\r
176 XYZT(XYZ xyz, long[] t) {
\r
181 XYZT(PartialXYZT partialXYZT) {
\r
183 fromPartialXYZT(this, partialXYZT);
\r
189 private static XYZT fromPartialXYZT(XYZT out, PartialXYZT in) {
\r
190 Field25519.mult(out.xyz.x, in.xyz.x, in.t);
\r
191 Field25519.mult(out.xyz.y, in.xyz.y, in.xyz.z);
\r
192 Field25519.mult(out.xyz.z, in.xyz.z, in.t);
\r
193 Field25519.mult(out.t, in.xyz.x, in.xyz.y);
\r
198 * Decodes {@code s} into an extented projective point.
\r
199 * See Section 5.1.3 Decoding in https://tools.ietf.org/html/rfc8032#section-5.1.3
\r
201 private static XYZT fromBytesNegateVarTime(byte[] s) throws GeneralSecurityException {
\r
202 long[] x = new long[LIMB_CNT];
\r
203 long[] y = Field25519.expand(s);
\r
204 long[] z = new long[LIMB_CNT];
\r
206 long[] t = new long[LIMB_CNT];
\r
207 long[] u = new long[LIMB_CNT];
\r
208 long[] v = new long[LIMB_CNT];
\r
209 long[] vxx = new long[LIMB_CNT];
\r
210 long[] check = new long[LIMB_CNT];
\r
211 Field25519.square(u, y);
\r
212 Field25519.mult(v, u, D);
\r
213 Field25519.sub(u, u, z); // u = y^2 - 1
\r
214 Field25519.sum(v, v, z); // v = dy^2 + 1
\r
216 long[] v3 = new long[LIMB_CNT];
\r
217 Field25519.square(v3, v);
\r
218 Field25519.mult(v3, v3, v); // v3 = v^3
\r
219 Field25519.square(x, v3);
\r
220 Field25519.mult(x, x, v);
\r
221 Field25519.mult(x, x, u); // x = uv^7
\r
223 pow2252m3(x, x); // x = (uv^7)^((q-5)/8)
\r
224 Field25519.mult(x, x, v3);
\r
225 Field25519.mult(x, x, u); // x = uv^3(uv^7)^((q-5)/8)
\r
227 Field25519.square(vxx, x);
\r
228 Field25519.mult(vxx, vxx, v);
\r
229 Field25519.sub(check, vxx, u); // vx^2-u
\r
230 if (isNonZeroVarTime(check)) {
\r
231 Field25519.sum(check, vxx, u); // vx^2+u
\r
232 if (isNonZeroVarTime(check)) {
\r
233 throw new GeneralSecurityException("Cannot convert given bytes to extended projective "
\r
234 + "coordinates. No square root exists for modulo 2^255-19");
\r
236 Field25519.mult(x, x, SQRTM1);
\r
239 if (!isNonZeroVarTime(x) && (s[31] & 0xff) >> 7 != 0) {
\r
240 throw new GeneralSecurityException("Cannot convert given bytes to extended projective "
\r
241 + "coordinates. Computed x is zero and encoded x's least significant bit is not zero");
\r
243 if (getLsb(x) == ((s[31] & 0xff) >> 7)) {
\r
247 Field25519.mult(t, x, y);
\r
248 return new XYZT(new XYZ(x, y, z), t);
\r
253 * Partial projective point representation ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
\r
255 * Note that this is referred as complete form in the original ref10 impl (ge_p1p1).
\r
256 * Also note that t = T below following Java coding style.
\r
258 * Although this has the same types as XYZT, it is redefined to have its own type so that it is
\r
259 * readable and 1:1 corresponds to ref10 impl.
\r
261 * Can be converted to XYZT as follows:
\r
262 * X1 = X * T = x * Z * T = x * Z1
\r
263 * Y1 = Y * Z = y * T * Z = y * Z1
\r
264 * Z1 = Z * T = Z * T
\r
265 * T1 = X * Y = x * Z * y * T = x * y * Z1 = X1Y1 / Z1
\r
267 private static class PartialXYZT {
\r
273 this(new XYZ(), new long[LIMB_CNT]);
\r
276 PartialXYZT(XYZ xyz, long[] t) {
\r
281 PartialXYZT(PartialXYZT other) {
\r
282 xyz = new XYZ(other.xyz);
\r
283 t = Arrays.copyOf(other.t, LIMB_CNT);
\r
288 * Corresponds to the caching mentioned in the last paragraph of Section 3.1 of
\r
289 * Hisil H., Wong K.KH., Carter G., Dawson E. (2008) Twisted Edwards Curves Revisited.
\r
292 static class CachedXYT {
\r
294 final long[] yPlusX;
\r
295 final long[] yMinusX;
\r
299 this(new long[LIMB_CNT], new long[LIMB_CNT], new long[LIMB_CNT]);
\r
303 * Creates a cached XYZT with Z = 1
\r
305 * @param yPlusX y + x
\r
306 * @param yMinusX y - x
\r
307 * @param t2d 2d * xy
\r
309 CachedXYT(long[] yPlusX, long[] yMinusX, long[] t2d) {
\r
310 this.yPlusX = yPlusX;
\r
311 this.yMinusX = yMinusX;
\r
315 CachedXYT(CachedXYT other) {
\r
316 yPlusX = Arrays.copyOf(other.yPlusX, LIMB_CNT);
\r
317 yMinusX = Arrays.copyOf(other.yMinusX, LIMB_CNT);
\r
318 t2d = Arrays.copyOf(other.t2d, LIMB_CNT);
\r
321 // z is one implicitly, so this just copies {@code in} to {@code output}.
\r
322 void multByZ(long[] output, long[] in) {
\r
323 System.arraycopy(in, 0, output, 0, LIMB_CNT);
\r
327 * If icopy is 1, copies {@code other} into this point. Time invariant wrt to icopy value.
\r
329 void copyConditional(CachedXYT other, int icopy) {
\r
330 Curve25519.copyConditional(yPlusX, other.yPlusX, icopy);
\r
331 Curve25519.copyConditional(yMinusX, other.yMinusX, icopy);
\r
332 Curve25519.copyConditional(t2d, other.t2d, icopy);
\r
336 private static class CachedXYZT extends CachedXYT {
\r
338 private final long[] z;
\r
341 this(new long[LIMB_CNT], new long[LIMB_CNT], new long[LIMB_CNT], new long[LIMB_CNT]);
\r
345 * ge_p3_to_cached.c
\r
347 CachedXYZT(XYZT xyzt) {
\r
349 Field25519.sum(yPlusX, xyzt.xyz.y, xyzt.xyz.x);
\r
350 Field25519.sub(yMinusX, xyzt.xyz.y, xyzt.xyz.x);
\r
351 System.arraycopy(xyzt.xyz.z, 0, z, 0, LIMB_CNT);
\r
352 Field25519.mult(t2d, xyzt.t, D2);
\r
356 * Creates a cached XYZT
\r
358 * @param yPlusX Y + X
\r
359 * @param yMinusX Y - X
\r
361 * @param t2d 2d * (XY/Z)
\r
363 CachedXYZT(long[] yPlusX, long[] yMinusX, long[] z, long[] t2d) {
\r
364 super(yPlusX, yMinusX, t2d);
\r
369 public void multByZ(long[] output, long[] in) {
\r
370 Field25519.mult(output, in, z);
\r
375 * Addition defined in Section 3.1 of
\r
376 * Hisil H., Wong K.KH., Carter G., Dawson E. (2008) Twisted Edwards Curves Revisited.
\r
378 * Please note that this is a partial of the operation listed there leaving out the final
\r
379 * conversion from PartialXYZT to XYZT.
\r
381 * @param extended extended projective point input
\r
382 * @param cached cached projective point input
\r
384 private static void add(PartialXYZT partialXYZT, XYZT extended, CachedXYT cached) {
\r
385 long[] t = new long[LIMB_CNT];
\r
388 Field25519.sum(partialXYZT.xyz.x, extended.xyz.y, extended.xyz.x);
\r
391 Field25519.sub(partialXYZT.xyz.y, extended.xyz.y, extended.xyz.x);
\r
393 // A = (Y1 - X1) * (Y2 - X2)
\r
394 Field25519.mult(partialXYZT.xyz.y, partialXYZT.xyz.y, cached.yMinusX);
\r
396 // B = (Y1 + X1) * (Y2 + X2)
\r
397 Field25519.mult(partialXYZT.xyz.z, partialXYZT.xyz.x, cached.yPlusX);
\r
399 // C = T1 * 2d * T2 = 2d * T1 * T2 (2d is written as k in the paper)
\r
400 Field25519.mult(partialXYZT.t, extended.t, cached.t2d);
\r
403 cached.multByZ(partialXYZT.xyz.x, extended.xyz.z);
\r
406 Field25519.sum(t, partialXYZT.xyz.x, partialXYZT.xyz.x);
\r
409 Field25519.sub(partialXYZT.xyz.x, partialXYZT.xyz.z, partialXYZT.xyz.y);
\r
412 Field25519.sum(partialXYZT.xyz.y, partialXYZT.xyz.z, partialXYZT.xyz.y);
\r
415 Field25519.sum(partialXYZT.xyz.z, t, partialXYZT.t);
\r
418 Field25519.sub(partialXYZT.t, t, partialXYZT.t);
\r
422 * Based on the addition defined in Section 3.1 of
\r
423 * Hisil H., Wong K.KH., Carter G., Dawson E. (2008) Twisted Edwards Curves Revisited.
\r
425 * Please note that this is a partial of the operation listed there leaving out the final
\r
426 * conversion from PartialXYZT to XYZT.
\r
428 * @param extended extended projective point input
\r
429 * @param cached cached projective point input
\r
431 private static void sub(PartialXYZT partialXYZT, XYZT extended, CachedXYT cached) {
\r
432 long[] t = new long[LIMB_CNT];
\r
435 Field25519.sum(partialXYZT.xyz.x, extended.xyz.y, extended.xyz.x);
\r
438 Field25519.sub(partialXYZT.xyz.y, extended.xyz.y, extended.xyz.x);
\r
440 // A = (Y1 - X1) * (Y2 + X2)
\r
441 Field25519.mult(partialXYZT.xyz.y, partialXYZT.xyz.y, cached.yPlusX);
\r
443 // B = (Y1 + X1) * (Y2 - X2)
\r
444 Field25519.mult(partialXYZT.xyz.z, partialXYZT.xyz.x, cached.yMinusX);
\r
446 // C = T1 * 2d * T2 = 2d * T1 * T2 (2d is written as k in the paper)
\r
447 Field25519.mult(partialXYZT.t, extended.t, cached.t2d);
\r
450 cached.multByZ(partialXYZT.xyz.x, extended.xyz.z);
\r
453 Field25519.sum(t, partialXYZT.xyz.x, partialXYZT.xyz.x);
\r
456 Field25519.sub(partialXYZT.xyz.x, partialXYZT.xyz.z, partialXYZT.xyz.y);
\r
459 Field25519.sum(partialXYZT.xyz.y, partialXYZT.xyz.z, partialXYZT.xyz.y);
\r
462 Field25519.sub(partialXYZT.xyz.z, t, partialXYZT.t);
\r
465 Field25519.sum(partialXYZT.t, t, partialXYZT.t);
\r
469 * Doubles {@code p} and puts the result into this PartialXYZT.
\r
471 * This is based on the addition defined in formula 7 in Section 3.3 of
\r
472 * Hisil H., Wong K.KH., Carter G., Dawson E. (2008) Twisted Edwards Curves Revisited.
\r
474 * Please note that this is a partial of the operation listed there leaving out the final
\r
475 * conversion from PartialXYZT to XYZT and also this fixes a typo in calculation of Y3 and T3 in
\r
476 * the paper, H should be replaced with A+B.
\r
478 private static void doubleXYZ(PartialXYZT partialXYZT, XYZ p) {
\r
479 long[] t0 = new long[LIMB_CNT];
\r
482 Field25519.square(partialXYZT.xyz.x, p.x);
\r
485 Field25519.square(partialXYZT.xyz.z, p.y);
\r
488 Field25519.square(partialXYZT.t, p.z);
\r
491 Field25519.sum(partialXYZT.t, partialXYZT.t, partialXYZT.t);
\r
494 Field25519.sum(partialXYZT.xyz.y, p.x, p.y);
\r
497 Field25519.square(t0, partialXYZT.xyz.y);
\r
500 Field25519.sum(partialXYZT.xyz.y, partialXYZT.xyz.z, partialXYZT.xyz.x);
\r
503 Field25519.sub(partialXYZT.xyz.z, partialXYZT.xyz.z, partialXYZT.xyz.x);
\r
506 Field25519.sub(partialXYZT.xyz.x, t0, partialXYZT.xyz.y);
\r
509 Field25519.sub(partialXYZT.t, partialXYZT.t, partialXYZT.xyz.z);
\r
513 * Doubles {@code p} and puts the result into this PartialXYZT.
\r
515 private static void doubleXYZT(PartialXYZT partialXYZT, XYZT p) {
\r
516 doubleXYZ(partialXYZT, p.xyz);
\r
520 * Compares two byte values in constant time.
\r
522 * Please note that this doesn't reuse {@link Curve25519#eq} method since the below inputs are
\r
525 private static int eq(int a, int b) {
\r
526 int r = ~(a ^ b) & 0xff;
\r
530 return (r >> 7) & 1;
\r
534 * This is a constant time operation where point b*B*256^pos is stored in {@code t}.
\r
535 * When b is 0, t remains the same (i.e., neutral point).
\r
537 * Although B_TABLE[32][8] (B_TABLE[i][j] = (j+1)*B*256^i) has j values in [0, 7], the select
\r
538 * method negates the corresponding point if b is negative (which is straight forward in elliptic
\r
539 * curves by just negating y coordinate). Therefore we can get multiples of B with the half of
\r
540 * memory requirements.
\r
542 * @param t neutral element (i.e., point 0), also serves as output.
\r
543 * @param pos in B[pos][j] = (j+1)*B*256^pos
\r
544 * @param b value in [-8, 8] range.
\r
546 private static void select(CachedXYT t, int pos, byte b) {
\r
547 int bnegative = (b & 0xff) >> 7;
\r
548 int babs = b - (((-bnegative) & b) << 1);
\r
550 t.copyConditional(B_TABLE[pos][0], eq(babs, 1));
\r
551 t.copyConditional(B_TABLE[pos][1], eq(babs, 2));
\r
552 t.copyConditional(B_TABLE[pos][2], eq(babs, 3));
\r
553 t.copyConditional(B_TABLE[pos][3], eq(babs, 4));
\r
554 t.copyConditional(B_TABLE[pos][4], eq(babs, 5));
\r
555 t.copyConditional(B_TABLE[pos][5], eq(babs, 6));
\r
556 t.copyConditional(B_TABLE[pos][6], eq(babs, 7));
\r
557 t.copyConditional(B_TABLE[pos][7], eq(babs, 8));
\r
559 long[] yPlusX = Arrays.copyOf(t.yMinusX, LIMB_CNT);
\r
560 long[] yMinusX = Arrays.copyOf(t.yPlusX, LIMB_CNT);
\r
561 long[] t2d = Arrays.copyOf(t.t2d, LIMB_CNT);
\r
563 CachedXYT minust = new CachedXYT(yPlusX, yMinusX, t2d);
\r
564 t.copyConditional(minust, bnegative);
\r
568 * Computes {@code a}*B
\r
569 * where a = a[0]+256*a[1]+...+256^31 a[31] and
\r
570 * B is the Ed25519 base point (x,4/5) with x positive.
\r
575 * @throws IllegalStateException iff there is arithmetic error.
\r
577 @SuppressWarnings("NarrowingCompoundAssignment")
\r
578 private static XYZ scalarMultWithBase(byte[] a) {
\r
579 byte[] e = new byte[2 * FIELD_LEN];
\r
580 for (int i = 0; i < FIELD_LEN; i++) {
\r
581 e[2 * i + 0] = (byte) (((a[i] & 0xff) >> 0) & 0xf);
\r
582 e[2 * i + 1] = (byte) (((a[i] & 0xff) >> 4) & 0xf);
\r
584 // each e[i] is between 0 and 15
\r
585 // e[63] is between 0 and 7
\r
587 // Rewrite e in a way that each e[i] is in [-8, 8].
\r
588 // This can be done since a[63] is in [0, 7], the carry-over onto the most significant byte
\r
589 // a[63] can be at most 1.
\r
591 for (int i = 0; i < e.length - 1; i++) {
\r
595 e[i] -= carry << 4;
\r
597 e[e.length - 1] += carry;
\r
599 PartialXYZT ret = new PartialXYZT(NEUTRAL);
\r
600 XYZT xyzt = new XYZT();
\r
601 // Although B_TABLE's i can be at most 31 (stores only 32 4bit multiples of B) and we have 64
\r
602 // 4bit values in e array, the below for loop adds cached values by iterating e by two in odd
\r
603 // indices. After the result, we can double the result point 4 times to shift the multiplication
\r
604 // scalar by 4 bits.
\r
605 for (int i = 1; i < e.length; i += 2) {
\r
606 CachedXYT t = new CachedXYT(CACHED_NEUTRAL);
\r
607 select(t, i / 2, e[i]);
\r
608 add(ret, XYZT.fromPartialXYZT(xyzt, ret), t);
\r
611 // Doubles the result 4 times to shift the multiplication scalar 4 bits to get the actual result
\r
612 // for the odd indices in e.
\r
613 XYZ xyz = new XYZ();
\r
614 doubleXYZ(ret, XYZ.fromPartialXYZT(xyz, ret));
\r
615 doubleXYZ(ret, XYZ.fromPartialXYZT(xyz, ret));
\r
616 doubleXYZ(ret, XYZ.fromPartialXYZT(xyz, ret));
\r
617 doubleXYZ(ret, XYZ.fromPartialXYZT(xyz, ret));
\r
619 // Add multiples of B for even indices of e.
\r
620 for (int i = 0; i < e.length; i += 2) {
\r
621 CachedXYT t = new CachedXYT(CACHED_NEUTRAL);
\r
622 select(t, i / 2, e[i]);
\r
623 add(ret, XYZT.fromPartialXYZT(xyzt, ret), t);
\r
626 // This check is to protect against flaws, i.e. if there is a computation error through a
\r
627 // faulty CPU or if the implementation contains a bug.
\r
628 XYZ result = new XYZ(ret);
\r
629 if (!result.isOnCurve()) {
\r
630 throw new IllegalStateException("arithmetic error in scalar multiplication");
\r
636 * Computes {@code a}*B
\r
637 * where a = a[0]+256*a[1]+...+256^31 a[31] and
\r
638 * B is the Ed25519 base point (x,4/5) with x positive.
\r
643 public static byte[] scalarMultWithBaseToBytes(byte[] a) {
\r
644 return scalarMultWithBase(a).toBytes();
\r
647 @SuppressWarnings("NarrowingCompoundAssignment")
\r
648 private static byte[] slide(byte[] a) {
\r
649 byte[] r = new byte[256];
\r
650 // Writes each bit in a[0..31] into r[0..255]:
\r
651 // a = a[0]+256*a[1]+...+256^31*a[31] is equal to
\r
652 // r = r[0]+2*r[1]+...+2^255*r[255]
\r
653 for (int i = 0; i < 256; i++) {
\r
654 r[i] = (byte) (1 & ((a[i >> 3] & 0xff) >> (i & 7)));
\r
657 // Transforms r[i] as odd values in [-15, 15]
\r
658 for (int i = 0; i < 256; i++) {
\r
660 for (int b = 1; b <= 6 && i + b < 256; b++) {
\r
661 if (r[i + b] != 0) {
\r
662 if (r[i] + (r[i + b] << b) <= 15) {
\r
663 r[i] += r[i + b] << b;
\r
665 } else if (r[i] - (r[i + b] << b) >= -15) {
\r
666 r[i] -= r[i + b] << b;
\r
667 for (int k = i + b; k < 256; k++) {
\r
685 * Computes {@code a}*{@code pointA}+{@code b}*B
\r
686 * where a = a[0]+256*a[1]+...+256^31*a[31].
\r
687 * and b = b[0]+256*b[1]+...+256^31*b[31].
\r
688 * B is the Ed25519 base point (x,4/5) with x positive.
\r
690 * Note that execution time varies based on the input since this will only be used in verification
\r
693 private static XYZ doubleScalarMultVarTime(byte[] a, XYZT pointA, byte[] b) {
\r
694 // pointA, 3*pointA, 5*pointA, 7*pointA, 9*pointA, 11*pointA, 13*pointA, 15*pointA
\r
695 CachedXYZT[] pointAArray = new CachedXYZT[8];
\r
696 pointAArray[0] = new CachedXYZT(pointA);
\r
697 PartialXYZT t = new PartialXYZT();
\r
698 doubleXYZT(t, pointA);
\r
699 XYZT doubleA = new XYZT(t);
\r
700 for (int i = 1; i < pointAArray.length; i++) {
\r
701 add(t, doubleA, pointAArray[i - 1]);
\r
702 pointAArray[i] = new CachedXYZT(new XYZT(t));
\r
705 byte[] aSlide = slide(a);
\r
706 byte[] bSlide = slide(b);
\r
707 t = new PartialXYZT(NEUTRAL);
\r
708 XYZT u = new XYZT();
\r
710 for (; i >= 0; i--) {
\r
711 if (aSlide[i] != 0 || bSlide[i] != 0) {
\r
715 for (; i >= 0; i--) {
\r
716 doubleXYZ(t, new XYZ(t));
\r
717 if (aSlide[i] > 0) {
\r
718 add(t, XYZT.fromPartialXYZT(u, t), pointAArray[aSlide[i] / 2]);
\r
719 } else if (aSlide[i] < 0) {
\r
720 sub(t, XYZT.fromPartialXYZT(u, t), pointAArray[-aSlide[i] / 2]);
\r
722 if (bSlide[i] > 0) {
\r
723 add(t, XYZT.fromPartialXYZT(u, t), B2[bSlide[i] / 2]);
\r
724 } else if (bSlide[i] < 0) {
\r
725 sub(t, XYZT.fromPartialXYZT(u, t), B2[-bSlide[i] / 2]);
\r
733 * Returns true if {@code in} is nonzero.
\r
735 * Note that execution time might depend on the input {@code in}.
\r
737 private static boolean isNonZeroVarTime(long[] in) {
\r
738 long[] inCopy = new long[in.length + 1];
\r
739 System.arraycopy(in, 0, inCopy, 0, in.length);
\r
740 Field25519.reduceCoefficients(inCopy);
\r
741 byte[] bytes = Field25519.contract(inCopy);
\r
742 for (byte b : bytes) {
\r
751 * Returns the least significant bit of {@code in}.
\r
753 private static int getLsb(long[] in) {
\r
754 return Field25519.contract(in)[0] & 1;
\r
758 * Negates all values in {@code in} and store it in {@code out}.
\r
760 private static void neg(long[] out, long[] in) {
\r
761 for (int i = 0; i < in.length; i++) {
\r
767 * Computes {@code in}^(2^252-3) mod 2^255-19 and puts the result in {@code out}.
\r
769 private static void pow2252m3(long[] out, long[] in) {
\r
770 long[] t0 = new long[LIMB_CNT];
\r
771 long[] t1 = new long[LIMB_CNT];
\r
772 long[] t2 = new long[LIMB_CNT];
\r
775 Field25519.square(t0, in);
\r
778 Field25519.square(t1, t0);
\r
779 for (int i = 1; i < 2; i++) {
\r
780 Field25519.square(t1, t1);
\r
784 Field25519.mult(t1, in, t1);
\r
787 Field25519.mult(t0, t0, t1);
\r
790 Field25519.square(t0, t0);
\r
793 Field25519.mult(t0, t1, t0);
\r
795 // z_10_5 = z_5_0^2^5
\r
796 Field25519.square(t1, t0);
\r
797 for (int i = 1; i < 5; i++) {
\r
798 Field25519.square(t1, t1);
\r
801 // z_10_0 = z_10_5*z_5_0
\r
802 Field25519.mult(t0, t1, t0);
\r
804 // z_20_10 = z_10_0^2^10
\r
805 Field25519.square(t1, t0);
\r
806 for (int i = 1; i < 10; i++) {
\r
807 Field25519.square(t1, t1);
\r
810 // z_20_0 = z_20_10*z_10_0
\r
811 Field25519.mult(t1, t1, t0);
\r
813 // z_40_20 = z_20_0^2^20
\r
814 Field25519.square(t2, t1);
\r
815 for (int i = 1; i < 20; i++) {
\r
816 Field25519.square(t2, t2);
\r
819 // z_40_0 = z_40_20*z_20_0
\r
820 Field25519.mult(t1, t2, t1);
\r
822 // z_50_10 = z_40_0^2^10
\r
823 Field25519.square(t1, t1);
\r
824 for (int i = 1; i < 10; i++) {
\r
825 Field25519.square(t1, t1);
\r
828 // z_50_0 = z_50_10*z_10_0
\r
829 Field25519.mult(t0, t1, t0);
\r
831 // z_100_50 = z_50_0^2^50
\r
832 Field25519.square(t1, t0);
\r
833 for (int i = 1; i < 50; i++) {
\r
834 Field25519.square(t1, t1);
\r
837 // z_100_0 = z_100_50*z_50_0
\r
838 Field25519.mult(t1, t1, t0);
\r
840 // z_200_100 = z_100_0^2^100
\r
841 Field25519.square(t2, t1);
\r
842 for (int i = 1; i < 100; i++) {
\r
843 Field25519.square(t2, t2);
\r
846 // z_200_0 = z_200_100*z_100_0
\r
847 Field25519.mult(t1, t2, t1);
\r
849 // z_250_50 = z_200_0^2^50
\r
850 Field25519.square(t1, t1);
\r
851 for (int i = 1; i < 50; i++) {
\r
852 Field25519.square(t1, t1);
\r
855 // z_250_0 = z_250_50*z_50_0
\r
856 Field25519.mult(t0, t1, t0);
\r
858 // z_252_2 = z_250_0^2^2
\r
859 Field25519.square(t0, t0);
\r
860 for (int i = 1; i < 2; i++) {
\r
861 Field25519.square(t0, t0);
\r
864 // z_252_3 = z_252_2*z1
\r
865 Field25519.mult(out, t0, in);
\r
869 * Returns 3 bytes of {@code in} starting from {@code idx} in Little-Endian format.
\r
871 private static long load3(byte[] in, int idx) {
\r
873 result = (long) in[idx] & 0xff;
\r
874 result |= (long) (in[idx + 1] & 0xff) << 8;
\r
875 result |= (long) (in[idx + 2] & 0xff) << 16;
\r
880 * Returns 4 bytes of {@code in} starting from {@code idx} in Little-Endian format.
\r
882 private static long load4(byte[] in, int idx) {
\r
883 long result = load3(in, idx);
\r
884 result |= (long) (in[idx + 3] & 0xff) << 24;
\r
890 * s[0]+256*s[1]+...+256^63*s[63] = s
\r
893 * s[0]+256*s[1]+...+256^31*s[31] = s mod l
\r
894 * where l = 2^252 + 27742317777372353535851937790883648493.
\r
895 * Overwrites s in place.
\r
897 public static void reduce(byte[] s) {
\r
899 // 2^252 mod l is equivalent to -27742317777372353535851937790883648493 mod l
\r
900 // Let m = -27742317777372353535851937790883648493
\r
901 // Thus a*2^252+b mod l is equivalent to a*m+b mod l
\r
903 // First s is divided into chunks of 21 bits as follows:
\r
904 // s0+2^21*s1+2^42*s3+...+2^462*s23 = s[0]+256*s[1]+...+256^63*s[63]
\r
905 long s0 = 2097151 & load3(s, 0);
\r
906 long s1 = 2097151 & (load4(s, 2) >> 5);
\r
907 long s2 = 2097151 & (load3(s, 5) >> 2);
\r
908 long s3 = 2097151 & (load4(s, 7) >> 7);
\r
909 long s4 = 2097151 & (load4(s, 10) >> 4);
\r
910 long s5 = 2097151 & (load3(s, 13) >> 1);
\r
911 long s6 = 2097151 & (load4(s, 15) >> 6);
\r
912 long s7 = 2097151 & (load3(s, 18) >> 3);
\r
913 long s8 = 2097151 & load3(s, 21);
\r
914 long s9 = 2097151 & (load4(s, 23) >> 5);
\r
915 long s10 = 2097151 & (load3(s, 26) >> 2);
\r
916 long s11 = 2097151 & (load4(s, 28) >> 7);
\r
917 long s12 = 2097151 & (load4(s, 31) >> 4);
\r
918 long s13 = 2097151 & (load3(s, 34) >> 1);
\r
919 long s14 = 2097151 & (load4(s, 36) >> 6);
\r
920 long s15 = 2097151 & (load3(s, 39) >> 3);
\r
921 long s16 = 2097151 & load3(s, 42);
\r
922 long s17 = 2097151 & (load4(s, 44) >> 5);
\r
923 long s18 = 2097151 & (load3(s, 47) >> 2);
\r
924 long s19 = 2097151 & (load4(s, 49) >> 7);
\r
925 long s20 = 2097151 & (load4(s, 52) >> 4);
\r
926 long s21 = 2097151 & (load3(s, 55) >> 1);
\r
927 long s22 = 2097151 & (load4(s, 57) >> 6);
\r
928 long s23 = (load4(s, 60) >> 3);
\r
947 // s23*2^462 = s23*2^210*2^252 is equivalent to s23*2^210*m in mod l
\r
948 // As m is a 125 bit number, the result needs to scattered to 6 limbs (125/21 ceil is 6)
\r
949 // starting from s11 (s11*2^210)
\r
950 // m = [666643, 470296, 654183, -997805, 136657, -683901] in 21-bit limbs
\r
951 s11 += s23 * 666643;
\r
952 s12 += s23 * 470296;
\r
953 s13 += s23 * 654183;
\r
954 s14 -= s23 * 997805;
\r
955 s15 += s23 * 136657;
\r
956 s16 -= s23 * 683901;
\r
959 s10 += s22 * 666643;
\r
960 s11 += s22 * 470296;
\r
961 s12 += s22 * 654183;
\r
962 s13 -= s22 * 997805;
\r
963 s14 += s22 * 136657;
\r
964 s15 -= s22 * 683901;
\r
967 s9 += s21 * 666643;
\r
968 s10 += s21 * 470296;
\r
969 s11 += s21 * 654183;
\r
970 s12 -= s21 * 997805;
\r
971 s13 += s21 * 136657;
\r
972 s14 -= s21 * 683901;
\r
975 s8 += s20 * 666643;
\r
976 s9 += s20 * 470296;
\r
977 s10 += s20 * 654183;
\r
978 s11 -= s20 * 997805;
\r
979 s12 += s20 * 136657;
\r
980 s13 -= s20 * 683901;
\r
983 s7 += s19 * 666643;
\r
984 s8 += s19 * 470296;
\r
985 s9 += s19 * 654183;
\r
986 s10 -= s19 * 997805;
\r
987 s11 += s19 * 136657;
\r
988 s12 -= s19 * 683901;
\r
991 s6 += s18 * 666643;
\r
992 s7 += s18 * 470296;
\r
993 s8 += s18 * 654183;
\r
994 s9 -= s18 * 997805;
\r
995 s10 += s18 * 136657;
\r
996 s11 -= s18 * 683901;
\r
999 // Reduce the bit length of limbs from s6 to s15 to 21-bits.
\r
1000 carry6 = (s6 + (1 << 20)) >> 21;
\r
1002 s6 -= carry6 << 21;
\r
1003 carry8 = (s8 + (1 << 20)) >> 21;
\r
1005 s8 -= carry8 << 21;
\r
1006 carry10 = (s10 + (1 << 20)) >> 21;
\r
1008 s10 -= carry10 << 21;
\r
1009 carry12 = (s12 + (1 << 20)) >> 21;
\r
1011 s12 -= carry12 << 21;
\r
1012 carry14 = (s14 + (1 << 20)) >> 21;
\r
1014 s14 -= carry14 << 21;
\r
1015 carry16 = (s16 + (1 << 20)) >> 21;
\r
1017 s16 -= carry16 << 21;
\r
1019 carry7 = (s7 + (1 << 20)) >> 21;
\r
1021 s7 -= carry7 << 21;
\r
1022 carry9 = (s9 + (1 << 20)) >> 21;
\r
1024 s9 -= carry9 << 21;
\r
1025 carry11 = (s11 + (1 << 20)) >> 21;
\r
1027 s11 -= carry11 << 21;
\r
1028 carry13 = (s13 + (1 << 20)) >> 21;
\r
1030 s13 -= carry13 << 21;
\r
1031 carry15 = (s15 + (1 << 20)) >> 21;
\r
1033 s15 -= carry15 << 21;
\r
1035 // Resume reduction where we left off.
\r
1036 s5 += s17 * 666643;
\r
1037 s6 += s17 * 470296;
\r
1038 s7 += s17 * 654183;
\r
1039 s8 -= s17 * 997805;
\r
1040 s9 += s17 * 136657;
\r
1041 s10 -= s17 * 683901;
\r
1044 s4 += s16 * 666643;
\r
1045 s5 += s16 * 470296;
\r
1046 s6 += s16 * 654183;
\r
1047 s7 -= s16 * 997805;
\r
1048 s8 += s16 * 136657;
\r
1049 s9 -= s16 * 683901;
\r
1052 s3 += s15 * 666643;
\r
1053 s4 += s15 * 470296;
\r
1054 s5 += s15 * 654183;
\r
1055 s6 -= s15 * 997805;
\r
1056 s7 += s15 * 136657;
\r
1057 s8 -= s15 * 683901;
\r
1060 s2 += s14 * 666643;
\r
1061 s3 += s14 * 470296;
\r
1062 s4 += s14 * 654183;
\r
1063 s5 -= s14 * 997805;
\r
1064 s6 += s14 * 136657;
\r
1065 s7 -= s14 * 683901;
\r
1068 s1 += s13 * 666643;
\r
1069 s2 += s13 * 470296;
\r
1070 s3 += s13 * 654183;
\r
1071 s4 -= s13 * 997805;
\r
1072 s5 += s13 * 136657;
\r
1073 s6 -= s13 * 683901;
\r
1076 s0 += s12 * 666643;
\r
1077 s1 += s12 * 470296;
\r
1078 s2 += s12 * 654183;
\r
1079 s3 -= s12 * 997805;
\r
1080 s4 += s12 * 136657;
\r
1081 s5 -= s12 * 683901;
\r
1084 // Reduce the range of limbs from s0 to s11 to 21-bits.
\r
1085 carry0 = (s0 + (1 << 20)) >> 21;
\r
1087 s0 -= carry0 << 21;
\r
1088 carry2 = (s2 + (1 << 20)) >> 21;
\r
1090 s2 -= carry2 << 21;
\r
1091 carry4 = (s4 + (1 << 20)) >> 21;
\r
1093 s4 -= carry4 << 21;
\r
1094 carry6 = (s6 + (1 << 20)) >> 21;
\r
1096 s6 -= carry6 << 21;
\r
1097 carry8 = (s8 + (1 << 20)) >> 21;
\r
1099 s8 -= carry8 << 21;
\r
1100 carry10 = (s10 + (1 << 20)) >> 21;
\r
1102 s10 -= carry10 << 21;
\r
1104 carry1 = (s1 + (1 << 20)) >> 21;
\r
1106 s1 -= carry1 << 21;
\r
1107 carry3 = (s3 + (1 << 20)) >> 21;
\r
1109 s3 -= carry3 << 21;
\r
1110 carry5 = (s5 + (1 << 20)) >> 21;
\r
1112 s5 -= carry5 << 21;
\r
1113 carry7 = (s7 + (1 << 20)) >> 21;
\r
1115 s7 -= carry7 << 21;
\r
1116 carry9 = (s9 + (1 << 20)) >> 21;
\r
1118 s9 -= carry9 << 21;
\r
1119 carry11 = (s11 + (1 << 20)) >> 21;
\r
1121 s11 -= carry11 << 21;
\r
1123 s0 += s12 * 666643;
\r
1124 s1 += s12 * 470296;
\r
1125 s2 += s12 * 654183;
\r
1126 s3 -= s12 * 997805;
\r
1127 s4 += s12 * 136657;
\r
1128 s5 -= s12 * 683901;
\r
1131 // Carry chain reduction to propagate excess bits from s0 to s5 to the most significant limbs.
\r
1132 carry0 = s0 >> 21;
\r
1134 s0 -= carry0 << 21;
\r
1135 carry1 = s1 >> 21;
\r
1137 s1 -= carry1 << 21;
\r
1138 carry2 = s2 >> 21;
\r
1140 s2 -= carry2 << 21;
\r
1141 carry3 = s3 >> 21;
\r
1143 s3 -= carry3 << 21;
\r
1144 carry4 = s4 >> 21;
\r
1146 s4 -= carry4 << 21;
\r
1147 carry5 = s5 >> 21;
\r
1149 s5 -= carry5 << 21;
\r
1150 carry6 = s6 >> 21;
\r
1152 s6 -= carry6 << 21;
\r
1153 carry7 = s7 >> 21;
\r
1155 s7 -= carry7 << 21;
\r
1156 carry8 = s8 >> 21;
\r
1158 s8 -= carry8 << 21;
\r
1159 carry9 = s9 >> 21;
\r
1161 s9 -= carry9 << 21;
\r
1162 carry10 = s10 >> 21;
\r
1164 s10 -= carry10 << 21;
\r
1165 carry11 = s11 >> 21;
\r
1167 s11 -= carry11 << 21;
\r
1169 // Do one last reduction as s12 might be 1.
\r
1170 s0 += s12 * 666643;
\r
1171 s1 += s12 * 470296;
\r
1172 s2 += s12 * 654183;
\r
1173 s3 -= s12 * 997805;
\r
1174 s4 += s12 * 136657;
\r
1175 s5 -= s12 * 683901;
\r
1178 carry0 = s0 >> 21;
\r
1180 s0 -= carry0 << 21;
\r
1181 carry1 = s1 >> 21;
\r
1183 s1 -= carry1 << 21;
\r
1184 carry2 = s2 >> 21;
\r
1186 s2 -= carry2 << 21;
\r
1187 carry3 = s3 >> 21;
\r
1189 s3 -= carry3 << 21;
\r
1190 carry4 = s4 >> 21;
\r
1192 s4 -= carry4 << 21;
\r
1193 carry5 = s5 >> 21;
\r
1195 s5 -= carry5 << 21;
\r
1196 carry6 = s6 >> 21;
\r
1198 s6 -= carry6 << 21;
\r
1199 carry7 = s7 >> 21;
\r
1201 s7 -= carry7 << 21;
\r
1202 carry8 = s8 >> 21;
\r
1204 s8 -= carry8 << 21;
\r
1205 carry9 = s9 >> 21;
\r
1207 s9 -= carry9 << 21;
\r
1208 carry10 = s10 >> 21;
\r
1210 s10 -= carry10 << 21;
\r
1212 // Serialize the result into the s.
\r
1214 s[1] = (byte) (s0 >> 8);
\r
1215 s[2] = (byte) ((s0 >> 16) | (s1 << 5));
\r
1216 s[3] = (byte) (s1 >> 3);
\r
1217 s[4] = (byte) (s1 >> 11);
\r
1218 s[5] = (byte) ((s1 >> 19) | (s2 << 2));
\r
1219 s[6] = (byte) (s2 >> 6);
\r
1220 s[7] = (byte) ((s2 >> 14) | (s3 << 7));
\r
1221 s[8] = (byte) (s3 >> 1);
\r
1222 s[9] = (byte) (s3 >> 9);
\r
1223 s[10] = (byte) ((s3 >> 17) | (s4 << 4));
\r
1224 s[11] = (byte) (s4 >> 4);
\r
1225 s[12] = (byte) (s4 >> 12);
\r
1226 s[13] = (byte) ((s4 >> 20) | (s5 << 1));
\r
1227 s[14] = (byte) (s5 >> 7);
\r
1228 s[15] = (byte) ((s5 >> 15) | (s6 << 6));
\r
1229 s[16] = (byte) (s6 >> 2);
\r
1230 s[17] = (byte) (s6 >> 10);
\r
1231 s[18] = (byte) ((s6 >> 18) | (s7 << 3));
\r
1232 s[19] = (byte) (s7 >> 5);
\r
1233 s[20] = (byte) (s7 >> 13);
\r
1234 s[21] = (byte) s8;
\r
1235 s[22] = (byte) (s8 >> 8);
\r
1236 s[23] = (byte) ((s8 >> 16) | (s9 << 5));
\r
1237 s[24] = (byte) (s9 >> 3);
\r
1238 s[25] = (byte) (s9 >> 11);
\r
1239 s[26] = (byte) ((s9 >> 19) | (s10 << 2));
\r
1240 s[27] = (byte) (s10 >> 6);
\r
1241 s[28] = (byte) ((s10 >> 14) | (s11 << 7));
\r
1242 s[29] = (byte) (s11 >> 1);
\r
1243 s[30] = (byte) (s11 >> 9);
\r
1244 s[31] = (byte) (s11 >> 17);
\r
1249 * a[0]+256*a[1]+...+256^31*a[31] = a
\r
1250 * b[0]+256*b[1]+...+256^31*b[31] = b
\r
1251 * c[0]+256*c[1]+...+256^31*c[31] = c
\r
1254 * s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
\r
1255 * where l = 2^252 + 27742317777372353535851937790883648493.
\r
1257 public static void mulAdd(byte[] s, byte[] a, byte[] b, byte[] c) {
\r
1258 // This is very similar to Ed25519.reduce, the difference in here is that it computes ab+c
\r
1259 // See Ed25519.reduce for related comments.
\r
1260 long a0 = 2097151 & load3(a, 0);
\r
1261 long a1 = 2097151 & (load4(a, 2) >> 5);
\r
1262 long a2 = 2097151 & (load3(a, 5) >> 2);
\r
1263 long a3 = 2097151 & (load4(a, 7) >> 7);
\r
1264 long a4 = 2097151 & (load4(a, 10) >> 4);
\r
1265 long a5 = 2097151 & (load3(a, 13) >> 1);
\r
1266 long a6 = 2097151 & (load4(a, 15) >> 6);
\r
1267 long a7 = 2097151 & (load3(a, 18) >> 3);
\r
1268 long a8 = 2097151 & load3(a, 21);
\r
1269 long a9 = 2097151 & (load4(a, 23) >> 5);
\r
1270 long a10 = 2097151 & (load3(a, 26) >> 2);
\r
1271 long a11 = (load4(a, 28) >> 7);
\r
1272 long b0 = 2097151 & load3(b, 0);
\r
1273 long b1 = 2097151 & (load4(b, 2) >> 5);
\r
1274 long b2 = 2097151 & (load3(b, 5) >> 2);
\r
1275 long b3 = 2097151 & (load4(b, 7) >> 7);
\r
1276 long b4 = 2097151 & (load4(b, 10) >> 4);
\r
1277 long b5 = 2097151 & (load3(b, 13) >> 1);
\r
1278 long b6 = 2097151 & (load4(b, 15) >> 6);
\r
1279 long b7 = 2097151 & (load3(b, 18) >> 3);
\r
1280 long b8 = 2097151 & load3(b, 21);
\r
1281 long b9 = 2097151 & (load4(b, 23) >> 5);
\r
1282 long b10 = 2097151 & (load3(b, 26) >> 2);
\r
1283 long b11 = (load4(b, 28) >> 7);
\r
1284 long c0 = 2097151 & load3(c, 0);
\r
1285 long c1 = 2097151 & (load4(c, 2) >> 5);
\r
1286 long c2 = 2097151 & (load3(c, 5) >> 2);
\r
1287 long c3 = 2097151 & (load4(c, 7) >> 7);
\r
1288 long c4 = 2097151 & (load4(c, 10) >> 4);
\r
1289 long c5 = 2097151 & (load3(c, 13) >> 1);
\r
1290 long c6 = 2097151 & (load4(c, 15) >> 6);
\r
1291 long c7 = 2097151 & (load3(c, 18) >> 3);
\r
1292 long c8 = 2097151 & load3(c, 21);
\r
1293 long c9 = 2097151 & (load4(c, 23) >> 5);
\r
1294 long c10 = 2097151 & (load3(c, 26) >> 2);
\r
1295 long c11 = (load4(c, 28) >> 7);
\r
1344 s0 = c0 + a0 * b0;
\r
1345 s1 = c1 + a0 * b1 + a1 * b0;
\r
1346 s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
\r
1347 s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
\r
1348 s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
\r
1349 s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
\r
1350 s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
\r
1351 s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
\r
1352 s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1
\r
1354 s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2
\r
1355 + a8 * b1 + a9 * b0;
\r
1356 s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3
\r
1357 + a8 * b2 + a9 * b1 + a10 * b0;
\r
1358 s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4
\r
1359 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
\r
1360 s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3
\r
1361 + a10 * b2 + a11 * b1;
\r
1362 s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3
\r
1364 s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4
\r
1366 s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
\r
1367 s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
\r
1368 s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
\r
1369 s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
\r
1370 s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
\r
1371 s20 = a9 * b11 + a10 * b10 + a11 * b9;
\r
1372 s21 = a10 * b11 + a11 * b10;
\r
1376 carry0 = (s0 + (1 << 20)) >> 21;
\r
1378 s0 -= carry0 << 21;
\r
1379 carry2 = (s2 + (1 << 20)) >> 21;
\r
1381 s2 -= carry2 << 21;
\r
1382 carry4 = (s4 + (1 << 20)) >> 21;
\r
1384 s4 -= carry4 << 21;
\r
1385 carry6 = (s6 + (1 << 20)) >> 21;
\r
1387 s6 -= carry6 << 21;
\r
1388 carry8 = (s8 + (1 << 20)) >> 21;
\r
1390 s8 -= carry8 << 21;
\r
1391 carry10 = (s10 + (1 << 20)) >> 21;
\r
1393 s10 -= carry10 << 21;
\r
1394 carry12 = (s12 + (1 << 20)) >> 21;
\r
1396 s12 -= carry12 << 21;
\r
1397 carry14 = (s14 + (1 << 20)) >> 21;
\r
1399 s14 -= carry14 << 21;
\r
1400 carry16 = (s16 + (1 << 20)) >> 21;
\r
1402 s16 -= carry16 << 21;
\r
1403 carry18 = (s18 + (1 << 20)) >> 21;
\r
1405 s18 -= carry18 << 21;
\r
1406 carry20 = (s20 + (1 << 20)) >> 21;
\r
1408 s20 -= carry20 << 21;
\r
1409 carry22 = (s22 + (1 << 20)) >> 21;
\r
1411 s22 -= carry22 << 21;
\r
1413 carry1 = (s1 + (1 << 20)) >> 21;
\r
1415 s1 -= carry1 << 21;
\r
1416 carry3 = (s3 + (1 << 20)) >> 21;
\r
1418 s3 -= carry3 << 21;
\r
1419 carry5 = (s5 + (1 << 20)) >> 21;
\r
1421 s5 -= carry5 << 21;
\r
1422 carry7 = (s7 + (1 << 20)) >> 21;
\r
1424 s7 -= carry7 << 21;
\r
1425 carry9 = (s9 + (1 << 20)) >> 21;
\r
1427 s9 -= carry9 << 21;
\r
1428 carry11 = (s11 + (1 << 20)) >> 21;
\r
1430 s11 -= carry11 << 21;
\r
1431 carry13 = (s13 + (1 << 20)) >> 21;
\r
1433 s13 -= carry13 << 21;
\r
1434 carry15 = (s15 + (1 << 20)) >> 21;
\r
1436 s15 -= carry15 << 21;
\r
1437 carry17 = (s17 + (1 << 20)) >> 21;
\r
1439 s17 -= carry17 << 21;
\r
1440 carry19 = (s19 + (1 << 20)) >> 21;
\r
1442 s19 -= carry19 << 21;
\r
1443 carry21 = (s21 + (1 << 20)) >> 21;
\r
1445 s21 -= carry21 << 21;
\r
1447 s11 += s23 * 666643;
\r
1448 s12 += s23 * 470296;
\r
1449 s13 += s23 * 654183;
\r
1450 s14 -= s23 * 997805;
\r
1451 s15 += s23 * 136657;
\r
1452 s16 -= s23 * 683901;
\r
1455 s10 += s22 * 666643;
\r
1456 s11 += s22 * 470296;
\r
1457 s12 += s22 * 654183;
\r
1458 s13 -= s22 * 997805;
\r
1459 s14 += s22 * 136657;
\r
1460 s15 -= s22 * 683901;
\r
1463 s9 += s21 * 666643;
\r
1464 s10 += s21 * 470296;
\r
1465 s11 += s21 * 654183;
\r
1466 s12 -= s21 * 997805;
\r
1467 s13 += s21 * 136657;
\r
1468 s14 -= s21 * 683901;
\r
1471 s8 += s20 * 666643;
\r
1472 s9 += s20 * 470296;
\r
1473 s10 += s20 * 654183;
\r
1474 s11 -= s20 * 997805;
\r
1475 s12 += s20 * 136657;
\r
1476 s13 -= s20 * 683901;
\r
1479 s7 += s19 * 666643;
\r
1480 s8 += s19 * 470296;
\r
1481 s9 += s19 * 654183;
\r
1482 s10 -= s19 * 997805;
\r
1483 s11 += s19 * 136657;
\r
1484 s12 -= s19 * 683901;
\r
1487 s6 += s18 * 666643;
\r
1488 s7 += s18 * 470296;
\r
1489 s8 += s18 * 654183;
\r
1490 s9 -= s18 * 997805;
\r
1491 s10 += s18 * 136657;
\r
1492 s11 -= s18 * 683901;
\r
1495 carry6 = (s6 + (1 << 20)) >> 21;
\r
1497 s6 -= carry6 << 21;
\r
1498 carry8 = (s8 + (1 << 20)) >> 21;
\r
1500 s8 -= carry8 << 21;
\r
1501 carry10 = (s10 + (1 << 20)) >> 21;
\r
1503 s10 -= carry10 << 21;
\r
1504 carry12 = (s12 + (1 << 20)) >> 21;
\r
1506 s12 -= carry12 << 21;
\r
1507 carry14 = (s14 + (1 << 20)) >> 21;
\r
1509 s14 -= carry14 << 21;
\r
1510 carry16 = (s16 + (1 << 20)) >> 21;
\r
1512 s16 -= carry16 << 21;
\r
1514 carry7 = (s7 + (1 << 20)) >> 21;
\r
1516 s7 -= carry7 << 21;
\r
1517 carry9 = (s9 + (1 << 20)) >> 21;
\r
1519 s9 -= carry9 << 21;
\r
1520 carry11 = (s11 + (1 << 20)) >> 21;
\r
1522 s11 -= carry11 << 21;
\r
1523 carry13 = (s13 + (1 << 20)) >> 21;
\r
1525 s13 -= carry13 << 21;
\r
1526 carry15 = (s15 + (1 << 20)) >> 21;
\r
1528 s15 -= carry15 << 21;
\r
1530 s5 += s17 * 666643;
\r
1531 s6 += s17 * 470296;
\r
1532 s7 += s17 * 654183;
\r
1533 s8 -= s17 * 997805;
\r
1534 s9 += s17 * 136657;
\r
1535 s10 -= s17 * 683901;
\r
1538 s4 += s16 * 666643;
\r
1539 s5 += s16 * 470296;
\r
1540 s6 += s16 * 654183;
\r
1541 s7 -= s16 * 997805;
\r
1542 s8 += s16 * 136657;
\r
1543 s9 -= s16 * 683901;
\r
1546 s3 += s15 * 666643;
\r
1547 s4 += s15 * 470296;
\r
1548 s5 += s15 * 654183;
\r
1549 s6 -= s15 * 997805;
\r
1550 s7 += s15 * 136657;
\r
1551 s8 -= s15 * 683901;
\r
1554 s2 += s14 * 666643;
\r
1555 s3 += s14 * 470296;
\r
1556 s4 += s14 * 654183;
\r
1557 s5 -= s14 * 997805;
\r
1558 s6 += s14 * 136657;
\r
1559 s7 -= s14 * 683901;
\r
1562 s1 += s13 * 666643;
\r
1563 s2 += s13 * 470296;
\r
1564 s3 += s13 * 654183;
\r
1565 s4 -= s13 * 997805;
\r
1566 s5 += s13 * 136657;
\r
1567 s6 -= s13 * 683901;
\r
1570 s0 += s12 * 666643;
\r
1571 s1 += s12 * 470296;
\r
1572 s2 += s12 * 654183;
\r
1573 s3 -= s12 * 997805;
\r
1574 s4 += s12 * 136657;
\r
1575 s5 -= s12 * 683901;
\r
1578 carry0 = (s0 + (1 << 20)) >> 21;
\r
1580 s0 -= carry0 << 21;
\r
1581 carry2 = (s2 + (1 << 20)) >> 21;
\r
1583 s2 -= carry2 << 21;
\r
1584 carry4 = (s4 + (1 << 20)) >> 21;
\r
1586 s4 -= carry4 << 21;
\r
1587 carry6 = (s6 + (1 << 20)) >> 21;
\r
1589 s6 -= carry6 << 21;
\r
1590 carry8 = (s8 + (1 << 20)) >> 21;
\r
1592 s8 -= carry8 << 21;
\r
1593 carry10 = (s10 + (1 << 20)) >> 21;
\r
1595 s10 -= carry10 << 21;
\r
1597 carry1 = (s1 + (1 << 20)) >> 21;
\r
1599 s1 -= carry1 << 21;
\r
1600 carry3 = (s3 + (1 << 20)) >> 21;
\r
1602 s3 -= carry3 << 21;
\r
1603 carry5 = (s5 + (1 << 20)) >> 21;
\r
1605 s5 -= carry5 << 21;
\r
1606 carry7 = (s7 + (1 << 20)) >> 21;
\r
1608 s7 -= carry7 << 21;
\r
1609 carry9 = (s9 + (1 << 20)) >> 21;
\r
1611 s9 -= carry9 << 21;
\r
1612 carry11 = (s11 + (1 << 20)) >> 21;
\r
1614 s11 -= carry11 << 21;
\r
1616 s0 += s12 * 666643;
\r
1617 s1 += s12 * 470296;
\r
1618 s2 += s12 * 654183;
\r
1619 s3 -= s12 * 997805;
\r
1620 s4 += s12 * 136657;
\r
1621 s5 -= s12 * 683901;
\r
1624 carry0 = s0 >> 21;
\r
1626 s0 -= carry0 << 21;
\r
1627 carry1 = s1 >> 21;
\r
1629 s1 -= carry1 << 21;
\r
1630 carry2 = s2 >> 21;
\r
1632 s2 -= carry2 << 21;
\r
1633 carry3 = s3 >> 21;
\r
1635 s3 -= carry3 << 21;
\r
1636 carry4 = s4 >> 21;
\r
1638 s4 -= carry4 << 21;
\r
1639 carry5 = s5 >> 21;
\r
1641 s5 -= carry5 << 21;
\r
1642 carry6 = s6 >> 21;
\r
1644 s6 -= carry6 << 21;
\r
1645 carry7 = s7 >> 21;
\r
1647 s7 -= carry7 << 21;
\r
1648 carry8 = s8 >> 21;
\r
1650 s8 -= carry8 << 21;
\r
1651 carry9 = s9 >> 21;
\r
1653 s9 -= carry9 << 21;
\r
1654 carry10 = s10 >> 21;
\r
1656 s10 -= carry10 << 21;
\r
1657 carry11 = s11 >> 21;
\r
1659 s11 -= carry11 << 21;
\r
1661 s0 += s12 * 666643;
\r
1662 s1 += s12 * 470296;
\r
1663 s2 += s12 * 654183;
\r
1664 s3 -= s12 * 997805;
\r
1665 s4 += s12 * 136657;
\r
1666 s5 -= s12 * 683901;
\r
1669 carry0 = s0 >> 21;
\r
1671 s0 -= carry0 << 21;
\r
1672 carry1 = s1 >> 21;
\r
1674 s1 -= carry1 << 21;
\r
1675 carry2 = s2 >> 21;
\r
1677 s2 -= carry2 << 21;
\r
1678 carry3 = s3 >> 21;
\r
1680 s3 -= carry3 << 21;
\r
1681 carry4 = s4 >> 21;
\r
1683 s4 -= carry4 << 21;
\r
1684 carry5 = s5 >> 21;
\r
1686 s5 -= carry5 << 21;
\r
1687 carry6 = s6 >> 21;
\r
1689 s6 -= carry6 << 21;
\r
1690 carry7 = s7 >> 21;
\r
1692 s7 -= carry7 << 21;
\r
1693 carry8 = s8 >> 21;
\r
1695 s8 -= carry8 << 21;
\r
1696 carry9 = s9 >> 21;
\r
1698 s9 -= carry9 << 21;
\r
1699 carry10 = s10 >> 21;
\r
1701 s10 -= carry10 << 21;
\r
1704 s[1] = (byte) (s0 >> 8);
\r
1705 s[2] = (byte) ((s0 >> 16) | (s1 << 5));
\r
1706 s[3] = (byte) (s1 >> 3);
\r
1707 s[4] = (byte) (s1 >> 11);
\r
1708 s[5] = (byte) ((s1 >> 19) | (s2 << 2));
\r
1709 s[6] = (byte) (s2 >> 6);
\r
1710 s[7] = (byte) ((s2 >> 14) | (s3 << 7));
\r
1711 s[8] = (byte) (s3 >> 1);
\r
1712 s[9] = (byte) (s3 >> 9);
\r
1713 s[10] = (byte) ((s3 >> 17) | (s4 << 4));
\r
1714 s[11] = (byte) (s4 >> 4);
\r
1715 s[12] = (byte) (s4 >> 12);
\r
1716 s[13] = (byte) ((s4 >> 20) | (s5 << 1));
\r
1717 s[14] = (byte) (s5 >> 7);
\r
1718 s[15] = (byte) ((s5 >> 15) | (s6 << 6));
\r
1719 s[16] = (byte) (s6 >> 2);
\r
1720 s[17] = (byte) (s6 >> 10);
\r
1721 s[18] = (byte) ((s6 >> 18) | (s7 << 3));
\r
1722 s[19] = (byte) (s7 >> 5);
\r
1723 s[20] = (byte) (s7 >> 13);
\r
1724 s[21] = (byte) s8;
\r
1725 s[22] = (byte) (s8 >> 8);
\r
1726 s[23] = (byte) ((s8 >> 16) | (s9 << 5));
\r
1727 s[24] = (byte) (s9 >> 3);
\r
1728 s[25] = (byte) (s9 >> 11);
\r
1729 s[26] = (byte) ((s9 >> 19) | (s10 << 2));
\r
1730 s[27] = (byte) (s10 >> 6);
\r
1731 s[28] = (byte) ((s10 >> 14) | (s11 << 7));
\r
1732 s[29] = (byte) (s11 >> 1);
\r
1733 s[30] = (byte) (s11 >> 9);
\r
1734 s[31] = (byte) (s11 >> 17);
\r
1737 static byte[] getHashedScalar(final byte[] privateKey)
\r
1738 throws GeneralSecurityException {
\r
1739 MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance("SHA-512");
\r
1740 digest.update(privateKey, 0, FIELD_LEN);
\r
1741 byte[] h = digest.digest();
\r
1742 // https://tools.ietf.org/html/rfc8032#section-5.1.2.
\r
1743 // Clear the lowest three bits of the first octet.
\r
1744 h[0] = (byte) (h[0] & 248);
\r
1745 // Clear the highest bit of the last octet.
\r
1746 h[31] = (byte) (h[31] & 127);
\r
1747 // Set the second highest bit if the last octet.
\r
1748 h[31] = (byte) (h[31] | 64);
\r
1753 * Returns the EdDSA signature for the {@code message} based on the {@code hashedPrivateKey}.
\r
1755 * @param message to sign
\r
1756 * @param hashedPrivateKey {@link Ed25519#getHashedScalar(byte[])} of the private key
\r
1757 * @return signature for the {@code message}.
\r
1758 * @throws GeneralSecurityException if there is no SHA-512 algorithm defined in
\r
1759 * {@link EngineFactory}.MESSAGE_DIGEST.
\r
1761 public static byte[] sign(final byte[] message, final byte[] publicKey, final byte[] hashedPrivateKey)
\r
1762 throws GeneralSecurityException {
\r
1763 // Copying the message to make it thread-safe. Otherwise, if the caller modifies the message
\r
1764 // between the first and the second hash then it might leak the private key.
\r
1765 byte[] messageCopy = Arrays.copyOfRange(message, 0, message.length);
\r
1766 MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance("SHA-512");
\r
1767 digest.update(hashedPrivateKey, FIELD_LEN, FIELD_LEN);
\r
1768 digest.update(messageCopy);
\r
1769 byte[] r = digest.digest();
\r
1772 byte[] rB = Arrays.copyOfRange(scalarMultWithBase(r).toBytes(), 0, FIELD_LEN);
\r
1774 digest.update(rB);
\r
1775 digest.update(publicKey);
\r
1776 digest.update(messageCopy);
\r
1777 byte[] hram = digest.digest();
\r
1779 byte[] s = new byte[FIELD_LEN];
\r
1780 mulAdd(s, hram, hashedPrivateKey, r);
\r
1781 return Bytes.concat(rB, s);
\r
1785 // The order of the generator as unsigned bytes in little endian order.
\r
1786 // (2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed, cf. RFC 7748)
\r
1787 static final byte[] GROUP_ORDER = new byte[]{
\r
1788 (byte) 0xed, (byte) 0xd3, (byte) 0xf5, (byte) 0x5c,
\r
1789 (byte) 0x1a, (byte) 0x63, (byte) 0x12, (byte) 0x58,
\r
1790 (byte) 0xd6, (byte) 0x9c, (byte) 0xf7, (byte) 0xa2,
\r
1791 (byte) 0xde, (byte) 0xf9, (byte) 0xde, (byte) 0x14,
\r
1792 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
\r
1793 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
\r
1794 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
\r
1795 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10};
\r
1797 // Checks whether s represents an integer smaller than the order of the group.
\r
1798 // This is needed to ensure that EdDSA signatures are non-malleable, as failing to check
\r
1799 // the range of S allows to modify signatures (cf. RFC 8032, Section 5.2.7 and Section 8.4.)
\r
1800 // @param s an integer in little-endian order.
\r
1801 private static boolean isSmallerThanGroupOrder(byte[] s) {
\r
1802 for (int j = FIELD_LEN - 1; j >= 0; j--) {
\r
1803 // compare unsigned bytes
\r
1804 int a = s[j] & 0xff;
\r
1805 int b = GROUP_ORDER[j] & 0xff;
\r
1814 * Returns true if the EdDSA {@code signature} with {@code message}, can be verified with
\r
1815 * {@code publicKey}.
\r
1817 * @throws GeneralSecurityException if there is no SHA-512 algorithm defined in
\r
1818 * {@link EngineFactory}.MESSAGE_DIGEST.
\r
1820 static boolean verify(final byte[] message, final byte[] signature,
\r
1821 final byte[] publicKey) throws GeneralSecurityException {
\r
1822 if (signature.length != SIGNATURE_LEN) {
\r
1825 byte[] s = Arrays.copyOfRange(signature, FIELD_LEN, SIGNATURE_LEN);
\r
1826 if (!isSmallerThanGroupOrder(s)) {
\r
1829 MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance("SHA-512");
\r
1830 digest.update(signature, 0, FIELD_LEN);
\r
1831 digest.update(publicKey);
\r
1832 digest.update(message);
\r
1833 byte[] h = digest.digest();
\r
1836 XYZT negPublicKey = XYZT.fromBytesNegateVarTime(publicKey);
\r
1837 XYZ xyz = doubleScalarMultVarTime(h, negPublicKey, s);
\r
1838 byte[] expectedR = xyz.toBytes();
\r
1839 for (int i = 0; i < FIELD_LEN; i++) {
\r
1840 if (expectedR[i] != signature[i]) {
\r