//умножение точки на число. public static CECPoint multiply(CECPoint p, BigInteger c) { CECPoint res = p; c = c - 1; while (c != 0) { if ((c % 2) != 0) { if ((res.x == p.x) || (res.y == p.y)) { res = doubling(res); } else { res = res + p; } c = c - 1; } c = c / 2; p = doubling(p); } return(res); }
//восстановление координат Y из координаты X и бита четности Y. private CECPoint 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; } CECPoint G = new CECPoint(); G.a = a; G.b = b; G.fieldChar = p; G.x = Xcord; G.y = Ycord; this.G = G; return(G); }
//генерация публичного ключа (с помощью секретного). public CECPoint genPublicKey(BigInteger d) { CECPoint G = gDecompression(); CECPoint Q = CECPoint.multiply(G, d); return(Q); }
//формирование цифровой подписи. public string genDS(byte[] h, BigInteger d) { BigInteger a = new BigInteger(h); BigInteger e = a % n; if (e == 0) { e = 1; } BigInteger k = new BigInteger(); CECPoint C = new CECPoint(); BigInteger r = new BigInteger(); BigInteger s = new BigInteger(); do { do { k.genRandomBits(n.bitCount(), new Random()); }while ((k < 0) || (k > n)); C = CECPoint.multiply(G, k); 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); }
public CECPoint(CECPoint p) { a = p.a; b = p.b; x = p.x; y = p.y; fieldChar = p.fieldChar; }
//сложение пары точек. public static CECPoint operator+(CECPoint p1, CECPoint p2) { CECPoint res = new CECPoint(); res.a = p1.a; res.b = p1.b; res.fieldChar = p1.fieldChar; BigInteger dx = p2.x - p1.x; BigInteger dy = p2.y - p1.y; if (dx < 0) { dx += p1.fieldChar; } if (dy < 0) { dy += p1.fieldChar; } BigInteger t = (dy * dx.modInverse(p1.fieldChar)) % p1.fieldChar; if (t < 0) { t += p1.fieldChar; } res.x = (t * t - p1.x - p2.x) % p1.fieldChar; res.y = (t * (p1.x - res.x) - p1.y) % p1.fieldChar; if (res.x < 0) { res.x += p1.fieldChar; } if (res.y < 0) { res.y += p1.fieldChar; } return(res); }
//проверка цифровой подписи. public bool verifDS(byte[] H, string sign, CECPoint Q) { string Rvector = sign.Substring(0, n.bitCount() / 4); string Svector = sign.Substring(n.bitCount() / 4, n.bitCount() / 4); BigInteger r = new BigInteger(Rvector, 16); BigInteger s = new BigInteger(Svector, 16); if ((r < 1) || (r > (n - 1)) || (s < 1) || (s > (n - 1))) { return(false); } BigInteger a = new BigInteger(H); BigInteger e = a % n; if (e == 0) { e = 1; } BigInteger v = e.modInverse(n); BigInteger z1 = (s * v) % n; BigInteger z2 = n + ((-(r * v)) % n); this.G = gDecompression(); CECPoint A = CECPoint.multiply(G, z1); CECPoint B = CECPoint.multiply(Q, z2); CECPoint C = A + B; BigInteger R = C.x % n; if (R == r) { return(true); } else { return(false); } }
//удвоение точки. public static CECPoint doubling(CECPoint p) { CECPoint res = new CECPoint(); res.a = p.a; res.b = p.b; res.fieldChar = p.fieldChar; BigInteger dx = 2 * p.y; BigInteger dy = 3 * p.x * p.x + p.a; if (dx < 0) { dx += p.fieldChar; } if (dy < 0) { dy += p.fieldChar; } BigInteger t = (dy * dx.modInverse(p.fieldChar)) % p.fieldChar; res.x = (t * t - p.x - p.x) % p.fieldChar; res.y = (t * (p.x - res.x) - p.y) % p.fieldChar; if (res.x < 0) { res.x += p.fieldChar; } if (res.y < 0) { res.y += p.fieldChar; } return(res); }