C# 用户ID混淆

C# 用户ID混淆,c#,obfuscation,C#,Obfuscation,我希望以前有人问过这个问题,但现在还没有找到合适的答案,也没有时间提出我自己的解决方案 如果我们有一个主键为int-identity的用户表,那么我们的用户在站点注册时拥有连续的ID 网站URL上的“我们拥有用户公共配置文件”页面: www.somesite.com/user/1234 其中1234是实际的用户ID。没有任何漏洞可以看到用户ID本身,但它确实让任何人都能够检查有多少用户在我的网站上注册。。。手动增加这个数字最终会使我得到一个无效的配置文件 这就是我想要一个可逆ID映射到一个看似

我希望以前有人问过这个问题,但现在还没有找到合适的答案,也没有时间提出我自己的解决方案

如果我们有一个主键为
int-identity
的用户表,那么我们的用户在站点注册时拥有连续的ID

网站URL上的“我们拥有用户公共配置文件”页面:

www.somesite.com/user/1234
其中1234是实际的用户ID。没有任何漏洞可以看到用户ID本身,但它确实让任何人都能够检查有多少用户在我的网站上注册。。。手动增加这个数字最终会使我得到一个无效的配置文件

这就是我想要一个可逆ID映射到一个看似随机且长度固定的数字的主要原因:

www.somesite.com/user/6123978458176573
你能给我指出一个做这个映射的简单类吗?当然,这个映射是可逆的,这一点很重要,否则我必须将映射与其他用户的数据一起保存

我想避免使用guid GUID索引搜索速度较慢,因为它们不是连续的,所以SQL必须扫描整个索引以匹配特定的GUID,而不是只搜索特定的计算索引页

如果我有ID+GUID,那么我将始终需要获取原始用户ID来执行任何有意义的数据操作,这又是一次速度降级


数学可逆整数置换似乎是最快的解决方案…

我建议您改用UUID。当您向数据库中添加新用户时,这可能是可索引的,并在存储过程中生成。这意味着要么向数据库表中添加一个新列,要么添加一个包含UUID但用户ID作为相关键的新表

编辑

如果你真的想避免使用guid,那么为什么不在用户访问他们的个人资料页面时使用用户名呢。毕竟,我认为在用户输入有效信息并将数据保存到数据库之前,您不会为其分配ID。

我会100%赞同“向表中添加GUID列”的方法。为每个当前用户生成一个,并更新插入过程以为每个新用户生成一个,需要几秒钟。这是最好的解决办法

然而,如果你真的不想采用这种方法,你可以使用很多模糊处理技术

简单地对数字的字符串表示形式进行Base64编码是一种(不好的)方法

    static public string EncodeTo64(string toEncode)
    {

      byte[] toEncodeAsBytes
            = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
      string returnValue
            = System.Convert.ToBase64String(toEncodeAsBytes);
      return returnValue;
    }

    static public string DecodeFrom64(string encodedData)
    {
      byte[] encodedDataAsBytes
          = System.Convert.FromBase64String(encodedData);
      string returnValue =
         System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
      return returnValue;
    }
糟糕的是,任何拥有半盎司技术知识的人(黑客/脚本编写者往往拥有丰富的技术知识)都会立即将结果识别为Base64并轻松进行反向工程


编辑:这篇博客文章提供了一个很好的例子。转换为C#会给您带来如下效果:

static int Prime = 1580030173;
static int PrimeInverse = 59260789;

public static int EncodeId(int input)
{
    return (input * Prime) & int.MaxValue;
}

public static int DecodeId(int input)
{
    return (input * PrimeInverse) & int.MaxValue;
}
输入-->输出
1234-->1989564746
5678-->1372124598
5679-->804671123

解释了如何使用随机异或更安全地实现这一点,以及如何计算
Prime
PrimeInverse
——我刚刚使用了原始博客中的预封装演示

  • 使用UUID

  • 在用户表中创建另一列,例如64位整数,并用随机数填充(每次新用户注册时-生成并检查其唯一性)。数字看起来比UUID好,但是需要更多的编码

  • 使用数学您可以生成一对数字
    X
    Y
    ,例如
    X*Y=1(mod M)
    。例如,
    X=10000000019L
    Y=1255114267L
    ,以及
    M=2^30
    。然后,您将有两个简单的函数:


  • 它将产生几乎随机编码的ID。这很容易,但可以破解。如果有人费心去破解它,他将能够猜出你的数字并看到编码的值。然而,我不完全确定它的复杂性,但我记得它不是很容易破解。

    如果有人能计算出网站上注册了多少用户,为什么会有问题?你不必从1点开始!你考虑过只使用guid吗?即使您的表已经存在,您也可以为每一行生成一个guid,并将其用于mapping@JonathonBolster:GUID不适合SQL索引,因为搜索速度较慢(仅通过GUID SQL无法知道结果将出现在哪个页面上)。。。拥有ID+GUID需要额外的SQL查询来获取实际使用ID以进行任何数据操作。。。出于这两个原因,我想避免使用guid。正如我在@jonathonbumple的评论中所概述的那样,我想避免使用guid是出于速度和添加查询的原因。哦,是的。。。素数计算很棒!比Base64编码好得多。素数和素数逆如何相互关联?我的意思是,当我有一个大于158030173的素数时,你能计算素数逆吗?下面是一个工作链接:@VisualBean:我在这里找到了一个很好的解释和一些代码:从中,我能够制作一个C#乘法逆计算器。注意,在C#中使用int值进行编码/解码的计算更像:
    return(int)(Math.BigMul(input,Prime)%int.MaxValue)可避免整数溢出。(或者你可以使用unchecked关闭溢出安全设置,但我认为以上更好地满足了alogrithm的意图。)请参阅我对@JonathonBoost的评论避免使用GUID(即Microsoft的UUID)的原因是什么。黑客不是问题。。。我没有加密敏感数据。。。ID是公共的。。。但我只是想混淆他们…当尝试第三个选项时。如果你决定使用它,我会记得代数解释如何为你自己生成这样的
    X
    Y
    数字。你应该对它们保密,每个知道它们的人都可以解码你的编码ID。
    long encode(long id)
    {  return (id * X) & M; }
    
    long decode(long encodedId)
    {  return (encodedId * Y) & M; }