将 VB6 随机化转换为 C#

发布于 2024-08-04 09:21:07 字数 360 浏览 10 评论 0 原文

我正在为旧数据库编写一个 C# 前端,该数据库使用 VB6 Rnd() 和 Randomize() 方法进行用户密码加密。 加密函数非常简单,实际上并不那么安全,但这就是所有当前密码都存储在其中。

我希望能够从 C# 应用程序对旧用户进行身份验证。我可以为 VB6 编写新的加密(或最好是散列)代码,以便所有未来的用户都拥有更安全的密码,并且可以在 C# 中复制。但我不想要求当前用户在使用新前端之前重置密码。

有什么方法可以在 C# 中重新实现该算法,以便它产生与旧版 VB6 代码相同的结果吗?

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

What I'd like to be able 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 that can be duplicated in C#. But I don't want to require current users to have had their password reset before they can use the new frontend.

Is there any way I can reimplement that algorithm in C# so that it produces identical results to the legacy VB6 code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

壹場煙雨 2024-08-11 09:21:07

这应该是可能的。棘手的部分是模拟对 Visual Basic 的 Randomize 语句和 Rnd 函数的调用。

我刚刚找到一篇知识库文章,看起来可能包含您需要的信息:

Visual Basic 如何为 RND 函数生成伪随机数

编辑...< /strong>

经过一番调查,最新版本的 Visual Basic 中的 RandomizeRnd 实现似乎使用与 VB6 完全相同的算法。

因此,好消息是您不需要自己弄清楚并重新实现 VB6 算法。只需导入 Microsoft.VisualBasic 命名空间,您就可以从 C# 调用内置方法:(

using Microsoft.VisualBasic;

// ...

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

如果您仍然对所使用的实际算法感到好奇,您可以随时在 Reflector 中查看!)

It should be possible. The tricky part will be emulating the calls to Visual Basic's Randomize statement and Rnd function.

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

How Visual Basic Generates Pseudo-Random Numbers for the RND Function

EDIT...

After some investigation, it appears that the Randomize and Rnd implementations in recent versions of Visual Basic use exactly the same algorithms as VB6.

So, the good news is that you don't need to figure out and re-implement the VB6 algorithms yourself. Just import the Microsoft.VisualBasic namespace 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 actual algorithms used, you can always take a look in Reflector!)

橪书 2024-08-11 09:21:07

您可以从 VB6 和 C# 生成相同的序列。只需注意我们的舍入误差(C# 的结果更精确)。确保在将新种子传递给 VBMath.Randomize() 之前调用 VBMath.Rnd(-1)

[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);
        }
    }
}

You can generate the same sequence from VB6 and C#. Just watch our for rounding errors (the results from C# are more precise). Make sure to call VBMath.Rnd(-1) before passing in 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);
        }
    }
}
向地狱狂奔 2024-08-11 09:21:07

示例 VB 代码:(

Randomize()
Dim x as Single = Rnd()

大致)相当于 C# 代码:

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

Random 类构造函数使用当前时间初始化随机数生成器,这就是 Randomize 的作用。您还可以将种子传递给构造函数,这相当于使用种子参数调用 Randomize

Sample VB code :

Randomize()
Dim x as Single = Rnd()

(roughly) equivalent C# code :

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文