Compare commits

..

No commits in common. "74ba5156dffdfe85233a013905c5d32e86a4f9ff" and "84585531d42fdfad4e3f25acad832090d44d1cf1" have entirely different histories.

6 changed files with 113 additions and 109 deletions

View File

@ -59,11 +59,6 @@ class KggTask {
} }
auto qmc2 = QMC2::Create(ekey); auto qmc2 = QMC2::Create(ekey);
if (!qmc2) {
error(L"create qmc2 instance failed (ekey decode error?)");
fprintf(stderr, "%s\n", ekey.c_str());
return;
}
std::string magic(4, 0); std::string magic(4, 0);
kgg_stream_in.seekg(offset_to_audio, std::ios::beg); kgg_stream_in.seekg(offset_to_audio, std::ios::beg);

View File

@ -3,31 +3,39 @@
#include "tc_tea.h" #include "tc_tea.h"
#include <algorithm> #include <algorithm>
#include <array>
#include <string> #include <string>
#include <array>
#include <vector> #include <vector>
const static std::string kEKeyV2Prefix = "UVFNdXNpYyBFbmNWMixLZXk6"; const static std::string kEKeyV2Prefix = "UVFNdXNpYyBFbmNWMixLZXk6";
const static std::array<uint8_t, 16> kEKeyV2Key1{ const static std::array<uint8_t, 16> kEKeyV2Key1{
0x33, 0x38, 0x36, 0x5A, 0x4A, 0x59, 0x21, 0x40, 0x23, 0x2A, 0x24, 0x25, 0x5E, 0x26, 0x29, 0x28, 0x33, 0x38, 0x36, 0x5A, 0x4A, 0x59, 0x21, 0x40,
0x23, 0x2A, 0x24, 0x25, 0x5E, 0x26, 0x29, 0x28,
}; };
const static std::array<uint8_t, 16> kEKeyV2Key2{ const static std::array<uint8_t, 16> kEKeyV2Key2{
0x2A, 0x2A, 0x23, 0x21, 0x28, 0x23, 0x24, 0x25, 0x26, 0x5E, 0x61, 0x31, 0x63, 0x5A, 0x2C, 0x54, 0x2A, 0x2A, 0x23, 0x21, 0x28, 0x23, 0x24, 0x25,
0x26, 0x5E, 0x61, 0x31, 0x63, 0x5A, 0x2C, 0x54,
}; };
template <typename T> template <typename T> std::span<T> ss2span(std::string_view sv) {
std::span<T> ss2span(std::string_view sv) {
auto *data = reinterpret_cast<const T *>(sv.data()); auto *data = reinterpret_cast<const T *>(sv.data());
return std::span<T>(const_cast<T *>(data), sv.size()); return std::span<T>(const_cast<T *>(data), sv.size());
} }
template <typename T> template <typename T> std::string_view span2ss(std::span<T> span) {
std::string_view span2ss(std::span<T> span) {
return std::string_view(reinterpret_cast<char *>(span.data()), span.size()); return std::string_view(reinterpret_cast<char *>(span.data()), span.size());
} }
void remove_trailing_zeros(std::vector<uint8_t> &vec) {
auto it = std::find_if(vec.rbegin(), vec.rend(),
[](uint8_t value) { return value != 0; });
vec.erase(it.base(), vec.end());
}
std::vector<uint8_t> decrypt_ekey_v1(std::string_view ekey) { std::vector<uint8_t> decrypt_ekey_v1(std::string_view ekey) {
std::vector<uint8_t> result = b64_decode(reinterpret_cast<const uint8_t*>(ekey.data()), ekey.size()); std::vector<uint8_t> result =
b64_decode(reinterpret_cast<const uint8_t *>(ekey.data()), ekey.size());
remove_trailing_zeros(result);
uint32_t tea_key[4] = { uint32_t tea_key[4] = {
0x69005600 | static_cast<uint32_t>(result[0] << 16) | (result[1]), 0x69005600 | static_cast<uint32_t>(result[0] << 16) | (result[1]),

View File

@ -10,11 +10,8 @@ constexpr size_t kTeaBlockSize = 8;
constexpr size_t kFixedSaltLen = 2; constexpr size_t kFixedSaltLen = 2;
constexpr size_t kZeroPadLen = 7; constexpr size_t kZeroPadLen = 7;
inline void decrypt_round(uint8_t* p_plain, inline void decrypt_round(uint8_t *p_plain, const uint8_t *p_cipher,
const uint8_t* p_cipher, uint64_t *iv1, uint64_t *iv2, const uint32_t *key) {
uint64_t* iv1,
uint64_t* iv2,
const uint32_t* key) {
uint64_t iv1_next = Endian::be_u64_read(p_cipher); uint64_t iv1_next = Endian::be_u64_read(p_cipher);
uint64_t iv2_next = tc_tea_ecb_decrypt(iv1_next ^ *iv2, key); uint64_t iv2_next = tc_tea_ecb_decrypt(iv1_next ^ *iv2, key);
uint64_t plain = iv2_next ^ *iv1; uint64_t plain = iv2_next ^ *iv1;
@ -23,7 +20,8 @@ inline void decrypt_round(uint8_t* p_plain,
Endian::be_u64_write(p_plain, plain); Endian::be_u64_write(p_plain, plain);
} }
std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher, const uint32_t* key) { std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher,
const uint32_t *key) {
// It needs to have at least 2 blocks long, due to the nature of the padding // It needs to have at least 2 blocks long, due to the nature of the padding
// scheme used. // scheme used.
if (cipher.size() % kTeaBlockSize != 0 || cipher.size() < kTeaBlockSize * 2) { if (cipher.size() % kTeaBlockSize != 0 || cipher.size() < kTeaBlockSize * 2) {
@ -52,7 +50,8 @@ std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher, const uint32_
if (real_plain_len != copy_len) { if (real_plain_len != copy_len) {
// Decrypt the rest of the blocks // Decrypt the rest of the blocks
for (size_t i = cipher.size() - kTeaBlockSize * 3; i != 0; i -= kTeaBlockSize) { for (size_t i = cipher.size() - kTeaBlockSize * 3; i != 0;
i -= kTeaBlockSize) {
decrypt_round(p_output, in_cipher, &iv1, &iv2, key); decrypt_round(p_output, in_cipher, &iv1, &iv2, key);
in_cipher += kTeaBlockSize; in_cipher += kTeaBlockSize;
p_output += kTeaBlockSize; p_output += kTeaBlockSize;

View File

@ -6,9 +6,11 @@
#include <span> #include <span>
#include <vector> #include <vector>
std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher, const uint32_t* key); std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher,
const uint32_t *key);
inline std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher, const uint8_t* key) { inline std::vector<uint8_t> tc_tea_cbc_decrypt(std::span<uint8_t> cipher,
const uint8_t *key) {
uint32_t key_u32[4]; uint32_t key_u32[4];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
key_u32[i] = Endian::be_u32_read(key + i * 4); key_u32[i] = Endian::be_u32_read(key + i * 4);