/*
AUTORE: Manuel Vichi
Cifratura di una stringa con chiave privata usando il codice ASCII
*/
#include <iostream>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
void clearConsole() {
    #ifdef _WIN32
        system("cls"); // Windows
    #else
        system("clear"); // MacOS/Linux
    #endif
}
char * encryptString(char * const string, char * const private_key, size_t private_key_length) {
	for (size_t i = 0, s = 0; string[i] != '\0'; i++,s++) {
		if (s == private_key_length)
			s = 0;
		string[i] = string[i] + private_key[s];
	}
	return string;
}
char * decryptString(char * const string, char * const private_key, size_t private_key_length) {
	for (size_t i = 0, s = 0; string[i] != '\0'; i++,s++) {
		if (s == private_key_length)
			s = 0;
		string[i] = string[i] - private_key[s];
	}
	return string;
}
int main(void) {
	char privkey[20+1];
	cout << "Benvenuto nella cifratura di stringhe" << endl << endl;
	cout << "Per iniziare, ti verra' chiesta la chiave privata." << endl << "La chiave privata e' una stringa che viene usata per cifrarne un'altra, e senza di essa la stringa cifrata e' quasi impossibile da decifrare." << endl << "Assicurati di non perdere la chiave privata e di fornirla a chi dovra decifrare la stringa." << endl << "Premendo invio, la console verra pulita, assicurati quindi di salvare la chiave privata prima di digitarla nel programma." << endl;
	cout << "Chiave privata (20 caratteri): ";
	cin.getline(privkey,sizeof(privkey));
	cout << endl;
	if (privkey[0] == '\0') {
		cerr << "La chiave privata non puo' essere vuota." << endl;
		return -1;
	}
	clearConsole(); // Pulizia della console cross-platform
	char stringa[80+1];
	int num = 0;
	cout << "Benvenuto nella cifratura di stringhe" << endl << endl << "1 - Cifra stringa" << endl << "2 - Decifra stringa" << endl;
	do {
		cout << "Scelta: ";
		cin >> num;
		cout << endl;
	} while (num < 0 || num > 2);
	if (num == 0)
		return -1;
	switch (num) {
		case 1:
			cout << "Inserire la stringa: ";
			cin.ignore(); // Fix per la getline
			cin.getline(stringa,sizeof(stringa));
			cout << endl;
			encryptString(stringa,privkey,strlen(privkey));
			cout << "Stringa cifrata: " << stringa << endl;
			break;
		case 2:
			cout << "Inserire la stringa cifrata: ";
			cin.ignore(); // Fix per la getline
			cin.getline(stringa,sizeof(stringa));
			cout << endl;
			decryptString(stringa,privkey,strlen(privkey));
			cout << "Stringa decifrata: " << stringa << endl;
			break;
		default:
			return -1;
	}
	cout << endl << "Premere Invio per chiudere...";
	getchar();
	return 0;
}
