private JacobianEcPoint Add(JacobianEcPoint p1, JacobianEcPoint p2) { if (p1.Inf) { return(p2); } if (p2.Inf) { return(p1); } var a = p1.X * p2.Z * p2.Z % P; var b = p2.X * p1.Z * p1.Z % P; var c = p1.Y * p2.Z * p2.Z * p2.Z % P; var d = p2.Y * p1.Z * p1.Z * p1.Z % P; var e = a - b; var f = c - d; if (e.IsZero) { return(f.IsZero ? Double(p1) : JacobianEcPoint.Infinity); } var x = f * f - e * e * e - 2 * b * e * e; var y = f * (b * e * e - x) - d * e * e * e; var z = p1.Z * p2.Z * e; x -= (x / P - (x.Sign < 0 ? 1 : 0)) * P; y -= (y / P - (y.Sign < 0 ? 1 : 0)) * P; z -= (z / P - (z.Sign < 0 ? 1 : 0)) * P; return(new JacobianEcPoint { X = x, Y = y, Z = z }); }
private JacobianEcPoint Negate(JacobianEcPoint p) { if (p.Inf) { return(p); } if (p.Y.IsZero) { return(p); } return(new JacobianEcPoint { X = p.X, Y = P - p.Y, Z = p.Z }); }
public EcPoint ToAffine(JacobianEcPoint jp) { if (jp.Inf) { return(EcPoint.Infinity); } if (jp.Affine) { return(new EcPoint(jp.X, jp.Y)); } BigInteger x, y; var zc = (jp.Z * jp.Z % P).InvMod(P); var zd = (jp.Z * jp.Z * jp.Z % P).InvMod(P); x = jp.X * zc % P; y = jp.Y * zd % P; return(new EcPoint(x, y)); }
private JacobianEcPoint Double(JacobianEcPoint p) { if (p.Inf) { return(p); } if (p.Y.IsZero) { return(JacobianEcPoint.Infinity); } var a = p.X * p.Y * p.Y % P; var b = _inv2 * (3 * p.X * p.X + A * BigInteger.ModPow(p.Z, 4, P)) % P; var x = b * b - 2 * a; var y = b * (a - x) - BigInteger.ModPow(p.Y, 4, P); var z = p.Y * p.Z; x -= (x / P - (x.Sign < 0 ? 1 : 0)) * P; y -= (y / P - (y.Sign < 0 ? 1 : 0)) * P; z -= (z / P - (z.Sign < 0 ? 1 : 0)) * P; return(new JacobianEcPoint { X = x, Y = y, Z = z }); }
public JacobianEcPoint Multiply(BigInteger k, JacobianEcPoint p, AnyRng rng) { if (k.Sign < 0) { k = -k; p = Negate(p); } if (k.IsZero) { return(JacobianEcPoint.Infinity); } if (k.IsOne) { return(p); } var ks = rng.NextBigInt(BigInteger.One, k); // return MultiplyAndAdd(ks, p, k - ks, p, rng); var(k1, k2) = ToNafBytes(k - ks, ks); var i = 0; while (i < k1.Length - 1) { var c = k1[i].NafValue() + k2[i].NafValue(); if (c != 0) { i++; continue; } if (k2[i + 1].NafValue() > 0) { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() - 1) & 0xF)); k2[i] = (byte)(((k2[i].H() + 2) << 4) | (k2[i].L() & 0xF)); } else { k2[i + 1] = (byte)((k2[i + 1].H() << 4) | ((k2[i + 1].L() + 1) & 0xF)); k2[i] = (byte)(((k2[i].H() - 2) << 4) | (k2[i].L() & 0xF)); } } var lut = new [] { JacobianEcPoint.Infinity, p, Double(p), Add(Double(p), p), Double(Double(p)) }; var r = lut[k1.Back().NafValue() + k2.Back().NafValue()]; for (i = k1.Length - 2; i >= 0; i--) { var c = k1[i].NafValue() + k2[i].NafValue(); r = Add(Double(Double(r)), c < 0 ? Negate(lut[-c]) : lut[c]); } return(r); }
public JacobianEcPoint MultiplyAndAdd(BigInteger k, JacobianEcPoint p, BigInteger m, JacobianEcPoint s, AnyRng rng) { if (k.Sign < 0) { k = -k; p = Negate(p); } if (m.Sign < 0) { m = -m; s = Negate(s); } if (k.IsZero) { return(Multiply(m, s, rng)); } if (m.IsZero) { return(Multiply(k, p, rng)); } if (k.IsOne) { return(Add(p, Multiply(m, s, rng))); } if (m.IsOne) { return(Add(s, Multiply(k, p, rng))); } var(kk, mm) = ToNafBytes(k, m); var i = 0; while (i < kk.Length - 1) { if (kk[i] != 0 || mm[i] != 0) { i++; continue; } switch (mm[i + 1]) { case 0: mm[i + 1] = 0x01; mm[i] = 0xE0; break; case 0x0F: mm[i + 1] = 0xF0; mm[i] = 0x20; break; case 0x01: mm[i + 1] = 0x10; mm[i] = 0xE0; break; case 0xF0: mm[i + 1] = 0x0F; mm[i] = 0xE0; break; case 0x10: mm[i + 1] = 0x01; mm[i] = 0x20; break; default: throw new Exception(); } } var lut = new [] { // T[x,y] = lut[7x+y-1] s, Double(s), JacobianEcPoint.Infinity, Double(Double(s)), Add(p, Negate(Double(s))), Add(p, Negate(s)), p, Add(p, s), Add(p, Double(s)), JacobianEcPoint.Infinity, JacobianEcPoint.Infinity, Add(Double(p), Negate(Double(s))), Add(Double(p), Negate(s)), Double(p), Add(Double(p), s), Add(Double(p), Double(s)) }; var r = lut[kk.Back().NafValue() * 7 + mm.Back().NafValue() - 1]; for (i = kk.Length - 2; i >= 0; i--) { r = Double(Double(r)); if (kk[i] == 0) { if (mm[i].NafValue() < 0) { r = Add(r, Negate(lut[-mm[i].NafValue() - 1])); } else { r = Add(r, lut[mm[i].NafValue() - 1]); } } else if (kk[i].NafValue() < 0) { r = Add(r, Negate(lut[-kk[i].NafValue() * 7 - mm[i].NafValue() - 1])); } else { r = Add(r, lut[kk[i].NafValue() * 7 + mm[i].NafValue() - 1]); } } return(r); }