Commit 8deca748 authored by 学习的菜鸟's avatar 学习的菜鸟

feature:加入了验证功能,未做完

parent 2a761b47
cmake_minimum_required(VERSION 3.10)
project(DeviceControlSystem
VERSION 1.1.7
VERSION 1.1.8
LANGUAGES C
)
......@@ -8,10 +8,6 @@ project(DeviceControlSystem
string(TIMESTAMP BUILD_TIMESTAMP)
set(BUILD_USER $ENV{USER})
# 调试信息,确认路径
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Trying to configure file: ${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in")
# 配置版本文件
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in
......@@ -20,7 +16,7 @@ configure_file(
# 添加生成的头文件目录
include_directories(
${CMAKE_CURRENT_BINARY_DIR}/include # 添加这行
${CMAKE_CURRENT_BINARY_DIR}/include
include
device_judg/device
device_judg/judg
......@@ -46,17 +42,25 @@ file(GLOB_RECURSE SOURCES
list(FILTER SOURCES EXCLUDE REGEX "zlog/src/zlog-chk-conf.c")
list(FILTER SOURCES EXCLUDE REGEX "zlog/src/zlog_win.c")
# 创建可执行文件${PROJECT_NAME}
add_executable( main ${SOURCES})
# 设置静态链接选项
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -Wl,-Bdynamic")
# 创建可执行文件
add_executable(main ${SOURCES})
# 链接库
target_link_libraries( main PRIVATE
# 链接静态库
target_link_libraries(main PRIVATE
-Wl,--start-group
wiringPi
mosquitto
cjson
curl
m
#zlog
ssl
crypto
-Wl,--end-group
)
# 安装规则(可选)
......
......@@ -520,6 +520,30 @@ src/mqtt.c.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mqtt.c.s
.PHONY : src/mqtt.c.s
src/mqtt_verify.o: src/mqtt_verify.c.o
.PHONY : src/mqtt_verify.o
# target to build an object file
src/mqtt_verify.c.o:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mqtt_verify.c.o
.PHONY : src/mqtt_verify.c.o
src/mqtt_verify.i: src/mqtt_verify.c.i
.PHONY : src/mqtt_verify.i
# target to preprocess a source file
src/mqtt_verify.c.i:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mqtt_verify.c.i
.PHONY : src/mqtt_verify.c.i
src/mqtt_verify.s: src/mqtt_verify.c.s
.PHONY : src/mqtt_verify.s
# target to generate assembly for a file
src/mqtt_verify.c.s:
$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mqtt_verify.c.s
.PHONY : src/mqtt_verify.c.s
src/opensh.o: src/opensh.c.o
.PHONY : src/opensh.o
......@@ -1512,6 +1536,9 @@ help:
@echo "... src/mqtt.o"
@echo "... src/mqtt.i"
@echo "... src/mqtt.s"
@echo "... src/mqtt_verify.o"
@echo "... src/mqtt_verify.i"
@echo "... src/mqtt_verify.s"
@echo "... src/opensh.o"
@echo "... src/opensh.i"
@echo "... src/opensh.s"
......
#define PROJECT_VERSION_MAJOR 1
#define PROJECT_VERSION_MINOR 1
#define PROJECT_VERSION_PATCH 7
#define PROJECT_VERSION_PATCH 8
#define GIT_HASH ""
#define BUILD_TIMESTAMP "2025-06-09T07:19:20"
#define BUILD_TIMESTAMP "2025-06-24T10:17:31"
#define BUILD_USER "orangepi"
No preview for this file type
#ifndef MQTT_VERIFY_H__
#define MQTT_VERIFY_H__
#define AES_BLOCK_SIZE 16
extern int gverify_count;//验证计时
extern int gverify_index;//判断是否验证成功
//接收安卓发送的mqtt
int receive_verify(cJSON *body);
//加密并发送mqtt
int mqtt_encryption();
#endif
\ No newline at end of file
......@@ -16,6 +16,7 @@
#include "ads1115.h"
#include "audioplay.h"
#include "wifichange.h"
#include "mqtt_verify.h"
struct mosquitto *mosq;
......@@ -129,7 +130,7 @@ void heartbeat_send() {//心跳发送格式*5/2
cJSON_Delete(root); // 释放 cJSON 对象
}
void angle_mqtt_send() {
void angle_mqtt_send() { //角度发送
float angle_shot=ads1115_read_channel(2);
if(angle_shot>0){
angle_shot=angle_shot*360/5;
......@@ -282,7 +283,8 @@ int device_message_receive(cJSON *json){//接收到的控制设备的mqtt消息
my_zlog_debug("刷新成功");
break;
case 3:
message_3(body);
receive_verify(body);
if(gverify_index == 0) message_3(body);
my_zlog_debug("进入pwm控制");
break;
case 4:
......
#include <time.h>
#include <cjson/cJSON.h>
#include "mqtt_verify.h"
#include "common.h"
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "mqtt.h"
#include "judg.h"
char *id = NULL;
char *model = NULL;
char *number = NULL;
int *start_time = NULL;
char *user_id = NULL;
int gverify_count =0;//判断是否有15s
int gverify_index =0;//判断是否验证成功
//接收验证消息并15s一次验证,只有在接收时候才会15s一次验证
int receive_verify(cJSON *body) {
cJSON *device_info = cJSON_GetObjectItem(body, "device_info");
if(device_info == NULL) {
my_zlog_debug("验证为空");
return 1;
}
// 取各个字段(字符串类型)
cJSON *json_id = cJSON_GetObjectItem(device_info, "id");
cJSON *json_model = cJSON_GetObjectItem(device_info, "model");
cJSON *json_number = cJSON_GetObjectItem(device_info, "number");
cJSON *json_start_time = cJSON_GetObjectItem(device_info, "start_time");
cJSON *json_user_id = cJSON_GetObjectItem(device_info, "user_id");
if (json_id && json_model && json_number && json_start_time && json_user_id) {
id=json_id->valuestring;
model=json_model->valuestring;
number=json_number->valuestring;
start_time=&json_start_time->valueint;
user_id=json_user_id->valuestring;
my_zlog_debug("id: %s", id);
my_zlog_debug("model: %s", model);
my_zlog_debug("number: %s", number);
my_zlog_debug("start_time: %d", *start_time);
my_zlog_debug("user_id: %s", user_id);
if(gverify_count>3000){
int encryption_index=mqtt_encryption();
my_zlog_notice("加密情况:%d",encryption_index);
gverify_count=0;
}
} else {
my_zlog_warn("Some fields missing");
return -1;
}
return 0;
}
/**
* @brief 根据传入的参数动态创建一个JSON字符串。
*
* @param id 记录ID
* @param model 设备型号
* @param number 编号
* @param start_time 开始时间
* @param user_id 用户ID
* @return char* 一个动态分配的JSON字符串。使用后必须调用free()释放。
* 如果内存分配失败,返回NULL。
*/
char* create_json_string(const char* id, const char* model, const char* number, const int* start_time, const char* user_id , const char* only_id) {
// JSON格式模板
const char *json_format = "{\"id\":\"%s\",\"model\":\"%s\",\"number\":\"%s\",\"start_time\":\"%s\",\"user_id\":\"%s\",\"only_id\":\"%s\"}";
char time_str[20]; // 足够存储20位数字和终止符
snprintf(time_str, sizeof(time_str), "%d", *start_time);
// 1. 计算所需总长度,以安全地分配内存
// 长度 = 模板长度 - 5*%s长度(10) + 各字符串实际长度 + 1个空终止符
int needed_size = strlen(json_format) - 10
+ strlen(id)
+ strlen(model)
+ strlen(number)
+ strlen(time_str)
+ strlen(user_id)
+ strlen(only_id) + 1;
// 2. 分配内存
char *json_string = (char*)malloc(needed_size);
if (json_string == NULL) {
fprintf(stderr, "错误: JSON字符串内存分配失败\n");
return NULL;
}
// 3. 使用snprintf安全地格式化字符串
snprintf(json_string, needed_size, json_format, id, model, number, time_str, user_id,only_id);
return json_string;
}
//base64编码代码
char* base64_encode(const unsigned char* buffer, int length) {
// Base64编码后的长度计算公式:4 * ((length + 2) / 3)
// +1 是为了最后的空终止符 '\0'
int b64_len = 4 * ((length + 2) / 3) + 1;
char *b64_str = (char*)malloc(b64_len);
if (b64_str == NULL) {
fprintf(stderr, "错误: Base64字符串内存分配失败\n");
return NULL;
}
// 使用OpenSSL的函数进行编码
int encoded_len = EVP_EncodeBlock((unsigned char*)b64_str, buffer, length);
// EVP_EncodeBlock 不会添加空终止符,我们需要手动添加
b64_str[encoded_len] = '\0';
return b64_str;
}
void mqtt_send_verify(unsigned char *ciphertext, int cipher_len) {
topic_middle_value();//指针中间函数
cJSON *root = cJSON_CreateObject();
cJSON *body = cJSON_CreateObject();
cJSON *head = cJSON_CreateObject();
// 8. 【新】将拼接后的二进制数据进行 Base64 编码
char *base64_output_str = base64_encode(ciphertext, cipher_len);
if (base64_output_str == NULL) {
// 错误处理
my_zlog_debug("base64_output_str为空");
return ;
}
// 打印出最终的、可以直接复制的Base64字符串
my_zlog_debug("要发送的完整数据 (Base64): %s", base64_output_str);
cJSON_AddStringToObject(body, "data", base64_output_str);//为0成功
cJSON_AddNumberToObject(head, "message_type",3006);
cJSON_AddItemToObject(root, "body", body);
cJSON_AddItemToObject(root, "head",head);
char *payload = cJSON_PrintUnformatted(root);
my_zlog_debug("%s",payload);
mosquitto_publish(mosq, NULL, TOPIC3, strlen(payload), payload, 0, false);
cJSON_Delete(root); // 释放 cJSON 对象
}
//加密并发送mqtt
int mqtt_encryption(){
// =================================================================
char *only_id="sadas";
// 1. 准备明文、密钥和IV
// 从配置数据动态生成JSON字符串
char *json_to_encrypt = create_json_string(id, model, number, start_time, user_id,only_id);
if (json_to_encrypt == NULL) {
return 1; // 内存分配失败,退出
}
my_zlog_debug("生成的待加密JSON: %s", json_to_encrypt);
const unsigned char *plaintext = (const unsigned char *)json_to_encrypt;
const unsigned char *key = (const unsigned char *)"gds-dfgbcvdfgghj";//密钥
unsigned char iv[AES_BLOCK_SIZE];
// 生成随机IV
if (!RAND_bytes(iv, sizeof(iv))) {
fprintf(stderr, "错误: 无法生成随机IV\n");
my_zlog_error("错误: 无法生成随机IV");
free(json_to_encrypt); // 别忘了释放内存
return 1;
}
my_zlog_debug("原始JSON: %s", plaintext);
my_zlog_debug("\n--- 加密开始 ---");
// 2. 初始化加密上下文
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
fprintf(stderr, "错误: EVP_CIPHER_CTX_new 失败\n");
my_zlog_debug("错误: EVP_CIPHER_CTX_new 失败");
free(json_to_encrypt);
return 1;
}
// 3. 设置加密算法、密钥和IV
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) {
fprintf(stderr, "错误: EVP_EncryptInit_ex 失败\n");
my_zlog_debug("错误: EVP_EncryptInit_ex 失败");
EVP_CIPHER_CTX_free(ctx);
free(json_to_encrypt);
return 1;
}
// 4. 提供明文进行加密
int plaintext_len = strlen((char*)plaintext);
unsigned char *ciphertext = malloc(plaintext_len + AES_BLOCK_SIZE);
int len, ciphertext_len;
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
// ... 错误处理 ...
my_zlog_error("错误处理,释放相关内存,返回1");
EVP_CIPHER_CTX_free(ctx);
free(json_to_encrypt);
free(ciphertext);
return 1;
}
ciphertext_len = len;
// 5. 结束加密
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
// ... 错误处理 ...
EVP_CIPHER_CTX_free(ctx);
free(json_to_encrypt);
free(ciphertext);
return 1;
}
ciphertext_len += len;
// 6. 打印结果并清理
my_zlog_debug("加密后的密文 (Ciphertext)", ciphertext, ciphertext_len);
EVP_CIPHER_CTX_free(ctx);
//拼接cbc
int final_data_len = AES_BLOCK_SIZE + ciphertext_len;
unsigned char *final_data = malloc(final_data_len);
if (final_data == NULL) {
// 错误处理
my_zlog_error("最终数据内存分配失败");
free(json_to_encrypt);
free(ciphertext);
return 1;
}
// 先拷贝IV到最终数据的前16个字节
memcpy(final_data, iv, AES_BLOCK_SIZE);
// 再拷贝密文到IV的后面
memcpy(final_data + AES_BLOCK_SIZE, ciphertext, ciphertext_len);
my_zlog_debug("--- 加密完成 ---");
mqtt_send_verify(final_data, final_data_len);//发送mqtt给服务端
// ********** 重要: 释放所有动态分配的内存 **********
free(json_to_encrypt);
free(ciphertext);
free(final_data);
return 0;
}
//解密函数
// base64解码函数
unsigned char *base64_decode(const char *base64_str, int *out_len) {
BIO *bio, *b64;
int decode_len = strlen(base64_str) * 3 / 4;
unsigned char *buffer = (unsigned char *)malloc(decode_len + 1);
if (buffer == NULL) {
fprintf(stderr, "内存分配失败\n");
return NULL;
}
bio = BIO_new_mem_buf((void *)base64_str, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
// 不使用换行符
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
*out_len = BIO_read(bio, buffer, strlen(base64_str));
buffer[*out_len] = '\0';
BIO_free_all(bio);
return buffer;
}
// AES-128-CBC 解密
int aes_decrypt(const unsigned char *ciphertext, int ciphertext_len, const unsigned char *key, const unsigned char *iv, unsigned char **plaintext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) {
fprintf(stderr, "EVP_CIPHER_CTX_new 失败\n");
return -1;
}
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) {
fprintf(stderr, "EVP_DecryptInit_ex 失败\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
*plaintext = (unsigned char *)malloc(ciphertext_len + AES_BLOCK_SIZE);
if (*plaintext == NULL) {
fprintf(stderr, "内存分配失败\n");
EVP_CIPHER_CTX_free(ctx);
return -1;
}
int len, plaintext_len;
if (1 != EVP_DecryptUpdate(ctx, *plaintext, &len, ciphertext, ciphertext_len)) {
fprintf(stderr, "EVP_DecryptUpdate 失败\n");
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
plaintext_len = len;
if (1 != EVP_DecryptFinal_ex(ctx, *plaintext + len, &len)) {
fprintf(stderr, "EVP_DecryptFinal_ex 失败,可能是密钥或IV错误,或者填充不正确\n");
EVP_CIPHER_CTX_free(ctx);
free(*plaintext);
return -1;
}
plaintext_len += len;
(*plaintext)[plaintext_len] = '\0';
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
//总解密函数,将base64位进行解密
int aes_decrypt_base64_cbc(const char *base64_input) {
// 密钥 (必须与加密端一致)
const unsigned char *key = (const unsigned char *)"gds-dfgbcvdfgghj";
// 1. Base64 解码
int binary_len = 0;
unsigned char *binary_data = base64_decode(base64_input, &binary_len);
if (binary_data == NULL) {
fprintf(stderr, "Base64 解码失败\n");
my_zlog_warn("Base64 解码失败");
return 1;
}
// 2. 提取 IV 和密文
if (binary_len <= AES_BLOCK_SIZE) {
fprintf(stderr, "数据长度不足,无法提取 IV\n");
my_zlog_warn("数据长度不足,无法提取 IV");
free(binary_data);
return 1;
}
unsigned char iv[AES_BLOCK_SIZE];
memcpy(iv, binary_data, AES_BLOCK_SIZE);
unsigned char *ciphertext = binary_data + AES_BLOCK_SIZE;
int ciphertext_len = binary_len - AES_BLOCK_SIZE;
// 3. 解密
unsigned char *plaintext = NULL;
int plaintext_len = aes_decrypt(ciphertext, ciphertext_len, key, iv, &plaintext);
if (plaintext_len < 0) {
fprintf(stderr, "解密失败\n");
my_zlog_error("解密失败");
free(binary_data);
return 1;
}
my_zlog_debug("解密结果: %s", plaintext);//解密出来的基本为json字符串,到时候可用
// 释放内存
free(binary_data);
free(plaintext);
return 0;
}
......@@ -11,6 +11,7 @@
#include "device_exit.h"
#include "thread_main.h"
#include "wifichange.h"
#include "mqtt_verify.h"
pthread_t thread[6]; // 全局线程句柄数组(或传参)
......@@ -135,7 +136,9 @@ void *Mqtt_onnect(void *arg) {
void *delay_count(void *arg) {
while (1) {
Delay_Ms(0,5);
device_delay_count++;
device_delay_count++;//设备计时,坦克打击倒退逻辑
gverify_count++;//验证计时,每15s一次
if(gverify_count >= 5000) gverify_count = 5000;
if(device_delay_count >= 5000) device_delay_count = 5000;
}
return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment