1919#include " ArduinoOTA.h"
2020#include " NetworkClient.h"
2121#include " ESPmDNS.h"
22- #include " MD5Builder .h"
22+ #include " SHA3Builder .h"
2323#include " Update.h"
2424
2525// #define OTA_DEBUG Serial
@@ -72,12 +72,12 @@ String ArduinoOTAClass::getHostname() {
7272
7373ArduinoOTAClass &ArduinoOTAClass::setPassword (const char *password) {
7474 if (_state == OTA_IDLE && password) {
75- MD5Builder passmd5 ;
76- passmd5 .begin ();
77- passmd5 .add (password);
78- passmd5 .calculate ();
75+ SHA3Builder passsha3 ;
76+ passsha3 .begin ();
77+ passsha3 .add (password);
78+ passsha3 .calculate ();
7979 _password.clear ();
80- _password = passmd5 .toString ();
80+ _password = passsha3 .toString ();
8181 }
8282 return *this ;
8383}
@@ -188,17 +188,17 @@ void ArduinoOTAClass::_onRx() {
188188 _udp_ota.read ();
189189 _md5 = readStringUntil (' \n ' );
190190 _md5.trim ();
191- if (_md5.length () != 32 ) {
191+ if (_md5.length () != 32 ) { // MD5 produces 32 character hex string for firmware integrity
192192 log_e (" bad md5 length" );
193193 return ;
194194 }
195195
196196 if (_password.length ()) {
197- MD5Builder nonce_md5 ;
198- nonce_md5 .begin ();
199- nonce_md5 .add (String (micros ()));
200- nonce_md5 .calculate ();
201- _nonce = nonce_md5 .toString ();
197+ SHA3Builder nonce_sha3 ;
198+ nonce_sha3 .begin ();
199+ nonce_sha3 .add (String (micros ()));
200+ nonce_sha3 .calculate ();
201+ _nonce = nonce_sha3 .toString ();
202202
203203 _udp_ota.beginPacket (_udp_ota.remoteIP (), _udp_ota.remotePort ());
204204 _udp_ota.printf (" AUTH %s" , _nonce.c_str ());
@@ -222,18 +222,26 @@ void ArduinoOTAClass::_onRx() {
222222 _udp_ota.read ();
223223 String cnonce = readStringUntil (' ' );
224224 String response = readStringUntil (' \n ' );
225- if (cnonce.length () != 32 || response.length () != 32 ) {
225+ if (cnonce.length () != 64 || response.length () != 64 ) { // SHA3-256 produces 64 character hex string
226226 log_e (" auth param fail" );
227227 _state = OTA_IDLE;
228228 return ;
229229 }
230230
231231 String challenge = _password + " :" + String (_nonce) + " :" + cnonce;
232- MD5Builder _challengemd5;
233- _challengemd5.begin ();
234- _challengemd5.add (challenge);
235- _challengemd5.calculate ();
236- String result = _challengemd5.toString ();
232+ SHA3Builder _challengesha3;
233+ _challengesha3.begin ();
234+ _challengesha3.add (challenge);
235+ _challengesha3.calculate ();
236+ String result = _challengesha3.toString ();
237+
238+ // Debug logging
239+ log_d (" Challenge: %s" , challenge.c_str ());
240+ log_d (" Expected: %s" , result.c_str ());
241+ log_d (" Received: %s" , response.c_str ());
242+ log_d (" Password hash: %s" , _password.c_str ());
243+ log_d (" Nonce: %s" , _nonce.c_str ());
244+ log_d (" CNonce: %s" , cnonce.c_str ());
237245
238246 if (result.equals (response)) {
239247 _udp_ota.beginPacket (_udp_ota.remoteIP (), _udp_ota.remotePort ());
@@ -266,7 +274,7 @@ void ArduinoOTAClass::_runUpdate() {
266274 _state = OTA_IDLE;
267275 return ;
268276 }
269- Update.setMD5 (_md5.c_str ());
277+ Update.setMD5 (_md5.c_str ()); // Note: Update library still uses MD5 for firmware integrity, this is separate from authentication
270278
271279 if (_start_callback) {
272280 _start_callback ();
0 commit comments