Пишем свой собственный крипточат на Python и PHP
Читают ли нашу переписку спецслужбы и любопытные хакеры? Этот вопрос волнует многих пользователей социальных сетей и распиаренных мессенджеров. А те кому хочется большей приватности просто создают свои собственные крипточаты.
Сегодня я расскажу вам как на Python и PHP создать простой крипточат. Все сообщения будут шифроваться на стороне Python скрипта алгоритмом AES, на сервере они будут храниться в зашифрованном виде, поэтому, даже если кто-то подберет пароль на вход в БД сервера, он ничего не сможет прочесть.
Сделаем интерфейс программы на PyQT, чтобы было удобно и кросплатформенно. Для работы программы нужен Python 3.
В нем нужно установить модули
pip3 install PyQT5
pip3 install cryptography
pip3 install requests
pip3 install bs4</b>
Далее привожу сперва код модуля внешнего вида программы. В нем содержится два текстовых поля - одно для ввода сообщений, другое для вывода чата, и две кнопки - для отправки сообщений и обновления чата.
Листинг файла gui.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 644)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(20, 40, 460, 100))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(20, 160, 760, 470))
self.textEdit_2.setObjectName("textEdit_2")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(520, 40, 250, 41))
self.pushButton.setObjectName("pushButton")
self.pushButton2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton2.setGeometry(QtCore.QRect(520, 90, 250, 41))
self.pushButton2.setObjectName("pushButton2")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 10, 371, 16))
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Криптомессенджер"))
self.pushButton.setText(_translate("MainWindow", "Отправить сообщение"))
self.pushButton2.setText(_translate("MainWindow", "Обновить чат"))
self.label.setText(_translate("MainWindow", "Текст сообщения"))
Теперь код второго файла - cryptomess.py который отвечает за программную часть шифрования
Листинг cryptomess.py
import sys
from gui import *
from PyQt5 import QtCore, QtGui, QtWidgets
from cryptography.fernet import Fernet
import requests, bs4, os
cipher_key = '72edzhrrHyu3m3hejo5I1EXFs70SzyT4e6j9GZuX-Bc='
cipher = Fernet(cipher_key)
password=u'SxB15jjkJKjklqw6'
user='Pythono'
text=''
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.SendMyMessage)
self.ui.pushButton2.clicked.connect(self.SendRefresh)
def Refresh(self):
r = requests.post("http://server.ru/m.php", data={'password': password, 'user': user, 'message': self.message})
b=bs4.BeautifulSoup(r.text, "html.parser")
p1=b.select('.mblock .user')
p2=b.select('.mblock .message')
i, count = 0, len(p2)
alltext=''
while (i < count):
alltext=alltext+('<b>'+p1[i].getText()+'</b><br><br>')
w = cipher.decrypt(bytes(p2[i].getText(), encoding='utf-8'))
alltext=alltext+('<i>'+w.decode(encoding='utf-8')+'</i><br><hr>')
i += 1
self.ui.textEdit_2.setText(alltext)
def SendRefresh(self):
self.ui.textEdit_2.setText("")
self.message = 'refresh'
self.Refresh()
def SendMyMessage(self):
self.ui.textEdit_2.setText("")
mytext=self.ui.textEdit.toPlainText().encode('utf-8')
self.message = cipher.encrypt(mytext)
self.Refresh()
if __name__=="__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = MyWin()
myapp.show()
sys.exit(app.exec_())
Для того чтобы поменять ник пользователя, измените строку user='Pythono'. Переменные password и cipher_key это пароли - первый нужен для связи с PHP скриптом, второй - используется как ключ шифрования сообщений. Оба этих пароля нужно в реале передать тому с кем хочется пообщаться в данном крипточате.
Кроме клиентской части на Python нам еще серверная часть на PHP.
В файле password.php хранится пароль для доступа клиентской части чата к серверной, а также ваши пароли для базы данных (ее нужно создать в phpMyAdmin).
Листинг файла password.php
<?php
$pass='SxB15jjkJKjklqw6';
$bzname='dbname';
$bzlogin='dblogin';
$bzpass='dbpassword';
$bzhost='localhost';
?>
Файл install.php используется для создания БД.
Листинг файла install.php
<?php
require_once('password.php');
$mysqli = new mysqli($bzhost, $bzlogin, $bzpass, $bzname);
$rei = $mysqli->query("SET NAMES utf8");
if ($mysqli->query("CREATE TABLE IF NOT EXISTS messages (
id INT AUTO_INCREMENT,
user TEXT,
message LONGTEXT,
PRIMARY KEY(id)
)") === TRUE) {
};
$mysqli->close();
?>
Этот файл нужно запустить перед тем как использовать крипточат. Он создаст на сервере нужную структуру БД.
И, наконец, основной серверный скрипт, который принимает сообщения помещает их в БД и отдает ответ клиенту.
Листинг файла m.php
<?php
session_start();
require('password.php');
if ($_POST['password']==$pass){
$code='';
$formdb = new PDO('mysql:host='.$bzhost.';dbname='.$bzname, $bzlogin, $bzpass); $formdb->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$formdb->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$formdb->exec("set names utf8");
$formdb->exec("SET CHARACTER SET utf8");
if((isset($_POST['message']))&&(($_POST['message'])!='refresh')){
$zapros='INSERT INTO messages (user, message) VALUES (:user, :message)';
$stmt=$formdb->prepare($zapros);
$stmt->bindValue(':user', $_POST['user']);
$stmt->bindValue(':message', $_POST['message']);
$stmt->execute();
};
$formstmt = $formdb->prepare("SELECT * FROM messages ORDER BY id DESC LIMIT 0,10");
if ($formstmt->execute()) {
while ($formrow = $formstmt->fetch()) {
$code.='<div class="mblock"><div class="user">'.$formrow['user'].'</div><div class="message">'.$formrow['message'].'</div></div>';
};
};
echo($code);
$formdb = null;
};
?>
Ответ сервера формируется в виде HTML кода с блоками, в которых прописаны классы. На стороне клиента Python с помощью BeautifulSoup4 парсит ответ сервера и выводит сообщения в текстовое поле.
Выглядит наш чат вот так:
Вы можете скомпилировать чат с помощью PyInstaller, залить PHP скрипты на хостинг, и разговаривать с кем-либо, шифруя сообщения надежными ключами.
Материал подготовлен автором @pythono