private static string ElGamalDecrypt(KeyStruct cipher, KeyStruct privateKey) { string m = ""; ulong x = publicKey.p - 1 - privateKey.a; /* jedes Zeichen wird wieder entschlüsselt */ for (int i = 0; i < cipher.c.Length; i++) { m += char.ConvertFromUtf32((int)((BigInteger.ModPow(cipher.B, x, publicKey.p) * cipher.c[i]) % publicKey.p)); } return(m); }
private static void KeyScheduling(ref KeyStruct publicKey, ref KeyStruct privateKey) { byte[] buffer = new byte[sizeof(UInt64)]; /* q brauchen wir für das Erzeugen einer Sophie-Germain-Primzahl */ ulong q; /* zuerst wird das q bestimmt, um so ein passendes p zu finden, * * dies bringt den Vorteil, dass durch Sophie-Germain Zahlen die Primfaktorzerlegung für das g wegfällt */ do { zufall.NextBytes(buffer); q = BitConverter.ToUInt64(buffer, 0); /* durch das Shiften um eine Stelle wird erreicht, dass p durch die Multiplikation mit 2 und q nicht seinen Wertebereich überschreitet */ q >>= 1; }while (!MillerRabin(q) || !SophieGermain(q)); ulong p = (q << 1) + 1; Console.WriteLine("p = " + p); /* Bestimmung des Generatorpolynoms --> ist jetzt relativ einfach, da die beiden primen Teiler von phi(p) 2 und q sind */ ulong g = GetGenerator(p, q); Console.WriteLine("g = " + g); /* ein zufälliges geheimes a wird gewählt --> wichtig für den Private Key */ zufall.NextBytes(buffer); ulong a = BitConverter.ToUInt64(buffer, 0) % p; Console.WriteLine("a = " + a); /* das große (öffentliche) A wird errechnet, mit dessen Hilfe Nachrichten verschlüsselt werden können */ ulong A = (ulong)BigInteger.ModPow(g, a, p); Console.WriteLine("A = " + A + "\n"); publicKey = new KeyStruct { p = p, g = g, A = A }; privateKey = new KeyStruct { a = a }; }