【问题标题】:C# Generating strings unique to the computerC# 生成计算机独有的字符串
【发布时间】:2018-11-24 18:50:50
【问题描述】:

我需要生成的字符串在生成它们的所有机器上具有极高概率是唯一的,并且每次运行代码时都不同。唯一性的概率不必是 100%,这与安全性无关,只有唯一性很重要(用例是播种大型状态非加密 PRNG)。

我目前的想法是对网络适配器信息进行 SHA512 哈希处理,包括适配器统计信息、计算机名称、进程 ID、计算机运行时间(以滴答为单位)和 UTC 当前时间(以滴答为单位),并将其转换为 64 个字符的 base 64 Unicode 字符串。

看起来不错,但有没有更好的方法,例如 .net 函数?

工作代码:

using System;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Text;

static class UniqueString
{
    private static SHA512 sha = SHA512.Create();

    public static string Gen()
    {
        NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
        StringBuilder uniqueString = new StringBuilder();

        foreach (NetworkInterface adapter in adapters)
        {
            IPInterfaceStatistics stats = adapter.GetIPStatistics();

            uniqueString.AppendFormat("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} {13} {14} {15} {16} {17} ",
                adapter.Description,
                adapter.Id,
                adapter.Name,
                adapter.Speed,
                adapter.GetPhysicalAddress(),
                adapter.NetworkInterfaceType,

                stats.BytesReceived,
                stats.BytesSent,
                stats.IncomingPacketsDiscarded,
                stats.IncomingPacketsWithErrors,
                stats.IncomingUnknownProtocolPackets,
                stats.NonUnicastPacketsReceived,
                stats.NonUnicastPacketsSent,
                stats.OutgoingPacketsDiscarded,
                stats.OutgoingPacketsWithErrors,
                stats.OutputQueueLength,
                stats.UnicastPacketsReceived,
                stats.UnicastPacketsSent);
        }

        uniqueString.AppendFormat("{0} {1} {2} {3}",
            Environment.MachineName,
            Process.GetCurrentProcess().Id,
            Environment.TickCount.ToString(),
            DateTime.UtcNow.Ticks);

        return Convert.ToBase64String(sha.ComputeHash(Encoding.Unicode.GetBytes(uniqueString.ToString())), 0, 48);
    }
}

【问题讨论】:

  • Guid.NewGuid()?
  • 想过这个问题,但是这台机器独有的概率是多少?
  • 极高。
  • 这里是关于 GUID 和冲突可能性的一个很好的答案 stackoverflow.com/a/2977648/6915929
  • 不要将 GUID 用于生成唯一标识符之外的任何事情。不能保证指南是随机性的良好来源。 如果您需要良好的随机性来源,请使用专门设计用于解决该问题的类,而不是使用 Guid 作为解决该问题的代理!

标签: c# uniqueidentifier


【解决方案1】:

我需要生成的字符串在生成它们的所有机器上具有极高概率是唯一的,并且每次运行代码时都不同。

让我从一个警告开始:

人们会立即告诉您使用 GUID,顾名思义,它是一个全球唯一标识符。 Type 4 的 guid 是随机生成的。

但是,我会反对使用 GUID 作为随机源。 GUID 保证唯一性,这就是它们被记录为保证的全部。实际上,是的,第四类 GUID 实际上是由非加密强度 PRNG 生成的随机 122 位数字。如果您使用 GUID 作为随机字符串,就可以了。但我个人不会在标签外使用 GUID。我使用它们生成唯一标识符,不多也不少。有更好的方法可以解决您的问题。

有关 GUID 的使用和滥用的更多信息,请参阅https://ericlippert.com/tag/guids/

看起来不错,但有没有更好的方法,例如 .net 函数?

执行此操作的正确方法是使用RNGCryptoServiceProvider 生成尽可能多的加密强度随机位,以确保您的标识符是唯一的,然后将其用作您的种子。

您的系统似乎是合理的,但是当为 Microsoft 工作的专家已经创建了一个系统,该系统可以为具有大量熵的加密强度随机数生成器提供种子时,您到底为什么要自己实施呢?不要在这里重新发明轮子。

【讨论】:

  • 只是想在这里表扬一下费力的答案,它不仅仅是回答问题,它解决了“我如何生成保证在整个.NET 中的宇宙”
  • @Eric Lippert - 我自己实现某些东西的原因是因为我不想依赖于可能耗尽的熵池。如果您不必使用它,请不要使用它,但也许这种担心是没有根据的。
  • @Thorham:RNGCryptoServiceProvider 的输出任何已知的统计测试都无法将其与真正随机的比特源区分开来。如果你认为你可以比从事 Windows 内部工作的加密专家更好地找到熵,那么你可以继续前进,但你在互联网上向陌生人提出这个问题的事实可能说明了这一点我说你并不比那些专家更擅长。使用他们的工作。它的质量很高。
  • @Eric Lippert - 我当然不是加密专家(远非如此),我的意图不是写具有加密级别强度的东西(用例根本不需要) .我刚刚阅读了有关其他系统上的可耗尽熵池的内容,并且由于我希望代码可用于 Mono 和 .Net,因此我认为自己编写它是一个好主意,这样它就不会依赖于任何系统特定的东西。
  • @Thorham:Mono 已经支持 RNGCryptoServiceProvider 十多年了。
猜你喜欢
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
相关资源
最近更新 更多