package im.actor.crypto.primitives.curve25519; public class ge_double_scalarmult { //CONVERT #include "ge.h" static public void slide(byte[] r,byte[] a) { int i; int b; int k; for (i = 0;i < 256;++i) { //CONVERT r[i] = 1 & (a[i >> 3] >> (i & 7)); r[i] = (byte)(1 & (a[i >> 3] >>> (i & 7))); } for (i = 0;i < 256;++i) if (r[i] != 0) { for (b = 1;b <= 6 && i + b < 256;++b) { if (r[i + b] != 0) { if (r[i] + (r[i + b] << b) <= 15) { r[i] += r[i + b] << b; r[i + b] = 0; } else if (r[i] - (r[i + b] << b) >= -15) { r[i] -= r[i + b] << b; for (k = i + b;k < 256;++k) { if (r[k] == 0) { r[k] = 1; break; } r[k] = 0; } } else break; } } } } static ge_precomp Bi[]; static { Bi = new ge_precomp[8]; Bi[0] = new ge_precomp( new int[]{ 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, new int[]{ -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, new int[]{ -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 } ); Bi[1] = new ge_precomp( new int[]{ 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, new int[]{ 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, new int[]{ 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 } ); Bi[2] = new ge_precomp( new int[]{ 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, new int[]{ 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, new int[]{ 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 } ); Bi[3] = new ge_precomp( new int[]{ 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, new int[]{ -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, new int[]{ 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 } ); Bi[4] = new ge_precomp( new int[]{ -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, new int[]{ -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, new int[]{ 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 } ); Bi[5] = new ge_precomp( new int[]{ -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, new int[]{ 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, new int[]{ 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 } ); Bi[6] = new ge_precomp( new int[]{ -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, new int[]{ -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, new int[]{ -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 } ); Bi[7] = new ge_precomp( new int[]{ -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, new int[]{ -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, new int[]{ -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 } ); } /* r = a * A + b * B where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ public static void ge_double_scalarmult_vartime(ge_p2 r,byte[] a,ge_p3 A,byte[] b) { byte[] aslide = new byte[256]; byte[] bslide = new byte[256]; ge_cached Ai[] = new ge_cached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ for (int count=0; count < 8; count++) Ai[count] = new ge_cached(); ge_p1p1 t = new ge_p1p1(); ge_p3 u = new ge_p3(); ge_p3 A2 = new ge_p3(); int i; slide(aslide,a); slide(bslide,b); ge_p3_to_cached.ge_p3_to_cached(Ai[0],A); ge_p3_dbl.ge_p3_dbl(t,A); ge_p1p1_to_p3.ge_p1p1_to_p3(A2,t); ge_add.ge_add(t,A2,Ai[0]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[1],u); ge_add.ge_add(t,A2,Ai[1]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[2],u); ge_add.ge_add(t,A2,Ai[2]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[3],u); ge_add.ge_add(t,A2,Ai[3]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[4],u); ge_add.ge_add(t,A2,Ai[4]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[5],u); ge_add.ge_add(t,A2,Ai[5]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[6],u); ge_add.ge_add(t,A2,Ai[6]); ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_p3_to_cached.ge_p3_to_cached(Ai[7],u); ge_p2_0.ge_p2_0(r); for (i = 255;i >= 0;--i) { if (aslide[i] !=0 || bslide[i] != 0) break; } for (;i >= 0;--i) { ge_p2_dbl.ge_p2_dbl(t,r); if (aslide[i] > 0) { ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_add.ge_add(t,u,Ai[aslide[i]/2]); } else if (aslide[i] < 0) { ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_sub.ge_sub(t,u,Ai[(-aslide[i])/2]); } if (bslide[i] > 0) { ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_madd.ge_madd(t,u,Bi[bslide[i]/2]); } else if (bslide[i] < 0) { ge_p1p1_to_p3.ge_p1p1_to_p3(u,t); ge_msub.ge_msub(t,u,Bi[(-bslide[i])/2]); } ge_p1p1_to_p2.ge_p1p1_to_p2(r,t); } } }