3

ユーザー パスワードの暗号化に VB6 Rnd() および Randomize() メソッドを使用するレガシー データベースへの C# フロントエンドを作成しています。暗号化機能は非常に単純化されており、実際にはそれほど安全ではありませんが、現在のすべてのパスワードが保存されているものです.

私ができるようにしたいのは、C# アプリケーションからレガシー ユーザーを認証することです。将来のすべてのユーザーがより安全なパスワードを持ち、C# で複製できるように、VB6 用の新しい暗号化 (またはできればハッシュ) コードを書くことができます。しかし、現在のユーザーが新しいフロントエンドを使用する前にパスワードをリセットする必要はありません。

そのアルゴリズムを C# で再実装して、従来の VB6 コードと同じ結果を生成する方法はありますか?

4

3 に答える 3

2

それは可能であるべきです。Randomize注意が必要なのは、Visual Basic のステートメントとRnd関数の呼び出しをエミュレートすることです。

必要な情報が含まれている可能性があるナレッジベースの記事を見つけました。

Visual Basic が RND 関数の疑似乱数を生成する方法

編集...

調査の結果、最近のバージョンの 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 を参照してください。)

于 2009-09-08T22:57:31.410 に答える
1

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);
        }
    }
}
于 2010-06-15T14:10:27.817 に答える
0

サンプル VB コード:

Randomize()
Dim x as Single = Rnd()

(大まかに) 同等の C# コード:

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

クラス コンストラクターはRandom、乱数ジェネレーターを現在の時刻で初期化します。これは、Randomize が行うことです。コンストラクターにシードを渡すこともできます。これは、シード パラメーターを指定して Randomize を呼び出すのと同じです。

于 2009-09-08T22:51:15.510 に答える