//генерация публичного ключа (с помощью секретного). public CECPoint publicKeyGen(BigInteger d) { CECPoint G = gDecompression(); CECPoint Q = CECPoint.multiply(G, d); return(Q); }
//восстановление координат 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 string DSGen(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 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); }
public CECPoint(CECPoint p) { a = p.a; b = p.b; x = p.x; y = p.y; fieldChar = p.fieldChar; }
static void Main(string[] args) { BigInteger p = new BigInteger("6277101735386680763835789423207666416083908700390324961279", 10); BigInteger a = new BigInteger("-3", 10); BigInteger b = new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16); byte[] xG = fromHexStringToByte("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"); BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16); DS ds = new DS(p, a, b, n, xG); BigInteger d = ds.privateKeyGen(192); CECPoint Q = ds.publicKeyGen(d); Stribog256 hash = new Stribog256(); Console.WriteLine("Выберите файл содержащий сообщение: "); String path = Console.ReadLine(); String message = File.ReadAllText(path); byte[] H = hash.GetHash(message); string sign = ds.DSGen(H, d); Console.WriteLine("Сообщение " + message + " имеет следующую ЭЦП: " + sign); Console.WriteLine("Выберите файл для сохранение ЭЦП: "); path = Console.ReadLine(); File.WriteAllText(path, sign); Console.WriteLine("Выберите файл для верификации сообщения: "); path = Console.ReadLine(); String message2 = File.ReadAllText(path); byte[] H2 = hash.GetHash(message2); Console.WriteLine("Выберите файл содержащий цифровую подпись: "); path = Console.ReadLine(); string signVer = File.ReadAllText(path); bool result = ds.verifyDS(H2, signVer, Q); if (result) { Console.WriteLine("Верификация прошла успешно. Цифровая подпись верна."); } else { Console.WriteLine("Верификация не прошла! Цифровая подпись не верна."); } Console.ReadLine(); }
//сложение пары точек. 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 verifyDS(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); }