Skip to content

Commit 0ac6ca4

Browse files
netmindzsofthack007
authored andcommitted
Merge pull request wled#5111 from DedeHai/safe_UID_generation
Safe uid generation
1 parent 1b38235 commit 0ac6ca4

File tree

1 file changed

+42
-40
lines changed

1 file changed

+42
-40
lines changed

wled00/util.cpp

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -703,60 +703,62 @@ String computeSHA1(const String& input) {
703703
}
704704

705705
#ifdef ESP32
706-
static String dump_raw_block(esp_efuse_block_t block)
707-
{
708-
const int WORDS = 8; // ESP32: 8×32-bit words per block i.e. 256bits
709-
uint32_t buf[WORDS] = {0};
710-
711-
const esp_efuse_desc_t d = {
712-
.efuse_block = block,
713-
.bit_start = 0,
714-
.bit_count = WORDS * 32
715-
};
716-
const esp_efuse_desc_t* field[2] = { &d, NULL };
717-
718-
esp_err_t err = esp_efuse_read_field_blob(field, buf, WORDS * 32);
719-
if (err != ESP_OK) {
720-
return "";
706+
#include "esp_adc_cal.h"
707+
String generateDeviceFingerprint() {
708+
uint32_t fp[2] = {0, 0}; // create 64 bit fingerprint
709+
esp_chip_info_t chip_info;
710+
esp_chip_info(&chip_info);
711+
esp_efuse_mac_get_default((uint8_t*)fp);
712+
fp[1] ^= ESP.getFlashChipSize();
713+
fp[0] ^= chip_info.full_revision | (chip_info.model << 16);
714+
// mix in ADC calibration data:
715+
esp_adc_cal_characteristics_t ch;
716+
#if SOC_ADC_MAX_BITWIDTH == 13 // S2 has 13 bit ADC
717+
#define BIT_WIDTH ADC_WIDTH_BIT_13
718+
#else
719+
#define BIT_WIDTH ADC_WIDTH_BIT_12
720+
#endif
721+
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch);
722+
fp[0] ^= ch.coeff_a;
723+
fp[1] ^= ch.coeff_b;
724+
if (ch.low_curve) {
725+
for (int i = 0; i < 8; i++) {
726+
fp[0] ^= ch.low_curve[i];
727+
}
721728
}
722-
723-
String result = "";
724-
for (const unsigned int i : buf) {
725-
char line[32];
726-
sprintf(line, "0x%08X", i);
727-
result += line;
729+
if (ch.high_curve) {
730+
for (int i = 0; i < 8; i++) {
731+
fp[1] ^= ch.high_curve[i];
732+
}
728733
}
729-
return result;
734+
char fp_string[17]; // 16 hex chars + null terminator
735+
sprintf(fp_string, "%08X%08X", fp[1], fp[0]);
736+
return String(fp_string);
737+
}
738+
#else // ESP8266
739+
String generateDeviceFingerprint() {
740+
uint32_t fp[2] = {0, 0}; // create 64 bit fingerprint
741+
WiFi.macAddress((uint8_t*)&fp); // use MAC address as fingerprint base
742+
fp[0] ^= ESP.getFlashChipId();
743+
fp[1] ^= ESP.getFlashChipSize() | ESP.getFlashChipVendorId() << 16;
744+
char fp_string[17]; // 16 hex chars + null terminator
745+
sprintf(fp_string, "%08X%08X", fp[1], fp[0]);
746+
return String(fp_string);
730747
}
731748
#endif
732749

733-
734-
// Generate a device ID based on SHA1 hash of MAC address salted with "WLED"
750+
// Generate a device ID based on SHA1 hash of MAC address salted with other unique device info
735751
// Returns: original SHA1 + last 2 chars of double-hashed SHA1 (42 chars total)
736752
String getDeviceId() {
737753
static String cachedDeviceId = "";
738754
if (cachedDeviceId.length() > 0) return cachedDeviceId;
739-
740-
uint8_t mac[6];
741-
WiFi.macAddress(mac);
742-
char macStr[18];
743-
sprintf(macStr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
744-
745755
// The device string is deterministic as it needs to be consistent for the same device, even after a full flash erase
746756
// MAC is salted with other consistent device info to avoid rainbow table attacks.
747757
// If the MAC address is known by malicious actors, they could precompute SHA1 hashes to impersonate devices,
748758
// but as WLED developers are just looking at statistics and not authenticating devices, this is acceptable.
749759
// If the usage data was exfiltrated, you could not easily determine the MAC from the device ID without brute forcing SHA1
750-
#ifdef ESP8266
751-
String deviceString = String(macStr) + "WLED" + ESP.getFlashChipId();
752-
#else
753-
String deviceString = String(macStr) + "WLED" + ESP.getChipModel() + ESP.getChipRevision();
754-
deviceString += dump_raw_block(EFUSE_BLK0);
755-
deviceString += dump_raw_block(EFUSE_BLK1);
756-
deviceString += dump_raw_block(EFUSE_BLK2);
757-
deviceString += dump_raw_block(EFUSE_BLK3);
758-
#endif
759-
String firstHash = computeSHA1(deviceString);
760+
761+
String firstHash = computeSHA1(generateDeviceFingerprint());
760762

761763
// Second hash: SHA1 of the first hash
762764
String secondHash = computeSHA1(firstHash);

0 commit comments

Comments
 (0)