WinRAR is a trialware file archiver utility for Windows, developed by Eugene Roshal of win.rar GmbH.
It can create and view archives in RAR or ZIP file formats and unpack numerous archive file formats.
WinRAR is not a free software. If you want to use it, you should pay to RARLAB and then you will get a license file named "rarreg.key"
.
This repository will tell you how WinRAR license file "rarreg.key"
is generated.
WinRAR uses a signature algorithm, which is a variant of Chinese SM2 digital signature algorithm, to process the user's name and the license type he/she got. Save the result to "rarreg.key" and add some header info, then a license file is generated.
The following will talk about the detail of the signature algorithm that WinRAR uses and how WinRAR process the user's name and his/her license type.
Let be base point that will be used during signature. The exact value is:
auto G = ecCurve.GetPoint({ // X, represents a polynomial
0x38CC, 0x052F, 0x2510, 0x45AA, // over GF((2 ^ 15) ^ 17), the first term
0x1B89, 0x4468, 0x4882, 0x0D67, // is in the front.
0x4FEB, 0x55CE, 0x0025, 0x4CB7,
0x0CC2, 0x59DC, 0x289E, 0x65E3,
0x56FD
}, { // Y, represents a polynomial
0x31A7, 0x65F2, 0x18C4, 0x3412, // over GF((2 ^ 15) ^ 17), the first term
0x7388, 0x54C1, 0x539B, 0x4A02, // is in the front.
0x4D07, 0x12D6, 0x7911, 0x3B5E,
0x4F0E, 0x216F, 0x2BF2, 0x1974,
0x20DA
});
is the order that will be used during signature. The exact value is:
const uint64_t P[4] = { // P = 0x1026dd85081b82314691ced9bbec30547840e4bf72d8b5e0d258442bbcd31
0x5e0d258442bbcd31,
0x0547840e4bf72d8b,
0x2314691ced9bbec3,
0x0001026dd85081b8
};
To generate PrivateKey , random number and hash , we need two byte-arrays. We call them in_data and in_private. Their length is in_data_length and in_private_length respectively.
is generated by in_private.
is generated by in_data.
is generated by both in_data and in_private.
For better understanding, here I give an case:
byte in_private[7] = { 'P', 'h', 'a', 'n', 't', 'o', 'm' };
byte in_data[9] = { 'L', 'a', 'b', 'y', 'r', 'i', 'n', 't', 'h' };
where in_private_length is 7 and in_data_length is 9.
Calculate in_private's SHA-1 digest.
In the case I give, it should be:
byte in_private_sha1[] = { // standard sha-1 value is : {
0xc0, 0x16, 0x3f, 0x02, // 0x02, 0x3f, 0x16, 0xc0,
0x78, 0x4b, 0xac, 0x8c, // 0x8c, 0xac, 0x4b, 0x78,
0xaf, 0x97, 0x0d, 0xe6, // 0xe6, 0x0d, 0x97, 0xaf,
0xd9, 0x46, 0xa4, 0x91, // 0x91, 0xa4, 0x46, 0xd9,
0xdc, 0xb3, 0xbf, 0x06 // 0x06, 0xbf, 0xb3, 0xdc
}; // }
NOTICE: Compared with standard SHA-1 calculation, WinRAR reversed each 32-bits block.
If in_private is null, use default value:
byte in_private_sha1[] = {
0x81, 0xb7, 0x3e, 0xeb,
0x29, 0x53, 0x26, 0x50,
0xa3, 0xf4, 0x5e, 0xdc,
0xd5, 0xb9, 0x47, 0x68,
0x4c, 0x3b, 0xe4, 0xcd
};
It is probably the SHA-1 digest of some secret data used in RARLAB
To get each part of , do 15 rounds of SHA-1 calculation:
1. Let i be uint32_t
varing from 1 to 15.
2. In each round, we calculate the SHA-1 digest of a 24-bytes-long byte-array which is the combination of i (little-endian) and src_data_sha1. Then take the first two bytes and append them at the end of .
After that, should be a 30-bytes-long and its value is:
In the case I give, is:
byte PrivateKey[30] = { // PrivateKey = 0xb7e256217a67f14e3fb4246e889ea18b69b246616e04525e96d515831f2a
0x2a, 0x1f, 0x83, 0x15, // which is a 240-bits-long integer.
0xd5, 0x96, 0x5e, 0x52,
0x04, 0x6e, 0x61, 0x46,
0xb2, 0x69, 0x8b, 0xa1,
0x9e, 0x88, 0x6e, 0x24,
0xb4, 0x3f, 0x4e, 0xf1,
0x67, 0x7a, 0x21, 0x56,
0xe2, 0xb7
};
In my code I use a uint64_t[4]
array to store it.
During the generation of , there is a temporary 24-bytes-long byte-array. After all of the 15 rounds, the temporary byte-array should be the combination of uint32_t(15) (little endian) and src_data_sha1.
In the case I give, it should be:
byte in_private_sha1_temp[] = {
0x0f, 0x00, 0x00, 0x00,
0xc0, 0x16, 0x3f, 0x02,
0x78, 0x4b, 0xac, 0x8c,
0xaf, 0x97, 0x0d, 0xe6,
0xd9, 0x46, 0xa4, 0x91,
0xdc, 0xb3, 0xbf, 0x06
};
Calculate in_data's SHA-1 digest:
In the case I give, it should be:
byte in_data_sha1[] = {
0xfc, 0x0e, 0xcd, 0xba,
0x12, 0xa0, 0xc6, 0x2e,
0x96, 0xf6, 0xbe, 0xdb,
0x9f, 0x89, 0x72, 0x10,
0x05, 0x05, 0x71, 0xe0
};
Append
byte empty_sha1[] = {
0x43, 0x8d, 0xfd, 0x0f,
0x7c, 0x3c, 0xe3, 0xb4,
0xd1, 0x1b, 0x46, 0x53,
0x46, 0xa5, 0x27, 0x0f,
0x0d, 0xd9, 0x50, 0x10
};
at the end of in_data_sha1 so we can get byte-array (in_data_sha1 + empty_sha1). The byte-array appended is the SHA-1 digest of null while 5 SHA-1 initial constants is set 0. Then take the first 30 bytes of (in_data_sha1 + empty_sha1) as .
Append (in_data_sha1 + empty_sha1) at the end of in_private_sha1_temp.
In the case I give, it should be:
byte in_private_sha1_temp[] = {
0x0f, 0x00, 0x00, 0x00, // original in_private_sha1_temp.
0xc0, 0x16, 0x3f, 0x02,
0x78, 0x4b, 0xac, 0x8c,
0xaf, 0x97, 0x0d, 0xe6,
0xd9, 0x46, 0xa4, 0x91,
0xdc, 0xb3, 0xbf, 0x06,
0xfc, 0x0e, 0xcd, 0xba, // in_data_sha1
0x12, 0xa0, 0xc6, 0x2e,
0x96, 0xf6, 0xbe, 0xdb,
0x9f, 0x89, 0x72, 0x10,
0x05, 0x05, 0x71, 0xe0,
0x43, 0x8d, 0xfd, 0x0f, // empty_sha1
0x7c, 0x3c, 0xe3, 0xb4,
0xd1, 0x1b, 0x46, 0x53,
0x46, 0xa5, 0x27, 0x0f,
0x0d, 0xd9, 0x50, 0x10
};
To get each part of , do 15 rounds of SHA-1 calculation.
In each round, do
++*reinterpreter_cast<uint32_t*>(in_private_sha1_temp);
first, then calculate the SHA-1 digest of in_private_sha1_temp and append the first two bytes of the digest at the end of .
In the case I give, it should be:
byte K[] = {
0xeb, 0xed, 0x4f, 0xba,
0x0b, 0x30, 0xe8, 0x26,
0xf4, 0xec, 0xe6, 0x92,
0x76, 0xcc, 0xe8, 0x0b,
0xa8, 0x9c, 0x6f, 0x3a,
0x41, 0x6d, 0x5c, 0xfe,
0x21, 0x42, 0x5a, 0x5a,
0x5d, 0xbe
};
In my code I use a uint64_t[4]
array to store it.
Now we have PrivateKey , random number , hash , order and base point .
NOTICE:
1. The dot in refers to the elliptic curve point multiplication on over .
2. means takeing X-axis value of a point. This value is a polynomial over .
3. Function converts a polynomial over to a integer whose bit length would not larger than 15 * 17 = 255
. The detail of function will be talked about later.
4. is integer addition.
NOTICE:
1. is integer multiplication.
NOTICE:
1. is division over .
2. is binary AND operation.
About function :
As I said before, it converts a polynomial over to a integer. If I use a 17-elements-long list represent a polynomial over , whose every element represents a polynomial over , function can be defined as the following Python code:
def T(x : list):
ret = 0
for i in range(0, 17):
ret += x[i] * 2 ** (15 * i)
return ret
rarreg.key consists of a header, user's name, license type, UID, registration data and checksum.
It is just a text line:
RAR registration data
Actually, when WinRAR verifies user's license file, it does not care what content the header have.
It is also just a text line. Here I give a case:
Phantom
Also just a text line. Actually it can be any text. Here I give a case:
Single PC usage License
It is just a join of two parts of registration data. Here I give a case:
UID=294d3fd81ae79b20c48c
Actually, when WinRAR verifies user's license file, it does not case UID at all.
Registration data has four parts. We name them RegData0, RegData1, RegData2, RegData3 respectively.
If ECC signature of license type is and (, which means in_data = license type, in_private = null) , convert their value to hex string str_R, str_S. The max possible length of str_R and str_S is 60 because and are both 30 bytes long. So RegData1 is the format output of "60", str_S and str_R:
_stprintf_s(RegData[1], TEXT("60%060s%060s"), str_S, str_R);
In the case I give, it should be:
char RegData[1] = "60cc0b2d34fdb287124c6ca6b4f3239d36aa3ef82a9aba3a22d45552465c93260c3f609e601c26f312c4f44e7f8773a98b078809297303f8cac4a5ff92";
Let str_Kpub be the hex string of that is generated by user's name (in_private = user's name). RegData3 is:
_stprintf_s(RegData[3], TEXT("%zd%.48s"), strlen(str_Kpub) - 4, str_Kpub);
In the case I give, it should be:
char RegData[3] = "6067c38462f2ff189c4b04e3c0540548d096e1068d9235023c";
Let str_Kpub2 be the hex string of that is generated by RegData3 (in_private = RegData3). So:
_stprintf_s(RegData[0], TEXT("%s"), str_Kpub2);
In the case I give, it should be:
char RegData[0] = "c48c1c168f2ddf266ab3c33118678236ddeb1319b06790c929a038e487c79c60";
UID is:
_stprintf_s(UID, TEXT("UID=%.16s%.4s"), str_Kpub + 48, str_Kpub2);
In the case I give, it should be:
char UID = "UID=294d3fd81ae79b20c48c";
which is the same as what said before.
If ECC signature of str_UserName_RegData0 that is the join of user's name and RegData0 is and (, which means in_data = user's name + RegData0, in_private = null) , convert their value to hex string str_R2, str_S2. So RegData2 is the format output of "60", str_S2 and str_R2:
_stprintf_s(RegData[2], TEXT("60%060s%060s"), str_S2, str_R2);
In the case I give, it should be:
char RegData[2] = "60625690ab228461b54ab9a4c0a4cc5f7fdf47aa192f839596b1628abf1bec0f405163f46ce6a778adc398cefae18dbb0e4f46291e4d61e573ae0eaeb9";
_tprintf_s(TEXT("RAR registration data\n%s\n%s\n%s\n"),
UserName,
LicenseType,
UID);
char temp[1024] = { };
_stprintf_s(temp, TEXT("%zd%zd%zd%zd%s%s%s%s%lu"),
strlen(RegisterData[0]),
strlen(RegisterData[1]),
strlen(RegisterData[2]),
strlen(RegisterData[3]),
RegisterData[0],
RegisterData[1],
RegisterData[2],
RegisterData[3],
checksum);
for (int i = 0; i < 8; ++i)
_tprintf_s(TEXT("%.54s\n"), temp + i * 54);
Please make sure that you have Visual Studio 2015 or the higher. Because this is a VS2015 project.
You can open the project by VS2015 IDE and then build it with one click. Or use VS Developer Command Prompt:
msbuild winrar-keygen.vcxproj /p:Configuration=Release;Platform=<x86|x64>;SolutionDir=<your_output_dir> /t:build
NOTICE: Do not use "Debug" configuration. Otherwise you may approximately wait for half a minute every time you generate a license file.
NOTICE: SolutionDir must end with \
NOTICE:
For Windows XP, you can build it by
msbuild winrar-keygen.vcxproj /p:Configuration=ForXP;Platform=x86;SolutionDir=<your_output_dir> /t:build
D:\Github\winrar-keygen>msbuild winrar-keygen.vcxproj /p:Configuration=Release;Platform=x64;SolutionDir=D:\winrar-keygen\ /t:build
......
......
D:\Github\winrar-keygen>cd D:\winrar-keygen\x64\Release
D:\winrar-keygen>winrar-keygen.exe "Phantom" "Single PC License" >> rarreg.key
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。