//формирование цифровой подписи. 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 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); }
//сложение пары точек. 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 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; }
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); CDS DS = new CDS(p, a, b, n, xG); BigInteger d = DS.genPrivateKey(192); CECPoint Q = DS.genPublicKey(d); CStribog hash = new CStribog(256); /* * byte[] H = hash.GetHash(Encoding.Default.GetBytes("Message")); * string sign = DS.genDS(H, d); * * byte[] H2 = hash.GetHash(Encoding.Default.GetBytes("message")); * string sign2 = DS.genDS(H2, d); */ Console.WriteLine("Выберите файл содержащий сообщение: "); String path = Console.ReadLine(); String message = readFile(path); byte[] H = hash.GetHash(Encoding.Default.GetBytes(message)); string sign = DS.genDS(H, d); Console.WriteLine("Сообщение \"{0}\" имеет следующую ЭЦП: {1}", message, sign); Console.WriteLine("Выберите файл для сохранение ЭЦП: "); path = Console.ReadLine(); writeFile(path, sign); Console.WriteLine("Выберите файл для верификации сообщения: "); path = Console.ReadLine(); String message2 = readFile(path); byte[] H2 = hash.GetHash(Encoding.Default.GetBytes(message2)); Console.WriteLine("Выберите файл содержащий цифровую подпись: "); path = Console.ReadLine(); string signVer = readFile(path); //string sign2 = DS.genDS(H2, d); bool result = DS.verifDS(H2, signVer, Q); if (result) { System.Console.WriteLine("Верификация прошла успешно. Цифровая подпись верна."); } else { System.Console.WriteLine("Верификация не прошла! Цифровая подпись не верна."); } System.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 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); } }
//восстановление координат 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 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); }
//умножение точки на число. 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 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); }