Compare commits

...

3 Commits

Author SHA1 Message Date
e34a192f1c chore: bump version to v0.6.1 2024-12-22 01:52:36 +09:00
fa80c2b4cd docs: update build command examples 2024-12-22 01:52:36 +09:00
4e710c27e7 build: use system sqlite3 if available 2024-12-22 01:52:36 +09:00
10 changed files with 166 additions and 22 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
build/ build/
.cache/ .cache/
cmake-build-* cmake-build-*
.vscode/

View File

@ -1,19 +1,27 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.14)
project(kgg-dec VERSION 0.6.0 LANGUAGES CXX) project(kgg-dec VERSION 0.6.1 LANGUAGES CXX)
option(USE_WIN_SQLITE3 "Use Windows SQLite3 (MSVC Only)" ${MSVC}) option(USE_SYSTEM_SQLITE3 "Use system SQLite3 (if not using WinSQLite3)" ON)
option(USE_WIN_CRYPTO "Use Windows Crypto API" ${WIN32}) option(USE_OPENSSL "Use OpenSSL API (if not using WinCrypto API)" ON)
if(WIN32)
option(USE_WIN_SQLITE3 "Use Windows SQLite3 (MSVC Only)" ${MSVC})
option(USE_WIN_CRYPTO "Use Windows Crypto API" ${WIN32})
else()
set(USE_WIN_SQLITE3 OFF)
set(USE_WIN_CRYPTO OFF)
endif()
# Setup CryptoAPI
if (NOT USE_WIN_CRYPTO AND USE_OPENSSL)
find_package(OpenSSL REQUIRED)
endif()
include(cmake/SetupSQLite3.cmake)
add_subdirectory(third-party/aes) add_subdirectory(third-party/aes)
add_subdirectory(third-party/md5) add_subdirectory(third-party/md5)
include(cmake/FindWinSQLite3.cmake)
if (NOT WinSQLite3_Found)
message("including sqlite3 to the build")
add_subdirectory(third-party/sqlite3)
endif ()
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -35,19 +43,29 @@ target_include_directories(kgg-dec
src/tc_tea src/tc_tea
) )
# Base crypto implementations
target_link_libraries(kgg-dec PRIVATE libaes libmd5) target_link_libraries(kgg-dec PRIVATE libaes libmd5)
if (USE_WIN_CRYPTO)
target_compile_definitions(kgg-dec PRIVATE USE_WIN_CRYPTO=1)
elseif(USE_OPENSSL)
target_compile_definitions(kgg-dec PRIVATE USE_OPENSSL=1)
endif ()
# Win32 specific
if (WIN32) if (WIN32)
target_link_libraries(kgg-dec PRIVATE shell32 ole32) target_link_libraries(kgg-dec PRIVATE shell32 ole32)
target_compile_definitions(kgg-dec PRIVATE NOMINMAX)
endif () endif ()
# SQLite3
if (WinSQLite3_Found) if (WinSQLite3_Found)
target_link_libraries(kgg-dec PRIVATE WinSQLite3) target_link_libraries(kgg-dec PRIVATE WinSQLite3)
target_include_directories(kgg-dec PRIVATE ${WindowsKitInclude}) target_include_directories(kgg-dec PRIVATE ${WindowsKitInclude})
elseif(SQLite3_FOUND)
target_link_libraries(kgg-dec PRIVATE SQLite::SQLite3)
else () else ()
target_link_libraries(kgg-dec PRIVATE sqlite3) target_link_libraries(kgg-dec PRIVATE sqlite3)
endif () endif ()
target_compile_definitions(kgg-dec PRIVATE NOMINMAX)
target_compile_definitions(kgg-dec PRIVATE KGGDEC_PROJECT_VERSION="${PROJECT_VERSION}")
if (USE_WIN_CRYPTO) # Extra definitions
target_compile_definitions(kgg-dec PRIVATE USE_WIN_CRYPTO=1) target_compile_definitions(kgg-dec PRIVATE KGGDEC_PROJECT_VERSION="${PROJECT_VERSION}")
endif ()

View File

@ -56,6 +56,22 @@ CMake 支持以下参数:
- `USE_WIN_SQLITE3` - 使用 Windows 内置的 SQLite3 链接库(仅限 Windows + MSVC 编译环境)。 - `USE_WIN_SQLITE3` - 使用 Windows 内置的 SQLite3 链接库(仅限 Windows + MSVC 编译环境)。
- `USE_WIN_CRYPTO` - 使用 Windows 内置的加密/哈希实现,而非软件实现(仅限 Windows 目标)。 - `USE_WIN_CRYPTO` - 使用 Windows 内置的加密/哈希实现,而非软件实现(仅限 Windows 目标)。
- `USE_SYSTEM_SQLITE3` - 使用外部的 SQLite3 实现 (Debian: `libsqlite3-dev`),找不到时会报错。
- `USE_OpenSSL` - 使用 OpenSSL 的加密/哈希实现 (Debian: `libssl-dev`),找不到时会报错。
Ubuntu 下编译发布版,不使用外部库:
```sh
cmake -G "Ninja Multi-Config" -B build/linux-all -DUSE_SYSTEM_SQLITE3=0 -DUSE_OPENSSL=0
cmake --build build/linux-all --config Release -j
```
Ubuntu 下编译发布版,链接到现有的库:
```sh
cmake -G "Ninja Multi-Config" -B build/linux-ext -DUSE_SYSTEM_SQLITE3=1 -DUSE_OPENSSL=1
cmake --build build/linux-ext --config Release -j
```
### 第三方软件 ### 第三方软件

View File

@ -12,3 +12,13 @@ if (MSVC AND USE_WIN_SQLITE3)
message("Using WinSQLite3 from Windows SDK (${WindowsKitVersion}).") message("Using WinSQLite3 from Windows SDK (${WindowsKitVersion}).")
endif () endif ()
endif () endif ()
if (NOT WinSQLite3_Found)
if (USE_SYSTEM_SQLITE3)
message("Using existing SQLite3.")
find_package(SQLite3 REQUIRED)
else()
message("including sqlite3 to the build")
add_subdirectory(third-party/sqlite3)
endif()
endif()

View File

@ -7,10 +7,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(SOURCES) set(SOURCES)
if (USE_WIN_CRYPTO) if (USE_WIN_CRYPTO)
message("Using Windows Crypto API for AES-CBC-128")
list(APPEND SOURCES aes_win32.cpp) list(APPEND SOURCES aes_win32.cpp)
elseif (USE_OPENSSL)
message("Using OpenSSL API for AES-CBC-128")
find_package(OpenSSL REQUIRED)
list(APPEND SOURCES aes_openssl.cpp)
else () else ()
# Tiny AES in C (https://github.com/kokke/tiny-AES-c/) # Tiny AES in C (https://github.com/kokke/tiny-AES-c/)
# is licensed under the Unlicense license. # is licensed under the Unlicense license.
message("Using included AES-CBC-128 implementation")
list(APPEND SOURCES aes.cpp) list(APPEND SOURCES aes.cpp)
endif () endif ()
@ -23,4 +29,7 @@ target_include_directories(libaes
if (USE_WIN_CRYPTO) if (USE_WIN_CRYPTO)
target_link_libraries(libaes PRIVATE bcrypt) target_link_libraries(libaes PRIVATE bcrypt)
target_compile_definitions(libaes PRIVATE USE_WIN_CRYPTO=1) target_compile_definitions(libaes PRIVATE USE_WIN_CRYPTO=1)
elseif (USE_OPENSSL)
target_link_libraries(libaes PRIVATE OpenSSL::Crypto)
target_compile_definitions(libaes PRIVATE USE_OPENSSL=1)
endif () endif ()

View File

@ -7,6 +7,8 @@
#include <windows.h> #include <windows.h>
#include <bcrypt.h> #include <bcrypt.h>
#elif USE_OPENSSL
#include <openssl/evp.h>
#endif #endif
namespace AES { namespace AES {
@ -20,6 +22,8 @@ struct AES_ctx {
BCRYPT_ALG_HANDLE hAlg; BCRYPT_ALG_HANDLE hAlg;
BCRYPT_KEY_HANDLE hKey; BCRYPT_KEY_HANDLE hKey;
uint8_t iv[0x10]; uint8_t iv[0x10];
#elif USE_OPENSSL
EVP_CIPHER_CTX* cipher_ctx;
#else #else
uint8_t RoundKey[kKeyExpansionSize]; uint8_t RoundKey[kKeyExpansionSize];
uint8_t Iv[16]; uint8_t Iv[16];
@ -35,7 +39,7 @@ bool AES_init_ctx_iv(AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
size_t AES_CBC_encrypt_buffer(AES_ctx* ctx, uint8_t* buf, size_t length); size_t AES_CBC_encrypt_buffer(AES_ctx* ctx, uint8_t* buf, size_t length);
size_t AES_CBC_decrypt_buffer(AES_ctx* ctx, uint8_t* buf, size_t length); size_t AES_CBC_decrypt_buffer(AES_ctx* ctx, uint8_t* buf, size_t length);
#if USE_WIN_CRYPTO #if USE_WIN_CRYPTO || USE_OPENSSL
bool AES_cleanup(AES_ctx* ctx); bool AES_cleanup(AES_ctx* ctx);
#else #else
inline bool AES_cleanup(AES_ctx* ctx) { inline bool AES_cleanup(AES_ctx* ctx) {

43
third-party/aes/aes_openssl.cpp vendored Normal file
View File

@ -0,0 +1,43 @@
#include <cassert>
#include <cstring>
#include "aes.h"
namespace AES {
bool AES_init_ctx_iv(AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) {
ctx->cipher_ctx = EVP_CIPHER_CTX_new();
if (!ctx->cipher_ctx) {
return false;
}
if (EVP_DecryptInit_ex(ctx->cipher_ctx, EVP_aes_128_cbc(), nullptr, key, iv) != 1) {
AES_cleanup(ctx);
return false;
}
EVP_CIPHER_CTX_set_padding(ctx->cipher_ctx, 0);
return true;
}
size_t AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) {
// not implemented
return 0;
}
size_t AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) {
auto buf_len = static_cast<int>(length);
EVP_DecryptUpdate(ctx->cipher_ctx, buf, &buf_len, buf, buf_len);
assert(buf_len == length && "AES_CBC_decrypt_buffer: buffer length mismatch");
return buf_len;
}
bool AES_cleanup(AES_ctx* ctx) {
if (ctx->cipher_ctx) {
EVP_CIPHER_CTX_free(ctx->cipher_ctx);
ctx->cipher_ctx = nullptr;
}
return true;
}
} // namespace AES

View File

@ -7,10 +7,16 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(SOURCES) set(SOURCES)
if (USE_WIN_CRYPTO) if (USE_WIN_CRYPTO)
message("Using Windows Crypto API for MD5")
list(APPEND SOURCES md5_win32.cpp) list(APPEND SOURCES md5_win32.cpp)
elseif (USE_OPENSSL)
message("Using OpenSSL API for MD5")
find_package(OpenSSL REQUIRED)
list(APPEND SOURCES md5_openssl.cpp)
else () else ()
# Derived from the "RSA Data Security, Inc. MD5 Message-Digest Algorithm": # Derived from the "RSA Data Security, Inc. MD5 Message-Digest Algorithm":
# https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/kern/md5c.c # https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/kern/md5c.c
message("Using included MD5 implementation")
list(APPEND SOURCES md5.cpp) list(APPEND SOURCES md5.cpp)
endif () endif ()
@ -24,4 +30,7 @@ target_include_directories(libmd5
if (USE_WIN_CRYPTO) if (USE_WIN_CRYPTO)
target_link_libraries(libmd5 PRIVATE crypt32) target_link_libraries(libmd5 PRIVATE crypt32)
target_compile_definitions(libmd5 PRIVATE USE_WIN_CRYPTO=1) target_compile_definitions(libmd5 PRIVATE USE_WIN_CRYPTO=1)
elseif (USE_OPENSSL)
target_link_libraries(libmd5 PRIVATE OpenSSL::Crypto)
target_compile_definitions(libmd5 PRIVATE USE_OPENSSL=1)
endif () endif ()

14
third-party/md5/md5.h vendored
View File

@ -1,21 +1,23 @@
#pragma once #pragma once
#include <cstdint>
#if USE_WIN_CRYPTO #if USE_WIN_CRYPTO
#include <windows.h> #include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
#elif USE_OPENSSL
#include <openssl/evp.h>
#endif #endif
#include <cstdint>
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16 #define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
struct MD5_CTX { struct MD5_CTX {
#if USE_WIN_CRYPTO #if USE_WIN_CRYPTO
HCRYPTPROV hProv; HCRYPTPROV hProv;
HCRYPTHASH hHash; HCRYPTHASH hHash;
#elif USE_OPENSSL
EVP_MD_CTX* md_ctx;
#else #else
uint64_t count; /* number of bits, modulo 2^64 (lsb first) */ uint64_t count; /* number of bits, modulo 2^64 (lsb first) */
uint32_t state[4]; /* state (ABCD) */ uint32_t state[4]; /* state (ABCD) */
@ -23,8 +25,8 @@ struct MD5_CTX {
#endif #endif
}; };
#if USE_WIN_CRYPTO #if USE_WIN_CRYPTO || USE_OPENSSL
bool md5_init(MD5_CTX* context); bool md5_init(MD5_CTX* ctx);
bool md5_cleanup(MD5_CTX* ctx); bool md5_cleanup(MD5_CTX* ctx);
#else #else
/* MD5 initialization. Begins an MD5 operation, writing a new context. */ /* MD5 initialization. Begins an MD5 operation, writing a new context. */

32
third-party/md5/md5_openssl.cpp vendored Normal file
View File

@ -0,0 +1,32 @@
#include <openssl/evp.h>
#include <cstring>
#include "md5.h"
bool md5_init(MD5_CTX* ctx) {
memset(ctx, 0, sizeof(*ctx));
ctx->md_ctx = EVP_MD_CTX_new();
if (!ctx->md_ctx) {
return false;
}
return EVP_DigestInit_ex(ctx->md_ctx, EVP_md5(), nullptr) == 1;
}
bool md5_cleanup(MD5_CTX* ctx) {
if (ctx->md_ctx != nullptr) {
EVP_MD_CTX_free(ctx->md_ctx);
}
memset(ctx, 0xcc, sizeof(*ctx));
return true;
}
void md5_update(MD5_CTX* ctx, const uint8_t* in, size_t len) {
EVP_DigestUpdate(ctx->md_ctx, in, len);
}
void md5_final(MD5_CTX* ctx, uint8_t* digest) {
unsigned int len{MD5_DIGEST_LENGTH};
EVP_DigestFinal_ex(ctx->md_ctx, digest, &len);
EVP_MD_CTX_reset(ctx->md_ctx);
}