效果如下:

起因:一些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