Converting VB6 Randomize to C #

I'm writing a C # interface to a legacy database that uses VB6's Rnd () and Randomize () methods to encrypt a user's password. The encryption function is very simplistic and really not everything is secure, but this is what all current passwords are stored.

What I would like to do is authenticate legacy users from a C # application. I can write new encryption (or preferably hashing) code for VB6 so that all future users have a more secure password and can be duplicated in C #. But I don't want current users to have their password reset before they can use the new interface.

Is there any way to implement this algorithm in C # so that it gives identical results to legacy VB6 code?

+2


source to share


3 answers


You can generate the same sequence from VB6 and C #. Just watch our rounding errors (results are more accurate with C #). Be sure to call VBMath.Rnd(-1)

before transferring a new seed to VBMath.Randomize()

.



[TestFixture]
public class VbaRandomTests
{
    // Random numbers generated from a known seed from VB6
    [TestCase(1, new[] { 0.333575300f, 0.068163870f, 0.593829300f, 0.766039500f, 0.189289400f, 0.537398600f, 0.326994400f, 0.393937000f, 0.073419150f, 0.831542500f, 0.854963000f, 0.828829900f, 0.962344000f, 0.833957400f, 0.090149820f, 0.645974500f, 0.192794900f, 0.346950500f, 0.188133400f, 0.691135000f })]
    [TestCase(32, new[] { 0.579913200f, 0.579150200f, 0.310870300f, 0.864916400f, 0.142658500f, 0.927291200f, 0.407316600f, 0.402970200f, 0.296319500f, 0.412841300f, 0.361066500f, 0.560519300f, 0.017275630f, 0.919162500f, 0.084534590f, 0.912820200f, 0.642257800f, 0.248561900f, 0.733299400f, 0.305637000f })]
    [TestCase(327680, new[] { 0.882708600f, 0.733264000f, 0.661029000f, 0.376940400f, 0.919086800f, 0.660506500f, 0.020170630f, 0.126908200f, 0.437005600f, 0.053283210f, 0.252240800f, 0.449496400f, 0.662844500f, 0.044955970f, 0.519654200f, 0.169961300f, 0.183334400f, 0.687831900f, 0.227989400f, 0.384067200f })]
    public void generates_same_results_as_VB6(int seed, float[] values)
    {
        VBMath.Rnd(-1);
        VBMath.Randomize(seed);

        float[] results = new float[values.Length];
        for (int index = 0; index < results.Length; index++)
        {
            results[index] = VBMath.Rnd();
        }

        CollectionAssert.AreEqual(values, results, new FloatEpsilonComparer(0.0000001f));
    }

    private class FloatEpsilonComparer
        : IComparer<float>, IComparer
    {
        private readonly float _epsilon;

        public FloatEpsilonComparer(float epsilon)
        {
            _epsilon = epsilon;
        }

        public int Compare(float x, float y)
        {
            float difference = x - y;

            if (Math.Abs(difference) < _epsilon)
            {
                return 0;
            }
            if (x < y)
            {
                return -1;
            }
            return 1;
        }

        public int Compare(object x, object y)
        {
            float xF = Convert.ToSingle(x);
            float yF = Convert.ToSingle(y);
            return Compare(xF, yF);
        }
    }
}

      

+1


source


It should be possible. The tricky part will emulate the Visual Basic operator calls Randomize

and Rnd

.

I just found a knowledge base article that looks like it might have the information you need:

How Visual Basic generates pseudo-random numbers for the RND function

EDIT ...



After some research it was found that the implementation Randomize

and Rnd

in the latest versions of Visual Basic use the same algorithms as VB6.

So, the good news is that you don't have to define and reimplement VB6 algorithms yourself. Just import the namespace Microsoft.VisualBasic

and you can call the built-in methods from C #:

using Microsoft.VisualBasic;

// ...

float x = VBMath.Rnd(-1);
VBMath.Randomize(password.Length);
float y = VBMath.Rnd();
// etc

      

(And if you're still curious about the algorithms used, you can always take a look at Reflector!)

+2


source


Sample VB code:

Randomize()
Dim x as Single = Rnd()

      

(roughly) equivalent C # code:

Random r = new Random();
double x = r.NextDouble();

      

The class constructor Random

initializes the random number generator with the current time, which is what Randomize does. You can also pass the seed to the constructor, which is equivalent to calling Randomize with the seed parameter

0


source







All Articles