我目前正在开发一个Python应用程序,该应用程序分为两个脚本,每个脚本将放入一个Docker容器中。
一个通过创建随机生成的数据来模仿自动化工作,该数据存储在dict对象中,然后通过python socket
库将其发送到另一个脚本。
我发送的数据显示如下:
{
"unit": 1,
"timestamp": 1561566549688,
"params": {
"0": {
"temp_tank": 3.2,
"temp_ext": 11.7,
"tank_weight": 3686,
"finished_product_weighht": 406,
"pH_rate": 7.2,
"potassium_rate": 36,
"NaCL_concentration": 1.7,
"salmonella_level": 18,
"e-coli_level": 40,
"listeria_level": 30
},
"1": {
"temp_tank": 3.6,
"temp_ext": 10.2,
"tank_weight": 4597,
"finished_product_weighht": -219,
"pH_rate": 7.0,
"potassium_rate": 44,
"NaCL_concentration": 1.4,
"salmonella_level": 29,
"e-coli_level": 41,
"listeria_level": 39
},
"2": {
"temp_tank": 3.6,
"temp_ext": 11.7,
"tank_weight": 4587,
"finished_product_weighht": -938,
"pH_rate": 6.9,
"potassium_rate": 39,
"NaCL_concentration": 1.1,
"salmonella_level": 35,
"e-coli_level": 42,
"listeria_level": 50
},
"3": {
"temp_tank": 3.3,
"temp_ext": 10.3,
"tank_weight": 4120,
"finished_product_weighht": -38,
"pH_rate": 7.2,
"potassium_rate": 41,
"NaCL_concentration": 1.7,
"salmonella_level": 32,
"e-coli_level": 38,
"listeria_level": 41
},
"4": {
"temp_tank": 2.5,
"temp_ext": 12.5,
"tank_weight": 3723,
"finished_product_weighht": -134,
"pH_rate": 7.1,
"potassium_rate": 43,
"NaCL_concentration": 1.3,
"salmonella_level": 22,
"e-coli_level": 39,
"listeria_level": 30
},
"5": {
"temp_tank": 3.2,
"temp_ext": 9.5,
"tank_weight": 4236,
"finished_product_weighht": 116,
"pH_rate": 7.2,
"potassium_rate": 41,
"NaCL_concentration": 1.4,
"salmonella_level": 19,
"e-coli_level": 39,
"listeria_level": 44
},
"6": {
"temp_tank": 2.8,
"temp_ext": 11.6,
"tank_weight": 4279,
"finished_product_weighht": -616,
"pH_rate": 6.9,
"potassium_rate": 46,
"NaCL_concentration": 1.2,
"salmonella_level": 29,
"e-coli_level": 47,
"listeria_level": 47
},
"7": {
"temp_tank": 2.8,
"temp_ext": 13.0,
"tank_weight": 3774,
"finished_product_weighht": 290,
"pH_rate": 7.1,
"potassium_rate": 38,
"NaCL_concentration": 1.6,
"salmonella_level": 20,
"e-coli_level": 41,
"listeria_level": 39
},
"8": {
"temp_tank": 3.6,
"temp_ext": 13.0,
"tank_weight": 3978,
"finished_product_weighht": 381,
"pH_rate": 6.8,
"potassium_rate": 45,
"NaCL_concentration": 1.4,
"salmonella_level": 35,
"e-coli_level": 37,
"listeria_level": 49
},
"9": {
"temp_tank": 2.9,
"temp_ext": 10.2,
"tank_weight": 4109,
"finished_product_weighht": -174,
"pH_rate": 7.1,
"potassium_rate": 46,
"NaCL_concentration": 1.5,
"salmonella_level": 24,
"e-coli_level": 36,
"listeria_level": 45
}
}
}
第二个脚本使用相同的socket
库检索该数据,然后将其推送到远程数据库中。
这部分工作正常,我可以轻松地使用套接字将数据字典的json格式的字符串从生成脚本发送到另一个脚本。
我现在遇到的问题是,我想通过非对称地加密和解密json格式的字符串来确保套接字连接的安全。
为此,我使用cryptography
python库并使用RSA加密。
当我启动脚本时,进入“套接字发送”行时,两个脚本都崩溃。第一个输出此错误:
cryptography.exceptions.InternalError:未知的OpenSSL错误。当另一个库没有清除OpenSSL错误堆栈时,通常会遇到此错误。如果您将加密技术与我们使用的另一个库一起使用 es OpenSSL尝试在报告错误之前将其禁用。否则,请向https://github.com/pyca/cryptography/issues提出问题,并提供有关如何重现此问题的信息。 ([])
第二个输出:
ValueError:密文长度必须等于密钥大小。
使用OpenSSL,我似乎没有其他正在运行的库。
这是我的两个脚本:
generate.py
##
# Generate file containing data from automates
##
import sys
import random
import json
import glob
import os
import time
import socket
import threading
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
# Generate the private and public keys once
# from cryptography.hazmat.primitives.asymmetric import rsa
# private_key = rsa.generate_private_key(
# public_exponent=65537,
# key_size=20480,
# backend=default_backend()
# )
# public_key = private_key.public_key()
#
# pem = private_key.private_bytes(
# encoding=serialization.Encoding.PEM,
# format=serialization.PrivateFormat.PKCS8,
# encryption_algorithm=serialization.NoEncryption()
# )
#
# with open('private.pem', 'wb') as f:
# f.write(pem)
#
# pem = public_key.public_bytes(
# encoding=serialization.Encoding.PEM,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
#
# with open('public.pem', 'wb') as f:
# f.write(pem)
with open("public.pem", "rb") as key_file:
public_key = serialization.load_pem_public_key(
key_file.read(),
backend=default_backend()
)
# Handle argument related errors, we only want 2! No more no less.
if len(sys.argv) > 3:
print("Please give max 2 arguments.")
exit()
elif len(sys.argv) < 2:
print("Please give the amount of time for the update cycle (in seconds), and the unit number.")
exit()
else:
print("Initializing...")
# Registering the passed arguments
cycle_value = float(sys.argv[1])
unit_number = int(sys.argv[2])
def encrypt_data(data):
return bytes(base64.b64encode(public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)), 'utf-8')
# Get the tank weight of the previous data set
def get_last_tank_weight(id):
if not os.path.isdir('generated-data'):
os.mkdir('generated-data')
if len(glob.glob('generated-data/*.json')) == 0:
return 0
else:
list_of_files = glob.glob('generated-data/*.json')
latest_file = max(list_of_files, key=os.path.getctime)
return int(json.loads(open(latest_file, 'r').read())["params"][str(id - 1)]["tank_weight"])
# Generate random value for each automate
def generate_values(id):
tank_weight = int(round(random.uniform(3512, 4607), 0))
params = {
"temp_tank": round(random.uniform(2.5, 4), 1),
"temp_ext": round(random.uniform(8, 14), 1),
"tank_weight": tank_weight,
"finished_product_weighht": get_last_tank_weight(id) - tank_weight,
"pH_rate": round(random.uniform(6.8, 7.2), 1),
"potassium_rate": int(round(random.uniform(35, 47), 0)),
"NaCL_concentration": round(random.uniform(1.0, 1.7), 1),
"salmonella_level": int(round(random.uniform(17, 37), 0)),
"e-coli_level": int(round(random.uniform(35, 49), 0)),
"listeria_level": int(round(random.uniform(28, 54), 0))
}
return params
# Create and fill the json data file for the unit
def fill_json():
timestamp = int(time.time() * 1000)
json_output = {
"unit": unit_number,
"timestamp": timestamp,
"params": {}
}
params = {}
f_automates = open("automates.json", "r")
json_automates = json.loads(f_automates.read())[str(unit_number)]
print("Generating values...")
for automate in json_automates:
params[int(automate["num"]) - 1] = generate_values(automate["num"])
json_output["params"] = params
filename = "paramunite_" + str(unit_number) + "_" + str(timestamp) + ".json"
with open("generated-data/" + filename, "w+") as json_file:
json.dump(json_output, json_file)
print("file " + filename + " successfully created.")
print(encrypt_data(bytes(json.dumps(json_output), 'utf-8')))
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((socket.gethostname(), 25565))
# s.connect(('pyconcentrator', 25565))
s.sendall(encrypt_data(bytes(json.dumps(json_output), 'utf-8')))
# Line to make script wait for new creation
threading.Timer(cycle_value, fill_json).start()
# Launch main script!
fill_json()
concentrator.py
import socket
import json
import base64
import mysql.connector as mariadb
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
host = socket.gethostname()
port = 25565
s = socket.socket()
s.bind((host, port))
s.listen(60)
with open("private.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
def decrypt_data(data):
return private_key.decrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Connect to MariaDB
def connect_to_db():
return mariadb.connect(
host='mariadbaubeurre', port=3306, user='root', password='beurette', database='beurre'
# host='127.0.0.1', port=3307, user='root', password='', database='test'
)
# Get the type of the automate given its id, by searching in the automates.json file
def get_automate_type(id, unit):
return json.loads(open('automates.json', 'r').read())[str(unit)][int(id)-1]["type"]
def send_to_db(data):
mariadb_connection = connect_to_db()
cursor = mariadb_connection.cursor()
i = 1
# Prepare INSERT SQL query
sql = "INSERT INTO measures (`measure_datetime`, `measure_temp_cuve`, `measure_temp_ext`, `measure_weight_milk`, `measure_weight_product`, `measure_ph`, `measure_k_plus`, `measure_nacl`, `measure_bacteria_salmonella`, `measure_bacteria_ecoli`, `measure_bacteria_listeria`, `measure_fk_automaton`) VALUES "
for y in data["params"]:
sql += "({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}),".format(
data["timestamp"],
data["params"][y]["temp_tank"],
data["params"][y]["temp_ext"],
data["params"][y]["tank_weight"],
data["params"][y]["finished_product_weight"],
data["params"][y]["pH_rate"],
data["params"][y]["potassium_rate"],
data["params"][y]["NaCL_concentration"],
data["params"][y]["salmonella_level"],
data["params"][y]["e-coli_level"],
data["params"][y]["listeria_level"],
"(SELECT automaton_id FROM automatons WHERE automaton_fk_unit = (SELECT unit_id FROM `units` WHERE unit_fk_site = 1 AND unit_num = {}) AND automaton_type LIKE '{}' AND automaton_num = {})".format(
data["unit"], get_automate_type(i, data["unit"]), i)
)
i += 1
cursor.execute(sql[:-1] + ";")
mariadb_connection.commit()
mariadb_connection.close()
def wait_for_data():
output = ""
print("Waiting for connection...")
conn, addr = s.accept()
print("Receiving from ", addr, "...")
while True:
data = conn.recv(1024)
output += decrypt_data(data).decode('utf-8')
if not data:
break
print(json.loads(output))
send_to_db(json.loads(output))
wait_for_data()
wait_for_data()
s.close()
我对此一无所知,找不到任何解决方法。 我是密码学的新手,所以也许我没有使用正确的加密方法或类似方法,但是我对所有加密方法都有些迷茫。
谢谢!