{"id":29057614,"url":"https://github.com/courseworks/aut_ap_2025_spring_hw5","last_synced_at":"2025-06-27T06:06:27.512Z","repository":{"id":292229534,"uuid":"973769016","full_name":"courseworks/AUT_AP_2025_Spring_HW5","owner":"courseworks","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-08T19:08:32.000Z","size":106,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-08T20:24:12.768Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/courseworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-27T17:43:13.000Z","updated_at":"2025-05-08T19:08:35.000Z","dependencies_parsed_at":"2025-05-08T20:35:45.299Z","dependency_job_id":null,"html_url":"https://github.com/courseworks/AUT_AP_2025_Spring_HW5","commit_stats":null,"previous_names":["courseworks/aut_ap_2025_spring_hw5"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/courseworks/AUT_AP_2025_Spring_HW5","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/courseworks%2FAUT_AP_2025_Spring_HW5","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/courseworks%2FAUT_AP_2025_Spring_HW5/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/courseworks%2FAUT_AP_2025_Spring_HW5/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/courseworks%2FAUT_AP_2025_Spring_HW5/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/courseworks","download_url":"https://codeload.github.com/courseworks/AUT_AP_2025_Spring_HW5/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/courseworks%2FAUT_AP_2025_Spring_HW5/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262202492,"owners_count":23274381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-27T06:06:22.222Z","updated_at":"2025-06-27T06:06:27.498Z","avatar_url":"https://github.com/courseworks.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n\u003cstrong\u003eAUT_AP_2025_Spring Homework 5\u003c/strong\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cstrong\u003e Deadline: 12th of Ordibehesht - 23:59 o'clock\u003c/strong\u003e\n\u003c/p\u003e\n\n## Overview\n\nIn this homework, you will design and implement a simple messenger system in C++. The system will support different types of messages (such as text and voice), and will allow users to send messages to each other securely using RSA cryptography. You will use the provided `crypto.h` file for all cryptographic operations.\n\nThe question is divided into several parts:\n\n1. **Message Hierarchy**: Implement a base `Message` class and derive `TextMessage` and `VoiceMessage` from it.\n2. **User and Server Classes**: Implement the `User` and `Server` classes, which interact to send, receive, and store messages.\n3. **Security**: All messages must be authenticated using RSA digital signatures.\n4. **Cryptography**: Use the provided `crypto.h` interface for key generation, signing, and verification.\n\n---\n\n## Part 1: Message Hierarchy\n\n### 1.1. The `Message` Class\n\nAll messages share some common properties. Define a base class `Message` with the following **private** member variables:\n\n```cpp\nclass Message {\npublic:\n    // (Member functions will be defined below)\nprivate:\n    std::string type;     // Type of the message (\"text\", \"voice\", ...)\n    std::string sender;   // Username of the sender\n    std::string receiver; // Username of the receiver\n    std::string time;     // Creation time in GMT, format: \"Sun Nov 13 17:50:43 2022\"\n};\n```\n\n#### Member Functions\n\nYou **must** implement the following member functions (you may add `const`, `override`, etc. as needed, but do not change the function signatures):\n\n-   **Constructor**:  \n    Assigns all member variables except `time`. The `time` variable should be set to the current GMT time in the format `\"Sun Nov 13 17:50:43 2022\"`. Use the `\u003cctime\u003e` library for this.\n\n    ```cpp\n    Message(std::string type, std::string sender, std::string receiver);\n    ```\n\n-   **Default Constructor**:  \n    Use constructor delegation to assign member variables.\n\n    ```cpp\n    Message();\n    ```\n\n-   **Getter Functions**:  \n    Since all member variables are private, provide getter functions for each:\n\n    ```cpp\n    std::string get_type();\n    std::string get_sender();\n    std::string get_receiver();\n    std::string get_time();\n    ```\n\n-   **Print Function**:  \n    Prints the message details to an output stream.\n\n    ```cpp\n    void print(std::ostream \u0026os);\n    ```\n\n    Example output:\n\n    ```\n    *************************\n    david -\u003e jenifer\n    message type: text\n    message time: Sun Nov 13 17:50:43 2022\n    *************************\n    ```\n\n-   **Stream Insertion Operator**:  \n    Overload the `\u003c\u003c` operator to print a `Message` using the `print` function.\n\n    ```cpp\n    std::ostream\u0026 operator\u003c\u003c(std::ostream \u0026os, const Message \u0026c);\n    ```\n\n**Question:**  \nAfter implementing the derived classes, answer:  \n_Why do you think we defined the `print` function and didn't implement everything in `operator\u003c\u003c` itself?_\n\n---\n\n### 1.2. The `TextMessage` Class\n\nThis class inherits from `Message` and adds a `text` member variable.\n\n```cpp\nclass TextMessage : public Message {\npublic:\n    // (Member functions will be defined below)\nprivate:\n    std::string text;\n};\n```\n\n#### Member Functions\n\n-   **Constructor**:  \n    Assigns all member variables.\n\n    ```cpp\n    TextMessage(std::string text, std::string sender, std::string receiver);\n    ```\n\n-   **Print Function**:  \n    Prints all message details, including the text.\n\n    ```cpp\n    void print(std::ostream \u0026os);\n    ```\n\n    Example output:\n\n    ```\n    *************************\n    david -\u003e jenifer\n    message type: text\n    message time: Sun Nov 13 17:50:43 2022\n    text: hello everybody\n    *************************\n    ```\n\n-   **Getter for Text**:\n\n    ```cpp\n    std::string get_text();\n    ```\n\n---\n\n### 1.3. The `VoiceMessage` Class\n\nThis class inherits from `Message` and adds a `voice` member variable, which is a vector of 5 random bytes.\n\n```cpp\nclass VoiceMessage : public Message {\npublic:\n    // (Member functions will be defined below)\nprivate:\n    std::vector\u003cunsigned char\u003e voice;\n};\n```\n\n#### Member Functions\n\n-   **Constructor**:  \n    Assigns all member variables and fills `voice` with 5 random bytes.\n\n    ```cpp\n    VoiceMessage(std::string sender, std::string receiver);\n    ```\n\n-   **Print Function**:  \n    Prints all message details, including the voice data as integers.\n\n    ```cpp\n    void print(std::ostream \u0026os);\n    ```\n\n    Example output:\n\n    ```\n    *************************\n    david -\u003e jenifer\n    message type: voice\n    message time: Sun Nov 13 17:50:43 2022\n    voice: 166 240 216 41 129\n    *************************\n    ```\n\n-   **Getter for Voice**:\n\n    ```cpp\n    std::vector\u003cunsigned char\u003e get_voice();\n    ```\n\n---\n\n## Part 2: User and Server Classes\n\nThe `User` and `Server` classes are tightly coupled. **Read all instructions before starting implementation.**\n\n### 2.1. The `User` Class\n\nRepresents a user who can send messages. Each user has a username, a private key, and a pointer to the server.\n\n```cpp\nclass User {\npublic:\n    // (Member functions will be defined below)\nprivate:\n    std::string username;     // Username of the user\n    std::string private_key;  // PEM-encoded private key\n    Server* const server;     // Pointer to the server\n};\n```\n\n#### Member Functions\n\n-   **Constructor**:  \n    Assigns all member variables.\n\n    ```cpp\n    User(std::string username, std::string private_key, Server* server);\n    ```\n\n-   **Getter for Username**:\n\n    ```cpp\n    std::string get_username();\n    ```\n\n-   **Send Text Message**:  \n    Sends a text message to another user. Returns `true` if successful, `false` otherwise.  \n    Use the `create_message` function of the `Server` class.\n\n    ```cpp\n    bool send_text_message(std::string text, std::string receiver);\n    ```\n\n-   **Send Voice Message**:  \n    Sends a voice message (5 random bytes) to another user. Returns `true` if successful, `false` otherwise.  \n    Use the `create_message` function of the `Server` class.\n\n    ```cpp\n    bool send_voice_message(std::string receiver);\n    ```\n\n---\n\n### 2.2. The `Server` Class\n\nResponsible for storing users, public keys, and messages.\n\n```cpp\nclass Server {\npublic:\n    // (Member functions will be defined below)\nprivate:\n    std::vector\u003cUser\u003e users;                        // List of users\n    std::map\u003cstd::string, std::string\u003e public_keys; // Map: username -\u003e public key\n    std::vector\u003cMessage*\u003e messages;                 // All messages sent\n};\n```\n\n#### Member Functions\n\n-   **Default Constructor**:\n\n    ```cpp\n    Server();\n    ```\n\n-   **Getter Functions**:\n\n    ```cpp\n    std::vector\u003cUser\u003e get_users();\n    std::map\u003cstd::string, std::string\u003e get_public_keys();\n    std::vector\u003cMessage*\u003e get_messages();\n    ```\n\n-   **Create User**:  \n    Creates a new user with a unique username. If the username already exists, throw `std::logic_error`.  \n    Generates an RSA key pair for the user. The private key is given to the user; the public key is stored in `public_keys`.\n\n    ```cpp\n    User create_user(std::string username);\n    ```\n\n-   **Create Message**:  \n    Adds a message to the server. The sender must sign their username as a signature.  \n    The server authenticates the signature before adding the message.\n\n    ```cpp\n    bool create_message(Message* msg, std::string signature);\n    ```\n\n-   **Get All Messages From**:  \n    Returns all messages sent from a given username.  \n    **You must use STL algorithms only (no loops).**\n\n    ```cpp\n    std::vector\u003cMessage*\u003e get_all_messages_from(std::string username);\n    ```\n\n-   **Get All Messages To**:  \n    Returns all messages sent to a given username.  \n    **You must use STL algorithms only (no loops).**\n\n    ```cpp\n    std::vector\u003cMessage*\u003e get_all_messages_to(std::string username);\n    ```\n\n-   **Get Chat**:  \n    Returns all messages between two users (regardless of direction).  \n    **You must use STL algorithms only (no loops).**\n\n    ```cpp\n    std::vector\u003cMessage*\u003e get_chat(std::string user1, std::string user2);\n    ```\n\n-   **Sort Messages**:  \n    Sorts a vector of messages by their creation time.  \n    **You must use STL algorithms only (no loops).**\n\n    ```cpp\n    void sort_msgs(std::vector\u003cMessage*\u003e msgs);\n    ```\n\n---\n\n## Part 3: Cryptography\n\n### Using the Provided `crypto.h` File\n\nYou are provided with a `crypto.h` file that contains all the cryptographic functions you need. **Do not implement your own cryptography!** Use these functions as described.\n\n#### How to Generate RSA Key Pairs\n\n```cpp\nstd::string public_key, private_key;\ncrypto::generate_key(public_key, private_key);\n```\n\n-   `public_key` and `private_key` will be PEM-encoded strings.\n\n#### How to Sign and Verify Data\n\nTo **sign** a string (e.g., a username) with a private key:\n\n```cpp\nstd::string signature = crypto::signMessage(private_key, \"my data\");\n```\n\nTo **verify** a signature with a public key:\n\n```cpp\nbool authentic = crypto::verifySignature(public_key, \"my data\", signature);\n```\n\n-   Returns `true` if the signature is valid, `false` otherwise.\n\n---\n\n## Part 4: RSA Algorithm Explanation\n\n### What is RSA?\n\nRSA is a widely-used public-key cryptosystem that enables secure data transmission and digital signatures. It is based on the mathematical difficulty of factoring large integers.\n\n#### How RSA Works\n\n-   **Key Generation**:\n    -   Each user generates a pair of keys: a public key (shared with others) and a private key (kept secret).\n-   **Signing**:\n    -   To prove a message is from a specific user, the user signs the message (or some data, like their username) with their private key.\n-   **Verification**:\n    -   Anyone with the user's public key can verify that the signature is valid and that the message was indeed signed by the owner of the private key.\n\n#### Why Use RSA in This Question?\n\n-   **Authentication**:\n    -   Ensures that only the legitimate sender can send messages as themselves.\n-   **Integrity**:\n    -   Guarantees that the message has not been tampered with.\n\n#### In Practice\n\n-   When a user sends a message, they sign their username with their private key.\n-   The server uses the sender's public key to verify the signature before accepting the message.\n\n---\n\n## Hints and Notes\n\n-   **Random Bytes**: For `VoiceMessage`, use C++ random number generation to fill the `voice` vector with 5 random bytes.\n-   **Time Formatting**: Use `std::time_t`, `std::gmtime`, and `std::strftime` to format the time string.\n-   **STL Algorithms**: For filtering and sorting messages, use algorithms like `std::copy_if`, `std::sort`, etc.\n-   **Memory Management**: Since `messages` is a vector of pointers, ensure you manage memory properly to avoid leaks.\n\n---\n\n## Provided: `crypto.h`\n\n```cpp\n// crypto.h\n#ifndef CRYPTO_H\n#define CRYPTO_H\n\n#include \u003cstring\u003e\n\nnamespace crypto {\n\n/*\n * Generate a 2048-bit RSA key pair.\n * public_key  \u003c- PEM-encoded public key\n * private_key \u003c- PEM-encoded private key\n */\nvoid generate_key(std::string\u0026 public_key, std::string\u0026 private_key);\n\n/*\n * Sign `data` using the PEM-encoded RSA private key.\n * Returns a Base64-encoded signature.\n */\nstd::string signMessage(const std::string\u0026 private_key,\n                        const std::string\u0026 data);\n\n/*\n * Verify a Base64-encoded signature over `data` using\n * the PEM-encoded RSA public key. Returns true if valid.\n */\nbool verifySignature(const std::string\u0026 public_key, const std::string\u0026 data,\n                     const std::string\u0026 signature);\n\n}  // namespace crypto\n\n#endif  // CRYPTO_H\n```\n\n---\n\n## **Final Step: How To Test Your Program**\n\nIf you want to debug your code, set the `if` statement to `true`. This will allow you to place your debugging code in the designated section. Once you're done with the debugging process, remember to set the `if` statement back to `false` to test your program using the provided `unit-test.cpp`.\n\n```cpp\n#include \u003cgtest/gtest.h\u003e\n\n#include \u003ciostream\u003e\n\n#include \"message.h\"\n#include \"server.h\"\n#include \"user.h\"\n\nint main(int argc, char **argv) {\n\tif (true)  // Set to false to run unit-tests\n\t{\n\t\t// Debug section: Place your debugging code here\n\t} else {\n\t\t::testing::InitGoogleTest(\u0026argc, argv);\n\t\tstd::cout \u003c\u003c \"RUNNING TESTS ...\" \u003c\u003c std::endl;\n\t\tint ret{RUN_ALL_TESTS()};\n\t\tif (!ret)\n\t\t\tstd::cout \u003c\u003c \"\u003c\u003c\u003cSUCCESS\u003e\u003e\u003e\" \u003c\u003c std::endl;\n\t\telse\n\t\t\tstd::cout \u003c\u003c \"FAILED\" \u003c\u003c std::endl;\n\t}\n\treturn 0;\n}\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./resource/That_Is_Why.webp\" alt=\"Are Your Really In Charge Here?\" style=\"width: 60%;\"\u003e\n\u003c/p\u003e\n\n**Best Regards, [Hamidi](https://github.com/smhamidi)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcourseworks%2Faut_ap_2025_spring_hw5","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcourseworks%2Faut_ap_2025_spring_hw5","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcourseworks%2Faut_ap_2025_spring_hw5/lists"}