不可预测的唯一标识符

本文关键字:标识符 唯一 不可预测 | 更新日期: 2023-09-27 18:11:04

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

  • 至少在应用程序中应该是唯一的,全局唯一就更好了
  • 应该是不可预测的
  • 它不应该太长,因为它将不得不在http请求头中传递,所以越小越好

我在考虑用一个加密随机数来改编一个Guid结构,但这可能有点过头了。有人知道我创建了一个适合所有这些属性的数据结构吗?

不可预测的唯一标识符

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

在guid规范中没有任何内容要求它们不可被攻击者预测。如果在块中分配guid,则允许guid是顺序的,guid允许使用非加密强度随机性创建,并且guid允许从有关世界的已知事实创建,例如您的MAC地址和当前时间。

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

更一般地说:为作业使用正确的工具,特别是当涉及到影响安全的代码时。guid的设计是为了确保两家公司不会意外地为两个不同的接口提供相同的标识符。如果这是您的应用程序,请为它使用GUID。 guid的发明是为了防止良性实体的事故,而不是为了保护无辜用户免受恶意攻击者的攻击。 guid就像停车标志——在那里是为了防止意外碰撞,而不是为了防止攻击坦克。

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

您可以使用加密的RandomNumberGenerator并获得您想要生成合适长度的标识符的任意字节。

    RandomNumberGenerator rng = RandomNumberGenerator.Create();
    byte[] bytes = new byte[8];
    rng.GetBytes(bytes);
    // produces a string like "4jpKc52ArXU="
    var s = Convert.ToBase64String(bytes);

如何使用ASP。生成唯一的、不可预测的和安全的会话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);
    }
}

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

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