From 2d9807410c1fa8410be1612c51e6eea61bcdab60 Mon Sep 17 00:00:00 2001 From: devoalda Date: Sat, 22 Apr 2023 09:21:57 +0800 Subject: [PATCH] Added a copy to clipboard button, Cleanup Code, Added Readme --- .gitignore | 170 +++++++++++++++++++++++++++ Ciphers/CaesarCipher/CaesarCipher.py | 28 ++--- README.MD | 111 +++++++++++++++++ app.py | 7 +- requirements.txt | 6 + templates/CaesarDecrypt.html | 11 +- templates/CaesarEncrypt.html | 14 ++- templates/base64Decode.html | 24 ++-- templates/base64Encode.html | 7 ++ 9 files changed, 347 insertions(+), 31 deletions(-) create mode 100644 .gitignore create mode 100644 README.MD create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05191e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,170 @@ +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + diff --git a/Ciphers/CaesarCipher/CaesarCipher.py b/Ciphers/CaesarCipher/CaesarCipher.py index 0694e2f..07588de 100644 --- a/Ciphers/CaesarCipher/CaesarCipher.py +++ b/Ciphers/CaesarCipher/CaesarCipher.py @@ -21,26 +21,17 @@ class CaesarCipher: self.shift = shift self.default_pad_length = 100 - self.file_type_dict = { - '.txt': { - 'function': self.convert_txt_to_list, - 'default_file_name': 'pad.txt' - }, - '.csv': { - 'function': self.convert_csv_to_list, - 'default_file_name': 'pad.csv' - } - } + self.file_type_dict = {'.txt': {'function': self.convert_txt_to_list, 'default_file_name': 'pad.txt'}, + '.csv': {'function': self.convert_csv_to_list, 'default_file_name': 'pad.csv'}} - if use_pad is False: + if not use_pad: self.pad = deque([0] * self.default_pad_length) else: if file_name: file_name, file_extension = os.path.splitext(file_name) - print(f'{file_name}, {file_extension}') if file_extension in self.file_type_dict: self.file_type_dict[file_extension]["function"](file_name + file_extension) - if file: + elif file: self.read_file(file) else: self.pad = pad if pad else self.gen_pad(self.default_pad_length) @@ -50,6 +41,8 @@ class CaesarCipher: Read file object into deque, space delimited or comma delimited :param file: file object to read :type file: IO[str] + :return: None + :rtype: None """ # Try space delimited, then comma delimited try: @@ -94,7 +87,7 @@ class CaesarCipher: pad_val = self.get_pad() result += chr((ord(char) + self.shift - 65 + pad_val) % 26 + 65) if char.isupper() else chr( (ord(char) + self.shift - 97 + pad_val) % 26 + 97) - print(f'Result: {result}') + # print(f'Result: {result}') return result def decrypt(self, cipher_text: str) -> str: @@ -166,6 +159,7 @@ class CaesarCipher: pad = [int(i) for i in pad.split(' ') if i.strip()] self.pad = deque(pad) + except FileNotFoundError: print(f'File {file_name} not found. Please check the file name and try again.') exit(1) @@ -198,6 +192,12 @@ if __name__ == "__main__": decipher = CaesarCipher(40, use_pad=False) dec = decipher.decrypt(enc) + cipher2 = CaesarCipher(40, use_pad=True, file_name='./pad.txt') + enc = cipher.encrypt(text) + + decipher2 = CaesarCipher(40, use_pad=True, file_name='./pad.txt') + dec = decipher.decrypt(enc) + print(f'Original: {text}') print(f'Encrypted: {enc}') print(f'Decrypted: {dec}') diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..47ecd34 --- /dev/null +++ b/README.MD @@ -0,0 +1,111 @@ +# Cipher App + +This is a simple cipher app that features: + +- Caesar Cipher +- Base64 Encoding/Decoding + +This is done using flask and python, with a simple html frontend and a Caesar Cipher python script. + +### Usage + +```bash +# Install the requirements +pip install -r requirements.txt + +# Run the app +python app.py +``` + +### File Locations + +All current and future cipher files will be located in the `Ciphers` folder. + +Web application files are located in root directory. + +## Caesar Cipher + +The Caesar Cipher is a simple cipher that shifts the alphabet by a certain amount. For example, if the shift is 3, then +A becomes D, B becomes E, and so on. This is done by using the `ord()` and `chr()` functions in python. + +What's different about this Caesar Cipher portion is the ability to include a One Time Pad (OTP) in the form of a `CSV` +or `TXT` file. This fortifies the cipher by adding a predefined shift to the characters. +The OTP looks like this: + +```text +19 33 71 15 21 25 43 38 9 68 2 79 85 97 62 80 63 61 5 71 97 73 47 20 5 6 11 83 3 97 61 11 92 67 11 59 9 53 97 39 94 63 4 99 16 3 43 42 93 28 41 18 72 75 92 16 66 82 77 10 36 1 40 73 78 11 90 94 31 70 52 52 80 45 15 60 70 6 47 29 36 28 4 90 92 8 36 56 63 85 37 81 82 35 62 20 41 41 79 68 +``` + +Where each number is a shift value for each character in the message. + +The OTP will be generated and saved into both a `CSV` and `TXT` file if `use_pad` is set to `True` but no `file_name` +or `file` is provided. This is done with `secrets` instead of `random` to ensure that the OTP is cryptographically +secure. +> Read more about `secrets` [here](https://docs.python.org/3/library/secrets.html#module-secrets) + +### Usage of Caesar Cipher class + +```python +# Import the class +from collections import deque + +text = "Hello World, this is a test!" + +# Pad Declaration using a list in a deque +pad = deque([19, 33, 71, 15, 21, 25, 43, 38, 9, 68, 2, 79, 85]) + +cipher = CaesarCipher(40, use_pad=False) +enc = cipher.encrypt(text) + +decipher = CaesarCipher(40, use_pad=False) +dec = decipher.decrypt(enc) + +cipher2 = CaesarCipher(40, use_pad=True, file_name='./pad.txt') +enc = cipher.encrypt(text) + +decipher2 = CaesarCipher(40, use_pad=True, file_name='./pad.txt') +dec = decipher.decrypt(enc) +``` + +The Constructor allows for multiple parameters: + +- `shift` - The shift value for the cipher (Default in the Web Application is 3, no default in the class) +- `pad` - `deque` object containing the OTP (Default is `None`) +- `file_name` - The name of the file containing the OTP (Default is `None`) +- `file` - The file containing the OTP (Default is `None`) +- `use_pad` - Whether to use the OTP (Default is `False`) + +Above is the sample usage of the class. The object will have to be recreated for each message to be encrypted/decrypted +since +the OTP is a one time use. + +## Base64 Encoding/Decoding + +Base64 is a way to encode binary data into a string format. This is done by splitting the binary data into 6-bit chunks +and then converting each chunk into a character. This is done by using the `base64` module in python. + +The base64 encoding/decoding is done using the `base64` module in the web application. + +## Web Application + +The web application is done using flask and python. The frontend is done using html and css. + +This is a simple web application that allows the user to encrypt/decrypt messages using the Caesar Cipher and Base64 +Encoding/Decoding. + +Basic Functions: + +- Fields are automatically updated as the user types in the message. +- The user can choose to use the OTP (via a file upload) +- Sliders can be used to change the shift value for the Caesar Cipher +- Both the Caesar Cipher and Base64 Encoding/Decoding can be used at the same time + +### Launching the Web Application + +To launch the web application, run the `app.py` file. This will launch the web application on `localhost:5000`. + +```bash +python app.py +``` + +Ensure that the requirements in `requirements.txt` file is installed before running the application. \ No newline at end of file diff --git a/app.py b/app.py index 447fa45..c53d0cf 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ -import io import base64 +import io from flask import Flask, render_template, request, jsonify @@ -32,14 +32,13 @@ def b64(): else: sample_string_bytes = text.encode("ascii") base64_bytes = base64.b64encode(sample_string_bytes) - # print(f'Encoded string: {base64_bytes.decode("ascii")}') result['ciphertext'] = str(base64_bytes.decode("ascii")) return jsonify(result) -@app.route('/encrypt_decrypt', methods=['POST']) -def encrypt_decrypt(): +@app.route('/CaesarCipherED', methods=['POST']) +def CaesarCipherED(): if 'plaintext_input' in request.form: text = request.form['plaintext_input'] ciphertext_input = False diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bbfd3e2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +click==8.1.3 +Flask==2.2.3 +itsdangerous==2.1.2 +Jinja2==3.1.2 +MarkupSafe==2.1.2 +Werkzeug==2.2.3 diff --git a/templates/CaesarDecrypt.html b/templates/CaesarDecrypt.html index 5f31866..9696db5 100644 --- a/templates/CaesarDecrypt.html +++ b/templates/CaesarDecrypt.html @@ -1,5 +1,5 @@
-
+ @@ -54,6 +54,7 @@ + Copy to Clipboard
@@ -74,7 +75,7 @@ formData.append('pad_file', pad_file); let xhrEncrypt = new XMLHttpRequest(); - xhrEncrypt.open('POST', '{{ url_for("encrypt_decrypt") }}'); + xhrEncrypt.open('POST', '{{ url_for("CaesarCipherED") }}'); xhrEncrypt.onload = function () { let ciphertext = JSON.parse(xhrEncrypt.responseText)['ciphertext']; let cleartext = JSON.parse(xhrEncrypt.responseText)['cleartext']; @@ -136,6 +137,12 @@ removeBtn.style.display = 'none'; } + function copyToClipboardCaesarDecrypt() { + const ciphertextInput = document.getElementById("cleartext-decrypt"); + ciphertextInput.select(); + document.execCommand("copy"); + } + document.getElementById('ciphertext_input').addEventListener('input', update_decrypt); document.getElementById('key-slider-decrypt').addEventListener('input', updateKeyInputDecrypt); document.getElementById('key-input-decrypt').addEventListener('input', updateSliderValueDecrypt); diff --git a/templates/CaesarEncrypt.html b/templates/CaesarEncrypt.html index 3fb60a7..bc15c10 100644 --- a/templates/CaesarEncrypt.html +++ b/templates/CaesarEncrypt.html @@ -1,5 +1,5 @@
- + @@ -38,6 +38,7 @@ + Copy to Clipboard
@@ -48,7 +49,7 @@
+ class="form-control" readonly>
@@ -68,7 +69,7 @@ formData.append('pad_file', pad_file); let xhrEncrypt = new XMLHttpRequest(); - xhrEncrypt.open('POST', '{{ url_for("encrypt_decrypt") }}'); + xhrEncrypt.open('POST', '{{ url_for("CaesarCipherED") }}'); xhrEncrypt.onload = function () { let ciphertext = JSON.parse(xhrEncrypt.responseText)['ciphertext']; let cleartext = JSON.parse(xhrEncrypt.responseText)['cleartext']; @@ -130,6 +131,13 @@ removeBtn.style.display = 'none'; } + function copyToClipboardCaesarEncrypt() { + const ciphertextInput = document.getElementById("ciphertext"); + ciphertextInput.select(); + document.execCommand("copy"); + alert("Copied to clipboard!"); + } + document.getElementById('plaintext_input').addEventListener('input', update); document.getElementById('key-slider').addEventListener('input', updateKeyInput); document.getElementById('key-input').addEventListener('input', updateSliderValue); diff --git a/templates/base64Decode.html b/templates/base64Decode.html index de1d048..92a4ec4 100644 --- a/templates/base64Decode.html +++ b/templates/base64Decode.html @@ -2,29 +2,37 @@ + placeholder="Enter your text here" class="form-control">
- - + + + Copy to Clipboard
diff --git a/templates/base64Encode.html b/templates/base64Encode.html index 84daa4c..0b933c7 100644 --- a/templates/base64Encode.html +++ b/templates/base64Encode.html @@ -9,6 +9,7 @@ + Copy to Clipboard @@ -27,5 +28,11 @@ xhrRequest.send(formData); } + function copyToClipboardB64Encrypt() { + const ciphertextInput = document.getElementById("b64_ciphertext"); + ciphertextInput.select(); + document.execCommand("copy"); + } + document.getElementById('b64_plaintext_input').addEventListener('input', b64Update);