From a2162b4a3e9d3c24d597de058a8516eef8469ae4 Mon Sep 17 00:00:00 2001 From: Timmoc Date: Mon, 25 Nov 2024 14:29:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=8E=B0=E5=9C=A8=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E4=BF=9D=E5=AD=98=E5=88=B0download=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=20=E5=A2=9E=E5=8A=A0=E5=8F=91=E9=80=81=E6=96=B9?= =?UTF-8?q?=E6=8F=90=E9=86=92=EF=BC=8C=E4=BD=BF=E7=94=A8Segwit=E5=9C=B0?= =?UTF-8?q?=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- recv/recv.py | 27 ++++++++++----- tool/DownloadPathTool.py | 29 ++++++++++++++++ tool/hash/Segwit.py | 72 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 tool/DownloadPathTool.py create mode 100644 tool/hash/Segwit.py diff --git a/recv/recv.py b/recv/recv.py index 5bf5675..91bfc4a 100644 --- a/recv/recv.py +++ b/recv/recv.py @@ -1,9 +1,12 @@ import base64 +from Crypto.Hash import SHA256 + from config import config from entity.Letter import Letter -from tool import PriKeyHelper +from tool import PriKeyHelper, DownloadPathTool from tool.asymmetric import RSA +from tool.hash import Segwit from tool.symmetric import SM4 @@ -15,14 +18,15 @@ def getLetter(): handleLetter(letter) pass -def handleLetter(letter:Letter): + +def handleLetter(letter: Letter): # 解析信件 确认收信人 # 获取自身key pki = PriKeyHelper.getUserKey() if pki[1] != letter.recvPubKey: raise Exception("信件不属于自己") # 用自己的私钥解密key 获得对称加密秘钥。 - key = RSA.decrypt_message(base64.b64decode(letter.encryptKey),pki[0]) + key = RSA.decrypt_message(base64.b64decode(letter.encryptKey), pki[0]) # 根据不同的对称加密算法 try: @@ -32,9 +36,9 @@ def handleLetter(letter:Letter): # 进行解密fileBase64 data = b"" if type == config.EncryptType.SM4_ECB: - data = base64.b64decode(SM4.decrypt_ecb(letter.fileBase64,key)) + data = base64.b64decode(SM4.decrypt_ecb(letter.fileBase64, key)) elif type == config.EncryptType.SM4_CBC: - data = base64.b64decode(SM4.decrypt_cbc_with_iv(letter.fileBase64,key)) + data = base64.b64decode(SM4.decrypt_cbc_with_iv(letter.fileBase64, key)) elif type == config.EncryptType.AES_ECB: raise NotImplementedError("未实现") elif type == config.EncryptType.AES_CBC: @@ -43,12 +47,17 @@ def handleLetter(letter:Letter): raise KeyError("不支持的对称加密算法") # 用发信人的公钥验签摘要 - result = RSA.verify_signature(data,letter.sign,letter.senderPubKey) + result = RSA.verify_signature(data, letter.sign, letter.senderPubKey) if not result: raise Exception("签名验证失败,文件不可信") # 保存文件 - with open(f"./{letter.fileName}","wb") as f: + + # 默认下载目录 + download_dir = DownloadPathTool.get_download_directory() + + with open(f"{download_dir}/{letter.fileName}", "wb") as f: f.write(data) - print(f"签名验证有效,已将文件 {letter.fileName} 保存至当前目录下") - return \ No newline at end of file + print(f"确认收到来自 {Segwit.encodeSegwit(letter.senderPubKey.encode("utf-8"))} 的文件") + print(f"签名验证有效,已将文件 {letter.fileName} 保存至 {download_dir} 下") + return diff --git a/tool/DownloadPathTool.py b/tool/DownloadPathTool.py new file mode 100644 index 0000000..1f9db0a --- /dev/null +++ b/tool/DownloadPathTool.py @@ -0,0 +1,29 @@ +import sys +import winreg +from pathlib import Path + + +def get_download_directory(): + if sys.platform == 'win32': + # 打开注册表项 + key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders') + + try: + # 读取 "Downloads" 路径 + download_dir, _ = winreg.QueryValueEx(key, '{374DE290-123F-4565-9164-39C4925E467B}') + + # 将路径从注册表中的格式转换为标准格式 + download_dir = Path(download_dir).resolve() + + finally: + # 关闭注册表项 + winreg.CloseKey(key) + else: + # 对于非 Windows 系统,使用 ~\Downloads 作为默认下载目录 + home_dir = Path.home() + download_dir = home_dir / 'Downloads' + dir_path = Path(download_dir) + if not dir_path.exists(): + dir_path.mkdir(parents=True, exist_ok=True) + return str(download_dir) diff --git a/tool/hash/Segwit.py b/tool/hash/Segwit.py new file mode 100644 index 0000000..f2e5319 --- /dev/null +++ b/tool/hash/Segwit.py @@ -0,0 +1,72 @@ +import hashlib +import bech32 + +# https://liaoxuefeng.com/books/blockchain/bitcoin/segwit/index.html + +def hash160(data): + """ + 计算输入数据的SHA-160哈希值。 + + 参数: + data (bytes): 输入数据 + + 返回: + bytes: SHA-160哈希值 + """ + return hashlib.new('ripemd160', hashlib.sha256(data).digest()).digest() + +def encodeSegwit(data_bytes, hrp="fst"): + """ + 将字节数据编码为Bech32格式。 + + 参数: + hrp (str): 人类可读部分 (Human-readable part) + data_bytes (bytes): 要编码的数据 + + 返回: + str: Bech32编码后的字符串 + """ + + # 将字节转换为5位整数列表 + data_ints = bech32.convertbits(hash160(data_bytes), 8, 5) + if not data_ints: + raise ValueError("Failed to convert bytes to 5-bit integers") + + return bech32.bech32_encode(hrp, data_ints) + + +def verifySegwit(bech32_str): + """ + 验证Bech32编码的字符串是否有效。 + + 参数: + bech32_str (str): Bech32编码的字符串 + + 返回: + bool: 如果字符串有效则返回True,否则返回False + """ + try: + hrp, data_ints = bech32.bech32_decode(bech32_str) + if not hrp or not data_ints: + return False + + # 将5位整数列表转换回字节 + data_bytes = bech32.convertbits(data_ints, 5, 8, False) + if not data_bytes: + return False + + return True + except Exception as e: + print(f"Verification failed: {e}") + return False + + +# 示例用法 +if __name__ == "__main__": + message = b"Hello, Bech32!" + + encoded = encodeSegwit(message) + print(f"Encoded: {encoded}") + + is_valid = verifySegwit(encoded) + print(f"Is valid: {is_valid}")