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
            };
        }