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
相关产品推荐
相关产品推荐

