From e785d5bd68f19de4c7d8fd3bbc5a0bb6a726cdb3 Mon Sep 17 00:00:00 2001 From: Andreas Gagas Date: Sat, 21 Nov 2020 19:19:35 -0500 Subject: [PATCH] CA, AS connected and step1 completed --- Lab6/ca.cpp | 125 +++++++++++++++++++++++++++++++++++++---- Lab6/server.cpp | 146 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 217 insertions(+), 54 deletions(-) diff --git a/Lab6/ca.cpp b/Lab6/ca.cpp index 2c29876..f0ab3cf 100644 --- a/Lab6/ca.cpp +++ b/Lab6/ca.cpp @@ -36,7 +36,10 @@ long long int get_epoch_time_seconds(); std::string encrypt_rsa(CryptoPP::RSA::PublicKey key, CryptoPP::AutoSeededRandomPool rng, std::string plain); -std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, CryptoPP::AutoSeededRandomPool rng, std::string cipher); +std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, std::string cipher); +std::string sign_rsa(CryptoPP::RSA::PrivateKey SK_CA, std::string message); + +std::string encrypt_des(std::string key_string, std::string plaintext); @@ -55,7 +58,6 @@ int main(int argc, char** argv) { std::string AD_C = "127.0.01:" + std::to_string(port_num); - // ===================== Generate RSA public/private keys and preshare PUBLIC key =================================================== CryptoPP::AutoSeededRandomPool rng; @@ -67,15 +69,11 @@ int main(int argc, char** argv) { // write public key PK_CA to a file, to "preshare" // use of CryptoPP to store CryptoPP::RSA::PublicKey in a file (instead of string with {n,e}). - CryptoPP::Base64Encoder public_key_sink(new CryptoPP::FileSink("public_key.txt")); PK_CA.DEREncode(public_key_sink); public_key_sink.MessageEnd(); - - - // ===================== Network Setup (Winsock) =================================================== // Init Winsock @@ -134,7 +132,7 @@ int main(int argc, char** argv) { return 1; } - std::cout << "(CA) Connected" << std::endl << std::endl; + std::cout << "(CA) Connected to (S)" << std::endl << std::endl; closesocket(ca_socket); char message_receive[BUFFER_LENGTH] = { 0 }; @@ -142,10 +140,76 @@ int main(int argc, char** argv) { std::string plaintext, ciphertext; + while (true) { + + std::cout << "\n (CA) Waiting to receive a message ... \n" << std::endl; + + // server will send RSA_PK_CA[K_tmp1 || ID_S || TS_1] + while ((retval_receive = recv(server_socket, message_receive, BUFFER_LENGTH, 0)) > 0) { + + if (retval_receive > 0) { + ciphertext.clear(); + ciphertext.append(message_receive, retval_receive); + + + // Decrypt using private key SK_CA to get K_TMP1 || ID_S || TS_1 + plaintext = decrypt_rsa(SK_CA, ciphertext); + + // Print out ciphertext and temp des key + std::cout << "\n***************************************************************" << std::endl; + std::cout << "(CA) received ciphertext: " << ciphertext << std::endl; + std::cout << "(CA) received K_TMP1 " << plaintext.substr(0, 8) << std::endl; + std::cout << "***************************************************************\n" << std::endl; + + // ===================== STEP 2 =================================================== + + // Extract DES_K_TMP1 from plaintext + std::string k_tmp1 = plaintext.substr(0, 8); // been using 8-byte keys + // Generate new public/private key pair for S (params defined above, key-size 1024) + CryptoPP::RSA::PrivateKey SK_S(params); // private key + CryptoPP::RSA::PublicKey PK_S(params); // public key + + + + // Build Cert_S = Sign_SK_CA [ID_S || IC_CA || PK_S] + std::string sign_sk_ca = ID_S; + sign_sk_ca += ID_CA; + //sign_sk_ca += PK_S; + + // Sign + sign_sk_ca = sign_rsa(SK_CA, sign_sk_ca); + + // Build PK_S || SK_S || CERT_S || ID_S || TS_2 + plaintext.clear(); + plaintext += "TODO"; + plaintext += "TODO"; + plaintext += sign_sk_ca; + plaintext += ID_S; + plaintext += std::to_string(get_epoch_time_seconds()); + + // Encrypt using DES_K_TMP1 + ciphertext = encrypt_des(k_tmp1, plaintext); + + // SEND encrypted msg (new key pair, cert_s, etc...) to client + + + + + } + } + + if (retval_receive <= 0) break; // server disconnected (likely connected to C, as work with CA done)) + } + // cleanup + shutdown(server_socket, SD_SEND); + closesocket(server_socket); + WSACleanup(); + std::cout << "CA closed" << std::endl; + return 0; } long long int get_epoch_time_seconds() { @@ -172,12 +236,12 @@ std::string encrypt_rsa(CryptoPP::RSA::PublicKey key, CryptoPP::AutoSeededRandom return cipher; } -std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, CryptoPP::AutoSeededRandomPool rng, std::string cipher) { +std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, std::string cipher) { // RSA decryption - std::string plain; - + CryptoPP::AutoSeededRandomPool rng; CryptoPP::RSAES_OAEP_SHA_Decryptor d(key); + std::string plain; CryptoPP::StringSource ss2(cipher, true, new CryptoPP::PK_DecryptorFilter(rng, d, @@ -188,3 +252,44 @@ std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, CryptoPP::AutoSeededRando return plain; } +std::string sign_rsa(CryptoPP::RSA::PrivateKey SK_CA, std::string message) { + // rsa signature, do so w/ privatekey + + CryptoPP::AutoSeededRandomPool rng; + CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(SK_CA); + std::string signature; + + + CryptoPP::StringSource ss1(message, true, + new CryptoPP::SignerFilter(rng, signer, + new CryptoPP::StringSink(signature) + ) + ); + + return signature; +} + +std::string encrypt_des(std::string key_string, std::string plaintext) { + + CryptoPP::SecByteBlock key((const unsigned char*)(key_string.data()), key_string.size()); + std::string ciphertext; + + try { + CryptoPP::ECB_Mode< CryptoPP::DES >::Encryption encrypt; + encrypt.SetKey(key, key.size()); + + // Encrypt, add padding if needed + CryptoPP::StringSource(plaintext, true, + new CryptoPP::StreamTransformationFilter(encrypt, + new CryptoPP::StringSink(ciphertext) + ) + ); + } + catch (const CryptoPP::Exception& err) { + std::cerr << "ERROR" << err.what() << std::endl; + exit(1); + } + + return ciphertext; +} + diff --git a/Lab6/server.cpp b/Lab6/server.cpp index 91f81f1..c8340a1 100644 --- a/Lab6/server.cpp +++ b/Lab6/server.cpp @@ -22,17 +22,21 @@ #include "cryptopp820/hex.h" #include "cryptopp820/secblock.h" #include "cryptopp820/modes.h" + #include "cryptopp820/rsa.h" +#include "cryptopp820/base64.h" +#include "cryptopp820/files.h" #define DEFAULT_PORT_NUM 8000 #define BUFFER_LENGTH 512 #define ID_CA "ID-CA" #define ID_S "ID-Server" +#define LIFETIME_SESS 86400 long long int get_epoch_time_seconds(); std::string encrypt_rsa(CryptoPP::RSA::PublicKey key, std::string plain); -std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, std::string cipher); +std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, CryptoPP::AutoSeededRandomPool rng, std::string cipher); int main(int argc, char** argv) { @@ -50,16 +54,29 @@ int main(int argc, char** argv) { std::string AD_C = "127.0.01:" + std::to_string(port_num); - // ====================== STEP 1 ("registers" with CA to get own public/private keys and cert) ======= - + + // Read des_key + //std::string des_key_string; + //std::cout << "des_key_string:" << des_key_string << std::cout; + // ===================== GET PUBLIC KEY PK_CA =================================================== + // CryptoPP::RSA::PublicKey was encoded and stored in "public_key.txt" + // Read, decode, and init CryptoPP::RSA::PublicKey to have CA's public key - // ===================== Network Setup (Winsock) =================================================== + CryptoPP::ByteQueue bytes; + CryptoPP::FileSource file("public_key.txt", true, new CryptoPP::Base64Decoder); + file.TransferTo(bytes); + bytes.MessageEnd(); + + CryptoPP::RSA::PublicKey PK_CA; + PK_CA.Load(bytes); + + // ===================== Network Setup (Winsock) to connect to CA first =================================================== - // Init Winsock WSADATA wsa_data; + // Init Winsock int retval = WSAStartup(MAKEWORD(2, 2), &wsa_data); if (retval != 0) { std::cout << "Error, WSAStartup failed" << std::endl; @@ -67,65 +84,84 @@ int main(int argc, char** argv) { } // Prepare sockaddr_in structure - struct sockaddr_in server, client; + struct sockaddr_in ca; - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; // default 127.0.0.1 - server.sin_port = htons(port_num); // default is 8000 + ca.sin_family = AF_INET; + ca.sin_addr.s_addr = inet_addr("127.0.0.1"); + ca.sin_port = htons(port_num); // default is 8000 - // Create Socket (server) - SOCKET server_socket; + // Create Socket (server to connect) + SOCKET connected_socket; - server_socket = socket(AF_INET, SOCK_STREAM, 0); - if (server_socket == INVALID_SOCKET) { + connected_socket = socket(AF_INET, SOCK_STREAM, 0); + if (connected_socket == INVALID_SOCKET) { std::cout << "Error, socket creation failed" << std::endl; WSACleanup(); return 1; } - // Bind (server socket address to socket desc.) - retval = bind(server_socket, (struct sockaddr*)&server, sizeof(server)); + // --------------- Connect to CA ------------------- + retval = connect(connected_socket, (struct sockaddr*)&ca, sizeof(ca)); if (retval == SOCKET_ERROR) { - std::cout << "Error, failed to bind" << std::endl; - closesocket(server_socket); + std::cout << "Error, failed to connect" << std::endl; + closesocket(connected_socket); WSACleanup(); return 1; } - // Listen - retval = listen(server_socket, SOMAXCONN); - std::cout << std::endl << "Waiting for incoming connection from 127.0.0.1 on PORT: " << port_num << std::endl; - if (retval == SOCKET_ERROR) { - std::cout << "Error, failed to listen" << std::endl; - closesocket(server_socket); - WSACleanup(); - return 1; - } - - // Accept connection (client) - SOCKET client_socket; - - client_socket = accept(server_socket, NULL, NULL); - if (client_socket == INVALID_SOCKET) { - std::cout << "Error, failed to accept connection" << std::endl; - closesocket(server_socket); - WSACleanup(); - return 1; - } - - std::cout << "(S) Connected" << std::endl << std::endl; - closesocket(server_socket); + std::cout << "(S) Connected to (CA)" << std::endl << std::endl; char message_receive[BUFFER_LENGTH] = { 0 }; int retval_send = 0, retval_receive = 0; std::string plaintext, ciphertext; + while (true) { + + // ===================== STEP 1, Register w/ CA =================================================== + + // temp DES key (testing) CHANGE LATER + std::string temp_des = "aBcjEFg4"; + + plaintext.clear(); + plaintext += temp_des; + plaintext += ID_S; + plaintext += std::to_string(get_epoch_time_seconds()); + + // Encrypt using, CA's public key: PK_CA + ciphertext = encrypt_rsa(PK_CA, plaintext); + + + do { + // Prompt server if ready to register with CA + std::cout << "Register with CA (RSA_PK_CA[K_TMP1 || ID_S || TS_1])? hit any key to confirm ...\n"; + } while (std::cin.get() != '\n'); + + // Send info to register with CA + retval_send = send(connected_socket, ciphertext.c_str(), ciphertext.size(), 0); + if (retval_send == SOCKET_ERROR) { + std::cout << "Error, failed to send" << std::endl; + closesocket(connected_socket); + WSACleanup(); + return 1; + } + std::cout << "\n(S) Waiting to receive a message from CA ... \n" << std::endl; + + + + } + // close old socket + // CONNECT to C (client.cpp) + + //shutdown(connected_socket2, SD_SEND); + //closesocket(connected_socket2); + //WSACleanup(); + std::cout << "(S) Server closed" << std::endl; return 0; @@ -142,14 +178,36 @@ long long int get_epoch_time_seconds() { std::string encrypt_rsa(CryptoPP::RSA::PublicKey key, std::string plain) { // RSA encryption (RSAES encryption scheme (OAEP using SHA-256). use CryptoPP filters to do so ...) + CryptoPP::AutoSeededRandomPool rng; + CryptoPP::RSAES_OAEP_SHA_Encryptor e(key); + std::string cipher; + + CryptoPP::StringSource(plain, true, + new CryptoPP::PK_EncryptorFilter(rng, e, + new CryptoPP::StringSink(cipher) + ) + ); + + return cipher; +} + +std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, CryptoPP::AutoSeededRandomPool rng, std::string cipher) { + // RSA decryption + + std::string plain; + CryptoPP::RSAES_OAEP_SHA_Decryptor d(key); + CryptoPP::StringSource ss2(cipher, true, + new CryptoPP::PK_DecryptorFilter(rng, d, + new CryptoPP::StringSink(plain) + ) + ); - return ""; + return plain; } -std::string decrypt_rsa(CryptoPP::RSA::PrivateKey key, std::string cipher) { - return ""; -} \ No newline at end of file + +