透過 WiFi 使用 HTTPS 傳輸資料



在上一章中,我們研究瞭如何使用 ESP32 透過 HTTP 傳輸資料。在本章中,我們將透過 HTTPS 傳輸資料。HTTPS 中的 S 代表“安全”。基本上,您傳輸的任何資料都使用傳輸層安全性 (TLS) 進行加密。這意味著,如果有人竊聽您的通訊,他們將無法理解您傳輸的內容。相反,他們得到的是一些亂碼。本章不涉及 HTTPS 的工作原理。但簡單的 Google 搜尋將為您提供多個有用的資源以幫助您入門。在本章中,我們將瞭解如何在 ESP32 上實現 HTTPS。

將任何 HTTP 請求轉換為 ESP32 上的 HTTPS

通常,如果您有用於向伺服器傳送 HTTP 請求的程式碼,則可以透過以下簡單步驟將其轉換為 HTTPS:

  • 將庫從 WiFiClient 更改為 WiFiClientSecure(您需要包含 WiFiClientSecure.h)

  • 將埠從 80 更改為 443

還有一個可選的第四步:為伺服器新增 CA 證書。此步驟是可選的,因為它不會影響通訊的安全性。它只是確保您正在與正確的伺服器通訊。如果您不提供 CA 證書,您的通訊仍然是安全的。

程式碼演練

您在下面看到的程式碼與用於 HTTP 通訊的程式碼非常相似。強烈建議您重新訪問那一章。在本演練中,我們將僅重點介紹與 HTTP 程式碼不同的部分。

程式碼可以在 GitHub 上找到

我們首先包含 WiFi 庫。我們還需要在此處包含 WiFiClientSecure 庫。

#include <WiFi.h>
#include <WiFiClientSecure.h>

接下來,我們將定義常量。請注意,埠現在為 443 而不是 80。

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

const char* server = "httpbin.org";
const int port = 443;

接下來,我們建立 WiFiClientSecure 物件,而不是 WiFiClient 物件。

WiFiClientSecure client;

接下來,我們為我們的伺服器 (httpbin.org) 定義 CA 證書。現在,您可能想知道如何獲取我們伺服器的 CA 證書。此處提供了使用 Google Chrome 獲取任何伺服器的 CA 證書的詳細步驟。在同一篇文章中,還提供了一篇關於 CA 證書有效性的說明,建議使用認證機構的證書,而不是伺服器的證書,尤其是在您只需程式設計裝置一次並將其傳送到現場多年使用的應用程式中。認證機構的證書具有更長的有效期(15年以上),而伺服器的證書有效期較短(1-2年)。因此,我們使用 Starfield Class 2 認證機構的證書(有效期至 2034 年),而不是 httpbin.org 的證書(有效期至 2021 年 2 月)。

CA Certificate
const char* ca_cert = \ 
"-----BEGIN CERTIFICATE-----\n" \
"MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"\
"MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"\
"U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"\
"NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"\
"ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"\
"ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"\
"DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"\
"8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"\
"+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"\
"X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"\
"K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"\
"1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"\
"A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"\
"zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"\
"YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"\
"bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"\
"DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"\
"L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"\
"eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"\
"xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"\
"VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"\
"WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"\
"-----END CERTIFICATE-----\n";

在設定中,我們像以前一樣使用提供的憑據以 station 模式連線到 WiFi。在這裡,我們還有設定 WiFiSecureClient 的 CA 證書的額外步驟。透過這樣做,我們告訴客戶端只有當其 CA 證書與提供的證書匹配時才與伺服器通訊。

void setup() {
   Serial.begin(115200);
   WiFi.mode(WIFI_STA);                    //The WiFi is in station mode. The    other is the softAP mode
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
   }
   Serial.println("");  Serial.print("WiFi connected to: "); Serial.println(ssid);  Serial.println("IP address: ");  Serial.println(WiFi.localIP());
   client.setCACert(ca_cert);            //Only communicate with the server if the CA certificates match
   delay(2000);
}

迴圈與 HTTP 示例中使用的迴圈完全相同。

void loop() {
   int  conn;
   int chip_id = ESP.getEfuseMac();;
   Serial.printf("  Flash Chip id = %08X\t", chip_id);
   Serial.println();
   Serial.println();
   String body = "ChipId=" + String(chip_id) + "&SentBy=" + "your_name";
   int body_len = body.length();

   Serial.println(".....");
   Serial.println(); Serial.print("For sending parameters, connecting to "); Serial.println(server);
   conn = client.connect(server, port);

   if (conn == 1) {
      Serial.println(); Serial.print("Sending Parameters...");
      //Request
      client.println("POST /post HTTP/1.1");
      //Headers
      client.print("Host: "); client.println(server);
      client.println("Content-Type: application/x−www−form−urlencoded");
      client.print("Content-Length: "); client.println(body_len);
      client.println("Connection: Close");
      client.println();
      //Body
      client.println(body);
      client.println();

      //Wait for server response
      while (client.available() == 0);

      //Print Server Response
      while (client.available()) {
         char c = client.read();
         Serial.write(c);
      }
   } else {
      client.stop();
      Serial.println("Connection Failed");
   }
   delay(5000);
}

伺服器期望的響應也類似於 HTTP 示例。唯一的區別是收到的響應也將是安全的。但我們不必擔心解密加密的訊息。ESP32 為我們完成了這項工作。

HTTPS Server response

請注意伺服器響應中的 URL 欄位。它包含 https 而不是 http,確認我們的傳輸是安全的。事實上,如果您稍微編輯 CA 證書,例如刪除一個字元,然後嘗試執行草圖,您將看到連線失敗。

HTTPS Server Failed Connection

但是,如果您從設定中刪除了client.setCACert()行,即使使用有故障的 CA 證書,連線也將再次安全地建立。這證明設定 CA 證書不會影響我們通訊的安全性。它只是幫助我們驗證我們正在與正確的伺服器通訊。如果我們確實設定了證書,那麼 ESP32 只有在提供的 CA 證書與伺服器的 CA 證書匹配時才會與伺服器通訊。如果我們不設定證書,ESP32 仍然可以安全地與伺服器通訊。

恭喜!!您已成功使用 ESP32 傳送 HTTPS 請求。

注意 - ESP32 上執行 HTTPS 訊息加密的硬體加速器最多支援 16384 位元組(16 KB)的資料。因此,如果您的訊息大小超過 16 KB,您可能需要將其分解成塊。

參考文獻

廣告

© . All rights reserved.