2

我有一个包含大量“颜色”的数组,我想更改这些颜色的顺序(随机),但使用密码:因此另一个用户只能使用正确的密码。如何在 Visual Basic .NET 或 C# 中做到这一点?我必须使用特定的加密引擎吗?

4

2 回答 2

4

这是使用密码打乱一组颜色的简单方法。

关键是将密码从字符串转换为数字。然后,您可以将该数字用作随机数生成器的种子。之后,您可以使用该随机数生成器来获得与颜色数组长度相同的排列您可以使用该排列来更改颜色的顺序并打乱数组。

解密时,如果给定相同的密码,则可以生成相同的排列并将数组解乱为原始形式。

这是该原理的一个示例,用 C# 编写:

int[] GetPermutation(int size, int seed)
{
    Random random = new Random(seed);
    int[] array = new int[size];
    for (int i = 0; i < size; i++)
        array[i] = i;
    for (int i = array.Length; i > 1; i--)
    {
        int j = random.Next(i);
        int tmp = array[j];
        array[j] = array[i - 1];
        array[i - 1] = tmp;
    }
    return array;
}

Color[] Encrypt(Color[] input, string password)
{
    int seed = password.GetHashCode();
    int[] perm = GetPermutation(input.Length, seed);
    Color[] encrypted = new Color[input.Length];
    for (int i = 0; i < input.Length; i++)
    {
        encrypted[perm[i]] = input[i];
    }
    return encrypted;
}

Color[] Decrypt(Color[] input, string password)
{
    int seed = password.GetHashCode();
    int[] perm = GetPermutation(input.Length, seed);
    Color[] decrypted = new Color[input.Length];
    for (int i = 0; i < input.Length; i++)
    {
        decrypted[i] = input[perm[i]];
    }
    return decrypted;
}

GetPermutation函数根据作为参数传递的种子生成排列。Encryptand函数实际上对Decrypt数组进行加扰和解扰。

这是一个使用示例:

Color[] array = new Color[5] { Color.Red, Color.Green, Color.Blue, Color.Yellow, Color.Black };
string password = "secret";
Color[] enc = Encrypt(array, password); // will always return Blue, Green, Black, Yellow, Red for the "secret" password
Color[] dec = Decrypt(enc, password); // will return the original array: Red, Green, Blue, Yellow, Black if given the "secret" password
Color[] dec2 = Decrypt(enc, "incorrectpwd"); // will return Green, Blue, Yellow, Black, Red, which is incorrect because the password was incorrect

笔记:

  • 为了简单起见,我使用了该.GetHashCode()方法。在 .NET 框架的未来版本中,此方法可能会为同一字符串生成不同的数字
  • 如果数组的长度很小,可以得到相同的加密顺序不同的密码,即使密码错误也能解密成功。例如:

    Color[] array = new Color[2] {Color.Red, Color.Green};
    Color[] enc = Encrypt(array, "one"); // will return Green, Red
    Color[] dec = Decrypt(enc, "one"); // will return Red, Green
    Color[] dec2 = Decrypt(enc, "two"); // will also return Red, Green, even though the password was incorrect
    
  • 如果您想使用颜色作为密码的替代品,您必须注意您会失去一些安全性,因为所有密码的空间都没有由字符、数字和符号组成的密码那么高。暴力破解这样的密码会容易得多。

于 2012-05-31T20:23:15.280 回答
3

我猜这可能有效:

  1. 让用户输入密码
  2. 散列密码(C++ 中的一些示例散列此处为 C++ 中的一些示例散列)并存储数字结果
  3. 使用以散列作为种子的洗牌算法。例如,请参见此处Random,只需使用哈希作为种子初始化对象。

同样,散列并不总是完美的(因为它可能会发生冲突),因此您可能需要找到适合您的问题的散列算法。

编辑:

以下是一些可能对您有所帮助的代码:

String input = "User inputted string here";
int hashSeed = input.GetHashCode();
Random rnd = new Random(hashSeed);
Color[] MyRandomColorArray = MyColorArray.OrderBy(x => rnd.Next()).ToArray();

注意: GetHashCode()会返回不同的值,无论它是在 32 位还是 64 位系统上。

于 2012-05-31T20:06:47.480 回答