public class ECPoint { public BigInteger x; public BigInteger y; public BigInteger a; public BigInteger b; public BigInteger FieldChar; public ECPoint(ECPoint p) { x = px; y = py; a = pa; b = pb; FieldChar = p.FieldChar; } public ECPoint() { x = new BigInteger(); y = new BigInteger(); a = new BigInteger(); b = new BigInteger(); FieldChar = new BigInteger(); } // 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 = pa; p2.b = pb; p2.FieldChar = p.FieldChar; BigInteger dy = 3 * px * px + pa; BigInteger dx = 2 * py; 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 - px - px) % p.FieldChar; p2.y = (m * (px - p2.x) - py) % p.FieldChar; if (p2.x < 0) p2.x += p.FieldChar; if (p2.y < 0) p2.y += p.FieldChar; return p2; } // 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 == px) || (temp.y == py)) temp = Double(temp); else temp = temp + p; x = x - 1; } x = x / 2; p = Double(p); } return temp; } }
public string SignGen(byte[] h, BigInteger d) { BigInteger alpha = new BigInteger(h); BigInteger e = alpha % n; if (e == 0) e = 1; BigInteger k = new BigInteger(); ECPoint C=new ECPoint(); BigInteger r=new BigInteger(); BigInteger s = new BigInteger(); do { do { k.genRandomBits(n.bitCount(), new Random()); } while ((k < 0) || (k > n)); C = ECPoint.multiply(k, G); r = Cx % 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 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); 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 alpha = new BigInteger(H); BigInteger e = alpha % 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(); ECPoint A = ECPoint.multiply(z1, G); ECPoint B = ECPoint.multiply(z2, Q); ECPoint C = A + B; BigInteger R = Cx % n; if (R == r) return true; else return false; }
class DSGost { private BigInteger p = new BigInteger(); private BigInteger a = new BigInteger(); private BigInteger b = new BigInteger(); private BigInteger n = new BigInteger(); private byte[] xG; private ECPoint G = new ECPoint(); public DSGost(BigInteger p, BigInteger a, BigInteger b, BigInteger n, byte[] xG) { this.a = a; this.b = b; this.n = n; this.p = p; this.xG = xG; } // public BigInteger GenPrivateKey(int BitSize) { BigInteger d = new BigInteger(); do { d.genRandomBits(BitSize, new Random()); } while ((d < 0) || (d > n)); return d; } // d Q=d*G, public ECPoint GenPublicKey(BigInteger d) { ECPoint G=GDecompression(); ECPoint Q = ECPoint.multiply(d, G); return Q; } // 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(); Ga = a; Gb = b; G.FieldChar = p; Gx = Xcord; Gy = Ycord; this.G = G; return G; } // q public BigInteger ModSqrt(BigInteger a, BigInteger q) { BigInteger b = new BigInteger(); do { b.genRandomBits(255, new Random()); } while (Legendre(b, q) == 1); BigInteger s = 0; BigInteger t = q - 1; while ((t & 1) != 1) { s++; t = t >> 1; } BigInteger InvA = a.modInverse(q); BigInteger c = b.modPow(t, q); BigInteger r = a.modPow(((t + 1) / 2), q); BigInteger d = new BigInteger(); for (int i = 1; i < s; i++) { BigInteger temp = 2; temp = temp.modPow((s - i - 1), q); d = (r.modPow(2, q) * InvA).modPow(temp, q); if (d == (q - 1)) r = (r * c) % q; c = c.modPow(2, q); } return r; } // public BigInteger Legendre(BigInteger a, BigInteger q) { return a.modPow((q - 1) / 2, q); } // public string SignGen(byte[] h, BigInteger d) { BigInteger alpha = new BigInteger(h); BigInteger e = alpha % n; if (e == 0) e = 1; BigInteger k = new BigInteger(); ECPoint C=new ECPoint(); BigInteger r=new BigInteger(); BigInteger s = new BigInteger(); do { do { k.genRandomBits(n.bitCount(), new Random()); } while ((k < 0) || (k > n)); C = ECPoint.multiply(k, G); r = Cx % 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 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); 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 alpha = new BigInteger(H); BigInteger e = alpha % 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(); ECPoint A = ECPoint.multiply(z1, G); ECPoint B = ECPoint.multiply(z2, Q); ECPoint C = A + B; BigInteger R = Cx % n; if (R == r) return true; else return false; } // n, n - private string padding(string input, int size) { if (input.Length < size) { do { input = "0" + input; } while (input.Length < size); } return input; } }
private void ECTest() { 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); DSGost DS = new DSGost(p, a, b, n, xG); BigInteger d=DS.GenPrivateKey(192); ECPoint Q = DS.GenPublicKey(d); GOST hash = new GOST(256); byte[] H = hash.GetHash(Encoding.Default.GetBytes("Message")); string sign = DS.SignGen(H, d); bool result = DS.SignVer(H, sign, Q); }
Source: https://habr.com/ru/post/191240/
All Articles