refactor/rework confid

This commit is contained in:
Neo-Desktop 2023-12-09 18:50:47 -08:00
parent 72d48dd38b
commit 8cc691b72f
12 changed files with 1463 additions and 945 deletions

2
.idea/UMSKT.iml Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

90
.idea/editor.xml Normal file
View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BackendCodeEditorSettings">
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/UMSKT.iml" filepath="$PROJECT_DIR$/.idea/UMSKT.iml" />
</modules>
</component>
</project>

View File

@ -185,7 +185,7 @@ CPMAddPackage(
### Resource compilation
CMRC_ADD_RESOURCE_LIBRARY(umskt-rc ALIAS umskt::rc NAMESPACE umskt keys.json)
SET(LIBUMSKT_SRC src/libumskt/libumskt.cpp src/libumskt/pidgen3/BINK1998.cpp src/libumskt/pidgen3/BINK2002.cpp src/libumskt/pidgen3/key.cpp src/libumskt/pidgen3/util.cpp src/libumskt/confid/confid.cpp src/libumskt/pidgen2/PIDGEN2.cpp src/libumskt/debugoutput.cpp)
SET(LIBUMSKT_SRC src/libumskt/libumskt.cpp src/libumskt/pidgen3/BINK1998.cpp src/libumskt/pidgen3/BINK2002.cpp src/libumskt/pidgen3/key.cpp src/libumskt/pidgen3/util.cpp src/libumskt/confid/confid.cpp src/libumskt/confid/polynomial.cpp src/libumskt/confid/residue.cpp src/libumskt/confid/divisor.cpp src/libumskt/pidgen2/PIDGEN2.cpp src/libumskt/debugoutput.cpp)
#### Separate Build Path for emscripten
IF (EMSCRIPTEN)

167
keys.json
View File

@ -93,6 +93,9 @@
"Plus! Digital Media Edition for Windows XP": {
"BINK": ["52", "53"]
},
"Rise of Nations - Rise of Legends": {
"BINK": ["52", "53"]
},
"Windows Longhorn (6.0.4033.0)": {
"BINK": ["54", "55"]
},
@ -1532,6 +1535,11 @@
},
"Activation": {
"Windows XP": {
"flags": {
"XPBrand": true,
"Office": false,
"version": 0
},
"p": "102011604035381881",
"x": {
"0": "0",
@ -1543,23 +1551,55 @@
},
"mul": "65537",
"priv": "1315384396487572637498562978064321",
"iid_key": "1791516372"
"iid_key": "6AC85ED4",
"non_residue": "43",
"mod_constants": {
"0": "0x604FA6A1C6346A87",
"1": "0x2D351C6D04F8B",
"2": "0x604FA6A1C6346A87",
"3": "0x2D351C6D04F8B"
},
"verification": {
"low": "351874082296375233",
"hi": "71307131016268"
}
},
"Windows XP Plus! Digital Media Edition": {
"p": "101996933280717187",
"Whistler": {
"flags": {
"XPBrand": false,
"Office": false,
"version": 1
},
"p": "102413083413401507",
"x": {
"0": "14442243999705614",
"1": "88154401999011195",
"2": "86996763276881336",
"3": "95455813375647760",
"4": "6252462837094107",
"0": "0",
"1": "62766224015201615",
"2": "45663410017725669",
"3": "38799131826419821",
"4": "57597400967455908",
"5": "1"
},
"mul": "65537",
"priv": "2752030625102368166730185283969067",
"iid_key": "1791516372"
"mul": "",
"priv": "",
"iid_key": "6AC85ED4",
"non_residue": "2",
"mod_constants": {
"0": "",
"1": "",
"2": "",
"3": ""
},
"verification": {
"low": "",
"hi": ""
}
},
"Office XP / Office 2003": {
"Office XP": {
"flags": {
"XPBrand": true,
"Office": true,
"version": 1
},
"p": "103099955908255721",
"x": {
"0": "0",
@ -1571,7 +1611,108 @@
},
"mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "1513142771"
"iid_key": "5A30B9F3",
"non_residue": "3",
"mod_constants": {
"0": "0x4FA8E4A40CDAE44A",
"1": "0x2CBAF12A59BBE",
"2": "0x4FA8E4A40CDAE44A",
"3": "0x2CBAF12A59BBE"
},
"verification": {
"low": "17284868327322833729",
"hi": "558057793417439"
}
},
"Office 2003": {
"flags": {
"XPBrand": false,
"Office": true,
"version": 3
},
"p": "103099955908255721",
"x": {
"0": "0",
"1": "64728167274549202",
"2": "4488766805843809",
"3": "70698430483539942",
"4": "64728167274549202",
"5": "1"
},
"mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "5A30B9F3",
"non_residue": "3",
"mod_constants": {
"0": "0x4FA8E4A40CDAE44A",
"1": "0x2CBAF12A59BBE",
"2": "0x4FA8E4A40CDAE44A",
"3": "0x2CBAF12A59BBE"
},
"verification": {
"low": "17284868327322833729",
"hi": "558057793417439"
}
},
"Office 2007": {
"flags": {
"XPBrand": false,
"Office": true,
"version": 4
},
"p": "103099955908255721",
"x": {
"0": "0",
"1": "64728167274549202",
"2": "4488766805843809",
"3": "70698430483539942",
"4": "64728167274549202",
"5": "1"
},
"mul": "65537",
"priv": "10294349293510589382098112327865153",
"iid_key": "5A30B9F3",
"non_residue": "3",
"mod_constants": {
"0": "0x4FA8E4A40CDAE44A",
"1": "0x2CBAF12A59BBE",
"2": "0x4FA8E4A40CDAE44A",
"3": "0x2CBAF12A59BBE"
},
"verification": {
"low": "17284868327322833729",
"hi": "558057793417439"
}
},
"Plus! Digital Media Edition for Windows XP": {
"flags": {
"XPBrand": true,
"Office": false,
"version": 4
},
"p": "101996933280717187",
"x": {
"0": "14442243999705614",
"1": "88154401999011195",
"2": "86996763276881336",
"3": "95455813375647760",
"4": "6252462837094107",
"5": "1"
},
"mul": "65537",
"priv": "2752030625102368166730185283969067",
"iid_key": "6AC85ED4",
"non_residue": "2",
"mod_constants": {
"0": "0x2C5C4D3654A594F0",
"1": "0x2D36C691A4EA5",
"2": "0x2C5C4D3654A594F0",
"3": "0x2D36C691A4EA5"
},
"verification": {
"low": "8953812210935468417",
"hi": "499255905936912"
}
}
}
}

View File

@ -253,7 +253,7 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
}
if (options->list) {
for (auto el : (*keys)["Products"].items()) {
for (auto const el : (*keys)["Products"].items()) {
int id;
sscanf((el.value()["BINK"][0]).get<std::string>().c_str(), "%x", &id);
std::cout << el.key() << ": " << el.value()["BINK"] << std::endl;
@ -426,7 +426,7 @@ int CLI::BINK1998Generate() {
sscanf(cRaw, "%d", &oRaw);
nRaw += (oRaw % 999999); // ensure our serial is less than 999999
BN_free(bnrand);
BN_free(bnrand);
}
if (this->options.verbose) {
@ -464,9 +464,11 @@ int CLI::BINK1998Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
if (this->options.nonewlines == false) {
fmt::print("\n");
if (!options.nonewlines) {
fmt::print("\n");
}
return 0;
}
@ -512,8 +514,9 @@ int CLI::BINK2002Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
if (this->options.nonewlines == false) {
fmt::print("\n");
if (!this->options.nonewlines) {
fmt::print("\n");
}
return 0;
@ -588,8 +591,8 @@ int CLI::ConfirmationID() {
case SUCCESS:
fmt::print(confirmation_id);
if (this->options.nonewlines == false) {
fmt::print("\n");
if (!this->options.nonewlines) {
fmt::print("\n");
}
return 0;

View File

@ -36,14 +36,6 @@
CMRC_DECLARE(umskt);
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
};
enum MODE {
MODE_BINK1998_GENERATE = 0,
MODE_BINK2002_GENERATE = 1,

File diff suppressed because it is too large Load Diff

View File

@ -26,48 +26,128 @@
#include "../libumskt.h"
// Confirmation ID generator constants
#define SUCCESS 0
#define ERR_TOO_SHORT 1
#define ERR_TOO_LARGE 2
#define ERR_INVALID_CHARACTER 3
#define ERR_INVALID_CHECK_DIGIT 4
#define ERR_UNKNOWN_VERSION 5
#define ERR_UNLUCKY 6
enum CONFIRMATION_ID_STATUS {
SUCCESS = 0,
ERR_TOO_SHORT = 1,
ERR_TOO_LARGE = 2,
ERR_INVALID_CHARACTER = 3,
ERR_INVALID_CHECK_DIGIT = 4,
ERR_UNKNOWN_VERSION = 5,
ERR_UNLUCKY = 6
};
#define BAD 0xFFFFFFFFFFFFFFFFull
typedef struct {
QWORD u[2];
QWORD v[2];
} TDivisor;
EXPORT class ConfirmationID {
static int calculateCheckDigit(int pid);
static QWORD residue_add(QWORD x, QWORD y);
static QWORD residue_sub(QWORD x, QWORD y);
static QWORD __umul128(QWORD a, QWORD b, QWORD* hi);
static QWORD ui128_quotient_mod(QWORD lo, QWORD hi);
static QWORD residue_mul(QWORD x, QWORD y);
static QWORD residue_pow(QWORD x, QWORD y);
static QWORD inverse(QWORD u, QWORD v);
static QWORD residue_inv(QWORD x);
static QWORD residue_sqrt(QWORD what);
static int find_divisor_v(TDivisor* d);
static int polynomial_mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]);
static int polynomial_div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient);
static void polynomial_xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int* pgcddeg, QWORD gcd[3], int* pmult1deg, QWORD mult1[3], int* pmult2deg, QWORD mult2[3]);
static int u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2]);
static void divisor_add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst);
static void divisor_mul(const TDivisor* src, QWORD mult, TDivisor* dst);
static void divisor_mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst);
static unsigned rol(unsigned x, int shift);
static void sha1_single_block(unsigned char input[64], unsigned char output[20]);
static void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version);
static void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
public:
static int Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid);
//EXPORT static int CLIRun();
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
};
EXPORT class ConfirmationID {
QWORD MOD = 0, NON_RESIDUE = 0;
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
QWORD p[4] = { 0x0, 0x0, 0x0, 0x0 };
QWORD u[2] = { 0x0, 0x0 };
unsigned char iid_key[4] = { 0x0, 0x0, 0x0, 0x0};
BOOL isOffice = false, isXPBrand = false;
unsigned flagVersion = 0;
public:
void setFlagVersion(unsigned int flagVersion);
private:
int calculateCheckDigit(int pid);
void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version);
void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
friend class Residue;
Residue *residue;
friend class Polynomial;
Polynomial *polynomial;
friend class Divisor;
Divisor *divisor;
public:
int Generate(const char* installation_id_str, char confirmation_id[49], std::string productid);
void setMod(QWORD mod);
void setNonResidue(QWORD nonResidue);
void setPValues(QWORD p0, QWORD p1, QWORD p2, QWORD p3);
void setPValues(QWORD pValues[4]);
void setFValues(QWORD f0, QWORD f1, QWORD f2, QWORD f3, QWORD f4, QWORD f5);
void setFValues(QWORD fValues[6]);
void setIsOffice(BOOL isOffice);
void setIsXPBrand(BOOL isXpBrand);
ConfirmationID() {
residue = new Residue(this);
polynomial = new Polynomial(this);
divisor = new Divisor(this);
}
~ConfirmationID() {
delete residue, polynomial, divisor;
}
};
class Residue {
ConfirmationID *parent;
public:
explicit Residue(ConfirmationID *in) {
parent = in;
}
QWORD add(QWORD x, QWORD y);
QWORD sub(QWORD x, QWORD y);
QWORD __umul128(QWORD a, QWORD b, QWORD* hi);
QWORD ui128_quotient_mod(QWORD lo, QWORD hi);
QWORD mul(QWORD x, QWORD y);
QWORD pow(QWORD x, QWORD y);
QWORD inverse(QWORD u, QWORD v);
QWORD inv(QWORD x);
QWORD sqrt(QWORD what);
};
class Polynomial {
ConfirmationID *parent;
public:
explicit Polynomial(ConfirmationID *in) {
parent = in;
}
int mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]);
int div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient);
void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int* pgcddeg, QWORD gcd[3], int* pmult1deg, QWORD mult1[3], int* pmult2deg, QWORD mult2[3]);
int u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2]);
};
class Divisor {
ConfirmationID *parent;
public:
explicit Divisor(ConfirmationID *in) {
parent = in;
}
int find_divisor_v(TDivisor* d);
void add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst);
void mul(const TDivisor* src, QWORD mult, TDivisor* dst);
void mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst);
};
#endif //UMSKT_CONFID_H

View File

@ -0,0 +1,355 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 12/05/2023
* @Maintainer Neo
*/
#include "confid.h"
int Divisor::find_divisor_v(TDivisor* d)
{
// u | v^2 - f
// u = u0 + u1*x + x^2
// f%u = f0 + f1*x
QWORD v1, f2[6];
for (int i = 0; i < 6; i++)
{
f2[i] = parent->f[i];
}
const QWORD u0 = d->u[0];
const QWORD u1 = d->u[1];
for (int j = 4; j--; )
{
f2[j] = parent->residue->sub(f2[j], parent->residue->mul(u0, f2[j + 2]));
f2[j + 1] = parent->residue->sub(f2[j + 1], parent->residue->mul(u1, f2[j + 2]));
f2[j + 2] = 0;
}
// v = v0 + v1*x
// u | (v0^2 - f0) + (2*v0*v1 - f1)*x + v1^2*x^2 = u0*v1^2 + u1*v1^2*x + v1^2*x^2
// v0^2 - f0 = u0*v1^2
// 2*v0*v1 - f1 = u1*v1^2
// v0^2 = f0 + u0*v1^2 = (f1 + u1*v1^2)^2 / (2*v1)^2
// (f1^2) + 2*(f1*u1-2*f0) * v1^2 + (u1^2-4*u0) * v1^4 = 0
// v1^2 = ((2*f0-f1*u1) +- 2*sqrt(-f0*f1*u1 + f0^2 + f1^2*u0))) / (u1^2-4*u0)
const QWORD f0 = f2[0];
const QWORD f1 = f2[1];
const QWORD u0double = parent->residue->add(u0, u0);
const QWORD coeff2 = parent->residue->sub(parent->residue->mul(u1, u1), parent->residue->add(u0double, u0double));
const QWORD coeff1 = parent->residue->sub(parent->residue->add(f0, f0), parent->residue->mul(f1, u1));
if (coeff2 == 0)
{
if (coeff1 == 0)
{
if (f1 == 0)
{
// impossible
//printf("bad f(), double root detected\n");
}
return 0;
}
QWORD sqr = parent->residue->mul(parent->residue->mul(f1, f1), parent->residue->inv(parent->residue->add(coeff1, coeff1)));
v1 = parent->residue->sqrt(sqr);
if (v1 == BAD)
{
return 0;
}
}
else
{
QWORD d = parent->residue->add(parent->residue->mul(f0, f0), parent->residue->mul(f1, parent->residue->sub(parent->residue->mul(f1, u0), parent->residue->mul(f0, u1))));
d = parent->residue->sqrt(d);
if (d == BAD)
{
return 0;
}
d = parent->residue->add(d, d);
QWORD inv = parent->residue->inv(coeff2);
QWORD root = parent->residue->mul(parent->residue->add(coeff1, d), inv);
v1 = parent->residue->sqrt(root);
if (v1 == BAD)
{
root = parent->residue->mul(parent->residue->sub(coeff1, d), inv);
v1 = parent->residue->sqrt(root);
if (v1 == BAD)
{
return 0;
}
}
}
QWORD v0 = parent->residue->mul(parent->residue->add(f1, parent->residue->mul(u1, parent->residue->mul(v1, v1))), parent->residue->inv(parent->residue->add(v1, v1)));
d->v[0] = v0;
d->v[1] = v1;
return 1;
}
int Divisor::u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2])
{
if (src->u[1] != BAD)
{
polyu[0] = src->u[0];
polyu[1] = src->u[1];
polyu[2] = 1;
polyv[0] = src->v[0];
polyv[1] = src->v[1];
return 2;
}
if (src->u[0] != BAD)
{
polyu[0] = src->u[0];
polyu[1] = 1;
polyv[0] = src->v[0];
polyv[1] = 0;
return 1;
}
polyu[0] = 1;
polyv[0] = 0;
polyv[1] = 0;
return 0;
}
void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
{
QWORD u1[3], u2[3], v1[2], v2[2];
int u1deg = u2poly(src1, u1, v1);
int u2deg = u2poly(src2, u2, v2);
// extended gcd: d1 = gcd(u1, u2) = e1*u1 + e2*u2
int d1deg, e1deg, e2deg;
QWORD d1[3], e1[3], e2[3];
parent->polynomial->xgcd(u1deg, u1, u2deg, u2, &d1deg, d1, &e1deg, e1, &e2deg, e2);
assert(e1deg <= 1);
assert(e2deg <= 1);
// extended gcd again: d = gcd(d1, v1+v2) = c1*d1 + c2*(v1+v2)
QWORD b[3] = {parent->residue->add(v1[0], v2[0]), parent->residue->add(v1[1], v2[1]), 0};
int bdeg = (b[1] == 0 ? (b[0] == 0 ? -1 : 0) : 1);
int ddeg, c1deg, c2deg;
QWORD d[3], c1[3], c2[3];
parent->polynomial->xgcd(d1deg, d1, bdeg, b, &ddeg, d, &c1deg, c1, &c2deg, c2);
assert(c1deg <= 0);
assert(c2deg <= 1);
assert(ddeg >= 0);
QWORD dmult = parent->residue->inv(d[ddeg]);
int i;
for (i = 0; i < ddeg; i++)
{
d[i] = parent->residue->mul(d[i], dmult);
}
d[i] = 1;
for (i = 0; i <= c1deg; i++)
{
c1[i] = parent->residue->mul(c1[i], dmult);
}
for (i = 0; i <= c2deg; i++)
{
c2[i] = parent->residue->mul(c2[i], dmult);
}
QWORD u[5];
int udeg = parent->polynomial->mul(u1deg, u1, u2deg, u2, -1, u);
// u is monic
QWORD v[7], tmp[7];
int vdeg, tmpdeg;
// c1*(e1*u1*v2 + e2*u2*v1) + c2*(v1*v2 + f)
// c1*(e1*u1*(v2-v1) + d1*v1) + c2*(v1*v2 + f)
v[0] = parent->residue->sub(v2[0], v1[0]);
v[1] = parent->residue->sub(v2[1], v1[1]);
tmpdeg = parent->polynomial->mul(e1deg, e1, 1, v, -1, tmp);
vdeg = parent->polynomial->mul(u1deg, u1, tmpdeg, tmp, -1, v);
vdeg = parent->polynomial->mul(d1deg, d1, 1, v1, vdeg, v);
for (i = 0; i <= vdeg; i++)
{
v[i] = parent->residue->mul(v[i], c1[0]);
}
memcpy(tmp, parent->f, 6 * sizeof(parent->f[0]));
tmpdeg = 5;
tmpdeg = parent->polynomial->mul(1, v1, 1, v2, tmpdeg, tmp);
vdeg = parent->polynomial->mul(c2deg, c2, tmpdeg, tmp, vdeg, v);
if (ddeg > 0)
{
assert(udeg >= 2*ddeg);
QWORD udiv[5];
parent->polynomial->div_monic(udeg, u, ddeg, d, udiv); udeg -= ddeg;
parent->polynomial->div_monic(udeg, udiv, ddeg, d, u); udeg -= ddeg;
if (vdeg >= 0)
{
assert(vdeg >= ddeg);
parent->polynomial->div_monic(vdeg, v, ddeg, d, udiv); vdeg -= ddeg;
memcpy(v, udiv, (vdeg + 1) * sizeof(v[0]));
}
}
vdeg = parent->polynomial->div_monic(vdeg, v, udeg, u, NULL);
while (udeg > 2) {
assert(udeg <= 4);
assert(vdeg <= 3);
// u' = monic((f-v^2)/u), v'=-v mod u'
tmpdeg = parent->polynomial->mul(vdeg, v, vdeg, v, -1, tmp);
for (i = 0; i <= tmpdeg && i <= 5; i++)
{
tmp[i] = parent->residue->sub(parent->f[i], tmp[i]);
}
for (; i <= tmpdeg; i++)
{
tmp[i] = parent->residue->sub(0, tmp[i]);
}
for (; i <= 5; i++)
{
tmp[i] = parent->f[i];
}
tmpdeg = i - 1;
QWORD udiv[5];
parent->polynomial->div_monic(tmpdeg, tmp, udeg, u, udiv);
udeg = tmpdeg - udeg;
QWORD mult = parent->residue->inv(udiv[udeg]);
for (i = 0; i < udeg; i++)
{
u[i] = parent->residue->mul(udiv[i], mult);
}
u[i] = 1;
for (i = 0; i <= vdeg; i++)
{
v[i] = parent->residue->sub(0, v[i]);
}
vdeg = parent->polynomial->div_monic(vdeg, v, udeg, u, NULL);
}
if (udeg == 2)
{
dst->u[0] = u[0];
dst->u[1] = u[1];
dst->v[0] = (vdeg >= 0 ? v[0] : 0);
dst->v[1] = (vdeg >= 1 ? v[1] : 0);
}
else if (udeg == 1)
{
dst->u[0] = u[0];
dst->u[1] = BAD;
dst->v[0] = (vdeg >= 0 ? v[0] : 0);
dst->v[1] = BAD;
}
else
{
assert(udeg == 0);
dst->u[0] = BAD;
dst->u[1] = BAD;
dst->v[0] = BAD;
dst->v[1] = BAD;
}
}
#define divisor_double(src, dst) add(src, src, dst)
void Divisor::mul(const TDivisor* src, QWORD mult, TDivisor* dst)
{
if (mult == 0)
{
dst->u[0] = BAD;
dst->u[1] = BAD;
dst->v[0] = BAD;
dst->v[1] = BAD;
return;
}
TDivisor cur = *src;
while (!(mult & 1))
{
divisor_double(&cur, &cur);
mult >>= 1;
}
*dst = cur;
while ((mult >>= 1) != 0)
{
divisor_double(&cur, &cur);
if (mult & 1)
{
add(dst, &cur, dst);
}
}
}
void Divisor::mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst)
{
if (mult_lo == 0 && mult_hi == 0)
{
dst->u[0] = BAD;
dst->u[1] = BAD;
dst->v[0] = BAD;
dst->v[1] = BAD;
return;
}
TDivisor cur = *src;
while (!(mult_lo & 1))
{
divisor_double(&cur, &cur);
mult_lo >>= 1;
if (mult_hi & 1) {
mult_lo |= (1ULL << 63);
}
mult_hi >>= 1;
}
*dst = cur;
for (;;)
{
mult_lo >>= 1;
if (mult_hi & 1)
{
mult_lo |= (1ULL << 63);
}
mult_hi >>= 1;
if (mult_lo == 0 && mult_hi == 0)
{
break;
}
divisor_double(&cur, &cur);
if (mult_lo & 1)
{
add(dst, &cur, dst);
}
}
}

View File

@ -0,0 +1,184 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 12/05/2023
* @Maintainer Neo
*/
#include "confid.h"
// generic short slow code
int Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[])
{
if (adeg < 0 || bdeg < 0)
{
return resultprevdeg;
}
int i, j;
for (i = resultprevdeg + 1; i <= adeg + bdeg; i++)
{
result[i] = 0;
}
resultprevdeg = i - 1;
for (i = 0; i <= adeg; i++)
{
for (j = 0; j <= bdeg; j++)
{
result[i + j] = parent->residue->add(result[i + j], parent->residue->mul(a[i], b[j]));
}
}
while (resultprevdeg >= 0 && result[resultprevdeg] == 0)
{
--resultprevdeg;
}
return resultprevdeg;
}
int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient)
{
assert(bdeg >= 0);
assert(b[bdeg] == 1);
int i, j;
for (i = adeg - bdeg; i >= 0; i--)
{
QWORD q = a[i + bdeg];
if (quotient)
{
quotient[i] = q;
}
for (j = 0; j < bdeg; j++)
{
a[i + j] = parent->residue->sub(a[i + j], parent->residue->mul(q, b[j]));
}
a[i + j] = 0;
}
i += bdeg;
while (i >= 0 && a[i] == 0)
{
i--;
}
return i;
}
void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int* pgcddeg, QWORD gcd[3], int* pmult1deg, QWORD mult1[3], int* pmult2deg, QWORD mult2[3])
{
int sdeg = -1;
QWORD s[3] = {0, 0, 0};
int mult1deg = 0;
mult1[0] = 1; mult1[1] = 0; mult1[2] = 0;
int tdeg = 0;
QWORD t[3] = {1, 0, 0};
int mult2deg = -1;
mult2[0] = 0; mult2[1] = 0; mult2[2] = 0;
int rdeg = bdeg;
QWORD r[3] = {b[0], b[1], b[2]};
int gcddeg = adeg;
gcd[0] = a[0]; gcd[1] = a[1]; gcd[2] = a[2];
// s*u1 + t*u2 = r
// mult1*u1 + mult2*u2 = gcd
while (rdeg >= 0)
{
if (rdeg > gcddeg)
{
unsigned tmp;
int tmpi;
tmp = rdeg; rdeg = gcddeg; gcddeg = tmp;
tmpi = sdeg; sdeg = mult1deg; mult1deg = tmpi;
tmpi = tdeg; tdeg = mult2deg; mult2deg = tmpi;
QWORD tmp2;
tmp2 = r[0]; r[0] = gcd[0]; gcd[0] = tmp2;
tmp2 = r[1]; r[1] = gcd[1]; gcd[1] = tmp2;
tmp2 = r[2]; r[2] = gcd[2]; gcd[2] = tmp2;
tmp2 = s[0]; s[0] = mult1[0]; mult1[0] = tmp2;
tmp2 = s[1]; s[1] = mult1[1]; mult1[1] = tmp2;
tmp2 = s[2]; s[2] = mult1[2]; mult1[2] = tmp2;
tmp2 = t[0]; t[0] = mult2[0]; mult2[0] = tmp2;
tmp2 = t[1]; t[1] = mult2[1]; mult2[1] = tmp2;
tmp2 = t[2]; t[2] = mult2[2]; mult2[2] = tmp2;
continue;
}
int delta = gcddeg - rdeg;
QWORD mult = parent->residue->mul(gcd[gcddeg], parent->residue->inv(r[rdeg]));
// quotient = mult * x**delta
assert(rdeg + delta < 3);
for (int i = 0; i <= rdeg; i++)
{
gcd[i + delta] = parent->residue->sub(gcd[i + delta], parent->residue->mul(mult, r[i]));
}
while (gcddeg >= 0 && gcd[gcddeg] == 0)
{
gcddeg--;
}
assert(sdeg + delta < 3);
for (int i = 0; i <= sdeg; i++)
{
mult1[i + delta] = parent->residue->sub(mult1[i + delta], parent->residue->mul(mult, s[i]));
}
if (mult1deg < sdeg + delta)
{
mult1deg = sdeg + delta;
}
while (mult1deg >= 0 && mult1[mult1deg] == 0)
{
mult1deg--;
}
assert(tdeg + delta < 3);
for (int i = 0; i <= tdeg; i++)
{
mult2[i + delta] = parent->residue->sub(mult2[i + delta], parent->residue->mul(mult, t[i]));
}
if (mult2deg < tdeg + delta)
{
mult2deg = tdeg + delta;
}
while (mult2deg >= 0 && mult2[mult2deg] == 0)
{
mult2deg--;
}
}
// d1 = gcd, e1 = mult1, e2 = mult2
*pgcddeg = gcddeg;
*pmult1deg = mult1deg;
*pmult2deg = mult2deg;
}

View File

@ -0,0 +1,222 @@
/**
* This file is a part of the UMSKT Project
*
* Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @FileCreated by Neo on 12/05/2023
* @Maintainer Neo
*/
#include "confid.h"
#if defined(__x86_64__) || defined(_M_AMD64) || defined(__aarch64__) || (defined(__arm64__) && defined(__APPLE__))
#ifdef __GNUC__
inline QWORD Residue::__umul128(QWORD a, QWORD b, QWORD* hi)
{
OWORD r = (OWORD)a * (OWORD)b;
*hi = r >> 64;
return (QWORD) r;
}
#else
#define __umul128 _umul128
#endif
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__)
inline QWORD Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi)
{
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
QWORD a = multiplier >> 32;
QWORD b = multiplier & 0xFFFFFFFF;
QWORD c = multiplicand >> 32;
QWORD d = multiplicand & 0xFFFFFFFF;
//QWORD ac = a * c;
QWORD ad = a * d;
//QWORD bc = b * c;
QWORD bd = b * d;
QWORD adbc = ad + (b * c);
QWORD adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
QWORD product_lo = bd + (adbc << 32);
QWORD product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
return product_lo;
}
#else
#error Unknown architecture detected - please edit confid.cpp to tailor __umul128() your architecture
#endif
QWORD Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
{
// hi:lo * ceil(2**170/MOD) >> (64 + 64 + 42)
QWORD prod1;
__umul128(lo, parent->p0, &prod1);
QWORD part1hi, part1lo;
part1lo = __umul128(lo, parent->p1, &part1hi);
QWORD part2hi, part2lo;
part2lo = __umul128(hi, parent->p2, &part2hi);
QWORD sum1 = part1lo + part2lo;
unsigned sum1carry = (sum1 < part1lo);
sum1 += prod1;
sum1carry += (sum1 < prod1);
QWORD prod2 = part1hi + part2hi + sum1carry;
QWORD prod3hi, prod3lo;
prod3lo = __umul128(hi, parent->p3, &prod3hi);
prod3lo += prod2;
prod3hi += (prod3lo < prod2);
return (prod3lo >> 42) | (prod3hi << 22);
}
QWORD Residue::mul(QWORD x, QWORD y)
{
// * ceil(2**170/MOD) = 0x2d351 c6d04f8b|604fa6a1 c6346a87 for (p-1)*(p-1) max
QWORD hi;
QWORD lo = __umul128(x, y, &hi);
QWORD quotient = ui128_quotient_mod(lo, hi);
return lo - quotient * parent->MOD;
}
QWORD Residue::pow(QWORD x, QWORD y)
{
if (y == 0)
{
return 1;
}
QWORD cur = x;
while (!(y & 1))
{
cur = mul(cur, cur);
y >>= 1;
}
QWORD res = cur;
while ((y >>= 1) != 0)
{
cur = mul(cur, cur);
if (y & 1)
{
res = mul(res, cur);
}
}
return res;
}
QWORD Residue::add(QWORD x, QWORD y)
{
QWORD z = x + y;
//z = z - (z >= MOD ? MOD : 0);
if (z >= parent->MOD)
{
z -= parent->MOD;
}
return z;
}
QWORD Residue::sub(QWORD x, QWORD y)
{
QWORD z = x - y;
//z += (x < y ? MOD : 0);
if (x < y)
{
z += parent->MOD;
}
return z;
}
QWORD Residue::inverse(QWORD u, QWORD v)
{
//assert(u);
int64_t tmp;
int64_t xu = 1, xv = 0;
QWORD v0 = v;
while (u > 1)
{
QWORD d = v / u; QWORD remainder = v % u;
tmp = u; u = remainder; v = tmp;
tmp = xu; xu = xv - d * xu; xv = tmp;
}
xu += (xu < 0 ? v0 : 0);
return xu;
}
QWORD Residue::inv(QWORD x)
{
return inverse(x, parent->MOD);
// return residue_pow(x, MOD - 2);
}
QWORD Residue::sqrt(QWORD what)
{
if (!what)
{
return 0;
}
QWORD g = parent->NON_RESIDUE, z, y, r, x, b, t;
QWORD e = 0, q = parent->MOD - 1;
while (!(q & 1))
{
e++, q >>= 1;
}
z = pow(g, q);
y = z;
r = e;
x = pow(what, (q - 1) / 2);
b = mul(mul(what, x), x);
x = mul(what, x);
while (b != 1) {
QWORD m = 0, b2 = b;
do
{
m++;
b2 = mul(b2, b2);
}
while (b2 != 1);
if (m == r)
{
return BAD;
}
t = pow(y, 1 << (r - m - 1));
y = mul(t, t);
r = m;
x = mul(x, t);
b = mul(b, y);
}
if (mul(x, x) != what)
{
//printf("internal error in sqrt\n");
return BAD;
}
return x;
}