winrar-keygen/README.HOW_DOES_IT_WORK.zh-CN.md
bitcookies b5884319fa 🌙 Adapt the Github Dark Theme
🌙 Adapt the Github Dark Theme
2022-04-24 14:46:11 +08:00

16 KiB
Raw Blame History

"rarreg.key"是如何生成的?

WinRAR 使用了基于 ECC 的签名算法来生成 rarreg.key 文件,其使用的签名算法是中国 SM2 数字签名算法的变体。与各种标准 ECDSA 不同的是WinRAR 使用的椭圆曲线是一个基于复合域 GF2p15p17-inlined GF2p15p17-inlined 上的曲线。

1. 复合域 GF2p15p17-inlined GF2p15p17-inlined

基域 GF2p15-inlinedGF2p15-inlined 采用标准基(多项式基)来表达,采用的不可约多项式为:

各项系数全部位于 GF2p15-inlinedGF2p15-inlined。设基域的标准基为:

则位于基域 GF2p15-inlinedGF2p15-inlined 上的元素 ![A-inlined] 可以用如下方式表达:


复合域 GF2p15p17-inlined GF2p15p17-inlined 的不可约多项式为:

各项系数全部位于 GF2p15-inlinedGF2p15-inlined。设复合域的标准基为:

则位于复合域 GF2p15p17-inlined GF2p15p17-inlined 上的元素 ![B-inlined] 可以用如下方式表达:


为了方便表述我们用255比特的大数 ![D-inlined] 来表示位于复合域 GF2p15p17-inlined GF2p15p17-inlined 上的元素 ![B-inlined]。它们的对应关系为:

2. 复合域 ![GF2p15p17-inlined] 上的椭圆曲线

曲线方程为:

基点 ![G-inlined] 为:

基点 ![G-inlined] 的阶 ![n-inlined] 为:

3. 消息哈希算法

设长度为 ![l-inlined] 的消息为:

则消息 ![M-inlined] 的SHA1值为

其中 s0,4s0,4 为SHA1算法输出时的5个状态值将这5个状态值按照大端字节序依次输出即为的SHA1哈希值 SHA1MSHA1M

WinRAR 在做完 SHA1 计算后,采用大数 ![h-inlined] 作为 ECC 签名时消息的哈希:

4. ECC签名算法

设私钥为 ![k-inlined],公钥为 ![P-inlined],即:

消息哈希为 ![h-inlined],则签名 (r,s)(r,s) 为:

  1. 生成随机数 ![Rnd-inlined],满足 RNDRND

  2. 计算 ![r-inlined]

    其中 RNDGxRNDGx 表示取 RNDGRNDG 的 X 坐标,同时将 X 坐标从 !GF2p15p17-inlined GF2p15p17-inlined 转换为大数。

    r=0r=0 或者 rRndrRnd 则回到步骤1。

  3. 计算 ![s-inlined]

    s=0s=0 则回到步骤1。

  4. 输出 (r,s)(r,s)

5. WinRAR的私钥生成算法

该算法会利用长度为 ![l-inlined] 的数据

来生成私钥 ![k-inlined]。

  1. 设6个32位整数为 g0-5g0-5,则有

  2. g0=0g0=0

  3. 如果 l!=0l!=0 则计算 ![T-inlined] 的 SHA1 值,并将状态值 SiSi 赋值给 gi+1gi+1

    否则,即 l=0l=0 时,令:

  4. g0g0 作为计数器自增1。

    计算 SHA1 值:

    S0S0 的低16位并记为 Kg0Kg0

  5. 步骤4再重复14次。

  6. 重复执行完后会得到 k1-15k1-15,则输出私钥

6. WinRAR的公钥和私钥

WinRAR的私钥 ![k-inlined] 为:

该私钥是通过算法5生成的其中数据 ![T-inlined] 的长度为0。

公钥 ![P-inlined] 为:

7. 授权文件"rarreg.key"的生成

授权文件的生成需要两个参数:

  1. 用户名的 ANSI 字符串,不包括 null-terminator记为

  2. 授权类型的 ANSI 字符串,不包括 null-terminator记为

rarreg.key 的生成算法如下:

  1. 使用用户名 ![UU-inlined] 通过算法5计算出私钥 kuku 以及公钥 pupu,并将公钥 pupu 按照 SM2 压缩公钥格式以Hex字符串ASCII编码)的形式输出。得到的 Hex 字符串记为临时值 ![Temp-inlined]。

    ![Temp-inlined] 的长度应该为64若长度不足则在前面补字符 '0'直到长度为64。

  2. 令字符串 ![Data3-inlined]为

  3. 使用 ![Data3-inlined] 通过算法5计算出私钥 kdata3kdata3 以及公钥 pdata3pdata3,并将公钥 pdata3pdata3 按照 SM2 压缩公钥格式以 Hex 字符串ASCII编码)的形式输出。得到的Hex字符串记为 ![Data0-inlined]。

    ![Data0-inlined] 的长度应该为64若长度不足则在前面补字符 '0'直到长度为64。

  4. 令字符串 ![UID-inlined]为

  5. 对授权类型 ![LL-inlined] 使用算法4得到签名 (rl,sl)(rl,sl)其中私钥见第6节。

    要求 rlrlslsl 的长度都不得超过240比特否则重复该步骤。

  6. rlrlslsl 以16进制形式输出"0x"前缀),分别记为 SZrlSZrlSZslSZsl

    若长度不满60则在前面补字符 '0'直到长度为60。

  7. 令字符串 ![Data1-inlined]为

  8. 令字符串 ![Temp-inlined]为

    对 ![Temp-inlined] 使用算法4得到签名 (rTemp,sTemp)(rTemp,sTemp)其中私钥见第6节。

    要求 rTemprTempsTempsTemp 的长度都不得超过240比特否则重复该步骤。

  9. rTemprTempsTempsTemp 以16进制形式输出"0x"前缀),分别记为 SZrTempSZrTempSZsTempSZsTemp

    若长度不满60则在前面补字符 '0'直到长度为60。

  10. 令字符串 ![Data2-inlined]为

  11. 计算 CRC32 值,最终校验和为 CRC32 值的反。将校验和以10进制形式输出若长度不满10则在前面补字符 '0'直到长度为10记为 SZchecksumSZchecksum

  12. 令字符串 ![Data-inlined]为

  13. 格式化输出。

    • 固定文件头 "RAR registration data",占一行。

    • 用户名,占一行。

    • 授权类型,占一行。

    • UID占一行

    • 将 ![Data-inlined] 按照每行54个字符输出。