upload codebase

Signed-off-by: Double Sine <xiao_ai_yu@live.cn>
This commit is contained in:
Double Sine
2022-02-14 15:47:41 +08:00
commit 9017721a5c
43 changed files with 4615 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
#include <iostream>
#include "navicat_serial_generator.hpp"
#include "exceptions/operation_canceled_exception.hpp"
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\CollectInformation.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
[[nodiscard]]
static int read_int(int min_val, int max_val, std::string_view prompt, std::string_view error_msg) {
int val;
for (std::string s;;) {
std::cout << prompt;
if (!std::getline(std::cin, s)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
if (s.empty())
continue;
try {
val = std::stoi(s, nullptr, 0);
if (min_val <= val && val <= max_val) {
return val;
} else {
throw std::invalid_argument("Out of range.");
}
} catch (std::invalid_argument&) {
std::cout << error_msg << std::endl;
}
}
}
[[nodiscard]]
static int read_int(int min_val, int max_val, int default_val, std::string_view prompt, std::string_view error_msg) {
int val;
for (std::string s;;) {
std::cout << prompt;
if (!std::getline(std::cin, s)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
if (s.empty()) {
return default_val;
}
try {
val = std::stoi(s, nullptr, 0);
if (min_val <= val && val <= max_val) {
return val;
} else {
throw std::invalid_argument("Out of range.");
}
} catch (std::invalid_argument&) {
std::cout << error_msg << std::endl;
}
}
}
[[nodiscard]]
navicat_serial_generator CollectInformationNormal() {
navicat_serial_generator sn_generator;
std::cout << "[*] Select Navicat product:" << std::endl;
std::cout << " 0. DataModeler" << std::endl;
std::cout << " 1. Premium" << std::endl;
std::cout << " 2. MySQL" << std::endl;
std::cout << " 3. PostgreSQL" << std::endl;
std::cout << " 4. Oracle" << std::endl;
std::cout << " 5. SQLServer" << std::endl;
std::cout << " 6. SQLite" << std::endl;
std::cout << " 7. MariaDB" << std::endl;
std::cout << " 8. MongoDB" << std::endl;
std::cout << " 9. ReportViewer" << std::endl;
std::cout << std::endl;
sn_generator.set_software_type(static_cast<navicat_software_type>(read_int(0, 9, "(Input index)> ", "Invalid index.")));
std::cout << std::endl;
std::cout << "[*] Select product language:" << std::endl;
std::cout << " 0. English" << std::endl;
std::cout << " 1. Simplified Chinese" << std::endl;
std::cout << " 2. Traditional Chinese" << std::endl;
std::cout << " 3. Japanese" << std::endl;
std::cout << " 4. Polish" << std::endl;
std::cout << " 5. Spanish" << std::endl;
std::cout << " 6. French" << std::endl;
std::cout << " 7. German" << std::endl;
std::cout << " 8. Korean" << std::endl;
std::cout << " 9. Russian" << std::endl;
std::cout << " 10. Portuguese" << std::endl;
std::cout << std::endl;
sn_generator.set_software_language(static_cast<navicat_software_language>(read_int(0, 10, "(Input index)> ", "Invalid index.")));
std::cout << std::endl;
std::cout << "[*] Input major version number:" << std::endl;
sn_generator.set_software_version(read_int(11, 16, 16, "(range: 11 ~ 16, default: 16)> ", "Invalid number."));
std::cout << std::endl;
return sn_generator;
}
[[nodiscard]]
navicat_serial_generator CollectInformationAdvanced() {
navicat_serial_generator sn_generator;
std::cout << "[*] Navicat Product Signature:" << std::endl;
sn_generator.set_software_type(static_cast<uint8_t>(read_int(0x00, 0xff, "(range: 0x00 ~ 0xFF)> ", "Invalid number.")));
std::cout << std::endl;
std::cout << "[*] Navicat Language Signature 0:" << std::endl;
auto s1 = static_cast<uint8_t>(read_int(0x00, 0xff, "(range: 0x00 ~ 0xFF)> ", "Invalid number."));
std::cout << std::endl;
std::cout << "[*] Navicat Language Signature 1:" << std::endl;
auto s2 = static_cast<uint8_t>(read_int(0x00, 0xff, "(range: 0x00 ~ 0xFF)> ", "Invalid number."));
sn_generator.set_software_language(s1, s2);
std::cout << std::endl;
std::cout << "[*] Input major version number:" << std::endl;
sn_generator.set_software_version(read_int(0, 15, 12, "(range: 0 ~ 15, default: 12)> ", "Invalid number."));
std::cout << std::endl;
return sn_generator;
}
}
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE

View File

@@ -0,0 +1,211 @@
#include <iostream>
#include <ctime>
#include <fmt/format.h>
#include <fcntl.h>
#include "exceptions/operation_canceled_exception.hpp"
#include "exceptions/unix_exception.hpp"
#include "resource_wrapper.hpp"
#include "resource_traits/unix_os/file_descriptor.hpp"
#include "rsa_cipher.hpp"
#include "navicat_serial_generator.hpp"
#include "base64_rfc4648.hpp"
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\GenerateLicense.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
void GenerateLicenseText(const rsa_cipher& cipher, const navicat_serial_generator& sn_generator) {
std::string u8_username;
std::string u8_organization;
std::string b64_request_code;
std::vector<uint8_t> request_code;
std::string u8_request_info;
std::string u8_response_info;
std::vector<uint8_t> response_code;
std::string b64_response_code;
std::cout << "[*] Your name: ";
if (!std::getline(std::cin, u8_username)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
std::cout << "[*] Your organization: ";
if (!std::getline(std::cin, u8_organization)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
std::cout << std::endl;
std::cout << "[*] Input request code in Base64: (Double press ENTER to end)" << std::endl;
while (true) {
std::string temp;
if (!std::getline(std::cin, temp)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
if (temp.empty()) {
break;
}
b64_request_code.append(temp);
}
request_code = base64_rfc4648::decode(b64_request_code);
if (request_code.size() != 256) {
throw ::nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), fmt::format("Broken request code. %zu", request_code.size()));
}
u8_request_info.resize((cipher.bits() + 7) / 8);
u8_request_info.resize(cipher.private_decrypt(request_code.data(), request_code.size(), u8_request_info.data(), RSA_PKCS1_PADDING));
std::cout << "[*] Request Info:" << std::endl;
std::cout << u8_request_info << std::endl;
std::cout << std::endl;
rapidjson::Document json;
rapidjson::Value N_Key;
rapidjson::Value N_Value;
rapidjson::Value O_Key;
rapidjson::Value O_Value;
rapidjson::Value T_Key;
rapidjson::Value T_Value;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
//
// Begin to parse
//
json.Parse(u8_request_info.c_str());
//
// Remove "Platform" info
//
json.RemoveMember("P");
//
// Set "Name" info
//
N_Key.SetString("N", 1);
N_Value.SetString(u8_username.c_str(), static_cast<rapidjson::SizeType>(u8_username.length()));
//
// Set "Organization" info
//
O_Key.SetString("O", 1);
O_Value.SetString(u8_organization.c_str(), static_cast<rapidjson::SizeType>(u8_organization.length()));
//
// Set "Time" info
//
T_Key.SetString("T", 1);
T_Value.SetUint(static_cast<unsigned int>(std::time(nullptr)));
//
// Add "Name", "Organization" and "Time"
//
json.AddMember(N_Key, N_Value, json.GetAllocator());
json.AddMember(O_Key, O_Value, json.GetAllocator());
json.AddMember(T_Key, T_Value, json.GetAllocator());
json.Accept(writer);
if (buffer.GetSize() > 240) {
throw ::nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Response Info is too long.");
}
u8_response_info.assign(buffer.GetString(), buffer.GetSize());
std::cout << "[*] Response Info:" << std::endl;
std::cout << u8_response_info << std::endl;
std::cout << std::endl;
response_code.resize((cipher.bits() + 7) / 8);
response_code.resize(cipher.private_encrypt(u8_response_info.data(), u8_response_info.size(), response_code.data(), RSA_PKCS1_PADDING));
b64_response_code = base64_rfc4648::encode(response_code);
std::cout << "[*] Activation Code:" << std::endl;
std::cout << b64_response_code << std::endl;
std::cout << std::endl;
}
void GenerateLicenseBinary(const rsa_cipher& cipher, const navicat_serial_generator& sn_generator) {
std::string u8_serial_number = sn_generator.serial_number();
std::string u8_username;
std::string u8_organization;
std::string u8_response_info;
std::vector<uint8_t> response_code;
std::cout << "[*] Your name: ";
if (!std::getline(std::cin, u8_username)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
std::cout << "[*] Your organization: ";
if (!std::getline(std::cin, u8_organization)) {
throw exceptions::operation_canceled_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Operation is canceled by user.");
}
std::cout << std::endl;
rapidjson::Document json;
rapidjson::Value N_Key;
rapidjson::Value N_Value;
rapidjson::Value O_Key;
rapidjson::Value O_Value;
rapidjson::Value T_Key;
rapidjson::Value T_Value;
rapidjson::Value K_Key;
rapidjson::Value K_Value;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
json.Parse("{}");
K_Key.SetString("K", 1);
K_Value.SetString(u8_serial_number.c_str(), static_cast<rapidjson::SizeType>(u8_serial_number.length()));
N_Key.SetString("N", 1);
N_Value.SetString(u8_username.c_str(), static_cast<rapidjson::SizeType>(u8_username.length()));
O_Key.SetString("O", 1);
O_Value.SetString(u8_organization.c_str(), static_cast<rapidjson::SizeType>(u8_organization.length()));
T_Key.SetString("T", 1);
T_Value.SetUint(static_cast<unsigned int>(std::time(nullptr)));
json.AddMember(K_Key, K_Value, json.GetAllocator());
json.AddMember(N_Key, N_Value, json.GetAllocator());
json.AddMember(O_Key, O_Value, json.GetAllocator());
json.AddMember(T_Key, T_Value, json.GetAllocator());
json.Accept(writer);
if (buffer.GetSize() > 240) {
throw ::nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Response Info is too long.");
}
u8_response_info.assign(buffer.GetString(), buffer.GetSize());
std::cout << "[*] Response Info:" << std::endl;
std::cout << u8_response_info << std::endl;
std::cout << std::endl;
response_code.resize((cipher.bits() + 7) / 8);
response_code.resize(cipher.private_encrypt(u8_response_info.data(), u8_response_info.size(), response_code.data(), RSA_PKCS1_PADDING));
resource_wrapper license_file{ resource_traits::unix_os::file_descriptor{}, open("license_file", O_WRONLY | O_CREAT) };
if (!license_file.is_valid()) {
throw exceptions::unix_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), errno, u8"open failed.");
}
if (write(license_file.get(), response_code.data(), response_code.size()) < 0) {
throw exceptions::unix_exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), errno, u8"write failed.");
}
std::cout << "[+] license_file has been generated." << std::endl;
}
}
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE

View File

@@ -0,0 +1,122 @@
#include "base32_rfc4648.hpp"
#include <limits>
#include <algorithm>
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\base32_rfc4648.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
char base32_rfc4648::symbol(alphabet_index_t idx) {
return alphabet[idx];
}
base32_rfc4648::alphabet_index_t base32_rfc4648::reverse_symbol(char c) {
if ('A' <= c && c <= 'Z') {
return c - 'A';
} else if ('2' <= c && c <= '7') {
return c - '2' + 26;
} else {
throw decoding_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Non-base32 digit is found.");
}
}
std::string base32_rfc4648::encode(const std::vector<uint8_t>& data) {
return encode(data.data(), data.size());
}
std::string base32_rfc4648::encode(const void* data_ptr, size_t data_size) {
std::string retval;
if (data_size) {
retval.reserve((data_size * 8 + 4) / 5);
auto p = reinterpret_cast<const uint8_t*>(data_ptr);
alphabet_index_t left_bits = 0;
alphabet_index_t bit_buffer = 0;
for (size_t i = 0; i < data_size; ++i) {
bit_buffer = (bit_buffer << 8) | p[i];
left_bits += 8;
while (left_bits >= 5) {
alphabet_index_t idx = (bit_buffer >> (left_bits - 5)) & 0x1f;
retval.push_back(symbol(idx));
left_bits -= 5;
}
}
if (left_bits > 0) {
alphabet_index_t idx = (bit_buffer << (5 - left_bits)) & 0x1f;
retval.push_back(symbol(idx));
}
switch (data_size % 5) {
case 0:
break;
case 1:
retval.append(6, padding_character);
break;
case 2:
retval.append(4, padding_character);
break;
case 3:
retval.append(3, padding_character);
break;
case 4:
retval.append(1, padding_character);
break;
default:
__builtin_unreachable();
}
}
return retval;
}
std::vector<uint8_t> base32_rfc4648::decode(std::string_view b32_string) {
if (b32_string.length() % 8 == 0) {
std::vector<uint8_t> retval;
size_t count_of_padding = std::distance(b32_string.crbegin(), std::find_if_not(b32_string.crbegin(), b32_string.crend(), [](char c) -> bool { return c == padding_character; }));
switch (count_of_padding) {
case 1:
retval.reserve(b32_string.length() / 8 * 5 - (5 - 4));
break;
case 3:
retval.reserve(b32_string.length() / 8 * 5 - (5 - 3));
break;
case 4:
retval.reserve(b32_string.length() / 8 * 5 - (5 - 2));
break;
case 6:
retval.reserve(b32_string.length() / 8 * 5 - (5 - 1));
break;
default:
throw decoding_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Incorrect padding");
}
size_t count_of_encoded = b32_string.length() - count_of_padding;
alphabet_index_t left_bits = 0;
alphabet_index_t bit_buffer = 0;
for (size_t i = 0; i < count_of_encoded; ++i) {
bit_buffer = (bit_buffer << 5) | reverse_symbol(b32_string[i]);
left_bits += 5;
while (left_bits >= 8) {
auto val = static_cast<uint8_t>((bit_buffer >> (left_bits - 8)) & 0xff);
retval.push_back(val);
left_bits -= 8;
}
}
return retval;
} else {
throw decoding_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Incorrect padding");
}
}
}
#undef NKG_CURRENT_SOURCE_LINE
#undef NKG_CURRENT_SOURCE_FILE

View File

@@ -0,0 +1,31 @@
#pragma once
#include <string>
#include <vector>
#include "exception.hpp"
namespace nkg {
struct base32_rfc4648 {
using alphabet_index_t = size_t;
static constexpr const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static constexpr const char padding_character = '=';
class decoding_error : public ::nkg::exception {
public:
decoding_error(std::string_view file, int line, std::string_view message) noexcept :
::nkg::exception(file, line, message) {}
};
static char symbol(alphabet_index_t idx);
static alphabet_index_t reverse_symbol(char c);
static std::string encode(const std::vector<uint8_t>& data);
static std::string encode(const void* data_ptr, size_t data_size);
static std::vector<uint8_t> decode(std::string_view b32_string);
};
}

View File

@@ -0,0 +1,99 @@
#include "base64_rfc4648.hpp"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "resource_wrapper.hpp"
#include "resource_traits/openssl/bio.hpp"
#include "resource_traits/openssl/bio_chain.hpp"
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\base64_rfc4648.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
std::string base64_rfc4648::encode(const std::vector<std::uint8_t>& data) {
resource_wrapper bio_b64{ resource_traits::openssl::bio_chain{}, BIO_new(BIO_f_base64()) };
if (!bio_b64.is_valid()) {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_new failed.");
}
BIO_set_flags(bio_b64.get(), BIO_FLAGS_BASE64_NO_NL);
resource_wrapper bio_memory{ resource_traits::openssl::bio{}, BIO_new(BIO_s_mem()) };
if (!bio_memory.is_valid()) {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_new failed.");
}
BIO_push(bio_b64.get(), bio_memory.get());
for (size_t written_size = 0, left_size = data.size(); left_size != 0;) {
int size_to_write = static_cast<int>(std::min(left_size, static_cast<size_t>(INT_MAX)));
int r = BIO_write(bio_b64.get(), data.data() + written_size, size_to_write);
if (r > 0) {
written_size += r;
left_size -= r;
} else {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_write failed.");
}
}
BIO_flush(bio_b64.get());
const char* pch = nullptr;
long lch = BIO_get_mem_data(bio_memory.get(), &pch);
bio_memory.discard(); // the bio_chain `bio_b64` will free it
return std::string(pch, lch);
}
std::vector<uint8_t> base64_rfc4648::decode(std::string_view b64_string) {
resource_wrapper bio_b64{ resource_traits::openssl::bio_chain{}, BIO_new(BIO_f_base64()) };
if (!bio_b64.is_valid()) {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_new failed.");
}
BIO_set_flags(bio_b64.get(), BIO_FLAGS_BASE64_NO_NL);
resource_wrapper bio_memory{ resource_traits::openssl::bio{}, BIO_new(BIO_s_mem()) };
if (!bio_memory.is_valid()) {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_new failed.");
}
BIO_push(bio_b64.get(), bio_memory.get());
for (size_t written_length = 0, left_length = b64_string.length(); left_length != 0;) {
int length_to_write = static_cast<int>(std::min(left_length, static_cast<size_t>(INT_MAX)));
int r = BIO_write(bio_memory.get(), b64_string.data() + written_length, length_to_write);
if (r > 0) {
written_length += r;
left_length -= r;
} else {
throw backend_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"BIO_write failed.");
}
}
std::vector<uint8_t> retval;
retval.reserve(b64_string.length() * 3 / 4 + 1);
for (uint8_t buf[256];;) {
auto len = BIO_read(bio_b64.get(), buf, sizeof(buf));
if (len > 0) {
retval.insert(retval.end(), buf, buf + len);
} else {
break;
}
}
bio_memory.discard(); // the bio_chain `bio_b64` will free it
return retval;
}
}
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE

View File

@@ -0,0 +1,20 @@
#pragma once
#include <string>
#include <vector>
#include "exception.hpp"
namespace nkg {
struct base64_rfc4648 {
class backend_error : public ::nkg::exception {
public:
backend_error(std::string_view file, int line, std::string_view message) noexcept :
::nkg::exception(file, line, message) {}
};
static std::string encode(const std::vector<std::uint8_t>& data);
static std::vector<uint8_t> decode(std::string_view str_b64);
};
}

123
navicat-keygen/main.cpp Normal file
View File

@@ -0,0 +1,123 @@
#include <stdio.h>
#include <string.h>
#include <functional>
#include "exception.hpp"
#include "exceptions/operation_canceled_exception.hpp"
#include "base64_rfc4648.hpp"
#include "navicat_serial_generator.hpp"
#include "rsa_cipher.hpp"
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\wmain.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
using fnCollectInformation = std::function<navicat_serial_generator()>;
using fnGenerateLicense = std::function<void(const rsa_cipher& cipher, const navicat_serial_generator& generator)>;
navicat_serial_generator CollectInformationNormal();
navicat_serial_generator CollectInformationAdvanced();
void GenerateLicenseText(const rsa_cipher& cipher, const navicat_serial_generator& sn_generator);
void GenerateLicenseBinary(const rsa_cipher& cipher, const navicat_serial_generator& sn_generator);
}
void welcome() {
puts("***************************************************");
puts("* navicat-keygen by @DoubleLabyrinth *");
puts("* version: 16.0.7.0 *");
puts("***************************************************");
puts("");
}
void help() {
puts("Usage:");
puts(" navicat-keygen.exe <-bin|-text> [-adv] <RSA-2048 Private Key File>");
puts("");
puts(" <-bin|-text> Specify \"-bin\" to generate \"license_file\" used by Navicat 11.");
puts(" Specify \"-text\" to generate base64-encoded activation code.");
puts(" This parameter must be specified.");
puts("");
puts(" [-adv] Enable advance mode.");
puts(" This parameter is optional.");
puts("");
puts(" <RSA-2048 Private Key File> A path to an RSA-2048 private key file.");
puts(" This parameter must be specified.");
puts("");
puts("Example:");
puts(" navicat-keygen.exe -text .\\RegPrivateKey.pem");
}
int main(int argc, char* argv[]) {
welcome();
if (argc == 3 || argc == 4) {
nkg::fnCollectInformation lpfnCollectInformation;
nkg::fnGenerateLicense lpfnGenerateLicense;
if (strcmp(argv[1], "-bin") == 0) {
lpfnGenerateLicense = nkg::GenerateLicenseBinary;
} else if (strcmp(argv[1], "-text") == 0) {
lpfnGenerateLicense = nkg::GenerateLicenseText;
} else {
help();
return -1;
}
if (argc == 4) {
if (strcmp(argv[2], "-adv") == 0) {
lpfnCollectInformation = nkg::CollectInformationAdvanced;
} else {
help();
return -1;
}
} else {
lpfnCollectInformation = nkg::CollectInformationNormal;
}
try {
nkg::rsa_cipher cipher;
cipher.import_private_key_file(argv[argc - 1]);
if (cipher.bits() != 2048) {
throw nkg::exception(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"RSA key length mismatches.")
.push_hint(u8"You must provide an RSA key whose modulus length is 2048 bits.");
}
auto sn_generator = lpfnCollectInformation();
sn_generator.generate();
puts("[*] Serial number:");
puts(sn_generator.serial_number_formatted().c_str());
puts("");
lpfnGenerateLicense(cipher, sn_generator);
return 0;
} catch (nkg::exceptions::operation_canceled_exception&) {
return -1;
} catch (nkg::exception& e) {
printf("[-] %s:%d ->\n", e.source_file().c_str(), e.source_line());
printf(" %s\n", e.custom_message().c_str());
if (e.error_code_exists()) {
printf(" %s (0x%zx)\n", e.error_string().c_str(), e.error_code());
}
for (auto& hint : e.hints()) {
printf(" Hints: %s\n", hint.c_str());
}
return -1;
} catch (std::exception& e) {
printf("[-] %s\n", e.what());
return -1;
}
} else {
help();
return -1;
}
}
#undef NKG_CURRENT_SOURCE_FILE
#undef NKG_CURRENT_SOURCE_LINE

View File

@@ -0,0 +1,160 @@
#include "navicat_serial_generator.hpp"
#include <fmt/format.h>
#include <openssl/rand.h>
#include <algorithm>
#include "base32_rfc4648.hpp"
#define NKG_CURRENT_SOURCE_FILE() u8".\\navicat-keygen\\navicat_serial_generator.cpp"
#define NKG_CURRENT_SOURCE_LINE() __LINE__
namespace nkg {
char navicat_serial_generator::_replace_confusing_chars(char c) {
if (c == 'I') {
return '8';
} else if (c == 'O') {
return '9';
} else {
return c;
}
};
navicat_serial_generator::navicat_serial_generator() noexcept :
m_data{ 0x68 , 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32 }, m_des_key{} {}
void navicat_serial_generator::set_software_language(navicat_software_language lang) noexcept {
switch (lang) {
case navicat_software_language::English:
m_data[5] = 0xAC; // Must be 0xAC for English version.
m_data[6] = 0x88; // Must be 0x88 for English version.
break;
case navicat_software_language::SimplifiedChinese:
m_data[5] = 0xCE; // Must be 0xCE for Simplified Chinese version.
m_data[6] = 0x32; // Must be 0x32 for Simplified Chinese version.
break;
case navicat_software_language::TraditionalChinese:
m_data[5] = 0xAA; // Must be 0xAA for Traditional Chinese version.
m_data[6] = 0x99; // Must be 0x99 for Traditional Chinese version.
break;
case navicat_software_language::Japanese:
m_data[5] = 0xAD; // Must be 0xAD for Japanese version. Discoverer: @dragonflylee
m_data[6] = 0x82; // Must be 0x82 for Japanese version. Discoverer: @dragonflylee
break;
case navicat_software_language::Polish:
m_data[5] = 0xBB; // Must be 0xBB for Polish version. Discoverer: @dragonflylee
m_data[6] = 0x55; // Must be 0x55 for Polish version. Discoverer: @dragonflylee
break;
case navicat_software_language::Spanish:
m_data[5] = 0xAE; // Must be 0xAE for Spanish version. Discoverer: @dragonflylee
m_data[6] = 0x10; // Must be 0x10 for Spanish version. Discoverer: @dragonflylee
break;
case navicat_software_language::French:
m_data[5] = 0xFA; // Must be 0xFA for French version. Discoverer: @Deltafox79
m_data[6] = 0x20; // Must be 0x20 for French version. Discoverer: @Deltafox79
break;
case navicat_software_language::German:
m_data[5] = 0xB1; // Must be 0xB1 for German version. Discoverer: @dragonflylee
m_data[6] = 0x60; // Must be 0x60 for German version. Discoverer: @dragonflylee
break;
case navicat_software_language::Korean:
m_data[5] = 0xB5; // Must be 0xB5 for Korean version. Discoverer: @dragonflylee
m_data[6] = 0x60; // Must be 0x60 for Korean version. Discoverer: @dragonflylee
break;
case navicat_software_language::Russian:
m_data[5] = 0xEE; // Must be 0xB5 for Russian version. Discoverer: @dragonflylee
m_data[6] = 0x16; // Must be 0x60 for Russian version. Discoverer: @dragonflylee
break;
case navicat_software_language::Portuguese:
m_data[5] = 0xCD; // Must be 0xCD for Portuguese version. Discoverer: @dragonflylee
m_data[6] = 0x49; // Must be 0x49 for Portuguese version. Discoverer: @dragonflylee
break;
default:
__builtin_unreachable();
}
}
void navicat_serial_generator::set_software_language(uint8_t lang_sig0, uint8_t lang_sig1) noexcept {
m_data[5] = lang_sig0;
m_data[6] = lang_sig1;
}
void navicat_serial_generator::set_software_type(navicat_software_type software_type) noexcept {
switch (software_type) {
case navicat_software_type::DataModeler:
m_data[7] = 0x84;
break;
case navicat_software_type::Premium:
m_data[7] = 0x65;
break;
case navicat_software_type::MySQL:
m_data[7] = 0x68;
break;
case navicat_software_type::PostgreSQL:
m_data[7] = 0x6C;
break;
case navicat_software_type::Oracle:
m_data[7] = 0x70;
break;
case navicat_software_type::SQLServer:
m_data[7] = 0x74;
break;
case navicat_software_type::SQLite:
m_data[7] = 0x78;
break;
case navicat_software_type::MariaDB:
m_data[7] = 0x7C;
break;
case navicat_software_type::MongoDB:
m_data[7] = 0x80;
break;
case navicat_software_type::ReportViewer:
m_data[7] = 0xb;
break;
default:
__builtin_unreachable();
}
}
void navicat_serial_generator::set_software_type(uint8_t software_type_sig) noexcept {
m_data[7] = software_type_sig;
}
void navicat_serial_generator::set_software_version(int ver) {
if (11 <= ver && ver < 16) {
m_data[8] = static_cast<std::uint8_t>((ver << 4) | (m_data[8] & 0x0f));
memcpy(m_des_key, s_des_key0, sizeof(s_des_key0));
} else if (16 <= ver && ver < 32) {
m_data[8] = static_cast<std::uint8_t>(((ver - 16) << 4) | (m_data[8] & 0x0f));
memcpy(m_des_key, s_des_key1, sizeof(s_des_key1));
} else {
throw version_error(NKG_CURRENT_SOURCE_FILE(), NKG_CURRENT_SOURCE_LINE(), u8"Invalid navicat version.");
}
}
void navicat_serial_generator::generate() {
RAND_bytes(m_data + 2, 3);
DES_key_schedule schedule;
DES_set_key_unchecked(&m_des_key, &schedule);
DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(m_data + 2), reinterpret_cast<const_DES_cblock*>(m_data + 2), &schedule, DES_ENCRYPT);
m_serial_number = base32_rfc4648::encode(m_data, sizeof(m_data));
std::transform(m_serial_number.begin(), m_serial_number.end(), m_serial_number.begin(), _replace_confusing_chars);
std::string_view sn = m_serial_number;
m_serial_number_formatted = fmt::format("{}-{}-{}-{}", sn.substr(0, 4), sn.substr(4, 4), sn.substr(8, 4), sn.substr(12, 4));
}
[[nodiscard]]
const std::string& navicat_serial_generator::serial_number() const noexcept {
return m_serial_number;
}
[[nodiscard]]
const std::string& navicat_serial_generator::serial_number_formatted() const noexcept {
return m_serial_number_formatted;
}
}
#undef NKG_CURRENT_SOURCE_LINE
#undef NKG_CURRENT_SOURCE_FILE

View File

@@ -0,0 +1,75 @@
#pragma once
#include <string>
#include <vector>
#include <openssl/des.h>
#include "exception.hpp"
namespace nkg {
enum class navicat_software_language {
English,
SimplifiedChinese,
TraditionalChinese,
Japanese,
Polish,
Spanish,
French,
German,
Korean,
Russian,
Portuguese
};
enum class navicat_software_type {
DataModeler,
Premium,
MySQL,
PostgreSQL,
Oracle,
SQLServer,
SQLite,
MariaDB,
MongoDB,
ReportViewer
};
class navicat_serial_generator {
public:
class version_error : public ::nkg::exception {
public:
version_error(std::string_view file, int line, std::string_view message) noexcept :
::nkg::exception(file, line, message) {}
};
private:
static inline const DES_cblock s_des_key0 = { 0x64, 0xAD, 0xF3, 0x2F, 0xAE, 0xF2, 0x1A, 0x27 };
static inline const DES_cblock s_des_key1 = { 0xE9, 0x7F, 0xB0, 0x60, 0x77, 0x45, 0x90, 0xAE };
uint8_t m_data[10];
DES_cblock m_des_key;
std::string m_serial_number;
std::string m_serial_number_formatted;
static char _replace_confusing_chars(char c);
public:
navicat_serial_generator() noexcept;
void set_software_language(navicat_software_language lang) noexcept;
void set_software_language(uint8_t lang_sig0, uint8_t lang_sig1) noexcept;
void set_software_type(navicat_software_type software_type) noexcept;
void set_software_type(uint8_t software_type_sig) noexcept;
void set_software_version(int Version);
void generate();
[[nodiscard]]
const std::string& serial_number() const noexcept;
[[nodiscard]]
const std::string& serial_number_formatted() const noexcept;
};
}