物联网应用层CoAP通信安全实现

实验目的及要求

CoAP协议是物联网应用中重要的应用层协议,上一次实验开展了CoAP协议的分析,对CoAP协议的交互机制进行了分析。但如果CoAP协议不进行安全实现,黑客可以恶意发布信息给服务器,特别是在工业、交通等物联网应用场合后果不堪设想。本实验旨构建CoAP协议安全通信。

实验要求

  1. 掌握CoAP的安全通信的基本原理;
  2. 设计CoAP安全通信的安全措施;
  3. 实现基于DTLS的CoAP通信。

实验基本步骤

Step1:CoAP安全通信的基本原理
Step2:设计CoAP安全通信的安全措施
Step3:实现基于DTLS的CoAP通信

实验过程、分析及有关程序代码

1 CoAP安全通信的基本原理

1.1 简单介绍

根据CoAP协议所遭受的安全威胁,CoAP协议标准规定需要依靠DTLS协议来提供相关安全保障,并为CoAP协议定义了三种安全模式,DTLS协议与CoAP协议的关系如图1.1所示。

图1.1 DTLS协议与CoAP协议的关系

CoAP协议标准RFC7252中对协议的安全模式描述如下:

  • NoSec模式:没有安全性(DTLS协议被禁用),即应用层和传输层并没有加入安全机制,此时可以采用其他的安全技术保障其安全性;
  • Pre Shared Key模式:(DTLS协议启用),在通信双方预存储一个预共享密钥的列表,其中每个密钥都对应着一个相应的标识;
  • Raw Public Key模式:(DTLS协议启用),通信双方拥有公私钥对,但是没有X.509证书。通信双方使用公钥类型字段作为证书的载荷,从而降低构造证书签名所带来的开销;
  • Certificate X.509模式:(DTLS协议启用),通信双方拥有公私钥对,并且引入第三方信任中心(CA)构造X.509证书,将构造的证书发送到它的请求方,通信双方通过验证证书来完成认证。

2 设计CoAP安全通信的安全措施

2.1 概述

DTLS的目标应用主要是C/S及其变体。这也是TLS的设计目标并且已很好工作。展示的安全模型中,server通过DNS名称和IP地址被认证,Client是匿名的或者被其他形式认证,典型的是在应用层通过用户名/密码来处理。

这个实现并不真正安全。然而,应用程序的设计者们,向在添加安全性的时候尽量能够维护他们的协议和实现架构。这个实现制造了一个类似于TLS或IPSec的有吸引力的信道安全协议,因为改动之非常小。从这个观点看来,理想的数据报信道安全协议应该取代对Server的DNS和基于IP认证的强加密认证,而是把client认证留给应用层协议。

2.2 握手协议

Handshake协议最主要的作用就是完成通信双方的认证过程,DTLS协议的Handshake协议相比TLS协议增加了Cookie机制和消息重传的功能。Handshake协议采用了Cookie交换机制,在客户端发送的第一条报文Client Hello中Cookie值为空。资源服务器接收到第一条请求报文后,会生成一个Cookie值填充至响应报文Hello_ Verify Request中。客户端接收到响应报文后,提取此Cookie值,再次发送至资源服务器。资源服务器接收后与自身的Cookie值进对比,如果对比结果相同,オ可以进行下一步通信,其交换过程如图2.1所示。

图2.1 Cookie交换模型

在完成了Cookie校验机制后,DTLS协议开始端到端的握手过程,其完整的握手过程如图2.2所示。

图2.2 DTLS协议握手交互过程

DTLS协议完整的握手交互过程解释如下:

  1. Client_Hello:报文中含有Cookie的值,此时Cookie值为空;
  2. Hello_Verify_Request:客户端检验接收到的Client_Hello报文中Cookie值是否为空,如果为空则说明之前并未建立过连接,服务器会生成一个Cookie值返回至客户端中;
  3. Client_Hello:此时客户端接收服务器发来的报文,提取出Cookie值填入此次报文中;
  4. Server_Hello:服务器接收客户端报文后,提取Cookie值与自身的值进行验证,验证通过则继续握手连接;
  5. Server Certificate:此报文段包含一个证书字段,用来验证服务器的身份(如果使用对称密钥算法则此条报文忽略);
  6. Server Key Exchange:此过程为密钥交换的过程,即采用上一段报文中所选择的密钥协商算法进行通信双方的密钥协商;
  7. Certificate Request:如果通信双方采用的是基于证书的认证模式,此条报文要求客户端要回应一个自身构造的证书,双方通过基于证书的认证签名机制来完成认证的过程(如果使用对称密钥算法,则此条报文忽略);
  8. Server Hello Done:此条表示服务器端操作完成,将上述三条报文打包发送至客户端,等待客户端;
  9. Client Certificates:客户端接收到上述报文后,如果双方使用了证书模式,则按照要求进行证书的验证以及签名等操作(如果使用对称密钥算法,则此条报文忽略);
  10. Client Key Exchange:如果客户端与资源服务器采用的是对称密钥算法,则此条报文用来协商生成会话密钥;
  11. Certificate Verif:此条报文对服务器端构造的证书进行解签名验证(如果使用对称密钥算法,则此条报文忽略);
  12. Change Cipher Spec:此消息用来告知资源服务器端所生成的会话密钥或者告知资源服务器双方的认证已经完成;
  13. Client Finished:此条报文表示客户端的操作已经完成,将上述三条报文打包发送至资源服务器;
  14. Change Cipher Spec Server:此消息用来完成会话密钥的生成或者证书的验证;
  15. Server Finished:此消息表示资源服务器端的操作已经全部完成,双方可以通过协商的会话密钥或者公私钥进行消息的加密。

3.实现基于DTLS的CoAP通信

3.1 简单实现

首先,我在kali中打开一个终端,使用下面的命令克隆FreeCoAP的源码,然后安装相关的依赖包和工具autoconf、libtool-bin、libgnutls-dev和wireshark-qt,如图3.1所示。

图3.1 安装依赖包

详细安装步骤可以参考下面的文章

https://github.com/keith-cullen/FreeCoAP

然后,在kali中打开另一个终端,通过调用tcpdump捕获通信数据包,如图3.2所示。

图3.2 捕获通信数据包

接着,再打开一个新的终端运行Demo的服务器,如图3.3所示。

图3.3 运行服务器

最后,打开最后一个终端,运行Demo的客户端,如图3.4所示。

图3.4 运行客户端

3.2 用wireshark分析

首先,用wireshark打开在3.1中用tcpdump捕获的通信数据包,发现了DTLSv1.2协议和信息通信的过程,如图3.5所示。

图3.5 捕获的数据包

然后,在预共享密钥模式下,在应用层和UDP之间引入DTLS协议,将预共享密钥机制与DTLS协议中密码规则协议相结合,采用TLS_ECDHE_ECDSA_WITH_AES_128_GSM_SHA256算法,实现可信的端到端安全关联和数据的加密,如图3.6所示。

图3.6 加密算法

接着,在密钥交换的过程中,利用Diffie-Hellman密钥交换协议巧妙确定对称密钥,达到安全通信的目的。另外,该过程还利用ecdsa_secp256r1_sha256算法对通信的数据进行签名,获得长度为71的签名,如图3.7所示。

密码规则协议中使用PSK预共享机制有以下两个原因:

  • 在网络资源受限的环境下,使用PSK预共享密钥算法相比公私钥等模式造成的开销较低;
  • 预共享密钥机制相比其他密码学算法的配置过程更加简洁,比如在一个封闭的网络环境中,大多数操作都是预先手动配置的,而配置PSK预共享密钥相比RSA公钥证书模式要更方便。

图3.7 密钥交换和签名

下一步,就是证书的验证过程,就是利用相同的签名算法进行验证,得到与上一过程相同的签名,如图3.8所示。

图3.8 验证签名

改变密码规则协议此协议是起到一个标志的作用,用来告知客户端和资源服务器已经完成了密钥的交换等过程,如图3.9所示。

图3.9 改变密码规则

警告协议Alert协议是一种返回机制,即通信双方在交互的时候如果发生错误或者安全威胁,就会通知通信双方,通信双方会结束会话避免信息的泄露,如图3.10所示。

图3.10 警告协议Alert

最后,在上面过程的基础上,服务器和客户端就可以传输加密的握手包信息和加密数据了,如图3.11所示。

图3.11 传输数据

3.3 代码展示

服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#ifdef COAP_DTLS_EN
#include <gnutls/gnutls.h>
#endif
#include "reg_server.h"
#include "coap_msg.h"
#include "coap_mem.h"
#include "coap_log.h"
#define REG_SERVER_URI_PATH_BUF_LEN 32
#define REG_SERVER_PAYLOAD_LEN 32
/**< Number of buffers in the small memory allocator */
#define REG_SERVER_SMALL_BUF_NUM 128
/**< Length of each buffer in the small memory allocator */
#define REG_SERVER_SMALL_BUF_LEN 256
/**< Number of buffers in the medium memory allocator */
#define REG_SERVER_MEDIUM_BUF_NUM 128
/**< Length of each buffer in the medium memory allocator */
#define REG_SERVER_MEDIUM_BUF_LEN 1024
/**< Number of buffers in the large memory allocator */
#define REG_SERVER_LARGE_BUF_NUM 32
/**< Length of each buffer in the large memory allocator */
#define REG_SERVER_LARGE_BUF_LEN 8192
static void reg_server_log_registrar(reg_server_t *server)
{
registrar_entry_t *entry = NULL;
int i = 0;
entry = registrar_get_first(&server->registrar);
while (entry != NULL)
{
coap_log_info("registrar[%d]: id='%s', addr='%s'",
i, registrar_entry_get_id(entry),
registrar_entry_get_addr(entry));
i++;
entry = registrar_entry_get_next(entry);
}
}
static int reg_server_handle_client_id(coap_server_trans_t *trans, coap_msg_t *req, coap_msg_t *resp)
{
reg_server_t *server = (reg_server_t *)trans->server;
registrar_t *registrar = &server->registrar;
const char *p = NULL;
unsigned code_detail = 0;
size_t n = 0;
char payload[REG_SERVER_PAYLOAD_LEN] = {0};
char addr[COAP_IPV_INET_ADDRSTRLEN] = {0};
int created = 0;
int ret = 0;
code_detail = coap_msg_get_code_detail(req);
if (code_detail == COAP_MSG_POST)
{
/* process request */
coap_log_info("Received request method: POST");
p = inet_ntop(COAP_IPV_AF_INET, &trans->client_sin.COAP_IPV_SIN_ADDR, addr, sizeof(addr));
if (p == NULL)
{
coap_log_warn("Could not resolve client address: %s", strerror(errno));
return coap_msg_set_code(resp, COAP_MSG_SERVER_ERR, COAP_MSG_INT_SERVER_ERR);
}
addr[sizeof(addr) - 1] = '\0';
coap_log_info("Received request from address: %s", addr);
p = coap_msg_get_payload(req);
n = coap_msg_get_payload_len(req);
if ((p == NULL) || (n == 0))
{
coap_log_warn("Received request message without payload");
return coap_msg_set_code(resp, COAP_MSG_CLIENT_ERR, COAP_MSG_BAD_REQ);
}
if ((n + 1) > sizeof(payload))
{
coap_log_warn("Payload buffer too small by %zd bytes", (n + 1) - sizeof(payload));
return coap_msg_set_code(resp, COAP_MSG_SERVER_ERR, COAP_MSG_INT_SERVER_ERR);
}
memcpy(payload, p, n);
memset(payload + n, 0, sizeof(payload) - n);
coap_log_info("Received request payload: '%s'", payload);
/* action */
ret = registrar_add(registrar, payload, addr);
if (ret < 0)
{
return ret;
}
if (ret == 0)
{
created = 1;
}
reg_server_log_registrar(server);
/* generate response */
if (created)
coap_msg_set_code(resp, COAP_MSG_SUCCESS, COAP_MSG_CREATED);
else
coap_msg_set_code(resp, COAP_MSG_SUCCESS, COAP_MSG_CHANGED);
ret = coap_msg_add_op(resp, COAP_MSG_URI_PATH, 6, "client");
if (ret < 0)
{
coap_log_warn("Failed to set URI path in response message");
return ret;
}
ret = coap_msg_add_op(resp, COAP_MSG_URI_PATH, 2, "id");
if (ret < 0)
{
coap_log_warn("Failed to set URI path in response message");
return ret;
}
memcpy(payload, "OK", 2);
memset(payload + 2, 0, sizeof(payload) - 2);
ret = coap_msg_set_payload(resp, payload, 2);
if (ret < 0)
{
coap_log_warn("Failed to set payload in response message");
return ret;
}
coap_log_info("Sent %s /client/id response with payload: '%s'",
created ? "CREATED" : "CHANGED", payload);
return 0;
}
coap_log_warn("Received request message with unsupported code detail: %d", code_detail);
return coap_msg_set_code(resp, COAP_MSG_SERVER_ERR, COAP_MSG_NOT_IMPL);
}
static int reg_server_handle(coap_server_trans_t *trans, coap_msg_t *req, coap_msg_t *resp)
{
size_t n = 0;
char uri_path[REG_SERVER_URI_PATH_BUF_LEN] = {0};
if (coap_msg_get_ver(req) != COAP_MSG_VER)
{
coap_log_warn("Received request message with invalid version: %d", coap_msg_get_ver(req));
return -EBADMSG;
}
n = coap_msg_uri_path_to_str(req, uri_path, sizeof(uri_path));
if ((n + 1) > sizeof(uri_path))
{
coap_log_warn("URI path buffer too small by %zd bytes", (n + 1) - sizeof(uri_path));
return -ENOSPC;
}
coap_log_info("Received request URI path: '%s'", uri_path);
if (strcmp(uri_path, "/client/id") != 0)
{
coap_log_warn("URI path not recognised");
return coap_msg_set_code(resp, COAP_MSG_CLIENT_ERR, COAP_MSG_NOT_FOUND);
}
return reg_server_handle_client_id(trans, req, resp);
}
/* one-time initialisation */
int reg_server_init(void)
{
#ifdef COAP_DTLS_EN
const char *gnutls_ver = NULL;
#endif
int ret = 0;
coap_log_set_level(COAP_LOG_INFO);
ret = coap_mem_all_create(REG_SERVER_SMALL_BUF_NUM, REG_SERVER_SMALL_BUF_LEN, REG_SERVER_MEDIUM_BUF_NUM, REG_SERVER_MEDIUM_BUF_LEN, REG_SERVER_LARGE_BUF_NUM, REG_SERVER_LARGE_BUF_LEN);
if (ret < 0)
{
coap_log_error("%s", strerror(-ret));
return -1;
}
#ifdef COAP_DTLS_EN
gnutls_ver = gnutls_check_version(NULL);
if (gnutls_ver == NULL)
{
coap_log_error("Unable to determine GnuTLS version");
coap_mem_all_destroy();
return -1;
}
coap_log_info("GnuTLS version: %s", gnutls_ver);
#endif
return 0;
}
void reg_server_deinit(void)
{
coap_mem_all_destroy();
}
int reg_server_create(reg_server_t *server,
const char *host,
const char *port,
const char *key_file_name,
const char *cert_file_name,
const char *trust_file_name,
const char *crl_file_name)
{
int ret = 0;
memset(server, 0, sizeof(reg_server_t));
#ifdef COAP_DTLS_EN
ret = coap_server_create(&server->coap_server,
reg_server_handle,
host,
port,
key_file_name,
cert_file_name,
trust_file_name,
crl_file_name);
#else
ret = coap_server_create(&server->coap_server,
reg_server_handle,
host,
port);
#endif
if (ret < 0)
{
if (ret != -1)
{
/* a return value of -1 indicates a DTLS failure which has already been logged */
coap_log_error("%s", strerror(-ret));
}
memset(server, 0, sizeof(reg_server_t));
return ret;
}
registrar_create(&server->registrar);
return ret;
}
void reg_server_destroy(reg_server_t *server)
{
registrar_destroy(&server->registrar);
coap_server_destroy(&server->coap_server);
memset(server, 0, sizeof(reg_server_t));
}
int reg_server_run(reg_server_t *server)
{
int ret = 0;
ret = coap_server_run(&server->coap_server);
if (ret < 0)
{
if (ret != -1)
{
/* a return value of -1 indicates a DTLS failure which has already been logged */
coap_log_error("%s", strerror(-ret));
}
}
return ret;
}

客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <string.h>
#include <errno.h>
#ifdef COAP_DTLS_EN
#include <gnutls/gnutls.h>
#endif
#include "reg_client.h"
#include "coap_msg.h"
#include "coap_mem.h"
#include "coap_log.h"
#define REG_CLIENT_URI_PATH_BUF_LEN 32
/**< Number of buffers in the small memory allocator */
#define REG_CLIENT_SMALL_BUF_NUM 128
/**< Length of each buffer in the small memory allocator */
#define REG_CLIENT_SMALL_BUF_LEN 256
/**< Number of buffers in the medium memory allocator */
#define REG_CLIENT_MEDIUM_BUF_NUM 128
/**< Length of each buffer in the medium memory allocator */
#define REG_CLIENT_MEDIUM_BUF_LEN 1024
/**< Number of buffers in the large memory allocator */
#define REG_CLIENT_LARGE_BUF_NUM 32
/**< Length of each buffer in the large memory allocator */
#define REG_CLIENT_LARGE_BUF_LEN 8192
/* one-time initialisation */
int reg_client_init(void)
{
#ifdef COAP_DTLS_EN
const char *gnutls_ver = NULL;
#endif
int ret = 0;
coap_log_set_level(COAP_LOG_INFO);
ret = coap_mem_all_create(REG_CLIENT_SMALL_BUF_NUM, REG_CLIENT_SMALL_BUF_LEN,
REG_CLIENT_MEDIUM_BUF_NUM, REG_CLIENT_MEDIUM_BUF_LEN,
REG_CLIENT_LARGE_BUF_NUM, REG_CLIENT_LARGE_BUF_LEN);
if (ret < 0)
{
coap_log_error("%s", strerror(-ret));
return -1;
}
#ifdef COAP_DTLS_EN
gnutls_ver = gnutls_check_version(NULL);
if (gnutls_ver == NULL)
{
coap_log_error("Unable to determine GnuTLS version");
coap_mem_all_destroy();
return -1;
}
coap_log_info("GnuTLS version: %s", gnutls_ver);
#endif
return 0;
}
void reg_client_deinit(void)
{
coap_mem_all_destroy();
}
int reg_client_create(reg_client_t *client,
const char *host,
const char *port,
const char *key_file_name,
const char *cert_file_name,
const char *trust_file_name,
const char *crl_file_name,
const char *common_name)
{
int ret = 0;
memset(client, 0, sizeof(reg_client_t));
#ifdef COAP_DTLS_EN
ret = coap_client_create(&client->coap_client,
host,
port,
key_file_name,
cert_file_name,
trust_file_name,
crl_file_name,
common_name);
#else
ret = coap_client_create(&client->coap_client,
host,
port);
#endif
if (ret < 0)
{
coap_log_error("%s", strerror(-ret));
memset(client, 0, sizeof(reg_client_t));
return ret;
}
return 0;
}
void reg_client_destroy(reg_client_t *client)
{
coap_client_destroy(&client->coap_client);
memset(client, 0, sizeof(reg_client_t));
}
int reg_client_register(reg_client_t *client, char *buf, size_t len)
{
coap_msg_t resp = {0};
coap_msg_t req = {0};
size_t n = 0;
char *p = NULL;
char uri_path[REG_CLIENT_URI_PATH_BUF_LEN] = {0};
int created = 0;
int ret = 0;
/* generate request */
coap_msg_create(&req);
coap_msg_set_type(&req, COAP_MSG_CON);
coap_msg_set_code(&req, COAP_MSG_REQ, COAP_MSG_POST);
coap_log_info("Sending POST /client/id request with payload: '%s'", buf);
ret = coap_msg_add_op(&req, COAP_MSG_URI_PATH, 6, "client");
if (ret < 0)
{
coap_log_error("Failed to set URI path in request message");
coap_msg_destroy(&req);
return ret;
}
ret = coap_msg_add_op(&req, COAP_MSG_URI_PATH, 2, "id");
if (ret < 0)
{
coap_log_error("Failed to set URI path in request message");
coap_msg_destroy(&req);
return ret;
}
ret = coap_msg_set_payload(&req, buf, strlen(buf));
if (ret < 0)
{
coap_log_error("Failed to set payload in request message");
coap_msg_destroy(&req);
return ret;
}
/* exchange */
coap_msg_create(&resp);
ret = coap_client_exchange(&client->coap_client, &req, &resp);
if (ret < 0)
{
if (ret != -1)
{
/* a return value of -1 indicates a DTLS failure which has already been logged */
coap_log_error("%s", strerror(-ret));
}
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return ret;
}
/* process response */
if (coap_msg_get_ver(&req) != coap_msg_get_ver(&resp))
{
coap_log_error("Received response message with invalid version: %d", coap_msg_get_ver(&resp));
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -EBADMSG;
}
if ((coap_msg_get_code_class(&resp) != COAP_MSG_SUCCESS)
|| ((coap_msg_get_code_detail(&resp) != COAP_MSG_CREATED) && (coap_msg_get_code_detail(&resp) != COAP_MSG_CHANGED)))
{
coap_log_error("Received response message with invalid code class: %d, code detail: %d",
coap_msg_get_code_class(&resp), coap_msg_get_code_detail(&resp));
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -EBADMSG;
}
created = coap_msg_get_code_detail(&resp) == COAP_MSG_CREATED;
n = coap_msg_uri_path_to_str(&resp, uri_path, sizeof(uri_path));
if ((n + 1) > sizeof(uri_path))
{
coap_log_error("URI path buffer too small by %zd bytes", (n + 1) - sizeof(uri_path));
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -ENOSPC;
}
if (strcmp(uri_path, "/client/id") != 0)
{
coap_log_error("Received response message with invalid URI path: '%s'", uri_path);
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -EBADMSG;
}
p = coap_msg_get_payload(&resp);
n = coap_msg_get_payload_len(&resp);
if ((p == NULL) || (n == 0))
{
coap_log_error("Received response message with invalid payload");
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -EBADMSG;
}
if ((n + 1) > len)
{
coap_log_error("Payload buffer too small by %zd bytes", (n + 1) - len);
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
return -ENOSPC;
}
memcpy(buf, p, n);
memset(buf + n, 0, len - n);
coap_msg_destroy(&resp);
coap_msg_destroy(&req);
if (strcmp(buf, "OK") != 0)
{
coap_log_error("Received response message with unexpected payload: '%s'", buf);
return -EBADMSG;
}
coap_log_info("Received %s %s response with payload: '%s'",
created ? "CREATED" : "CHANGED", uri_path, buf);
return n;}

实验体会

在这次实验中,我和同学遇到了极大的困难,对我来说,这次实验堪称大学以来最难做的实验,但是,通过我和舍友一起翻阅资料,还是能够按时完成实验。

通过这次实验,我又一步加深了对C语言的理解,使用C语言实现CoAP服务器和客户端的加密通信。同时,查阅了RFC7252中对CoAP的安全模式,理解了DTLS协议和CoAP协议在计算机网络中的层次,深入分析CoAP协议的基本原理,明白了客户端和服务器之间利用预共享密钥机制之间的密钥协商过程。另外,通过在kali中使用tcpdump捕获通信数据包,并用wireshark进行分析流量包,进一步理解了握手过程中Cookie机制和通信双方的认证过程。

最后,这次实验是对我进入矿大后的一次总结吧,充分利用了平常自己和老师在课上教授的各种知识,做到了学以致用。

声明

本文创作时参考的文章如下:

https://blog.csdn.net/hylaking/article/details/89473172


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏