internal Projective EcFullSub(Projective s, Projective t) { var u = new Projective() { x = t.x.Clone(), y = p.SubMod(t.y, p, negP), z = t.z.Clone() }; var res = EcFullAdd(s, u); u.Clear(); return(res); }
internal Projective EcDouble(Projective s) { var size = s.x.Length; var t1 = s.x; var t2 = s.y; var t3 = s.z; if (t3.IsZero()) { return(new Projective() { x = new BigInt(1, size), y = new BigInt(1, size), z = new BigInt(0, size) }); } var t4 = modp(t3 * t3); var t5 = t1.SubMod(t4, p, negP); var t4_2 = t1.AddMod(t4, p, negP); var t5_2 = modp(t4_2 * t5); var t4_3 = t5_2.Mul3Mod(p, negP); var t3_2 = modp(t3 * t2); var t3_3 = t3_2.AddMod(t3_2, p, negP); var t2_2 = modp(t2 * t2); var t5_3 = modp(t1 * t2_2); var t5_4 = t5_3.Mul4Mod(p, negP); var t1_2 = modp(t4_3 * t4_3); var t1_3tmp = t1_2.SubMod(t5_4, p, negP); var t1_3 = t1_3tmp.SubMod(t5_4, p, negP); var t2_3 = modp(t2_2 * t2_2); var t2_4 = t2_3.Mul8Mod(p, negP); var t5_5 = t5_4.SubMod(t1_3, p, negP); var t5_6 = modp(t4_3 * t5_5); var t2_5 = t5_6.SubMod(t2_4, p, negP); t4.Clear(); t5.Clear(); t4_2.Clear(); t5_2.Clear(); t4_3.Clear(); t3_2.Clear(); t2_2.Clear(); t5_3.Clear(); t5_4.Clear(); t1_2.Clear(); t1_3tmp.Clear(); t2_3.Clear(); t2_4.Clear(); t5_5.Clear(); t5_6.Clear(); return(new Projective() { x = t1_3, y = t2_5, z = t3_3 }); }
internal Projective EcMult(BigInt d, Projective s) { var size = s.x.Length; if (d.IsZero() || s.z.IsZero()) { return(new Projective() { x = new BigInt(1, size), y = new BigInt(1, size), z = new BigInt(0, size) }); } if (d.IsOne()) { return(s.Clone()); } if (!s.z.IsOne()) { var affine = EcAffinify(s); s = EcProjectify(affine); affine.Clear(); } else { s = s.Clone(); } var r = s.Clone(); var h = d.Mul3(); for (var i = h.BitCount() - 2; i >= 1; i--) { var rTmp = r; r = EcDouble(r); rTmp.Clear(); if (h.BitAt(i) && !d.BitAt(i)) { var u = EcFullAdd(r, s); r.Clear(); r = u; } else if (!h.BitAt(i) && d.BitAt(i)) { var u = EcFullSub(r, s); r.Clear(); r = u; } } h.Clear(); return(r); }
internal Affine EcAffinify(Projective s) { Debug.Assert(!s.z.IsZero()); var lambda = s.z.ModInv(p, negP); var lambda2 = modp(lambda * lambda); var lambda3 = modp(lambda2 * lambda); var res = new Affine() { x = modp(lambda2 * s.x), y = modp(lambda3 * s.y) }; lambda.Clear(); lambda2.Clear(); lambda3.Clear(); return(res); }
internal Projective EcFullAdd(Projective s, Projective t) { if (s.z.IsZero()) { return(t.Clone()); } if (t.z.IsZero()) { return(s.Clone()); } Projective r = EcAdd(s, t); if (r.x.IsZero() && r.y.IsZero() && r.z.IsZero()) { return(EcDouble(s)); } return(r); }
internal Projective EcAdd(Projective s, Projective t) { var size = s.x.Length; var t1 = s.x.Clone(); var t2 = s.y.Clone(); var t3 = s.z.Clone(); var t4 = t.x; var t5 = t.y; var t6 = t.z; if (!t.z.IsOne()) { var t7_ = modp(t6 * t6); Assign(ref t1, modp(t1 * t7_)); Assign(ref t7_, modp(t6 * t7_)); Assign(ref t2, modp(t2 * t7_)); t7_.Clear(); } var t7 = modp(t3 * t3); t4 = modp(t4 * t7); Assign(ref t7, modp(t3 * t7)); t5 = modp(t5 * t7); Assign(ref t4, t1.SubMod(t4, p, negP)); Assign(ref t5, t2.SubMod(t5, p, negP)); if (t4.IsZero()) { t1.Clear(); t2.Clear(); t3.Clear(); t4.Clear(); t7.Clear(); if (t5.IsZero()) { return(new Projective() { x = new BigInt(0, size), y = new BigInt(0, size), z = new BigInt(0, size) }); } else { t5.Clear(); return(new Projective() { x = new BigInt(1, size), y = new BigInt(1, size), z = new BigInt(0, size) }); } } Assign(ref t1, t1.AddMod(t1, p, negP)); Assign(ref t1, t1.SubMod(t4, p, negP)); Assign(ref t2, t2.AddMod(t2, p, negP)); Assign(ref t2, t2.SubMod(t5, p, negP)); if (!t.z.IsOne()) { Assign(ref t3, modp(t3 * t6)); } Assign(ref t3, modp(t3 * t4)); Assign(ref t7, modp(t4 * t4)); Assign(ref t4, modp(t4 * t7)); Assign(ref t7, modp(t1 * t7)); Assign(ref t1, modp(t5 * t5)); Assign(ref t1, t1.SubMod(t7, p, negP)); Assign(ref t7, t7.SubMod(t1, p, negP)); Assign(ref t7, t7.SubMod(t1, p, negP)); Assign(ref t5, modp(t5 * t7)); Assign(ref t4, modp(t2 * t4)); Assign(ref t2, t5.SubMod(t4, p, negP)); t2.Div2(p); t4.Clear(); t5.Clear(); t7.Clear(); return(new Projective() { x = t1, y = t2, z = t3 }); }
internal Projective EcTwinMult(BigInt d0, Projective S, BigInt d1, Projective T) { var d = new BigInt[2] { d0, d1 }; var SpT = EcFullAdd(S, T); var SmT = EcFullSub(S, T); var m0 = d0.BitCount(); var m1 = d1.BitCount(); var m = Math.Max(m0, m1); var c = new int[2][]; c[0] = new int[6] { 0, 0, d0.BitAt(m - 1) ? 1 : 0, d0.BitAt(m - 2) ? 1 : 0, d0.BitAt(m - 3) ? 1 : 0, d0.BitAt(m - 4) ? 1 : 0 }; c[1] = new int[6] { 0, 0, d1.BitAt(m - 1) ? 1 : 0, d1.BitAt(m - 2) ? 1 : 0, d1.BitAt(m - 3) ? 1 : 0, d1.BitAt(m - 4) ? 1 : 0 }; var R = new Projective() { x = new BigInt(1, S.x.Length), y = new BigInt(1, S.x.Length), z = new BigInt(0, S.x.Length) }; int[] h = new int[2], u = new int[2]; for (var k = m; k >= 0; k--) { for (var i = 0; i <= 1; i++) { h[i] = (c[i][1] << 4) + (c[i][2] << 3) + (c[i][3] << 2) + (c[i][4] << 1) + c[i][5]; if (c[i][0] == 1) { h[i] = 31 - h[i]; } } for (var i = 0; i <= 1; i++) { var t = h[1 - i]; int f; if (18 <= t && t < 22) { f = 9; } else if (14 <= t && t < 18) { f = 10; } else if (22 <= t && t < 24) { f = 11; } else if (4 <= t && t < 12) { f = 14; } else { f = 12; } if (h[i] < f) { u[i] = 0; } else { u[i] = (c[i][0] & 1) != 0 ? -1 : 1; } } for (var i = 0; i < 2; i++) { c[i][0] = ((u[i] != 0) ^ (c[i][1] != 0)) ? 1 : 0; c[i][1] = c[i][2]; c[i][2] = c[i][3]; c[i][3] = c[i][4]; c[i][4] = c[i][5]; c[i][5] = d[i].BitAt(k - 5) ? 1 : 0; } R = EcDouble(R); if (u[0] == -1) { if (u[1] == -1) { R = EcFullSub(R, SpT); } else if (u[1] == 0) { R = EcFullSub(R, S); } else { R = EcFullSub(R, SmT); } } else if (u[0] == 0) { if (u[1] == -1) { R = EcFullSub(R, T); } else if (u[1] == 1) { R = EcFullAdd(R, T); } } else if (u[0] == 1) { if (u[1] == -1) { R = EcFullAdd(R, SmT); } else if (u[1] == 0) { R = EcFullAdd(R, S); } else { R = EcFullAdd(R, SpT); } } } return(R); }