arduino-LoRa icon indicating copy to clipboard operation
arduino-LoRa copied to clipboard

Better random number generation from RSSI

Open unprovable opened this issue 6 years ago • 6 comments

Hello, The API call LoRa.random() gave users really bad random numbers. They need some level of whitening in order to be useful, so I've added some rather dirty (sorry!) code to implement a von Neumann Extractor. It's normally implemented in three functions, but I didn't want to bloat the class - feel free to edit it to make it more stylistic if you like :) See here for more information: https://en.wikipedia.org/wiki/Randomness_extractor#Von_Neumann_extractor

I tested the code that was originally there, and the random numbers were disappointing - I can send samples if you would like. This code will generate better random numbers. I also added a warning that these are not cryptographically secure, as I haven't proven that they are otherwise yet. :P

The speed is slightly slower, but very fast in the grander scheme of things (other entropy pools take a long time to generate entropy). I'm happy to answer any questions.

Many thanks! M.

unprovable avatar May 28 '18 13:05 unprovable

FYI, here is Semtech implementation on SX1276 driver (no Von Neumann Extractor, but maybe the 1ms delay between samples is useful):

uint32_t SX1276Random( void )
{
    uint8_t i;
    uint32_t rnd = 0;

    /*
     * Radio setup for random number generation
     */
    // Set LoRa modem ON
    SX1276SetModem( MODEM_LORA );

    // Disable LoRa modem interrupts
    SX1276Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
                  RFLR_IRQFLAGS_RXDONE |
                  RFLR_IRQFLAGS_PAYLOADCRCERROR |
                  RFLR_IRQFLAGS_VALIDHEADER |
                  RFLR_IRQFLAGS_TXDONE |
                  RFLR_IRQFLAGS_CADDONE |
                  RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
                  RFLR_IRQFLAGS_CADDETECTED );

    // Set radio in continuous reception
    SX1276SetOpMode( RF_OPMODE_RECEIVER );

    for( i = 0; i < 32; i++ )
    {
        DelayMs( 1 );
        // Unfiltered RSSI value reading. Only takes the LSB value
        rnd |= ( ( uint32_t )SX1276Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) << i;
    }

    SX1276SetSleep( );

    return rnd;
}

sergio303 avatar May 28 '18 23:05 sergio303

Aye - the extractor just helps to normalise the probabilities (P(0)=P(1)=0.5 under this scheme of output). It's not critical, but it's recommended to do some sort of whitening of this kind. :) Many thanks! M.

unprovable avatar May 29 '18 07:05 unprovable

In testing this PR it just hangs for me. Presumably a != read... is never evaluating true

morganrallen avatar Jul 30 '18 18:07 morganrallen

Any updates on the hanging?

sandeepmistry avatar Aug 19 '18 13:08 sandeepmistry

I'm messing with random this weekend and I found https://gist.github.com/endolith/2568571 I have tested some codes and get great results using left rotate and XOR. Check https://github.com/sandeepmistry/arduino-LoRa/pull/188

ricaun avatar Oct 03 '18 18:10 ricaun

There is another PR #395 where is added the seed necessary to have better random numbers

wero1414 avatar Sep 07 '20 15:09 wero1414