//сложение двух точек P1 и P2 public static ECPoint operator +(ECPoint p1, ECPoint p2) { ECPoint p3 = new ECPoint(); p3.a = p1.a; p3.b = p1.b; p3.FieldChar = p1.FieldChar; BigInteger dy = p2.y - p1.y; BigInteger dx = p2.x - p1.x; if (dx < 0) dx += p1.FieldChar; if (dy < 0) dy += p1.FieldChar; BigInteger m = (dy * dx.modInverse(p1.FieldChar)) % p1.FieldChar; if (m < 0) m += p1.FieldChar; p3.x = (m * m - p1.x - p2.x) % p1.FieldChar; p3.y = (m * (p1.x - p3.x) - p1.y) % p1.FieldChar; if (p3.x < 0) p3.x += p1.FieldChar; if (p3.y < 0) p3.y += p1.FieldChar; return p3; }
//сложение точки P c собой же public static ECPoint Double(ECPoint p) { ECPoint p2 = new ECPoint(); p2.a = p.a; p2.b = p.b; p2.FieldChar = p.FieldChar; BigInteger dy = 3 * p.x * p.x + p.a; BigInteger dx = 2 * p.y; if (dx < 0) dx += p.FieldChar; if (dy < 0) dy += p.FieldChar; BigInteger m = (dy * dx.modInverse(p.FieldChar)) % p.FieldChar; p2.x = (m * m - p.x - p.x) % p.FieldChar; p2.y = (m * (p.x - p2.x) - p.y) % p.FieldChar; if (p2.x < 0) p2.x += p.FieldChar; if (p2.y < 0) p2.y += p.FieldChar; return p2; }
public ECPoint(ECPoint p) { x = p.x; y = p.y; a = p.a; b = p.b; FieldChar = p.FieldChar; }
//Восстанавливаем координату y из координаты x и бита четности y private ECPoint GDecompression() { byte y = xG[0]; byte[] x = new byte[xG.Length - 1]; Array.Copy(xG, 1, x, 0, xG.Length - 1); BigInteger Xcord = new BigInteger(x); BigInteger temp = (Xcord * Xcord * Xcord + a * Xcord + b) % p; BigInteger beta = ModSqrt(temp, p); BigInteger Ycord = new BigInteger(); if ((beta % 2) == (y % 2)) Ycord = beta; else Ycord = p - beta; ECPoint G = new ECPoint(); G.a = a; G.b = b; G.FieldChar = p; G.x = Xcord; G.y = Ycord; this.G = G; return G; }
//проверяем подпись public bool SignVer(byte[] H, string sign, ECPoint Q) { string Rvector = sign.Substring(0, n.bitCount() / 4); string Svector = sign.Substring(n.bitCount() / 4, n.bitCount() / 4); encr_r = new BigInteger(Rvector, 16); encr_s = new BigInteger(Svector, 16); if ((encr_r < 1) || (encr_r > (n - 1)) || (encr_s < 1) || (encr_s > (n - 1))) return false; encr_alpha = new BigInteger(H); encr_e = encr_alpha % n; if (encr_e == 0) encr_e = 1; v = encr_e.modInverse(n); z1 = (encr_s * v) % n; z2 = n + ((-(encr_r * v)) % n); this.G = GDecompression(); A = ECPoint.multiply(z1, G); B = ECPoint.multiply(z2, Q); encr_C = A + B; R = encr_C.x % n; if (R == encr_r) return true; else return false; }
//подписываем сообщение public string SignGen(byte[] h, BigInteger d) { alpha = new BigInteger(h); e = alpha % n; if (e == 0) e = 1; k = new BigInteger(); C = new ECPoint(); r = new BigInteger(); s = new BigInteger(); do { do { k.genRandomBits(n.bitCount(), new Random()); } while ((k < 0) || (k > n)); C = ECPoint.multiply(k, G); r = C.x % n; s = ((r * d) + (k * e)) % n; } while ((r == 0) || (s == 0)); string Rvector = padding(r.ToHexString(), n.bitCount() / 4); string Svector = padding(s.ToHexString(), n.bitCount() / 4); return Rvector + Svector; }
//умножение точки на число x, по сути своей представляет x сложений точки самой с собой public static ECPoint multiply(BigInteger x, ECPoint p) { ECPoint temp = p; x = x - 1; while (x != 0) { if ((x % 2) != 0) { if ((temp.x == p.x) || (temp.y == p.y)) temp = Double(temp); else temp = temp + p; x = x - 1; } x = x / 2; p = Double(p); } return temp; }