生成产品激活的序列号

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

这是我的要求:

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

我不是在寻找能够满足所有这些要求的银弹,而是或多或少地指向文档或现有库的一些链接,这些链接将帮助我开始。 我见过的唯一一个库是XHEO DeployLX库; 这对我的需求来说太过分了。

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

你有没有看过关于这件事的Brandon Staggs文章 ?

在delphi,但理论掌握着任何语言。

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

使用串行密钥,您需要考虑一些事情。

我在狩猎期间看到了链接,指向使用简单的Guid.NewGuid(); 接近然后对字符串进行一些转换以生成自定义样式的串行密钥。 这很容易做到,但是产品所有者有责任跟踪数据库中的序列密钥,并且在一天结束时有人可能通过使用Guid.NewGuid()随机找到有效的序列号。 他们自己。 如果地球上的每个人同时开始生成Guids,碰撞机会就很可能​​发生。

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

为此,我倾向于使用:

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

好吧,让我们想象一下我从一个guid中取出前16位数字。 然后我将它与Nonce和秘密盐组合,然后使用SHA256从值中导出哈希。 然后,我可以使用“难度”因子来确定散列是否以0或其他我想要的字符开头。

例如:如果散列有6个0前缀,那么我将所有数据保存起来,因为我刚刚发现了一个相当安全的串行密钥。

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

下面是一些示例代码 – 非常粗糙,因为我很无聊。

我们的想法是您的应用程序可以将产品密钥和序列发送到激活服务器。 服务器知道秘密盐。 然后返回true或false以确定生成的哈希是否满足安全性要求。 如果不是:Serial无效,或对提供的密钥无效。 如果它确实具有所需的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密集,但是使得它们非常快速地进行validation。

 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)值。