private static GroupElementP1 Madd(ref GroupElementP3 p, ref GroupElementP4 q) { var t0 = FieldElementOperations.Add(ref p.Z, ref p.Z); /* D = 2*Z1 */ var r = new GroupElementP1(); /* YpX1 = Y1+X1 */ r.X = FieldElementOperations.Add(ref p.Y, ref p.X); /* YmX1 = Y1-X1 */ r.Y = FieldElementOperations.Sub(ref p.Y, ref p.X); /* A = YpX1*ypx2 */ r.Z = FieldElementOperations.Multiplication(ref r.X, ref q.YplusX); /* B = YmX1*ymx2 */ r.Y = FieldElementOperations.Multiplication(ref r.Y, ref q.YminusX); /* C = xy2d2*T1 */ r.T = FieldElementOperations.Multiplication(ref q.XY2D, ref p.T); /* X3 = A-B */ r.X = FieldElementOperations.Sub(ref r.Z, ref r.Y); /* Y3 = A+B */ r.Y = FieldElementOperations.Add(ref r.Z, ref r.Y); /* Z3 = D+C */ r.Z = FieldElementOperations.Add(ref t0, ref r.T); /* T3 = D-C */ r.T = FieldElementOperations.Sub(ref t0, ref r.T); return(r); }
private static GroupElementP1 P2ToP1(ref GroupElementP2 p) { var r = new GroupElementP1(); /* XX=X1^2 */ r.X = FieldElementOperations.Squared(ref p.X); /* YY=Y1^2 */ r.Z = FieldElementOperations.Squared(ref p.Y); /* B=2*Z1^2 */ r.T = FieldElementOperations.DoubleSquare(ref p.Z); /* A=X1+Y1 */ r.Y = FieldElementOperations.Add(ref p.X, ref p.Y); /* AA=A^2 */ var t0 = FieldElementOperations.Squared(ref r.Y); /* Y3=YY+XX */ r.Y = FieldElementOperations.Add(ref r.Z, ref r.X); /* Z3=YY-XX */ r.Z = FieldElementOperations.Sub(ref r.Z, ref r.X); /* X3=AA-Y3 */ r.X = FieldElementOperations.Sub(ref t0, ref r.Y); /* T3=B-Z3 */ r.T = FieldElementOperations.Sub(ref r.T, ref r.Z); return(r); }
private static GroupElementP3 P1ToP3(ref GroupElementP1 p) => new GroupElementP3 { X = FieldElementOperations.Multiplication(ref p.X, ref p.T), Y = FieldElementOperations.Multiplication(ref p.Y, ref p.Z), Z = FieldElementOperations.Multiplication(ref p.Z, ref p.T), T = FieldElementOperations.Multiplication(ref p.X, ref p.Y) };
private static GroupElementP4 Select(int pos, sbyte b) { GroupElementP4 t; GroupElementP4 minust; var bnegative = Negative(b); var babs = (byte)(b - ((-bnegative & b) << 1)); t = new GroupElementP4 { YplusX = FieldElementOperations.Set1(), YminusX = FieldElementOperations.Set1(), XY2D = FieldElementOperations.Set0() }; var table = LookupTables.Base[pos]; Cmov(ref t, ref table[0], Equal(babs, 1)); Cmov(ref t, ref table[1], Equal(babs, 2)); Cmov(ref t, ref table[2], Equal(babs, 3)); Cmov(ref t, ref table[3], Equal(babs, 4)); Cmov(ref t, ref table[4], Equal(babs, 5)); Cmov(ref t, ref table[5], Equal(babs, 6)); Cmov(ref t, ref table[6], Equal(babs, 7)); Cmov(ref t, ref table[7], Equal(babs, 8)); minust.YplusX = t.YminusX; minust.YminusX = t.YplusX; minust.XY2D = FieldElementOperations.Negate(ref t.XY2D); Cmov(ref t, ref minust, bnegative); return(t); }
/// <summary> /// Curve25519 uses a so-called differential-addition chain proposed by Montgomery to multiply a point, /// identified only by its x-coordinate, by a scalar /// </summary> /// <param name="n"></param> /// <param name="p"></param> /// <param name="qSize"></param> /// <returns></returns> internal static byte[] ScalarMultiplication(byte[] n, byte[] p, int qSize) { var q = new byte[qSize]; var p0 = FieldElementOperations.FromBytes(p); var q0 = CalculateLadderStep(n, ref p0); FieldElementOperations.ToBytes(q, ref q0); return(q); }
/// <summary> /// h = a * B /// where a = a[0]+256*a[1]+...+256^31 a[31] /// B is the Ed25519 base point (x,4/5) with x positive. /// /// Preconditions: /// a[31] <= 127 /// </summary> /// <param name="a"></param> /// <param name="offset"></param> /// <returns></returns> internal static GroupElementP3 ScalarMultiplicationBase(byte[] a, int offset = 0) { GroupElementP3 h; var e = new sbyte[64]; sbyte carry; GroupElementP1 r; GroupElementP2 s; GroupElementP4 t; int i; for (i = 0; i < 32; ++i) { e[2 * i + 0] = (sbyte)((a[offset + i] >> 0) & 15); e[2 * i + 1] = (sbyte)((a[offset + i] >> 4) & 15); } /* each e[i] is between 0 and 15 */ /* e[63] is between 0 and 7 */ carry = 0; for (i = 0; i < 63; ++i) { e[i] += carry; carry = (sbyte)(e[i] + 8); carry >>= 4; e[i] -= (sbyte)(carry << 4); } e[63] += carry; /* each e[i] is between -8 and 8 */ h = new GroupElementP3 { X = FieldElementOperations.Set0(), Y = FieldElementOperations.Set1(), Z = FieldElementOperations.Set1(), T = FieldElementOperations.Set0() }; for (i = 1; i < 64; i += 2) { t = Select(i / 2, e[i]); r = Madd(ref h, ref t); h = P1ToP3(ref r); } r = P3ToP1(ref h); s = P1ToP2(ref r); r = P2ToP1(ref s); s = P1ToP2(ref r); r = P2ToP1(ref s); s = P1ToP2(ref r); r = P2ToP1(ref s); h = P1ToP3(ref r); for (i = 0; i < 64; i += 2) { t = Select(i / 2, e[i]); r = Madd(ref h, ref t); h = P1ToP3(ref r); } return(h); }
private static void Cmov(ref GroupElementP4 t, ref GroupElementP4 u, byte b) { FieldElementOperations.Mov(ref t.YplusX, ref u.YplusX, b); FieldElementOperations.Mov(ref t.YminusX, ref u.YminusX, b); FieldElementOperations.Mov(ref t.XY2D, ref u.XY2D, b); }
private static FieldElement CalculateLadderStep(byte[] n, ref FieldElement p, int noffset = 0) { var e = new byte[32]; uint i; FieldElement x1; FieldElement x2; FieldElement z2; FieldElement x3; FieldElement z3; int pos; uint swap; for (i = 0; i < 32; ++i) { e[i] = n[noffset + i]; } ClampOperation.Clamp(e, 0); x1 = p; x2 = FieldElementOperations.Set1(); z2 = FieldElementOperations.Set0(); x3 = x1; z3 = FieldElementOperations.Set1(); swap = 0; for (pos = 254; pos >= 0; --pos) { var b = (uint)(e[pos / 8] >> (pos & 7)); b &= 1; swap ^= b; FieldElementOperations.Swap(ref x2, ref x3, swap); FieldElementOperations.Swap(ref z2, ref z3, swap); swap = b; /* D = X3-Z3 */ var tmp0 = FieldElementOperations.Sub(ref x3, ref z3); /* B = X2-Z2 */ var tmp1 = FieldElementOperations.Sub(ref x2, ref z2); /* A = X2+Z2 */ x2 = FieldElementOperations.Add(ref x2, ref z2); /* C = X3+Z3 */ z2 = FieldElementOperations.Add(ref x3, ref z3); /* DA = D*A */ z3 = FieldElementOperations.Multiplication(ref tmp0, ref x2); /* CB = C*B */ z2 = FieldElementOperations.Multiplication(ref z2, ref tmp1); /* BB = B^2 */ tmp0 = FieldElementOperations.Squared(ref tmp1); /* AA = A^2 */ tmp1 = FieldElementOperations.Squared(ref x2); /* t0 = DA+CB */ x3 = FieldElementOperations.Add(ref z3, ref z2); /* t1 = DA-CB */ z2 = FieldElementOperations.Sub(ref z3, ref z2); /* X4 = AA*BB */ x2 = FieldElementOperations.Multiplication(ref tmp1, ref tmp0); /* E = AA-BB */ tmp1 = FieldElementOperations.Sub(ref tmp1, ref tmp0); /* t2 = t1^2 */ z2 = FieldElementOperations.Squared(ref z2); /* t3 = a24*E */ z3 = FieldElementOperations.Multiply121666(ref tmp1); /* X5 = t0^2 */ x3 = FieldElementOperations.Squared(ref x3); /* t4 = BB+t3 */ tmp0 = FieldElementOperations.Add(ref tmp0, ref z3); /* Z5 = X1*t2 */ z3 = FieldElementOperations.Multiplication(ref x1, ref z2); /* Z4 = E*t4 */ z2 = FieldElementOperations.Multiplication(ref tmp1, ref tmp0); } FieldElementOperations.Swap(ref x2, ref x3, swap); FieldElementOperations.Swap(ref z2, ref z3, swap); z2 = FieldElementOperations.Invert(ref z2); x2 = FieldElementOperations.Multiplication(ref x2, ref z2); var q = x2; Array.Clear(e, 0, e.Length); return(q); }