├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── src ├── MatrixEncryptor.cpp ├── MatrixEncryptor.h ├── More Example ├── InputHandler.cpp ├── InputHandler.h └── main.cpp └── mainexample.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.a 22 | *.lib 23 | 24 | # Executables 25 | *.exe 26 | *.out 27 | *.app 28 | 29 | # CMake build directory 30 | build/ 31 | 32 | # Visual Studio Code workspace settings folder 33 | .vscode/ 34 | 35 | # macOS specific files 36 | .DS_Store 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Faruk Alpay 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX := g++ 2 | CXXFLAGS := -Wall -Werror -Wextra -pedantic -std=c++23 -march=native -O3 3 | 4 | TARGET := encryptor 5 | 6 | SRC := src/mainexample.cpp src/MatrixEncryptor.cpp 7 | OBJ := $(SRC:.cpp=.o) 8 | 9 | all: $(TARGET) 10 | 11 | $(TARGET): $(OBJ) 12 | $(CXX) $(CXXFLAGS) -o $@ $^ 13 | 14 | %.o: %.cpp 15 | $(CXX) $(CXXFLAGS) -c -o $@ $< 16 | 17 | clean: 18 | rm -f $(OBJ) $(TARGET) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Hits](https://hits.sh/github.com/farukalpay/TextEncryptionWithLinearAlgebra.svg)](https://hits.sh/github.com/farukalpay/TextEncryptionWithLinearAlgebra/) 2 | 3 | ## Introduction 4 | 5 | This project implements a text encryption and decryption system using a matrix-based encryption technique. This project serves as an educational and practical exploration of matrix-based encryption techniques, demonstrating the fundamental concepts of encryption and decryption in a user-friendly manner. 6 | 7 | ## How to implement this Library 8 | 9 | Clone the repository and copy the library your local project folder then include `MatrixEncryptor.h`. After that you need to implement [Eigen](https://gitlab.com/libeigen/eigen) to your project. From the given link, only the folder Eigen is required. After putting it to your project folder, from your Project's Property Pages, `C/C++ -> General -> Additional Include Directories` add Eigen folder's path. 10 | 11 | ## Getting started 12 | 13 | ### Prerequisites 14 | Before getting started with **Text Encryption With Linear Algebra**, ensure that you have the following dependencies installed on your Linux system: 15 | - **g++ compiler** 16 | - [**Eigen library**](https://eigen.tuxfamily.org/index.php?title=Main_Page) 17 | 18 | ### Installation 19 | To use the **Text Encryption With Linear Algebra**, follow these steps: 20 | 21 | 1. Clone this repository 22 | ```Bash 23 | git clone git@github.com:farukalpay/TextEncryptionWithLinearAlgebra.git 24 | ``` 25 | 2. Clone the repository of Eigen Library: 26 | ```Bash 27 | git clone https://gitlab.com/libeigen/eigen 28 | ``` 29 | 3. Go inside the directory of Eigen Library and copy the directory Eigen into this repository 30 | ```Bash 31 | cp -r 32 | ``` 33 | 4. Use the Makefile to compile with make 34 | ```Bash 35 | make 36 | ``` 37 | 5. Now you should see the executable in the directory of **Text Encryption With Linear Algebra** 38 | 39 | ## Explanation of the Algorithm 40 | 41 | ### Convert Input String to ASCII Integer 42 | 43 | 1. **Initialization**: 44 | - Given an input string $S$ of length $n$, where $S = s_1 s_2 s_3 \ldots s_n$, and each $s_i$ represents a character in the string.\ 45 | Initialize an empty vector $\text{parsed}$ to store the ASCII integer representations of characters extracted from the input string $S$. 46 | 47 | - Consider the input string $S = \text{"Hello World"}$.\ 48 | Initialize $\text{parsed} = []$. 49 | 50 | 2. **Token Extraction**: 51 | - Extract tokens (words) from the input string $S$. Let $T_1, T_2, \ldots, T_m$ be the tokens extracted from $S$, where $m$ is the number of tokens. 52 | 53 | - Extract tokens: $T_1 = \text{"Hello"}$ and $T_2 = \text{"World"}$. 54 | 55 | 3. **Character Processing for Token $T_i$**: 56 | - For each token $T_i$, consisting of characters $t_{i1}, t_{i2}, \ldots, t_{ik}$, where $k$ is the length of the token: 57 | - Convert each character $t_{ij}$ to its ASCII integer representation $a_{ij}$. 58 | - Add each $a_{ij}$ to end of the $parsed$ vector. 59 | 60 | - Convert 'H' to ASCII integer $72$, 'e' to $101$, 'l' to $108$, 'l' to $108$, 'o' to $111$.\ 61 | Add these integers to $\text{parsed}$: $[72, 101, 108, 108, 111]$. 62 | 63 | 4. **Adding Space**: 64 | - After processing each character in a token $T_i$, add a space character ' ' to the $parsed$ vector. 65 | 66 | - Add a space ' ' to $\text{parsed}$. 67 | 68 | 5. **End of Token**: 69 | - Repeat steps 3-4 for all tokens $T_1, T_2, \ldots, T_m$. 70 | 71 | - Process characters for $T_2$: 72 | - Convert 'W' to ASCII integer $87$, 'o' to $111$, 'r' to $114$, 'l' to $108$, 'd' to $100$. 73 | - Add these integers to $\text{parsed}$: $[87, 111, 114, 108, 100]$. 74 | - Add a space ' ' to $\text{parsed}$. 75 | 76 | 6. **Return Result**: 77 | - The function returns the $\text{parsed}$ vector containing ASCII integer representations of characters in $S$, with spaces after each token. 78 | 79 | - Return $\text{parsed} = [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 32]$. 80 | 81 | ### Generate Random Key 82 | 83 | 1. **Initialization**: 84 | - Let $key$ be a square matrix of size $size \times size$, represented as $key = [key_{ij}]$ where $i, j = 0, 1, \ldots, size - 1$. 85 | - Each element $key_{ij}$ denotes a value in the key matrix. 86 | 87 | - Consider the ASCII representation of the string ${\text{"hi"} + \text{Space (ASCII 32)}}$, where the ASCII values are $[104, 105, 32]$. Let $key$ be a square matrix of size $3 \times 3$ 88 | 89 | 2. **Random Number Generation Setup**: 90 | - Initialize a pseudo-random number generator with a random seed. 91 | 92 | 3. **Uniform Distribution Setup**: 93 | - Define a uniform distribution to produce random numbers uniformly distributed between -10.0 and 10.0. 94 | 95 | 4. **Random Key Generation**: 96 | - For each element $key_{ij}$ of $key$: 97 | - Sample a random value $r_{ij}$ from the uniform distribution. 98 | - Assign $r_{ij}$ as the value of $key_{ij}$ in the key matrix. 99 | - Mathematically, $key_{ij} = r_{ij}$ for $i, j = 0, 1, \ldots, size - 1$. 100 | 101 | 5. **Return the Key**: 102 | - Once all elements of the matrix $key$ have been assigned random values, return the resulting key matrix $key$. 103 | 104 | - Generated key matrix for $[104, 105, 32]$: 105 | 106 | $$ 107 | \text{K} = 108 | \begin{bmatrix} 109 | 1.25024 & -2.33247 & -3.94038 \\ 110 | 3.39427 & 0.800577 & -5.14653 \\ 111 | -6.62477 & -1.65797 & 3.84418 112 | \end{bmatrix} 113 | $$ 114 | 115 | ### Encryption Algorithm 116 | 117 | 1. **Message Padding**: 118 | - Given a message $M$ represented as a vector of integers $\text{message} = [m_1, m_2, \ldots, m_n]$, where $n$ is the size of the message and $\text{size}$ is the size of the key matrix. 119 | - Determine the remainder $r$ when dividing the size of the message by the size of the key matrix: $r = \text{size} - (n \mod \text{size})$. 120 | - Pad the message with spaces to make its size a multiple of the size of the key matrix: $M' = [m_1, m_2, \ldots, m_n, \underbrace{\text{space}, \text{space}, \ldots, \text{space}}_{r \text{ times}}]$. 121 | 122 | - The message $\text{"hi"}$ corresponds to the vector $\text{message} = [104, 105, 32]$. Since the size of the key matrix is 3, the message needs to be padded with spaces to make its size a multiple of $3$. Thus, the padded message becomes $[104, 105, 32, 32, 32, 32]$. 123 | 124 | 2. **Message Vectorization**: 125 | - Split the padded message $M'$ into vectors of size $\text{size}$: $\text{messageVector}_1, \text{messageVector}_2, \ldots, \text{messageVector}_k$, where $k = \frac{n + r}{\text{size}}$. 126 | - Each $\text{messageVector}_i$ is a column vector of size $\text{size}$ containing consecutive elements from $M'$. 127 | 128 | - Generated $\text{messageVector}_i$ column matrices for $[104, 105, 32, 32, 32, 32]$: 129 | 130 | $$ 131 | \text{messageVector}_1 = 132 | \begin{bmatrix} 133 | 104 \\ 134 | 105 \\ 135 | 32 136 | \end{bmatrix}, 137 | \quad 138 | \text{messageVector}_2 = 139 | \begin{bmatrix} 140 | 32 \\ 141 | 32 \\ 142 | 32 143 | \end{bmatrix} 144 | $$ 145 | 146 | 147 | 3. **Encryption**: 148 | 149 | - For each message vector $\text{messageVector}_i$: 150 | - Perform matrix-vector multiplication with the key matrix $K$: $\text{encryptedVector}_i = K \cdot \text{messageVector}_i$. 151 | - After performing the matrix-vector multiplication, the resulting elements in $\text{encryptedVector}_i$ rounded to the nearest integer. 152 | - Each element of $\text{encryptedVector}_i$ represents an encrypted value corresponding to the corresponding message vector element. 153 | 154 | For $\text{messageVector}_1$: 155 | 156 | $$ 157 | \text{encryptedVector}_1 = K \cdot \text{messageVector}_1 = 158 | \begin{bmatrix} 159 | 1.25024 & -2.33247 & -3.94038 \\ 160 | 3.39427 & 0.800577 & -5.14653 \\ 161 | -6.62477 & -1.65797 & 3.84418 162 | \end{bmatrix} 163 | \begin{bmatrix} 164 | 104 \\ 165 | 105 \\ 166 | 32 167 | \end{bmatrix} = 168 | \begin{bmatrix} 169 | -(int + round)240.97655 \\ 170 | (int + round)272.375705 \\ 171 | -(int + round)740.04917 172 | \end{bmatrix} = 173 | \begin{bmatrix} 174 | -241 \\ 175 | 272 \\ 176 | -740 177 | \end{bmatrix} 178 | $$ 179 | 180 | For $\text{messageVector}_2$: 181 | 182 | $$ 183 | \text{encryptedVector}_2 = K \cdot \text{messageVector}_2 = 184 | \begin{bmatrix} 185 | 1.25024 & -2.33247 & -3.94038 \\ 186 | 3.39427 & 0.800577 & -5.14653 \\ 187 | -6.62477 & -1.65797 & 3.84418 188 | \end{bmatrix} 189 | \begin{bmatrix} 190 | 32 \\ 191 | 32 \\ 192 | 32 193 | \end{bmatrix} = 194 | \begin{bmatrix} 195 | -(int + round)160.72352 \\ 196 | -(int + round)30.453856 \\ 197 | -(int + round)142.03392 198 | \end{bmatrix} = 199 | \begin{bmatrix} 200 | -161 \\ 201 | -30 \\ 202 | -142 203 | \end{bmatrix} 204 | $$ 205 | 206 | 4. **Result**: 207 | - Concatenate all elements of the encrypted vectors to form the encrypted message $E$: $E = [\text{encryptedVector}_1[1], \text{encryptedVector}_1[2], \ldots, \text{encryptedVector}_k[\text{size}], \ldots]$. 208 | 209 | - The resulting encrypted message corresponding to the input $\text{"hi"}$ encrypted using this key matrix is: 210 | 211 | $$ 212 | \text{E = [-241, 272, -740, -161, -30, -142]} 213 | $$ 214 | 215 | ### Decryption Algorithm 216 | 217 | 1. **Initialization**: 218 | - Let $\text{EncryptedMessage} = [e_1, e_2, \ldots, e_n]$ be the encrypted message represented as a vector of integers, where $n$ is the size of the encrypted message. 219 | 220 | - Consider the encrypted message ${E = [-241, 272, -740, -161, -30, -142]}$ 221 | - Key matrix $K$ used for encryption: 222 | 223 | $$ 224 | \text{K} = 225 | \begin{bmatrix} 226 | 1.25024 & -2.33247 & -3.94038 \\ 227 | 3.39427 & 0.800577 & -5.14653 \\ 228 | -6.62477 & -1.65797 & 3.84418 229 | \end{bmatrix} 230 | $$ 231 | 232 | 2. **Segmentation**: 233 | 234 | - Divide the encrypted message into segments, each consisting of $\text{size}$ elements, where $\text{size}$ is the size of the key matrix $K$. 235 | 236 | - Segments of the encrypted message, denoted as $\text{Segment}_i$, are obtained by splitting $\text{EncryptedMessage}$ into $\frac{n}{\text{size}}$ segments, where $i$ ranges from $1$ to $\frac{n}{\text{size}}$. 237 | 238 | - Each segment $\text{Segment}_i$ consists of $\text{size}$ consecutive elements starting from index $i \times \text{size}$. 239 | 240 | - Each segment $\text{Segment}_i$ is represented as a column matrix of size $\text{size}$: 241 | 242 | $$ 243 | \text{Segment}\_i = 244 | \begin{bmatrix} 245 | e_{(i-1) \times \text{size} + 1} \\ 246 | e_{(i-1) \times \text{size} + 2} \\ 247 | \vdots \\ 248 | e_{i \times \text{size}} 249 | \end{bmatrix} 250 | $$ 251 | 252 | - Segmented column matrices for ${E = [-241, 272, -740, -161, -30, -142]}$: 253 | 254 | $$ 255 | \text{EncryptedVector}_1 = 256 | \begin{bmatrix} 257 | -241 \\ 258 | 272 \\ 259 | -740 260 | \end{bmatrix}, 261 | \quad 262 | \text{EncryptedVector}_2 = 263 | \begin{bmatrix} 264 | -161 \\ 265 | -30 \\ 266 | -142 \\ 267 | \end{bmatrix} 268 | $$ 269 | 270 | 3. **Matrix Multiplication**: 271 | 272 | - For each segment $\text{encryptedVector}_i$: 273 | - Perform matrix-vector multiplication with the inverse key matrix $K^{-1}$: $\text{decryptedVector}_i = K^{-1} \cdot \text{encryptedVector}_i$ 274 | - After performing the matrix-vector multiplication, the resulting elements in $\text{decryptedVector}_i$ rounded to the nearest integer. 275 | - Each element of $\text{decryptedVector}_i$ represents an decrypted ASCII value corresponding to the corresponding message vector element. 276 | 277 | For $\text{encryptedVector}_1$: 278 | 279 | $$ 280 | \text{decryptedVector}_1 = K^{-1} \cdot \text{encryptedVector}_1 = 281 | \begin{bmatrix} 282 | 0.09985 & -0.28369 & -0.27745 \\ 283 | -0.38522 & 0.38983 & 0.12703 \\ 284 | 0.00592 & -0.32077 & -0.16323 285 | \end{bmatrix} 286 | \begin{bmatrix} 287 | -241 \\ 288 | 272 \\ 289 | -740 290 | \end{bmatrix} = 291 | \begin{bmatrix} 292 | (int + round)104.09060 \\ 293 | (int + round)104.86881 \\ 294 | (int + round)32.11234 295 | \end{bmatrix} = 296 | \begin{bmatrix} 297 | 104 \\ 298 | 105 \\ 299 | 32 300 | \end{bmatrix} 301 | $$ 302 | 303 | For $\text{encryptedVector}_2$: 304 | 305 | $$ 306 | \text{decryptedVector}_2 = K^{-1} \cdot \text{encryptedVector}_2 = 307 | \begin{bmatrix} 308 | 0.09985 & -0.28369 & -0.27745 \\ 309 | -0.38522 & 0.38983 & 0.12703 \\ 310 | 0.00592 & -0.32077 & -0.16323 311 | \end{bmatrix} 312 | \begin{bmatrix} 313 | -161 \\ 314 | -30 \\ 315 | -142 316 | \end{bmatrix} = 317 | \begin{bmatrix} 318 | (int + round)31.83422 \\ 319 | (int + round)32.28774 \\ 320 | (int + round)31.84724 321 | \end{bmatrix} = 322 | \begin{bmatrix} 323 | 32 \\ 324 | 32 \\ 325 | 32 326 | \end{bmatrix} 327 | $$ 328 | 329 | 5. **Result**: 330 | - Concatenate all elements of the decrypted message vectors to form the decrypted message $D$: $D = [\text{decryptedVector}_1[1], \text{decryptedVector}_1[2], \ldots, \text{decryptedVector}_k[\text{size}], \ldots]$. The resulting decrypted message is a sequence of ASCII characters obtained by converting each integer in $D$ to its corresponding ASCII character. 331 | 332 | - The resulting decrypted message corresponding to the encrypted message ${E = [-241, 272, -740, -161, -30, -142]}$ decrypted using the key matrix is: 333 | 334 | $$ 335 | \text{D = [104, 105, 32, 32, 32, 32]} 336 | $$ 337 | 338 | The decrypted message $D$ is obtained by converting each integer in the sequence to its corresponding ASCII character. Therefore, the decrypted message is $\text{"hi "}$. 339 | 340 | ## Example Runtime Screenshots 341 | ###### Encryption 342 | ![](https://raw.githubusercontent.com/farukalpay/TextEncryptionWithLinearAlgebra/gh-pages/img/encrypt.png) 343 | ###### Decryption 344 | ![](https://github.com/farukalpay/TextEncryptionWithLinearAlgebra/blob/gh-pages/img/decrypted.png) 345 | -------------------------------------------------------------------------------- /src/MatrixEncryptor.cpp: -------------------------------------------------------------------------------- 1 | #include "MatrixEncryptor.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace { 7 | inline void removeLastASCIISpaces(std::vector& data) { 8 | while (!data.empty() && data.back() == ' ') { 9 | data.pop_back(); 10 | } 11 | } 12 | } 13 | 14 | Eigen::MatrixXd MatrixEncryptor::generateRandomKey(int size) { 15 | Eigen::MatrixXd key(size, size); 16 | std::random_device rd; 17 | std::mt19937 generator(rd()); 18 | std::uniform_real_distribution distribution(-10.0, 10.0); 19 | 20 | for (int i = 0; i < size; ++i) { 21 | for (int j = 0; j < size; ++j) { 22 | key(i, j) = distribution(generator); 23 | } 24 | } 25 | return key; 26 | } 27 | 28 | MatrixEncryptor::MatrixEncryptor(int size) { 29 | keyMatrix = generateRandomKey(size); 30 | } 31 | 32 | MatrixEncryptor::MatrixEncryptor(const Eigen::MatrixXd& customKey) : keyMatrix(customKey) {} 33 | 34 | std::vector MatrixEncryptor::encrypt(const std::vector& message) const { 35 | int size = keyMatrix.rows(); 36 | int messageSize = message.size(); 37 | int remainder = size - (messageSize % size); 38 | std::vector paddedMessage = message; 39 | paddedMessage.insert(paddedMessage.end(), remainder, ' '); // Padding message with spaces to make its size a multiple of the key matrix size 40 | 41 | std::vector encrypted_message; 42 | for (size_t i = 0; i < paddedMessage.size(); i += size) { 43 | Eigen::VectorXd messageVector(size); 44 | for (int j = 0; j < size; ++j) { 45 | messageVector(j) = paddedMessage[i + j]; 46 | } 47 | Eigen::VectorXd encryptedVector = keyMatrix * messageVector; 48 | for (int j = 0; j < size; ++j) { 49 | encrypted_message.push_back(static_cast(std::round(encryptedVector(j)))); 50 | } 51 | } 52 | return encrypted_message; 53 | } 54 | 55 | std::vector MatrixEncryptor::decrypt(const std::vector& encrypted_message, int size) const { 56 | std::vector decrypted_message; 57 | for (size_t i = 0; i < encrypted_message.size(); i += size) { 58 | Eigen::VectorXd encryptedVector(size); 59 | for (int j = 0; j < size; ++j) { 60 | encryptedVector(j) = encrypted_message[i + j]; 61 | } 62 | Eigen::MatrixXd inverseKey = keyMatrix.inverse(); 63 | Eigen::VectorXd decryptedVector = inverseKey * encryptedVector; 64 | for (int j = 0; j < size; ++j) { 65 | // Round to the nearest integer before converting back to int 66 | int decrypted_value = static_cast(std::round(decryptedVector(j))); 67 | decrypted_message.push_back(decrypted_value); 68 | } 69 | } 70 | removeLastASCIISpaces(decrypted_message); 71 | return decrypted_message; 72 | } 73 | 74 | const Eigen::MatrixXd& MatrixEncryptor::getKey() const { 75 | return keyMatrix; 76 | } 77 | 78 | std::vector MatrixEncryptor::parseInput(const std::string& input) { 79 | std::vector parsed; 80 | std::istringstream iss(input); 81 | std::string token; 82 | while (iss >> token) { 83 | for (char c : token) { 84 | parsed.push_back(static_cast(c)); 85 | } 86 | parsed.push_back(' '); // Add space after each token 87 | } 88 | return parsed; 89 | } 90 | 91 | Eigen::MatrixXd MatrixEncryptor::getCustomKey(int size) { 92 | Eigen::MatrixXd customKey(size, size); 93 | for (int i = 0; i < size; ++i) { 94 | for (int j = 0; j < size; ++j) { 95 | std::cin >> customKey(i, j); 96 | } 97 | } 98 | return customKey; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/MatrixEncryptor.h: -------------------------------------------------------------------------------- 1 | #ifndef MATRIXENCRYPTOR_H 2 | #define MATRIXENCRYPTOR_H 3 | 4 | #include "../Eigen/Dense" 5 | #include 6 | #include 7 | 8 | class MatrixEncryptor { 9 | private: 10 | Eigen::MatrixXd keyMatrix; 11 | 12 | Eigen::MatrixXd generateRandomKey(int size); 13 | 14 | public: 15 | MatrixEncryptor(int size); 16 | MatrixEncryptor(const Eigen::MatrixXd& customKey); 17 | 18 | std::vector encrypt(const std::vector& message) const; 19 | std::vector decrypt(const std::vector& encrypted_message, int size) const; 20 | const Eigen::MatrixXd& getKey() const; 21 | 22 | static std::vector parseInput(const std::string& input); 23 | static Eigen::MatrixXd getCustomKey(int size); 24 | static size_t calculateHash(const std::vector& data); 25 | }; 26 | 27 | #endif // MATRIXENCRYPTOR_H 28 | -------------------------------------------------------------------------------- /src/More Example/InputHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "InputHandler.h" 2 | #include "MatrixEncryptor.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // For system() function 8 | #include 9 | 10 | void clearScreen() { 11 | #ifdef _WIN32 12 | std::system("cls"); // Clear screen for Windows 13 | #else 14 | std::system("clear"); // Clear screen for Unix-like systems 15 | #endif 16 | } 17 | 18 | void displayEncryptionOptions() { 19 | std::cout << "Options:" << std::endl; 20 | std::cout << "(1) Show Encrypted Data" << std::endl; 21 | std::cout << "(2) Save Encrypted Data" << std::endl; 22 | std::cout << "(3) Show Key" << std::endl; 23 | std::cout << "(4) Save Key" << std::endl; 24 | std::cout << "(5) Show All Values" << std::endl; 25 | std::cout << "(6) Back to Menu" << std::endl; 26 | std::cout << "(7) Exit" << std::endl; 27 | } 28 | 29 | void displayDecryptionOptions() { 30 | std::cout << "Options:" << std::endl; 31 | std::cout << "(1) Show Decrypted Data" << std::endl; 32 | std::cout << "(2) Save Decrypted Data" << std::endl; 33 | std::cout << "(3) Show Key" << std::endl; 34 | std::cout << "(4) Save Key" << std::endl; 35 | std::cout << "(5) Show All Values" << std::endl; 36 | std::cout << "(6) Back to Menu" << std::endl; 37 | std::cout << "(7) Exit" << std::endl; 38 | } 39 | 40 | //Text encryption 41 | void InputHandler::encryptText() { 42 | 43 | char textChoice; 44 | std::vector message; 45 | clearScreen(); 46 | std::cout << "Do you want to enter the text manually or load it from a file? (m/f): "; 47 | std::cin >> textChoice; 48 | std::cin.ignore(std::numeric_limits::max(), '\n'); 49 | 50 | if (textChoice == 'm' || textChoice == 'M') { 51 | std::cout << "Enter the text to encrypt: "; 52 | std::string input_text; 53 | std::getline(std::cin, input_text); 54 | message = MatrixEncryptor::parseInput(input_text); 55 | 56 | } 57 | else if (textChoice == 'f' || textChoice == 'F') { 58 | std::string filename; 59 | std::cout << "Enter the path to the file containing the data: "; 60 | std::getline(std::cin, filename); 61 | std::vector fileText = readTextFromFile(filename); 62 | 63 | // Check if the file contains valid data 64 | if (fileText.empty()) { 65 | std::cout << "The file does not contain any valid data to encrypt." << std::endl; 66 | return; 67 | } 68 | 69 | // Convert file text to vector of ints if needed 70 | message.clear(); // Clear any existing data 71 | for (char ch : fileText) { 72 | // Convert char to int (ASCII value) 73 | message.push_back(static_cast(ch)); 74 | } 75 | } 76 | else { 77 | clearScreen(); 78 | std::cout << "Invalid choice. Aborting encryption." << std::endl; 79 | return; 80 | } 81 | 82 | int keySize = message.size(); 83 | char keyChoice; 84 | std::cout << "Do you want to use a custom key or generate it automatically? (c/g): "; 85 | std::cin >> keyChoice; 86 | std::cin.clear(); 87 | std::cin.ignore(std::numeric_limits::max(), '\n'); 88 | 89 | MatrixEncryptor encryptor(keySize); 90 | 91 | if (keyChoice == 'c' || keyChoice == 'C') { 92 | std::cout << "Enter the elements of the key matrix:" << std::endl; 93 | Eigen::MatrixXd customKey = MatrixEncryptor::getCustomKey(keySize); 94 | encryptor = MatrixEncryptor(customKey); 95 | } 96 | else if (keyChoice != 'g' && keyChoice != 'G') { 97 | clearScreen(); 98 | std::cout << "Invalid choice. Aborting encryption." << std::endl; 99 | return; 100 | } 101 | 102 | std::vector encrypted_message = encryptor.encrypt(message); 103 | 104 | // Clear screen and inform the user about encryption completion 105 | clearScreen(); 106 | 107 | // Options after encryption 108 | std::cout << "Encryption is completed." << std::endl; 109 | displayEncryptionOptions(); 110 | 111 | while (true) { 112 | std::cout << "Enter your choice: "; 113 | int choice; 114 | std::cin >> choice; 115 | switch (choice) { 116 | case 1: 117 | clearScreen(); 118 | std::cout << "Encrypted data:\n"; 119 | for (int num : encrypted_message) { 120 | std::cout << num << " "; 121 | } 122 | std::cout << std::endl; 123 | break; 124 | case 2: 125 | { 126 | clearScreen(); 127 | std::string fileloc; 128 | std::cout << "Enter the path and filename to save the encrypted data: "; 129 | std::cin.ignore(); 130 | std::getline(std::cin, fileloc); 131 | saveToFile(encrypted_message, fileloc); 132 | std::cout << "Encrypted data saved." << std::endl; 133 | break; 134 | } 135 | case 3: 136 | clearScreen(); 137 | std::cout << "Key used for encryption:" << std::endl; 138 | std::cout << encryptor.getKey() << std::endl; 139 | break; 140 | case 4: 141 | { 142 | clearScreen(); 143 | std::string fileloc; 144 | std::cout << "Enter the path and filename to save the key matrix: "; 145 | std::cin.ignore(); 146 | std::getline(std::cin, fileloc); 147 | saveKeyToFile(encryptor.getKey(), fileloc); 148 | std::cout << "Key matrix data saved." << std::endl; 149 | break; 150 | } 151 | case 5: 152 | clearScreen(); 153 | std::cout << "Original text: \n"; 154 | for (int num : message) { 155 | std::cout << static_cast(num); 156 | } 157 | std::cout << "\n\nEncrypted data: \n"; 158 | for (int num : encrypted_message) { 159 | std::cout << num << " "; 160 | } 161 | std::cout << "\n\nKey used for encryption:" << std::endl; 162 | std::cout << encryptor.getKey() << std::endl; 163 | 164 | std::cout << "Original message (ASCII values): "; 165 | for (int num : message) { 166 | std::cout << num << " "; 167 | } 168 | std::cout << std::endl; 169 | 170 | break; 171 | case 6: 172 | clearScreen(); 173 | return; // Back to Menu 174 | case 7: 175 | exit(0); 176 | default: 177 | clearScreen(); 178 | std::cout << "Invalid choice. Exiting.." << std::endl; 179 | exit(0); 180 | } 181 | std::cout << "\n(1) Back\n(2) Exit" << std::endl; 182 | std::cout << "Enter your choice: "; 183 | int backChoice; 184 | std::cin >> backChoice; 185 | if (backChoice == 1) { 186 | clearScreen(); 187 | displayEncryptionOptions(); 188 | } 189 | else if (backChoice == 2) { 190 | exit(0); 191 | } 192 | else { 193 | std::cout << "Invalid choice. Please try again." << std::endl; 194 | } 195 | } 196 | } 197 | 198 | void InputHandler::decryptText() { 199 | clearScreen(); 200 | std::cout << "Do you want to enter the encrypted data manually or load it from a file? (m/f): "; 201 | char inputChoice; 202 | std::cin >> inputChoice; 203 | std::cin.ignore(std::numeric_limits::max(), '\n'); 204 | 205 | std::vector input_encrypted_message; 206 | if (inputChoice == 'm' || inputChoice == 'M') { 207 | std::cout << "Enter the encrypted text to decrypt: "; 208 | std::string input_line; 209 | std::getline(std::cin, input_line); 210 | std::istringstream iss(input_line); 211 | int num; 212 | while (iss >> num) { 213 | input_encrypted_message.push_back(num); 214 | } 215 | } 216 | else if (inputChoice == 'f' || inputChoice == 'F') { 217 | std::string filename; 218 | std::cout << "Enter the path to the file containing the encrypted data: "; 219 | std::getline(std::cin, filename); 220 | input_encrypted_message = readEncryptedDataFromFile(filename); 221 | } 222 | else { 223 | clearScreen(); 224 | std::cout << "Invalid choice. Aborting decryption." << std::endl; 225 | return; 226 | } 227 | 228 | if (!input_encrypted_message.empty()) { 229 | int keySize = input_encrypted_message.size() / 2; 230 | clearScreen(); 231 | char keyChoice; 232 | std::cout << "Do you want to enter the key manually or load it from a file? (m/f): "; 233 | std::cin >> keyChoice; 234 | std::cin.ignore(std::numeric_limits::max(), '\n'); 235 | 236 | Eigen::MatrixXd decryptionKey; 237 | 238 | if (keyChoice == 'm' || keyChoice == 'M') { 239 | std::cout << "Enter the elements of the key matrix:" << std::endl; 240 | decryptionKey = MatrixEncryptor::getCustomKey(keySize); 241 | } 242 | else if (keyChoice == 'f' || keyChoice == 'F') { 243 | std::string keyFilename; 244 | std::cout << "Enter the path to the key file: "; 245 | std::getline(std::cin, keyFilename); 246 | decryptionKey = readKeyFromFile(keyFilename); 247 | if (decryptionKey.rows() != keySize || decryptionKey.cols() != keySize) { 248 | clearScreen(); 249 | std::cout << "Invalid key size. Aborting decryption." << std::endl; 250 | return; 251 | } 252 | } 253 | else { 254 | clearScreen(); 255 | std::cout << "Invalid choice. Aborting decryption." << std::endl; 256 | return; 257 | } 258 | clearScreen(); 259 | MatrixEncryptor decryptor(decryptionKey); 260 | std::vector decrypted_message = decryptor.decrypt(input_encrypted_message, keySize); 261 | std::cout << "Decryption is completed.\n"; 262 | displayDecryptionOptions(); 263 | 264 | while (true) { 265 | std::cout << "Enter your choice: "; 266 | int choice; 267 | std::cin >> choice; 268 | switch (choice) { 269 | case 1: 270 | clearScreen(); 271 | std::cout << "Decrypted text:\n"; 272 | for (int num : decrypted_message) { 273 | std::cout << static_cast(num); 274 | } 275 | std::cout << std::endl; 276 | break; 277 | case 2: 278 | { 279 | clearScreen(); 280 | std::string fileloc; 281 | std::cout << "Enter the path and filename to save the decrypted data: "; 282 | std::cin.ignore(); 283 | std::getline(std::cin, fileloc); 284 | saveToFile(decrypted_message, fileloc); 285 | std::cout << "Encrypted data saved." << std::endl; 286 | break; 287 | } 288 | case 3: 289 | clearScreen(); 290 | std::cout << "Key used for decryption:" << std::endl; 291 | std::cout << decryptor.getKey() << std::endl; 292 | break; 293 | case 4: 294 | { 295 | clearScreen(); 296 | std::string fileloc; 297 | std::cout << "Enter the path and filename to save the key matrix: "; 298 | std::cin.ignore(); 299 | std::getline(std::cin, fileloc); 300 | saveKeyToFile(decryptor.getKey(), fileloc); 301 | std::cout << "Key matrix data saved." << std::endl; 302 | break; 303 | } 304 | case 5: 305 | clearScreen(); 306 | std::cout << "Encrypted text: \n"; 307 | for (int num : input_encrypted_message) { 308 | std::cout << (num) << " "; 309 | } 310 | std::cout << std::endl; 311 | std::cout << "Decrypted text: \n"; 312 | for (int num : decrypted_message) { 313 | std::cout << static_cast(num); 314 | } 315 | std::cout << "\n\nKey used for decryption:" << std::endl; 316 | std::cout << decryptor.getKey() << std::endl; 317 | std::cout << std::endl; 318 | 319 | break; 320 | case 6: 321 | clearScreen(); 322 | return; // Back to Menu 323 | case 7: 324 | exit(0); 325 | default: 326 | clearScreen(); 327 | std::cout << "Invalid choice. Exiting.." << std::endl; 328 | exit(0); 329 | } 330 | std::cout << "\n(1) Back\n(2) Exit" << std::endl; 331 | std::cout << "Enter your choice: "; 332 | int backChoice; 333 | std::cin >> backChoice; 334 | if (backChoice == 1) { 335 | clearScreen(); 336 | displayDecryptionOptions(); 337 | } 338 | else if (backChoice == 2) { 339 | exit(0); 340 | } 341 | else { 342 | std::cout << "Invalid choice. Please try again." << std::endl; 343 | } 344 | } 345 | 346 | // Saving decrypted message 347 | saveToFile(decrypted_message, "decrypted_text.txt"); 348 | std::cout << "Decrypted data saved to 'decrypted_text.txt'" << std::endl; 349 | } 350 | else { 351 | std::cout << "Empty message. Decryption aborted." << std::endl; 352 | } 353 | } 354 | //To save decrypted message to file 355 | void InputHandler::saveToFile(const std::vector& data, const std::string& filename) { 356 | std::ofstream file(filename); 357 | if (file.is_open()) { 358 | for (int num : data) { 359 | file << static_cast(num); // Convert ASCII value to character 360 | } 361 | file.close(); 362 | std::cout << "Text saved to '" << filename << "'" << std::endl; 363 | } 364 | else { 365 | std::cerr << "Unable to open file for saving: " << filename << std::endl; 366 | } 367 | } 368 | 369 | //To save key to file 370 | void InputHandler::saveKeyToFile(const Eigen::MatrixXd& key, const std::string& filename) { 371 | std::ofstream file(filename); 372 | if (file.is_open()) { 373 | file << key; 374 | file.close(); 375 | std::cout << "Key matrix saved to '" << filename << "'" << std::endl; 376 | } 377 | else { 378 | std::cerr << "Unable to open file for saving: " << filename << std::endl; 379 | } 380 | } 381 | 382 | //To read key from file 383 | Eigen::MatrixXd InputHandler::readKeyFromFile(const std::string& filename) { 384 | std::ifstream file(filename); 385 | Eigen::MatrixXd key; 386 | if (file.is_open()) { 387 | std::vector> matrixData; 388 | std::string line; 389 | while (std::getline(file, line)) { 390 | std::vector row; 391 | std::istringstream iss(line); 392 | double num; 393 | while (iss >> num) { 394 | row.push_back(num); 395 | } 396 | matrixData.push_back(row); 397 | } 398 | 399 | int rows = matrixData.size(); 400 | int cols = (rows > 0) ? matrixData[0].size() : 0; 401 | key.resize(rows, cols); 402 | 403 | for (int i = 0; i < rows; ++i) { 404 | for (int j = 0; j < cols; ++j) { 405 | key(i, j) = matrixData[i][j]; 406 | } 407 | } 408 | file.close(); 409 | } 410 | else { 411 | std::cerr << "Unable to open file for reading: " << filename << std::endl; 412 | } 413 | return key; 414 | } 415 | 416 | std::vector InputHandler::readEncryptedDataFromFile(const std::string& filename) { 417 | std::vector data; 418 | std::ifstream file(filename); 419 | if (file.is_open()) { 420 | int num; 421 | while (file >> num) { 422 | data.push_back(num); 423 | } 424 | file.close(); 425 | } 426 | else { 427 | std::cerr << "Unable to open file for reading: " << filename << std::endl; 428 | } 429 | return data; 430 | } 431 | 432 | std::vector InputHandler::readTextFromFile(const std::string& filename) { 433 | std::vector data; 434 | std::ifstream file(filename); 435 | if (file.is_open()) { 436 | char ch; 437 | while (file.get(ch)) { 438 | data.push_back(ch); 439 | } 440 | file.close(); 441 | } 442 | else { 443 | std::cerr << "Unable to open file for reading: " << filename << std::endl; 444 | } 445 | return data; 446 | } 447 | -------------------------------------------------------------------------------- /src/More Example/InputHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUTHANDLER_H 2 | #define INPUTHANDLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class InputHandler { 9 | public: 10 | static void saveToFile(const std::vector& data, const std::string& filename); 11 | 12 | static void encryptText(); 13 | static void decryptText(); 14 | static void saveKeyToFile(const Eigen::MatrixXd& key, const std::string& filename); 15 | static Eigen::MatrixXd readKeyFromFile(const std::string& filename); 16 | static std::vector readEncryptedDataFromFile(const std::string& filename); 17 | static std::vector readTextFromFile(const std::string& filename); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/More Example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "InputHandler.h" 3 | 4 | int main() { 5 | int choice; 6 | do { 7 | std::cout << "(1) Encrypt a text" << std::endl; 8 | std::cout << "(2) Decrypt a text" << std::endl; 9 | std::cout << "(3) Exit" << std::endl; 10 | std::cout << "Enter your choice: "; 11 | std::cin >> choice; 12 | 13 | switch (choice) { 14 | case 1: 15 | InputHandler::encryptText(); 16 | break; 17 | case 2: 18 | InputHandler::decryptText(); 19 | break; 20 | case 3: 21 | std::cout << "Exiting program..." << std::endl; 22 | break; 23 | default: 24 | std::cout << "Invalid choice. Please try again." << std::endl; 25 | } 26 | } while (choice != 3); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/mainexample.cpp: -------------------------------------------------------------------------------- 1 | #include "MatrixEncryptor.h" 2 | #include 3 | 4 | int main() { 5 | // Example using randomly generated key 6 | MatrixEncryptor encryptor(3); // Create an encryptor with a 3x3 randomly generated key 7 | 8 | // Original message 9 | std::string message = "Hi"; 10 | // Encrypt the original message 11 | std::vector encrypted_message = encryptor.encrypt(MatrixEncryptor::parseInput(message)); 12 | 13 | // Print encrypted message 14 | std::cout << "Encrypted message:" << std::endl; 15 | for (int encrypted_char : encrypted_message) { 16 | std::cout << encrypted_char << " "; 17 | } 18 | std::cout << std::endl; 19 | 20 | // Decrypt the encrypted message 21 | std::vector decrypted_message = encryptor.decrypt(encrypted_message, 3); 22 | // Print decrypted message 23 | std::cout << "Decrypted message: "; 24 | for (int decrypted_char : decrypted_message) { 25 | std::cout << static_cast(decrypted_char); 26 | } 27 | std::cout << std::endl; 28 | 29 | // Example using custom key 30 | std::cout << "Enter a 3x3 custom key:" << std::endl; 31 | // Get custom key from user input 32 | Eigen::MatrixXd customKey = MatrixEncryptor::getCustomKey(3); 33 | // Create an encryptor with the custom key 34 | MatrixEncryptor encryptor_custom(customKey); 35 | 36 | // Another message to encrypt 37 | std::string message_custom = "hi"; 38 | // Encrypt the custom message 39 | std::vector encrypted_message_custom = encryptor_custom.encrypt(MatrixEncryptor::parseInput(message_custom)); 40 | 41 | // Print encrypted message with custom key 42 | std::cout << "Encrypted message with custom key:" << std::endl; 43 | for (int encrypted_char : encrypted_message_custom) { 44 | std::cout << encrypted_char << " "; 45 | } 46 | std::cout << std::endl; 47 | 48 | // Decrypt the encrypted message with custom key 49 | std::vector decrypted_message_custom = encryptor_custom.decrypt(encrypted_message_custom, 3); 50 | // Print decrypted message with custom key 51 | std::cout << "Decrypted message with custom key: "; 52 | for (int decrypted_char : decrypted_message_custom) { 53 | std::cout << static_cast(decrypted_char); 54 | } 55 | std::cout << std::endl; 56 | 57 | return 0; 58 | } 59 | --------------------------------------------------------------------------------