ESP8266-Arduino网络编程实例-SSL-Web服务器

SSL-Web服务器

若要保护 Web 服务器,可以使用传输层安全 (TLS)(以前称为安全套接字层 (SSL))证书来加密 Web 流量。本文将介绍如何创建Web SSL服务器。

1、硬件准备

  • ESP8266 NodeMCU开发板一块
  • 数据线一条

2、软件准备

  • Arduino IDE或VSCode + PlatformIO

在前面的文章中,对如何搭建ESP8266开发环境做了详细的介绍,请参考:

ESP8266 NodeMCU的引脚介绍在前面的文章中做了详细的介绍,请参考:

3、代码实现

1)创建证书

下载并安装OpenSSL:http://slproweb.com/download/Win64OpenSSL-3\_0\_5.exe

在Windows命令行下运行如下命令:

1)创建根证书

1
2
3
4
5
# 创建 CA 私钥
openssl genrsa -out ca.key 2048
# 制作 CA 公钥(证书)
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

2)签发证书

1
2
3
4
5
6
7
8
9
10
# 创建密钥(私钥/公钥)
openssl genrsa -out a.pem 1024
openssl rsa -in a.pem -out a.key
# 生成签发请求
openssl req -new -key a.pem -out a.csr
# 使用 CA 证书进行签发
openssl x509 -req -sha256 -in a.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out a.crt
# 验证签发证书是否正确
openssl verify -CAfile ca.crt a.crt

Web服务器将使用到证书和私钥。这两个文件分为:ca.crt和a.key。

2)代码实现

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
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServerSecure.h>
#include <ESP8266mDNS.h>

const char* ssid = "DESKTOP-4LOBMNU0960";
const char* ssid_pwd = "iot123456";

// SSL Web服务器
BearSSL::ESP8266WebServerSecure server(443);
// 服务器缓存
BearSSL::ServerSessions serverCache(5);

// 证书数据
static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDRTCCAi0CFAe0zMu6PmqmjpIb8CxaQ2778xnHMA0GCSqGSIb3DQEBCwUAMIGg
MQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3VhbmdEb25nMRIwEAYDVQQHDAlHdWFu
Z1pob3UxFDASBgNVBAoMC0lvVCBTZXJ2aWNlMRQwEgYDVQQLDAtJb1QgU2Vydmlj
ZTEUMBIGA1UEAwwLSW9UIFNlcnZpY2UxJzAlBgkqhkiG9w0BCQEWGGtrb29sZXJ0
ZXJAaW90c2VydmljZS5jbjAeFw0yMjEwMDkxMzMzMzdaFw0zMjEwMDYxMzMzMzda
MIGgMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3VhbmdEb25nMRIwEAYDVQQHDAlH
dWFuZ1pob3UxFDASBgNVBAoMC0lvVCBTZXJ2aWNlMRQwEgYDVQQLDAtJb1QgU2Vy
dmljZTEUMBIGA1UEAwwLSW9UIFNlcnZpY2UxJzAlBgkqhkiG9w0BCQEWGGtrb29s
ZXJ0ZXJAaW90c2VydmljZS5jbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
4Mx75uHCRDmuSWZi4XAw3UuH8PsOqXhrNbc044eI1uHCDs0cwoqECT5wofKYvGF0
Edbhwt91ikenG8aZxmaOQXdWPQudwAWau1jYF8zN2ayJokwjhHy+y02RwE0NCyAd
rAsdbTxmcmIGVl6uxBwG1nVZZWxclw7h8a+CSU5/SfMCAwEAATANBgkqhkiG9w0B
AQsFAAOCAQEAWqxfGDyQm6hemq26BaPg/FTbKoBPJDKU9GawYQtoH6qEVchY1DKN
6AZnJtopRZXbjX8805qdhPtLa7pygR4rcmJbEegtauFc4seOMmd4VT1hRxB8+/Ti
AEmVhUH2ozbw/tDYqijs72JNUe8FNuabTzle3afOYBDlAeAMWPwGnYtUSM/8HfHv
QFRLRDpz2jRmcpM4wjJIy7y83OPKvgXBP9BQgpDutFpiQTfNpPwlgX/CHI+JqT00
gVpf53ZeHH9LvQNZ1X3OwKZqvBEGSaFptQZ2KsuYJ+NK4oNv1QZ0hILNEP39A9ER
XBvh3PK6UDGjKdnWUllgOY8VL9QsPxPlhw==
-----END CERTIFICATE-----
)EOF";

// 服务器私钥
static const char serverKey[] PROGMEM = R"EOF(
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAODMe+bhwkQ5rklm
YuFwMN1Lh/D7Dql4azW3NOOHiNbhwg7NHMKKhAk+cKHymLxhdBHW4cLfdYpHpxvG
mcZmjkF3Vj0LncAFmrtY2BfMzdmsiaJMI4R8vstNkcBNDQsgHawLHW08ZnJiBlZe
rsQcBtZ1WWVsXJcO4fGvgklOf0nzAgMBAAECgYAf/9uvTPmrXo6ZsjJnJuI9zg+m
1QYMR7DzL4Ye0V9AP1ixZK8wXilXa4T6+J6XSkQMegsfA1InAfYetRGUtWqQUM9I
NC5Rqbl02/9hx6iWv36Fth/s+sgcAK/6oPFRVGW42tlZRdaQXs/k/zAcVO9vlVG9
fluls5/ngHaeBrKwgQJBAPOwOTP8YGMF5QvsrqsCw746b0PP3e/Q5grRti638c4m
BRbJFvXvoJv9Aax5rr5ZNuaEfVrbV4UICPORm1ruyzMCQQDsJ/MCEVaiFYxccdoN
SNaKCAnTSuvgEvJ+N0pxbRpC0YB3TR3ZzQ/O3YMm6Yz7OaRd7CCDMLvXFPWYEjMI
e4ZBAkEA7MHlAc4M84hRncFJfprEBPkPCwpVLV9/cTmI0GEkzE4CGb4r0awMFiG9
U44xqXxSK6rDg9ehc313/PUVxEZHIwJBAN3blhfONCZnugqrRyAN2seoT5q6GyjS
hBABX6V5yx8U9OyffTi9xmkgf3MSHMlz2LAIAm9dXEruvN+V0W3ZpkECQHI+wZoU
GKc4qi0b39FpU9kuO7yU9TtQW0ilISCLtKGsMecKiQniRBKIO8z6BVOQpFxKfohY
NOwmh1Pdk4GyqFA=
-----END PRIVATE KEY-----
)EOF";


const int led = 2;

void handleRoot() {
digitalWrite(led, 1);
server.send(200, "text/plain", "Hello from esp8266 over HTTPS!");
digitalWrite(led, 0);
}

void handleNotFound() {
digitalWrite(led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
server.send(404, "text/plain", message);
digitalWrite(led, 0);
}

void setup(void) {
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.begin(ssid, ssid_pwd);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }

// 设置证书和私钥
server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));

// 缓存 SSL 会话,用来加速SSL握手
server.getServer().setCache(&serverCache);

server.on("/", handleRoot);

server.on("/inline", []() {
server.send(200, "text/plain", "this works as well");
});

server.onNotFound(handleNotFound);
// 启动服务器
server.begin();
Serial.println("HTTPS server started");
}

运行结果

在这里插入图片描述

文章来源: https://iotsmart.blog.csdn.net/article/details/127263585