This code is a large-scale RSA encryption and decryption. The selection of q and p uses pseudo-randomly generated large numbers and performs primality testing; the three characters in the plaintext are divided into blocks, and the characters in the block are not satisfied. Three are filled, and the filling scheme used is PKCS#7 filling.
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <stdlib.h> #include <time.h> #include <math.h> using namespace std; long long int N; long long int D; // Generate pseudo prime numbers const int MAX_ROW = 50; size_t Pseudoprime() { bool ifprime = false; size_t a = 0; int arr[MAX_ROW]; //The array arr is {3, 4, 5, 6...52} for (int i = 0; i < MAX_ROW; + + i) { arr[i] = i + 3; } while (!ifprime) { srand((unsigned)time(0)); ifprime = true; a = (rand() % 10000) * 3 + 10000; //Generate an odd number in the range of 10000 to 40000 for (int j = 0; j < MAX_ROW; + + j) { if (a % arr[j] == 0) { ifprime = false; break; } } } return a; } size_t repeatMod(size_t base, size_t n, size_t mod)//modular repeat square algorithm to find (b^n)%m { size_t a = 1; while(n) { if (n & 1) { a = (a * base) % mod; } base = (base * base) % mod; n = n >> 1; } return a; } //Miller-Rabin prime number detection bool rabinmiller(size_t n, size_t k) { int s = 0; int temp = n - 1; while ((temp & amp; 0x1) == 0 & amp; & amp; temp) { temp = temp >> 1; s++; } //Represent n-1 as (2^s)*t size_t t = temp; while (k--) //Judge that the probability of misjudgment in round k is not greater than (1/4)^k { srand((unsigned)time(0)); size_t b = rand() % (n - 2) + 2; //Generate a b(2≤a ≤n-2) size_t y = repeatMod(b, t, n); if (y == 1 || y == (n - 1)) return true; for (int j = 1; j <= (s - 1) & amp; & amp; y != (n - 1); + + j) { y = repeatMod(y, 2, n); if(y==1) return false; } if (y != (n - 1)) return false; } return true; } /* //Simple prime number detection method bool isprime(size_t n) { if(n==2) return true; for (int i = 2; i <= (int)sqrt((float)n); + + i) { if (n % i == 0) return false; } return true; }*/ // Calculate the greatest common divisor unsigned long long gcd(unsigned long long a, unsigned long long b) { if(b==0) return a; return gcd(b, a % b); } // Calculate modular inverse elements unsigned long long modInverse(unsigned long long a, unsigned long long m) { long long m0 = m; long long y = 0, x = 1; if(m==1) return 0; while (a > 1) { long long q = a / m; long long t = m; m = a % m; a = t; t = y; y = x - q * y; x = t; } if (x < 0) x + = m0; return x; } // Fast modular exponentiation unsigned long long modExp(unsigned long long base, unsigned long long exponent, unsigned long long modulus) { unsigned long long result = 1; base = base % modulus; while (exponent > 0) { if (exponent & 1) { result = (result * base) % modulus; } exponent = exponent >> 1; base = (base * base) % modulus; } return result; } // RSA segmented encryption function (including padding) unsigned long long* encryptString(const char* plaintext, unsigned long long n, unsigned long long e, int blockSize, int* numBlocks) { int plaintextLength = strlen(plaintext); int paddingLength = blockSize - (plaintextLength % blockSize); *numBlocks = (int)ceil((double)(plaintextLength + paddingLength) / blockSize); unsigned long long* ciphertext = new unsigned long long[*numBlocks]; for (int i = 0; i < *numBlocks; i + + ) { int startIndex = i * blockSize; int endIndex = (i + 1) * blockSize; if (endIndex > plaintextLength) { endIndex = plaintextLength; } unsigned long long blockValue = 0; for (int j = startIndex; j < endIndex; j + + ) { blockValue = blockValue * 256 + (unsigned long long)plaintext[j]; } if (i == (*numBlocks - 1)) { //The last block is filled for (int j = 0; j < paddingLength; j + + ) { blockValue = blockValue * 256 + paddingLength; } } ciphertext[i] = modExp(blockValue, e, n); } return ciphertext; } // RSA segmented decryption function (including depadding) char* decryptString(unsigned long long* ciphertext, unsigned long long n, unsigned long long d, int blockSize, int numBlocks) { char* plaintext = new char[numBlocks * blockSize + 1]; // Add 1 to store the null terminator for (int i = 0; i < numBlocks; i + + ) { unsigned long long decryptedBlock = modExp(ciphertext[i], d, n); for (int j = blockSize - 1; j >= 0; j--) { plaintext[i * blockSize + j] = (char)(decryptedBlock % 256); decryptedBlock = decryptedBlock / 256; } } //Remove padding bytes int padding = (int)plaintext[numBlocks * blockSize - 1]; //The last byte indicates the padding length int plaintextLength = numBlocks * blockSize - padding; plaintext[plaintextLength] = '\0'; return plaintext; } void encryptNumber(long M, unsigned long long n, unsigned long long e) { int r = 1; e = e + 1; while (e != 1) { r = r * M; r = r % n; e--; } printf("Original message: %ld\ ", M); printf("Encrypted message:"); cout << r << endl; } // Various parameters of RSA encryption and decryption void rsa(int mode) { cout << "Generating RSA encrypted public and private keys, please wait..." << endl; unsigned long long int p = 0; unsigned long long int q = 0; for (int i = 0; i <= 1; i + + ) { size_t ret = Pseudoprime(); if (i == 0 & amp; & amp; p == 0) { if (rabinmiller(ret, 10)) { cout << "generated" << ret << "is a prime number" << endl; cout << "p is:" << ret << endl; p = ret; cout << "---------------------------------------------" << endl ; } else { i--; } } else if (i == 1 & amp; & amp; q == 0 & amp; & amp; p != 0) { if (rabinmiller(ret, 10) & amp; & amp; ret != p) { cout << "generated" << ret << "is a prime number" << endl; cout << "q is:" << ret << endl; q = ret; cout << "---------------------------------------------" << endl ; } else { i--; } } } unsigned long long int n = p * q; // Calculate n unsigned long long int phi = (p - 1) * (q - 1); // Calculate Euler function phi(n) unsigned long long int e = 0; while (1) { e = rand() % phi; // Randomly select an encryption index e if (gcd(e, phi) == 1) // Ensure that e and phi are mutually prime break; } cout << "n is:" << n << endl; N = n; cout << "Randomly generate e:" << e << endl; cout << "The phi value is:" << phi << endl; // Calculate the decryption index d unsigned long long d = modInverse(e, phi); printf("Private key (d): %llu\ ", d); D = d; cout << "---------------------------------------------" << endl ; if (mode == 10) { char filename[256]; printf("Please enter the local file name containing plain text:"); scanf("%5s", filename); FILE* file = fopen(filename, "r"); if (file == NULL) { printf("Cannot open file %s\ ", filename); return; } fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); char* plaintext = (char*)malloc((fileSize + 1) * sizeof(char)); fread(plaintext, sizeof(char), fileSize, file); plaintext[fileSize] = '\0'; fclose(file); int blockSize = 3; int numBlocks; unsigned long long* encrypted = encryptString(plaintext, n, e, blockSize, & amp;numBlocks); printf("Original message: %s\ ", plaintext); printf("Encrypted message:"); for (int i = 0; i < numBlocks; i + + ) { printf("%llu ", encrypted[i]); } printf("\ "); //Write to txt local file printf("Please enter the file name to save the ciphertext:"); char filename1[256]; scanf("%5s", filename1); FILE* file1 = fopen(filename1, "w"); if (file == NULL) { printf("Cannot open file %s\ ", filename1); return; } for (int i = 0; i < numBlocks; i + + ) { fprintf(file1, "%llu ", encrypted[i]); } fclose(file1); printf("The ciphertext has been saved to file %s\ ", filename1); free(plaintext); free(encrypted); } if (mode == 21) { char plaintext[256]; printf("Please enter the plain text to be encrypted:"); scanf("%5s", plaintext); int numBlocks; unsigned long long* encrypted = encryptString(plaintext, n, e, 3, & amp;numBlocks); printf("Original message: %s\ ", plaintext); printf("Encrypted message:"); for (int i = 0; i < numBlocks; i + + ) { printf("%llu ", encrypted[i]); } cout << endl; //Write to txt local file printf("Please enter the file name to save the ciphertext:"); char filename[256]; scanf("%5s", filename); FILE* file = fopen(filename, "w"); if (file == NULL) { printf("Cannot open file %s\ ", filename); return; } for (int i = 0; i < numBlocks; i + + ) { fprintf(file, "%llu ", encrypted[i]); } fclose(file); printf("The ciphertext has been saved to file %s\ ", filename); free(encrypted); } if (mode == 22) { long M; cout << "Please enter a number:"; scanf("%ld", & amp;M); encryptNumber(M, n, e); } } //Main function int main(void) { int choice = 0; while (choice != 3) { printf("Welcome to RSA encryption and decryption system\ "); cout << "------------------------------------------------- -------------------------------------------------- --------------------" << endl; printf("Please select function:\ "); printf(" 1. Encryption\ "); printf(" 2. Decrypt\ "); printf(" 3. Exit\ "); printf("Select:"); scanf("%d", & amp;choice); switch (choice) { case 1: { int option = 0; printf("Please select input method:\ "); printf("1. Read plain text from local file\ "); printf("2. Directly output plain text\ "); printf("Select:"); scanf("%d", & amp;option); if (option == 1) { //Read plain text from file // char* plainText = readPlainTextFromFile(filename); // if (plainText == NULL) { // break; // } // free(plainText); rsa(10); break; } else if (option == 2) { int op = 0; bool flag = false; printf("Please select input method:\ "); printf(" 1. Encrypted string\ "); printf(" 2. Encrypted number\ "); printf("Select:"); int modeNumber = 22; //Encrypted number int modeString = 21; //Encrypted string while (op > -1 & amp; & amp; flag == false) { scanf("%d", & amp;op); if (op == 1) { rsa(modeString); flag = 1; break; } else if (op == 2) break; else { printf("Invalid selection, please re-enter:\ "); } } while (op > -1 & amp; & amp; flag == false) { scanf("%d", & amp;op); if (op == 2) { rsa(modeNumber); flag = 1; break; } else { printf("Invalid selection, please re-enter:\ "); } } break; } } //Decrypt the ciphertext case 2: { printf("Please select input method:\ "); printf(" 1. Read ciphertext from local file\ "); printf(" 2. Directly output the ciphertext\ "); printf("Select:"); int option = 0; scanf("%d", & amp;option); if (option == 2) { unsigned long long ciphertext[256]; int numBlocks = 0; printf("Please enter the ciphertext to be decrypted (separated by spaces, stopped by newlines):"); while (scanf("%llu", & ciphertext[numBlocks]) == 1) { numBlocks + + ; // Read and discard newlines if (getchar() == '\ ') { break; } } getchar(); // Clear newline characters in the input buffer // Get private keys d and n unsigned long long d, n; cout << "Please enter private keys d and n" << endl; cout << "d is: "; cin >> d; cout << "n is: "; cin >> n; //Perform decryption operation char* decrypted = decryptString(ciphertext, n, d, 3, numBlocks); printf("Decrypted message: %s\ ", decrypted); free(decrypted); break; } else if (option == 1) { cout << "Private key PR={" << D << "," << N << "}" << endl; printf("Please enter the name of the ciphertext file to be read:"); char filename[256]; scanf("%5s", filename); FILE* file = fopen(filename, "r"); if (file == NULL) { printf("Cannot open file %s\ ", filename); return 1; } unsigned long long* ciphertext = NULL; int numBlocks = 0; int c; //Read ciphertext data unsigned long long block; while ((c = fgetc(file)) != EOF) { if (isdigit(c) || c == '-') { ungetc(c, file); if (fscanf(file, "%llu", & block) == 1) { numBlocks + + ; ciphertext = (unsigned long long*)realloc(ciphertext, numBlocks * sizeof(unsigned long long)); ciphertext[numBlocks - 1] = block; } } else if (c == ' ') { continue; // ignore space characters } } fclose(file); char* decrypted = decryptString(ciphertext, N, D, 3, numBlocks); printf("Decrypted plain text: %s\ ", decrypted); free(ciphertext); free(decrypted); break; } } case 3: { printf("Exit the program.\ "); break; } default: { printf("Invalid selection.\ "); break; } } cout << endl; } return 0; }
Any similarity is purely coincidental.