mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2024-12-22 20:40:16 +02:00
Complete rewrite of XP Algorithm (w/ comments). Now fully optimized and readable
This commit is contained in:
parent
21e31fd1b6
commit
9812529903
40
src/header.h
40
src/header.h
@ -28,20 +28,26 @@
|
|||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/ec.h>
|
#include <openssl/ec.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
// Algorithm macros
|
// Algorithm macros
|
||||||
#define PK_LENGTH 25
|
#define PK_LENGTH 25
|
||||||
#define NULL_TERMINATOR 1
|
#define NULL_TERMINATOR 1
|
||||||
|
|
||||||
#define FIELD_BITS 384
|
#define FIELD_BITS 384
|
||||||
#define FIELD_BYTES 48
|
#define FIELD_BYTES 48
|
||||||
#define FIELD_BITS_2003 512
|
#define FIELD_BITS_2003 512
|
||||||
#define FIELD_BYTES_2003 64
|
#define FIELD_BYTES_2003 64
|
||||||
|
|
||||||
#define NEXTSNBITS(field, n, offset) (((QWORD)field >> offset) & ((1ULL << (n)) - 1))
|
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
|
||||||
|
|
||||||
|
#define NEXTSNBITS(field, n, offset) (((QWORD)field >> offset) & ((1ULL << (n)) - 1))
|
||||||
#define FIRSTNBITS(field, n) NEXTSNBITS(field, n, 0)
|
#define FIRSTNBITS(field, n) NEXTSNBITS(field, n, 0)
|
||||||
|
|
||||||
|
#define BYDWORD(n) (n[0] | n[1] << 8 | n[2] << 16 | n[3] << 24)
|
||||||
|
#define BITMASK(n) ((1ULL << n) - 1)
|
||||||
|
|
||||||
// Confirmation ID generator constants
|
// Confirmation ID generator constants
|
||||||
#define SUCCESS 0
|
#define SUCCESS 0
|
||||||
#define ERR_TOO_SHORT 1
|
#define ERR_TOO_SHORT 1
|
||||||
@ -62,7 +68,9 @@ typedef uint64_t QWORD;
|
|||||||
extern char pCharset[];
|
extern char pCharset[];
|
||||||
|
|
||||||
// util.cpp
|
// util.cpp
|
||||||
|
int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
|
||||||
void endian(BYTE *data, int length);
|
void endian(BYTE *data, int length);
|
||||||
|
|
||||||
EC_GROUP *initializeEllipticCurve(
|
EC_GROUP *initializeEllipticCurve(
|
||||||
std::string pSel,
|
std::string pSel,
|
||||||
std::string aSel,
|
std::string aSel,
|
||||||
@ -71,8 +79,8 @@ EC_GROUP *initializeEllipticCurve(
|
|||||||
std::string generatorYSel,
|
std::string generatorYSel,
|
||||||
std::string publicKeyXSel,
|
std::string publicKeyXSel,
|
||||||
std::string publicKeyYSel,
|
std::string publicKeyYSel,
|
||||||
EC_POINT *&genPoint,
|
EC_POINT *&genPoint,
|
||||||
EC_POINT *&pubPoint
|
EC_POINT *&pubPoint
|
||||||
);
|
);
|
||||||
|
|
||||||
// key.cpp
|
// key.cpp
|
||||||
@ -98,18 +106,18 @@ void showHelp(char *argv[]);
|
|||||||
// xp.cpp
|
// xp.cpp
|
||||||
bool verifyXPKey(
|
bool verifyXPKey(
|
||||||
EC_GROUP *eCurve,
|
EC_GROUP *eCurve,
|
||||||
EC_POINT *generator,
|
EC_POINT *basePoint,
|
||||||
EC_POINT *publicKey,
|
EC_POINT *publicKey,
|
||||||
char (&cdKey)[25]
|
char (&cdKey)[25]
|
||||||
);
|
);
|
||||||
|
|
||||||
void generateXPKey(
|
void generateXPKey(
|
||||||
EC_GROUP *eCurve,
|
EC_GROUP *eCurve,
|
||||||
EC_POINT *generator,
|
EC_POINT *basePoint,
|
||||||
BIGNUM *order,
|
BIGNUM *genOrder,
|
||||||
BIGNUM *privateKey,
|
BIGNUM *privateKey,
|
||||||
DWORD pRaw,
|
DWORD pSerial,
|
||||||
char (&cdKey)[25]
|
char (&cdKey)[25]
|
||||||
);
|
);
|
||||||
|
|
||||||
// server.cpp
|
// server.cpp
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
//
|
||||||
|
// Created by Andrew on 01/06/2023.
|
||||||
|
//
|
||||||
|
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
|
|
||||||
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
||||||
|
15
src/util.cpp
15
src/util.cpp
@ -85,3 +85,18 @@ EC_GROUP *initializeEllipticCurve(
|
|||||||
|
|
||||||
return eCurve;
|
return eCurve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen) {
|
||||||
|
if (a == nullptr || to == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int len = BN_bn2bin(a, to);
|
||||||
|
|
||||||
|
if (len > tolen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
|
||||||
|
endian(to, tolen);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
309
src/xp.cpp
309
src/xp.cpp
@ -1,23 +1,10 @@
|
|||||||
/*
|
//
|
||||||
Windows XP CD Key Verification/Generator v0.03
|
// Created by Andrew on 01/06/2023.
|
||||||
by z22
|
//
|
||||||
|
|
||||||
Compile with OpenSSL libs, modify to suit your needs.
|
|
||||||
http://gnuwin32.sourceforge.net/packages/openssl.htm
|
|
||||||
|
|
||||||
History:
|
|
||||||
0.03 Stack corruptionerror on exit fixed (now pkey is large enough)
|
|
||||||
More Comments added
|
|
||||||
0.02 Changed name the *.cpp;
|
|
||||||
Fixed minor bugs & Make it compilable on VC++
|
|
||||||
0.01 First version compilable MingW
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
|
|
||||||
/* Unpacks the Windows XP Product Key. */
|
/* Unpacks the Windows XP-like Product Key. */
|
||||||
void unpackXP(
|
void unpackXP(
|
||||||
QWORD (&pRaw)[2],
|
QWORD (&pRaw)[2],
|
||||||
DWORD &pSerial,
|
DWORD &pSerial,
|
||||||
@ -37,7 +24,7 @@ void unpackXP(
|
|||||||
pSignature = FIRSTNBITS(pRaw[1], 51) << 5 | NEXTSNBITS(pRaw[0], 5, 59);
|
pSignature = FIRSTNBITS(pRaw[1], 51) << 5 | NEXTSNBITS(pRaw[0], 5, 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Packs the Windows XP Product Key. */
|
/* Packs the Windows XP-like Product Key. */
|
||||||
void packXP(
|
void packXP(
|
||||||
QWORD (&pRaw)[2],
|
QWORD (&pRaw)[2],
|
||||||
DWORD pSerial,
|
DWORD pSerial,
|
||||||
@ -53,213 +40,207 @@ void packXP(
|
|||||||
pRaw[1] = NEXTSNBITS(pSignature, 51, 5);
|
pRaw[1] = NEXTSNBITS(pSignature, 51, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify Product Key */
|
/* Verifies the Windows XP-like Product Key. */
|
||||||
bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, char (&cdKey)[25]) {
|
bool verifyXPKey(
|
||||||
BN_CTX *context = BN_CTX_new();
|
EC_GROUP *eCurve,
|
||||||
|
EC_POINT *basePoint,
|
||||||
|
EC_POINT *publicKey,
|
||||||
|
char (&cdKey)[25]
|
||||||
|
) {
|
||||||
|
BN_CTX *numContext = BN_CTX_new();
|
||||||
|
|
||||||
|
QWORD pRaw[2]{},
|
||||||
|
pSignature = 0;
|
||||||
|
|
||||||
|
DWORD pSerial = 0,
|
||||||
|
pHash = 0;
|
||||||
|
|
||||||
// Convert Base24 CD-key to bytecode.
|
// Convert Base24 CD-key to bytecode.
|
||||||
QWORD bKey[2]{};
|
unbase24((BYTE *)pRaw, cdKey);
|
||||||
DWORD pID, checkHash;
|
|
||||||
|
|
||||||
QWORD sig = 0;
|
// Extract RPK, hash and signature from bytecode.
|
||||||
|
unpackXP(pRaw, pSerial, pHash, pSignature);
|
||||||
|
|
||||||
unbase24((BYTE *)bKey, cdKey);
|
/*
|
||||||
|
*
|
||||||
|
* Scalars:
|
||||||
|
* e = Hash
|
||||||
|
* s = Schnorr Signature
|
||||||
|
*
|
||||||
|
* Points:
|
||||||
|
* G(x, y) = Generator (Base Point)
|
||||||
|
* K(x, y) = Public Key
|
||||||
|
*
|
||||||
|
* Equation:
|
||||||
|
* P = sG + eK
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
// Extract data, hash and signature from the bytecode.
|
BIGNUM *e = BN_lebin2bn((BYTE *)&pHash, sizeof(pHash), nullptr),
|
||||||
unpackXP(bKey, pID, checkHash, sig);
|
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr),
|
||||||
|
*x = BN_new(),
|
||||||
|
*y = BN_new();
|
||||||
|
|
||||||
// e = Hash
|
// Create 2 points on the elliptic curve.
|
||||||
// s = Signature
|
EC_POINT *t = EC_POINT_new(eCurve);
|
||||||
BIGNUM *e, *s;
|
EC_POINT *p = EC_POINT_new(eCurve);
|
||||||
|
|
||||||
// Put hash word into BigNum e.
|
// t = sG
|
||||||
e = BN_new();
|
EC_POINT_mul(eCurve, t, nullptr, basePoint, s, numContext);
|
||||||
BN_set_word(e, checkHash);
|
|
||||||
|
|
||||||
// Reverse signature and create a new BigNum s.
|
// p = eK
|
||||||
endian((BYTE *)&sig, sizeof(sig));
|
EC_POINT_mul(eCurve, p, nullptr, publicKey, e, numContext);
|
||||||
s = BN_bin2bn((BYTE *)&sig, sizeof(sig), nullptr);
|
|
||||||
|
|
||||||
// Create x and y.
|
// p += t
|
||||||
BIGNUM *x = BN_new();
|
EC_POINT_add(eCurve, p, t, p, numContext);
|
||||||
BIGNUM *y = BN_new();
|
|
||||||
|
|
||||||
// Create 2 new points on the existing elliptic curve.
|
// x = p.x; y = p.y;
|
||||||
EC_POINT *u = EC_POINT_new(eCurve);
|
EC_POINT_get_affine_coordinates(eCurve, p, x, y, numContext);
|
||||||
EC_POINT *v = EC_POINT_new(eCurve);
|
|
||||||
|
|
||||||
// EC_POINT_mul calculates r = generator * n + q * m.
|
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||||
// v = s * generator + e * (-publicKey)
|
msgBuffer[SHA_MSG_LENGTH_XP]{},
|
||||||
|
xBin[FIELD_BYTES]{},
|
||||||
|
yBin[FIELD_BYTES]{};
|
||||||
|
|
||||||
// u = generator * s
|
DWORD compHash;
|
||||||
EC_POINT_mul(eCurve, u, nullptr, generator, s, context);
|
|
||||||
|
|
||||||
// v = publicKey * e
|
// Convert resulting point coordinates to bytes.
|
||||||
EC_POINT_mul(eCurve, v, nullptr, publicKey, e, context);
|
BN_bn2lebin(x, xBin, FIELD_BYTES);
|
||||||
|
BN_bn2lebin(y, yBin, FIELD_BYTES);
|
||||||
|
|
||||||
// v += u
|
// Assemble the SHA message.
|
||||||
EC_POINT_add(eCurve, v, u, v, context);
|
memcpy((void *)&msgBuffer[0], (void *)&pSerial, 4);
|
||||||
|
memcpy((void *)&msgBuffer[4], (void *)xBin, FIELD_BYTES);
|
||||||
|
memcpy((void *)&msgBuffer[4 + FIELD_BYTES], (void *)yBin, FIELD_BYTES);
|
||||||
|
|
||||||
// EC_POINT_get_affine_coordinates() sets x and y, either of which may be nullptr, to the corresponding coordinates of p.
|
// Retrieve the message digest.
|
||||||
// x = v.x; y = v.y;
|
SHA1(msgBuffer, SHA_MSG_LENGTH_XP, msgDigest);
|
||||||
EC_POINT_get_affine_coordinates(eCurve, v, x, y, context);
|
|
||||||
|
|
||||||
BYTE buf[FIELD_BYTES], md[SHA_DIGEST_LENGTH], t[4];
|
// Translate the byte digest into a 32-bit integer - this is our computed hash.
|
||||||
DWORD newHash;
|
// Truncate the hash to 28 bits.
|
||||||
|
compHash = BYDWORD(msgDigest) >> 4;
|
||||||
SHA_CTX hContext;
|
compHash &= BITMASK(28);
|
||||||
|
|
||||||
// h = First32(SHA-1(pID || v.x || v.y)) >> 4
|
|
||||||
SHA1_Init(&hContext);
|
|
||||||
|
|
||||||
// Chop Product ID into 4 bytes.
|
|
||||||
t[0] = (pID & 0xff); // First 8 bits
|
|
||||||
t[1] = (pID & 0xff00) >> 8; // Second 8 bits
|
|
||||||
t[2] = (pID & 0xff0000) >> 16; // Third 8 bits
|
|
||||||
t[3] = (pID & 0xff000000) >> 24; // Fourth 8 bits
|
|
||||||
|
|
||||||
// Hash chunk of data.
|
|
||||||
SHA1_Update(&hContext, t, sizeof(t));
|
|
||||||
|
|
||||||
// Empty buffer, place v.x in little-endian.
|
|
||||||
memset(buf, 0, FIELD_BYTES);
|
|
||||||
BN_bn2bin(x, buf);
|
|
||||||
endian(buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Hash chunk of data.
|
|
||||||
SHA1_Update(&hContext, buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Empty buffer, place v.y in little-endian.
|
|
||||||
memset(buf, 0, FIELD_BYTES);
|
|
||||||
BN_bn2bin(y, buf);
|
|
||||||
endian(buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Hash chunk of data.
|
|
||||||
SHA1_Update(&hContext, buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Store the final message from hContext in md.
|
|
||||||
SHA1_Final(md, &hContext);
|
|
||||||
|
|
||||||
// h = First32(SHA-1(pID || v.x || v.y)) >> 4
|
|
||||||
newHash = (md[0] | (md[1] << 8) | (md[2] << 16) | (md[3] << 24)) >> 4;
|
|
||||||
newHash &= 0xfffffff;
|
|
||||||
|
|
||||||
BN_free(e);
|
BN_free(e);
|
||||||
BN_free(s);
|
BN_free(s);
|
||||||
BN_free(x);
|
BN_free(x);
|
||||||
BN_free(y);
|
BN_free(y);
|
||||||
|
|
||||||
BN_CTX_free(context);
|
BN_CTX_free(numContext);
|
||||||
|
|
||||||
EC_POINT_free(u);
|
EC_POINT_free(t);
|
||||||
EC_POINT_free(v);
|
EC_POINT_free(p);
|
||||||
|
|
||||||
// If we managed to generate a key with the same hash, the key is correct.
|
// If the computed hash checks out, the key is valid.
|
||||||
return newHash == checkHash;
|
return compHash == pHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a valid Product Key. */
|
/* Generate a valid Product Key. */
|
||||||
void generateXPKey(EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *order, BIGNUM *privateKey, DWORD pRaw, char (&pKey)[25]) {
|
void generateXPKey(
|
||||||
EC_POINT *r = EC_POINT_new(eCurve);
|
EC_GROUP *eCurve,
|
||||||
BN_CTX *ctx = BN_CTX_new();
|
EC_POINT *basePoint,
|
||||||
|
BIGNUM *genOrder,
|
||||||
|
BIGNUM *privateKey,
|
||||||
|
DWORD pSerial,
|
||||||
|
char (&pKey)[25]
|
||||||
|
) {
|
||||||
|
BN_CTX *numContext = BN_CTX_new();
|
||||||
|
|
||||||
BIGNUM *c = BN_new();
|
BIGNUM *c = BN_new();
|
||||||
BIGNUM *s = BN_new();
|
BIGNUM *s = BN_new();
|
||||||
BIGNUM *x = BN_new();
|
BIGNUM *x = BN_new();
|
||||||
BIGNUM *y = BN_new();
|
BIGNUM *y = BN_new();
|
||||||
|
|
||||||
QWORD bKey[2]{};
|
QWORD pRaw[2]{};
|
||||||
|
|
||||||
do {
|
do {
|
||||||
DWORD hash = 0;
|
EC_POINT *r = EC_POINT_new(eCurve);
|
||||||
QWORD sig = 0;
|
|
||||||
|
|
||||||
memset(bKey, 0, 2 * sizeof(QWORD));
|
QWORD pSignature = 0;
|
||||||
|
DWORD pHash;
|
||||||
|
|
||||||
// Generate a random number c consisting of 384 bits without any constraints.
|
// Generate a random number c consisting of 384 bits without any constraints.
|
||||||
BN_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
|
BN_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
|
||||||
|
|
||||||
// r = generator * c;
|
// Pick a random derivative of the base point on the elliptic curve.
|
||||||
EC_POINT_mul(eCurve, r, nullptr, generator, c, ctx);
|
// R = cG;
|
||||||
|
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);
|
||||||
|
|
||||||
// x = r.x; y = r.y;
|
// Acquire its coordinates.
|
||||||
EC_POINT_get_affine_coordinates(eCurve, r, x, y, ctx);
|
// x = R.x; y = R.y;
|
||||||
|
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
|
||||||
|
|
||||||
SHA_CTX hContext;
|
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||||
BYTE md[SHA_DIGEST_LENGTH]{}, buf[FIELD_BYTES]{}, t[4]{};
|
msgBuffer[SHA_MSG_LENGTH_XP]{},
|
||||||
|
xBin[FIELD_BYTES]{},
|
||||||
|
yBin[FIELD_BYTES]{};
|
||||||
|
|
||||||
// h = (First-32(SHA1(pRaw, r.x, r.y)) >> 4
|
// Convert coordinates to bytes.
|
||||||
SHA1_Init(&hContext);
|
BN_bn2lebin(x, xBin, FIELD_BYTES);
|
||||||
|
BN_bn2lebin(y, yBin, FIELD_BYTES);
|
||||||
|
|
||||||
// Chop Raw Product Key into 4 bytes.
|
// Assemble the SHA message.
|
||||||
t[0] = (pRaw & 0xff);
|
memcpy((void *)&msgBuffer[0], (void *)&pSerial, 4);
|
||||||
t[1] = (pRaw & 0xff00) >> 8;
|
memcpy((void *)&msgBuffer[4], (void *)xBin, FIELD_BYTES);
|
||||||
t[2] = (pRaw & 0xff0000) >> 16;
|
memcpy((void *)&msgBuffer[4 + FIELD_BYTES], (void *)yBin, FIELD_BYTES);
|
||||||
t[3] = (pRaw & 0xff000000) >> 24;
|
|
||||||
|
|
||||||
// Hash chunk of data.
|
// Retrieve the message digest.
|
||||||
SHA1_Update(&hContext, t, sizeof(t));
|
SHA1(msgBuffer, SHA_MSG_LENGTH_XP, msgDigest);
|
||||||
|
|
||||||
// Empty buffer, place r.x in little-endian
|
// Translate the byte digest into a 32-bit integer - this is our computed pHash.
|
||||||
memset(buf, 0, FIELD_BYTES);
|
// Truncate the pHash to 28 bits.
|
||||||
BN_bn2bin(x, buf);
|
pHash = BYDWORD(msgDigest) >> 4;
|
||||||
endian(buf, FIELD_BYTES);
|
pHash &= BITMASK(28);
|
||||||
|
|
||||||
// Hash chunk of data.
|
/*
|
||||||
SHA1_Update(&hContext, buf, FIELD_BYTES);
|
*
|
||||||
|
* Scalars:
|
||||||
|
* c = Random multiplier
|
||||||
|
* e = Hash
|
||||||
|
* s = Signature
|
||||||
|
* n = Order of G
|
||||||
|
* k = Private Key
|
||||||
|
* K = Public Key
|
||||||
|
*
|
||||||
|
* Points:
|
||||||
|
* G(x, y) = Generator (Base Point)
|
||||||
|
*
|
||||||
|
* We need to find the signature s that satisfies the equation with a given hash:
|
||||||
|
* P = sG + eK
|
||||||
|
* s = ek + c (mod n) <- computation optimization
|
||||||
|
*/
|
||||||
|
|
||||||
// Empty buffer, place r.y in little-endian.
|
// s = ek;
|
||||||
memset(buf, 0, FIELD_BYTES);
|
|
||||||
BN_bn2bin(y, buf);
|
|
||||||
endian(buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Hash chunk of data.
|
|
||||||
SHA1_Update(&hContext, buf, FIELD_BYTES);
|
|
||||||
|
|
||||||
// Store the final message from hContext in md.
|
|
||||||
SHA1_Final(md, &hContext);
|
|
||||||
|
|
||||||
// h = (First-32(SHA1(pRaw, r.x, r.y)) >> 4
|
|
||||||
hash = (md[0] | (md[1] << 8) | (md[2] << 16) | (md[3] << 24)) >> 4;
|
|
||||||
hash &= 0xfffffff;
|
|
||||||
|
|
||||||
/* s = privateKey * hash + c; */
|
|
||||||
// s = privateKey;
|
|
||||||
BN_copy(s, privateKey);
|
BN_copy(s, privateKey);
|
||||||
|
BN_mul_word(s, pHash);
|
||||||
|
|
||||||
// s *= hash;
|
// s += c (mod n)
|
||||||
BN_mul_word(s, hash);
|
BN_mod_add(s, s, c, genOrder, numContext);
|
||||||
|
|
||||||
// BN_mod_add() adds a to b % m and places the non-negative result in r.
|
// Translate resulting scalar into a 64-bit integer (the byte order is little-endian).
|
||||||
// s = |s + c % order|;
|
BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s));
|
||||||
BN_mod_add(s, s, c, order, ctx);
|
|
||||||
|
|
||||||
// Convert s from BigNum back to bytecode and reverse the endianness.
|
|
||||||
BN_bn2bin(s, (BYTE *)&sig);
|
|
||||||
endian((BYTE *)&sig, BN_num_bytes(s));
|
|
||||||
|
|
||||||
// Pack product key.
|
// Pack product key.
|
||||||
packXP(bKey, pRaw, hash, sig);
|
packXP(pRaw, pSerial, pHash, pSignature);
|
||||||
|
|
||||||
//printf("PID: %.8X\nHash: %.8X\nSig: %.8X %.8X\n", pRaw[0], hash, sig[1], sig[0]);
|
std::cout << " Serial: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSerial << std::endl
|
||||||
std::cout << " PID: " << std::hex << std::setw(8) << std::setfill('0') << pRaw << std::endl
|
<< " Hash: 0x" << std::hex << std::setw(8) << std::setfill('0') << pHash << std::endl
|
||||||
<< "Hash: " << std::hex << std::setw(8) << std::setfill('0') << hash << std::endl
|
<< " Signature: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSignature << std::endl
|
||||||
<< " Sig: " << std::hex << std::setw(8) << std::setfill('0') << sig << std::endl
|
<< std::endl;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
} while (bKey[1] >= (1ULL << 50));
|
EC_POINT_free(r);
|
||||||
|
} while (pRaw[1] > BITMASK(50));
|
||||||
// ↑ ↑ ↑
|
// ↑ ↑ ↑
|
||||||
// bKey[1] can't be longer than 50 bits, else the signature part will make
|
// pRaw[1] can't be longer than 50 bits, else the signature part
|
||||||
// the CD-key longer than 25 characters.
|
// will make the CD-key longer than 25 characters.
|
||||||
|
|
||||||
// Convert the key to Base24.
|
// Convert bytecode to Base24 CD-key.
|
||||||
base24(pKey, (BYTE *)bKey);
|
base24(pKey, (BYTE *)pRaw);
|
||||||
|
|
||||||
BN_free(c);
|
BN_free(c);
|
||||||
BN_free(s);
|
BN_free(s);
|
||||||
BN_free(x);
|
BN_free(x);
|
||||||
BN_free(y);
|
BN_free(y);
|
||||||
|
|
||||||
BN_CTX_free(ctx);
|
BN_CTX_free(numContext);
|
||||||
EC_POINT_free(r);
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user