【问题标题】:Generating a serial number for product activation为产品激活生成序列号
【发布时间】:2012-11-30 09:41:27
【问题描述】:

首先,这不是关于为其他产品生成序列号的问题。我希望“破解”其他产品。

这是我的要求:

  • 我想生成一个标准外观的序列号:AILU7-ABCDE-54321-1234-AFCK-17UDF
  • 我需要一些流程来验证该序列号是否“有效” - 这部分不是必须非常复杂。即,如果所有数字的总和大于 X - 我可以接受,但如果有解决方案可以为我处理这种复杂性,我会很乐意使用它们。
  • 验证序列号的进程可以不是在服务器端。即,我无法向外部 Web 服务器发出请求以验证序列号是否有效。
  • 我需要某种方法从序列号中提取元数据。即,在我验证序列号正确后,我需要能够从中读出一些值:“用户限制”、“到期日期”等...
  • 序列号的验证将通过 ASP.NET MVC 3 应用程序完成。不过,序列号的生成不一定必须这样做。

我并不是在寻找能够满足所有这些要求的灵丹妙药,而是或多或少地寻找一些可以帮助我入门的文档或现有库的链接。我见过的唯一库是XHEO DeployLX 库;这对我的需求来说太过分了。

您能否提供任何可以为我指明正确方向的信息?

【问题讨论】:

  • 你在 SO 上看到过这个链接吗:stackoverflow.com/questions/4583630/…
  • 我不确定您要实现的目标是否可行,例如,如果可能的话,将公司名称嵌入到一个短字符串中将非常困难。如果您需要额外的元数据,也许您应该考虑使用许可文件模型,或者在某处存储密钥->元数据映射。
  • @Ian - 我也完全同意。我只需要有关如何开始使用该模型的信息。目前,密码学对我来说很陌生。
  • @Ian - 同意。从短字符串中验证公司名称或其他任何内容当然是可能的,但是编码要困难得多。这是一个压缩问题。
  • @BryanRay:我实际上不知道任何例子(我想看看是否有一种常见的做法)。这个想法是你有一个包含所有元信息(公司名称、机器信息等)和生成的 ID 的文件。然后,提供商将使用私钥对其进行哈希处理。应用程序将使用公钥通过检查哈希来验证文件未被修改,然后可以从中读取所有许可证信息。

标签: c# asp.net-mvc-3


【解决方案1】:

你查看Brandon Staggs article on this very matter了吗?

在 Delphi 中,但理论适用于任何语言。

【讨论】:

  • 很棒的链接。我将从那里开始。非常感谢,维克托。
  • 我几乎希望我的软件需要这种保护,这样我才能实现它。设计听起来很有趣。
【解决方案2】:

那里有很多库,其中一个是 http://skgl.codeplex.com/http://softwareprotector.codeplex.com/,并且还附带一个 nuget 包。

【讨论】:

    【解决方案3】:

    使用序列号需要考虑一些事情。

    我在搜索过程中看到了指向使用简单 Guid.NewGuid(); 的链接。方法,然后对字符串进行一些转换以制作自定义样式的序列键。这很容易做到,但产品所有者有责任跟踪数据库中的序列号,最终有人可能会随机找到通过使用 Guid.NewGuid() 工作的序列号;他们自己。如果地球上的每个人都同时开始生成 Guid,那么碰撞的可能性就变得很大。

    有一种解决方案可以通过在 Guid.NewGuid() 之上使用更复杂的算法来降低碰撞事件的可能性;

    为此,我倾向于使用:

    1. Guid.NewGuid(); (仅前 16 个字符,减去 -(连字符)
    2. 一个不断增加或变化的值。 (Nonce)(一个 int 可以工作:i++ 等)
    3. 一种秘密盐,您将在网络中保持私密和安全。
    4. 一个困难因素:从比特币中借用这个原理。

    好的,假设我正在从 guid 中获取前 16 位数字。 然后我将它与 Nonce 和秘密盐结合起来, 然后使用 SHA256 从值派生哈希。 然后我可以使用难度系数来确定哈希是否以我想要的 0 或其他字符的数量开头。

    例如:如果哈希有六个 0 前缀,那么我会保存所有数据,因为我刚刚找到了一个相当安全的串行密钥。

    当我的意思是安全时,我的意思是我找到了一个序列,当它与产品密钥(Nonce)结合,然后与秘密 Salt 一起使用时,它会产生一个符合我的生产标准的哈希。

    下面是一些示例代码 - 做得很粗糙,因为我很无聊。

    这个想法是您的应用程序可以将产品密钥和序列号发送到激活服务器。服务器知道秘密盐。然后它返回 true 或 false 以确定生成的哈希是否满足安全要求。 如果不是:序列号无效,或者对提供的密钥无效。 如果它确实有所需的 0:它是一个有效的序列号。

        Guid theGuid;
        string Hash = "";
        int iAccess = 0;
        string PrivateSalt = "Alpha";
        string SourceString = "";
        string guidString;
        while (true)
        {
            theGuid = Guid.NewGuid();
            guidString = theGuid.ToString().Replace("-", "").Substring(0,16);
            SourceString = guidString + "|" + iAccess.ToString() + "|" + PrivateSalt;
            byte[] data = Encoding.Default.GetBytes(SourceString);
            Hash = Crypto.GenerateSHA256(data);
            if (Hash.StartsWith(GetDiff()))
            {
                break;
            }
    
            iAccess++;
        }
        Console.WriteLine(SourceString+" Gives hash "+Hash);
        string s1, s2, s3, s4;
        s1 = guidString.Substring(0, 4);
        s2 = guidString.Substring(4, 4);
        s3 = guidString.Substring(8, 4);
        s4 = guidString.Substring(12, 4);
        string serial = s1 + "-" + s2 + "-" + s3 + "-" + s4;
    
        Console.WriteLine(serial + " :" + SourceString + " Gives hash " + Hash);
    

    GetDiff() 基本上只是一个字符串:"000000";

    此方法的示例输出如下所示:

    d9c9-f6f0-45be-427a :d9c9f6f045be427a|15135|Alpha Gives hash    000000f718f69c8389d496e01d1e992946fe1b8cf72bc4200a7a2b800b40aa0a
    fe49-70b9-08d8-40df :fe4970b908d840df|9096414|Alpha Gives hash  000000e29cfccfb54d1e7edc816feb084f1a2cd11a20c3132a965f9048fc9bf4
    7f58-0636-c853-4f0a :7f580636c8534f0a|12297217|Alpha Gives hash 0000007bb44f39a964bbe985885451c3dc0e037fcd12951261404e48819bf89b
    6f65-82d3-d95b-4882 :6f6582d3d95b4882|15064854|Alpha Gives hash 000000f1a3bed79e441108cfd26d8733d3fc10f5cd66d234ed35fe2b769663a3
    edee-b8b7-9f6f-40ab :edeeb8b79f6f40ab|17782415|Alpha Gives hash 000000b70b96e7b008a96a860efc572fe868154ae81e67b9397249a51f2db71c
    0948-4bb3-7de4-4054 :09484bb37de44054|21105690|Alpha Gives hash 000000ec7317eccd5fd9bb701759a2b0e77d37099347d9d665f4b492a69ca3ec
    bbf5-5119-bf4e-463c :bbf55119bf4e463c|21715642|Alpha Gives hash 000000a134c886d01606da83cd5e8f672fddb6aa061968e9f08202c781514b16
    80f6-c9c5-0ddf-436d :80f6c9c50ddf436d|26450310|Alpha Gives hash 00000092305b2956381c23dacba5b8ff9a37ab994148b37677732dc2a0650386
    0a4f-143b-b5f5-48ca :0a4f143bb5f548ca|33691865|Alpha Gives hash 00000054ecdae57c6ec686b6084faf68ae49a78f7c07bbe8e51357d76de63870
    

    您可以通过在前缀中添加更多的 0 来增加难度。 这意味着查找串行组合将花费更长的时间,但也使其更加安全。

    显然您会将这些数据组合存储在某个地方,因此在激活期间,您可以比较序列号和产品密钥(Nonce)。

    在我的示例中:我正在使用序列密钥(16 位)、递增 int 和单词 Alpha 来表示秘密盐。

    这使得生成串行密钥很慢且占用大量 CPU,但验证它们的速度非常快。

    IsSerialValid("edee-b8b7-9f6f-40ab", 17782415);
    
    public bool IsSerialValid(string serialCode, int ProductCode)
            {
                string SourceString = serialCode.Replace("-", "") + "|" + ProductCode.ToString() + "|" + "Alpha";
                byte[] data = Encoding.Default.GetBytes(SourceString);
                string Hash = Crypto.GenerateSHA256(data);
                if (Hash.StartsWith(GetDiff()))
                {
                    return true;
                }
                return false;
            }
    

    秘密 Salt 可能是一个代码短语,它映射到您可能正在开发的不同产品。这允许您跨多个产品线重复使用产品密钥 (Nonce) 值。

    【讨论】:

    • 验证不起作用总是返回 false,因为验证中使用的源字符串与生成产品代码部分中使用的源字符串不同。
    猜你喜欢
    • 2011-11-22
    • 1970-01-01
    • 2015-05-03
    • 2015-02-23
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    相关资源
    最近更新 更多