1
$\begingroup$

I'm hoping to get some help regarding an old problem that has eluded me. I'm trying to figure out how the VB6 PRNG was used to generate a byte output from the two byte seed that the Randomize() function provided it. I'm trying to replicate the code in C and seed it with my own 2 bytes, something like 0x12FF.

I'm looking to create an 8 byte output, derived from 8x one byte outputs (as opposed to one 8-byte output) from the PRNG with a specific seed. The output would preferably be hexadecimal, as an example: FF1A2B3C4D5E6F1A

I understand that the VB6 PRNG has a massive flaw, my experiment is designed to demonstrate the flaw and replicate it to illustrate why a PRNG such as that should not be used in cryptography as it has repeatable outputs.

The only documentation I can seem to find is how to generate an integer output, which isn't useful to me unless the integer output was somehow used to generate a byte output. I'm not familiar with the outputs and would appreciate any help I can get.

The integer output example I have (taken from a Microsoft KB article, edited to include stdio.h) is below:

#include <math.h>

int main(int argc, char* argv[])
{
unsigned long       rndVal;

rndVal = 0x50000L;
int i;
float rndFloat;

for (i=0;i<8;i++)
    {
    rndVal = (rndVal * 0x43fd43fdL + 0xc39ec3L) & 0xffffffL;
    rndFloat = (float)rndVal / (float)16777216.0;
    printf("Value is %.15f\n",rndFloat);
    }
return 0;
}

And my version of the above is:

#include <stdio.h>
#include <math.h>

int main(int argc, char* argv[])
{
    int rndOut, irnd, i;
    
    const int inc = 0x01;
    
    float rndFloat;
    
    unsigned int rndVal = 0x0000;
    
    for (irnd = 0; irnd < 65536; irnd ++)
        {
        for (i=0;i<8;i++)
            {
            rndVal = (rndVal * 0x43fd43fdL + 0xc39ec3L) & 0xffffffL;
            rndFloat = (float)rndVal / (float)16777216.0;
            rndOut = (0xff * rndFloat) + 0x00;
            printf("%02X",rndOut);
            }
        printf("\n");
        rndVal += inc;
        }
return 0;
}

However, without knowing the how the VB6 PRNG did the byte output, I am unable to get seemingly similar results. I have a list of around 500 outputs from the VB6 one that I can't get to seem to match.

Any help would be greatly appreciated.

$\endgroup$
1
  • $\begingroup$ rndOut = (0xff * rndFloat) + 0x00; does not generate uniformly distributed integers in [0, 255]: the 254 bytes in [1, 254] each have probablity 1/255 rather than 1/256 as intended; while 0 and 255 share the remaining 1/255 in a manner depending on rounding mode. The canonical method to generate a byte would be rndOut = rndVal>>16; (without declaring or computing rndFloat), because rndValis a 24-bit uniformly-distributed integer. As a minor aside, what rndVal += inc; attempts to achieve is unclear, but what it actually does is not seeding the RNG with incremental values. $\endgroup$
    – fgrieu
    Commented May 16, 2023 at 16:15

0