Skip to content

Commit dc5732a

Browse files
authored
Merge pull request #5111 from DedeHai/safe_UID_generation
Safe uid generation
2 parents a9811c2 + ce6577e commit dc5732a

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
@@ -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)
11921208
String 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

Comments
 (0)