Windows序列号算法

很容易在各大网站上找到不完整的Windows安装序列号的破解的文章。在这里尝试收集整理一下,而且附带了完整的公式。

认证过程

1.解码
下面的计算都是基于这个序列号的:
JCF8T-2MG8G-Q6BBK-MQKGT-X3GBB
因为字符"-"不包含任何信息,所以微软的产品序列号实际上是由25个字符组成的。另外,微软没有使用易混淆的字符,比如"I"和"1","O"和 "0",其产品序列号之包括"BCDFGHJKMPQRTVWXY2346789"进行编码。于是,一个产品序列号中,最多包含log22425约等于 114个bit的信息。要把这些字符解码为2进制,我们需要:
a.将上面的序列号"JCF8T2MG8GQ6BBKMQKGTX3GBB"转化为"6 1 3 22 ......",即,‘B'=0, ‘C'=1, ‘D'=2 ......,我们定义得到的数组为base24[]。
b.计算解码:decode=∑{base24[i]*24^(24-i)}(i=0 to 24),运算的结果是:00 C5 31 77 E8 4D BE 73 2C 55 47 35 BD 8D 01 00 (采用little-endian表示)
c. 解码结果可以被分为:12bit + 31bit + 62bit + 9bit,四个部分分别表达的含义为:12bit: 操作系统家族, 31bit: Hash码, 62bit: 签名, 9bit: 前缀.
2.校验
如果阅读本段遇到了麻烦,请首先参阅一些椭圆曲线密码论(Elliptic Curve Cryptography,ECC)材料。
在开始校验产品序列号前,我们首先应将上述4个部分12bit: 操作系统家族, 31bit: Hash码, 62bit: 签名, 9bit: 前缀.进行一些计算。
微软产品序列号认证程序采用的是一个ECC公钥,这个公钥可以在PIDGEN.DLL's BINK找到,它包含:
p,a,b构造的曲线:y2=x3+ax+b(mod p)
G(x,y) 代表曲线上的一个点,称为"generator"。
K(x,y)代表曲线上的一点,由某个整数k以及"generator"点G决定。
没有私钥k,则我们无法创建一个有效的序列号,但是我们可以通过公钥key:{p, a, b, G, K}来验证一个序列号。
1. 计算 H=SHA-1(5D 操作系统家族,Hash码,前缀,00 00),总长为11个byte。H长160个bit,我们需要的只是其前两个word。将H的第二个word进行位运算,右移2个bits。比如,若 SHA-1返回了FE DC BA 98 76 54 32 10,则H=FE DC BA 98 1D 95 0C 04。(译者注:H的前面FE DC BA 98保留,将76 54 32 10作2次逻辑右移)。
2.计算 R(rx,ry)=Signature * (Signature*G + H*K) (mod p)
3.计算 SHA-1(79 OS Family, rx, ry)总输入长度为 1+2+64*2=131个 byte。最后比较Hash与计算结果,如果两者相同,则序列号是可用的!

创建可用的序列号!

我们假设我们已经获取了私钥k,(当然,微软不会公布k的值,我们只有自己破解它了),那么序列号验证系统的计算等式如下:
Hash=SHA(Signature*(Signature*G+SHA(Hash)*K) (mod p))
我们需要做的,便是计算出一个满足上面等式的Signature。 过程如下:
1.随机取一个整数r,并计算 R(rx,ry)=r * G
2.计算Hash= SHA-1(79 操作系统家族, rx, ry) ,输入总长为1+2+64*2=131个 byte,我们只需要前62个bit作为结果。
3.计算 H=SHA-1(5D 操作系统家族,Hash码, 前缀, 00 00) ,其总长为11个byte,我们只需要其前面的2个word,并且将H的第二个字右移2个bit。(译者注:具体方法见前文的验证部分)现在,我们有了如下等式:
Signature*(Signature*G+H*K) = r * G (mod p)
将K=k*G代入,有:
Signature*(Signature*G+H*k*G) = r * G (mod p)
Signature2+H*k*Signature-r=0 (mod n),式中,n为椭圆上点G的级。
解上面的方程,得到Signature的值:Signature=0.5*{-H*k±root[(H*k)2+4r]}(mod n),
注意:因为一元二次方程需满足判别式大于等于零的要求,因此如果Signature无实数根,则一切要从第一步重新开始。Get
由公钥获取私钥
我曾提到过私钥k并没有被包含在BINK的资源中,所以我们需要自己破解它。
在公钥中:K(x,y) = k * G, 我们只知道generator G, K, 但是难以获得k的值.
由 K(x,y) = k * G获得k的有效方法是Pollard's Rho (或者是它的变体) , 其复杂处只在于n应为G的级。 (n并不包括在公钥的资源中,因此我们需要通过 Schoof's 法则来获得n值)
因为用户不可能承受过于冗长的序列号的输入,因此Signature还是应该比较短的. 微软公司选择使用62位长的Signature,因此,n仅仅有62位长,计算私钥k的复杂度为 O(2^31).

原文地址:https://www.cnblogs.com/javawebsoa/p/2458159.html