You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeMCU ESP8266CH340使用WifiClientSecure验证SSL指纹失败,POST请求返回httpCode-1求助

问题:NodeMCU ESP8266CH340 SSL指纹验证失败导致POST请求返回httpCode -1

使用NodeMCU ESP8266CH340开发板,通过WifiClientSecure验证Google Trust颁发的SSL证书指纹时失败,POST请求执行失败并返回httpCode -1。不想设置client.setInsecure()绕过SSL验证,寻求解决方法。

相关代码

//ADC_MODE(ADC_VCC) //To read Temp, VCC potential
#define DEBUG  //Set debug environment
#pragma GCC optimize("Ofast") //For fast execustion (aggressive optimization)

//Header files
#include <cstddef>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <NTPClient.h>

IPAddress remote_ip;
ESP8266WebServer server(80);
WiFiUDP ntpUDP;

const long utcOffsetInSeconds = 19800; //Timezone: Asia/Kolkata (IST/GMT+5:30)
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);


int D1 = 5;
int raw = analogRead(A0);
float vcc = 1.0*1024.0/raw; //Read VCC potential
float temp = (raw-21)/1.7; //Read CPU temp

//Fingerprint of API endpoint to verify SSL/TLS
const char fingerprint[] PROGMEM = "FF:46:2F:ED:A1:38:BA:98:4D:CD:DA:B5:AE:9B:A5:D1:00:12:04:D5:77:95:A4:77:B2:41:ED:37:42:35:A5:71";

void setup() {
  //To ctrl DC FAN motor
  pinMode(D1,OUTPUT);
  digitalWrite(D1,LOW);

  //Begin Serial monitor (COM port)
  Serial.begin(115200);
  timeClient.begin();//Begin fetching timestamp

  WiFi.mode(WIFI_AP_STA);
  WiFi.hostname("Jabilli");
  WiFi.setSleepMode(WIFI_LIGHT_SLEEP);

  //Connect to router for internet
  WiFi.begin("CHETAN SAI","XXXXXX");

  //Setup Local Area Network (LAN)
  Serial.println();
  Serial.print("Setting up Soft-AP... ");
  if (WiFi.softAP("Jabilli", "987654321",1,false)) {
    Serial.println("Access Point Established.");
  } else {
    Serial.println("AP initialization Failed!");
  }

  //Check WiFi conn status
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
 
  //Start mDNS responder to softAPIP
  if (MDNS.begin("jabilli")) {
    Serial.println("mDNS responder started");
    Serial.println("Access your device at http://jabilli.local");
    Serial.print("NodeMCU IP Address: ");
    Serial.println(WiFi.softAPIP());
  } else {
    Serial.println("Error with Access Point mDNS responder!");
  }

  MDNS.addService("http", "tcp", 80);
    server.on("/", HTTP_GET, []() {
      server.send(200, "text/html", "Sending GET request...");
      //sendPostReq();
  });

    // Start the server
  server.begin();
  Serial.println("HTTP server started");
}

void IRAM_ATTR sendPostReq(String serverName) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    WiFiClientSecure client;

    client.setTimeout(15000);
    client.setFingerprint(fingerprint); //Veify encryption
    //client.setInsecure(); 
    // Specify the server and path for the POST request
    String host = serverName.substring(serverName.indexOf("://") + 3); // Remove "http://" or "https://"
    host = host.substring(0, host.indexOf('/'));

    //Timestamp
    unsigned long epochTime = timeClient.getEpochTime();


    String postData = "chipID=" + String(ESP.getChipId()) + 
                      "&coreVer=" + ESP.getCoreVersion() + 
                      "&flashID=" + String(ESP.getFlashChipId()) +
                      "&macAddr=" + WiFi.macAddress() +
                      "&temp=" + temp +
                      "&ts=" + String(timeClient.getFormattedTime());

    // Begin the HTTP request
    http.begin(client,serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    if (WiFi.hostByName(host.c_str(), remote_ip)) {
    Serial.print("Fetching URL from: ");
    Serial.println(remote_ip);
  } else {
    Serial.println("DNS resolution failed");
  }


    // Send the HTTP POST request
    int httpCode = http.POST(postData);  // Send GET request

    // Check the HTTP response code
    if (httpCode > 0) {
      // If HTTP response is positive, print the result
      String payload = http.getString();  // Get the response payload
      Serial.println("GET Request successful!");
      Serial.println("Response: ");
      Serial.println(payload);  // Print the response body
      if (payload.equals("1")) {
        Serial.println("Turning on Fan....");
        // You can add your custom code here to handle when payload is "1"
        digitalWrite(D1,HIGH);
      } else {
        Serial.println("Turning off Fan...");
        digitalWrite(D1,LOW);
      }
    } else {
      // If the request fails
      Serial.println("POST request failed!");
      Serial.println("Error code: " + String(httpCode));
    }

    // End the HTTP connection
    http.end();
  } else {
    Serial.println("WiFi not connected");
  }
}

void loop() {
  server.handleClient();
  MDNS.update();
  timeClient.update();

  sendPostReq("https://log.suchana.infy.uk/fan.txt?i=1"); //Periodic POST request

  int numDevices = WiFi.softAPgetStationNum();
  //Serial.print("Number of devices connected: ");
  //Serial.println(numDevices);
}

错误信息

Post Request Failed!
Error code: -1

预期效果

成功向API端点发送POST请求,端点将数据记录到数据库并返回1或0,以此控制连接在GPIO5和GND上的直流电机。

问题解决过程

  • 已通过OpenSSL命令交叉验证SSL证书指纹有效,但问题仍存在
  • 最终定位问题根源:代码中使用了30字节的SHA256指纹,而WifiClientSecure仅支持20字节的SHA1指纹,对应库代码定义如下:
    // Only check SHA1 fingerprint of certificate
    bool setFingerprint(const uint8_t fingerprint[20]) {
      return _ctx->setFingerprint(fingerprint);
    }
    
  • 可通过以下OpenSSL命令获取目标服务器证书的SHA1指纹(需移除结果中的冒号):
    openssl s_client -connect your-server.com:443 -showcerts | openssl x509 -sha1 -fingerprint -noout
    
  • 将代码中的指纹替换为SHA1格式后,POST请求成功发送,问题解决。感谢Arduino论坛社区的帮助。

内容的提问来源于stack exchange,提问作者HEMANTH ABHIRAM SOMARAJU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:34:55