ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WinRAR rarreg.key 生成原理深度解析:基于复合域 GF((2^15)^17) 的 SM2 变体 ECC 签名算法

WinRAR rarreg.key 生成原理深度解析:基于复合域 GF((2^15)^17) 的 SM2 变体 ECC 签名算法 密码学逆向工程CLI【免费下载链接】winrar-keygenPrinciple of WinRAR key generation.项目地址https://gitcode.com/gh_mirrors/wi/winrar-keygen点击查看免费下载导读WinRAR 的授权文件rarreg.key并非简单的用户名拼接而是由一套基于椭圆曲线密码学ECC的签名算法动态生成。本文以仓库文档 README.HOW_DOES_IT_WORK.md 为骨架完整拆解其背后的数学构造——定义在复合域 GF((2^15)^17) 上的 SM2 变体数字签名方案包括域构造、椭圆曲线参数、特殊 SHA1 哈希处理、签名与私钥派生算法以及最终组装rarreg.key的 13 步完整流程并逐一对齐仓库源码中的实现细节。读完本文你将能理解 WinRAR 授权文件的全部生成链路并能在源码中找到每一步对应的实现位置。1. 背景rarreg.key 与 SM2 变体 ECC 签名WinRAR 使用基于 ECC 的签名算法来生成rarreg.key。该算法是中国 SM2 数字签名算法的一个变体与常见的标准 ECDSA 不同WinRAR 选用的椭圆曲线定义在一个复合域GF((2^15)^17) 之上。整个算法链条可以概括为五个环节也是本文随后依次展开的主线复合域构造GF(2^15) 的 17 次扩张得到 GF((2^15)^17)椭圆曲线定义在复合域上的二元域曲线及其基点 G、阶 n消息哈希将输入消息的 SHA1 状态值直接构造成大整数 h签名算法SM2 变体的 ECC 签名输出 (r, s)密钥派生由用户名等输入数据派生私钥再组装输出rarreg.key。2. 复合域 GF((2^15)^17) 的构造2.1 基域 GF(2^15)基域 GF(2^15) 中的元素采用**标准基多项式基**表示其不可约多项式为即x^15 x 1其中每个系数都在 GF(2) 中。若以即 {1, α, α², …, α^14}作为基域的标准基则 GF(2^15) 中的任意元素 A 可以表示为由于 x^15 x 1 是本原多项式GF(2^15) 的乘法群由 α 生成阶为 2^15 − 1 0x7FFF。这一点在源码中体现为GF2p15LogExpTableType uint16_t[0x8000]的对数/指数查表参见 WinRarConfig.hppInitializeGF2p15Table用temp * 2若溢出则temp ^ 0x8003完成模 x^15x1 归约恰好对应生成元乘法。2.2 二次扩张构造复合域复合域 GF((2^15)^17) 的不可约多项式为即y^17 y^3 1其中每个系数都在 GF(2^15) 中。以即 {1, β, β², …, β^16}作为复合域标准基则复合域中任意元素 B 可表示为源码中GF2p15p17TraitsWinRarConfig.hpp正是这一结构的直接映射ElementType为uint16_t Items[17]即 17 个 15 位系数BitSizeValue 15 * 17 255Verify校验每个系数 0x8000乘法先做教科书式全乘FullMultiplySchoolBook依赖 GF(2^15) 对数/指数表再按y^17 y^3 1归约ModularReduction中A[i-17] ^ A[i]、A[i-14] ^ A[i]对应 y^17 与 y^3 两项。2.3 元素与 255 位整数的映射为表述方便文档用255 位整数 D表示复合域中的元素 B其映射关系为从 README.VERIFY_Point_G.md 给出的转换 Python 代码可以看出这个映射按**每 15 位一段小端顺序**把 255 位整数切分成 17 个 15 位系数def to_field_repr(val, bits15, count17): mask (1 bits) - 1 result [] for _ in range(count): result.append(val mask) val bits return result3. 定义在复合域上的椭圆曲线WinRAR 使用的椭圆曲线方程为即二元域标准曲线形式y² xy x³ ax² b中取 a 0、b 1610xA1。这与源码中曲线定义完全一致WinRarConfig.hppstatic inline const EllipticCurveGF2mGaloisFieldGF2p15p17Traits Curve{ { GaloisFieldInitByZero{} }, // A 0 { GaloisFieldInitByElement{}, { 161 } } // B 161 };基点 G 为其大整数表示为README.VERIFY_Point_G.mdGx 0x56fdcbc6a27acee0cc2996e0096ae74feb1acf220a2341b898b549440297b8cc Gy 0x20da32e8afc90b7cf0e76bde44496b4d0794054e6ea60f388682463132f931a7转换到 17×15 位小端分段表示后与 WinRarConfig.hpp 中基点 G 的 34 个 16 位系数逐一对齐Gx 系数以0x38CC, 0x052F, …, 0x56FD开头Gy 系数以0x31A7, 0x65F2, …, 0x20DA开头。仓库还提供了完整的落点验证脚本 README.VERIFY_Point_G.md在纯 Python 中实现 GF(2^15) 乘法模 x^15x1、GF((2^15)^17) 多项式乘法与归约模 y^17y^31然后通过y² xy x³ b校验 G 与公钥 PK 是否在曲线上。基点 G 的阶 n 为即n 0x1026dd85081b82314691ced9bbec30547840e4bf72d8b5e0d258442bbcd31WinRarConfig.hpp共 241 位。这个阶的位长是后续私钥合法性判断的关键见第 6 节。4. 消息哈希SHA1 状态值直接构造成大整数设输入消息为即长度为 l 的消息 M。其标准 SHA1 值为其中 s₀…s₄ 是 SHA1 输出时的 5 个状态值。通常最终 SHA1 值是这 5 个状态值按大端序各自序列化后拼接而成的 160 字节实为 20 字节摘要。然而 WinRAR 并不对这 5 个状态值做标准序列化。相反它直接用一个大整数 h 作为输入消息的哈希源码实现GenerateHashIntegerWinRarKeygen.hpp印证了这一点它把 SHA1 的 5 个 32 位状态字逐个大端字节序转换后写入RawHash[0..4]再填入RawHash[5..9]为固定常量注释注明是SHA1() with all-zeroed initial value即0x0ffd8d43, 0xb4e33c7c, 0x53461bd1, 0x0f27a546, 0x1050d90d最终取前240 位构成哈希整数 h。5. ECC 数字签名算法SM2 变体设私钥为 k、公钥为 P则必然有即P k·G源码中GeneratePublicKey直接计算__ConfigType::G * PrivateKey见 WinRarKeygen.hpp。以 h 表示输入数据的哈希WinRAR 使用如下算法完成签名生成随机大整数 Rnd满足条件即 0 Rnd n。实现上GenerateRandomIntegerWinRarKeygen.hpp以srand(time(nullptr))为种子生成 15 个 16 位随机值组成 240 位整数——由于 240 位 241 位的阶 n天然满足 Rnd n。计算 r其中 X(Rnd·G) 表示取 Rnd·G 的 X 坐标并把它从 GF((2^15)^17) 转换回大整数。源码WinRarKeygen.hpp为Signature.r.Load(false, (__ConfigType::G * Random).GetX().Dump(), true); Signature.r Hash; Signature.r % __ConfigType::Order;若 r 0 或 r Rnd n即 r ≡ −Rnd mod n则回到步骤 1 重新生成随机数。计算 s即s (Rnd − k·r) mod n。源码WinRarKeygen.hpp为Signature.s Random - __ConfigType::PrivateKey * Signature.r; Signature.s % __ConfigType::Order;若 s 0回到步骤 1。输出签名对 (r, s)。与标准方案对比标准 SM2 中 r 取(e x1) mod ne 为经 ZA 处理的哈希而 s 形如(1 dA)^−1 · (k − r·dA) mod nWinRAR 保留了 r 的哈希加 x 坐标形态此处 e 直接取 240 位哈希整数 h但 s 的计算简化为了Rnd − k·r mod n省略了(1d)^−1因子。从公式结构与源码实现WinRarKeygen.hpp可以推断这是 SM2 框架下的一种简化变体而非标准的 ECDSA标准 ECDSA 的 s 还包含随机数逆元项。6. WinRAR 私钥生成算法种子 → 240 位私钥设输入数据为即长度为 l 的数据 T。WinRAR 用它生成私钥 k过程如下用 g₀…g₅ 表示 6 个 32 位整数满足令g₀ 0。若 l ≠ 0计算 T 的 SHA1 值并把 SHA1 状态值 Sᵢ 赋给 gᵢ₊₁i 0…4否则l 0令即 g₁…g₅ 取固定常量。源码中对应GeneratePrivateKeyWinRarKeygen.hpp有种子时取 SHA1 摘要的 5 个 32 位字大端转换后填入Generator[1..5]无种子时直接填入0xeb3eb781, 0x50265329, 0xdc5ef4a3, 0x6847b9d5, 0xcde43b4c。把 g₀ 视为计数器自增 1计算取 S₀ 的最低 16 位记为 K_g0。对应源码循环WinRarKeygen.hppGenerator[0] i 1对 24 字节的 Generator 计算 SHA1取第一个状态字的低 16 位写入RawPrivateKey[i]。将步骤 4 再重复14 次共 15 轮i 1…15得到 k₁…k₁₅。输出私钥即k k₁ k₂·2¹⁶ k₃·2³² … k₁₅·2²²⁴是一个 15×16 240 位的整数。源码注释WinRarKeygen.hpp特别指出Order有 241 位而RawPrivateKey最多只有 240 位因此派生出的私钥必然小于阶 n必然是合法私钥无需再做范围校验。7. WinRAR 的固定私钥与公钥WinRAR 自己的私钥 k 为即k 0x59fe6abcca90bdb95f0105271fa85fb9f11f467450c1ae9044b7fd61d65e240 位见 WinRarConfig.hpp。该私钥正是用第 6 节的算法、以长度 l 0 的空数据为种子生成的源码注释标注Generated byWinRarKeygenWinRarConfig::GeneratePrivateKey(nullptr, 0);。对应的公钥 P 为源码中以 17×15 位小端分段给出WinRarConfig.hppPKx 系数以0x3A1A, 0x1109, …, 0x3861开头PKy 系数以0x6C20, 0x6027, …, 0x12B6开头与 README.VERIFY_Point_G.md 中的验证脚本输入完全一致。8. rarreg.key 的完整生成流程生成授权文件rarreg.key需要两个输入参数用户名 UANSI 编码字符串不含null 终止符。授权类型 LANSI 编码字符串不含null 终止符。完整流程如下源码总入口为GenerateRegisterInfo见 WinRarKeygen.hpp8.1 由用户名派生密钥对并得到 Temp用第 6 节算法以 U 为种子生成私钥 kᵤ 与公钥 pᵤ然后将公钥以SM2 压缩公钥格式输出为十六进制字符串 Temp。Temp 长度应为 64不足 64 位时用字符0左侧补齐。对应源码GeneratePublicKeySM2CompressedFormatWinRarKeygen.hpp公钥先按 SEC1 压缩0x02/0x03前缀 X 坐标再变换为2·x 奇偶位的 256 位整数十六进制化后补齐到 64 字符。8.2 由 Data3 派生 Data0令 Data3 为即固定前缀60后接 Temp 的前 48 个十六进制字符共 50 字符对应源码HelperStringFormat(60%.48s, temp.c_str())。再用第 6 节算法以 Data3 为种子生成私钥 k_data3 与公钥 p_data3同样以 SM2 压缩公钥格式输出十六进制串Data0长度 64不足补0。8.3 计算 UID令 UID 为即UID Temp 的后 16 个字符 Data0 的前 4 个字符共 20 个十六进制字符对应源码HelperStringFormat(%.16s%.4s, temp.c_str() 48, RegInfo.Items[0].c_str())。8.4 对授权类型签名得到 Data1用第 5 节签名算法以 L 为消息、第 7 节的固定私钥 k 签名得到 (rₗ, sₗ)。rₗ 与 sₗ 的位长不得超过 240否则重复本步。转换为不带0x前缀的十六进制串 SZrₗ、SZsₗ长度不足 60 时补0。然后令 Data1 为即Data1 60 SZsₗ SZrₗ2 60 60 122 字符。源码循环直至 r、s 十六进制串均恰好为 60 长度再以60%s%s先 s 后 r格式化WinRarKeygen.hpp。8.5 对 (U Data0) 签名得到 Data2重新令 Temp 为即Temp U Data0对应源码temp RegInfo.UserName RegInfo.Items[0];。用第 5 节算法以 Temp 为消息、固定私钥 k 签名得到 (r_Temp, s_Temp)位长同样不得超过 240。转换为十六进制串 SZr_Temp、SZs_Temp无0x前缀不足 60 补0令 Data2 为即Data2 60 SZs_Temp SZr_Temp122 字符对应源码HelperStringFormat(60%s%s, …)WinRarKeygen.hpp。8.6 计算 CRC32 校验和对以下消息计算 CRC32即L U Data0 Data1 Data2 Data3的拼接。最终校验和为 CRC32 值的按位取反补码再转换为十进制字符串 SZchecksum不足 10 位时补0。源码CalculateChecksumWinRarKeygen.hpp依次对 LicenseType、UserName、Items[0…3] 调用Crc32.Update最终Info.Checksum ~Crc32.Evaluate()其中 CRC32 使用反射多项式0xEDB88320HasherCrc32Traits.hpp。8.7 组装 Data 并输出令 Data 为即Data 各段长度十进制拼接 Data0 Data1 Data2 Data3 校验和。源码格式为%zu%zu%zu%zu%s%s%s%s%010luWinRarKeygen.hpp先输出 Data0、Data1、Data2、Data3 的长度 64、122、122、50即前缀6412212250随后接四个数据段最后是 10 位十进制校验和。整串共 10 (6412212250) 10 378 字符恰好 378 ÷ 54 7 行整——这也解释了为何最终文件按每行 54 字符输出源码中若长度非 54 的倍数会抛出InternalError。最终文件按如下格式输出固定首行RAR registration data用户名占一行授权类型占一行UID占一行格式为即UID 20 位十六进制串Data 内容每行 54 字符。仓库 README.md 给出了一个真实输出样例可与上述结构逐行核对RAR registration data Github Single PC usage license UID3a3d02329a32b63da7d8 6412212250a7d8753c5e7037d83011171578c57042fa30c506caae 9954e4853d415ec594e46017cb3db740bc4b32e47aea25db62f350 9f22065a27da4f8216d2938e1050b6e3347501a3767d1fdd7ee130 dd4ab952600ba16a99236d910bfa995d5f60651ec451f462511507 95b3722d059f2d5303a231e396cf21f17098edeec0b6e3347501a3 767d1fdd7ee45388769767642338ee8a63178f3458b71de5609b18 5eede7ed46566b10bf033daa6384062b259194b1acbd0378116064可以看到第 4 行 UID 恰为 20 位十六进制第 5 行以6412212250四个数据段长度开头后续共 7 行 × 54 字符。9. 源码级对照命令行使用与验证整个算法在仓库中的实现入口为WinRarKeygenWinRarConfig::GenerateRegisterInfoWinRarKeygen.hpp它返回RegisterInfo含 UserName、LicenseType、UID、Items[4]、Checksum、HexData随后由命令行程序 _tmain.cpp 负责编码转换与文件输出。命令行用法详见 README.mdwinrar-keygen.exe Username LicenseName [options] winrar-keygen.exe -v | --version winrar-keygen.exe -h | --help参数说明-e, --encoding enc编码utf8默认、ascii、ansi-o, --output file输出文件路径默认rarreg.key-a, --activate直接写入%APPDATA%\WinRAR\rarreg.key-t, --text仅打印到控制台不写文件-u, --update检查更新-v, --version显示版本-h, --help显示帮助一个 ASCII 编码的示例README.md./winrar-keygen.exe Github Single PC usage license -t -e ascii需要说明的编码前提本文档描述的生成算法中用户名与授权类型均以ANSI 编码不含 null 终止符参与哈希与签名而 CLI 默认utf8编码非 ASCII 字符会按 README 所述自动添加utf8:前缀ansi编码依赖当前 Windows 区域代码页如 Windows-1252跨区域可能产生乱码ascii编码只接受纯 ASCII 字符。这与文档ANSI 编码字符串的前提是配套的——内部算法只关心参与运算的字节串编码层由 CLI 负责。若希望独立验证曲线参数的正确性仓库提供了不依赖 C 代码的纯 Python 验证脚本 README.VERIFY_Point_G.md可独立运行并打印Verify whether the point G is on the curve: True与Verify whether the PK is on the curve: True是理解复合域运算与曲线方程最直观的入门材料。10. 总结rarreg.key的生成可以浓缩为一条完整的密码学链路域GF((2^15)^17) GF(2^15)[y]/(y^17y^31)基域不可约多项式为 x^15x1曲线y² xy x³ ba 0b 161基点 G、241 位阶 n 见 WinRarConfig.hpp哈希SHA1 的 5 个状态值不做标准序列化直接拼成大整数 hWinRarKeygen.hpp签名r X(Rnd·G) h mod ns (Rnd − k·r) mod n是 SM2 的一种简化变体WinRarKeygen.hpp私钥派生以输入串为种子经 15 轮 SHA1 截位生成 240 位私钥WinRarKeygen.hpp组装用户名公钥SM2 压缩格式→ Data3 → Data0 → UID → 两次签名Data1、Data2→ CRC32 补码校验和 → 按 54 字符每行输出。整个设计最值得注意的两点在于其一是复合域 GF((2^15)^17)而非主流标准曲线所采用的素数域或单一扩域配合对数/指数查表实现高速乘法其二是签名公式对 SM2 的简化s 省略了 (1d)^−1 因子以及哈希采用状态值直构大整数的非标准处理。这三处非常规选择共同构成了 WinRAR 授权机制的技术特征也正因如此只要掌握了私钥派生算法任何人理论上都可以复现其rarreg.key生成过程——这正是本仓库的核心价值所在。赞分享密码学逆向工程CLI【免费下载链接】winrar-keygenPrinciple of WinRAR key generation.项目地址https://gitcode.com/gh_mirrors/wi/winrar-keygen点击查看免费下载相关推荐GmSSL高级特性深度解析SM2盲签名、环签名与可恢复签名的终极指南GmSSL作为北京大学开发的国产商用密码开源库在支持国密SM2/SM3/SM4/SM9/SSL的基础上还提供了一系列高级密码学特性。本文将深入解析SM2盲签密码学网络安全PyGMTSAR地表形变监测入门指南8个真实案例看懂InSAR处理全流程PyGMTSAR地表形变监测入门指南8个真实案例看懂InSAR处理全流程 地面沉降、地震错动、火山隆起……这些肉眼难察的地表形变正在世界各地悄悄发生。 PyHS256签名算法深度解析从数学原理到PHP-JWT实战HS256签名算法深度解析从数学原理到PHP JWT实战 引言你还在为JWT签名安全发愁 当你使用JSON Web TokenJWTJSON网络令牌后端安全上一篇WVP-GB28181-Pro终极指南5步搞定多品牌监控统一管理下一篇3步完成Koikatu HF Patch安装解锁200模组的终极游戏增强指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表