WinRAR 使用了基于 ECC 的签名算法来生成 rarreg.key
文件,其使用的签名算法是中国 SM2 数字签名算法的变体。与各种标准 ECDSA 不同的是,WinRAR 使用的椭圆曲线是一个基于复合域 上的曲线。
1. 复合域
基域 采用标准基(多项式基)来表达,采用的不可约多项式为:
各项系数全部位于 。设基域的标准基为:
则位于基域 上的元素 可以用如下方式表达:
复合域 的不可约多项式为:
各项系数全部位于 。设复合域的标准基为:
则位于复合域 上的元素 可以用如下方式表达:
为了方便表述我们用 255 比特的大数 来表示位于复合域 上的元素 。它们的对应关系为:
2. 复合域 上的椭圆曲线
曲线方程为:
基点 为:
基点 的阶 为:
3. 消息哈希算法
设长度为 的消息为:
则消息 的 SHA1 值为:
其中 为 SHA1 算法输出时的 5 个状态值;将这 5 个状态值按照大端字节序依次输出,即为的 SHA1 哈希值 。
WinRAR 在做完 SHA1 计算后,采用大数 作为 ECC 签名时消息的哈希:
4. ECC 签名算法
设私钥为 ,公钥为 ,即:
消息哈希为 ,则签名 为:
生成随机数 ,满足 。
计算
其中 表示取 的 X 坐标,同时将 X 坐标从 转换为大数。
若 或者 则回到步骤 1。
计算
若 则回到步骤 1。
输出 。
5. WinRAR 的私钥生成算法
该算法会利用长度为 的数据
来生成私钥 。
设 6 个 32 位整数为 ,则有
令 。
如果 则计算 的 SHA1 值,并将状态值 赋值给 :
否则,即 时,令:
把 作为计数器,自增 1。
计算 SHA1 值:
取 的低 16 位并记为 。
步骤 4 再重复 14 次。
重复执行完后会得到 ,则输出私钥
6. WinRAR 的公钥和私钥
WinRAR 的私钥 为:
该私钥是通过算法 5 生成的,其中数据 的长度为 0。
公钥 为:
7. 授权文件"rarreg.key"的生成
授权文件的生成需要两个参数:
用户名的 ANSI 字符串,不包括 null-terminator;记为
授权类型的 ANSI 字符串,不包括 null-terminator;记为
rarreg.key
的生成算法如下:
使用用户名 通过算法 5 计算出私钥 以及公钥 ,并将公钥 按照 SM2 压缩公钥格式以 Hex 字符串(ASCII 编码)的形式输出。得到的 Hex 字符串记为临时值 。
的长度应该为 64;若长度不足,则在前面补字符
'0'
,直到长度为 64。令字符串 为
使用 通过算法 5 计算出私钥 以及公钥 ,并将公钥 按照 SM2 压缩公钥格式以 Hex 字符串(ASCII 编码)的形式输出。得到的 Hex 字符串记为 。
的长度应该为 64;若长度不足,则在前面补字符
'0'
,直到长度为 64。令字符串 为
对授权类型 使用算法 4 得到签名 ,其中私钥见第 6 节。
要求 和 的长度都不得超过 240 比特,否则重复该步骤。
将 和 以 16 进制形式输出(无
"0x"
前缀),分别记为 和 。若长度不满 60,则在前面补字符
'0'
,直到长度为 60。令字符串 为
令字符串 为
对 使用算法 4 得到签名 ,其中私钥见第 6 节。
要求 和 的长度都不得超过 240 比特,否则重复该步骤。
将 和 以 16 进制形式输出(无
"0x"
前缀),分别记为 和 。若长度不满 60,则在前面补字符
'0'
,直到长度为 60。令字符串 为
对
计算 CRC32 值,最终校验和为 CRC32 值的反。将校验和以 10 进制形式输出,若长度不满 10,则在前面补字符
'0'
,直到长度为 10,记为 。令字符串 为
格式化输出。
固定文件头
"RAR registration data"
,占一行。用户名,占一行。
授权类型,占一行。
UID,占一行:
将 按照每行 54 个字符输出。