From c70db96eab988634cf33c40276d5936c41c17a79 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Mon, 14 Nov 2016 16:27:51 +0700 Subject: [PATCH] Added CN3 encryption - Source: https://github.com/iebb/HonokaMiku/commit/9f904b71530b3430f1777593a51011270bdd5a82 - It's unknown if it works for real SIF CNv3 assets file --- Makefile | 10 +++++++-- VersionInfo.rc | 6 +++--- sln/HonokaMiku.vcxproj | 1 + sln/HonokaMiku.vcxproj.filters | 3 +++ src/CN_Decrypter.cc | 39 ++++++++++++++++++++++++++++++++++ src/DecrypterContext.h | 31 +++++++++++++++++++++------ src/Helper.cc | 18 +++++++++++++--- src/HonokaMiku.cc | 25 ++++++++++++++-------- src/V1_Decrypter.cc | 5 +++++ src/V2_Decrypter.cc | 5 +++++ src/V3_Decrypter.cc | 5 +++++ 11 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 src/CN_Decrypter.cc diff --git a/Makefile b/Makefile index 9a467bf..1e94617 100644 --- a/Makefile +++ b/Makefile @@ -47,8 +47,8 @@ DEBUG_MSV_CMD := NDK_DEBUG := # Files -GCC_FILES=V1_Decrypter.o V2_Decrypter.o V3_Decrypter.o EN_Decrypter.o JP_Decrypter.o Helper.o HonokaMiku.o -MSVC_FILES=V1_Decrypter.obj V2_Decrypter.obj V3_Decrypter.obj EN_Decrypter.obj JP_Decrypter.obj Helper.obj HonokaMiku.obj VersionInfo.res +GCC_FILES=V1_Decrypter.o V2_Decrypter.o V3_Decrypter.o EN_Decrypter.o JP_Decrypter.o CN_Decrypter.o Helper.o HonokaMiku.o +MSVC_FILES=V1_Decrypter.obj V2_Decrypter.obj V3_Decrypter.obj EN_Decrypter.obj JP_Decrypter.obj CN_Decrypter.obj Helper.obj HonokaMiku.obj VersionInfo.res # Rules all: honokamiku @@ -96,6 +96,12 @@ clean: # Object files # .o for GCC # .obj for MSVC +CN_Decrypter.o: + $(xPREFIX)g++ -c $(RELEASE_GCC_CMD) $(DEBUG_GCC_CMD) $(CXXFLAGS) src/CN_Decrypter.cc + +CN_Decrypter.obj: + cl -nologo -W3 -Zc:wchar_t -Za $(RELEASE_MSV_CMD) -wd"4996" -D"WIN32" -D"_CONSOLE" -EHsc -c $(CFLAGS) src/CN_Decrypter.cc + EN_Decrypter.o: $(xPREFIX)g++ -c $(RELEASE_GCC_CMD) $(DEBUG_GCC_CMD) $(CXXFLAGS) src/EN_Decrypter.cc diff --git a/VersionInfo.rc b/VersionInfo.rc index 46b44f2..eaef9d7 100644 --- a/VersionInfo.rc +++ b/VersionInfo.rc @@ -4,10 +4,10 @@ #define _STR2(x) _DEPSTR1(x) #define HONOKAMIKU_VERSION_MAJOR 4 -#define HONOKAMIKU_VERSION_MINOR 0 -#define HONOKAMIKU_VERSION_PATCH 2 +#define HONOKAMIKU_VERSION_MINOR 1 +#define HONOKAMIKU_VERSION_PATCH 0 #define HONOKAMIKU_VERSION_STRING "" _STR2(HONOKAMIKU_VERSION_MAJOR) "." _STR2(HONOKAMIKU_VERSION_MINOR) "." _STR2(HONOKAMIKU_VERSION_PATCH) "" -#define HONOKAMIKU_VERSION_STRING_RC "4.0.2.0" +#define HONOKAMIKU_VERSION_STRING_RC "4.1.0.0" #define HONOKAMIKU_VERSION ((HONOKAMIKU_VERSION_MAJOR*100000000)+(HONOKAMIKU_VERSION_MINOR*100000)+(HONOKAMIKU_VERSION_PATCH)) #ifdef RC_INVOKED diff --git a/sln/HonokaMiku.vcxproj b/sln/HonokaMiku.vcxproj index eecf314..a072df5 100644 --- a/sln/HonokaMiku.vcxproj +++ b/sln/HonokaMiku.vcxproj @@ -167,6 +167,7 @@ + diff --git a/sln/HonokaMiku.vcxproj.filters b/sln/HonokaMiku.vcxproj.filters index 44842b4..c3b4c41 100644 --- a/sln/HonokaMiku.vcxproj.filters +++ b/sln/HonokaMiku.vcxproj.filters @@ -25,6 +25,9 @@ Decrypter + + Decrypter + diff --git a/src/CN_Decrypter.cc b/src/CN_Decrypter.cc new file mode 100644 index 0000000..d8f46c4 --- /dev/null +++ b/src/CN_Decrypter.cc @@ -0,0 +1,39 @@ +/** +* CN_Decrypter.cc +* SIF CN game files related things +**/ + +#include "DecrypterContext.h" +static const unsigned int cn_key_tables[64] = { + 0x1b695658u, 0x0a43a213u, 0x0ead0863u, 0x1400056du, + 0xd470461du, 0xb6152300u, 0xfbe054bcu, 0x9ac9f112u, + 0x23d3cab6u, 0xcd8fe028u, 0x6905bd74u, 0x01a3a612u, + 0x6e96a579u, 0x333d7ad1u, 0xb6688bffu, 0x29160495u, + 0xd7743bcfu, 0x8ede97bbu, 0xcacb7e8du, 0x24d81c23u, + 0xdbfc6947u, 0xb07521c8u, 0xf506e2aeu, 0x3f48df2fu, + 0x52beb172u, 0x695935e8u, 0x13e2a0a9u, 0xe2edf409u, + 0x96cba5c1u, 0xdbb1e890u, 0x4c2af968u, 0x17fd17c6u, + 0x1b9af5a8u, 0x97c0bc25u, 0x8413c879u, 0xd9b13fe1u, + 0x4066a948u, 0x9662023au, 0x74a4feeeu, 0x1f24b4f6u, + 0x637688c8u, 0x7a7ccf70u, 0x91042eecu, 0x57edd02cu, + 0x666da2ddu, 0x92839de9u, 0x43baa9edu, 0x024a8e2cu, + 0xd4ee7b72u, 0x34c18b72u, 0x13b275c4u, 0xed506a6eu, + 0xbc1c29b9u, 0xfa66a220u, 0xc2364de3u, 0x767e52b2u, + 0xe2d32439u, 0xe6f0cef5u, 0xd18c8687u, 0x14bba295u, + 0xcd84d15bu, 0xa0290f82u, 0xd3e95afcu, 0x9c6a97b4u +}; + +HonokaMiku::CN3_Dctx::CN3_Dctx(const void* header, const char* filename): HonokaMiku::V3_Dctx(HonokaMiku::GetPrefixFromGameId(7), cn_key_tables, header, filename) {} + + +void HonokaMiku::CN3_Dctx::final_setup(const char* filename, const void* block_rest) +{ + finalDecryptV3(this, 1847, filename, block_rest); +} + +HonokaMiku::CN3_Dctx* HonokaMiku::CN3_Dctx::encrypt_setup(const char* filename,void* hdr_out) +{ + CN3_Dctx* dctx = new CN3_Dctx; + setupEncryptV3(dctx, HonokaMiku::GetPrefixFromGameId(7), cn_key_tables, 1847, filename, hdr_out); + return dctx; +} diff --git a/src/DecrypterContext.h b/src/DecrypterContext.h index 0d4e9e9..155b724 100644 --- a/src/DecrypterContext.h +++ b/src/DecrypterContext.h @@ -161,6 +161,24 @@ namespace HonokaMiku void final_setup(const char* filename, const void* block_rest); }; + /// Chinese SIF decrypter context (Version 3) + class CN3_Dctx: public V3_Dctx + { + protected: + inline CN3_Dctx() {} + public: + /// \brief Initialize SIF CN decrypter context (version 3) + /// \param header The first 4-bytes contents of the file + /// \param filename File name that want to be decrypted. This affects the key calculation. + /// \exception std::runtime_error The header does not match and this decrypter context can't decrypt it. + CN3_Dctx(const void* header, const char* filename); + /// \brief Creates SIF CN decrypter context specialized for encryption. (version 3) + /// \param filename File name that want to be encrypted. This affects the key calculation. + /// \param hdr_out Pointer with size of 16-bytes to store the file header. + static CN3_Dctx* encrypt_setup(const char* filename, void* hdr_out); + void final_setup(const char* filename, const void* block_rest); + }; + /// International SIF decrypter context class EN2_Dctx:public V2_Dctx { @@ -229,22 +247,22 @@ namespace HonokaMiku /// Simplified Chinese SIF decrypter context. /// It has longest prefix key currently - class CN_Dctx: public V2_Dctx + class CN2_Dctx: public V2_Dctx { protected: - CN_Dctx():V2_Dctx() {} + CN2_Dctx():V2_Dctx() {} public: /// \brief Initialize SIF CN decrypter context /// \param header The first 4-bytes contents of the file /// \param filename File name that want to be decrypted. This affects the key calculation. /// \exception std::runtime_error The header does not match and this decrypter context can't decrypt it. - CN_Dctx(const void* header, const char* filename):V2_Dctx("iLbs0LpvJrXm3zjdhAr4", header, filename) {} + CN2_Dctx(const void* header, const char* filename):V2_Dctx("iLbs0LpvJrXm3zjdhAr4", header, filename) {} /// \brief Creates SIF CN decrypter context specialized for encryption. /// \param filename File name that want to be encrypted. This affects the key calculation. /// \param hdr_out Pointer with size of 16-bytes to store the file header. - inline static CN_Dctx* encrypt_setup(const char* filename, void* hdr_out) + inline static CN2_Dctx* encrypt_setup(const char* filename, void* hdr_out) { - CN_Dctx* dctx=new CN_Dctx(); + CN2_Dctx* dctx=new CN2_Dctx(); setupEncryptV2(dctx, "iLbs0LpvJrXm3zjdhAr4", filename,hdr_out); return dctx; } @@ -288,7 +306,8 @@ namespace HonokaMiku case 2: case 4: return "Hello"; case 3: return "M2o2B7i3M6o6N88"; - case 5: return "iLbs0LpvJrXm3zjdhAr4"; + case 5: + case 7: return "iLbs0LpvJrXm3zjdhAr4"; default: return NULL; } } diff --git a/src/Helper.cc b/src/Helper.cc index 0eeaa80..46d4d21 100644 --- a/src/Helper.cc +++ b/src/Helper.cc @@ -53,11 +53,19 @@ HonokaMiku::DecrypterContext* HonokaMiku::FindSuitable(const char* filename, con { try { - dctx = new CN_Dctx(header, filename); + dctx = new CN2_Dctx(header, filename); *game_type = 5; } catch(std::runtime_error) { + try + { + dctx = new CN3_Dctx(header, filename); + *game_type = 7; + } + catch(std::runtime_error) + { + } } } } @@ -83,9 +91,11 @@ HonokaMiku::DecrypterContext* HonokaMiku::CreateFrom(char game_id, const void* h case 4: return new JP2_Dctx(header, filename); case 5: - return new CN_Dctx(header, filename); + return new CN2_Dctx(header, filename); case 6: return new EN3_Dctx(header, filename); + case 7: + return new CN3_Dctx(header, filename); default: return NULL; } @@ -109,9 +119,11 @@ HonokaMiku::DecrypterContext* HonokaMiku::EncryptPrepare(char game_id, const cha case 4: return JP2_Dctx::encrypt_setup(filename, header_out); case 5: - return CN_Dctx::encrypt_setup(filename, header_out); + return CN2_Dctx::encrypt_setup(filename, header_out); case 6: return EN3_Dctx::encrypt_setup(filename, header_out); + case 7: + return CN3_Dctx::encrypt_setup(filename, header_out); default: return NULL; } diff --git a/src/HonokaMiku.cc b/src/HonokaMiku.cc index 1627768..befe936 100644 --- a/src/HonokaMiku.cc +++ b/src/HonokaMiku.cc @@ -19,8 +19,7 @@ #include "CompilerName.h" #include "../VersionInfo.rc" -// Actually this is `strnicmp` implementation in MSVCRT v110 -// Copyright Microsoft Corporation. +// Copied from MSVC strnicmp.c int msvcr110_strnicmp (const char * first, const char * last, size_t count) { if(count) @@ -62,8 +61,8 @@ static char usage_string[] = " -b Use basename as decrypt/encrypt\n" " --basename key. Required if reading from stdin.\n" "\n" - " -c Assume is SIF CN game file.\n" - " --sif-cn\n" + " -c[3] Assume is SIF CN game file.\n" + " --sif-cn[-v3]" "\n" " -d Detect game file type only. [output file]\n" " --detect and the other parameters is omitted.\n" @@ -116,10 +115,12 @@ char get_gametype(const char* a) return 4; else if(msvcr110_strnicmp(a, "j3", 3) == 0 || msvcr110_strnicmp(a, "sif-jp-v3", 10) == 0) return 2; - else if(msvcr110_strnicmp(a,"t",2)==0 || msvcr110_strnicmp(a,"sif-tw",7)==0) + else if(msvcr110_strnicmp(a, "t", 2) == 0 || msvcr110_strnicmp(a, "sif-tw", 7) == 0) return 3; - else if(msvcr110_strnicmp(a,"c",2)==0 || msvcr110_strnicmp(a,"sif-cn",7)==0) + else if(msvcr110_strnicmp(a, "c", 2) == 0 || msvcr110_strnicmp(a, "sif-cn", 7) == 0) return 5; + else if(msvcr110_strnicmp(a, "c3", 3) == 0 || msvcr110_strnicmp(a, "sif-cn-v3", 10) == 0) + return 7; return 0; } @@ -136,9 +137,11 @@ const char* gameid_to_string(char gameid) case 4: return "JP (Version 2) game file"; case 5: - return "CN game file"; + return "CN (Version 2) game file"; case 6: return "EN (Version 3) game file"; + case 7: + return "CN (Version 3) game file"; default: return "Unknown"; } @@ -157,6 +160,7 @@ const char* gameid_to_string_v1(char gameid) case 3: return "TW game file"; case 5: + case 7: return "CN game file"; default: return "Unknown"; @@ -244,7 +248,10 @@ void parse_args(int argc,char* argv[]) g_Basename = argv[i] + 2; } else if(s == 'c') - g_DecryptGame = 5; + if(argv[i][2] == '3') + g_DecryptGame = 7; + else + g_DecryptGame = 5; else if(s == 'd') g_TestMode = true; @@ -681,4 +688,4 @@ int main(int argc, char* argv[]) delete dctx; return 0; -} \ No newline at end of file +} diff --git a/src/V1_Decrypter.cc b/src/V1_Decrypter.cc index b30d497..b058a24 100644 --- a/src/V1_Decrypter.cc +++ b/src/V1_Decrypter.cc @@ -5,6 +5,11 @@ #include +// Mac OS fix +#include +#include +#include + #include "DecrypterContext.h" #include "md5.h" diff --git a/src/V2_Decrypter.cc b/src/V2_Decrypter.cc index 9da4957..8d1fd8e 100644 --- a/src/V2_Decrypter.cc +++ b/src/V2_Decrypter.cc @@ -10,6 +10,11 @@ #include #include +// Mac OS fix +#include +#include +#include + #include "DecrypterContext.h" #include "md5.h" diff --git a/src/V3_Decrypter.cc b/src/V3_Decrypter.cc index d51b626..86aa0e6 100644 --- a/src/V3_Decrypter.cc +++ b/src/V3_Decrypter.cc @@ -9,6 +9,11 @@ #include #include +// Mac OS fix +#include +#include +#include + #include "DecrypterContext.h" #include "md5.h"