@@ -1159,60 +1159,62 @@ String computeSHA1(const String& input) {
11591159}
11601160
11611161#ifdef ESP32
1162- static String dump_raw_block (esp_efuse_block_t block)
1163- {
1164- const int WORDS = 8 ; // ESP32: 8×32-bit words per block i.e. 256bits
1165- uint32_t buf[WORDS] = {0 };
1166-
1167- const esp_efuse_desc_t d = {
1168- .efuse_block = block,
1169- .bit_start = 0 ,
1170- .bit_count = WORDS * 32
1171- };
1172- const esp_efuse_desc_t * field[2 ] = { &d, NULL };
1173-
1174- esp_err_t err = esp_efuse_read_field_blob (field, buf, WORDS * 32 );
1175- if (err != ESP_OK) {
1176- return " " ;
1162+ #include " esp_adc_cal.h"
1163+ String generateDeviceFingerprint () {
1164+ uint32_t fp[2 ] = {0 , 0 }; // create 64 bit fingerprint
1165+ esp_chip_info_t chip_info;
1166+ esp_chip_info (&chip_info);
1167+ esp_efuse_mac_get_default ((uint8_t *)fp);
1168+ fp[1 ] ^= ESP.getFlashChipSize ();
1169+ fp[0 ] ^= chip_info.full_revision | (chip_info.model << 16 );
1170+ // mix in ADC calibration data:
1171+ esp_adc_cal_characteristics_t ch;
1172+ #if SOC_ADC_MAX_BITWIDTH == 13 // S2 has 13 bit ADC
1173+ #define BIT_WIDTH ADC_WIDTH_BIT_13
1174+ #else
1175+ #define BIT_WIDTH ADC_WIDTH_BIT_12
1176+ #endif
1177+ esp_adc_cal_characterize (ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100 , &ch);
1178+ fp[0 ] ^= ch.coeff_a ;
1179+ fp[1 ] ^= ch.coeff_b ;
1180+ if (ch.low_curve ) {
1181+ for (int i = 0 ; i < 8 ; i++) {
1182+ fp[0 ] ^= ch.low_curve [i];
1183+ }
11771184 }
1178-
1179- String result = " " ;
1180- for (const unsigned int i : buf) {
1181- char line[32 ];
1182- sprintf (line, " 0x%08X" , i);
1183- result += line;
1185+ if (ch.high_curve ) {
1186+ for (int i = 0 ; i < 8 ; i++) {
1187+ fp[1 ] ^= ch.high_curve [i];
1188+ }
11841189 }
1185- return result;
1190+ char fp_string[17 ]; // 16 hex chars + null terminator
1191+ sprintf (fp_string, " %08X%08X" , fp[1 ], fp[0 ]);
1192+ return String (fp_string);
1193+ }
1194+ #else // ESP8266
1195+ String generateDeviceFingerprint () {
1196+ uint32_t fp[2 ] = {0 , 0 }; // create 64 bit fingerprint
1197+ WiFi.macAddress ((uint8_t *)&fp); // use MAC address as fingerprint base
1198+ fp[0 ] ^= ESP.getFlashChipId ();
1199+ fp[1 ] ^= ESP.getFlashChipSize () | ESP.getFlashChipVendorId () << 16 ;
1200+ char fp_string[17 ]; // 16 hex chars + null terminator
1201+ sprintf (fp_string, " %08X%08X" , fp[1 ], fp[0 ]);
1202+ return String (fp_string);
11861203}
11871204#endif
11881205
1189-
1190- // Generate a device ID based on SHA1 hash of MAC address salted with "WLED"
1206+ // Generate a device ID based on SHA1 hash of MAC address salted with other unique device info
11911207// Returns: original SHA1 + last 2 chars of double-hashed SHA1 (42 chars total)
11921208String getDeviceId () {
11931209 static String cachedDeviceId = " " ;
11941210 if (cachedDeviceId.length () > 0 ) return cachedDeviceId;
1195-
1196- uint8_t mac[6 ];
1197- WiFi.macAddress (mac);
1198- char macStr[18 ];
1199- sprintf (macStr, " %02x:%02x:%02x:%02x:%02x:%02x" , mac[0 ], mac[1 ], mac[2 ], mac[3 ], mac[4 ], mac[5 ]);
1200-
12011211 // The device string is deterministic as it needs to be consistent for the same device, even after a full flash erase
12021212 // MAC is salted with other consistent device info to avoid rainbow table attacks.
12031213 // If the MAC address is known by malicious actors, they could precompute SHA1 hashes to impersonate devices,
12041214 // but as WLED developers are just looking at statistics and not authenticating devices, this is acceptable.
12051215 // If the usage data was exfiltrated, you could not easily determine the MAC from the device ID without brute forcing SHA1
1206- #ifdef ESP8266
1207- String deviceString = String (macStr) + " WLED" + ESP.getFlashChipId ();
1208- #else
1209- String deviceString = String (macStr) + " WLED" + ESP.getChipModel () + ESP.getChipRevision ();
1210- deviceString += dump_raw_block (EFUSE_BLK0);
1211- deviceString += dump_raw_block (EFUSE_BLK1);
1212- deviceString += dump_raw_block (EFUSE_BLK2);
1213- deviceString += dump_raw_block (EFUSE_BLK3);
1214- #endif
1215- String firstHash = computeSHA1 (deviceString);
1216+
1217+ String firstHash = computeSHA1 (generateDeviceFingerprint ());
12161218
12171219 // Second hash: SHA1 of the first hash
12181220 String secondHash = computeSHA1 (firstHash);
0 commit comments