WinRarKeygen.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #pragma once
  2. #include "BigInteger.hpp"
  3. #include "Hasher.hpp"
  4. #include "HasherSha1Traits.hpp"
  5. #include "HasherCrc32Traits.hpp"
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <string>
  10. #include <utility>
  11. #ifndef _WIN32
  12. #define _byteswap_ulong __builtin_bswap32
  13. #endif
  14. template<typename __ConfigType>
  15. class WinRarKeygen {
  16. public:
  17. struct RegisterInfo {
  18. std::string UserName;
  19. std::string LicenseType;
  20. std::string UID;
  21. std::string Items[4];
  22. uint32_t Checksum;
  23. std::string HexData;
  24. };
  25. private:
  26. struct ECCSignature {
  27. BigInteger r;
  28. BigInteger s;
  29. };
  30. static BigInteger GeneratePrivateKey(const void* lpSeed, size_t cbSeed) {
  31. uint32_t Generator[6];
  32. uint16_t RawPrivateKey[15] = {};
  33. if (cbSeed) {
  34. Hasher Sha1(HasherSha1Traits{}, lpSeed, cbSeed);
  35. HasherSha1Traits::DigestType Sha1Digest;
  36. Sha1Digest = Sha1.Evaluate();
  37. for (unsigned i = 0; i < 5; ++i) {
  38. Generator[i + 1] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
  39. }
  40. } else {
  41. Generator[1] = 0xeb3eb781;
  42. Generator[2] = 0x50265329;
  43. Generator[3] = 0xdc5ef4a3;
  44. Generator[4] = 0x6847b9d5;
  45. Generator[5] = 0xcde43b4c;
  46. }
  47. for (uint32_t i = 0; i < 15; ++i) {
  48. Hasher Sha1(HasherSha1Traits{});
  49. HasherSha1Traits::DigestType Sha1Digest;
  50. Generator[0] = i + 1;
  51. Sha1.Update(Generator, sizeof(Generator));
  52. Sha1Digest = Sha1.Evaluate();
  53. RawPrivateKey[i] = static_cast<uint16_t>(
  54. _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[0])
  55. );
  56. }
  57. // `Order` has 241 bits, while `RawPrivateKey` has (15 * 16 = 240) bits at most
  58. // So `RawPrivateKey` must be less than `Order` which means `RawPrivateKey` must be valid private key.
  59. return BigInteger(false, RawPrivateKey, sizeof(RawPrivateKey), true);
  60. }
  61. static auto GeneratePublicKey(const BigInteger& PrivateKey) {
  62. return __ConfigType::G * PrivateKey;
  63. }
  64. static std::string GeneratePublicKeySM2CompressedFormat(const char* lpszMessage) {
  65. auto PrivateKey = GeneratePrivateKey(lpszMessage, strlen(lpszMessage));
  66. auto PublicKey = GeneratePublicKey(PrivateKey);
  67. auto PublicKeyCompressed = PublicKey.DumpCompressed();
  68. auto PublicKeyXInteger = BigInteger(false, PublicKeyCompressed.data() + 1, PublicKeyCompressed.size() - 1, false); // 255 bits at most
  69. PublicKeyXInteger *= 2; // 256 bits at most
  70. if (PublicKeyCompressed[0] == 0x03) { // when LSB(PublicKeyY / PublicKeyX) == 1
  71. PublicKeyXInteger.SetBit(0);
  72. }
  73. auto PublicKeyCompressedSM2Format = PublicKeyXInteger.ToString(16, true);
  74. if (PublicKeyCompressedSM2Format.length() < 32 * 2) {
  75. PublicKeyCompressedSM2Format.insert(PublicKeyCompressedSM2Format.begin(), 32 * 2 - PublicKeyCompressedSM2Format.size(), '0');
  76. }
  77. return PublicKeyCompressedSM2Format;
  78. }
  79. static BigInteger GenerateRandomInteger() {
  80. uint16_t RawRandomInteger[15];
  81. srand(static_cast<unsigned int>(time(nullptr)));
  82. for (size_t i = 0; i < 15; ++i) {
  83. RawRandomInteger[i] = static_cast<uint16_t>(rand());
  84. }
  85. return BigInteger(false, RawRandomInteger, sizeof(RawRandomInteger), true);
  86. }
  87. static BigInteger GenerateHashInteger(const void* lpMessage, size_t cbMessage) {
  88. uint32_t RawHash[10];
  89. Hasher Sha1(HasherSha1Traits{}, lpMessage, cbMessage);
  90. HasherSha1Traits::DigestType Sha1Digest = Sha1.Evaluate();
  91. for (size_t i = 0; i < 5; ++i) {
  92. RawHash[i] = _byteswap_ulong(reinterpret_cast<uint32_t*>(Sha1Digest.Bytes)[i]);
  93. }
  94. // SHA1("") with all-zeroed initial value
  95. RawHash[5] = 0x0ffd8d43;
  96. RawHash[6] = 0xb4e33c7c;
  97. RawHash[7] = 0x53461bd1;
  98. RawHash[8] = 0x0f27a546;
  99. RawHash[9] = 0x1050d90d;
  100. return BigInteger(false, RawHash, 15 * sizeof(uint16_t), true); // take first 240 bits
  101. }
  102. static ECCSignature Sign(const void* lpData, size_t cbData) {
  103. ECCSignature Signature;
  104. BigInteger Hash = GenerateHashInteger(lpData, cbData);
  105. while (true) {
  106. BigInteger Random = GenerateRandomInteger();
  107. //
  108. // Calculate Signature.r
  109. //
  110. Signature.r.Load(false, (__ConfigType::G * Random).GetX().Dump(), true);
  111. Signature.r += Hash;
  112. Signature.r %= __ConfigType::Order;
  113. if (Signature.r.IsZero() || Signature.r + Random == __ConfigType::Order) {
  114. continue;
  115. }
  116. //
  117. // Calculate Signature.s
  118. //
  119. Signature.s = Random - __ConfigType::PrivateKey * Signature.r;
  120. Signature.s %= __ConfigType::Order;
  121. if (Signature.s.IsZero()) {
  122. continue;
  123. }
  124. break;
  125. }
  126. return Signature;
  127. }
  128. static void CalculateChecksum(RegisterInfo& Info) {
  129. Hasher Crc32(HasherCrc32Traits<0xEDB88320>{});
  130. Crc32.Update(Info.LicenseType.c_str(), Info.LicenseType.length());
  131. Crc32.Update(Info.UserName.c_str(), Info.UserName.length());
  132. Crc32.Update(Info.Items[0].c_str(), Info.Items[0].length());
  133. Crc32.Update(Info.Items[1].c_str(), Info.Items[1].length());
  134. Crc32.Update(Info.Items[2].c_str(), Info.Items[2].length());
  135. Crc32.Update(Info.Items[3].c_str(), Info.Items[3].length());
  136. Info.Checksum = ~Crc32.Evaluate();
  137. }
  138. public:
  139. template<typename... ArgTypes>
  140. static inline std::string HelperStringFormat(const char* lpszFormat, ArgTypes&& ... Args) {
  141. std::string s(snprintf(nullptr, 0, lpszFormat, std::forward<ArgTypes>(Args)...) + 1, '\x00');
  142. snprintf(s.data(), s.size(), lpszFormat, std::forward<ArgTypes>(Args)...);
  143. while (s.back() == '\x00') {
  144. s.pop_back();
  145. }
  146. return s;
  147. }
  148. static RegisterInfo GenerateRegisterInfo(const char* lpszUserName, const char* lpszLicenseType) {
  149. RegisterInfo RegInfo;
  150. std::string temp;
  151. RegInfo.UserName = lpszUserName;
  152. RegInfo.LicenseType = lpszLicenseType;
  153. temp = GeneratePublicKeySM2CompressedFormat(lpszUserName);
  154. RegInfo.Items[3] = HelperStringFormat("60%.48s", temp.c_str());
  155. RegInfo.Items[0] = GeneratePublicKeySM2CompressedFormat(RegInfo.Items[3].c_str());
  156. RegInfo.UID = HelperStringFormat("%.16s%.4s", temp.c_str() + 48, RegInfo.Items[0].c_str());
  157. while (true) {
  158. auto LicenseTypeSignature = Sign(RegInfo.LicenseType.c_str(), RegInfo.LicenseType.length());
  159. auto LicenseTypeSignatureR = LicenseTypeSignature.r.ToString(16, true);
  160. auto LicenseTypeSignatureS = LicenseTypeSignature.s.ToString(16, true);
  161. if (LicenseTypeSignatureR.length() <= 60 && LicenseTypeSignatureS.length() <= 60) {
  162. RegInfo.Items[1] = HelperStringFormat("60%060s%060s", LicenseTypeSignatureS.c_str(), LicenseTypeSignatureR.c_str());
  163. break;
  164. }
  165. }
  166. temp = RegInfo.UserName + RegInfo.Items[0];
  167. while (true) {
  168. auto UserNameSignature = Sign(temp.c_str(), temp.length());
  169. auto UserNameSignatureR = UserNameSignature.r.ToString(16, true);
  170. auto UserNameSignatureS = UserNameSignature.s.ToString(16, true);
  171. if (UserNameSignatureR.length() <= 60 || UserNameSignatureS.length() <= 60) {
  172. RegInfo.Items[2] = HelperStringFormat("60%060s%060s", UserNameSignatureS.c_str(), UserNameSignatureR.c_str());
  173. break;
  174. }
  175. }
  176. CalculateChecksum(RegInfo);
  177. RegInfo.HexData = HelperStringFormat(
  178. "%zd%zd%zd%zd%s%s%s%s%010lu",
  179. RegInfo.Items[0].length(),
  180. RegInfo.Items[1].length(),
  181. RegInfo.Items[2].length(),
  182. RegInfo.Items[3].length(),
  183. RegInfo.Items[0].c_str(),
  184. RegInfo.Items[1].c_str(),
  185. RegInfo.Items[2].c_str(),
  186. RegInfo.Items[3].c_str(),
  187. RegInfo.Checksum
  188. );
  189. if (RegInfo.HexData.length() % 54 != 0) {
  190. throw std::runtime_error("InternalError: The length of register data is not correct.");
  191. }
  192. return RegInfo;
  193. }
  194. };
  195. #ifndef _WIN32
  196. #undef _byteswap_ulong
  197. #endif