不可预测的唯一标识符

时间:2011-10-11 21:09:31

标签: c#

对于我正在处理的应用程序,我需要生成一个必须具有以下属性的会话令牌:

  • 它应该是至少应用程序的唯一,全球唯一会更好
  • 应该是不可预测的
  • 它不应该太长,因为它必须在http请求标头中传递,所以越小越好

我正在考虑使用加密随机数来调整Guid结构,但这可能是一种过度杀伤力。有人知道/创建了一个适合所有这些属性的数据结构吗?

4 个答案:

答案 0 :(得分:28)

让我在这一点上非常清楚。 所有使用GUID的答案都是错误的,在任何情况下都不应该这样做。

GUID规范中没有任何内容要求攻击者无法预测。如果以块分配,则允许GUID是顺序的,允许使用非加密强度随机性创建GUID,并且允许从关于世界的已知事实创建GUID,例如MAC地址和当前时间。 无论什么都不要求GUID无法预测。

如果您需要一个不可预测的会话密钥,那么使用加密强度随机数生成器生成一个密钥以生成足够多的位。

更一般地说:使用正确的工具,特别是涉及影响安全性的代码时。 GUID旨在确保两家公司不会意外地将相同的标识符提供给两个不同的接口。如果那是您的应用程序,请为其使用GUID。 GUID的发明是为了防止良性实体发生意外,而不是保护无辜的用户免受确定的攻击者的伤害。 GUID就像停车标志 - 防止意外碰撞,防止攻击坦克。

GUID 旨在解决除事故预防之外的任何问题,因此在任何情况下都不会使用它们来解决加密问题。使用专门为解决您的问题而设计的加密库,并由世界级专家实施。

答案 1 :(得分:7)

您可以使用加密RandomNumberGenerator并获取要生成适当长度标识符的多个字节。

    RandomNumberGenerator rng = RandomNumberGenerator.Create();

    byte[] bytes = new byte[8];
    rng.GetBytes(bytes);

    // produces a string like "4jpKc52ArXU="
    var s = Convert.ToBase64String(bytes);

答案 2 :(得分:3)

如何使用what ASP.NET uses生成唯一,不可预测且安全的会话ID:

using System;
using System.IO;
using System.Web;
using System.Web.SessionState;

class Program
{
    static void Main()
    {
        var request = new HttpRequest("", "http://localhost", "");
        var response = new HttpResponse(TextWriter.Null);
        var context = new HttpContext(request, response);
        var id = new SessionIDManager().CreateSessionID(context);
        Console.WriteLine(id);
    }
}

答案 3 :(得分:1)

如果您确实必须具有不可预测性,那么生成GUID并使用128位混频器重新排列这些位。可能最好使用64位混频器来混合高低部分。而且,是的,有些混音器可以保证每个独特输入的独特输出。

请注意,这不是完全不可预测的。如果有人在观察时知道该值是混淆的GUID,那么他可能会检查连续的值,并且通过一些努力,可能会对您的位混音器进行逆向工程。