From 84a3e8d493e6e00428f87734d0c5515ea7b4f984 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Thu, 7 May 2026 23:25:54 -0400 Subject: [PATCH 1/3] Implement BINK2002 serial range specification and serial range argument --- src/cli.cpp | 44 +++++++++++++++++++++---------- src/cli.h | 3 ++- src/libumskt/libumskt.cpp | 8 +++--- src/libumskt/pidgen3/BINK2002.cpp | 34 ++++++++++++++++++------ src/libumskt/pidgen3/BINK2002.h | 3 +++ 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/cli.cpp b/src/cli.cpp index c1ed25b..d7b0a5e 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -67,7 +67,7 @@ void CLI::showHelp(char *argv[]) { fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n"); fmt::print("\t-l --list\tshow which products/binks can be loaded\n"); fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n"); - fmt::print("\t-s --serial\tspecifies a serial to use in the product ID (defaults to random, BINK1998 only)\n"); + fmt::print("\t-s --serial\tspecifies a serial (eg. 123456) or comma-separated serial range (recommended for BINK2002, eg. 1234,5678) to use in the product ID (defaults to 0,999999)\n"); fmt::print("\t-u --upgrade\tspecifies the Product Key will be an \"Upgrade\" version\n"); fmt::print("\t-V --validate\tproduct key to validate signature\n"); fmt::print("\t-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n"); @@ -86,6 +86,7 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) { "", 640, 0, + 999999, 1, false, false, @@ -149,12 +150,20 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) { break; } - int serial_val; - if (!sscanf(argv[i+1], "%d", &serial_val)) { - options->error = true; - } else { + int serial_min; + int serial_max; + if (strchr(argv[i+1], ',') && sscanf(argv[i + 1], "%d,%d", &serial_min, &serial_max)) { options->serialSet = true; - options->serial = serial_val; + options->serialMin = serial_min; + options->serialMax = serial_max; + } + else if (sscanf(argv[i + 1], "%d", &serial_min)) { + options->serialSet = true; + options->serialMin = serial_min; + options->serialMax = serial_min; + } + else { + options->error = true; } i++; } else if (arg == "-u" || arg == "--upgrade") { @@ -293,10 +302,15 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) { } // don't allow any serial not between 0 and 999999 - if (options->serial > 999999 || options->serial < 0) { + if (options->serialMin > 999999 || options->serialMin < 0 || options->serialMax < 0 || options->serialMax > 999999) { fmt::print("ERROR: refusing to create a key with a Serial not between 000000 and 999999\n"); return 1; } + + if (options->serialMin > options->serialMax) { + fmt::print("ERROR: serial minimum cannot be greater than serial maximum\n"); + return 1; + } return 0; } @@ -429,11 +443,13 @@ CLI::CLI(Options options, json keys) { int CLI::BINK1998Generate() { // raw PID/serial value DWORD nRaw = this->options.channelID * 1'000'000 ; /* <- change */ + DWORD serMin = this->options.serialMin; + DWORD serMax = this->options.serialMax; // using user-provided serial - if (this->options.serialSet) { + if ((serMin == serMax) && this->options.serialSet) { // just in case, make sure it's less than 1000000 - int serialRnd = (this->options.serial % 1000000); + int serialRnd = (this->options.serialMin % 1000000); nRaw += serialRnd; } else { // generate a random number to use as a serial @@ -444,8 +460,8 @@ int CLI::BINK1998Generate() { char *cRaw = BN_bn2dec(bnrand); sscanf(cRaw, "%d", &oRaw); - nRaw += (oRaw % 1000000); // ensure our serial is less than 1000000 - BN_free(bnrand); + nRaw += serMin + (oRaw % (serMax - serMin + 1)); // ensure our serial is within specified range + BN_free(bnrand); } if (this->options.verbose) { @@ -506,9 +522,9 @@ int CLI::BINK2002Generate() { fmt::print("> AuthInfo: {}\n", pAuthInfo); } - PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->pKey); + PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->options.serialMin, this->options.serialMax, this->pKey); - bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey); + bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, NULL, this->pKey); if (isValid) { CLI::printKey(this->pKey); if (i < this->total - 1 || this->options.verbose) { // check if end of list or verbose @@ -567,7 +583,7 @@ int CLI::BINK2002Validate() { CLI::printKey(product_key); fmt::print("\n"); - if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key)) { + if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, nullptr, product_key)) { fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n"); return 1; } diff --git a/src/cli.h b/src/cli.h index 99d440b..d01b463 100644 --- a/src/cli.h +++ b/src/cli.h @@ -59,7 +59,8 @@ struct Options { std::string keyToCheck; std::string productid; int channelID; - int serial; + int serialMin; + int serialMax; int numKeys; bool upgrade; bool serialSet; diff --git a/src/libumskt/libumskt.cpp b/src/libumskt/libumskt.cpp index 753b2f7..442e6ff 100644 --- a/src/libumskt/libumskt.cpp +++ b/src/libumskt/libumskt.cpp @@ -43,12 +43,12 @@ FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, B return PIDGEN3::BINK1998::Generate(eCurve, basePoint, genOrder, privateKey, pSerial, pUpgrade, pKey); } -FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]) { - return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, cdKey); +FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, DWORD *pSerial, char (&cdKey)[25]) { + return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, pSerial, cdKey); } -FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]) { - return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, pKey); +FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, DWORD serMin, DWORD serMax, char (&pKey)[25]) { + return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, serMin, serMax, pKey); } FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) { diff --git a/src/libumskt/pidgen3/BINK2002.cpp b/src/libumskt/pidgen3/BINK2002.cpp index 73b6e07..805f049 100644 --- a/src/libumskt/pidgen3/BINK2002.cpp +++ b/src/libumskt/pidgen3/BINK2002.cpp @@ -78,6 +78,7 @@ bool PIDGEN3::BINK2002::Verify( EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, + DWORD *pSerial, char (&cdKey)[25] ) { BN_CTX *context = BN_CTX_new(); @@ -100,14 +101,6 @@ bool PIDGEN3::BINK2002::Verify( pData = pChannelID << 1 | pUpgrade; - fmt::print(UMSKT::debug, "Validation results:\n"); - fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade); - fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID); - fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash); - fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature); - fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo); - fmt::print(UMSKT::debug, "\n"); - BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{}, @@ -187,6 +180,18 @@ bool PIDGEN3::BINK2002::Verify( // compHash = SHA1(79 || Channel ID || p.x || p.y) SHA1(msgBuffer, SHA_MSG_LENGTH_2003, msgDigest); + DWORD serial = (((BYDWORD(msgDigest + 4) >> 13) << 1) | (BYDWORD(msgDigest) >> 31)) & BITMASK(20); + if (pSerial != nullptr) *pSerial = serial; + + fmt::print(UMSKT::debug, "Validation results:\n"); + fmt::print(UMSKT::debug, " Upgrade: 0x{:08x}\n", pUpgrade); + fmt::print(UMSKT::debug, "Channel ID: 0x{:08x}\n", pChannelID); + fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash); + fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature); + fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo); + fmt::print(UMSKT::debug, " Serial: {:06d}\n", serial); + fmt::print(UMSKT::debug, "\n"); + // Translate the byte digest into a 32-bit integer - this is our computed hash. // Truncate the hash to 31 bits. DWORD compHash = BYDWORD(msgDigest) & BITMASK(31); @@ -214,6 +219,8 @@ void PIDGEN3::BINK2002::Generate( DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, + DWORD serMin, + DWORD serMax, char (&pKey)[25] ) { BN_CTX *numContext = BN_CTX_new(); @@ -265,8 +272,18 @@ void PIDGEN3::BINK2002::Generate( // pHash = SHA1(79 || Channel ID || R.x || R.y) SHA1(msgBuffer, SHA_MSG_LENGTH_2003, msgDigest); + // Derive serial value from byte digest and do bounds checks. + // This is important in some cases since serial can technically exceed 999999, affecting the derived Channel ID. + + DWORD serial = (((BYDWORD(msgDigest + 4) >> 13) << 1) | (BYDWORD(msgDigest) >> 31)) & BITMASK(20); + + if (serial < serMin || serial > serMax) { + continue; + } + // Translate the byte digest into a 32-bit integer - this is our computed hash. // Truncate the hash to 31 bits. + DWORD pHash = BYDWORD(msgDigest) & BITMASK(31); // Assemble the second SHA message. @@ -365,6 +382,7 @@ void PIDGEN3::BINK2002::Generate( fmt::print(UMSKT::debug, " Hash: 0x{:08x}\n", pHash); fmt::print(UMSKT::debug, " Signature: 0x{:08x}\n", pSignature); fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo); + fmt::print(UMSKT::debug, " Serial: {:06d}\n", serial); fmt::print(UMSKT::debug, "\n"); EC_POINT_free(r); diff --git a/src/libumskt/pidgen3/BINK2002.h b/src/libumskt/pidgen3/BINK2002.h index 75a0e7d..921ff65 100644 --- a/src/libumskt/pidgen3/BINK2002.h +++ b/src/libumskt/pidgen3/BINK2002.h @@ -49,6 +49,7 @@ public: EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, + DWORD *pSerial, char (&cdKey)[25] ); @@ -60,6 +61,8 @@ public: DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, + DWORD serMin, + DWORD serMax, char (&pKey)[25] ); }; From 090b9805be37319511c87054262ee5dd84af205a Mon Sep 17 00:00:00 2001 From: TheTank20 <57580668+thepwrtank18@users.noreply.github.com> Date: Fri, 8 May 2026 20:23:01 -0400 Subject: [PATCH 2/3] BINK2002-specific action tests (#181) --- .github/workflows/dos-djgpp.yml | 40 +++++++++++++++++----- .github/workflows/freebsd.yml | 6 ++-- .github/workflows/linux.yml | 48 +++++++++++++++++---------- .github/workflows/macos.yml | 8 +++-- .github/workflows/windows-arm.yml | 8 +++-- .github/workflows/windows-x86-x64.yml | 8 +++-- 6 files changed, 81 insertions(+), 37 deletions(-) diff --git a/.github/workflows/dos-djgpp.yml b/.github/workflows/dos-djgpp.yml index f267223..857543c 100644 --- a/.github/workflows/dos-djgpp.yml +++ b/.github/workflows/dos-djgpp.yml @@ -109,10 +109,13 @@ jobs: cat > dosbox_test/test.bat << EOL @echo off echo Running test 1... - umskt.exe -b 2C -c 365 -s 069420 > TEST1.TXT + umskt.exe -b 2C -c 365 -s 069420,999999 > TEST1.TXT if errorlevel 1 goto error echo Running test 2... - umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST2.TXT + umskt.exe -b 5A -c 640 -s 069420,999999 > TEST2.TXT + if errorlevel 1 goto error + echo Running test 3... + umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST3.TXT if errorlevel 1 goto error echo Tests completed > DONE.TXT goto end @@ -154,21 +157,28 @@ jobs: echo "Test 2 output:" cat TEST2.TXT fi + if [ -f TEST3.TXT ]; then + echo "Test 3 output:" + cat TEST3.TXT + fi exit 1 fi # Verify test outputs - if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ]; then + if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ] || [ ! -f TEST3.TXT ]; then echo "Test output files missing" exit 1 fi # Check test results - looking for key format patterns if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \ - ! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST2.TXT; then + ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST2.TXT || \ + ! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST3.TXT; then echo "Tests failed - unexpected output format" echo "Test 1 output:" cat TEST1.TXT echo "Test 2 output:" cat TEST2.TXT + echo "Test 3 output:" + cat TEST3.txt exit 1 else echo "All tests passed successfully" @@ -176,6 +186,8 @@ jobs: cat TEST1.TXT echo "Test 2 output:" cat TEST2.TXT + echo "Test 3 output:" + cat TEST3.TXT fi - name: Move executable to upload directory @@ -226,10 +238,13 @@ jobs: cat > dosbox_test/test.bat << EOL @echo off echo Running test 1... - umskt.exe -b 2C -c 365 -s 069420 > TEST1.TXT + umskt.exe -b 2C -c 365 -s 069420,999999 > TEST1.TXT if errorlevel 1 goto error echo Running test 2... - umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST2.TXT + umskt.exe -b 5A -c 640 -s 069420,999999 > TEST2.TXT + if errorlevel 1 goto error + echo Running test 3... + umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST3.TXT if errorlevel 1 goto error echo Tests completed > DONE.TXT goto end @@ -272,21 +287,28 @@ jobs: echo "Test 2 output:" cat TEST2.TXT fi + if [ -f TEST3.TXT ]; then + echo "Test 3 output:" + cat TEST3.TXT + fi exit 1 fi # Verify test outputs - if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ]; then + if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ] || [ ! -f TEST3.TXT ]; then echo "Test output files missing" exit 1 fi # Check test results - looking for key format patterns if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \ - ! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST2.TXT; then + ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST2.TXT || \ + ! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST3.TXT; then echo "Tests failed - unexpected output format" echo "Test 1 output:" cat TEST1.TXT echo "Test 2 output:" cat TEST2.TXT + echo "Test 3 output:" + cat TEST3.txt exit 1 else echo "All tests passed successfully" @@ -294,6 +316,8 @@ jobs: cat TEST1.TXT echo "Test 2 output:" cat TEST2.TXT + echo "Test 3 output:" + cat TEST3.TXT fi - name: Move executable to upload directory diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index e2ef6e5..c8f7b21 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -51,8 +51,10 @@ cd build cmake .. make - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v + echo Test 1 - generating key (BINK1998) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key (BINK2002) + ./umskt -b 5A -c 640 -s 069420,999999 -v echo Test 2 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 73a07a3..a212a68 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -86,9 +86,11 @@ jobs: if: ${{ matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 shell: alpine-target.sh {0} @@ -96,9 +98,11 @@ jobs: if: ${{ !matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 - name: Move files to correct directory @@ -131,9 +135,11 @@ jobs: if: ${{ matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 shell: alpine-target.sh {0} @@ -141,9 +147,11 @@ jobs: if: ${{ !matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 - name: Configure and build shared deps UMSKT (Alpine) @@ -165,9 +173,11 @@ jobs: if: ${{ matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 shell: alpine-target.sh {0} @@ -175,7 +185,9 @@ jobs: if: ${{ !matrix.use_alpine }} run: | cd build - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 80b87f4..44b331d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -86,9 +86,11 @@ jobs: - name: Run tests run: | cd build/actions_upload - echo Test 1 - generating key - ./umskt -b 2C -c 365 -s 069420 -v - echo Test 2 - generating confid + echo Test 1 - generating key \(BINK1998\) + ./umskt -b 2C -c 365 -s 069420,999999 -v + echo Test 2 - generating key \(BINK2002\) + ./umskt -b 5A -c 640 -s 069420,999999 -v + echo Test 3 - generating confid ./umskt -i 253286028742154311079061239762245184619981623171292574 - name: Upload platform-specific build diff --git a/.github/workflows/windows-arm.yml b/.github/workflows/windows-arm.yml index a0399c5..99c5886 100644 --- a/.github/workflows/windows-arm.yml +++ b/.github/workflows/windows-arm.yml @@ -138,7 +138,9 @@ jobs: - name: Run tests shell: pwsh run: | - Write-Host Test 1 - generating key - .\umskt.exe -b 2C -c 365 -s 069420 -v - Write-Host Test 2 - generatng confid + Write-Host Test 1 - generating key `(BINK1998`) + .\umskt.exe -b 2C -c 365 -s 069420,999999 -v + Write-Host Test 2 - generating key `(BINK2002`) + .\umskt.exe -b 5A -c 640 -s 069420,999999 -v + Write-Host Test 3 - generatng confid .\umskt.exe -i 253286028742154311079061239762245184619981623171292574 diff --git a/.github/workflows/windows-x86-x64.yml b/.github/workflows/windows-x86-x64.yml index 9afa794..b64b3ab 100644 --- a/.github/workflows/windows-x86-x64.yml +++ b/.github/workflows/windows-x86-x64.yml @@ -223,9 +223,11 @@ jobs: - name: Run tests shell: pwsh run: | - Write-Host Test 1 - generating key - .\umskt.exe -b 2C -c 365 -s 069420 -v - Write-Host Test 2 - generatng confid + Write-Host Test 1 - generating key `(BINK1998`) + .\umskt.exe -b 2C -c 365 -s 069420,999999 -v + Write-Host Test 2 - generating key `(BINK2002`) + .\umskt.exe -b 5A -c 640 -s 069420,999999 -v + Write-Host Test 3 - generatng confid .\umskt.exe -i 253286028742154311079061239762245184619981623171292574 - name: Upload build artifact From b6ee24a6e4bae8c8b54be757f62af1d7e25c3b88 Mon Sep 17 00:00:00 2001 From: WitherOrNot Date: Fri, 8 May 2026 20:24:51 -0400 Subject: [PATCH 3/3] Fix intermittent crash --- src/libumskt/pidgen3/BINK2002.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libumskt/pidgen3/BINK2002.cpp b/src/libumskt/pidgen3/BINK2002.cpp index 805f049..2ead4eb 100644 --- a/src/libumskt/pidgen3/BINK2002.cpp +++ b/src/libumskt/pidgen3/BINK2002.cpp @@ -238,6 +238,7 @@ void PIDGEN3::BINK2002::Generate( DWORD pData = pChannelID << 1 | pUpgrade; BOOL noSquare; + BOOL serialInRange; do { EC_POINT *r = EC_POINT_new(eCurve); @@ -276,10 +277,8 @@ void PIDGEN3::BINK2002::Generate( // This is important in some cases since serial can technically exceed 999999, affecting the derived Channel ID. DWORD serial = (((BYDWORD(msgDigest + 4) >> 13) << 1) | (BYDWORD(msgDigest) >> 31)) & BITMASK(20); - - if (serial < serMin || serial > serMax) { - continue; - } + serialInRange = (serial >= serMin) && (serial <= serMax); + if (!serialInRange) continue; // Translate the byte digest into a 32-bit integer - this is our computed hash. // Truncate the hash to 31 bits. @@ -386,7 +385,7 @@ void PIDGEN3::BINK2002::Generate( fmt::print(UMSKT::debug, "\n"); EC_POINT_free(r); - } while (pSignature > BITMASK(62) || noSquare); + } while (pSignature > BITMASK(62) || noSquare || !serialInRange); // ↑ ↑ ↑ // The signature can't be longer than 62 bits, else it will // overlap with the AuthInfo segment next to it.