-
Notifications
You must be signed in to change notification settings - Fork 13.3k
HttpClient: HTTPS request without specifying certificate fingerprint? #3417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Not the best solution, but could you proxy the requests through a service/server you control? I suppose you'd have the same issue once your service/server's certificate expires though... |
This issue relates to #1851 ... Maybe I add a php-script inbetween to decouple https-request from esp8266, but this is more a workaround than a real solution. |
Found this: Have to check if this is a valid solution for my use-case. |
Currently I'm testing the solution provided in #1851, but I would like to see, that I can make https-calls, without specifying a certificate-finger-print and without providing the root-ca-certificate to do certificate validation. Just "accept all certificates and ignore the complete certificate-check", like you can do on any other desktop-programming-language ... Is this in general possible? Or is this technically on the esp8266 not possible? |
you might be able to do it if you set the methods that check the cert to return as if they matched at all times, from a brief look you need to:
I would suggest that to do what you want you'll want to move the returns closer to the start of each function, but after checking that you have an ssl context, so i'd suggest just adding return true before each of these lines:
can always give this a try. |
Sounds like copy&paste&modify of Wificlientsecure.cpp/.h to create a quick'n'easy workaround... Did someone test this already? |
I just had the same problem. Just ignore the result of the client.verify() method, or just dont run it at all. It's up to you what to do if the certificate verification fails. |
Finally, I have some feedback: When I use this sample as a starting point: https://github.com./esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino and just ignore lines 52-56: if (client.verify(fingerprint, host)) {
Serial.println("certificate matches");
} else {
Serial.println("certificate doesn't match");
} then https communication is working in principle. My Code: void sendMessageHTTPS(String msg) {
// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;
Serial.print("connecting to : '");
Serial.print(host);
Serial.println("'");
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
// if (client.verify(fingerprint, host)) {
// Serial.println("certificate matches");
// } else {
// Serial.println("certificate doesn't match");
// }
Serial.print("requesting URL: '");
Serial.print(url);
Serial.println("'");
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n" +
"Accept: */*\r\n" +
"User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n" +
"Content-Type: application/json;charset=utf-8\r\n" +
"Authorization: Bearer "+cloudDeviceToken+"\r\n" +
"Content-Length: "+msg.length()+"\r\n" +
"\r\n" +
msg + "\r\n");
Serial.println("request sent");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
} but I face some ESP crashes after a few https requests. Still need to investigate what goes wrong. |
decoded stacktrace:
Hmm ... |
@igrr |
Initially, the request was sent every 5 sec. It fails every 5-8 times, then I get stacktrace, device restarts. I changed interval from 5sec to 60sec. This did not change anything. Crashed after 5 requests. Beside the https-request, the device is serving a small webpage (which has not been accessed during my tests), queries NTP time and reads power-measurement data from HLW8012 chip via interrupt. Would be great if someone can shed some light on this issue. |
switches from 2.4.0-rc1 to rc2... looks better now. already running with >20requests without any crash. |
Any chance to get this working with HTTPClient? My responses could become lager and I don't want to deal with chunked responses manually... |
a noob question: this fingerprint changes over time? I know you are trying not to use them, but I have a valid one and I was thinking to hardcode it on my device. |
@odelot That's a good question. Yes, fingerprints do change over time. They'll change any time the web server's SSL certificate changes. So if a web server's SSL certificate expires on March 21, 2018 then it'll need a new certificate then and the new certificate will have a new fingerprint. The server's certificate might easily change before the expiration date, too. It's even possible for a web server which is load balanced by multiple servers to use different certificates on different servers, so you might see different fingerprints for the same HTTPS endpoint. That's not a likely scenario - it's probably the result of an odd or mis-configuration - but it's possible. Using the fingerprint to verify the server isn't ideal, but the alternative is maintaining a list of certificates for the root certificate authorities - this is what more capable computers do. Unfortunately these need to be updated too, and their size well exceeds the storage available on an ESP8266. Unfortunately I don't have a good alternative to hardcoding the fingerprint on your device. |
@odelot @romkey To get a root certificate you can view it in a browser (click the green padlock), view certificate, select the root certificate and export it as a .der file. I wrote a little python script to format .der files as a hex string you can past straight into the CACert.ino file. |
@tuxedo0801 , I have a nearly identical error (stacktrace) - what do you mean by 2.4.0-rc2? My NodeMCU v1.0 crashes at the first attempt.
|
Apologies - after fiddeling with the variables I found I needed to add the 'https://' to the host adress in order for it to work. I was attempting a POST request a custom Google Cloud functions https endpoint. Somehow I could not find documentation on a Firebase/store request but not Cloud Functions. (e.g. .cloudfunctions.net). I did had a near similar error - so perhaps that might help? Cheers! |
Closing due to bearssl merge (axtls will be deprecated). |
https://github.com./esp8266/Arduino/tree/master/libraries/ESP8266WiFi/examples I can only find an example HTTPSRequest which still uses the fingerprint, am I looking in the wrong place? |
To use https and ignore fingerprint validation, that worked for me. Modified the verify function from the line 73 in ESP8266HTTPClient.cpp ,a different way. bool verify(WiFiClient& client, const char* host) override Then in sketch when to begin client, Use a fake fingerprint, e.g. all Zeroes. #include <ESP8266WiFi.h> void setup() { .... // this goes to: bool HTTPClient::begin(String url, String httpsFingerprint) or char array } |
You should not patch libraries but use their api (or propose patches/fixes): |
For I am not a programmer, Sorry for the anomalous way in recent. Then using HTTPClient wrapper in this way could send an insecure get request on port 443. `#include <ESP8266WiFi.h> const char *ssid = "my_ssid"; const char * host = "api.github.com."; void setup() { Serial.begin(115200); Serial.println("conntecting to network.."); BearSSL::WiFiClientSecure client; Serial.println("conntecting to server.."); } }` |
Here's a write-up that explains how to use HttpClient while checking against an actual certificate store (rather than specifying a certificate fingerprint): https://medium.com/@dfa_31434/doing-ssl-requests-on-esp8266-correctly-c1f60ad46f5e |
Thanks for this golden info :) |
yes it kinda works (I have only some problems with Let's Encrypt Wildcard Certs), but it runs 10x longer. In my case it was 20 seconds using BearSSL certificate store vs 2 seconds using direct fingerprint string. |
Note from mtnr: This message is about esp32 and not applicable here I found that simply by not setting the certificate you can get around the whole verify thing. This is because in the ssl_client library, which is used by WiFiClientSecure, if no certificate is provided it will default to not trying to verify it. See here ` // MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and
|
@technorainbows Are you working on esp32 ? |
Do you know if setInSecure with a valid certificate at the backend, not expired allow encryption of the connection line? I want toe accept several backends on several domains but i dont want to specifiy fingerprint or Cert Authority certificate with setCACert |
|
very useful |
Bonjour à tous, |
Hey, I'm facing the same problem. ChatGTP getting me confused too as it's saying that ESP8266HTTPClient will make https work without certificate configuration in the esp itself (as opposed to the WiFiClientSecure). Anyway, I am considering to make a view(for django) that will collect the certificate using python and send the current certificate to the esp. So everytime the esp will be turned on there will be a request to the webserver through HTTP, which will respond with the certificate and from there I can create an https connection. But yes, for the original case this wouldn't be possible as the server is not accessible through HTTP only. |
Hi there,
I have to push some data from ESP8266 to an IoT Cloud system. But this requires HTTPS.
In the examples I found, I always need to specify the fingerprint of the https-certficate.
This binds my source directly to the cloud system. If certificate changes, the request fails I guess...
So I have to update my sketch with every certificate-change, which is not that easy for my use-case.
Is there a possibility to accept whatever certificate is running behind https?
For my use-case it would be okay to use http instead of https, but the cloud system does only provide https. So I have to stick to it.
br,
Alex
The text was updated successfully, but these errors were encountered: