#include #include #include #include #include #include char buffer[1024]; const int MAX_DIGITS = 50; int i, j = 0; struct public_key_class { long long modulus; long long exponent; }; struct private_key_class { long long modulus; long long exponent; }; // This should totally be in the math library. long long gcd(long long a, long long b) { long long c; while (a != 0) { c = a; a = b % a; b = c; } return b; } long long ExtEuclid(long long a, long long b) { long long x = 0, y = 1, u = 1, v = 0, gcd = b, m, n, q, r; while (a != 0) { q = gcd / a; r = gcd % a; m = x - u * q; n = y - v * q; gcd = a; a = r; x = u; y = v; u = m; v = n; } return y; } static inline long long modmult(long long a, long long b, long long mod) { // this is necessary since we will be dividing by a if (a == 0) { return 0; } register long long product = a * b; //if multiplication does not overflow, we can use it if (product / a == b) { return product % mod; } // if a % 2 == 1 i. e. a >> 1 is not a / 2 if (a & 1) { product = modmult((a >> 1), b, mod); if ((product << 1) > product) { return (((product << 1) % mod) + b) % mod; } } //implicit else product = modmult((a >> 1), b, mod); if ((product << 1) > product) { return (product << 1) % mod; } //implicit else: this is about 10x slower than the code above, but it will not overflow long long sum; sum = 0; while (b > 0) { if (b & 1) sum = (sum + a) % mod; a = (2 * a) % mod; b >>= 1; } return sum; } long long rsa_modExp(long long b, long long e, long long m) { long long product; product = 1; if (b < 0 || e < 0 || m <= 0) { return -1; } b = b % m; while (e > 0) { if (e & 1) { product = modmult(product, b, m); } b = modmult(b, b, m); e >>= 1; } return product; } // Calling this function will generate a public and private key and store them in the pointers // it is given. void rsa_gen_keys(struct public_key_class *pub, struct private_key_class *priv) { pub->modulus = 1580420911; pub->exponent = 131073; priv->modulus = 1580420911; priv->exponent = 874267137; } unsigned char *rsa_encrypt(const unsigned char *message, const unsigned long message_size, const struct public_key_class *pub) { long long *encrypted = malloc(sizeof(long long) * message_size); if (encrypted == NULL) { fprintf(stderr, "Error: Heap allocation failed.\n"); return NULL; } long long i = 0; for (i = 0; i < message_size; i++) { if ((encrypted[i] = rsa_modExp(message[i], pub->exponent, pub->modulus)) == -1) return NULL; } return (unsigned char*)encrypted; } unsigned char *rsa_decrypt(const long long *message, const unsigned long message_size, const struct private_key_class *priv) { if (message_size % sizeof(long long) != 0) { fprintf(stderr, "Error: message_size is not divisible by %d, so cannot be output of rsa_encrypt\n", (int) sizeof(long long)); return NULL; } // We allocate space to do the decryption (temp) and space for the output as a char array // (decrypted) unsigned char *decrypted = malloc(message_size / sizeof(long long)); unsigned char *temp = malloc(message_size); if ((decrypted == NULL) || (temp == NULL)) { fprintf(stderr, "Error: Heap allocation failed.\n"); return NULL; } // Now we go through each 8-byte chunk and decrypt it. long long i = 0; for (i = 0; i < message_size / 8; i++) { if ((temp[i] = rsa_modExp(message[i], priv->exponent, priv->modulus)) == -1) { free(temp); return NULL; } } // The result should be a number in the char range, which gives back the original byte. // We put that into decrypted, then return. for (i = 0; i < message_size / 8; i++) { decrypted[i] = temp[i]; } free(temp); return decrypted; }