遗漏的部分

This commit is contained in:
qing committed 2026-08-02 21:21:03 +08:00
1 parent 84fb370da8
commit 0493383ee8
63 files changed
+28237 -4

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
from .to_pmc import PmcComm
from .to_dnfs import DnfsComm
from .from_cops import CopsComm
from .rsa import Rsa_Pri_Key
from .aes import MyAES
from .parser import upload_file
#from .chat_comm import print_to_pmc
+85
View File
@@ -0,0 +1,85 @@
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
class MyAES:
def __init__(self, key: str, iv: str):
self.key: bytes = bytes.fromhex(key)
self.iv: bytes = bytes.fromhex(iv)
def decrypt(self, ciphertext: str):
cipher: bytes = bytes.fromhex(ciphertext)
plain: bytes = MyAES.aes_decrypt(cipher, self.key, self.iv)
try:
return plain.decode('utf-8')
except UnicodeDecodeError as e:
# 返回原始字节的十六进制表示作为备选
return plain.hex()
def encrypt(self, original_text: str):
plaintext: byte = original_text.encode('utf-8')
ciphertext: byte = MyAES.aes_encrypt(plaintext, self.key, self.iv)
return ciphertext.hex()
@staticmethod
def aes_decrypt(ciphertext: bytes, key: bytes, iv: bytes) -> bytes:
"""
使用AES-256-CBC算法解密数据
参数
- ciphertext: 待解密的密文字节串
- key: 256位(32字节)的密钥字节串
- iv: 初始化向量字节串(必须为16字节)
返回:
- 解密后的明文字节串
"""
# 验证输入参数长度
if len(key) != 32:
raise ValueError('AES-256密钥必须是32字节长度')
if len(iv) != 16:
raise ValueError('AES-CBC的IV必须是16字节长度')
# 创建AES-CBC解密器
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
try:
# 执行解密并移除PKCS#7填充
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
return plaintext
except Exception as e:
print(f"解密失败:{e}")
return b''
@staticmethod
def aes_encrypt(plaintext: bytes, key: bytes, iv: bytes) -> bytes:
"""
AES-256-CBC 加密
参数
plaintext: 要加密的密文
key: 32字节的密钥
iv: 16字节的初始化向量
返回:
加密后的密文
"""
# 检查密钥和IV的长度
if len(key) != 32:
raise ValueError("密钥必须是32字节(AES-256)")
if len(iv) != 16:
raise ValueError("IV必须是16字节")
# 创建加密器
cipher = Cipher(
algorithms.AES(key),
modes.CBC(iv),
backend=default_backend()
)
encryptor = cipher.encryptor()
# 添加PKCS7填充
padder = padding.PKCS7(128).padder()
padded_data = padder.update(plaintext) + padder.finalize()
# 加密数据
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
return ciphertext
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
import argparse
import socket
def send_client(msg: str, addr: str, port: int, name: str):
'''发送消息给聊天室服务器。
需要输入消息、地址、端口、昵称'''
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((addr, port))
s.sendall(f"{name}: {msg}".encode('utf-8'))
s.close()
print('success')
except ConnectionRefusedError:
print(f"Could not connect to {addr}:{port}")
except Exception as e:
print(f"Unexpected error: {e}")
class ChatComm:
'''与聊天服务器进行交流的类。'''
def __init__(self, addr: str, port: int, name: str):
self.addr = addr
self.port = port
self. name = name
def send(self, msg: str):
send_client(msg, self.addr, self.port, self.name)
def main():
parser = argparse.ArgumentParser(description='发送到聊天室。')
parser.add_argument("--msg", type=str, help="要发送的消息")
parser.add_argument('--addr', type=str, default='localhost', help='选择要连接的地址')
parser.add_argument('--port', type=int, default=8003, help='选择要连接的地址')
parser.add_argument('--name', type=str, default='Unknow', help='你的名字是什么')
args = parser.parse_args()
comm = ChatComm(args.addr, args.port, args.name)
comm.send(args.msg)
if __name__ == '__main__':
main()
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
'''
这是用于访问协处理器http服务的程序
'''
import requests
import os
import argparse
class CopsComm:
'''与协处理器的通信类'''
def __init__(self, url: str):
self.url: str= url
def http_post(self, module: str):
response = requests.post(self.url, json={'cmd': module}, headers={'Content-Type': 'application/json'} )
response.raise_for_status()
return response.text
if __name__ == "__main__":
# python3 from_cops.py --url=http://192.168.254.101:8001/api --mod=MPU6050
parser = argparse.ArgumentParser(description="COPS的http调用示例。")
parser.add_argument('--url', help='访问的URL')
parser.add_argument('--mod', help='要输入的指令')
args = parser.parse_args()
comm = CopsComm(args.url)
rsp = comm.http_post(args.mod)
print(rsp)
+99
View File
@@ -0,0 +1,99 @@
import urllib.request
import argparse
import sys
def openfile(filename):
try:
with open(filename, "r", encoding='utf-8') as f:
content = f.read()
print(f"✅ 文件读取成功,内容长度: {len(content)} 字符")
return content
except FileNotFoundError as e:
print(f"❌ 错误:指定的文件不存在 -> {filename}")
raise e
except PermissionError as e:
print(f"❌ 错误:没有权限读取文件 -> {filename}")
raise e
except Exception as e:
print(f"❌ 错误:读取文件失败 -> {str(e)}")
raise e
def httppost(url: str, msg: str) -> str:
try:
# 核心转换:字符串 → 字节流(原生库必须要求)
post_body_bytes = msg.encode("utf-8")
# 发送POST请求,timeout=10秒防止卡死
response = urllib.request.urlopen(url, data=post_body_bytes, timeout=2)
# 解析响应结果
if response.getcode() == 200:
resp_content = response.read().decode("utf-8")
print("\n🎉 请求上传成功!HTTP状态码: 200")
print(f"🎉 服务端响应内容:\n{resp_content}")
else:
resp_content = f'---{str(response.getcode())}---'
print(f"\n⚠️ 请求上传完成,但服务端返回异常状态码: {response.getcode()}")
print(f"⚠️ 服务端响应内容: {resp_content}")
return resp_content
except urllib.error.URLError as e:
print(f"\n❌ 请求失败:网络错误/连接超时/端口未开放 -> {str(e)}")
raise e
except urllib.error.HTTPError as e:
print(f"\n❌ 请求失败:HTTP错误 -> 状态码: {e.code}, 详情: {e.read().decode('utf-8')}")
raise e
except Exception as e:
print(f"\n❌ 请求失败:未知错误 -> {str(e)}")
raise e
def upload_file(file: str, host: str, port: int) -> str:
"""抽象的URL访问函数,用于上传文件到指定服务器
Args:
file: 待上传的文件路径
host: 目标服务器IP
port: 目标服务器端口
"""
try:
# 读取文件内容
msg = openfile(file)
# 构造URL
url = f"http://{host}:{port}/api/v1/mybot-sample"
# 发送POST请求
resp = httppost(url, msg)
except Exception as e:
print(f"❌ 错误:上传文件失败 -> {str(e)}")
resp = str(e)
return resp
def upload_file_and_train(file: str, host: str, port: int) -> str:
"""抽象的URL访问函数,用于上传文件到指定服务器
Args:
file: 待上传的文件路径
host: 目标服务器IP
port: 目标服务器端口
"""
try:
# 读取文件内容
msg = openfile(file)
# 构造URL
url = f"http://{host}:{port}/api/v1/mybot-nn"
# 发送POST请求
resp = httppost(url, msg)
except Exception as e:
print(f"❌ 错误:上传文件失败 -> {str(e)}")
resp = str(e)
return resp
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="python 远程上传文本内容")
parser.add_argument("file", type=str, help="待上传的文件")
parser.add_argument('--port', type=int, default=9203, help="目标服务器监听端口,默认9203")
parser.add_argument("--host", type=str, default="127.0.0.1", help="目标服务器的IP,默认本地")
args =parser.parse_args()
resp = upload_file(args.file, args.host, args.port)
#resp = upload_file_and_train(args.file, args.host, args.port)
print(resp)
+103
View File
@@ -0,0 +1,103 @@
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
import os
class Rsa_Pri_Key:
'''RSA 私钥对象'''
def __init__(self, fullpath: str) -> None:
self.pri_key=Rsa_Pri_Key.load_private_key(fullpath)
def decrypt(self, ciphertext: str) -> str:
return Rsa_Pri_Key.decrypt_hex_ciphertext(self.pri_key, ciphertext)
@staticmethod
def load_private_key(pem_file, password=None):
'''
从PEM文件加载RSA私钥
:param pem_file: PEM格式的私钥文件路径
:param password: 私钥密码(如果有)
:return RSA私钥对象
'''
with open(pem_file, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=password.encode() if password else None,
backend=default_backend()
)
return private_key
@staticmethod
def decrypt_hex_ciphertext(private_key, hex_ciphertext):
'''
解密HEX格式的RSA密文
:param private_key: 已加载的RSA私钥
:param hex_ciphertext: Hex字符串格式的密文
:return: 解密后的明文
'''
try:
# 将Hex字符串转换为bytes
ciphertext = bytes.fromhex(hex_ciphertext)
# 使用OAEP填充方案解密
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
# OPENSSL 没有显式指定时,这个是SHA1
mgf=padding.MGF1(algorithm=hashes.SHA1()),
algorithm=hashes.SHA1(),
label=None
)
)
return plaintext
except ValueError as e:
print(f"Hex解码失败:{str(e)}")
return None
except Exception as e:
print(f"解密失败:{str(e)}")
return None
def main():
...
if __name__ == '__main__':
main()
"""
# 生成RSA私钥
private_key = rsa.generate_private_key(
public_exponent=65537, # 通常使用65537作为公钥指数
key_size=2048, # 密钥长度,推荐至少2048位
)
# 将私钥序列化为PEM格式
pem_private_key = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption() # 这里不加密私钥
)
# 获取对应的公钥
public_key = private_key.public_key()
# 将公钥序列化为PEM格式
pem_public_key = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# 打印密钥
print("私钥:")
print(pem_private_key.decode('utf-8'))
print("公钥:")
print(pem_public_key.decode('utf-8'))
# 可选:将密钥保存到文件
with open('private_key.pem', 'wb') as f:
f.write(pem_private_key)
with open('public_key.pem', 'wb') as f:
f.write(pem_public_key)
"""
+118
View File
@@ -0,0 +1,118 @@
import requests
import hashlib
import json
def calculate_sha256(input_string):
"""
计算输入字符串的SHA-256哈希值
参数:
input_string (str): 要计算哈希的字符串
返回:
str: 输入字符串的SHA-256哈希值(十六进制字符串)
"""
# 创建sha256哈希对象
sha256_hash = hashlib.sha256()
# 更新哈希对象,需要将字符串编码为字节
sha256_hash.update(input_string.encode('utf-8'))
# 获取十六进制格式的哈希值
hex_digest = sha256_hash.hexdigest()
return hex_digest
class DnfsComm:
'''=====抛出异常表示失败。=====
Dnfs即树状网络文件系统,该类是用于与dnfs通信的类。
可以获取子节点列表、添加节点、删除节点、更新节点。
计划在以后加入分组获取内容的功能。'''
def __init__(self, url: str) -> None:
self.url: str = url
# 获取某个节点下的子节点(0是主节点)
def get(self, pid: int) -> object:
rsp = requests.post(self.url + "/get_notes", json={
"pid": pid
},)
if (rsp.status_code == 200):
return rsp.text
else:
raise DnfsComm.GetFailed(rsp.text)
def get_and_trans(self, pid: int) -> list:
return json.loads(self.get(pid))
# 以pid节点为父节点添加节点
def add(self, pid: int, title: str, content: str) -> object:
rsp = requests.post(self.url + "/add_note", json={
"pid": pid,
"title": title,
"content": content
},)
if (rsp.status_code == 200 or rsp.status_code == 201):
return rsp.text
else:
raise DnfsComm.AddFailed(rsp.text)
# 删除一个节点
def dele(self, id: int) -> object:
rsp = requests.post(self.url + "/delete_note", json={
"id": id,
},)
if (rsp.status_code == 200):
return rsp.text
else:
raise DnfsComm.DelFailed(rsp.text)
# 更新id节点
def upd(self, id: int, pid: int, title: str, content: str) -> object:
rsp = requests.post(self.url + "/update_note", json={
"id": id,
"pid": pid,
"title": title,
"content": content
},)
if (rsp.status_code == 200):
return rsp.text
else:
raise DnfsComm.UpdFailed(rsp.text)
class TheExp(Exception):
def __init__(self, msg: str):
super().__init__(msg)
class GetFailed(TheExp):
def __init__(self, msg: str):
super().__init__(msg)
class AddFailed(TheExp):
def __init__(self, msg: str):
super().__init__(msg)
class DelFailed(TheExp):
def __init__(self, msg: str):
super().__init__(msg)
class UpdFailed(TheExp):
def __init__(self, msg):
super().__init__(msg)
if __name__ == "__main__":
comm = DnfsComm("http://101.245.108.250:8006")
#comm.add(0, "test pkg", "hello")
#comm.dele(2)
#comm.upd(id=1, pid=0, title="Users", content=f"""1::admin::{calculate_sha256('baigezi')}::admin
#2::qing::{calculate_sha256('123456')}::normal
#3::test::{calculate_sha256('44112233')}::normal
#4::test2::{calculate_sha256('44112233')}::mormal""")
#comm.upd(id=2, pid=0, title="Sensors", content='''101::temperature
#102::humidity''')
comm.upd(id=3, pid=0, title="Protected", content='''''')
print(comm.get_and_trans(0))
+135
View File
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
'''
这个代码是与PMC服务通信的工具
即PMC子系统调用
通过PMC服务,你可以创建和管理进程
===============================
20250701: 版本:0.0.4
使得这个模块可以访问任何地址的pmc服务
20250702:版本 0.0.5
使得这个模块在创建之初就保存一个url
20250709: 版本 0.1.0
使得模块在通信过程中应用RSA和AES加密手段
'''
from .rsa import Rsa_Pri_Key
from .aes import MyAES
import requests
import os
import json
import sys
class PmcComm:
'''并发机器通信'''
def __init__(self, url: str):
self.url: str = url
# 新库
############################
@staticmethod
def post_to(url, payload="", retry=10):
count = 0
while count < retry:
count += 1
try:
response = requests.post(url, data=payload)
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError:
...
raise Exception("连接失败")
@staticmethod
def get_from(url, retry=10):
count = 0
while count < retry:
count += 1
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError:
...
raise Exception("连接失败")
def get_key(self) -> str:
return PmcComm.get_from(f"{self.url}/api/v1/get_key")
def get_iv(self) -> str:
return PmcComm.get_from(f"{self.url}/api/v1/get_iv")
def get_list(self,) -> str:
ls = PmcComm.get_from(f"{self.url}/api/v1/get_list")
return self.aes.decrypt(ls).strip() # 第二天早上就出现了空格
def start(self, module: str) -> str:
msg = json.dumps({'module': module})
msg = self.aes.encrypt(msg)
return PmcComm.post_to(
f'{self.url}/api/v1/start',
payload=msg
)
def try_start(self, module: str) -> str:
try:
self.start(module)
except Exception as e:
print(f'{module}: {e}', file=sys.stderr)
def kill(self, pid: int) -> str:
msg = json.dumps({'pid': pid})
msg = self.aes.encrypt(msg)
return PmcComm.post_to(
f'{self.url}/api/v1/kill',
payload=msg
)
def clear(self, ) -> str:
return PmcComm.post_to(f'{self.url}/api/v1/clear')
def list_mods(self,) -> str:
ls = PmcComm.get_from(f"{self.url}/api/v1/list_mods")
return self.aes.decrypt(ls)
def Set_RSA_Pri_Key(self, fullpath: str) -> None:
self.rsa_pri: Rsa_Pro_Key = Rsa_Pri_Key(fullpath)
def Set_AES_Key(self, key: str, iv: str) -> None:
self.aes = MyAES(key.decode(), iv.decode())
def Try_Get_AES_Key(self, retry: int=10) -> None:
'''试图获取AES密钥,测试中失败率比较高'''
key_data = self.get_key()
key = self.rsa_pri.decrypt(key_data)
iv_data = self.get_iv()
iv = self.rsa_pri.decrypt(iv_data)
self.Set_AES_Key(key, iv)
def Test():
# 测试对象
#url = "http://101.245.108.250:8012"
url = "http://localhost:8012"
# 创建交流对象
comm = PmcComm(url)
comm.Set_RSA_Pri_Key("private_key.pem")
comm.Try_Get_AES_Key()
#msg = comm.start("mgmt")
#msg = comm.kill(6488)
#msg =comm.clear()
msg = comm.get_list()
print(msg)