Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .coverage
Binary file not shown.
75 changes: 75 additions & 0 deletions .github/workflows/tests_git.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Python CI

on:
push:
branches: [development]

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install flake8 flake8-html pytest-html

- name: Run tests
run: |
mkdir -p reports/coverage reports/flake8 reports/junit
python -m pytest --cov=src tests/ --cov-report term --junitxml=reports/junit/junit.xml --html=reports/junit/index.html
coverage report
coverage xml -o reports/coverage/coverage.xml
coverage html -d reports/coverage
flake8 src --exit-zero --format=html --htmldir reports/flake8 --statistics --tee --output-file reports/flake8/flake8stats.txt
- name: Upload reports
uses: actions/upload-artifact@v4
with:
name: reports
path: reports
update-badges:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Download reports
uses: actions/download-artifact@v4
with:
name: reports
path: reports
- name: Create badges
run: |
pip install genbadge[all]
genbadge tests -o badges/tests.svg
genbadge coverage -o badges/coverage.svg
genbadge flake8 -o badges/flake8.svg
- name: Deploy badges
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'Update badges'
branch: gh-pages
file_pattern: 'badges/* reports/*'
skip_fetch: true
skip_checkout: true
- name: Checkout back
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Python
__pycache__/
*.pyc

# Virtual environment
venv/

# IDE
.idea/
31 changes: 31 additions & 0 deletions Main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from src.FileHandler import *
from src.CesarStatisticsDecipher import *
import argparse


def parse_arguments():
parser = argparse.ArgumentParser(description='Encryption and decryption program')
parser.add_argument('-e', '--encrypt', action='store_true', help='Encrypt data')
parser.add_argument('-d', '--decrypt', action='store_true', help='Decrypt data')
parser.add_argument('-a', '--algorithm', choices=['caesar', 'vernam', 'vigenere', 'statistical_caesar'],
help='Encryption/Decryption algorithm')
parser.add_argument('-i', '--input_file', help='Input file')
parser.add_argument('-l', '--lang', choices=['rus', 'eng'], help='Language')
parser.add_argument('-k', '--key', default='', help='shift for cesar / key for vernam or vigenere / nothing for '
'statistical_caesar')
return parser.parse_args()


def main():
args = parse_arguments()
file_handler = FileHandler()
if args.encrypt:
file_handler.encrypt_file(args.input_file, args.algorithm, args.lang, args.key)
elif args.decrypt:
file_handler.decrypt_file(args.input_file, args.algorithm, args.lang, args.key)
else:
print('Please specify whether you want to encrypt (-e) or decrypt (-d) the data.')


if __name__ == "__main__":
main()
61 changes: 48 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[![Python CI](https://github.com/kirillzol/Python-encryption/actions/workflows/tests_git.yml/badge.svg)](https://github.com/kirillzol/Python-encryption/actions/workflows/tests_git.yml)
[![tests](https://kirillzol.github.io/Python-encryption/badges/tests.svg)](https://kirillzol.github.io/Python-encryption/reports/junit/index.html)
[![cov](https://kirillzol.github.io/Python-encryption/badges/coverage.svg)](https://kirillzol.github.io/Python-encryption/reports/coverage/index.html)
[![flake8](https://kirillzol.github.io/Python-encryption/badges/flake8.svg)](https://kirillzol.github.io/Python-encryption/reports/flake8/index.html)

# Python-encryption
## Описание проекта

Expand Down Expand Up @@ -25,9 +30,7 @@

- Cipher.py - содержит в себе 3 класса, внутри которых реализуются 3 основных алгоритма проекта. Класс для алгоритма Цезаря: имееет 2 атрибута - русский и английски алфавиты, а также функции кодирования и декодирования текстового файла по алфавиту и сдвигу. Класс для шифра Виженера - имеет функцию генерации ключа: она генерирует ключ циклически, пока его длина не станет равна длине исходного текста, а также функции кодирования и декодирования текстового файла по ключу. И наконец класс для шифра Вернама: функция генерации ключа: Создается случайная последовательность битов, которая должна быть такой же длины, как и текст, а также функции кодирования и декодирования текстового файла по ключу.

- CesarStatisticsDecipher.py - файл, в котором содержится класс CesarStatisticsDecipher - имеет атрибуты: русский и английски алфавиты, а так же статистические данные по каждому из языков. Метод collect_statistics_from_text возвращает статистические данные по тексту. find_opt_step находит статистически оптимальный сдвиг, сопоставляя данные по тексту и по языку. После чего вызывается decrypt из CesarCipher.

- Steganography.py - содержит класс Steganography: generate_data - преобразует данные в бинарный формат (8-битный ASCII код каждого символа) и возвращает список бинарных кодов. modify_pixels - модифицирует пиксели изображения в соответствии с бинарными данными. Каждый бит данных встраивается в младший бит каждого компонента цвета RGB. encrypt - кодирует изображение. Она принимает объект изображения и данные, которые нужно внедрить. Затем она вызывает функцию modPix для модификации пикселей изображения. decrypt() - Функция для декодирования данных из изображения.
- CesarStatisticsDecipher.py - файл, в котором содержится класс CesarStatisticsDecipher - имеет атрибуты: русский и английски алфавиты, а так же статистические данные по каждому из языков. Метод collect_statistics_from_text возвращает статистические данные по тексту. find_opt_step находит статистически оптимальный сдвиг при помощи , сопоставляя данные по тексту и по языку. После чего вызывается decrypt из CesarCipher.

- FileHandler.py содержит класс FileHandler, который отвечает за обработку файлов в проекте: read_file, generate_file - для чтения и записи файлов. Также этот класс содержит методы для обработки файлов, используемых в процессе шифрования и дешифрования: encrypt_file, decrypt_file.

Expand Down Expand Up @@ -65,31 +68,63 @@
└── def __init__(self, text)
└── def collect_statistics_from_text(text)
└── def find_opt_step(text, alfavit, statistics_data_text, statistics_data_lang)
├── Steganography.py
└── class Steganography
└── def __init__(self, path)
└── def generate_data(path)
└── def modify_pixels(pix, data)
└── def encrypt(img, data)
└── def decrypt()
├── FileHandler.py
└── class FileHandler
└── def __init__(self, file_path):
└── def read_file(self)
└── def generate_file(self, data)
└── def encrypt_file(self, cipher)
└── def decrypt_file(self, cipher)
├── Utils.py # вспомогательный файл, возможно не пригодится вовсе
└── README.md
```
## Стек технологий и используемые библиотеки

### Стек технологий:
Python: Основной язык программирования для разработки проекта.
### Используемые библиотеки:
- PIL (Python Imaging Library): Используется для работы с изображениями, включая извлечение пикселей, модификацию изображений и сохранение изображений.
- argparse: Используется для обработки аргументов командной строки.
- os: Используется для взаимодействия с операционной системой, включая создание директорий и работы с файлами.
- math: Используется для выполнения математических операций, например, для вычисления ключей шифрования и дешифрования.
- random: Используется для генерации случайных чисел, которые могут использоваться в алгоритмах шифрования.

## Тестирование
<img width="443" alt="Снимок экрана 2024-04-17 в 23 07 30" src="https://github.com/kirillzol/Python-encryption/assets/97293695/19001d5e-4ff1-4d2a-9b8f-f001db88a6c4">

## Инструкция по запуску
### Установка зависимостей:
Убедитесь, что у вас установлен Python версии 3.x.
```
pip install -r requirements.txt
```
### Запуск программы:
Программа предоставляет возможность шифрования и дешифрования файлов с использованием различных алгоритмов.
```
python main.py -e -a caesar -i input.txt -l eng -k 3
```
Для шифрования файла input.txt с использованием алгоритма Цезаря на английском языке с ключом сдвига равным 3.
```
python main.py -d -a vernam -i encrypted.txt -l rus -k secret_key
```
Для дешифрования файла encrypted.txt с использованием алгоритма Вернама на русском языке с секретным ключом secret_key.

### Опции командной строки:
- -e, --encrypt: Запуск программы в режиме шифрования.
- -d, --decrypt: Запуск программы в режиме дешифрования.
- -a, --algorithm: Выбор алгоритма шифрования/дешифрования (caesar, vernam, vigenere, statistical_caesar).
- -i, --input_file: Путь к входному файлу.
- -l, --lang: Язык текста (rus, eng).
- -k, --key: Ключ для шифрования/дешифрования (сдвиг для Цезаря, ключ для Вернама или Виженера).

Примеры:

Шифрование файла на английском языке с использованием алгоритма Виженера и ключа password123:
```
python main.py -e -a vigenere -i input.txt -l eng -k password123
```
Дешифрование файла на русском языке с использованием алгоритма Цезаря и сдвига 5:
```
python main.py -d -a caesar -i encrypted.txt -l rus -k 5
```

Обратите внимание:
Перед запуском убедитесь, что у вас есть необходимые файлы для входных данных и выбраны правильные параметры для шифрования/дешифрования.
В случае использования алгоритма statistical_caesar ключ не требуется.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest-cov
pytest
110 changes: 110 additions & 0 deletions src/CesarStatisticsDecipher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from src.Cipher import *


class CesarStatisticsDecipher:
alphabets = dict(rus=["абвгдеёжзийклмнопрстуфхцчшщъыьэюя", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"],
eng=["abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"], )

def __init__(self):
pass

statistics_data_eng = {
'a': 8.17,
'b': 1.49,
'c': 2.78,
'd': 4.25,
'e': 12.70,
'f': 2.23,
'g': 2.02,
'h': 6.09,
'i': 6.97,
'j': 0.15,
'k': 0.77,
'l': 4.03,
'm': 2.41,
'n': 6.75,
'o': 7.51,
'p': 1.93,
'q': 0.10,
'r': 5.99,
's': 6.33,
't': 9.06,
'u': 2.76,
'v': 0.98,
'w': 2.36,
'x': 0.15,
'y': 1.97,
'z': 0.07
}

statistics_data_ru = {
'а': 8.01,
'б': 1.59,
'в': 4.54,
'г': 1.70,
'д': 2.98,
'е': 8.45,
'ё': 0.04,
'ж': 0.94,
'з': 1.65,
'и': 7.35,
'й': 1.21,
'к': 3.49,
'л': 4.40,
'м': 3.21,
'н': 6.70,
'о': 10.97,
'п': 2.81,
'р': 4.73,
'с': 5.47,
'т': 6.26,
'у': 2.62,
'ф': 0.26,
'х': 0.97,
'ц': 0.48,
'ч': 1.44,
'ш': 0.73,
'щ': 0.36,
'ъ': 0.04,
'ы': 1.90,
'ь': 1.74,
'э': 0.32,
'ю': 0.64,
'я': 2.01
}

def collect_statistics_from_text(self, text: str, alph: str) -> dict:
dictionary = {i: 0 for i in self.alphabets[alph][0]}
l = 0
for letter in text:
if letter.lower() in self.alphabets[alph][0]:
dictionary[letter.lower()] += 100
l += 1
for i in dictionary:
dictionary[i] /= l
return dictionary

def generate_shifted_alph(self, shift: int, alph: str) -> str:
cyp = CesarCipher(shift)
return cyp.encrypt(alphabets[alph][0], alph)

def find_opt_step(self, text: str, alph: str) -> int:
statistics_data_text = self.collect_statistics_from_text(text, alph)
if alph == 'eng':
statistics_data_lang = self.statistics_data_eng
else:
statistics_data_lang = self.statistics_data_ru
"""using standard deviation"""
min_standard_deviation = 1000000
res = 0
lst = list(statistics_data_text.values())
for i in range(0, len(alphabets[alph][0])):
new_alpha = self.generate_shifted_alph(i, alph)
temp_dictionary = {j: lst[(new_alpha.index(j)) % len(new_alpha)] for j in new_alpha}
standard_deviation = (sum(
(statistics_data_lang[char] - temp_dictionary[char]) ** 2 for char in new_alpha) / len(
new_alpha)) ** 0.5
if min_standard_deviation > standard_deviation:
res, min_standard_deviation = i, standard_deviation
print(res)
return res
Loading