|
@@ -29,10 +29,22 @@ static uint32_t generate_rng_from_ir(InfraredWorkerSignal* signal) {
|
|
|
size_t timings_cnt;
|
|
size_t timings_cnt;
|
|
|
infrared_worker_get_raw_signal(signal, &timings, &timings_cnt);
|
|
infrared_worker_get_raw_signal(signal, &timings, &timings_cnt);
|
|
|
|
|
|
|
|
- uint32_t seed = 0;
|
|
|
|
|
|
|
+ uint32_t seed = furi_hal_random_get(); // Start with hardware RNG
|
|
|
|
|
+ uint32_t cpu_ticks = DWT->CYCCNT; // CPU cycle counter
|
|
|
|
|
+
|
|
|
|
|
+ seed ^= seed >> 16;
|
|
|
|
|
+ seed *= 0x7feb352d;
|
|
|
|
|
+ seed ^= seed >> 15;
|
|
|
|
|
+ seed *= 0x846ca68b;
|
|
|
|
|
+ seed ^= seed >> 16;
|
|
|
|
|
+
|
|
|
|
|
+ // More thorough mixing of entropy sources
|
|
|
for(size_t i = 0; i < timings_cnt; i++) {
|
|
for(size_t i = 0; i < timings_cnt; i++) {
|
|
|
- seed ^= timings[i] ^ (seed << 5) ^ (seed >> 3); // mix bits
|
|
|
|
|
|
|
+ seed = (seed << 7) ^ (seed >> 25) ^ timings[i];
|
|
|
|
|
+ seed += cpu_ticks ^ (i * 0x9E3779B9);
|
|
|
|
|
+ cpu_ticks = DWT->CYCCNT; // Refresh CPU ticks
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return seed;
|
|
return seed;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -47,27 +59,27 @@ static void ir_callback(void* ctx, InfraredWorkerSignal* signal) {
|
|
|
|
|
|
|
|
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
|
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
|
|
|
|
|
|
|
- // Better entropy mixing pipeline
|
|
|
|
|
- uint32_t rng_number = furi_hal_random_get();
|
|
|
|
|
-
|
|
|
|
|
- // 1. Combine with seed using non-linear operation
|
|
|
|
|
- rng_number += (seed * 0x9E3779B9); // Golden ratio constant for mixing
|
|
|
|
|
-
|
|
|
|
|
- // 2. Improved bit diffusion (xorshift variant)
|
|
|
|
|
|
|
+ // Combine multiple entropy sources
|
|
|
|
|
+ uint32_t rng_number = seed ^ furi_hal_random_get();
|
|
|
|
|
+ rng_number ^= (uint32_t)furi_get_tick(); // System ticks
|
|
|
|
|
+
|
|
|
|
|
+ // Improved mixing function (based on xxHash)
|
|
|
rng_number ^= rng_number >> 15;
|
|
rng_number ^= rng_number >> 15;
|
|
|
rng_number *= 0x85EBCA77;
|
|
rng_number *= 0x85EBCA77;
|
|
|
rng_number ^= rng_number >> 13;
|
|
rng_number ^= rng_number >> 13;
|
|
|
rng_number *= 0xC2B2AE3D;
|
|
rng_number *= 0xC2B2AE3D;
|
|
|
rng_number ^= rng_number >> 16;
|
|
rng_number ^= rng_number >> 16;
|
|
|
-
|
|
|
|
|
- // 3. Safer range reduction (better than simple modulo)
|
|
|
|
|
- state->rng_value = (uint32_t)((rng_number & 0xFFFFFFFF) * 1000000ULL) % 1000000;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Better range reduction without bias
|
|
|
|
|
+ uint64_t scaled = (uint64_t)rng_number * 1000000ULL;
|
|
|
|
|
+ state->rng_value = (scaled >> 32); // Take high bits
|
|
|
|
|
+
|
|
|
state->seed = seed;
|
|
state->seed = seed;
|
|
|
update_history(state, state->rng_value);
|
|
update_history(state, state->rng_value);
|
|
|
state->new_value = true;
|
|
state->new_value = true;
|
|
|
state->message_timestamp = furi_get_tick();
|
|
state->message_timestamp = furi_get_tick();
|
|
|
|
|
+
|
|
|
furi_mutex_release(state->mutex);
|
|
furi_mutex_release(state->mutex);
|
|
|
-
|
|
|
|
|
FURI_LOG_I(TAG, "Generated RNG: %lu (seed: %lu)", state->rng_value, state->seed);
|
|
FURI_LOG_I(TAG, "Generated RNG: %lu (seed: %lu)", state->rng_value, state->seed);
|
|
|
}
|
|
}
|
|
|
|
|
|