效果如下:
起因:一些NSFW的话题,不想在经常使用的即时通讯工具中发送明文。之前写了传话机V1.0,但是是对称加密,传话机软件暴露了就可以被解密了Q Q
设计思路:生成随机公私钥对 -> A提供公钥 -> B拿A的公钥进行加密 -> B把密文给A -> A用私钥进行解密
设计界面:公钥生成文本框、别人提供的公钥文本框、加密文本框、解密文本框、相应功能按钮
功能代码:
from PySide2.QtWidgets import QApplication, QMessageBox from PySide2.QtUiTools import QUiLoader from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding class Stats: def __init__(self): self.ui = QUiLoader().load('rsa.ui') self.ui.setFixedSize(703, 566) self.ui.gongyao.clicked.connect(self.gongyao) self.ui.copy_gongyao.clicked.connect(self.copy_gongyao) self.ui.other_jiami.clicked.connect(self.other_jiami) self.ui.other_fuzhi.clicked.connect(self.other_fuzhi) self.ui.siyao_jiemi.clicked.connect(self.siyao_jiemi) self.ui.siyao_copy.clicked.connect(self.siyao_copy) self.private_key_bytes = None def gongyao(self): private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) public_key = private_key.public_key() public_key_bytes = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) self.private_key_bytes = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ) self.ui.gongyao_text.clear() self.ui.gongyao_text.append(str(public_key_bytes.decode("utf-8"))) def copy_gongyao(self): gongyao_to_copy = self.ui.gongyao_text.toPlainText() clipboard = QApplication.clipboard() clipboard.setText(gongyao_to_copy) def other_jiami(self): plaintext_to_encrypt = self.ui.other_text.toPlainText() other_public_key_str = self.ui.other_gongyao.toPlainText() try: other_public_key = serialization.load_pem_public_key( other_public_key_str.encode('utf-8'), backend=default_backend() ) encrypted_text = other_public_key.encrypt( plaintext_to_encrypt.encode('utf-8'), padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) self.ui.other_text.clear() self.ui.other_text.append(str(encrypted_text.hex())) except Exception as e: QMessageBox.about(self.ui, '错误', f'加密失败:{str(e)}') def other_fuzhi(self): jiami_to_copy = self.ui.other_text.toPlainText() clipboard = QApplication.clipboard() clipboard.setText(jiami_to_copy) def siyao_jiemi(self): ciphertext_to_decrypt = self.ui.siyao_text.toPlainText() private_key = str(self.private_key_bytes.decode("utf-8")) try: private_key_obj = serialization.load_pem_private_key( self.private_key_bytes, password=None, backend=default_backend() ) decrypted_text = private_key_obj.decrypt( bytes.fromhex(ciphertext_to_decrypt), padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None ) ) self.ui.siyao_text.clear() self.ui.siyao_text.append(decrypted_text.decode('utf-8')) except Exception as e: QMessageBox.about(self.ui, '错误', f'解密失败:{str(e)}') def siyao_copy(self): jiami_to_copy = self.ui.siyao_text.toPlainText() clipboard = QApplication.clipboard() clipboard.setText(jiami_to_copy) app = QApplication([]) stats = Stats() stats.ui.show() app.exec_()
QSS美化:默认的感觉不太好看,创建了一个geek_style.qss。用chatgpt生成了一个有极客风格的样式表。
/* Main Window */ QWidget { background-color: #121212; color: #b8b8b8; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } /* Buttons */ QPushButton { background-color: #4CAF50; color: #FFFFFF; border: 2px solid #4CAF50; border-radius: 6px; } QPushButton:hover { background-color: #45a049; } /* Text Edit Boxes */ QTextEdit { background-color: #212121; color: #b8b8b8; border: 2px solid #4CAF50; border-radius: 4px; padding: 5px; } /* Labels */ QLabel { color: #4CAF50; } /* Message Box */ QMessageBox { background-color: #212121; color: #b8b8b8; border: 2px solid #4CAF50; } /* Message Box Buttons */ QMessageBox QPushButton { background-color: #4CAF50; color: #FFFFFF; border: 2px solid #4CAF50; border-radius: 6px; padding: 4px 8px; } QMessageBox QPushButton:hover { background-color: #45a049; }
引入:
... from PySide2.QtCore import QFile, QTextStream ... class Stats: def __init__(self): # ... (省略原有代码) self.apply_geek_style() self.private_key_bytes = None def apply_geek_style(self): # 读取自定义样式表 style_file = QFile('geek_style.qss') if style_file.open(QFile.ReadOnly | QFile.Text): style_stream = QTextStream(style_file) style_sheet = style_stream.readAll() self.ui.setStyleSheet(style_sheet) style_file.close() ... app = QApplication([]) stats = Stats() stats.ui.show() app.exec_()
生成exe:使用pyinstaller+upx,添加了图标(logo.png)。主程序图标设定:
from PySide2.QtGui import QIcon app = QApplication([]) # 加载 icon app.setWindowIcon(QIcon('logo.png'))
打包:
pyinstaller.exe -F -w -i logo.png rsa.py upx --force rsa.exe
使用Inno Setup将exe、qss、ui、logo这堆都打包成一个安装程序。
特别感谢:EDS、Chatgpt