我正在为使用 VB6 Rnd() 和 Randomize() 方法进行用户密码加密的旧数据库编写 C# 前端。加密功能非常简单,实际上并不是那么安全,但它是所有当前密码的存储方式。
我想做的是从 C# 应用程序对旧用户进行身份验证。我可以为 VB6 编写新的加密(或最好是散列)代码,以便所有未来的用户都有一个更安全的密码,并且可以在 C# 中复制。但我不想要求当前用户在使用新前端之前重置密码。
有什么方法可以在 C# 中重新实现该算法,以便它产生与旧版 VB6 代码相同的结果?
我正在为使用 VB6 Rnd() 和 Randomize() 方法进行用户密码加密的旧数据库编写 C# 前端。加密功能非常简单,实际上并不是那么安全,但它是所有当前密码的存储方式。
我想做的是从 C# 应用程序对旧用户进行身份验证。我可以为 VB6 编写新的加密(或最好是散列)代码,以便所有未来的用户都有一个更安全的密码,并且可以在 C# 中复制。但我不想要求当前用户在使用新前端之前重置密码。
有什么方法可以在 C# 中重新实现该算法,以便它产生与旧版 VB6 代码相同的结果?
这应该是可能的。棘手的部分是模拟对 Visual BasicRandomize
语句和Rnd
函数的调用。
我刚刚找到一篇知识库文章,看起来它可能包含您需要的信息:
编辑...
Randomize
经过一番调查,最近版本的 Visual Basic 中的和实现似乎Rnd
使用与 VB6 完全相同的算法。
所以,好消息是您不需要自己弄清楚并重新实现 VB6 算法。只需导入Microsoft.VisualBasic
命名空间,您就可以从 C# 调用内置方法:
using Microsoft.VisualBasic;
// ...
float x = VBMath.Rnd(-1);
VBMath.Randomize(password.Length);
float y = VBMath.Rnd();
// etc
(如果您仍然对实际使用的算法感到好奇,您可以随时查看 Reflector!)
您可以从 VB6 和 C# 生成相同的序列。只需注意我们的舍入错误(C# 的结果更精确)。确保VBMath.Rnd(-1)
在将新种子传递给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);
}
}
}
示例 VB 代码:
Randomize()
Dim x as Single = Rnd()
(大致)等效的 C# 代码:
Random r = new Random();
double x = r.NextDouble();
类Random
构造函数用当前时间初始化随机数生成器,这就是 Randomize 所做的。也可以给构造函数传递一个seed,相当于调用带有seed参数的Randomize