mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2024-12-22 12:30:17 +02:00
standardize using clang-format
This commit is contained in:
parent
8cc691b72f
commit
c0a4c76b54
216
.clang-format
Normal file
216
.clang-format
Normal file
@ -0,0 +1,216 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Microsoft
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: BinPack
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RequiresClausePosition: OwnLine
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
496
src/cli.cpp
496
src/cli.cpp
@ -31,22 +31,27 @@ CLI::~CLI()
|
||||
BN_free(genOrder);
|
||||
}
|
||||
|
||||
bool CLI::loadJSON(const fs::path& filename, json *output) {
|
||||
if (!filename.empty() && !fs::exists(filename)) {
|
||||
bool CLI::loadJSON(const fs::path &filename, json *output)
|
||||
{
|
||||
if (!filename.empty() && !fs::exists(filename))
|
||||
{
|
||||
fmt::print("ERROR: File {} does not exist\n", filename.string());
|
||||
return false;
|
||||
}
|
||||
else if (fs::exists(filename)) {
|
||||
else if (fs::exists(filename))
|
||||
{
|
||||
std::ifstream f(filename);
|
||||
*output = json::parse(f, nullptr, false, false);
|
||||
}
|
||||
else if (filename.empty()) {
|
||||
else if (filename.empty())
|
||||
{
|
||||
cmrc::embedded_filesystem fs = cmrc::umskt::get_filesystem();
|
||||
cmrc::file keys = fs.open("keys.json");
|
||||
*output = json::parse(keys, nullptr, false, false);
|
||||
}
|
||||
|
||||
if (output->is_discarded()) {
|
||||
if (output->is_discarded())
|
||||
{
|
||||
fmt::print("ERROR: Unable to parse keys from {}\n", filename.string());
|
||||
return false;
|
||||
}
|
||||
@ -54,16 +59,18 @@ bool CLI::loadJSON(const fs::path& filename, json *output) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CLI::showHelp(char *argv[]) {
|
||||
void CLI::showHelp(char *argv[])
|
||||
{
|
||||
fmt::print("usage: {} \n", argv[0]);
|
||||
fmt::print("\t-h --help\tshow this message\n");
|
||||
fmt::print("\t-v --verbose\tenable verbose output\n");
|
||||
fmt::print("\t-n --number\tnumber of keys to generate (defaults to 1)\n");
|
||||
fmt::print("\t-f --file\tspecify which keys file to load\n");
|
||||
fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n");
|
||||
fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", \"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
|
||||
fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office 2K7 programs\n");
|
||||
fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", "
|
||||
"\"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
|
||||
fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office "
|
||||
"2K7 programs\n");
|
||||
fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n");
|
||||
fmt::print("\t-l --list\tshow which products/binks can be loaded\n");
|
||||
fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n");
|
||||
@ -74,186 +81,243 @@ void CLI::showHelp(char *argv[]) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
|
||||
int CLI::parseCommandLine(int argc, char *argv[], Options *options)
|
||||
{
|
||||
// set default options
|
||||
*options = Options {
|
||||
"2E",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
640,
|
||||
0,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
MODE_BINK1998_GENERATE,
|
||||
WINDOWS
|
||||
};
|
||||
*options = Options{"2E", "", "", "", "", 640, 0, 1,
|
||||
false, false, false, false, false, false, false, MODE_BINK1998_GENERATE,
|
||||
WINDOWS};
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
if (arg == "-v" || arg == "--verbose") {
|
||||
if (arg == "-v" || arg == "--verbose")
|
||||
{
|
||||
options->verbose = true;
|
||||
UMSKT::setDebugOutput(stderr);
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help")
|
||||
{
|
||||
options->help = true;
|
||||
} else if (arg == "-n" || arg == "--number") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-n" || arg == "--number")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
int nKeys;
|
||||
if (!sscanf(argv[i+1], "%d", &nKeys)) {
|
||||
if (!sscanf(argv[i + 1], "%d", &nKeys))
|
||||
{
|
||||
options->error = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
options->numKeys = nKeys;
|
||||
}
|
||||
i++;
|
||||
} else if (arg == "-b" || arg == "--bink") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-b" || arg == "--bink")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
options->binkid = argv[i+1];
|
||||
options->binkid = argv[i + 1];
|
||||
i++;
|
||||
} else if (arg == "-l" || arg == "--list") {
|
||||
}
|
||||
else if (arg == "-l" || arg == "--list")
|
||||
{
|
||||
options->list = true;
|
||||
} else if (arg == "-c" || arg == "--channelid") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-c" || arg == "--channelid")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
int siteID;
|
||||
if (!sscanf(argv[i+1], "%d", &siteID)) {
|
||||
if (!sscanf(argv[i + 1], "%d", &siteID))
|
||||
{
|
||||
options->error = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
options->channelID = siteID;
|
||||
}
|
||||
i++;
|
||||
} else if (arg == "-s" || arg == "--serial") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-s" || arg == "--serial")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
int serial_val;
|
||||
if (!sscanf(argv[i+1], "%d", &serial_val)) {
|
||||
if (!sscanf(argv[i + 1], "%d", &serial_val))
|
||||
{
|
||||
options->error = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
options->serialSet = true;
|
||||
options->serial = serial_val;
|
||||
}
|
||||
i++;
|
||||
} else if (arg == "-u" || arg == "--upgrade") {
|
||||
options->upgrade = true;
|
||||
} else if (arg == "-f" || arg == "--file") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-u" || arg == "--upgrade")
|
||||
{
|
||||
options->upgrade = true;
|
||||
}
|
||||
else if (arg == "-f" || arg == "--file")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
options->keysFilename = argv[i+1];
|
||||
options->keysFilename = argv[i + 1];
|
||||
i++;
|
||||
} else if (arg == "-i" || arg == "--instid") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-i" || arg == "--instid")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
options->instid = argv[i+1];
|
||||
options->instid = argv[i + 1];
|
||||
options->applicationMode = MODE_CONFIRMATION_ID;
|
||||
i++;
|
||||
} else if (arg == "-m" || arg == "--mode") {
|
||||
std::string mode = argv[i+1];
|
||||
}
|
||||
else if (arg == "-m" || arg == "--mode")
|
||||
{
|
||||
std::string mode = argv[i + 1];
|
||||
char *p = &mode[0];
|
||||
for (; *p; p++) {
|
||||
for (; *p; p++)
|
||||
{
|
||||
*p = toupper((unsigned char)*p);
|
||||
}
|
||||
}
|
||||
p = &mode[0];
|
||||
if (strcmp(p, "WINDOWS") == 0) {
|
||||
if (strcmp(p, "WINDOWS") == 0)
|
||||
{
|
||||
options->activationMode = WINDOWS;
|
||||
} else if (strcmp(p, "OFFICEXP") == 0) {
|
||||
}
|
||||
else if (strcmp(p, "OFFICEXP") == 0)
|
||||
{
|
||||
options->activationMode = OFFICE_XP;
|
||||
} else if (strcmp(p, "OFFICE2K3") == 0) {
|
||||
}
|
||||
else if (strcmp(p, "OFFICE2K3") == 0)
|
||||
{
|
||||
options->activationMode = OFFICE_2K3;
|
||||
} else if (strcmp(p, "OFFICE2K7") == 0) {
|
||||
}
|
||||
else if (strcmp(p, "OFFICE2K7") == 0)
|
||||
{
|
||||
options->activationMode = OFFICE_2K7;
|
||||
} else if (strcmp(p, "PLUSDME") == 0) {
|
||||
}
|
||||
else if (strcmp(p, "PLUSDME") == 0)
|
||||
{
|
||||
options->activationMode = PLUS_DME;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} else if (arg == "-p" || arg == "--productid") {
|
||||
if (i == argc -1) {
|
||||
}
|
||||
else if (arg == "-p" || arg == "--productid")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
options->productid = argv[i+1];
|
||||
}
|
||||
options->productid = argv[i + 1];
|
||||
i++;
|
||||
} else if (arg == "-V" || arg == "--validate") {
|
||||
if (i == argc - 1) {
|
||||
}
|
||||
else if (arg == "-V" || arg == "--validate")
|
||||
{
|
||||
if (i == argc - 1)
|
||||
{
|
||||
options->error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
options->keyToCheck = argv[i+1];
|
||||
options->keyToCheck = argv[i + 1];
|
||||
options->applicationMode = MODE_BINK1998_VALIDATE;
|
||||
i++;
|
||||
|
||||
} else if (arg == "-N" || arg == "--nonewlines") {
|
||||
options->nonewlines = true;
|
||||
} else {
|
||||
}
|
||||
else if (arg == "-N" || arg == "--nonewlines")
|
||||
{
|
||||
options->nonewlines = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
options->error = true;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure that a product id is entered for OFFICE_2K3 or OFFICE_2K7 IIDs
|
||||
if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) && (options->productid.empty() || options->instid.empty()) ) {
|
||||
if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) &&
|
||||
(options->productid.empty() || options->instid.empty()))
|
||||
{
|
||||
return options->error = true;
|
||||
}
|
||||
|
||||
return !options->error;
|
||||
}
|
||||
|
||||
int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
|
||||
if (options->help || options->error) {
|
||||
if (options->error) {
|
||||
int CLI::validateCommandLine(Options *options, char *argv[], json *keys)
|
||||
{
|
||||
if (options->help || options->error)
|
||||
{
|
||||
if (options->error)
|
||||
{
|
||||
fmt::print("error parsing command line options\n");
|
||||
}
|
||||
showHelp(argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (options->verbose) {
|
||||
if(options->keysFilename.empty()) {
|
||||
if (options->verbose)
|
||||
{
|
||||
if (options->keysFilename.empty())
|
||||
{
|
||||
fmt::print("Loading internal keys file\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::print("Loading keys file {}\n", options->keysFilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadJSON(options->keysFilename, keys)) {
|
||||
if (!loadJSON(options->keysFilename, keys))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (options->verbose) {
|
||||
if(options->keysFilename.empty()) {
|
||||
if (options->verbose)
|
||||
{
|
||||
if (options->keysFilename.empty())
|
||||
{
|
||||
fmt::print("Loaded internal keys file successfully\n");
|
||||
} else {
|
||||
fmt::print("Loaded keys from {} successfully\n",options->keysFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::print("Loaded keys from {} successfully\n", options->keysFilename);
|
||||
}
|
||||
}
|
||||
|
||||
if (options->list) {
|
||||
for (auto const el : (*keys)["Products"].items()) {
|
||||
if (options->list)
|
||||
{
|
||||
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;
|
||||
@ -269,23 +333,28 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
|
||||
sscanf(options->binkid.c_str(), "%x", &intBinkID);
|
||||
|
||||
// FE and FF are BINK 1998, but do not generate valid keys, so we throw an error
|
||||
if (intBinkID >= 0xFE) {
|
||||
if (intBinkID >= 0xFE)
|
||||
{
|
||||
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (intBinkID >= 0x40) {
|
||||
|
||||
if (intBinkID >= 0x40)
|
||||
{
|
||||
// set bink2002 validate mode if in bink1998 validate mode, else set bink2002 generate mode
|
||||
options->applicationMode = (options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
|
||||
options->applicationMode =
|
||||
(options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
|
||||
}
|
||||
|
||||
if (options->channelID > 999) {
|
||||
if (options->channelID > 999)
|
||||
{
|
||||
fmt::print("ERROR: refusing to create a key with a Channel ID greater than 999\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// don't allow any serial not between 0 and 999999
|
||||
if (options->serial > 999999 || options->serial < 0) {
|
||||
if (options->serial > 999999 || options->serial < 0)
|
||||
{
|
||||
fmt::print("ERROR: refusing to create a key with a Serial not between 000000 and 999999\n");
|
||||
return 1;
|
||||
}
|
||||
@ -293,7 +362,8 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CLI::printID(DWORD *pid) {
|
||||
void CLI::printID(DWORD *pid)
|
||||
{
|
||||
char raw[12];
|
||||
char b[6], c[8];
|
||||
int i, digit = 0;
|
||||
@ -311,42 +381,51 @@ void CLI::printID(DWORD *pid) {
|
||||
// Make checksum digit-part {...56X-}
|
||||
assert(strlen(c) == 6);
|
||||
for (i = 0; i < 6; i++)
|
||||
digit -= c[i] - '0'; // Sum digits
|
||||
{
|
||||
digit -= c[i] - '0'; // Sum digits
|
||||
}
|
||||
|
||||
while (digit < 0)
|
||||
{
|
||||
digit += 7;
|
||||
}
|
||||
c[6] = digit + '0';
|
||||
c[7] = 0;
|
||||
|
||||
fmt::print("> Product ID: PPPPP-{}-{}-23xxx\n", b, c);
|
||||
}
|
||||
|
||||
void CLI::printKey(char *pk) {
|
||||
void CLI::printKey(char *pk)
|
||||
{
|
||||
assert(strlen(pk) >= PK_LENGTH);
|
||||
|
||||
std::string spk = pk;
|
||||
fmt::print("{}-{}-{}-{}-{}",
|
||||
spk.substr(0,5),
|
||||
spk.substr(5,5),
|
||||
spk.substr(10,5),
|
||||
spk.substr(15,5),
|
||||
spk.substr(20,5));
|
||||
fmt::print("{}-{}-{}-{}-{}", spk.substr(0, 5), spk.substr(5, 5), spk.substr(10, 5), spk.substr(15, 5),
|
||||
spk.substr(20, 5));
|
||||
}
|
||||
|
||||
bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH]) {
|
||||
bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH])
|
||||
{
|
||||
// copy out the product key stripping out extraneous characters
|
||||
const char *p = in_key;
|
||||
size_t i = 0;
|
||||
for (; *p; p++) {
|
||||
for (; *p; p++)
|
||||
{
|
||||
// strip out space or dash
|
||||
if (*p == ' ' || *p == '-')
|
||||
continue;
|
||||
if (*p == ' ' || *p == '-')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// check if we've passed the product key length to avoid overflow
|
||||
if (i >= PK_LENGTH)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// convert to uppercase - if character allowed, copy into array
|
||||
for (int j = 0; j < strlen(PIDGEN3::pKeyCharset); j++) {
|
||||
if (toupper(*p) == PIDGEN3::pKeyCharset[j]) {
|
||||
for (int j = 0; j < strlen(PIDGEN3::pKeyCharset); j++)
|
||||
{
|
||||
if (toupper(*p) == PIDGEN3::pKeyCharset[j])
|
||||
{
|
||||
out_key[i++] = toupper(*p);
|
||||
continue;
|
||||
}
|
||||
@ -356,7 +435,8 @@ bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH]) {
|
||||
return (i == PK_LENGTH);
|
||||
}
|
||||
|
||||
CLI::CLI(Options options, json keys) {
|
||||
CLI::CLI(Options options, json keys)
|
||||
{
|
||||
this->options = options;
|
||||
this->keys = keys;
|
||||
|
||||
@ -371,10 +451,11 @@ CLI::CLI(Options options, json keys) {
|
||||
this->genOrder = BN_new();
|
||||
|
||||
/* Computed data */
|
||||
BN_dec2bn(&this->genOrder, this->keys["BINK"][this->BINKID]["n"]. get<std::string>().c_str());
|
||||
BN_dec2bn(&this->genOrder, this->keys["BINK"][this->BINKID]["n"].get<std::string>().c_str());
|
||||
BN_dec2bn(&this->privateKey, this->keys["BINK"][this->BINKID]["priv"].get<std::string>().c_str());
|
||||
|
||||
if (options.verbose) {
|
||||
if (options.verbose)
|
||||
{
|
||||
fmt::print("----------------------------------------------------------- \n");
|
||||
fmt::print("Loaded the following elliptic curve parameters: BINK[{}]\n", this->BINKID);
|
||||
fmt::print("----------------------------------------------------------- \n");
|
||||
@ -390,33 +471,33 @@ CLI::CLI(Options options, json keys) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
|
||||
eCurve = PIDGEN3::initializeEllipticCurve(
|
||||
this->keys["BINK"][this->BINKID]["p"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["a"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["b"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["g"]["x"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["g"]["y"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["pub"]["x"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["pub"]["y"].get<std::string>(),
|
||||
this->genPoint,
|
||||
this->pubPoint
|
||||
);
|
||||
eCurve = PIDGEN3::initializeEllipticCurve(this->keys["BINK"][this->BINKID]["p"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["a"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["b"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["g"]["x"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["g"]["y"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["pub"]["x"].get<std::string>(),
|
||||
this->keys["BINK"][this->BINKID]["pub"]["y"].get<std::string>(),
|
||||
this->genPoint, this->pubPoint);
|
||||
|
||||
this->count = 0;
|
||||
this->total = this->options.numKeys;
|
||||
}
|
||||
|
||||
int CLI::BINK1998Generate() {
|
||||
int CLI::BINK1998Generate()
|
||||
{
|
||||
// raw PID/serial value
|
||||
DWORD nRaw = this->options.channelID * 1'000'000 ; /* <- change */
|
||||
DWORD nRaw = this->options.channelID * 1'000'000; /* <- change */
|
||||
|
||||
// using user-provided serial
|
||||
if (this->options.serialSet) {
|
||||
if (this->options.serialSet)
|
||||
{
|
||||
// just in case, make sure it's less than 999999
|
||||
int serialRnd = (this->options.serial % 999999);
|
||||
nRaw += serialRnd;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// generate a random number to use as a serial
|
||||
BIGNUM *bnrand = BN_new();
|
||||
BN_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
|
||||
@ -426,10 +507,11 @@ 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) {
|
||||
if (this->options.verbose)
|
||||
{
|
||||
// print the resulting Product ID
|
||||
// PID value is printed in BINK1998::Generate
|
||||
printID(&nRaw);
|
||||
@ -438,22 +520,29 @@ int CLI::BINK1998Generate() {
|
||||
// generate a key
|
||||
BN_sub(this->privateKey, this->genOrder, this->privateKey);
|
||||
|
||||
for (int i = 0; i < this->total; i++) {
|
||||
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, options.upgrade, this->pKey);
|
||||
for (int i = 0; i < this->total; i++)
|
||||
{
|
||||
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw,
|
||||
options.upgrade, this->pKey);
|
||||
|
||||
bool isValid = PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
|
||||
if (isValid) {
|
||||
if (isValid)
|
||||
{
|
||||
CLI::printKey(this->pKey);
|
||||
if (i < this->total - 1 || this->options.verbose) {
|
||||
if (i < this->total - 1 || this->options.verbose)
|
||||
{
|
||||
fmt::print("\n");
|
||||
}
|
||||
this->count += isValid;
|
||||
}
|
||||
else {
|
||||
if (this->options.verbose) {
|
||||
else
|
||||
{
|
||||
if (this->options.verbose)
|
||||
{
|
||||
CLI::printKey(this->pKey);
|
||||
fmt::print(" [Invalid]");
|
||||
if (i < this->total - 1) {
|
||||
if (i < this->total - 1)
|
||||
{
|
||||
fmt::print("\n");
|
||||
}
|
||||
}
|
||||
@ -461,49 +550,61 @@ int CLI::BINK1998Generate() {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->options.verbose) {
|
||||
if (this->options.verbose)
|
||||
{
|
||||
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
|
||||
}
|
||||
|
||||
if (!options.nonewlines) {
|
||||
fmt::print("\n");
|
||||
if (!options.nonewlines)
|
||||
{
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CLI::BINK2002Generate() {
|
||||
int CLI::BINK2002Generate()
|
||||
{
|
||||
DWORD pChannelID = this->options.channelID;
|
||||
|
||||
if (this->options.verbose) {
|
||||
if (this->options.verbose)
|
||||
{
|
||||
fmt::print("> Channel ID: {:03d}\n", this->options.channelID);
|
||||
}
|
||||
|
||||
// generate a key
|
||||
for (int i = 0; i < this->total; i++) {
|
||||
for (int i = 0; i < this->total; i++)
|
||||
{
|
||||
DWORD pAuthInfo;
|
||||
RAND_bytes((BYTE *)&pAuthInfo, 4);
|
||||
pAuthInfo &= BITMASK(10);
|
||||
|
||||
if (this->options.verbose) {
|
||||
if (this->options.verbose)
|
||||
{
|
||||
fmt::print("> AuthInfo: {}\n", pAuthInfo);
|
||||
}
|
||||
|
||||
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->pKey);
|
||||
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID,
|
||||
pAuthInfo, options.upgrade, this->pKey);
|
||||
|
||||
bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
|
||||
if (isValid) {
|
||||
if (isValid)
|
||||
{
|
||||
CLI::printKey(this->pKey);
|
||||
if (i < this->total - 1 || this->options.verbose) { // check if end of list or verbose
|
||||
if (i < this->total - 1 || this->options.verbose)
|
||||
{ // check if end of list or verbose
|
||||
fmt::print("\n");
|
||||
}
|
||||
this->count += isValid; // add to count
|
||||
}
|
||||
else {
|
||||
if (this->options.verbose) {
|
||||
else
|
||||
{
|
||||
if (this->options.verbose)
|
||||
{
|
||||
CLI::printKey(this->pKey); // print the key
|
||||
fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
|
||||
if (i < this->total - 1) { // check if end of list
|
||||
fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
|
||||
if (i < this->total - 1)
|
||||
{ // check if end of list
|
||||
fmt::print("\n");
|
||||
}
|
||||
}
|
||||
@ -511,28 +612,33 @@ int CLI::BINK2002Generate() {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->options.verbose) {
|
||||
if (this->options.verbose)
|
||||
{
|
||||
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
|
||||
}
|
||||
|
||||
if (!this->options.nonewlines) {
|
||||
fmt::print("\n");
|
||||
if (!this->options.nonewlines)
|
||||
{
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CLI::BINK1998Validate() {
|
||||
int CLI::BINK1998Validate()
|
||||
{
|
||||
char product_key[PK_LENGTH]{};
|
||||
|
||||
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key)) {
|
||||
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
|
||||
{
|
||||
fmt::print("ERROR: Product key is in an incorrect format!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLI::printKey(product_key);
|
||||
fmt::print("\n");
|
||||
if (!PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key)) {
|
||||
if (!PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
|
||||
{
|
||||
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
|
||||
return 1;
|
||||
}
|
||||
@ -541,17 +647,20 @@ int CLI::BINK1998Validate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CLI::BINK2002Validate() {
|
||||
int CLI::BINK2002Validate()
|
||||
{
|
||||
char product_key[PK_LENGTH]{};
|
||||
|
||||
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key)) {
|
||||
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
|
||||
{
|
||||
fmt::print("ERROR: Product key is in an incorrect format!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLI::printKey(product_key);
|
||||
fmt::print("\n");
|
||||
if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key)) {
|
||||
if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
|
||||
{
|
||||
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
|
||||
return 1;
|
||||
}
|
||||
@ -560,46 +669,45 @@ int CLI::BINK2002Validate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CLI::ConfirmationID() {
|
||||
int CLI::ConfirmationID()
|
||||
{
|
||||
char confirmation_id[49];
|
||||
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id, options.activationMode, options.productid);
|
||||
|
||||
switch (err) {
|
||||
case ERR_TOO_SHORT:
|
||||
fmt::print("ERROR: Installation ID is too short.\n");
|
||||
return 1;
|
||||
auto confid = new class ConfirmationID();
|
||||
int err = confid->Generate(this->options.instid.c_str(), confirmation_id, options.productid);
|
||||
|
||||
case ERR_TOO_LARGE:
|
||||
fmt::print("ERROR: Installation ID is too long.\n");
|
||||
return 1;
|
||||
if (err == SUCCESS)
|
||||
{
|
||||
fmt::print(confirmation_id);
|
||||
if (!this->options.nonewlines)
|
||||
{
|
||||
fmt::print("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ERR_INVALID_CHARACTER:
|
||||
fmt::print("ERROR: Invalid character in installation ID.\n");
|
||||
return 1;
|
||||
switch (err)
|
||||
{
|
||||
case ERR_TOO_SHORT:
|
||||
fmt::print("ERROR: Installation ID is too short.\n");
|
||||
|
||||
case ERR_INVALID_CHECK_DIGIT:
|
||||
fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n");
|
||||
return 1;
|
||||
case ERR_TOO_LARGE:
|
||||
fmt::print("ERROR: Installation ID is too long.\n");
|
||||
|
||||
case ERR_UNKNOWN_VERSION:
|
||||
fmt::print("ERROR: Unknown installation ID version.\n");
|
||||
return 1;
|
||||
case ERR_INVALID_CHARACTER:
|
||||
fmt::print("ERROR: Invalid character in installation ID.\n");
|
||||
|
||||
case ERR_UNLUCKY:
|
||||
fmt::print("ERROR: Unable to generate valid confirmation ID.\n");
|
||||
return 1;
|
||||
case ERR_INVALID_CHECK_DIGIT:
|
||||
fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n");
|
||||
|
||||
case SUCCESS:
|
||||
fmt::print(confirmation_id);
|
||||
if (!this->options.nonewlines) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
return 0;
|
||||
case ERR_UNKNOWN_VERSION:
|
||||
fmt::print("ERROR: Unknown installation ID version.\n");
|
||||
|
||||
default:
|
||||
fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err);
|
||||
case ERR_UNLUCKY:
|
||||
fmt::print("ERROR: Unable to generate valid confirmation ID.\n");
|
||||
|
||||
default:
|
||||
fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
27
src/cli.h
27
src/cli.h
@ -27,24 +27,26 @@
|
||||
|
||||
#include <cmrc/cmrc.hpp>
|
||||
|
||||
#include "libumskt/confid/confid.h"
|
||||
#include "libumskt/libumskt.h"
|
||||
#include "libumskt/pidgen2/PIDGEN2.h"
|
||||
#include "libumskt/pidgen3/PIDGEN3.h"
|
||||
#include "libumskt/pidgen3/BINK1998.h"
|
||||
#include "libumskt/pidgen3/BINK2002.h"
|
||||
#include "libumskt/confid/confid.h"
|
||||
#include "libumskt/pidgen3/PIDGEN3.h"
|
||||
|
||||
CMRC_DECLARE(umskt);
|
||||
|
||||
enum MODE {
|
||||
enum MODE
|
||||
{
|
||||
MODE_BINK1998_GENERATE = 0,
|
||||
MODE_BINK2002_GENERATE = 1,
|
||||
MODE_CONFIRMATION_ID = 2,
|
||||
MODE_CONFIRMATION_ID = 2,
|
||||
MODE_BINK1998_VALIDATE = 3,
|
||||
MODE_BINK2002_VALIDATE = 4,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
struct Options
|
||||
{
|
||||
std::string binkid;
|
||||
std::string keysFilename;
|
||||
std::string instid;
|
||||
@ -65,24 +67,25 @@ struct Options {
|
||||
ACTIVATION_ALGORITHM activationMode;
|
||||
};
|
||||
|
||||
class CLI {
|
||||
class CLI
|
||||
{
|
||||
Options options;
|
||||
json keys;
|
||||
const char* BINKID;
|
||||
const char *BINKID;
|
||||
BIGNUM *privateKey, *genOrder;
|
||||
EC_POINT *genPoint, *pubPoint;
|
||||
EC_GROUP *eCurve;
|
||||
char pKey[25];
|
||||
int count, total;
|
||||
|
||||
public:
|
||||
public:
|
||||
CLI(Options options, json keys);
|
||||
~CLI();
|
||||
|
||||
static bool loadJSON(const fs::path& filename, json *output);
|
||||
static bool loadJSON(const fs::path &filename, json *output);
|
||||
static void showHelp(char *argv[]);
|
||||
static int parseCommandLine(int argc, char* argv[], Options *options);
|
||||
static int validateCommandLine(Options* options, char *argv[], json *keys);
|
||||
static int parseCommandLine(int argc, char *argv[], Options *options);
|
||||
static int validateCommandLine(Options *options, char *argv[], json *keys);
|
||||
static void printID(DWORD *pid);
|
||||
static void printKey(char *pk);
|
||||
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
|
||||
@ -94,4 +97,4 @@ public:
|
||||
int ConfirmationID();
|
||||
};
|
||||
|
||||
#endif //UMSKT_CLI_H
|
||||
#endif // UMSKT_CLI_H
|
||||
|
@ -25,12 +25,12 @@
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
@ -38,4 +38,4 @@
|
||||
using json = nlohmann::json;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#endif //UMSKT_HEADER_H
|
||||
#endif // UMSKT_HEADER_H
|
||||
|
@ -82,19 +82,18 @@ void ConfirmationID::setFlagVersion(unsigned int flagVersion)
|
||||
ConfirmationID::flagVersion = flagVersion;
|
||||
}
|
||||
|
||||
|
||||
int ConfirmationID::calculateCheckDigit(int pid)
|
||||
{
|
||||
unsigned int i = 0, j = 0, k = 0;
|
||||
for (j = pid; j; i += k)
|
||||
{
|
||||
k = j % 10;
|
||||
j /= 10;
|
||||
}
|
||||
return ((10 * pid) - (i % 7)) + 7;
|
||||
unsigned int i = 0, j = 0, k = 0;
|
||||
for (j = pid; j; i += k)
|
||||
{
|
||||
k = j % 10;
|
||||
j /= 10;
|
||||
}
|
||||
return ((10 * pid) - (i % 7)) + 7;
|
||||
}
|
||||
|
||||
void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version)
|
||||
void ConfirmationID::decode_iid_new_version(unsigned char *iid, unsigned char *hwid, int *version)
|
||||
{
|
||||
QWORD buffer[5];
|
||||
for (int i = 0; i < 5; i++)
|
||||
@ -113,15 +112,15 @@ void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* h
|
||||
*version = buffer[0] & 7;
|
||||
}
|
||||
|
||||
void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize)
|
||||
void ConfirmationID::Mix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize)
|
||||
{
|
||||
unsigned char sha1_input[64], sha1_result[20];
|
||||
size_t half = bufSize / 2;
|
||||
unsigned char sha1_input[64], sha1_result[20];
|
||||
size_t half = bufSize / 2;
|
||||
|
||||
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
|
||||
for (int external_counter = 0; external_counter < 4; external_counter++)
|
||||
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
|
||||
for (int external_counter = 0; external_counter < 4; external_counter++)
|
||||
{
|
||||
memset(sha1_input, 0, sizeof(sha1_input));
|
||||
memset(sha1_input, 0, sizeof(sha1_input));
|
||||
|
||||
if (isXPBrand)
|
||||
{
|
||||
@ -145,30 +144,30 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c
|
||||
|
||||
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
|
||||
|
||||
for (size_t i = half & ~3; i < half; i++)
|
||||
for (size_t i = half & ~3; i < half; i++)
|
||||
{
|
||||
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < half; i++)
|
||||
for (size_t i = 0; i < half; i++)
|
||||
{
|
||||
unsigned char tmp = buffer[i + half];
|
||||
buffer[i + half] = buffer[i] ^ sha1_result[i];
|
||||
buffer[i] = tmp;
|
||||
}
|
||||
}
|
||||
unsigned char tmp = buffer[i + half];
|
||||
buffer[i + half] = buffer[i] ^ sha1_result[i];
|
||||
buffer[i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned char key[4], size_t keySize)
|
||||
void ConfirmationID::Unmix(unsigned char *buffer, size_t bufSize, const unsigned char key[4], size_t keySize)
|
||||
{
|
||||
unsigned char sha1_input[64];
|
||||
unsigned char sha1_result[20];
|
||||
size_t half = bufSize / 2;
|
||||
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
|
||||
unsigned char sha1_input[64];
|
||||
unsigned char sha1_result[20];
|
||||
size_t half = bufSize / 2;
|
||||
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
|
||||
|
||||
for (int external_counter = 0; external_counter < 4; external_counter++)
|
||||
for (int external_counter = 0; external_counter < 4; external_counter++)
|
||||
{
|
||||
memset(sha1_input, 0, sizeof(sha1_input));
|
||||
memset(sha1_input, 0, sizeof(sha1_input));
|
||||
|
||||
if (isXPBrand)
|
||||
{
|
||||
@ -188,116 +187,117 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
|
||||
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
|
||||
}
|
||||
|
||||
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
|
||||
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
|
||||
|
||||
for (size_t i = half & ~3; i < half; i++)
|
||||
for (size_t i = half & ~3; i < half; i++)
|
||||
{
|
||||
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < half; i++)
|
||||
for (size_t i = 0; i < half; i++)
|
||||
{
|
||||
unsigned char tmp = buffer[i];
|
||||
buffer[i] = buffer[i + half] ^ sha1_result[i];
|
||||
buffer[i + half] = tmp;
|
||||
}
|
||||
}
|
||||
unsigned char tmp = buffer[i];
|
||||
buffer[i] = buffer[i + half] ^ sha1_result[i];
|
||||
buffer[i + half] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], std::string productid)
|
||||
int ConfirmationID::Generate(const char *installation_id_str, char confirmation_id[49], std::string productid)
|
||||
{
|
||||
int version;
|
||||
unsigned char hardwareID[8];
|
||||
unsigned char installation_id[19]; // 10**45 < 256**19
|
||||
int version;
|
||||
unsigned char hardwareID[8];
|
||||
unsigned char installation_id[19]; // 10**45 < 256**19
|
||||
unsigned char productID[4];
|
||||
|
||||
size_t installation_id_len = 0;
|
||||
const char* pid = installation_id_str;
|
||||
size_t installation_id_len = 0;
|
||||
const char *pid = installation_id_str;
|
||||
|
||||
size_t count = 0, totalCount = 0;
|
||||
unsigned check = 0;
|
||||
size_t count = 0, totalCount = 0;
|
||||
unsigned check = 0;
|
||||
|
||||
size_t i;
|
||||
size_t i;
|
||||
|
||||
for (; *pid; pid++)
|
||||
for (; *pid; pid++)
|
||||
{
|
||||
if (*pid == ' ' || *pid == '-')
|
||||
if (*pid == ' ' || *pid == '-')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int d = *pid - '0';
|
||||
int d = *pid - '0';
|
||||
|
||||
if (d < 0 || d > 9)
|
||||
if (d < 0 || d > 9)
|
||||
{
|
||||
return ERR_INVALID_CHARACTER;
|
||||
}
|
||||
|
||||
if (count == 5 || p[1] == 0)
|
||||
if (count == 5 || p[1] == 0)
|
||||
{
|
||||
if (!count)
|
||||
if (!count)
|
||||
{
|
||||
return (totalCount == 45) ? ERR_TOO_LARGE : ERR_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (d != check % 7)
|
||||
if (d != check % 7)
|
||||
{
|
||||
return (count < 5) ? ERR_TOO_SHORT : ERR_INVALID_CHECK_DIGIT;
|
||||
}
|
||||
|
||||
check = 0;
|
||||
count = 0;
|
||||
continue;
|
||||
}
|
||||
check = 0;
|
||||
count = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
check += (count % 2 ? d * 2 : d);
|
||||
count++;
|
||||
check += (count % 2 ? d * 2 : d);
|
||||
count++;
|
||||
|
||||
totalCount++;
|
||||
if (totalCount > 45)
|
||||
totalCount++;
|
||||
if (totalCount > 45)
|
||||
{
|
||||
return ERR_TOO_LARGE;
|
||||
}
|
||||
|
||||
unsigned char carry = d;
|
||||
for (i = 0; i < installation_id_len; i++)
|
||||
unsigned char carry = d;
|
||||
for (i = 0; i < installation_id_len; i++)
|
||||
{
|
||||
unsigned x = installation_id[i] * 10 + carry;
|
||||
installation_id[i] = x & 0xFF;
|
||||
carry = x >> 8;
|
||||
}
|
||||
unsigned x = installation_id[i] * 10 + carry;
|
||||
installation_id[i] = x & 0xFF;
|
||||
carry = x >> 8;
|
||||
}
|
||||
|
||||
if (carry)
|
||||
if (carry)
|
||||
{
|
||||
assert(installation_id_len < sizeof(installation_id));
|
||||
installation_id[installation_id_len++] = carry;
|
||||
}
|
||||
}
|
||||
assert(installation_id_len < sizeof(installation_id));
|
||||
installation_id[installation_id_len++] = carry;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalCount != 41 && totalCount < 45)
|
||||
if (totalCount != 41 && totalCount < 45)
|
||||
{
|
||||
return ERR_TOO_SHORT;
|
||||
}
|
||||
|
||||
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
|
||||
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
|
||||
{
|
||||
installation_id[installation_id_len] = 0;
|
||||
}
|
||||
|
||||
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
|
||||
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
|
||||
|
||||
if (installation_id[18] >= 0x10)
|
||||
if (installation_id[18] >= 0x10)
|
||||
{
|
||||
return ERR_UNKNOWN_VERSION;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct {
|
||||
QWORD HardwareID;
|
||||
QWORD ProductIDLow;
|
||||
unsigned char ProductIDHigh;
|
||||
unsigned short KeySHA1;
|
||||
} parsed;
|
||||
struct
|
||||
{
|
||||
QWORD HardwareID;
|
||||
QWORD ProductIDLow;
|
||||
unsigned char ProductIDHigh;
|
||||
unsigned short KeySHA1;
|
||||
} parsed;
|
||||
#pragma pack(pop)
|
||||
|
||||
if (isXPBrand)
|
||||
@ -306,7 +306,7 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
|
||||
productID[0] = parsed.ProductIDLow & ((1 << 17) - 1);
|
||||
productID[1] = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1);
|
||||
productID[2] = (parsed.ProductIDLow >> 27) & ((1 << 24) - 1);
|
||||
version = (parsed.ProductIDLow >> 51) & 15;
|
||||
version = (parsed.ProductIDLow >> 51) & 15;
|
||||
productID[3] = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
|
||||
|
||||
if (flagVersion == 0)
|
||||
@ -331,9 +331,9 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
|
||||
}
|
||||
|
||||
memcpy(&parsed, hardwareID, 8);
|
||||
productID[0] = stoi(productid.substr(0,5));
|
||||
productID[0] = stoi(productid.substr(0, 5));
|
||||
|
||||
std::string channelid = productid.substr(6,3);
|
||||
std::string channelid = productid.substr(6, 3);
|
||||
char *p = &channelid[0];
|
||||
for (; *p; p++)
|
||||
{
|
||||
@ -342,38 +342,40 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
|
||||
|
||||
if (strcmp(&channelid[0], "OEM") == 0)
|
||||
{
|
||||
productID[1] = stoi(productid.substr(12,3));
|
||||
productID[2] = (stoi(productid.substr(15,1)) * 100000) + stoi(productid.substr(18,5));
|
||||
productID[1] = stoi(productid.substr(12, 3));
|
||||
productID[2] = (stoi(productid.substr(15, 1)) * 100000) + stoi(productid.substr(18, 5));
|
||||
productID[2] = calculateCheckDigit(productID[2]);
|
||||
productID[3] = ((stoi(productid.substr(10,2))) * 1000) + productID[3];
|
||||
productID[3] = ((stoi(productid.substr(10, 2))) * 1000) + productID[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
productID[1] = stoi(productid.substr(6,3));
|
||||
productID[2] = stoi(productid.substr(10,7));
|
||||
productID[3] = stoi(productid.substr(18,5));
|
||||
productID[1] = stoi(productid.substr(6, 3));
|
||||
productID[2] = stoi(productid.substr(10, 7));
|
||||
productID[3] = stoi(productid.substr(18, 5));
|
||||
}
|
||||
//fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
|
||||
// fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
|
||||
}
|
||||
|
||||
unsigned char keybuf[16];
|
||||
memcpy(keybuf, &parsed.HardwareID, 8);
|
||||
unsigned char keybuf[16];
|
||||
memcpy(keybuf, &parsed.HardwareID, 8);
|
||||
|
||||
QWORD productIdMixed = (QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
|
||||
memcpy(keybuf + 8, &productIdMixed, 8);
|
||||
QWORD productIdMixed =
|
||||
(QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
|
||||
memcpy(keybuf + 8, &productIdMixed, 8);
|
||||
|
||||
TDivisor d;
|
||||
unsigned char attempt;
|
||||
TDivisor d;
|
||||
unsigned char attempt;
|
||||
|
||||
union {
|
||||
unsigned char buffer[14];
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
QWORD lo;
|
||||
QWORD hi;
|
||||
};
|
||||
} ulowhi;
|
||||
|
||||
for (attempt = 0; attempt <= 0x80; attempt++)
|
||||
for (attempt = 0; attempt <= 0x80; attempt++)
|
||||
{
|
||||
ulowhi.lo = this->u[0];
|
||||
ulowhi.hi = this->u[1];
|
||||
@ -387,122 +389,123 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
|
||||
ulowhi.buffer[6] = attempt;
|
||||
}
|
||||
|
||||
Mix(ulowhi.buffer, 14, keybuf, 16);
|
||||
QWORD x2 = residue->ui128_quotient_mod(ulowhi.lo, ulowhi.hi);
|
||||
QWORD x1 = ulowhi.lo - x2 * MOD;
|
||||
x2++;
|
||||
Mix(ulowhi.buffer, 14, keybuf, 16);
|
||||
QWORD x2 = residue->ui128_quotient_mod(ulowhi.lo, ulowhi.hi);
|
||||
QWORD x1 = ulowhi.lo - x2 * MOD;
|
||||
x2++;
|
||||
|
||||
d.u[0] = residue->sub(residue->mul(x1, x1), residue->mul(NON_RESIDUE, residue->mul(x2, x2)));
|
||||
d.u[1] = residue->add(x1, x1);
|
||||
if (divisor->find_divisor_v(&d))
|
||||
d.u[0] = residue->sub(residue->mul(x1, x1), residue->mul(NON_RESIDUE, residue->mul(x2, x2)));
|
||||
d.u[1] = residue->add(x1, x1);
|
||||
if (divisor->find_divisor_v(&d))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attempt > 0x80)
|
||||
if (attempt > 0x80)
|
||||
{
|
||||
return ERR_UNLUCKY;
|
||||
}
|
||||
|
||||
divisor->mul128(&d, u[0], u[1], &d);
|
||||
|
||||
union {
|
||||
struct {
|
||||
QWORD encoded_lo, encoded_hi;
|
||||
};
|
||||
struct {
|
||||
uint32_t encoded[4];
|
||||
};
|
||||
} e;
|
||||
union {
|
||||
struct
|
||||
{
|
||||
QWORD encoded_lo, encoded_hi;
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t encoded[4];
|
||||
};
|
||||
} e;
|
||||
|
||||
if (d.u[0] == BAD)
|
||||
if (d.u[0] == BAD)
|
||||
{
|
||||
// we can not get the zero divisor, actually...
|
||||
e.encoded_lo = residue->__umul128(MOD + 2, MOD, &e.encoded_hi);
|
||||
}
|
||||
// we can not get the zero divisor, actually...
|
||||
e.encoded_lo = residue->__umul128(MOD + 2, MOD, &e.encoded_hi);
|
||||
}
|
||||
else if (d.u[1] == BAD)
|
||||
{
|
||||
// O(1/MOD) chance
|
||||
//encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
|
||||
e.encoded_lo += MOD;
|
||||
e.encoded_hi += (e.encoded_lo < MOD);
|
||||
}
|
||||
// O(1/MOD) chance
|
||||
// encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
|
||||
e.encoded_lo += MOD;
|
||||
e.encoded_hi += (e.encoded_lo < MOD);
|
||||
}
|
||||
else
|
||||
{
|
||||
QWORD x1 = (d.u[1] % 2 ? d.u[1] + MOD : d.u[1]) / 2;
|
||||
QWORD x2sqr = residue->sub(residue->mul(x1, x1), d.u[0]);
|
||||
QWORD x2 = residue->sqrt(x2sqr);
|
||||
QWORD x1 = (d.u[1] % 2 ? d.u[1] + MOD : d.u[1]) / 2;
|
||||
QWORD x2sqr = residue->sub(residue->mul(x1, x1), d.u[0]);
|
||||
QWORD x2 = residue->sqrt(x2sqr);
|
||||
|
||||
if (x2 == BAD)
|
||||
{
|
||||
x2 = residue->sqrt(residue->mul(x2sqr, residue->inv(NON_RESIDUE)));
|
||||
assert(x2 != BAD);
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, MOD + x2, &e.encoded_hi);
|
||||
e.encoded_lo += x1;
|
||||
e.encoded_hi += (e.encoded_lo < x1);
|
||||
}
|
||||
x2 = residue->sqrt(residue->mul(x2sqr, residue->inv(NON_RESIDUE)));
|
||||
assert(x2 != BAD);
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, MOD + x2, &e.encoded_hi);
|
||||
e.encoded_lo += x1;
|
||||
e.encoded_hi += (e.encoded_lo < x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// points (-x1+x2, v(-x1+x2)) and (-x1-x2, v(-x1-x2))
|
||||
QWORD x1a = residue->sub(x1, x2);
|
||||
QWORD y1 = residue->sub(d.v[0], residue->mul(d.v[1], x1a));
|
||||
QWORD x2a = residue->add(x1, x2);
|
||||
QWORD y2 = residue->sub(d.v[0], residue->mul(d.v[1], x2a));
|
||||
if (x1a > x2a)
|
||||
// points (-x1+x2, v(-x1+x2)) and (-x1-x2, v(-x1-x2))
|
||||
QWORD x1a = residue->sub(x1, x2);
|
||||
QWORD y1 = residue->sub(d.v[0], residue->mul(d.v[1], x1a));
|
||||
QWORD x2a = residue->add(x1, x2);
|
||||
QWORD y2 = residue->sub(d.v[0], residue->mul(d.v[1], x2a));
|
||||
if (x1a > x2a)
|
||||
{
|
||||
QWORD tmp = x1a;
|
||||
x1a = x2a;
|
||||
x2a = tmp;
|
||||
}
|
||||
QWORD tmp = x1a;
|
||||
x1a = x2a;
|
||||
x2a = tmp;
|
||||
}
|
||||
|
||||
if ((y1 ^ y2) & 1)
|
||||
{
|
||||
QWORD tmp = x1a;
|
||||
x1a = x2a;
|
||||
x2a = tmp;
|
||||
}
|
||||
QWORD tmp = x1a;
|
||||
x1a = x2a;
|
||||
x2a = tmp;
|
||||
}
|
||||
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
|
||||
e.encoded_lo += x2a;
|
||||
e.encoded_hi += (e.encoded_lo < x2a);
|
||||
e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
|
||||
e.encoded_lo += x2a;
|
||||
e.encoded_hi += (e.encoded_lo < x2a);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char decimal[35];
|
||||
for (i = 0; i < 35; i++)
|
||||
unsigned char decimal[35];
|
||||
for (i = 0; i < 35; i++)
|
||||
{
|
||||
unsigned c = e.encoded[3] % 10;
|
||||
e.encoded[3] /= 10;
|
||||
unsigned c2 = ((QWORD)c << 32 | e.encoded[2]) % 10;
|
||||
e.encoded[2] = ((QWORD)c << 32 | e.encoded[2]) / 10;
|
||||
unsigned c3 = ((QWORD)c2 << 32 | e.encoded[1]) % 10;
|
||||
e.encoded[1] = ((QWORD)c2 << 32 | e.encoded[1]) / 10;
|
||||
unsigned c4 = ((QWORD)c3 << 32 | e.encoded[0]) % 10;
|
||||
e.encoded[0] = ((QWORD)c3 << 32 | e.encoded[0]) / 10;
|
||||
decimal[34 - i] = c4;
|
||||
}
|
||||
unsigned c = e.encoded[3] % 10;
|
||||
e.encoded[3] /= 10;
|
||||
unsigned c2 = ((QWORD)c << 32 | e.encoded[2]) % 10;
|
||||
e.encoded[2] = ((QWORD)c << 32 | e.encoded[2]) / 10;
|
||||
unsigned c3 = ((QWORD)c2 << 32 | e.encoded[1]) % 10;
|
||||
e.encoded[1] = ((QWORD)c2 << 32 | e.encoded[1]) / 10;
|
||||
unsigned c4 = ((QWORD)c3 << 32 | e.encoded[0]) % 10;
|
||||
e.encoded[0] = ((QWORD)c3 << 32 | e.encoded[0]) / 10;
|
||||
decimal[34 - i] = c4;
|
||||
}
|
||||
|
||||
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
|
||||
char* q = confirmation_id;
|
||||
for (i = 0; i < 7; i++)
|
||||
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
|
||||
char *q = confirmation_id;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
if (i)
|
||||
if (i)
|
||||
{
|
||||
*q++ = '-';
|
||||
}
|
||||
|
||||
unsigned char* p = decimal + i*5;
|
||||
q[0] = p[0] + '0';
|
||||
q[1] = p[1] + '0';
|
||||
q[2] = p[2] + '0';
|
||||
q[3] = p[3] + '0';
|
||||
q[4] = p[4] + '0';
|
||||
q[5] = ((p[0]+p[1]*2+p[2]+p[3]*2+p[4]) % 7) + '0';
|
||||
q += 6;
|
||||
}
|
||||
*q++ = 0;
|
||||
return 0;
|
||||
unsigned char *p = decimal + i * 5;
|
||||
q[0] = p[0] + '0';
|
||||
q[1] = p[1] + '0';
|
||||
q[2] = p[2] + '0';
|
||||
q[3] = p[3] + '0';
|
||||
q[4] = p[4] + '0';
|
||||
q[5] = ((p[0] + p[1] * 2 + p[2] + p[3] * 2 + p[4]) % 7) + '0';
|
||||
q += 6;
|
||||
}
|
||||
*q++ = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,49 +26,53 @@
|
||||
#include "../libumskt.h"
|
||||
|
||||
// Confirmation ID generator constants
|
||||
enum CONFIRMATION_ID_STATUS {
|
||||
SUCCESS = 0,
|
||||
ERR_TOO_SHORT = 1,
|
||||
ERR_TOO_LARGE = 2,
|
||||
ERR_INVALID_CHARACTER = 3,
|
||||
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
|
||||
ERR_UNKNOWN_VERSION = 5,
|
||||
ERR_UNLUCKY = 6
|
||||
};
|
||||
|
||||
#define BAD 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
QWORD u[2];
|
||||
QWORD v[2];
|
||||
} TDivisor;
|
||||
|
||||
enum ACTIVATION_ALGORITHM {
|
||||
WINDOWS = 0,
|
||||
OFFICE_XP = 1,
|
||||
OFFICE_2K3 = 2,
|
||||
OFFICE_2K7 = 3,
|
||||
PLUS_DME = 4,
|
||||
enum ACTIVATION_ALGORITHM
|
||||
{
|
||||
WINDOWS = 0,
|
||||
OFFICE_XP = 1,
|
||||
OFFICE_2K3 = 2,
|
||||
OFFICE_2K7 = 3,
|
||||
PLUS_DME = 4,
|
||||
};
|
||||
|
||||
EXPORT class ConfirmationID {
|
||||
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 };
|
||||
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};
|
||||
unsigned char iid_key[4] = {0x0, 0x0, 0x0, 0x0};
|
||||
BOOL isOffice = false, isXPBrand = false;
|
||||
unsigned flagVersion = 0;
|
||||
public:
|
||||
|
||||
public:
|
||||
void setFlagVersion(unsigned int flagVersion);
|
||||
|
||||
private:
|
||||
|
||||
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);
|
||||
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;
|
||||
@ -79,8 +83,8 @@ private:
|
||||
friend class Divisor;
|
||||
Divisor *divisor;
|
||||
|
||||
public:
|
||||
int Generate(const char* installation_id_str, char confirmation_id[49], std::string productid);
|
||||
public:
|
||||
int Generate(const char *installation_id_str, char confirmation_id[49], std::string productid);
|
||||
|
||||
void setMod(QWORD mod);
|
||||
void setNonResidue(QWORD nonResidue);
|
||||
@ -91,28 +95,32 @@ public:
|
||||
void setIsOffice(BOOL isOffice);
|
||||
void setIsXPBrand(BOOL isXpBrand);
|
||||
|
||||
ConfirmationID() {
|
||||
ConfirmationID()
|
||||
{
|
||||
residue = new Residue(this);
|
||||
polynomial = new Polynomial(this);
|
||||
divisor = new Divisor(this);
|
||||
}
|
||||
|
||||
~ConfirmationID() {
|
||||
~ConfirmationID()
|
||||
{
|
||||
delete residue, polynomial, divisor;
|
||||
}
|
||||
};
|
||||
|
||||
class Residue {
|
||||
class Residue
|
||||
{
|
||||
ConfirmationID *parent;
|
||||
|
||||
public:
|
||||
explicit Residue(ConfirmationID *in) {
|
||||
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 __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);
|
||||
@ -121,33 +129,37 @@ public:
|
||||
QWORD sqrt(QWORD what);
|
||||
};
|
||||
|
||||
class Polynomial {
|
||||
class Polynomial
|
||||
{
|
||||
ConfirmationID *parent;
|
||||
|
||||
public:
|
||||
explicit Polynomial(ConfirmationID *in) {
|
||||
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]);
|
||||
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 {
|
||||
class Divisor
|
||||
{
|
||||
ConfirmationID *parent;
|
||||
|
||||
public:
|
||||
explicit Divisor(ConfirmationID *in) {
|
||||
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);
|
||||
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
|
||||
#endif // UMSKT_CONFID_H
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "confid.h"
|
||||
|
||||
int Divisor::find_divisor_v(TDivisor* d)
|
||||
int Divisor::find_divisor_v(TDivisor *d)
|
||||
{
|
||||
// u | v^2 - f
|
||||
// u = u0 + u1*x + x^2
|
||||
@ -36,7 +36,7 @@ int Divisor::find_divisor_v(TDivisor* d)
|
||||
|
||||
const QWORD u0 = d->u[0];
|
||||
const QWORD u1 = d->u[1];
|
||||
for (int j = 4; j--; )
|
||||
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]));
|
||||
@ -63,11 +63,12 @@ int Divisor::find_divisor_v(TDivisor* d)
|
||||
if (f1 == 0)
|
||||
{
|
||||
// impossible
|
||||
//printf("bad f(), double root detected\n");
|
||||
// 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)));
|
||||
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)
|
||||
{
|
||||
@ -76,7 +77,9 @@ int Divisor::find_divisor_v(TDivisor* d)
|
||||
}
|
||||
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))));
|
||||
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)
|
||||
{
|
||||
@ -98,14 +101,15 @@ int Divisor::find_divisor_v(TDivisor* d)
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
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])
|
||||
int Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
|
||||
{
|
||||
if (src->u[1] != BAD)
|
||||
{
|
||||
@ -132,7 +136,7 @@ int Divisor::u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2])
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
|
||||
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);
|
||||
@ -198,21 +202,25 @@ void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
|
||||
|
||||
if (ddeg > 0)
|
||||
{
|
||||
assert(udeg >= 2*ddeg);
|
||||
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;
|
||||
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;
|
||||
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) {
|
||||
while (udeg > 2)
|
||||
{
|
||||
assert(udeg <= 4);
|
||||
assert(vdeg <= 3);
|
||||
// u' = monic((f-v^2)/u), v'=-v mod u'
|
||||
@ -280,7 +288,7 @@ void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
|
||||
|
||||
#define divisor_double(src, dst) add(src, src, dst)
|
||||
|
||||
void Divisor::mul(const TDivisor* src, QWORD mult, TDivisor* dst)
|
||||
void Divisor::mul(const TDivisor *src, QWORD mult, TDivisor *dst)
|
||||
{
|
||||
if (mult == 0)
|
||||
{
|
||||
@ -309,7 +317,7 @@ void Divisor::mul(const TDivisor* src, QWORD mult, TDivisor* dst)
|
||||
}
|
||||
}
|
||||
|
||||
void Divisor::mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst)
|
||||
void Divisor::mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst)
|
||||
{
|
||||
if (mult_lo == 0 && mult_hi == 0)
|
||||
{
|
||||
@ -325,7 +333,8 @@ void Divisor::mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor
|
||||
{
|
||||
divisor_double(&cur, &cur);
|
||||
mult_lo >>= 1;
|
||||
if (mult_hi & 1) {
|
||||
if (mult_hi & 1)
|
||||
{
|
||||
mult_lo |= (1ULL << 63);
|
||||
}
|
||||
mult_hi >>= 1;
|
||||
|
@ -55,7 +55,7 @@ int Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int re
|
||||
return resultprevdeg;
|
||||
}
|
||||
|
||||
int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient)
|
||||
int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient)
|
||||
{
|
||||
assert(bdeg >= 0);
|
||||
assert(b[bdeg] == 1);
|
||||
@ -84,25 +84,32 @@ int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD*
|
||||
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])
|
||||
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;
|
||||
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;
|
||||
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];
|
||||
gcd[0] = a[0];
|
||||
gcd[1] = a[1];
|
||||
gcd[2] = a[2];
|
||||
// s*u1 + t*u2 = r
|
||||
// mult1*u1 + mult2*u2 = gcd
|
||||
|
||||
@ -112,19 +119,43 @@ void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], in
|
||||
{
|
||||
unsigned tmp;
|
||||
int tmpi;
|
||||
tmp = rdeg; rdeg = gcddeg; gcddeg = tmp;
|
||||
tmpi = sdeg; sdeg = mult1deg; mult1deg = tmpi;
|
||||
tmpi = tdeg; tdeg = mult2deg; mult2deg = 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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,11 @@
|
||||
|
||||
#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)
|
||||
inline QWORD Residue::__umul128(QWORD a, QWORD b, QWORD *hi)
|
||||
{
|
||||
OWORD r = (OWORD)a * (OWORD)b;
|
||||
*hi = r >> 64;
|
||||
return (QWORD) r;
|
||||
return (QWORD)r;
|
||||
}
|
||||
#else
|
||||
#define __umul128 _umul128
|
||||
@ -44,9 +44,9 @@ inline QWORD Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *pro
|
||||
QWORD c = multiplicand >> 32;
|
||||
QWORD d = multiplicand & 0xFFFFFFFF;
|
||||
|
||||
//QWORD ac = a * c;
|
||||
// QWORD ac = a * c;
|
||||
QWORD ad = a * d;
|
||||
//QWORD bc = b * c;
|
||||
// QWORD bc = b * c;
|
||||
QWORD bd = b * d;
|
||||
|
||||
QWORD adbc = ad + (b * c);
|
||||
@ -91,7 +91,7 @@ QWORD Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
|
||||
|
||||
QWORD Residue::mul(QWORD x, QWORD y)
|
||||
{
|
||||
// * ceil(2**170/MOD) = 0x2d351 c6d04f8b|604fa6a1 c6346a87 for (p-1)*(p-1) max
|
||||
// * 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);
|
||||
@ -128,7 +128,7 @@ QWORD Residue::pow(QWORD x, QWORD y)
|
||||
QWORD Residue::add(QWORD x, QWORD y)
|
||||
{
|
||||
QWORD z = x + y;
|
||||
//z = z - (z >= MOD ? MOD : 0);
|
||||
// z = z - (z >= MOD ? MOD : 0);
|
||||
if (z >= parent->MOD)
|
||||
{
|
||||
z -= parent->MOD;
|
||||
@ -139,7 +139,7 @@ QWORD Residue::add(QWORD x, QWORD y)
|
||||
QWORD Residue::sub(QWORD x, QWORD y)
|
||||
{
|
||||
QWORD z = x - y;
|
||||
//z += (x < y ? MOD : 0);
|
||||
// z += (x < y ? MOD : 0);
|
||||
if (x < y)
|
||||
{
|
||||
z += parent->MOD;
|
||||
@ -149,15 +149,20 @@ QWORD Residue::sub(QWORD x, QWORD y)
|
||||
|
||||
QWORD Residue::inverse(QWORD u, QWORD v)
|
||||
{
|
||||
//assert(u);
|
||||
// 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;
|
||||
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;
|
||||
@ -190,15 +195,15 @@ QWORD Residue::sqrt(QWORD what)
|
||||
x = pow(what, (q - 1) / 2);
|
||||
b = mul(mul(what, x), x);
|
||||
x = mul(what, x);
|
||||
while (b != 1) {
|
||||
while (b != 1)
|
||||
{
|
||||
QWORD m = 0, b2 = b;
|
||||
|
||||
do
|
||||
{
|
||||
m++;
|
||||
b2 = mul(b2, b2);
|
||||
}
|
||||
while (b2 != 1);
|
||||
} while (b2 != 1);
|
||||
|
||||
if (m == r)
|
||||
{
|
||||
@ -214,7 +219,7 @@ QWORD Residue::sqrt(QWORD what)
|
||||
|
||||
if (mul(x, x) != what)
|
||||
{
|
||||
//printf("internal error in sqrt\n");
|
||||
// printf("internal error in sqrt\n");
|
||||
return BAD;
|
||||
}
|
||||
|
||||
|
@ -22,14 +22,13 @@
|
||||
|
||||
#include "libumskt.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
std::FILE* UMSKT::debug = std::fopen("NUL:", "w");
|
||||
std::FILE *UMSKT::debug = std::fopen("NUL:", "w");
|
||||
#else
|
||||
std::FILE* UMSKT::debug = std::fopen("/dev/null", "w");
|
||||
std::FILE *UMSKT::debug = std::fopen("/dev/null", "w");
|
||||
#endif
|
||||
|
||||
|
||||
void UMSKT::setDebugOutput(std::FILE* input) {
|
||||
void UMSKT::setDebugOutput(std::FILE *input)
|
||||
{
|
||||
debug = input;
|
||||
}
|
||||
|
@ -22,39 +22,53 @@
|
||||
|
||||
#include "libumskt.h"
|
||||
#include "confid/confid.h"
|
||||
#include "pidgen3/PIDGEN3.h"
|
||||
#include "pidgen2/PIDGEN2.h"
|
||||
#include "pidgen3/BINK1998.h"
|
||||
#include "pidgen3/BINK2002.h"
|
||||
#include "pidgen2/PIDGEN2.h"
|
||||
#include "pidgen3/PIDGEN3.h"
|
||||
|
||||
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid) {
|
||||
FNEXPORT int ConfirmationID_Generate(const char *installation_id_str, char confirmation_id[49], int mode,
|
||||
std::string productid)
|
||||
{
|
||||
return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid);
|
||||
}
|
||||
|
||||
FNEXPORT EC_GROUP* PIDGEN3_initializeEllipticCurve(char* pSel, char* aSel, char* bSel, char* generatorXSel, char* generatorYSel, char* publicKeyXSel, char* publicKeyYSel, EC_POINT *&genPoint, EC_POINT *&pubPoint) {
|
||||
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel, publicKeyYSel, genPoint, pubPoint);
|
||||
FNEXPORT EC_GROUP *PIDGEN3_initializeEllipticCurve(char *pSel, char *aSel, char *bSel, char *generatorXSel,
|
||||
char *generatorYSel, char *publicKeyXSel, char *publicKeyYSel,
|
||||
EC_POINT *&genPoint, EC_POINT *&pubPoint)
|
||||
{
|
||||
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel,
|
||||
publicKeyYSel, genPoint, pubPoint);
|
||||
}
|
||||
|
||||
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]) {
|
||||
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
|
||||
{
|
||||
return PIDGEN3::BINK1998::Verify(eCurve, basePoint, publicKey, pKey);
|
||||
}
|
||||
|
||||
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, BOOL pUpgrade,char (&pKey)[25]) {
|
||||
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
|
||||
DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
|
||||
{
|
||||
return PIDGEN3::BINK1998::Generate(eCurve, basePoint, genOrder, privateKey, pSerial, pUpgrade, pKey);
|
||||
}
|
||||
|
||||
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]) {
|
||||
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
|
||||
{
|
||||
return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, cdKey);
|
||||
}
|
||||
|
||||
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]) {
|
||||
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
|
||||
DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25])
|
||||
{
|
||||
return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, pKey);
|
||||
}
|
||||
|
||||
FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) {
|
||||
FNEXPORT int PIDGEN2_GenerateRetail(char *channelID, char *&keyout)
|
||||
{
|
||||
return PIDGEN2::GenerateRetail(channelID, keyout);
|
||||
}
|
||||
|
||||
FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout) {
|
||||
FNEXPORT int PIDGEN2_GenerateOEM(char *year, char *day, char *oem, char *keyout)
|
||||
{
|
||||
return PIDGEN2::GenerateOEM(year, day, oem, keyout);
|
||||
}
|
||||
|
@ -25,49 +25,49 @@
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
// Algorithm macros
|
||||
#define PK_LENGTH 25
|
||||
#define NULL_TERMINATOR 1
|
||||
#define PK_LENGTH 25
|
||||
#define NULL_TERMINATOR 1
|
||||
|
||||
#define FIELD_BITS 384
|
||||
#define FIELD_BYTES 48
|
||||
#define FIELD_BITS_2003 512
|
||||
#define FIELD_BYTES_2003 64
|
||||
#define FIELD_BITS 384
|
||||
#define FIELD_BYTES 48
|
||||
#define FIELD_BITS_2003 512
|
||||
#define FIELD_BYTES_2003 64
|
||||
|
||||
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
|
||||
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
|
||||
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
|
||||
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
|
||||
|
||||
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
|
||||
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
|
||||
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
|
||||
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
|
||||
|
||||
#define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes) * 8), ((bytes) * 8))
|
||||
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((bytes) * 8))
|
||||
#define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes)*8), ((bytes)*8))
|
||||
#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 BITMASK(n) ((1ULL << (n)) - 1)
|
||||
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
|
||||
#define BITMASK(n) ((1ULL << (n)) - 1)
|
||||
|
||||
class UMSKT {
|
||||
public:
|
||||
static std::FILE* debug;
|
||||
class UMSKT
|
||||
{
|
||||
public:
|
||||
static std::FILE *debug;
|
||||
class PIDGEN2;
|
||||
class PIDGEN3;
|
||||
class ConfigurationID;
|
||||
|
||||
static void setDebugOutput(std::FILE* input);
|
||||
static void setDebugOutput(std::FILE *input);
|
||||
};
|
||||
|
||||
|
||||
#endif //UMSKT_LIBUMSKT_H
|
||||
#endif // UMSKT_LIBUMSKT_H
|
||||
|
@ -22,12 +22,15 @@
|
||||
|
||||
#include "PIDGEN2.h"
|
||||
|
||||
const char* channelIDBlacklist [7] = {"333", "444", "555", "666", "777", "888", "999"};
|
||||
const char* validYears[8] = { "95", "96", "97", "98", "99", "00", "01", "02"};
|
||||
const char *channelIDBlacklist[7] = {"333", "444", "555", "666", "777", "888", "999"};
|
||||
const char *validYears[8] = {"95", "96", "97", "98", "99", "00", "01", "02"};
|
||||
|
||||
bool PIDGEN2::isNumericString(char* input) {
|
||||
for(int i = 0; i < strlen(input); i++) {
|
||||
if (input[i] < '0' || input[i] > '9') {
|
||||
bool PIDGEN2::isNumericString(char *input)
|
||||
{
|
||||
for (int i = 0; i < strlen(input); i++)
|
||||
{
|
||||
if (input[i] < '0' || input[i] > '9')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -35,27 +38,34 @@ bool PIDGEN2::isNumericString(char* input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int PIDGEN2::addDigits(char* input) {
|
||||
int PIDGEN2::addDigits(char *input)
|
||||
{
|
||||
int output = 0;
|
||||
|
||||
if (!isNumericString(input)) {
|
||||
if (!isNumericString(input))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i = 0; i < strlen(input); i++) {
|
||||
for (int i = 0; i < strlen(input); i++)
|
||||
{
|
||||
output += input[i] - '0';
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool PIDGEN2::isValidChannelID(char* channelID) {
|
||||
if (strlen(channelID) > 3) {
|
||||
bool PIDGEN2::isValidChannelID(char *channelID)
|
||||
{
|
||||
if (strlen(channelID) > 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 6; i++) {
|
||||
if (strcmp(channelID, channelIDBlacklist[i]) != 0) {
|
||||
for (int i = 0; i <= 6; i++)
|
||||
{
|
||||
if (strcmp(channelID, channelIDBlacklist[i]) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -63,13 +73,17 @@ bool PIDGEN2::isValidChannelID(char* channelID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIDGEN2::isValidOEMID(char* OEMID) {
|
||||
if (!isNumericString(OEMID)) {
|
||||
bool PIDGEN2::isValidOEMID(char *OEMID)
|
||||
{
|
||||
if (!isNumericString(OEMID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen(OEMID) > 5) {
|
||||
if (OEMID[0] != '0' || OEMID[1] != '0') {
|
||||
if (strlen(OEMID) > 5)
|
||||
{
|
||||
if (OEMID[0] != '0' || OEMID[1] != '0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -79,52 +93,65 @@ bool PIDGEN2::isValidOEMID(char* OEMID) {
|
||||
return (mod % 21 == 0);
|
||||
}
|
||||
|
||||
bool PIDGEN2::isValidYear(char* year) {
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
if (year == validYears[i]) {
|
||||
bool PIDGEN2::isValidYear(char *year)
|
||||
{
|
||||
for (int i = 0; i <= 7; i++)
|
||||
{
|
||||
if (year == validYears[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIDGEN2::isValidDay(char* day) {
|
||||
if (!isNumericString(day)) {
|
||||
bool PIDGEN2::isValidDay(char *day)
|
||||
{
|
||||
if (!isNumericString(day))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int iDay = std::stoi(day);
|
||||
if (iDay == 0 || iDay >= 365) {
|
||||
if (iDay == 0 || iDay >= 365)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIDGEN2::isValidRetailProductID(char* productID) {
|
||||
bool PIDGEN2::isValidRetailProductID(char *productID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int PIDGEN2::GenerateRetail(char* channelID, char* &keyout) {
|
||||
if (!isValidChannelID(channelID)) {
|
||||
int PIDGEN2::GenerateRetail(char *channelID, char *&keyout)
|
||||
{
|
||||
if (!isValidChannelID(channelID))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PIDGEN2::GenerateOEM(char* year, char* day, char* oem, char* &keyout) {
|
||||
if (!isValidOEMID(oem)) {
|
||||
int PIDGEN2::GenerateOEM(char *year, char *day, char *oem, char *&keyout)
|
||||
{
|
||||
if (!isValidOEMID(oem))
|
||||
{
|
||||
int mod = addDigits(oem);
|
||||
mod += mod % 21;
|
||||
|
||||
strcpy(oem, fmt::format("{:07d}", mod).c_str());
|
||||
}
|
||||
|
||||
if (!isValidYear(year)) {
|
||||
if (!isValidYear(year))
|
||||
{
|
||||
strcpy(year, validYears[0]);
|
||||
}
|
||||
|
||||
if (!isValidDay(day)) {
|
||||
if (!isValidDay(day))
|
||||
{
|
||||
int iday = std::stoi(day);
|
||||
iday = (iday + 1) % 365;
|
||||
}
|
||||
|
@ -25,17 +25,18 @@
|
||||
|
||||
#include "../libumskt.h"
|
||||
|
||||
EXPORT class PIDGEN2 {
|
||||
public:
|
||||
static bool isNumericString(char* input);
|
||||
static bool isValidChannelID(char* channelID);
|
||||
static bool isValidOEMID(char* OEMID);
|
||||
static bool isValidYear(char* year);
|
||||
static bool isValidDay(char* day);
|
||||
static bool isValidRetailProductID(char* productID);
|
||||
static int addDigits(char* input);
|
||||
static int GenerateRetail(char* channelID, char* &keyout);
|
||||
static int GenerateOEM(char* year, char* day, char* oem, char* &keyout);
|
||||
EXPORT class PIDGEN2
|
||||
{
|
||||
public:
|
||||
static bool isNumericString(char *input);
|
||||
static bool isValidChannelID(char *channelID);
|
||||
static bool isValidOEMID(char *OEMID);
|
||||
static bool isValidYear(char *year);
|
||||
static bool isValidDay(char *day);
|
||||
static bool isValidRetailProductID(char *productID);
|
||||
static int addDigits(char *input);
|
||||
static int GenerateRetail(char *channelID, char *&keyout);
|
||||
static int GenerateOEM(char *year, char *day, char *oem, char *&keyout);
|
||||
};
|
||||
|
||||
#endif //UMSKT_PIDGEN2_H
|
||||
#endif // UMSKT_PIDGEN2_H
|
||||
|
@ -30,13 +30,8 @@
|
||||
#include "BINK1998.h"
|
||||
|
||||
/* Unpacks a Windows XP-like Product Key. */
|
||||
void PIDGEN3::BINK1998::Unpack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL &pUpgrade,
|
||||
DWORD &pSerial,
|
||||
DWORD &pHash,
|
||||
QWORD &pSignature
|
||||
) {
|
||||
void PIDGEN3::BINK1998::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature)
|
||||
{
|
||||
// We're assuming that the quantity of information within the product key is at most 114 bits.
|
||||
// log2(24^25) = 114.
|
||||
|
||||
@ -54,13 +49,8 @@ void PIDGEN3::BINK1998::Unpack(
|
||||
}
|
||||
|
||||
/* Packs a Windows XP-like Product Key. */
|
||||
void PIDGEN3::BINK1998::Pack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL pUpgrade,
|
||||
DWORD pSerial,
|
||||
DWORD pHash,
|
||||
QWORD pSignature
|
||||
) {
|
||||
void PIDGEN3::BINK1998::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature)
|
||||
{
|
||||
// The quantity of information the key provides is 114 bits.
|
||||
// We're storing it in 2 64-bit quad-words with 14 trailing bits.
|
||||
// 64 * 2 = 128
|
||||
@ -71,22 +61,15 @@ void PIDGEN3::BINK1998::Pack(
|
||||
}
|
||||
|
||||
/* Verifies a Windows XP-like Product Key. */
|
||||
bool PIDGEN3::BINK1998::Verify(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
EC_POINT *publicKey,
|
||||
char (&pKey)[25]
|
||||
) {
|
||||
bool PIDGEN3::BINK1998::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
|
||||
{
|
||||
BN_CTX *numContext = BN_CTX_new();
|
||||
|
||||
QWORD pRaw[2]{},
|
||||
pSignature;
|
||||
QWORD pRaw[2]{}, pSignature;
|
||||
|
||||
DWORD pData,
|
||||
pSerial,
|
||||
pHash;
|
||||
DWORD pData, pSerial, pHash;
|
||||
|
||||
BOOL pUpgrade;
|
||||
BOOL pUpgrade;
|
||||
|
||||
// Convert Base24 CD-key to bytecode.
|
||||
PIDGEN3::unbase24((BYTE *)pRaw, pKey);
|
||||
@ -119,9 +102,7 @@ bool PIDGEN3::BINK1998::Verify(
|
||||
*/
|
||||
|
||||
BIGNUM *e = BN_lebin2bn((BYTE *)&pHash, sizeof(pHash), nullptr),
|
||||
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr),
|
||||
*x = BN_new(),
|
||||
*y = BN_new();
|
||||
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
|
||||
|
||||
// Create 2 points on the elliptic curve.
|
||||
EC_POINT *t = EC_POINT_new(eCurve);
|
||||
@ -139,10 +120,7 @@ bool PIDGEN3::BINK1998::Verify(
|
||||
// x = P.x; y = P.y;
|
||||
EC_POINT_get_affine_coordinates(eCurve, p, x, y, numContext);
|
||||
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||
msgBuffer[SHA_MSG_LENGTH_XP]{},
|
||||
xBin[FIELD_BYTES]{},
|
||||
yBin[FIELD_BYTES]{};
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_XP]{}, xBin[FIELD_BYTES]{}, yBin[FIELD_BYTES]{};
|
||||
|
||||
// Convert resulting point coordinates to bytes.
|
||||
BN_bn2lebin(x, xBin, FIELD_BYTES);
|
||||
@ -175,29 +153,20 @@ bool PIDGEN3::BINK1998::Verify(
|
||||
}
|
||||
|
||||
/* Generates a Windows XP-like Product Key. */
|
||||
void PIDGEN3::BINK1998::Generate(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
BIGNUM *genOrder,
|
||||
BIGNUM *privateKey,
|
||||
DWORD pSerial,
|
||||
BOOL pUpgrade,
|
||||
char (&pKey)[25]
|
||||
) {
|
||||
void PIDGEN3::BINK1998::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
|
||||
DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
|
||||
{
|
||||
BN_CTX *numContext = BN_CTX_new();
|
||||
|
||||
BIGNUM *c = BN_new(),
|
||||
*s = BN_new(),
|
||||
*x = BN_new(),
|
||||
*y = BN_new();
|
||||
BIGNUM *c = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
|
||||
|
||||
QWORD pRaw[2]{},
|
||||
pSignature = 0;
|
||||
QWORD pRaw[2]{}, pSignature = 0;
|
||||
|
||||
// Data segment of the RPK.
|
||||
DWORD pData = pSerial << 1 | pUpgrade;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
EC_POINT *r = EC_POINT_new(eCurve);
|
||||
|
||||
// Generate a random number c consisting of 384 bits without any constraints.
|
||||
@ -211,10 +180,7 @@ void PIDGEN3::BINK1998::Generate(
|
||||
// x = R.x; y = R.y;
|
||||
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
|
||||
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||
msgBuffer[SHA_MSG_LENGTH_XP]{},
|
||||
xBin[FIELD_BYTES]{},
|
||||
yBin[FIELD_BYTES]{};
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_XP]{}, xBin[FIELD_BYTES]{}, yBin[FIELD_BYTES]{};
|
||||
|
||||
// Convert coordinates to bytes.
|
||||
BN_bn2lebin(x, xBin, FIELD_BYTES);
|
||||
|
@ -25,40 +25,17 @@
|
||||
|
||||
#include "PIDGEN3.h"
|
||||
|
||||
EXPORT class PIDGEN3::BINK1998 {
|
||||
public:
|
||||
static void Unpack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL &pUpgrade,
|
||||
DWORD &pSerial,
|
||||
DWORD &pHash,
|
||||
QWORD &pSignature
|
||||
);
|
||||
EXPORT class PIDGEN3::BINK1998
|
||||
{
|
||||
public:
|
||||
static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature);
|
||||
|
||||
static void Pack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL pUpgrade,
|
||||
DWORD pSerial,
|
||||
DWORD pHash,
|
||||
QWORD pSignature
|
||||
);
|
||||
static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature);
|
||||
|
||||
static bool Verify(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
EC_POINT *publicKey,
|
||||
char (&pKey)[25]
|
||||
);
|
||||
static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]);
|
||||
|
||||
static void Generate(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
BIGNUM *genOrder,
|
||||
BIGNUM *privateKey,
|
||||
DWORD pSerial,
|
||||
BOOL pUpgrade,
|
||||
char (&pKey)[25]
|
||||
);
|
||||
static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial,
|
||||
BOOL pUpgrade, char (&pKey)[25]);
|
||||
};
|
||||
|
||||
#endif //UMSKT_BINK1998_H
|
||||
#endif // UMSKT_BINK1998_H
|
||||
|
@ -30,14 +30,9 @@
|
||||
#include "BINK2002.h"
|
||||
|
||||
/* Unpacks a Windows Server 2003-like Product Key. */
|
||||
void PIDGEN3::BINK2002::Unpack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL &pUpgrade,
|
||||
DWORD &pChannelID,
|
||||
DWORD &pHash,
|
||||
QWORD &pSignature,
|
||||
DWORD &pAuthInfo
|
||||
) {
|
||||
void PIDGEN3::BINK2002::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
|
||||
DWORD &pAuthInfo)
|
||||
{
|
||||
// We're assuming that the quantity of information within the product key is at most 114 bits.
|
||||
// log2(24^25) = 114.
|
||||
|
||||
@ -60,37 +55,24 @@ void PIDGEN3::BINK2002::Unpack(
|
||||
}
|
||||
|
||||
/* Packs a Windows Server 2003-like Product Key. */
|
||||
void PIDGEN3::BINK2002::Pack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL pUpgrade,
|
||||
DWORD pChannelID,
|
||||
DWORD pHash,
|
||||
QWORD pSignature,
|
||||
DWORD pAuthInfo
|
||||
) {
|
||||
void PIDGEN3::BINK2002::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature,
|
||||
DWORD pAuthInfo)
|
||||
{
|
||||
// AuthInfo [113..104] <- Signature [103..42] <- Hash [41..11] <- Channel ID [10..1] <- Upgrade [0]
|
||||
pRaw[0] = FIRSTNBITS(pSignature, 22) << 42 | (QWORD)pHash << 11 | pChannelID << 1 | pUpgrade;
|
||||
pRaw[1] = FIRSTNBITS(pAuthInfo, 10) << 40 | NEXTSNBITS(pSignature, 40, 22);
|
||||
}
|
||||
|
||||
/* Verifies a Windows Server 2003-like Product Key. */
|
||||
bool PIDGEN3::BINK2002::Verify(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
EC_POINT *publicKey,
|
||||
char (&cdKey)[25]
|
||||
) {
|
||||
bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
|
||||
{
|
||||
BN_CTX *context = BN_CTX_new();
|
||||
|
||||
QWORD bKey[2]{},
|
||||
pSignature = 0;
|
||||
QWORD bKey[2]{}, pSignature = 0;
|
||||
|
||||
DWORD pData,
|
||||
pChannelID,
|
||||
pHash,
|
||||
pAuthInfo;
|
||||
DWORD pData, pChannelID, pHash, pAuthInfo;
|
||||
|
||||
BOOL pUpgrade;
|
||||
BOOL pUpgrade;
|
||||
|
||||
// Convert Base24 CD-key to bytecode.
|
||||
unbase24((BYTE *)bKey, cdKey);
|
||||
@ -108,10 +90,8 @@ bool PIDGEN3::BINK2002::Verify(
|
||||
fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
|
||||
fmt::print(UMSKT::debug, "\n");
|
||||
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||
msgBuffer[SHA_MSG_LENGTH_2003]{},
|
||||
xBin[FIELD_BYTES_2003]{},
|
||||
yBin[FIELD_BYTES_2003]{};
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{},
|
||||
yBin[FIELD_BYTES_2003]{};
|
||||
|
||||
// Assemble the first SHA message.
|
||||
msgBuffer[0x00] = 0x5D;
|
||||
@ -130,7 +110,8 @@ bool PIDGEN3::BINK2002::Verify(
|
||||
SHA1(msgBuffer, 11, msgDigest);
|
||||
|
||||
// Translate the byte digest into a 64-bit integer - this is our computed intermediate signature.
|
||||
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits (per spec).
|
||||
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits
|
||||
// (per spec).
|
||||
QWORD iSignature = NEXTSNBITS(BYDWORD(&msgDigest[4]), 30, 2) << 32 | BYDWORD(msgDigest);
|
||||
|
||||
/*
|
||||
@ -149,9 +130,7 @@ bool PIDGEN3::BINK2002::Verify(
|
||||
*/
|
||||
|
||||
BIGNUM *e = BN_lebin2bn((BYTE *)&iSignature, sizeof(iSignature), nullptr),
|
||||
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr),
|
||||
*x = BN_new(),
|
||||
*y = BN_new();
|
||||
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
|
||||
|
||||
// Create 2 points on the elliptic curve.
|
||||
EC_POINT *p = EC_POINT_new(eCurve);
|
||||
@ -206,33 +185,22 @@ bool PIDGEN3::BINK2002::Verify(
|
||||
}
|
||||
|
||||
/* Generates a Windows Server 2003-like Product Key. */
|
||||
void PIDGEN3::BINK2002::Generate(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
BIGNUM *genOrder,
|
||||
BIGNUM *privateKey,
|
||||
DWORD pChannelID,
|
||||
DWORD pAuthInfo,
|
||||
BOOL pUpgrade,
|
||||
char (&pKey)[25]
|
||||
) {
|
||||
void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
|
||||
DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25])
|
||||
{
|
||||
BN_CTX *numContext = BN_CTX_new();
|
||||
|
||||
BIGNUM *c = BN_new(),
|
||||
*e = BN_new(),
|
||||
*s = BN_new(),
|
||||
*x = BN_new(),
|
||||
*y = BN_new();
|
||||
BIGNUM *c = BN_new(), *e = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
|
||||
|
||||
QWORD pRaw[2]{},
|
||||
pSignature = 0;
|
||||
QWORD pRaw[2]{}, pSignature = 0;
|
||||
|
||||
// Data segment of the RPK.
|
||||
DWORD pData = pChannelID << 1 | pUpgrade;
|
||||
|
||||
BOOL noSquare;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
EC_POINT *r = EC_POINT_new(eCurve);
|
||||
|
||||
// Generate a random number c consisting of 512 bits without any constraints.
|
||||
@ -245,10 +213,8 @@ void PIDGEN3::BINK2002::Generate(
|
||||
// x = R.x; y = R.y;
|
||||
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
|
||||
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||
msgBuffer[SHA_MSG_LENGTH_2003]{},
|
||||
xBin[FIELD_BYTES_2003]{},
|
||||
yBin[FIELD_BYTES_2003]{};
|
||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{},
|
||||
yBin[FIELD_BYTES_2003]{};
|
||||
|
||||
// Convert resulting point coordinates to bytes.
|
||||
BN_bn2lebin(x, xBin, FIELD_BYTES_2003);
|
||||
@ -286,7 +252,8 @@ void PIDGEN3::BINK2002::Generate(
|
||||
SHA1(msgBuffer, 11, msgDigest);
|
||||
|
||||
// Translate the byte digest into a 64-bit integer - this is our computed intermediate signature.
|
||||
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits (per spec).
|
||||
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2
|
||||
// bits (per spec).
|
||||
QWORD iSignature = NEXTSNBITS(BYDWORD(&msgDigest[4]), 30, 2) << 32 | BYDWORD(msgDigest);
|
||||
|
||||
BN_lebin2bn((BYTE *)&iSignature, sizeof(iSignature), e);
|
||||
@ -346,9 +313,11 @@ void PIDGEN3::BINK2002::Generate(
|
||||
// If s is odd, add order to it.
|
||||
// The order is a prime, so it can't be even.
|
||||
if (BN_is_odd(s))
|
||||
{
|
||||
|
||||
// s = -ek + √((ek)² + 4c) + n
|
||||
BN_add(s, s, genOrder);
|
||||
}
|
||||
|
||||
// s /= 2 (s >>= 1)
|
||||
BN_rshift1(s, s);
|
||||
|
@ -25,43 +25,18 @@
|
||||
|
||||
#include "PIDGEN3.h"
|
||||
|
||||
EXPORT class PIDGEN3::BINK2002 {
|
||||
public:
|
||||
static void Unpack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL &pUpgrade,
|
||||
DWORD &pChannelID,
|
||||
DWORD &pHash,
|
||||
QWORD &pSignature,
|
||||
DWORD &pAuthInfo
|
||||
);
|
||||
EXPORT class PIDGEN3::BINK2002
|
||||
{
|
||||
public:
|
||||
static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
|
||||
DWORD &pAuthInfo);
|
||||
|
||||
static void Pack(
|
||||
QWORD (&pRaw)[2],
|
||||
BOOL pUpgrade,
|
||||
DWORD pChannelID,
|
||||
DWORD pHash,
|
||||
QWORD pSignature,
|
||||
DWORD pAuthInfo
|
||||
);
|
||||
static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature, DWORD pAuthInfo);
|
||||
|
||||
static bool Verify(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
EC_POINT *publicKey,
|
||||
char (&cdKey)[25]
|
||||
);
|
||||
static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]);
|
||||
|
||||
static void Generate(
|
||||
EC_GROUP *eCurve,
|
||||
EC_POINT *basePoint,
|
||||
BIGNUM *genOrder,
|
||||
BIGNUM *privateKey,
|
||||
DWORD pChannelID,
|
||||
DWORD pAuthInfo,
|
||||
BOOL pUpgrade,
|
||||
char (&pKey)[25]
|
||||
);
|
||||
static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID,
|
||||
DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]);
|
||||
};
|
||||
|
||||
#endif //UMSKT_BINK2002_H
|
||||
#endif // UMSKT_BINK2002_H
|
||||
|
@ -25,25 +25,20 @@
|
||||
|
||||
#include "../libumskt.h"
|
||||
|
||||
class PIDGEN3 {
|
||||
public:
|
||||
class PIDGEN3
|
||||
{
|
||||
public:
|
||||
class BINK1998;
|
||||
class BINK2002;
|
||||
|
||||
// util.cpp
|
||||
static int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
|
||||
static int BN_bn2lebin(const BIGNUM *a, unsigned char *to,
|
||||
int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
|
||||
static void endian(BYTE *data, int length);
|
||||
static EC_GROUP* initializeEllipticCurve(
|
||||
std::string pSel,
|
||||
std::string aSel,
|
||||
std::string bSel,
|
||||
std::string generatorXSel,
|
||||
std::string generatorYSel,
|
||||
std::string publicKeyXSel,
|
||||
std::string publicKeyYSel,
|
||||
EC_POINT *&genPoint,
|
||||
EC_POINT *&pubPoint
|
||||
);
|
||||
static EC_GROUP *initializeEllipticCurve(std::string pSel, std::string aSel, std::string bSel,
|
||||
std::string generatorXSel, std::string generatorYSel,
|
||||
std::string publicKeyXSel, std::string publicKeyYSel, EC_POINT *&genPoint,
|
||||
EC_POINT *&pubPoint);
|
||||
|
||||
// key.cpp
|
||||
static constexpr char pKeyCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
||||
@ -51,4 +46,4 @@ public:
|
||||
static void base24(char *cdKey, BYTE *byteSeq);
|
||||
};
|
||||
|
||||
#endif //UMSKT_PIDGEN3_H
|
||||
#endif // UMSKT_PIDGEN3_H
|
||||
|
@ -23,16 +23,20 @@
|
||||
#include "PIDGEN3.h"
|
||||
|
||||
/* Converts from CD-key to a byte sequence. */
|
||||
void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
|
||||
void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey)
|
||||
{
|
||||
BYTE pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{};
|
||||
BIGNUM *y = BN_new();
|
||||
|
||||
BN_zero(y);
|
||||
|
||||
// Remove dashes from the CD-key and put it into a Base24 byte array.
|
||||
for (int i = 0, k = 0; i < strlen(cdKey) && k < PK_LENGTH; i++) {
|
||||
for (int j = 0; j < 24; j++) {
|
||||
if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j]) {
|
||||
for (int i = 0, k = 0; i < strlen(cdKey) && k < PK_LENGTH; i++)
|
||||
{
|
||||
for (int j = 0; j < 24; j++)
|
||||
{
|
||||
if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j])
|
||||
{
|
||||
pDecodedKey[k++] = j;
|
||||
break;
|
||||
}
|
||||
@ -43,7 +47,8 @@ void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
|
||||
memset(byteSeq, 0, 16);
|
||||
|
||||
// Calculate the weighed sum of byte array elements.
|
||||
for (int i = 0; i < PK_LENGTH; i++) {
|
||||
for (int i = 0; i < PK_LENGTH; i++)
|
||||
{
|
||||
BN_mul_word(y, PK_LENGTH - 1);
|
||||
BN_add_word(y, pDecodedKey[i]);
|
||||
}
|
||||
@ -60,7 +65,8 @@ void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
|
||||
}
|
||||
|
||||
/* Converts from byte sequence to the CD-key. */
|
||||
void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
|
||||
void PIDGEN3::base24(char *cdKey, BYTE *byteSeq)
|
||||
{
|
||||
BYTE rbyteSeq[16];
|
||||
BIGNUM *z;
|
||||
|
||||
@ -70,7 +76,10 @@ void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
|
||||
// Skip trailing zeroes and reverse y.
|
||||
int length;
|
||||
|
||||
for (length = 15; rbyteSeq[length] == 0; length--);
|
||||
for (length = 15; rbyteSeq[length] == 0; length--)
|
||||
{
|
||||
;
|
||||
}
|
||||
endian(rbyteSeq, ++length);
|
||||
|
||||
// Convert reversed byte sequence to BigNum z.
|
||||
@ -80,7 +89,9 @@ void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
|
||||
cdKey[25] = 0;
|
||||
|
||||
for (int i = 24; i >= 0; i--)
|
||||
{
|
||||
cdKey[i] = pKeyCharset[BN_div_word(z, 24)];
|
||||
}
|
||||
|
||||
BN_free(z);
|
||||
}
|
||||
|
@ -22,14 +22,17 @@
|
||||
|
||||
#include "PIDGEN3.h"
|
||||
|
||||
int randomRange() {
|
||||
return 4; // chosen by fair dice roll
|
||||
// guaranteed to be random
|
||||
int randomRange()
|
||||
{
|
||||
return 4; // chosen by fair dice roll
|
||||
// guaranteed to be random
|
||||
}
|
||||
|
||||
/* Convert data between endianness types. */
|
||||
void PIDGEN3::endian(BYTE *data, int length) {
|
||||
for (int i = 0; i < length / 2; i++) {
|
||||
void PIDGEN3::endian(BYTE *data, int length)
|
||||
{
|
||||
for (int i = 0; i < length / 2; i++)
|
||||
{
|
||||
BYTE temp = data[i];
|
||||
data[i] = data[length - i - 1];
|
||||
data[length - i - 1] = temp;
|
||||
@ -37,17 +40,11 @@ void PIDGEN3::endian(BYTE *data, int length) {
|
||||
}
|
||||
|
||||
/* Initializes the elliptic curve. */
|
||||
EC_GROUP* PIDGEN3::initializeEllipticCurve(
|
||||
const std::string pSel,
|
||||
const std::string aSel,
|
||||
const std::string bSel,
|
||||
const std::string generatorXSel,
|
||||
const std::string generatorYSel,
|
||||
const std::string publicKeyXSel,
|
||||
const std::string publicKeyYSel,
|
||||
EC_POINT *&genPoint,
|
||||
EC_POINT *&pubPoint
|
||||
) {
|
||||
EC_GROUP *PIDGEN3::initializeEllipticCurve(const std::string pSel, const std::string aSel, const std::string bSel,
|
||||
const std::string generatorXSel, const std::string generatorYSel,
|
||||
const std::string publicKeyXSel, const std::string publicKeyYSel,
|
||||
EC_POINT *&genPoint, EC_POINT *&pubPoint)
|
||||
{
|
||||
// Initialize BIGNUM and BIGNUMCTX structures.
|
||||
// BIGNUM - Large numbers
|
||||
// BIGNUMCTX - Context large numbers (temporary)
|
||||
@ -83,7 +80,8 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
|
||||
|
||||
/* Elliptic 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.
|
||||
// The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the
|
||||
// curve given in group.
|
||||
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).
|
||||
@ -94,7 +92,8 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
|
||||
pubPoint = EC_POINT_new(eCurve);
|
||||
EC_POINT_set_affine_coordinates(eCurve, pubPoint, publicKeyX, publicKeyY, context);
|
||||
|
||||
// If generator and public key points are not on the elliptic curve, either the generator or the public key values are incorrect.
|
||||
// If generator and public key points are not on the elliptic curve, either the generator or the public key values
|
||||
// are incorrect.
|
||||
assert(EC_POINT_is_on_curve(eCurve, genPoint, context) == true);
|
||||
assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true);
|
||||
|
||||
@ -111,14 +110,19 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
|
||||
return eCurve;
|
||||
}
|
||||
|
||||
int PIDGEN3::BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen) {
|
||||
int PIDGEN3::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);
|
||||
|
38
src/main.cpp
38
src/main.cpp
@ -20,13 +20,15 @@
|
||||
* @Maintainer Neo
|
||||
*/
|
||||
|
||||
#include "header.h"
|
||||
#include "cli.h"
|
||||
#include "header.h"
|
||||
|
||||
Options options;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!CLI::parseCommandLine(argc, argv, &options)) {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (!CLI::parseCommandLine(argc, argv, &options))
|
||||
{
|
||||
fmt::print("error parsing command line options\n");
|
||||
CLI::showHelp(argv);
|
||||
return !options.error ? 0 : 1;
|
||||
@ -35,29 +37,31 @@ int main(int argc, char *argv[]) {
|
||||
json keys;
|
||||
|
||||
int status = CLI::validateCommandLine(&options, argv, &keys);
|
||||
if (status > 0) {
|
||||
if (status > 0)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
CLI run(options, keys);
|
||||
|
||||
switch(options.applicationMode) {
|
||||
case MODE_BINK1998_GENERATE:
|
||||
return run.BINK1998Generate();
|
||||
switch (options.applicationMode)
|
||||
{
|
||||
case MODE_BINK1998_GENERATE:
|
||||
return run.BINK1998Generate();
|
||||
|
||||
case MODE_BINK2002_GENERATE:
|
||||
return run.BINK2002Generate();
|
||||
case MODE_BINK2002_GENERATE:
|
||||
return run.BINK2002Generate();
|
||||
|
||||
case MODE_BINK1998_VALIDATE:
|
||||
return run.BINK1998Validate();
|
||||
case MODE_BINK1998_VALIDATE:
|
||||
return run.BINK1998Validate();
|
||||
|
||||
case MODE_BINK2002_VALIDATE:
|
||||
return run.BINK2002Validate();
|
||||
case MODE_BINK2002_VALIDATE:
|
||||
return run.BINK2002Validate();
|
||||
|
||||
case MODE_CONFIRMATION_ID:
|
||||
return run.ConfirmationID();
|
||||
case MODE_CONFIRMATION_ID:
|
||||
return run.ConfirmationID();
|
||||
|
||||
default:
|
||||
return 1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@
|
||||
#ifndef UMSKT_TYPEDEFS_H
|
||||
#define UMSKT_TYPEDEFS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdbool>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <cassert>
|
||||
@ -46,8 +46,8 @@
|
||||
#endif
|
||||
|
||||
// Type definitions
|
||||
typedef bool BOOL;
|
||||
typedef uint8_t BYTE;
|
||||
typedef bool BOOL;
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t WORD;
|
||||
typedef uint32_t DWORD;
|
||||
typedef uint64_t QWORD;
|
||||
@ -56,4 +56,4 @@ typedef uint64_t QWORD;
|
||||
typedef unsigned __int128 OWORD;
|
||||
#endif
|
||||
|
||||
#endif //UMSKT_TYPEDEFS_H
|
||||
#endif // UMSKT_TYPEDEFS_H
|
||||
|
@ -21,23 +21,23 @@
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include <windows.h>
|
||||
|
||||
BOOLEAN WINAPI DllMain( IN HINSTANCE hDllHandle,
|
||||
IN DWORD nReason,
|
||||
IN LPVOID Reserved ) {
|
||||
BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle, IN DWORD nReason, IN LPVOID Reserved)
|
||||
{
|
||||
|
||||
BOOLEAN bSuccess = TRUE;
|
||||
// Perform global initialization.
|
||||
switch (nReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// For optimization.
|
||||
DisableThreadLibraryCalls(hDllHandle);
|
||||
break;
|
||||
switch (nReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// For optimization.
|
||||
DisableThreadLibraryCalls(hDllHandle);
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
|
@ -24,15 +24,15 @@
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by umskt.rc
|
||||
//
|
||||
#define IDI_ICON1 101
|
||||
#define IDI_ICON1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user