【问题标题】:C# Generate unique secure random strings graduallyC#逐渐生成唯一的安全随机字符串
【发布时间】:2018-11-26 23:59:26
【问题描述】:

我想随机生成唯一且安全的字符串,并且我想随着时间的推移去做。我想为我的使用选择尽可能短的长度(足够大,以至于随机尝试很有可能失败)。我也希望这个过程很快。使用下面的代码并测试它的唯一性,重复发生的时间比我预期的要早。不知道有没有问题。

P.S.:使用池来生成数字是否安全?

P.P.S:我不想在字母表中添加“-”和“_”。值得去掉吗?

string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
string Random(int length,string alphabet)
    {
        StringBuilder result = new StringBuilder();
        using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
        {
            for (int i = 0; i < length; i++)
            {
                byte[] buffer = new byte[sizeof(uint)];
                rng.GetBytes(buffer);
                uint num = BitConverter.ToUInt32(buffer, 0);
                result.Append(alphabet[(int)(num % (uint)alphabet.Length)]);
            }
        }

        return result.ToString();
    }

【问题讨论】:

  • 也许对您的代码运行拼写检查可能会有所帮助。看了一下,代码根本不会运行。
  • duplicates occur sooner than I expected. 你什么时候期待他们的?它们是什么时候发生的?
  • 这感觉像是一个 XY 问题 - meta.stackexchange.com/questions/66377/what-is-the-xy-problem为什么你想这样做?
  • “短”和“安全”是通常不能很好地结合在一起的两件事。任何足够短的东西也可以很容易地被暴力破解和/或预测。更重要的是,您不希望通过具有难以猜测的名称来确保事物的安全,您希望通过根本无法访问它们来确保它们的安全。如果您使用 16 个随机字节并将它们转换为 32 个字符的十六进制字符串并完成它,您将拥有 128 位的随机性。这当然足以防止碰撞。 Guid.NewGuid() 也是如此,尽管这在密码学上并不安全。

标签: c# random unique


【解决方案1】:

一般来说,在您的Alphabet 中,每个字符都有 6 位“信息”(有 64 个字符)。所以长度 = 10 的字符串有 60 位信息。对于 sqrt(2^60) 之后的birthday paradox,即 2^30,您应该有 0.5 的可能性(50%)发生碰撞。 2^30 相当大,但如果字符数较少,那么碰撞会更早发生。

请注意,可以在您的代码中进行可能的优化(预先分配 StringBuilder 的“正确”长度)并且存在错误:

public const string BaseAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

public static string Random(int length, string alphabet = BaseAlphabet)
{
    StringBuilder result = new StringBuilder(length);
    uint maxValue = (uint)((((ulong)uint.MaxValue) + 1) / (uint)alphabet.Length * (uint)alphabet.Length);

    using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
    {
        for (int i = 0; i < length; i++)
        {
            uint num;

            do
            {
                byte[] buffer = new byte[sizeof(uint)];
                rng.GetBytes(buffer);
                num = BitConverter.ToUInt32(buffer, 0);
            }
            while (num >= maxValue);

            result.Append(alphabet[(int)(num % (uint)alphabet.Length)]);
        }
    }

    return result.ToString();
}

在您编写的代码中,某些字符可能比其他字符更有可能出现。这是因为如果 (uint.MaxValue + 1)(由 rng 生成的可能数字的整个范围)不能被 alphabet.Length 完全整除,那么 alphabet 末尾的字符比开头的字符更不可能。

【讨论】:

    猜你喜欢
    • 2012-11-21
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 2012-11-09
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多