BINK Preset Upgrade

This commit is contained in:
Andrew 2023-06-25 01:40:50 +03:00
parent 8272256406
commit 0756a807b8
22 changed files with 584 additions and 304 deletions

View File

@ -97,7 +97,7 @@
<ClCompile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ExceptionHandling>Sync</ExceptionHandling>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
@ -184,6 +184,7 @@
<SubSystem>Console</SubSystem>
<AdditionalManifestDependencies>"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
<RegisterOutput>true</RegisterOutput>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
@ -274,13 +275,13 @@
<SubSystem>Windows</SubSystem>
<AdditionalManifestDependencies>"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
<RegisterOutput>true</RegisterOutput>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<Media Include="resources\neon.wav" />
<Media Include="resources\pxiii.wav" />
</ItemGroup>
<ItemGroup>
@ -293,12 +294,14 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\header.h" />
<ClInclude Include="src\presets.h" />
<ClInclude Include="src\resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\bink.cpp" />
<ClCompile Include="src\key.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\presets.cpp" />
<ClCompile Include="src\server.cpp" />
<ClCompile Include="src\utilities.cpp" />
<ClCompile Include="src\windows.cpp" />
@ -307,6 +310,16 @@
<ItemGroup>
<ResourceCompile Include="src\resource.rc" />
</ItemGroup>
<ItemGroup>
<None Include="resources\bink\BINK2003.bin" />
<None Include="resources\bink\BINK2003OEM.bin" />
<None Include="resources\bink\BINK98SE.bin" />
<None Include="resources\bink\BINK98SEOEM.bin" />
<None Include="resources\bink\BINKXP.bin" />
<None Include="resources\bink\BINKXP64.bin" />
<None Include="resources\bink\BINKXP64OEM.bin" />
<None Include="resources\bink\BINKXPOEM.bin" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -10,33 +10,39 @@
<Filter Include="Resources">
<UniqueIdentifier>{8c8a7e56-fe48-4168-8eb0-0715690de23e}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\BINK">
<UniqueIdentifier>{f5cd78be-da1c-4cfe-a3b9-56a21fefadf4}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\Bitmaps">
<UniqueIdentifier>{7847a032-b440-4d10-a8a6-ed1b9cb62197}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\Wave">
<UniqueIdentifier>{198e89a5-06ad-4790-bfaa-1e59588bf2d2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Media Include="resources\neon.wav">
<Filter>Resources</Filter>
</Media>
<Media Include="resources\pxiii.wav">
<Filter>Resources</Filter>
<Filter>Resources\Wave</Filter>
</Media>
</ItemGroup>
<ItemGroup>
<Image Include="resources\ender.bmp">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\icon.ico">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\logo.bmp">
<Filter>Resources</Filter>
<Image Include="resources\dropdown.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\ender.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\musicoff.bmp">
<Filter>Resources</Filter>
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\musicon.bmp">
<Filter>Resources</Filter>
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\dropdown.bmp">
<Filter>Resources</Filter>
<Image Include="resources\logo.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
</ItemGroup>
<ItemGroup>
@ -46,6 +52,9 @@
<ClInclude Include="src\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\presets.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\windows.cpp">
@ -69,10 +78,39 @@
<ClCompile Include="src\utilities.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\presets.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="src\resource.rc">
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="resources\bink\BINK98SE.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK98SEOEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK2003.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK2003OEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP64.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP64OEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXPOEM.bin">
<Filter>Resources\BINK</Filter>
</None>
</ItemGroup>
</Project>

BIN
resources/bink/BINK2003.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
resources/bink/BINK98SE.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
resources/bink/BINKXP.bin Normal file

Binary file not shown.

BIN
resources/bink/BINKXP64.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3,63 +3,56 @@
//
#include "header.h"
#define BINK_RETAIL MAKEINTRESOURCEW(1)
#define BINK_OEM MAKEINTRESOURCEW(2)
#define RT_BINK L"BINK"
#include "resource.h"
#include "presets.h"
/*
Bink resource doesn't exist
The file you selected isn't a library
Bink resource is invalid
*/
typedef struct _EC_BYTE_POINT {
CHAR x[256]; // x-coordinate of the point on the elliptic curve.
CHAR y[256]; // y-coordinate of the point on the elliptic curve.
} EC_BYTE_POINT;
typedef struct _BINKHDR {
// BINK version - not stored in the resource.
ULONG32 dwVersion;
// Original BINK header.
ULONG32 dwID;
ULONG32 dwSize;
ULONG32 dwHeaderLength;
ULONG32 dwChecksum;
ULONG32 dwDate;
ULONG32 dwKeySizeInDWORDs;
ULONG32 dwHashLength;
ULONG32 dwSignatureLength;
/*BOOL SelectPreset(int nIndex) {
if (nIndex >= WCOUNT) return false;
// Extended BINK header. (Windows Server 2003+)
ULONG32 dwAuthCodeLength;
ULONG32 dwProductIDLength;
} BINKHDR;
strcpy(pBINKPreset.p, p[nIndex]);
strcpy(pBINKPreset.a, a);
strcpy(pBINKPreset.b, b);
strcpy(pBINKPreset.G.x, gx[nIndex]);
strcpy(pBINKPreset.G.y, gy[nIndex]);
strcpy(pBINKPreset.K.x, kx[nIndex]);
strcpy(pBINKPreset.K.y, ky[nIndex]);
typedef struct _BINKDATA {
CHAR p[256]; // Finite Field order p.
CHAR a[256]; // Elliptic Curve parameter a.
CHAR b[256]; // Elliptic Curve parameter b.
pBINKPreset.I.x;
pBINKPreset.I.y;
pBINKPreset.n = n[nIndex];
pBINKPreset.k = k[nIndex];
EC_BYTE_POINT G; // Base point (Generator) G.
EC_BYTE_POINT K; // Public key K.
EC_BYTE_POINT I; // Inverse of the public key K.
} BINKDATA;
return true;
}*/
typedef struct _BINKEY {
BINKHDR header;
BINKDATA data;
} BINKEY;
BOOL CALLBACK EnumResourceProc(HMODULE hModule, CONST WCHAR *lpType, WCHAR *lpName, LONG_PTR lParam) {
(*(UINT *)lParam)++;
DWORD extractBINKResource(HMODULE hLibrary, BYTE **pData) {
HRSRC hRes = FindResourceW(hLibrary, BINK_OEM, RT_BINK);
return TRUE;
}
UINT countResources(WCHAR *pName) {
UINT nResources = 0;
EnumResourceNamesW(NULL, pName, EnumResourceProc, (LONG_PTR)&nResources);
return nResources;
}
DWORD extractBINKResource(HMODULE hModule, UINT nPreset, BYTE **pMemory) {
HRSRC hRes = FindResourceW(hModule, MAKEINTRESOURCEW(nPreset), RT_BINK);
DWORD dwSize = 0;
if (hRes != NULL) {
dwSize = SizeofResource(hLibrary, hRes);
*pData = (BYTE *)LoadResource(hLibrary, hRes);
dwSize = SizeofResource(hModule, hRes);
*pMemory = (BYTE *)LoadResource(hModule, hRes);
}
return dwSize;
@ -75,64 +68,135 @@ BYTE hexToDecDigit(CHAR nDigit) {
return nDigit - 'A' + 10;
}
ULONG32 byteToInteger(BYTE *pByte) {
return hexToDecDigit(pByte[0]) << 4 + hexToDecDigit(pByte[1]);
void reverseBytes(BYTE *pBytes) {
UINT nBytes = strlen((CHAR *)pBytes) / 2;
CHAR *pBytesCopy = strdup((CHAR *)pBytes);
for (int i = 0; i < nBytes; i++) {
memcpy(&pBytes[(nBytes - (i + 1)) * 2], &pBytesCopy[i * 2], 2 * sizeof(BYTE));
}
free(pBytesCopy);
}
void reverseBytes(CONST BYTE *pBytes, ULONG32 nBytes, BYTE *pReversed) {
for (int i = nBytes - 1; i >= 0; i--) {
memcpy((BYTE *)&pBytes[i * 2], (BYTE *)&pReversed[(nBytes - i + 1) * 2], 2 * sizeof(BYTE));
VOID byteToHex(BYTE *pDestination, BYTE pByte) {
BYTE loByte = pByte % 16,
hiByte = pByte / 16;
pDestination[0] = hiByte < 10 ? hiByte + '0' : hiByte + 'A' - 10;
pDestination[1] = loByte < 10 ? loByte + '0' : loByte + 'A' - 10;
}
VOID formatBytes(BYTE *pDestination, BYTE *pSource, UINT nLength) {
for (int i = 0; i < nLength; i++) {
byteToHex(pDestination + i * 2, pSource[i]);
}
}
ULONG32 ulToInteger(BYTE *pUL, BOOL bLittleEndian) {
BYTE pULCopy[8] = { 0 };
ULONG32 nUL = 0;
BOOL decodeBINKResource(BYTE *pData, ULONG32 nLength, BINKEYEX *pBINK) {
ULONG32 nStructOffset,
nCurveOffset,
nCurveField = FIELD_BYTES_2003;
// If BINK is incomplete or the containers are null pointers, return.
if (pData == nullptr || pBINK == nullptr || nLength < 0x170) return false;
// Reset structure to 0.
memset(pBINK, 0, sizeof(BINKEYEX));
// Read ID and the BINK header.
for (nStructOffset = 0; nStructOffset < sizeof(ULONG32) + sizeof(BINKHDR); nStructOffset += sizeof(ULONG32)) {
*(ULONG32 *)((BYTE *)pBINK + nStructOffset) = BYDWORD(pData + nStructOffset);
}
// If it's an older BINK, there are only 7 arguments.
if (pBINK->binKey.header.dwVersion == 19980206) {
pBINK->binKey.header.dwProductIDLength = 0;
pBINK->binKey.header.dwAuthCodeLength = 0;
nCurveField = FIELD_BYTES;
}
for (nCurveOffset = (pBINK->binKey.header.dwHeaderLength + 1) * sizeof(ULONG32); nStructOffset < sizeof(ULONG32) + sizeof(BINKDATA); nStructOffset += FIELD_LENGTH_MAX, nCurveOffset += nCurveField) {
BYTE *pCurveParameter = (BYTE *)pBINK + nStructOffset;
formatBytes(pCurveParameter, pData + nCurveOffset, nCurveField);
reverseBytes(pCurveParameter);
}
// Calculate the inverse of the public key.
// The elliptic curve is symmetric about the x axis, so we only need to calculate the y-coordinate.
// I.y = p - K.y
BIGNUM *fieldOrder = BN_new(),
*publicKeyY = BN_new();
BN_hex2bn(&fieldOrder, pBINK->binKey.data.p);
BN_hex2bn(&publicKeyY, pBINK->binKey.data.K.y);
BN_sub(publicKeyY, fieldOrder, publicKeyY);
CHAR *pInverse = BN_bn2hex(publicKeyY);
strcpy(pBINK->I.x, pBINK->binKey.data.K.x);
strcpy(pBINK->I.y, pInverse);
if (pUL == NULL)
return 0;
free(pInverse);
if (bLittleEndian)
reverseBytes(pUL, 4, pULCopy);
for (int i = 0; i < 4; i++) {
nUL += byteToInteger(&pULCopy[i * 2]);
}
return nUL;
}
// Additional calculations (not implemented yet)
BIGNUM *derivative = BN_new();
BIGNUM *generatorx = BN_new();
BIGNUM *generatory = BN_new();
BN_CTX *ctx = BN_CTX_new();
void decodeBINKResource(BYTE *pData, ULONG32 nLength, BINKEY *pBINK) {
ULONG32 nBlockBytes = 4;
BN_hex2bn(&generatorx, pBINK->binKey.data.G.x);
BN_hex2bn(&generatory, pBINK->binKey.data.G.y);
// If BINK is incomplete, return.
if (nLength < 0x170) return;
/*EC_POINT *genPoint, *pubPoint, *genDerivative;
EC_GROUP *eCurve = initializeEllipticCurve(
pBINK->data.p,
pBINK->data.a,
pBINK->data.b,
pBINK->data.G.x,
pBINK->data.G.y,
pBINK->data.K.x,
pBINK->data.K.y,
&genPoint,
&pubPoint
);
ulToInteger(pData, TRUE);
genDerivative = EC_POINT_new(eCurve);
EC_POINT_copy(genDerivative, genPoint);
/*/ Read BINK header.
for (ULONG32 nOffset = 0; nOffset < sizeof(BINKHDR); nOffset += nBlockBytes) {
pBINK[nOffset] =
for (ULONG64 iter = 0; iter != 65153636961774397; iter++) {
printf("iter: %llu\n", iter);
EC_POINT_add(eCurve, genDerivative, genPoint, genDerivative, ctx);
}*/
return true;
}
void base(WCHAR *pPath) {
HMODULE pIDgen = LoadLibraryExW(pPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
VOID InitializePreset(UINT nIndex, BINKEYEX *pBINK) {
/* HMODULE pIDgen = LoadLibraryExW(pPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (pIDgen == NULL)
return;
return;*/
BYTE *pBuffer = NULL;
ULONG32 nLength = extractBINKResource(pIDgen, &pBuffer);
BYTE *pMemory = NULL;
ULONG32 nLength = extractBINKResource(NULL, IDR_BINK1 + nIndex, &pMemory);
if (nLength == 0) {
return;
}
BINKEY pBINK = { 0 };
decodeBINKResource(pMemory, nLength, pBINK);
decodeBINKResource(pBuffer, nLength, &pBINK);
pBINK->n = generatorOrderArr[nIndex];
pBINK->k = privateKeyArr[nIndex];
FreeLibrary(pIDgen);
}
// FreeLibrary(pIDgen);
return;
}

View File

@ -18,6 +18,7 @@
#pragma warning(disable: 6387)
// Arithmetic macros
#define PK_LENGTH 25
#define NULL_TERMINATOR 1
@ -27,9 +28,14 @@
#define FIELD_BITS_2003 512
#define FIELD_BYTES_2003 (FIELD_BITS_2003 / 8)
#define FIELD_BITS_MAX FIELD_BITS_2003
#define FIELD_BYTES_MAX FIELD_BYTES_2003
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
#define FIELD_LENGTH_MAX (FIELD_BYTES_MAX * 2 + NULL_TERMINATOR)
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
@ -37,8 +43,10 @@
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((bytes) * 8))
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BYDWORDBE(n) (DWORD)(*((n) + 3) | *((n) + 2) << 8 | *((n) + 1) << 16 | *((n) + 0) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
// Control macros
#define IDC_BUTTON1 1000
#define IDC_BUTTON2 1001
#define IDC_BUTTON3 1002
@ -67,18 +75,71 @@
#define IDC_LABEL5 1109
#define IDC_LABEL6 1110
// Resource macros
#define BINK_RETAIL MAKEINTRESOURCEW(1)
#define BINK_OEM MAKEINTRESOURCEW(2)
#define RT_BINK TEXT("BINK")
// Type definitions
typedef uint64_t QWORD;
extern char pCharset[];
// Structures
typedef struct _EC_BYTE_POINT {
CHAR x[FIELD_LENGTH_MAX]; // x-coordinate of the point on the elliptic curve.
CHAR y[FIELD_LENGTH_MAX]; // y-coordinate of the point on the elliptic curve.
} EC_BYTE_POINT;
typedef struct _BINKHDR {
// Original BINK header.
ULONG32 dwSize;
ULONG32 dwHeaderLength;
ULONG32 dwChecksum;
ULONG32 dwVersion;
ULONG32 dwKeySizeInDWORDs;
ULONG32 dwHashLength;
ULONG32 dwSignatureLength;
// Extended BINK header. (Windows Server 2003+)
ULONG32 dwAuthCodeLength;
ULONG32 dwProductIDLength;
} BINKHDR, *PBINKHDR;
typedef struct _BINKDATA {
CHAR p[FIELD_LENGTH_MAX]; // Finite Field order p.
CHAR a[FIELD_LENGTH_MAX]; // Elliptic Curve parameter a.
CHAR b[FIELD_LENGTH_MAX]; // Elliptic Curve parameter b.
EC_BYTE_POINT G; // Base point (Generator) G.
EC_BYTE_POINT K; // Public key K.
} BINKDATA, *PBINKDATA;
typedef struct _BINKEY {
BINKHDR header;
BINKDATA data;
} BINKEY, *PBINKEY;
typedef struct _BINKEYEX {
// ID of the BINK. (Separate from the BINKEY structure per spec)
ULONG32 dwID;
// BINKEY structure.
BINKEY binKey;
// Calculated values.
EC_BYTE_POINT I; // Inverse of the public key K.
QWORD n; // Order of the generator G.
QWORD k; // Private Key k.
} BINKEYEX, *PBINKEYEX;
extern BINKEYEX pBINKPreset;
extern CHAR pCharset[];
extern const char pXP[];
extern const long aXP;
extern const long bXP;
// xp.cpp
VOID unpackXP(
QWORD(&pRaw)[2],
BOOL &pUpgrade,
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pChannelID,
DWORD &pSequence,
DWORD &pHash,
@ -106,10 +167,11 @@ VOID generateXPKey(
);
BOOL keyXP(
CHAR(&pKey)[PK_LENGTH + NULL_TERMINATOR],
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
);
@ -151,10 +213,11 @@ VOID generateServerKey(
);
BOOL keyServer(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
);
@ -166,17 +229,15 @@ void stopAudio();
bool playAudio(HINSTANCE hInstance, WCHAR *lpName, UINT bFlags);
EC_GROUP *initializeEllipticCurve(
const char *pSel,
long aSel,
long bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
BIGNUM *genOrderSel,
BIGNUM *privateKeySel,
EC_POINT **genPoint,
EC_POINT **pubPoint
CONST CHAR *pSel,
CONST CHAR *aSel,
CONST CHAR *bSel,
CONST CHAR *generatorXSel,
CONST CHAR *generatorYSel,
CONST CHAR *publicKeyXSel,
CONST CHAR *publicKeyYSel,
EC_POINT **genPoint,
EC_POINT **pubPoint
);
int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen);
@ -195,6 +256,7 @@ bool InitializeWindow(HINSTANCE hInstance);
// bink.cpp
void base(WCHAR *pPath);
VOID InitializePreset(UINT nIndex, BINKEYEX *pBINK);
UINT countResources(WCHAR *pName);
#endif //KEYGEN_HEADER_H

View File

@ -87,7 +87,7 @@ void formatXP(BOOL bUpgrade, WCHAR *pBSection, WCHAR *pCSection, WCHAR *pText) {
DWORD nChannelID = wcstoul(pBSection, nullptr, 10),
nSequence = wcstoul(pCSection, nullptr, 10);
BOOL bValid = keyXP(pKey, nChannelID, nSequence, bUpgrade);
BOOL bValid = keyXP(pKey, pBINKPreset, nChannelID, nSequence, bUpgrade);
QWORD pRaw[2]{},
pSignature;
@ -131,7 +131,7 @@ void formatServer(BOOL bUpgrade, WCHAR *pBSection, WCHAR *pAuthSection, WCHAR *p
DWORD nChannelID = wcstoul(pBSection, nullptr, 10);
DWORD nAuthInfo = wcstoul(pAuthSection, nullptr, 0) % 0x400;
BOOL bValid = keyServer(pKey, nChannelID, nAuthInfo, bUpgrade);
BOOL bValid = keyServer(pKey, pBINKPreset, nChannelID, nAuthInfo, bUpgrade);
QWORD pRaw[2]{},
pSignature;

View File

@ -61,12 +61,15 @@
#include "header.h"
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
BINKEYEX pBINKPreset;
CHAR pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
INT wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ WCHAR *pCmdLine, _In_ INT nCmdShow) {
INT wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ WCHAR *pCmdLine, _In_ INT nCmdShow) {
srand(GetTickCount64());
//base(L"D:\\Desktop\\ECC Research\\pIDgen\\pidgenxp.dll");
InitializePreset(2, &pBINKPreset);
return InitializeWindow(hInstance);
// don't forget to free bink presets (I Forgor)
}

23
src/presets.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "presets.h"
const unsigned long long generatorOrderArr[] = {
71314261946000873,
65153636961774397,
61760995553426173,
62443961168019161,
5532044755580494717,
4755964586330124773,
4710798293276956193,
5152953887135671777,
};
const unsigned long long privateKeyArr[] = {
42187888123314505,
52329725233299758,
24306963676698312,
32781177223842894,
2739897280441110808,
174180799641457829,
11731326262766101,
1583498175279647618,
};

27
src/presets.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
enum VERSIONS {
W98SE,
W98SEOEM,
WXP,
WXPOEM,
WSERVER2003,
WXP64,
WXP64OEM,
WCOUNT
};
extern const wchar_t *pPresets[256];
extern const char *p[256];
extern const char *a;
extern const char *b;
extern const char *gx[256];
extern const char *gy[256];
extern const char *kx[256];
extern const char *ky[256];
extern const unsigned long long generatorOrderArr[];
extern const unsigned long long privateKeyArr[];

View File

@ -10,6 +10,15 @@
#define IDB_BITMAP4 106
#define IDB_BITMAP5 107
#define IDR_BINK1 1001
#define IDR_BINK2 1002
#define IDR_BINK3 1003
#define IDR_BINK4 1004
#define IDR_BINK5 1005
#define IDR_BINK6 1006
#define IDR_BINK7 1007
#define IDR_BINK8 1008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED

Binary file not shown.

View File

@ -4,66 +4,6 @@
#include "header.h"
/* Windows Server 2003 */
const char pSv[] = "C9AE7AED19F6A7E100AADE98134111AD8118E59B8264734327940064BC675A0C682E19C89695FBFA3A4653E47D47FD7592258C7E3C3C61BBEA07FE5A7E842379";
const long aSv = 1;
const long bSv = 0;
// Base point G (Generator)
const char genXSv[] = "85ACEC9F9F9B456A78E43C3637DC88D21F977A9EC15E5225BD5060CE5B892F24FEDEE574BF5801F06BC232EEF2161074496613698D88FAC4B397CE3B475406A7";
const char genYSv[] = "66B7D1983F5D4FE43E8B4F1E28685DE0E22BBE6576A1A6B86C67533BF72FD3D082DBA281A556A16E593DB522942C8DD7120BA50C9413DF944E7258BDDF30B3C4";
// Inverse of the public key
const char pubXSv[] = "90BF6BD980C536A8DB93B52AA9AEBA640BABF1D31BEC7AA345BB7510194A9B07379F552DA7B4A3EF81A9B87E0B85B5118E1E20A098641EE4CCF2045558C98C0E";
const char pubYSv[] = "6B87D1E658D03868362945CDD582E2CF33EE4BA06369E0EFE9E4851F6DCBEC7F15081E250D171EA0CC4CB06435BCFCFEA8F438C9766743A06CBD06E7EFB4C3AE";
// Order of G <- from MSKey 4-in-1
const char genOrderSv[] = "4CC5C56529F0237D";
// Computed private key
const char privateKeySv[] = "2606120F59C05118";
/* Windows XP x64
Public key (-K) = (1989960177638374390878377737764297057685259206834686428253479199374616869742150776410973898745805799780071536831208959469038333664656928533078897351495263; 2680493145252003995204016438404731303203625133293449171132691660710342616258476835192643732221910418645447349019141673820306444587247165566828458285756618)
Order of base point G (n) = 4710798293276956193
Private key (k) = 4699066967014190092 for INVERSE. 11731326262766101
const char pSv[] = "D4B49D04A01EF209121C370DCF0D6292569EC65B8F147A8C62319B6B90DEA2D1CD45199B93582732BFEE27F40BF62D7EB2559BCD08041E301E0D14037A25D989";
const long aSv = 1;
const long bSv = 0;
const char genXSv[] = "828A23E65A03F2CE12342DC2B3AA4089C1447DD5C4DC36C0470885A4662F10187037F72B2216C3F671B434267A329BD3363BB27055F0EBBA8A0ABEF451D3F6A3";
const char genYSv[] = "23B0823295C9CB669E1643B298624083F68C58F14FEEC55D0B247EF37B353A1066F502D7BC71050056C7D006156A26CC9222F5135FB8B255D7773AE0CDCA31E2";
const char pubXSv[] = "25FEB90513F63C0833F1096369149E65C9359F4BCC8DE9A8F647030F96485BC71929594FF369DB967910B8F0A59BC7C30CF0D38311486293BA0B2952EE648E5F";
const char pubYSv[] = "A186A2C2913E5584F05E97D3CD49E354E6C41BE329877D7FCC7B2BF877A0B00C9298901D305D7FF012FF7902B4202D4ED64D6A90C6AD05960253BAB8F69D68BF";
// Order of G <- CALCULATED ON MY i7-12700K in 20 seconds
const char genOrderSv[] = "41601E16BF4A1621";
// Computed private key <- CALCULATED ON MY i7-12700K in 5 minutes 40 seconds
const char privateKeySv[] = "29AD943EA2EA15"; */
/* Windows XP x64 OEM
const char pSv[] = "A6FEDE9568C7863685F783F864A5943D34DED45EC460EEB2EC0455B01BC3C4D21FE081E479F2338BAAF7B10903AC89D23774938F41FDBFB6F16A615ECE5A04A1";
const long aSv = 1;
const long bSv = 0;
const char genXSv[] = "3CCFE20244697894A5CF8F8A57F335462C8C7C4935E171A373C2C1BA85C304D121A48931A99E4DD911945B410E10DEF21C00B2ED33FEF4E8F6FCBE16014E0AA8";
const char genYSv[] = "7D3F4583D6A45EF6547532B2AE6AC83281317A212223A47ADA92FB48DF055A225DD3E8DF17850EBFAD744780C8166B14F0A39C96B3D216E2247A89518985F6F8";
const char pubXSv[] = "19D3C8A75DACEAB3CE42970BCF3097F712FD3F6D3B171BE55D7AEF6210C48194480E998AFAC181935DCB9E66BD23769AF5E7ABB8ED2A7E5FAABD4FD1F8D24F7C";
const char pubYSv[] = "47A138CDB3C51BEB5443A00FD24734C6DE5DCE6DBA3B2EC337984C09B1CB108E45E8B50F78AEE5FBCA068C0B285576AC26099BD4D52AE2AF9F32A30A340705AF";
// Order of G <- CALCULATED ON MY i7-12700K in 2 hours (single threaded).
const char genOrderSv[] = "4782F84242B0A5E1";
// Computed private key <- CALCULATED ON MY i7-12700K in 5 minutes 40 seconds
const char privateKeySv[] = "15F9B7336005CB82";// or "3189410EE2AADA5F";
*/
/* Unpacks the Windows Server 2003-like Product Key. */
VOID unpackServer(
QWORD (&pRaw)[2],
@ -219,6 +159,30 @@ BOOL verifyServerKey(
// Truncate the hash to 31 bits.
DWORD compHash = BYDWORD(msgDigest) & BITMASK(31);
#ifdef _DEBUG
printf(
"Validating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n AuthInfo: 0x%03lX\n\n Hash: 0x%08lX\n Computed Hash: 0x%08lX\n Signature: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pAuthInfo,
pHash,
compHash,
BN_bn2hex(s)
);
printf(
" K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n",
BN_bn2hex(x),
BN_bn2hex(y)
);
printf(
" compHash %s pHash (%s)\n\n\n",
compHash == pHash ? "==" : "!=",
compHash == pHash ? "VALID" : "INVALID"
);
#endif
BN_free(s);
BN_free(e);
BN_free(x);
@ -386,6 +350,27 @@ VOID generateServerKey(
// Pack product key.
packServer(pRaw, pUpgrade, pChannelID, pHash, pSignature, pAuthInfo);
#ifdef _DEBUG
printf(
"Generating a Server 2003-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n AuthInfo: 0x%03lX\n\n Generator Order: 0x%s\n Private Key: 0x%s\n Seed: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pAuthInfo,
BN_bn2hex(genOrder),
BN_bn2hex(privateKey),
BN_bn2hex(c)
);
printf(
" R(x; y) = {\n 0x%s,\n 0x%s\n }\n\n Signature bits: %02d (%s)\n BN_mod_sqrt(Intermediate): %s\n\n\n",
BN_bn2hex(x),
BN_bn2hex(y),
BN_num_bits(s),
BN_num_bits(s) <= 62 ? "GOOD" : "BAD",
noSquare ? "False" : "True"
);
#endif
EC_POINT_free(r);
} while (pSignature > BITMASK(62) || noSquare);
// ↑ ↑ ↑
@ -405,32 +390,39 @@ VOID generateServerKey(
}
BOOL keyServer(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
) {
// If the Channel ID isn't valid, quit.
if (nChannelID >= 1'000)
return false;
if (pBINK.n == 0 ||
pBINK.k == 0) {
#ifdef _DEBUG
printf("!! NOT IMPLEMENTED !!\n\n");
#endif
return false;
}
BIGNUM *privateKey = BN_new();
BIGNUM *genOrder = BN_new();
BN_hex2bn(&privateKey, privateKeySv);
BN_hex2bn(&genOrder, genOrderSv);
BN_set_word(privateKey, pBINK.k);
BN_set_word(genOrder, pBINK.n);
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve = initializeEllipticCurve(
pSv,
aSv,
bSv,
genXSv,
genYSv,
pubXSv,
pubYSv,
genOrder,
privateKey,
pBINK.binKey.data.p,
pBINK.binKey.data.a,
pBINK.binKey.data.b,
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
&genPoint,
&pubPoint
);
@ -441,9 +433,23 @@ BOOL keyServer(
nAuthInfo &= 0x3FF;
}
do {
generateServerKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nAuthInfo, bUpgrade, pKey);
} while (!verifyServerKey(eCurve, genPoint, pubPoint, pKey));
#ifdef _DEBUG
printf(
"Created elliptic curve:\n\n E = EllipticCurve(\n GF(0x%s),\n [0, 0, 0, %d, %d]\n ) => y^2 = x^3 + %dx + %d;\n\n G(x; y) = {\n 0x%s,\n 0x%s\n }\n\n K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n AuthInfo: 0x%03lX\n\n\n",
pBINK.binKey.data.p,
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
nAuthInfo
);
#endif
return true;
generateServerKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nAuthInfo, bUpgrade, pKey);
return verifyServerKey(eCurve, genPoint, pubPoint, pKey);
}

View File

@ -43,57 +43,54 @@ bool playAudio(HINSTANCE hInstance, WCHAR *lpName, UINT bFlags) {
/* Initializes the elliptic curve. */
EC_GROUP *initializeEllipticCurve(
const char *pSel,
long aSel,
long bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
BIGNUM *genOrderSel,
BIGNUM *privateKeySel,
EC_POINT **genPoint,
EC_POINT **pubPoint
CONST CHAR *pSel,
CONST CHAR *aSel,
CONST CHAR *bSel,
CONST CHAR *generatorXSel,
CONST CHAR *generatorYSel,
CONST CHAR *publicKeyXSel,
CONST CHAR *publicKeyYSel,
EC_POINT **genPoint,
EC_POINT **pubPoint
) {
// Initialize BIGNUM and BIGNUMCTX structures.
// BIGNUM - Large numbers
// BIGNUMCTX - Context large numbers (temporary)
// BN_CTX - Context variables (allow concurrency)
BIGNUM *a, *b, *p, *generatorX, *generatorY, *publicKeyX, *publicKeyY;
BN_CTX *context;
// Microsoft Product Key identification program uses a public key stored in pidgen.dll's BINK resource,
// which is an Elliptic Curve Cryptography (ECC) public key. It can be decomposed into a following mathematical task:
// We're presented with an elliptic curve, a multivariable function y(x; p; a; b), where
// y^2 % p = x^3 + ax + b % p.
// We're presented with an elliptic curve, a multivariable function F(y; x; p; a; b), where
// y^2 = x^3 + ax + b (mod p).
a = BN_new();
b = BN_new();
p = BN_new();
// Public key will consist of the resulting (x; y) values.
// K(x; y) is the resulting point.
publicKeyX = BN_new();
publicKeyY = BN_new();
// G(x; y) is a generator function, its return value represents a point on the elliptic curve.
// G(x; y) is the base point.
generatorX = BN_new();
generatorY = BN_new();
// Context variable
// Context variable.
context = BN_CTX_new();
/* Public data */
// Initialize public data from the BINK resource.
BN_hex2bn(&p, pSel);
BN_set_word(a, aSel);
BN_set_word(b, bSel);
BN_hex2bn(&a, aSel);
BN_hex2bn(&b, bSel);
BN_hex2bn(&generatorX, generatorXSel);
BN_hex2bn(&generatorY, generatorYSel);
BN_hex2bn(&publicKeyX, publicKeyXSel);
BN_hex2bn(&publicKeyY, publicKeyYSel);
/* Elliptical Curve calculations. */
// The group is defined via Fp = all integers [0; p - 1], where p is prime.
// The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the curve given in group.
// Elliptic Curve calculations.
// The abelian group is defined via Galois field Fp - all integers [0; p - 1], where p is prime.
EC_GROUP *eCurve = EC_GROUP_new_curve_GFp(p, a, b, context);
// Create new point for the generator on the elliptic curve and set its coordinates to (genX; genY).
@ -108,7 +105,7 @@ EC_GROUP *initializeEllipticCurve(
assert(EC_POINT_is_on_curve(eCurve, *genPoint, context) == 1);
assert(EC_POINT_is_on_curve(eCurve, *pubPoint, context) == 1);
// Cleanup
// Cleanup.
BN_CTX_free(context);
return eCurve;

View File

@ -13,18 +13,28 @@
HWND hMainWindow;
const WCHAR *pAboutLink = L"https://github.com/Endermanch/XPKeygen",
CONST WCHAR *pAboutLink = L"https://github.com/Endermanch/XPKeygen",
*pWebsite = L"https://malwarewatch.org",
*pVersion = L"2.5",
*pTitle = L"Windows XP Pro SP3 // Server 2003 SP0 x86 VLK - Enderman[ch]",
*pGroupTitle = L"Windows XP Pro SP3 // Server 2003 SP0 x86 VLK",
*pRBText = L"z22 / MSKey / Endermanch ◄ 14/06/2023";
*pTitle = L"Windows 98 - Windows Server 2003 / SP2 x64 VLK - Enderman[ch]",
*pGroupTitle = L"Windows 98 - Windows Server 2003 / SP2 x64 VLK",
*pRBText = L"z22 / MSKey / Endermanch ◄ 14/06/2023",
*pPresets[256] = {
L"Windows 98",
L"Windows 98 (OEM)",
L"Windows XP VLK",
L"Windows XP VLK (OEM)",
L"Windows Server 2003 VLK",
L"Windows Server 2003 VLK (OEM)",
L"Windows XP x64 Edition VLK",
L"Windows XP x64 Edition VLK (OEM)",
};
bool bServer = false,
BOOL bServer = false,
bUpgrade = false,
bMusic = true;
const int w = 615,
CONST INT w = 615,
h = 545,
x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2,
y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
@ -543,26 +553,26 @@ LRESULT CALLBACK WNDProc(HWND hWindow, UINT uMessage, WPARAM wParam, LPARAM lPar
case IDC_COMBO1:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
int nSelect = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
case CBN_SELCHANGE: {
UINT nPresetSelect = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
switch (nSelect) {
case 0:
InitializePreset(nPresetSelect, &pBINKPreset);
if (pBINKPreset.binKey.header.dwVersion == 19980206) {
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT2), true);
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT3), false);
bServer = false;
break;
case 1:
}
else {
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT2), false);
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT3), true);
bServer = true;
break;
}
}
break;
break;
}
}
break;
@ -867,10 +877,11 @@ bool InitializeWindow(HINSTANCE hInstance) {
SendMessageW(hComboBox, WM_SETFONT, (WPARAM)hLabelFont, 0);
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)L"Windows XP (SP0 - SP3)");
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)L"Windows Server 2003 (SP0)");
for (int i = 0; i < countResources(RT_BINK); i++) {
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)pPresets[i]);
}
SendMessageW(hComboBox, CB_SETCURSEL, 0, 0);
SendMessageW(hComboBox, CB_SETCURSEL, 2, 0);
HWND hUpgrade = CreateWindowExW(
WS_EX_WINDOWEDGE,
@ -1040,7 +1051,8 @@ bool InitializeWindow(HINSTANCE hInstance) {
HWND hAuthInfoLabel = CreateWindowExW(
0,
L"Static", L"AuthInfo:",
L"Static",
L"AuthInfo:",
WS_CHILD | WS_VISIBLE,
290, 220 + 1,
70, 16,
@ -1176,6 +1188,8 @@ bool InitializeWindow(HINSTANCE hInstance) {
ShowWindow(hMainWindow, SW_SHOW);
UpdateWindow(hMainWindow);
stopAudio();
MSG uMessage;
while(GetMessageW(&uMessage, nullptr, 0, 0)) {

View File

@ -4,46 +4,6 @@
#include "header.h"
/* Windows XP */
const char pXP[] = "92ddcf14cb9e71f4489a2e9ba350ae29454d98cb93bdbcc07d62b502ea12238ee904a8b20d017197aae0c103b32713a9";
const long aXP = 1;
const long bXP = 0;
// Base point G (Generator)
const char genXXP[] = "46E3775ECE21B0898D39BEA57050D422A0AF989E497962BAEE2CB17E0A28D5360D5476B8DC966443E37A14F1AEF37742";
const char genYXP[] = "7C8E741D2C34F4478E325469CD491603D807222C9C4AC09DDB2B31B3CE3F7CC191B3580079932BC6BEF70BE27604F65E";
// The public key
const char pubXXP[] = "5D8DBE75198015EC41C45AAB6143542EB098F6A5CC9CE4178A1B8A1E7ABBB5BC64DF64FAF6177DC1B0988AB00BA94BF8";
const char pubYXP[] = "23A2909A0B4803C89F910C7191758B48746CEA4D5FF07667444ACDB9512080DBCA55E6EBF30433672B894F44ACE92BFA";
// The order of G was computed in 18 hours using a Pentium III 450
const char genOrderXP[] = "DB6B4C58EFBAFD";
// The private key was computed in 10 hours using a Pentium III 450
const char privateKeyXP[] = "565B0DFF8496C8";
/* Windows 98
const char pXP[] = "ec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029";
const long aXP = 1;
const long bXP = 0;
// Base point G (Generator)
const char genXXP[] = "b5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340";
const char genYXP[] = "a84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b";
// The public key
const char pubXXP[] = "26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811";
const char pubYXP[] = "1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2";
// The order of G was computed in 18 hours using a Pentium III 450
const char genOrderXP[] = "E778E33AEE6B3D";
// The private key was computed in 10 hours using a Pentium III 450
const char privateKeyXP[] = "B9E99B9BB9812E"; // "677A485D4BE4A0";*/
/* Unpacks a Windows XP-like Product Key. */
VOID unpackXP(
QWORD (&pRaw)[2],
@ -172,6 +132,30 @@ BOOL verifyXPKey(
// Truncate the hash to 28 bits.
DWORD compHash = BYDWORD(msgDigest) >> 4 & BITMASK(28);
#ifdef _DEBUG
printf(
"Validating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n Sequence: %d\n\n Hash: 0x%08lX\n Computed Hash: 0x%08lX\n Signature: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pSequence,
pHash,
compHash,
BN_bn2hex(s)
);
printf(
" K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n",
BN_bn2hex(x),
BN_bn2hex(y)
);
printf(
" compHash %s pHash (%s)\n\n\n",
compHash == pHash ? "==" : "!=",
compHash == pHash ? "VALID" : "INVALID"
);
#endif
BN_free(e);
BN_free(s);
BN_free(x);
@ -277,6 +261,26 @@ VOID generateXPKey(
// Pack product key.
packXP(pRaw, pUpgrade, pChannelID, pSequence, pHash, pSignature);
#ifdef _DEBUG
printf(
"Generating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n Sequence: %d\n\n Generator Order: 0x%s\n Private Key: 0x%s\n Seed: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pSequence,
BN_bn2hex(genOrder),
BN_bn2hex(privateKey),
BN_bn2hex(c)
);
printf(
" R(x; y) = {\n 0x%s,\n 0x%s\n }\n\nSignature bits: %02d (%s)\n\n\n",
BN_bn2hex(x),
BN_bn2hex(y),
BN_num_bits(s),
BN_num_bits(s) <= 55 ? "GOOD" : "BAD"
);
#endif
EC_POINT_free(r);
} while (pSignature > BITMASK(55));
// ↑ ↑ ↑
@ -295,39 +299,59 @@ VOID generateXPKey(
}
BOOL keyXP(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
) {
// If the Channel ID or the random sequence aren't valid, quit.
if (nChannelID >= 1'000 || nSequence >= 1'000'000)
return false;
if (pBINK.n == 0 ||
pBINK.k == 0) {
#ifdef _DEBUG
printf("!! NOT IMPLEMENTED !!\n\n");
#endif
return false;
}
BIGNUM *privateKey = BN_new();
BIGNUM *genOrder = BN_new();
BN_hex2bn(&privateKey, privateKeyXP);
BN_hex2bn(&genOrder, genOrderXP);
BN_set_word(privateKey, pBINK.k);
BN_set_word(genOrder, pBINK.n);
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve = initializeEllipticCurve(
pXP,
aXP,
bXP,
genXXP,
genYXP,
pubXXP,
pubYXP,
genOrder,
privateKey,
pBINK.binKey.data.p,
pBINK.binKey.data.a,
pBINK.binKey.data.b,
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
&genPoint,
&pubPoint
);
do {
generateXPKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nSequence, bUpgrade, pKey);
} while (!verifyXPKey(eCurve, genPoint, pubPoint, pKey));
#ifdef _DEBUG
printf(
"Created elliptic curve:\n\n E = EllipticCurve(\n GF(0x%s),\n [0, 0, 0, %d, %d]\n ) => y^2 = x^3 + %dx + %d;\n\n G(x; y) = {\n 0x%s,\n 0x%s\n }\n\n K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n\n",
pBINK.binKey.data.p,
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y
);
#endif
return true;
generateXPKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nSequence, bUpgrade, pKey);
return verifyXPKey(eCurve, genPoint, pubPoint, pKey);
}