#include #include #include long long int P = 192754319; long long int Q = 613463863; long long int S = 427419669081; long long int M; int is_good_prime (long long int p) { long long int t; if (p < 2) return 0; if (p % 4 != 3) return 0; if (p < 4) return 1; for (t=3; t*t <= p; t += 2) { if (p % t == 0) return 0; } return 1; } long long phi (long long v) { long long ret = 1; long long t = 2; while (v > 1) { if (t*t > v) { ret *= v-1; break; } if (v % t == 0) { ret *= t-1; v /= t; } while (v % t == 0) { ret *= t; v /= t; } t++; } return ret; } long long int gcd (long long int a, long long int b) { while (a && b) { if (a > b) { a %= b; } else { b %= a; } } return a+b; } void init (void) { if (!is_good_prime (P) || !is_good_prime (Q)) { fprintf (stderr, "WARNING: One of the primes in bad\n"); exit (1); } if (gcd (phi(P-1), phi(Q-1)) > 10) { fprintf (stderr, "WARNING: The gcd of P-1 and Q-1 is large\n"); exit (1); } M = P*Q; } int get (int decrypt) { long long ret = S % 26LL; if (decrypt) { ret = 26-ret; } /* Die folgenden Schleife berechnet (S*S) % M ohne Ueberlauf in * long long, falls S und M in ca. 62 Bit darstellbar sind. * Nur fuer Beispieltext 3 notwendig. */ long long f1 = S, f2 = S; S = 0; while (f1) { if (f1 % 2LL) { S += f2; S %= M; } f1 /= 2LL; f2 *= 2LL; f2 %= M; } return ret; } void usage (char * p) { fprintf (stderr, "usage: %s [-e | -d ] P Q S\n", p); exit (1); } int main (int argc, char * argv[]) { int ch; int decrypt = -1; char dummy; /* ARGUMENTVERARBEITUNG: Einlesen von P, Q und S. War nicht verlangt */ if (argc != 5) { usage (argv[0]); } if (strcmp (argv[1], "-e") == 0) { decrypt = 0; } if (strcmp (argv[1], "-d") == 0) { decrypt = 1; } if (sscanf (argv[2], "%lld%c", &P, &dummy) != 1) { usage (argv[0]); } if (sscanf (argv[3], "%lld%c", &Q, &dummy) != 1) { usage (argv[0]); } if (sscanf (argv[4], "%lld%c", &S, &dummy) != 1) { usage (argv[0]); } /* Ende Argumentverarbeitung */ init (); while (1) { ch = getchar (); if (ch < 0) break; switch (ch) { case 'a' ... 'z': ch = 'a' + (ch-'a'+get(decrypt)) % 26; break; case 'A' ... 'Z': ch = 'A' + (ch-'A'+get(decrypt)) % 26; break; default: ; } printf ("%c", ch); } return 0; }