Place Holder Products Code
Bash MySQL
Notes Return of the Fed Login
Admin Control Panel Email Control Panel Product Control Panel Debug Info Beacon Create Snippet Tag Control Panel

Code

*More fully fledged applications can be found on the Products page. The Bash page is dedicated to fully commented oneliners, and a MySQL quick reference is available here.



				
/* rsa.cpp * - Will Bergen - 2019 * - Toy implementation of RSA pubkey algorithm * - Uses hardcoded, small primes for test purposes * - compile with: g++ rsa.cpp -std=c++11 -g * */ #include <stdlib.h> #include <stdio.h> #include <cstdint> #include <string.h> using namespace std; /* RSA Algo: * Key Generation * - Find 2 primes, p and q * - p and q should be similar, * - Compute n = p*q * - Compute C(n) where C is Carmichael Function * - C(n) = lcm(p-1,q-1) where lcm is Least Common Multiple * - I don't understand the theory here... * - Choose e s.t. 1 < e < C(n) AND gcd(e,C(n)) == 1 * - ie. Choose e s.t. e and C(n) are coprime * - Compute d = e^-1 mod C(n) * - ie. Compute d, the multiplicative inverse of e mod C(n) * - e is pub key * - d is priv key * * Encryption * - Plain text represented as integer p (ignoring padding) * - Cipher text c = p^e (mod n) where e is the other's public key * * Decryption * - Cipher text represented as integer c * - Plain text p = c^d (mod n) where d is your private key * */ uint64_t C(uint64_t n); // Carmichael uint64_t gcd(uint64_t i, uint64_t j); // Greatest Common Divisor uint64_t my_pow(uint64_t x, uint64_t y, uint64_t m); // Power Mod uint64_t modInverse(uint64_t x, uint64_t m); // Multiplicative Inverse void encrypt(char *input, int msg_length, uint64_t e, uint64_t n, uint64_t *output); void decrypt(uint64_t *input, int msg_length, uint64_t d, uint64_t n, char *output); int main(int argc, char **argv) { printf("RSA Running!\n"); // Hardcoded test: uint64_t p = 371; uint64_t q = 377; uint64_t n = p * q; printf("Using: [p: %lu, q: %lu, n: %lu]\n", p, q, n); printf("Finding C(n)... "); uint64_t c = C(p * q); // Carmichael's Function printf("%lu!\n",c); // - Choose e s.t. 1 < e < C(n) AND gcd(e,C(n)) == 1 // - ie. Choose e s.t. e and C(n) are coprime uint64_t e; int i; for (int i = 16; i < c; ++i) { if (gcd(i,c) == 1){ e = i; break; } } printf("Chose %lu for e!\n", e); // - Compute d = e^-1 mod C(n) // - ie. Compute d, the multiplicative inverse of e mod C(n) uint64_t d = modInverse(e,c); printf("Chose %lu as d!\n", d); // Encrypt a message: char msg[] = "This is my much longer Message!"; int msg_length = strlen(msg); printf("Message String: %s, (Length: %i)\n", msg, msg_length); // - Cipher text c = p^e (mod n) where e is the other's public key // Declares pointers to arrays of size msg_length uint64_t ciph_pad[msg_length]; char decrypted_pad[msg_length]; // Encrypt: encrypt(msg, msg_length, e, n, ciph_pad); // Print Encrypted Message: printf("Cipher Text: "); for (int i = 0; i < msg_length; ++i) { printf("%c", (int)ciph_pad[i]); } printf("\n"); // Decrypt: decrypt(ciph_pad, msg_length, d, n, decrypted_pad); // Print Decrypted Message: printf("Decrypted Text: "); for (int i = 0; i < msg_length; ++i) { printf("%c", decrypted_pad[i]); } printf("\n"); } /* Encrypt: * - Takes pointer to input char array, ie the message to encrypt * - Takes pointer to output uint64_t array, ie. the cipher buffer */ void encrypt(char *input, int msg_length, uint64_t e, uint64_t n, uint64_t *output) { for (int i = 0; i < msg_length; ++i) { output[i] = (uint64_t)my_pow(input[i], e, n); } } /* Decrypt: * - Takes pointer to input uint64_t array, ie the cipher buffer * - Takes pointer to output char array, ie. decrypted message buffer */ void decrypt(uint64_t *input, int msg_length, uint64_t d, uint64_t n, char *output) { for (int i = 0; i < msg_length; ++i) { output[i] = (char)my_pow(input[i], d, n); } } // Try them all naive: uint64_t modInverse(uint64_t x, uint64_t m) { int i; for (int i = 1; i < m; ++i) { if ((x*i) % m == 1) // if ((x * i) == (1 % m)) { return i; } } } // From https://www.geeksforgeeks.org/carmichael-numbers/ // Computes (x ^ y) mod m: // Vast majority of time spent here uint64_t my_pow(uint64_t x, uint64_t y, uint64_t m) { if (y == 0) { return 1; } uint64_t temp = my_pow(x,y/2,m) % m; temp = (temp * temp) % m; if (y % 2 == 1) { temp = (temp * x) % m; } return temp; } /* Greatest Common Divisor * - Takes two ints i and j * - If either is 0, return the other * - r = i mod k * - Call gcd(j, r) */ uint64_t gcd(uint64_t i, uint64_t j) { if (i == 0) { return j; } if (j == 0) { return i; } uint64_t r = i % j; uint64_t t = gcd(j,r); } /* Carmichael Function * - Takes n * - Generate sequence Xm (ie. X = [m1, m2, .., mn]) * - For each i < n, add to X if gcd(i,n) == 1 * - X = list of all numbers less than n which are coprime to n * - k = 1 * - For each m in X, increment k if (m^k) mod n == 1 * - Return k */ uint64_t C(uint64_t n) { uint64_t x[100]; memset(&x, 0, sizeof(uint64_t)*100); int i; int cp_n = 0; // starts at 1? for (i = 1;i < n; i++) { if (cp_n >= 99) {break;printf("pad exhausted!\n");exit(0);} if (gcd(i,n) == 1) { x[cp_n] = i; cp_n ++; } } int k = 1; bool flag; while (true) { flag = true; uint64_t k2 = k; for (i = 0;i < cp_n; i++) { // printf("%lu ^ %i mod %lu == %lu\n", x[i], k, n, my_pow(x[i], k, n)); if (my_pow(x[i], k, n) != 1) { flag = false; } } if (!flag) { k++; flag = true; } else { break; } } return (uint64_t)k; }