Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
vp-webdev
6 лет назад

Пишем свой собственный крипточат на 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

562
62.520 GOLOS
На Golos с August 2017
Комментарии (7)
Сортировать по:
Сначала старые