navicat_serial_generator.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #include "navicat_serial_generator.hpp"
  2. #include "exception.hpp"
  3. #include "base32_rfc4648.hpp"
  4. #include <fmt/format.h>
  5. #include <openssl/rand.h>
  6. #include <algorithm>
  7. #define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\navicat_serial_generator.cpp"
  8. #define NKG_CURRENT_SOURCE_LINE() __LINE__
  9. namespace nkg {
  10. navicat_serial_generator::navicat_serial_generator() noexcept :
  11. m_data{ 0x68 , 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32 }, m_des_key{} {}
  12. void navicat_serial_generator::set_software_language(navicat_software_language lang) noexcept {
  13. switch (lang) {
  14. case navicat_software_language::English:
  15. m_data[5] = 0xAC; // Must be 0xAC for English version.
  16. m_data[6] = 0x88; // Must be 0x88 for English version.
  17. break;
  18. case navicat_software_language::SimplifiedChinese:
  19. m_data[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
  20. m_data[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
  21. break;
  22. case navicat_software_language::TraditionalChinese:
  23. m_data[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
  24. m_data[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
  25. break;
  26. case navicat_software_language::Japanese:
  27. m_data[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
  28. m_data[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
  29. break;
  30. case navicat_software_language::Polish:
  31. m_data[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
  32. m_data[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
  33. break;
  34. case navicat_software_language::Spanish:
  35. m_data[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
  36. m_data[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
  37. break;
  38. case navicat_software_language::French:
  39. m_data[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
  40. m_data[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
  41. break;
  42. case navicat_software_language::German:
  43. m_data[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
  44. m_data[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
  45. break;
  46. case navicat_software_language::Korean:
  47. m_data[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
  48. m_data[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
  49. break;
  50. case navicat_software_language::Russian:
  51. m_data[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
  52. m_data[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
  53. break;
  54. case navicat_software_language::Portuguese:
  55. m_data[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
  56. m_data[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
  57. break;
  58. default:
  59. break;
  60. }
  61. }
  62. void navicat_serial_generator::set_software_language(uint8_t lang_sig0, uint8_t lang_sig1) noexcept {
  63. m_data[5] = lang_sig0;
  64. m_data[6] = lang_sig1;
  65. }
  66. void navicat_serial_generator::set_software_type(navicat_software_type software_type) noexcept {
  67. switch (software_type) {
  68. case navicat_software_type::DataModeler:
  69. m_data[7] = 0x84;
  70. break;
  71. case navicat_software_type::Premium:
  72. m_data[7] = 0x65;
  73. break;
  74. case navicat_software_type::MySQL:
  75. m_data[7] = 0x68;
  76. break;
  77. case navicat_software_type::PostgreSQL:
  78. m_data[7] = 0x6C;
  79. break;
  80. case navicat_software_type::Oracle:
  81. m_data[7] = 0x70;
  82. break;
  83. case navicat_software_type::SQLServer:
  84. m_data[7] = 0x74;
  85. break;
  86. case navicat_software_type::SQLite:
  87. m_data[7] = 0x78;
  88. break;
  89. case navicat_software_type::MariaDB:
  90. m_data[7] = 0x7C;
  91. break;
  92. case navicat_software_type::MongoDB:
  93. m_data[7] = 0x80;
  94. break;
  95. case navicat_software_type::ReportViewer:
  96. m_data[7] = 0xb;
  97. break;
  98. default:
  99. break;
  100. }
  101. }
  102. void navicat_serial_generator::set_software_type(uint8_t software_type_sig) noexcept {
  103. m_data[7] = software_type_sig;
  104. }
  105. void navicat_serial_generator::set_software_version(int ver) {
  106. if (11 <= ver && ver < 16) {
  107. m_data[8] = static_cast<std::uint8_t>((ver << 4) | (m_data[8] & 0x0f));
  108. memcpy(m_des_key, s_des_key0, sizeof(s_des_key0));
  109. } else if (16 <= ver && ver < 32) {
  110. m_data[8] = static_cast<std::uint8_t>(((ver - 16) << 4) | (m_data[8] & 0x0f));
  111. memcpy(m_des_key, s_des_key1, sizeof(s_des_key1));
  112. } else {
  113. throw exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Invalid navicat version.");
  114. }
  115. }
  116. void navicat_serial_generator::generate() {
  117. RAND_bytes(m_data + 2, 3);
  118. DES_key_schedule schedule;
  119. DES_set_key_unchecked(&m_des_key, &schedule);
  120. DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(m_data + 2), reinterpret_cast<const_DES_cblock*>(m_data + 2), &schedule, DES_ENCRYPT);
  121. m_serial_number = base32_rfc4648::encode(m_data, sizeof(m_data));
  122. std::transform(
  123. m_serial_number.begin(), m_serial_number.end(), m_serial_number.begin(),
  124. [](char c) -> char {
  125. if (c == 'I') {
  126. return '8';
  127. } else if (c == 'O') {
  128. return '9';
  129. } else {
  130. return c;
  131. }
  132. }
  133. );
  134. std::string_view sn = m_serial_number;
  135. m_serial_number_formatted = fmt::format("{}-{}-{}-{}", sn.substr(0, 4), sn.substr(4, 4), sn.substr(8, 4), sn.substr(12, 4));
  136. }
  137. [[nodiscard]]
  138. const std::string& navicat_serial_generator::serial_number() const noexcept {
  139. return m_serial_number;
  140. }
  141. [[nodiscard]]
  142. const std::string& navicat_serial_generator::serial_number_formatted() const noexcept {
  143. return m_serial_number_formatted;
  144. }
  145. }
  146. #undef NKG_CURRENT_SOURCE_LINE
  147. #undef NKG_CURRENT_SOURCE_FILE