243 Commits

Author SHA1 Message Date
2bcc9d5178 Revert x2 2025-07-18 00:21:54 -05:00
af058711ec Revert because you just don't use macos icons for cli 2025-07-18 00:21:12 -05:00
793432f07b use --args 2025-07-18 00:18:24 -05:00
8cb00c165d use open -a 2025-07-18 00:16:32 -05:00
070dbe46d0 oh yeah we're an app now x2 2025-07-18 00:12:42 -05:00
51248fb5cc oh yeah we're an app now 2025-07-18 00:11:19 -05:00
bda0ea93c8 macOS icon + diff placeholder 2025-07-18 00:09:53 -05:00
843b904639 placeholder icon change 2025-07-17 23:48:08 -05:00
f7427792e3 Add Wither's gists as references (#137)
* Add Wither's gists as references

* remove broken ones

---------

Co-authored-by: WitherOrNot <damemem@gmail.com>
2025-07-09 20:12:49 -05:00
c0aca723b8 Update windows-x86-x64.yml 2025-07-09 16:04:20 -05:00
8c98a3d173 Update windows-x86-x64.yml 2025-07-09 16:02:26 -05:00
a1845d9d6a Update windows-x86-x64.yml 2025-07-09 16:01:50 -05:00
817695d988 Update windows-x86-x64.yml 2025-07-09 15:57:08 -05:00
8dc6dfb97e Downgrade OpenSSL to 1.1.1 (#136)
* Update windows-x86-x64.yml

* Update windows-arm.yml

* Update windows-arm.yml

* Update windows-arm.yml

* Update windows-arm.yml

* Update windows-arm.yml
2025-07-09 15:43:33 -05:00
8d964c6fad Update README.md 2025-07-09 13:15:30 -05:00
e66f0cc724 Update README.md 2025-07-09 13:14:57 -05:00
ca7db29776 Update README.md 2025-07-09 13:12:44 -05:00
ed19cf2148 Update windows-arm.yml 2025-07-09 12:55:38 -05:00
4de84b6439 lower sdk target 2025-07-09 12:22:52 -05:00
827c26bc45 ARM32 support for Windows RT (#135) 2025-07-09 12:17:15 -05:00
a0e7a2561f move msys 2025-07-07 15:28:52 -05:00
8d92cc123d Update README.md 2025-07-07 14:37:44 -05:00
7af4a1fbcf Update README.md 2025-07-07 14:37:33 -05:00
2796923983 Update README.md 2025-07-07 14:36:04 -05:00
6fda0c9ab8 lets see 2025-07-07 14:18:57 -05:00
5e9ebe10cd i686 2025-07-07 14:07:37 -05:00
f216019046 what the fuck is this naming scheme 2025-07-07 13:57:44 -05:00
9663669c0c i486 2025-07-07 13:48:01 -05:00
af35f41c3f add the atomic lib (2) 2025-07-07 13:30:44 -05:00
0a4561b1cd add the atomic lib 2025-07-07 13:15:47 -05:00
fe8e7c72e0 no atomics 2025-07-07 13:00:58 -05:00
f630ed1e53 compatibility fixes 2025-07-07 12:53:00 -05:00
7c8a7dd54c Compile OpenSSL in-action (#134) 2025-07-07 11:27:04 -05:00
befe149285 let's actually check that 2025-07-06 16:31:21 -05:00
5eb3ed11f8 use CWSDSTUB to avoid needing CWSDPMI (#131) 2025-07-06 15:08:03 -05:00
f3be9fb950 Update dos-djgpp.yml 2025-07-04 09:35:48 -05:00
761ba76081 Update linux.yml 2025-07-04 09:35:34 -05:00
c072d096f3 Update windows.yml 2025-07-04 09:34:58 -05:00
1002e0a6d5 Windows on ARM support + icon fixes (#129)
* Support for Windows on ARM (uses MSVC, but it's Windows 11 exclusive anyway so `¯\_(ツ)_/¯`)
* Adds the icon back for x86/x64 TDM-GCC builds
* Makes Linux compilation on ARM much faster
* added tests to every workflow
2025-07-04 09:29:23 -05:00
6b85771db1 Static OpenSSL for macOS (#127) 2025-07-03 13:03:11 -05:00
8db1fe25d7 Make UMSKT (mostly) static on macOS (#126) 2025-07-03 12:11:00 -05:00
0db5d7f982 Universal binary compilation for macOS (#124) 2025-07-03 10:31:15 -05:00
25ed8d4f43 Merge pull request #120 from UMSKT/nodashes-cmd
Command line argument to remove dashes from product key
2025-06-18 21:50:16 -05:00
324688e9ef Update cli.cpp 2025-06-18 21:33:07 -05:00
6ae46d6aa2 duh 2025-06-18 21:24:37 -05:00
e07c080ee8 Update cli.h 2025-06-18 21:18:11 -05:00
ce9ff7e624 Revert "Update cli.h"
This reverts commit 714895c61b.
2025-06-18 21:17:08 -05:00
714895c61b Update cli.h 2025-06-18 21:13:50 -05:00
6ecf9c5309 Update cli.h 2025-06-18 21:09:15 -05:00
9f7d53dab3 Update cli.cpp 2025-06-18 21:08:02 -05:00
a66e579377 remove everything in a 2 mile radius 2025-06-10 23:43:31 -05:00
e30a4713b6 Update CMakeLists.txt 2025-06-10 23:34:14 -05:00
e9228045d3 Update dos-djgpp.yml 2025-06-10 22:38:03 -05:00
36de07ecdf Update dos-djgpp.yml 2025-06-10 22:33:18 -05:00
a28f4b5ca3 Update dos-djgpp.yml 2025-06-10 22:28:02 -05:00
a0cb9e9869 Update dos-djgpp.yml 2025-06-10 22:26:20 -05:00
6d30abba98 Update dos-djgpp.yml 2025-06-10 22:23:14 -05:00
8b6c3b252b Update dos-djgpp.yml 2025-06-10 22:20:39 -05:00
1fd7550f85 Merge pull request #119 from thepwrtank18/djgpp-rng
RNG bugfix for DOS (DJGPP)
2025-06-09 23:20:45 -05:00
1f85bf954e RNG bugfix for DOS (DJGPP) 2025-06-09 23:15:34 -05:00
74ff1ea08c https://www.youtube.com/watch?v=y3M3xpKV7wA
Replace MSVC with TDM-GCC
2025-06-07 21:11:48 -04:00
0a63055e91 32-bit 2025-06-05 01:05:45 -04:00
94da628e48 Update windows.yml 2025-06-05 01:00:39 -04:00
8e58232803 ops 2025-06-05 00:58:06 -04:00
78ec40f4e3 sdfjkwwhqd 2025-06-05 00:57:13 -04:00
9d36fb2f66 this is stupid 2025-06-05 00:41:27 -04:00
2166ee6e2f PICK ONE ARE YOU WINDOWS OR UNIX 2025-06-05 00:14:58 -04:00
e85add2a54 5 HOURS DEBUGGING THIS CRAP 2025-06-05 00:10:01 -04:00
f459316865 Satya Nadella this is your fault 2025-06-04 23:59:59 -04:00
60a9b0ea70 i'm going to kms
https://learn.microsoft.com/en-us/windows-server/get-started/kms-client-activation-key
2025-06-04 23:49:36 -04:00
0ebce49cf0 final theory 2025-06-04 23:34:50 -04:00
caa37365d4 theory of everything 3 2025-06-04 23:32:32 -04:00
8fe0fc06b2 theory of everything 2 2025-06-04 23:24:02 -04:00
fc4b83d1e8 theory of everything 2025-06-04 23:13:06 -04:00
aa331ad6e4 broken glass theory 2025-06-04 23:03:30 -04:00
9b06fcf162 ice soup theory 2025-06-04 22:52:06 -04:00
a4d810b030 tree method 2025-06-04 22:43:58 -04:00
c209070a66 progress 2025-06-04 20:24:27 -04:00
9c01c93e77 ctrl shift l moment 2025-06-04 20:09:07 -04:00
b41b596e54 ??? 2025-06-04 20:04:51 -04:00
8723928e48 Update windows.yml 2025-06-04 19:59:50 -04:00
8b603c96f1 Update windows.yml 2025-06-04 19:51:59 -04:00
403bcb9dd5 initial TDM-GCC switchover 2025-06-04 19:43:22 -04:00
8368b6a6c7 Merge pull request #116 from UMSKT/disable-freebsd
Disable automatic FreeBSD GH action
2025-04-13 21:14:58 -04:00
2415d1374f Disable FreeBSD GH action 2025-04-13 19:52:53 -04:00
d1024950da Fix GH actions 2025-04-13 19:09:02 -04:00
1ca5114b21 Update dos-djgpp.yml 2025-04-13 17:50:24 -04:00
da10583fdf Update freebsd.yml 2025-04-13 17:50:14 -04:00
034c00a5b8 Update linux.yml 2025-04-13 17:50:02 -04:00
cd050c65d6 Update macos.yml 2025-04-13 17:49:44 -04:00
02434e935d Update windows.yml 2025-04-13 17:49:00 -04:00
09f1300afc Update windows.yml 2025-04-13 17:47:43 -04:00
a3de0e845f Update keys.json 2025-04-13 17:42:09 -04:00
6287b4c773 Bink Data Update (#113)
* Update keys.json

Added BINK ID10

* Update keys.json

added/updated some missing BINKID data
BINKID 0x0B
BINKID 0x42
BINKID 0x43
BINKID 0x44
BINKID 0x45
2025-03-12 10:35:47 -07:00
a5ce3abe13 the end of updating openssl manually 2024-07-25 23:47:07 -05:00
27344f6d4b begone strikethrough 2024-07-25 23:32:38 -05:00
01b216dbc4 let it end 2024-06-22 00:01:28 -05:00
Neo
c29db1d30a Update keys.json 2024-04-15 08:02:38 -07:00
1c1e26012f add "2007 Microsoft Office system" bink (#91) 2024-04-15 07:38:26 -07:00
75f22215b1 Merge pull request #92 from thepwrtank18/version-check-bypass
Override version check for confirmation ID's
2024-04-13 16:02:18 -04:00
be99f6b8e9 Update cli.cpp 2024-04-13 19:12:57 +00:00
e830f97e7e Update cli.cpp 2024-04-13 19:01:34 +00:00
0251546d0d Update libumskt.cpp 2024-04-13 18:59:34 +00:00
a12afcd601 Update confid.h 2024-04-13 18:46:31 +00:00
c7a555abe4 Update cli.cpp 2024-04-13 18:44:41 +00:00
74ff4bf144 Update cli.h 2024-04-13 18:43:59 +00:00
2b408913c4 Update cli.cpp 2024-04-13 18:43:50 +00:00
c965b88113 Update confid.cpp 2024-04-13 18:43:32 +00:00
2bc3503fd8 Update cli.h 2024-04-13 18:40:03 +00:00
3fbd1cffea Update cli.cpp 2024-04-13 18:39:58 +00:00
4bf3800281 Comment out ERR_UNKNOWN_VERSION checks
Temporary fix for Office 2007 not generating confid's.
2024-04-13 18:00:07 +00:00
8ec60bf396 Update windows.yml 2024-04-13 14:45:46 +00:00
5fbbd5e6eb changing the openssl links every update isn't sustainable 2024-04-13 14:34:13 +00:00
d378c6499e Update README.md 2024-01-05 06:52:47 -05:00
3ea8731271 Merge pull request #80 from Neilpang/patch-1
Upgrade to freebsd-vm@v1
2023-12-19 17:03:52 +00:00
018f9f533c add trigger for pull_request 2023-12-17 20:38:37 +01:00
f1f1e0e6ea Upgrade to freebsd-vm@v1
The v0 is not working.
2023-12-17 20:26:24 +01:00
c4b63c15b2 Update keys.json (#79)
Added BINK ID10
2023-12-15 13:32:09 -08:00
1548e14169 Update OpenSSL to 3.1.4
Please see GIF attached for what we'll eventually do to OpenSSL.
2023-12-14 00:24:33 +00:00
72d48dd38b Merge pull request #74 from whatdoineed2do/build-static-normal-fixes
cleanup CMakeLists.txt
2023-09-30 17:51:45 -04:00
00d4906b28 djgpp: drop forced shared 2023-09-29 22:43:52 +01:00
88f60630c1 gh: window - upgrade from 404'd 3.1.2 resource to openssl 3.1.3 2023-09-29 22:16:33 +01:00
2ac6920e2c cleanup CMakeLists.txt to build normal with statically linked internal lib without need for full static linkage 2023-09-29 22:16:33 +01:00
8f843ad4c3 Merge pull request #72 from whatdoineed2do/usage-validation-memleaks
Usage validation and memleaks fixes
2023-09-27 04:42:08 -04:00
2753bf2a40 Update README.md 2023-09-26 23:05:22 -04:00
d17ada2e64 Merge pull request #73 from techguy16/master
Add Discord Invite
2023-09-26 14:28:13 -04:00
6685b38aac Update README.md 2023-09-27 07:26:10 +13:00
884d8c9703 Update README.md 2023-09-27 07:24:56 +13:00
5ba2dbddd4 EC/BN memleak 2023-09-25 12:13:53 +01:00
bf40bb6402 CLI moved to stack object 2023-09-25 12:13:43 +01:00
12a041c380 BN_free() memleaks 2023-09-25 12:04:52 +01:00
ecd9cd8dd2 office 2k7 enterprise must be given inst id 2023-09-25 11:26:28 +01:00
6989ae6c94 ensure arg for -p 2023-09-25 11:21:42 +01:00
ac510f8253 Update README.md 2023-09-17 19:05:16 -04:00
72c42f66c9 Merge pull request #70 from pottzman/master
Universal ConfirmationID
2023-09-07 13:34:10 -04:00
759c4009ef Merge pull request #16 from UMSKT/master
test merge
2023-09-07 19:21:48 +10:00
78c358c933 Merge pull request #15 from pottzman/ConfirmationID
Universal ConfirmationID
2023-09-07 19:17:53 +10:00
1d5e233c19 Update confid.cpp 2023-09-07 18:44:47 +10:00
6c06732331 Update confid.cpp 2023-09-07 18:05:58 +10:00
f347231362 Update confid.cpp 2023-09-07 17:29:07 +10:00
a7e97e45ee Update confid.cpp 2023-09-07 17:16:00 +10:00
bf57c32eae Merge pull request #12 from pottzman/ConfirmationID
Universal ConfirmationID
2023-09-06 23:16:38 +10:00
25db955b61 Update confid.cpp 2023-09-06 22:56:28 +10:00
1aeceb28f1 Update confid.cpp 2023-09-06 21:56:53 +10:00
b451a04f3c Update confid.cpp 2023-09-06 21:32:12 +10:00
3e5e03df4d Update confid.cpp 2023-09-06 20:54:34 +10:00
e3bdc93249 Update confid.cpp 2023-09-06 20:49:09 +10:00
36b2eb3e7d Update confid.cpp 2023-09-06 20:46:36 +10:00
49fefca596 Fix DOS compilation (Attempt 2) 2023-09-02 13:44:35 -04:00
178c9e0689 Fix DOS compilation (Attempt 1) 2023-09-02 13:43:03 -04:00
214d2d38a5 Merge pull request #68 from UMSKT/newline-fix 2023-09-02 13:16:56 -04:00
3ae078e3c5 update arg from nonewline to nonewlines 2023-09-02 11:53:09 -04:00
12e511b3a5 Update cli.cpp 2023-09-02 11:39:22 -04:00
21bac3b66c Update cli.cpp 2023-09-02 11:37:41 -04:00
09842ace12 Update cli.h 2023-09-02 11:37:38 -04:00
0d016b8872 Update cli.cpp 2023-09-02 11:31:25 -04:00
b1743f4bff fix name for FreeBSD 2023-09-02 11:17:52 -04:00
cc765edb4f Merge pull request #61 from UMSKT/workflow-update 2023-09-02 11:11:47 -04:00
4d1b5d6681 Update README.md 2023-09-02 11:11:16 -04:00
f59d77bdd1 Merge branch 'master' into workflow-update 2023-09-02 10:43:12 -04:00
71cbd19017 Add universal Confirmation ID 2023-09-02 10:42:26 -04:00
974f400cfc Revert "TEMP -- use -v" 2023-09-02 09:56:36 -04:00
a2d521c230 Update CMakeLists.txt 2023-09-02 09:55:20 -04:00
d53409f5bd TEMP -- use -v 2023-09-02 09:51:35 -04:00
2703e17f69 Update cli.cpp 2023-09-02 23:51:08 +10:00
680239bdb7 Merge branch 'cmake-fix' into master 2023-09-02 09:44:57 -04:00
104bdb19e3 Update confid.cpp 2023-09-02 23:33:47 +10:00
f2f859faeb Update confid.h 2023-09-02 23:27:02 +10:00
a2d9c46a4b Update libumskt.cpp 2023-09-02 23:25:14 +10:00
f65533bbb3 macOS build is not static 2023-09-02 09:24:04 -04:00
90e31b667a Update cli.h 2023-09-02 23:23:59 +10:00
492d245f86 Update cli.cpp
added CLI options for confirmation ID generation
2023-09-02 23:22:53 +10:00
361a39e204 Fix macOS compilation (Attempt 1) 2023-09-02 09:20:54 -04:00
31993afb62 Merge pull request #3 from UMSKT/master
FE and FF BINK exclusions
2023-09-02 23:03:17 +10:00
b3f64e6330 fix typo 2023-09-02 00:59:34 -04:00
ccf93a0089 Merge pull request #51 from UMSKT/fe-ff-fix
Add exclusions for FE and FF BINKs
2023-09-01 23:17:58 -04:00
ae391a5e50 Update cli.cpp 2023-09-01 22:43:32 -04:00
3620cf5af6 Update README.md 2023-09-01 19:54:08 -04:00
33774f7ad2 put all the stuff into cmake-fix 2023-09-01 19:12:57 -04:00
06ed5ef240 Update windows.yml 2023-09-01 18:50:59 -04:00
161aa2de4c put the working dir in the right place 2023-09-01 18:37:12 -04:00
a50688657d Fix v141_xp compilation 2023-09-01 18:20:02 -04:00
1679583e64 Update README.md 2023-09-01 18:19:35 -04:00
02c85b50b1 Change build config to v141_xp 2023-09-01 18:08:53 -04:00
93732e152b Add XP support for x64 2023-09-01 18:07:02 -04:00
95803054ba Tidy up Readme
- Order Operating Systems
- Add separators
- Fix build instructions (git clone doesn't just get the code, you need the url)
2023-09-02 09:46:19 +12:00
8619fccb11 Update freebsd.yml 2023-09-02 09:12:52 +12:00
06b9d937b1 Update freebsd.yml 2023-09-01 20:14:46 +12:00
453151f20f Add Tests for FreeBSD 2023-09-01 12:47:39 +12:00
1bb00cf53d Remove unnecessary zipping. 2023-09-01 11:56:37 +12:00
a787fc8e85 Fix Windows Build 2023-09-01 11:55:22 +12:00
582ddf1bb8 Merge pull request #63 from techguy16/master
Add Office 2k3 and Works Suite 2003/2004
2023-08-27 15:54:03 -04:00
13bf69c7e1 Add Office 2k3 and Works Suite 2003/2004 2023-08-28 07:20:10 +12:00
b7965f19e8 Delete test.md 2023-08-14 22:20:59 -04:00
52c9a57ea2 Create test.md 2023-08-14 22:16:07 -04:00
283df1c1fe Update linux.yml 2023-08-14 22:01:07 -04:00
c1eb81490b Update freebsd.yml 2023-08-14 22:01:01 -04:00
2ee6a99acd Update macos.yml 2023-08-14 22:00:58 -04:00
1370a6ecff Update windows.yml 2023-08-14 22:00:56 -04:00
e3a6b78407 Update dos-djgpp.yml 2023-08-14 21:59:25 -04:00
9fec269ad0 Only show successful runs on links 2023-08-14 21:35:42 -04:00
6ae5c9e435 Update windows.yml 2023-08-14 15:12:24 -04:00
a6bfaed6e8 Update macos.yml 2023-08-14 15:12:13 -04:00
f7b41a9810 Update linux.yml 2023-08-14 15:11:53 -04:00
e76eb7ac33 Update freebsd.yml 2023-08-14 15:11:35 -04:00
c91bbad69a Update dos-djgpp.yml 2023-08-14 15:11:17 -04:00
75e81e7049 Update dos-djgpp.yml 2023-08-14 15:09:41 -04:00
e9131e45c8 Update freebsd.yml 2023-08-14 15:09:16 -04:00
c664ea7f9c Update linux.yml 2023-08-14 15:08:52 -04:00
f95501b789 Update macos.yml 2023-08-14 15:08:24 -04:00
444f8c45c7 Allow manual workflows and auto workflows on all branches
This lets workflows work on all branches without changing anything, and allows workflows to be activated manually.
2023-08-14 15:07:24 -04:00
de09feb18f Update dos-djgpp.yml 2023-08-10 17:00:49 -04:00
bde4371cbe Update dos-djgpp.yml 2023-08-10 16:59:23 -04:00
f43a2d5c37 Update CMakeLists.txt 2023-08-10 16:54:33 -04:00
46c39df15d Update CMakeLists.txt 2023-08-10 16:23:01 -04:00
c078247bea Delete _dummy.txt 2023-08-10 14:46:11 -05:00
232be6aba2 trigger GitHub Actions 2023-08-10 14:45:04 -05:00
c0c3149be7 Update OpenSSL to 3.1.2 (to cmake-fix) 2023-08-10 14:42:44 -05:00
8e15a4f5b8 Update OpenSSL to 3.1.2 2023-08-10 12:07:39 -05:00
d411d56d81 Update dos-djgpp.yml 2023-08-10 10:18:55 -04:00
11253c5e2c Revert to old CMakeLists for now 2023-08-10 09:59:20 -04:00
9f7920ca2d Update CMakeLists.txt 2023-08-10 09:51:10 -04:00
9063e32a89 Update CMakeLists.txt 2023-08-10 09:49:04 -04:00
958169ccb5 Merge pull request #55 from pottzman/pottzman-upgrade-flag
Pottzman upgrade flag
2023-08-10 04:43:42 -03:00
63fbbd83ef Update cli.cpp 2023-08-10 17:27:03 +10:00
de659846d4 Update cli.cpp 2023-08-10 17:16:24 +10:00
7c4bcdc847 Update cli.cpp 2023-08-10 16:56:58 +10:00
859a21656c Update cli.cpp 2023-08-10 16:56:05 +10:00
4b2ef7ac72 Update cli.cpp 2023-08-10 16:52:19 +10:00
216c9cdf9d Update cli.cpp 2023-08-10 16:51:53 +10:00
8f685a022c Update cli.cpp 2023-08-10 16:49:57 +10:00
e4058ddf19 Update cli.h 2023-08-10 16:45:50 +10:00
Neo
45004623be Why does the Github web editor commit tabs??? 2023-07-28 16:17:57 -07:00
Neo
a4cb524fed re-add removed comment 2023-07-28 16:16:31 -07:00
Neo
03ae90163a cleaner cli.cpp fix 2023-07-28 16:15:37 -07:00
c1e9a0f021 add exclusions for FE and FF 2023-07-28 18:10:25 -05:00
152c03456c Merge pull request #50 from UMSKT/readme-fix 2023-07-28 17:49:23 -05:00
ea51438766 Update README.md 2023-07-28 17:32:15 -05:00
8ee1acc2be Fix multiple key issue 2023-07-28 16:50:40 -05:00
3134a6f7a3 Update cli.cpp
Attempt to fix "duplicate keys" issue
2023-07-28 16:31:54 -05:00
b75d08b3be Update README.md 2023-07-27 19:01:50 -05:00
20c84661b2 Add macOS and FreeBSD support and fix DJGPP build (#48) 2023-07-24 23:53:42 -07:00
Neo
fefc8552b6 Update README.md (#45)
Closes #44
2023-07-16 05:51:46 -07:00
36 changed files with 4225 additions and 290 deletions

View File

@ -21,7 +21,10 @@
name: C/C++ CI (DOS DJGPP)
on:
workflow_call:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
env:
CC: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc
@ -34,12 +37,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup build environment
run: |
sudo apt -y update
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib dosbox tree
- name: Download and Setup DJGPP Toolchain
run: |
@ -47,6 +50,7 @@ jobs:
wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2
tar xjf djgpp-linux64-gcc1220.tar.bz2
cd ${{ github.workspace }}/djgpp
tree . -S
git clone https://github.com/UMSKT/Watt-32.git watt32
cd watt32/util
make clean && make linux
@ -56,29 +60,131 @@ jobs:
make -f djgpp.mak
ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
- name: Cache OpenSSL 3.1.2
uses: actions/cache/restore@v4
id: cache-openssl
with:
path: |
${{ github.workspace }}/djgpp
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
- name: Checkout and Cross Compile OpenSSL 3.1.2
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: |
git clone https://github.com/UMSKT/openssl.git openssl
pushd openssl
source ${{ github.workspace }}/djgpp/setenv
./Configure no-threads -DOPENSSL_DEV_NO_ATOMICS --prefix=${{ github.workspace }}/djgpp DJGPP
make && make install
./Configure 386 no-threads no-tests no-sse2 no-asm -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -mno-sse -mno-sse2 -march=i386 --prefix=${{ github.workspace }}/djgpp DJGPP
make && make install_sw
popd
- name: Save OpenSSL 3.1.2
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/djgpp
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
- name: Download stub
run: |
wget https://web.archive.org/web/20250308092209/https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/util/system/cwsdpmi/csdpmi7b.zip -O CSDPMI7B.ZIP
mkdir /home/runner/dpmibin
7z e CSDPMI7B.ZIP bin/CWSDSTUB.EXE -o/home/runner/dpmibin
- name: Build
run: |
source ${{ github.workspace }}/djgpp/setenv
pushd build
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
make
- name: Setup DOSBox test environment
run: |
mkdir -p dosbox_test
cp build/umskt.exe dosbox_test/
# Download DPMI server directly
# wget https://github.com/UMSKT/winactiontest/raw/refs/heads/main/CWSDPMI.EXE -O dosbox_test/CWSDPMI.EXE
# Create test batch file
cat > dosbox_test/test.bat << EOL
@echo off
echo Running test 1...
umskt.exe -b 2C -c 365 -s 069420 > TEST1.TXT
if errorlevel 1 goto error
echo Running test 2...
umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST2.TXT
if errorlevel 1 goto error
echo Tests completed > DONE.TXT
goto end
:error
echo Test failed > ERROR.TXT
:end
exit
EOL
# Create DOSBox configuration
cat > dosbox_test/dosbox.conf << EOL
[sdl]
nosound=true
[cpu]
cputype=386
core=dynamic
cycles=max
[autoexec]
mount c .
c:
test.bat
exit
EOL
- name: Run tests in DOSBox
run: |
cd dosbox_test
timeout 30s dosbox -conf dosbox.conf -nogui -exit
# Check if the test completed successfully
if [ ! -f DONE.TXT ]; then
echo "Tests did not complete successfully"
if [ -f ERROR.TXT ]; then
echo "Test execution failed"
fi
if [ -f TEST1.TXT ]; then
echo "Test 1 output:"
cat TEST1.TXT
fi
if [ -f TEST2.TXT ]; then
echo "Test 2 output:"
cat TEST2.TXT
fi
exit 1
fi
# Verify test outputs
if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ]; then
echo "Test output files missing"
exit 1
fi
# Check test results - looking for key format patterns
if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \
! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST2.TXT; then
echo "Tests failed - unexpected output format"
echo "Test 1 output:"
cat TEST1.TXT
echo "Test 2 output:"
cat TEST2.TXT
exit 1
else
echo "All tests passed successfully"
echo "Test 1 output:"
cat TEST1.TXT
echo "Test 2 output:"
cat TEST2.TXT
fi
- name: Move executable to upload directory
run: |
mkdir build/actions_upload
mv build/umskt.exe build/actions_upload/
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-DOS
name: UMSKT-DOS-x86
path: build/actions_upload

68
.github/workflows/freebsd.yml vendored Normal file
View File

@ -0,0 +1,68 @@
# This file is a part of the UMSKT Project
#
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @FileCreated by techguy16 on 07/23/2023
# @Maintainer techguy16
name: C/C++ CI (FreeBSD)
on:
#push:
# branches: [ "*" ]
# paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
#pull_request:
# branches: [ "*" ]
# paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
name: build-x86_64
steps:
- uses: actions/checkout@v4
- name: Build & Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
envs: 'MYTOKEN MYTOKEN2'
usesh: true
prepare: |
pkg install -y cmake openssl git bash
run: |
mkdir build
cd build
cmake ..
make
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
- name: Move files to correct directory
run: |
mkdir -p build/actions_upload
mv build/umskt build/actions_upload/umskt
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-FreeBSD
path: build/actions_upload

View File

@ -22,24 +22,31 @@ name: C/C++ CI (Linux)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- arch: x86
runner: ubuntu-latest
use_alpine: true
- arch: x86_64
runner: ubuntu-latest
use_alpine: true
- arch: aarch64
runner: ubuntu-24.04-arm
use_alpine: false
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup latest Alpine Linux for ${{ matrix.arch }}
- name: Setup latest Alpine Linux
if: ${{ matrix.use_alpine }}
uses: jirutka/setup-alpine@v1
with:
packages: >
@ -50,23 +57,125 @@ jobs:
musl-dev
openssl-dev
openssl-libs-static
zlib-dev
arch: ${{ matrix.arch }}
shell-name: alpine-target.sh
- name: Configure and build UMSKT
- name: Install Dependencies (Ubuntu ARM64)
if: ${{ !matrix.use_alpine }}
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake git libssl-dev zlib1g-dev
- name: Configure and build UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=ON
run-build: true
shell: alpine-target.sh {0}
- name: Move executable to upload directory
- name: Configure and build UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=ON
run-build: true
- name: Test UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
shell: alpine-target.sh {0}
- name: Test UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
- name: Move files to correct directory
run: |
mkdir -p build/actions_upload
mv build/umskt build/actions_upload/umskt
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-linux-${{ matrix.arch }}-static
name: UMSKT-Linux-${{ matrix.arch }}-static
path: build/actions_upload
- name: Configure and build static internal deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF
run-build: true
shell: alpine-target.sh {0}
- name: Configure and build static internal deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF
run-build: true
- name: Test static internal deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
shell: alpine-target.sh {0}
- name: Test static internal deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
- name: Configure and build shared deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
run-build: true
shell: alpine-target.sh {0}
- name: Configure and build shared deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
with:
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
run-build: true
- name: Test shared deps UMSKT (Alpine)
if: ${{ matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
shell: alpine-target.sh {0}
- name: Test shared deps UMSKT (Ubuntu)
if: ${{ !matrix.use_alpine }}
run: |
cd build
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574

123
.github/workflows/macos.yml vendored Normal file
View File

@ -0,0 +1,123 @@
# This file is a part of the UMSKT Project
#
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @FileCreated by techguy16 on 07/23/2023
# @Maintainer techguy16
name: C/C++ CI (macOS)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
include:
- arch: x86_64
- arch: arm64
steps:
- name: Checkout Source Tree
uses: actions/checkout@v4
- name: Install Rosetta
if: matrix.arch == 'x86_64'
run: |
sudo softwareupdate --install-rosetta --agree-to-license || true
- name: Install Homebrew for x86_64
if: matrix.arch == 'x86_64'
env: { NONINTERACTIVE: 1 }
run: |
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- name: Install x86_64 OpenSSL
if: matrix.arch == 'x86_64'
run: |
arch -x86_64 /usr/local/bin/brew install openssl@3
echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3" >> $GITHUB_ENV
echo "OPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@3/include" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/usr/local/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
- name: Install arm64 OpenSSL
if: matrix.arch == 'arm64'
run: |
brew install openssl@3
echo "OPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@3" >> $GITHUB_ENV
echo "OPENSSL_INCLUDE_DIR=/opt/homebrew/opt/openssl@3/include" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=/opt/homebrew/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
- name: Configure and build UMSKT
run: |
cd build
cmake -DCMAKE_BUILD_TYPE=Release .. \
-DCMAKE_OSX_ARCHITECTURES=${{matrix.arch}} \
-DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR \
-DOPENSSL_INCLUDE_DIR=$OPENSSL_INCLUDE_DIR \
-DOPENSSL_USE_STATIC_LIBS=TRUE \
-DBUILD_SHARED_LIBS=OFF
make
- name: Move files to correct directory
run: |
ls -a build
mkdir -p build/actions_upload
mv build/umskt build/actions_upload/umskt
- name: Run tests
run: |
cd build/actions_upload
echo Test 1 - generating key
./umskt -b 2C -c 365 -s 069420 -v
echo Test 2 - generating confid
./umskt -i 253286028742154311079061239762245184619981623171292574
- name: Upload platform-specific build
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-macOS-${{ matrix.arch }}
path: build/actions_upload
universal:
needs: build
runs-on: macos-latest
steps:
- name: Download x86_64 slice
uses: actions/download-artifact@v4
with:
name: UMSKT-macOS-x86_64
path: x86
- name: Download arm64 slice
uses: actions/download-artifact@v4
with:
name: UMSKT-macOS-arm64
path: arm
- name: Create universal binary
shell: bash
run: |
mkdir fat
lipo -create x86/umskt arm/umskt -output fat/umskt
lipo -info fat/umskt
- name: Upload universal build
uses: actions/upload-artifact@v4
with:
name: UMSKT-macOS-universal
path: fat

147
.github/workflows/windows-arm.yml vendored Normal file
View File

@ -0,0 +1,147 @@
# This file is a part of the UMSKT Project
#
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @FileCreated by TheTank20 on 07/08/2025
# @Maintainer Neo
name: C/C++ CI (Windows ARM)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**']
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- arch: arm32
arch_compilename: amd64_arm
vcpkg_arch: arm-windows-static
cmake_arch: ARM
sdk_version: '10.0.17763.0'
- arch: arm64
arch_compilename: amd64_arm64
vcpkg_arch: arm64-windows-static
cmake_arch: ARM64
sdk_version: '10.0.17763.0'
steps:
- name: Setup MSVC for ${{ matrix.arch }}
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch_compilename }}
sdk: ${{ matrix.sdk_version }}
- name: Checkout Source Tree
uses: actions/checkout@v4
- name: Cache OpenSSL Binaries
uses: actions/cache/restore@v4
with:
path: |
${{ github.workspace }}-OpenSSL-MSVC-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Checkout and Compile OpenSSL v1.1.1
shell: pwsh
run: |
git clone https://github.com/UMSKT/openssl --branch OpenSSL_1_1_1-stable --depth 1 openssl-src
cd openssl-src
# Install Perl if needed
choco install strawberryperl -y
# Configure and build OpenSSL for ARM32
$env:PATH = "C:\Strawberry\perl\bin;$env:PATH"
# First set up Visual Studio environment
$vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
$vcvarsall = Join-Path $vsPath "VC\Auxiliary\Build\vcvarsall.bat"
$vcTarget = ""
if ("${{ matrix.arch}}" -eq "arm32") {
$vcTarget = "VC-WIN32-ARM"
} else {
$vcTarget = "VC-WIN64-ARM"
}
# Configure OpenSSL
perl Configure $vcTarget no-shared no-asm no-engine --prefix="$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}"
# Build using MSVC ARM32 tools
cmd /c "call `"$vcvarsall`" ${{matrix.arch_compilename}} && nmake && nmake install_sw"
cd ..
- name: Save OpenSSL Binaries
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/OpenSSL-MSVC-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Set OpenSSL Environment
shell: pwsh
run: |
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Configure UMSKT
shell: pwsh
run: |
cmake -G "Visual Studio 17 2022" `
-A ${{ matrix.cmake_arch }} `
-DWINDOWS_ARM=ON `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }} `
.
- name: Build UMSKT
shell: pwsh
run: |
cmake --build . --config Release
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: Release/umskt.exe
test-arm64:
needs: build
if: success()
runs-on: windows-11-arm
strategy:
matrix:
arch: [arm64]
steps:
- name: Download ARM64 artifact
uses: actions/download-artifact@v4
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: .
- name: Run tests
shell: pwsh
run: |
Write-Host Test 1 - generating key
.\umskt.exe -b 2C -c 365 -s 069420 -v
Write-Host Test 2 - generatng confid
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574

160
.github/workflows/windows-x86-x64.yml vendored Normal file
View File

@ -0,0 +1,160 @@
# This file is a part of the UMSKT Project
#
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @FileCreated by TheTank20 on 07/08/2025
# @Maintainer Neo
name: C/C++ CI (Windows x86+64)
on:
push:
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**']
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- arch: x86
msystem: MINGW
cmake_flag: -m32
- arch: x64
msystem: MINGW64
cmake_flag: -m64
steps:
- name: Setup TDM-GCC
run: |
Write-Host Downloading TDM-GCC v10.3.0...
Invoke-WebRequest -Uri 'https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe' -OutFile 'C:\Windows\temp\TDM-GCC-64.exe'
Write-Host Creating directory...
New-Item -ItemType Directory -Path 'C:\TDM-GCC-64'
Write-Host Copying files [Set 1/3]...
Start-Process '7z' -ArgumentList 'e C:\Windows\temp\TDM-GCC-64.exe -oC:\TDM-GCC-64 -y' -Wait
Write-Host Copying files [Set 2/3]...
Start-Process '7z' -ArgumentList 'e C:\TDM-GCC-64\*.tar.xz -oC:\TDM-GCC-64 -y' -Wait
Write-Host Copying files [Set 3/3]...
Start-Process '7z' -ArgumentList 'x C:\TDM-GCC-64\*.tar -oC:\TDM-GCC-64 -y' -Wait
Write-Host Adding environment variables...
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
- name: Checkout Source Tree
uses: actions/checkout@v4
- name: Cache OpenSSL 1.1.1
uses: actions/cache/restore@v4
id: cache-openssl
with:
path: |
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Setup MSYS2
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.arch == 'x86' && 'MINGW32' || 'MINGW64' }}
update: true
install: >-
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-gcc
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-make
mingw-w64-x86_64-perl
perl
git
- name: Checkout and Compile OpenSSL 1.1.1
if: steps.cache-openssl.outputs.cache-hit != 'true'
shell: msys2 {0}
run: |
# Clone UMSKT's OpenSSL fork
echo "Cloning UMSKT OpenSSL fork..."
git clone https://github.com/UMSKT/openssl.git --branch OpenSSL_1_1_1-stable --depth 1 openssl-1.1.1
# Set up proper MSYS2 environment
export MSYS=winsymlinks:nativestrict
export MSYS2_PATH_TYPE=strict
export LANG=en_US.UTF-8
export PATH="/usr/bin:/mingw64/bin:$PATH"
export PATH="/c/TDM-GCC-64/bin:$PATH"
export MSYSTEM=${{ matrix.msystem }}
cd openssl-1.1.1
if [[ ${{ matrix.arch }} == "x86" ]]; then
/usr/bin/perl Configure mingw --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-32 no-tests no-sse2 no-asm no-threads -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -mno-sse -mno-sse2 -march=i686 -mtune=generic
else
/usr/bin/perl Configure mingw64 --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-64 no-tests no-asm -DOPENSSL_DEV_NO_ATOMICS -mno-mmx
fi
mingw32-make -j
mingw32-make install_sw
cd ..
- name: Save OpenSSL 1.1.1
if: steps.cache-openssl.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
- name: Set OpenSSL Environment
shell: pwsh
run: |
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-TDM-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CMAKE_FLAGS=${{ matrix.cmake_flag }}" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: Configure UMSKT
shell: pwsh
run: |
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
$OPENSSL_ROOT = "$env:OPENSSL_ROOT"
$OPENSSL_LIB = "$OPENSSL_ROOT/$env:OPENSSL_LIBDIR"
$OPENSSL_INC = "$OPENSSL_ROOT/include"
cmake -G "MinGW Makefiles" `
-DCMAKE_C_COMPILER="gcc" `
-DCMAKE_CXX_COMPILER="g++" `
-DOPENSSL_ROOT_DIR="$OPENSSL_ROOT" `
-DOPENSSL_INCLUDE_DIR="$OPENSSL_INC" `
-DOPENSSL_CRYPTO_LIBRARY="$OPENSSL_LIB/libcrypto.a" `
-DOPENSSL_SSL_LIBRARY="$OPENSSL_LIB/libssl.a" `
-DCMAKE_C_FLAGS="$env:CMAKE_FLAGS" `
-DCMAKE_CXX_FLAGS="$env:CMAKE_FLAGS" `
.
- name: Build UMSKT
shell: pwsh
run: |
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
mingw32-make
- name: Run tests
shell: pwsh
run: |
Write-Host Test 1 - generating key
.\umskt.exe -b 2C -c 365 -s 069420 -v
Write-Host Test 2 - generatng confid
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574
- name: Upload build artifact
uses: actions/upload-artifact@v4.6.2
with:
name: UMSKT-WinNT-${{ matrix.arch }}
path: umskt.exe

View File

@ -1,117 +0,0 @@
# This file is a part of the UMSKT Project
#
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# @FileCreated by TheTank20 on 06/13/2023
# @Maintainer Neo
name: C/C++ CI (Windows)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build-djgpp:
uses: ./.github/workflows/dos-djgpp.yml
build:
runs-on: windows-latest
needs: build-djgpp
strategy:
matrix:
include:
- arch: Win32
OpenSSL-File: Win32OpenSSL-3_1_1.exe
msbuild-arch: Win32
cmake-args: -D MSVC_MSDOS_STUB=..\umskt.exe
- arch: Win64
OpenSSL-File: Win64OpenSSL-3_1_1.exe
msbuild-arch: x64
cmake-args: ""
steps:
- name: Checkout Source Tree
uses: actions/checkout@v3
- name: Install Windows XP Support for Visual Studio
uses: thepwrtank18/install-vs-components@v1.0.0
with:
components: Microsoft.VisualStudio.Component.WinXP
- name: Download And Install ${{ matrix.OpenSSL-File }}
run: |
$installDir = "$Env:ProgramFiles\OpenSSL"
$installerURL = "https://slproweb.com/download/${{ matrix.OpenSSL-File }}"
$installerName = "${{ matrix.OpenSSL-File }}"
$installerPath = Join-Path -Path "${env:Temp}" -ChildPath "$installerName"
(New-Object System.Net.WebClient).DownloadFile($installerURL, $installerPath)
Remove-Item "$installDir" -Force -Recurse
$installerArgs = '/silent', '/sp-', '/suppressmsgboxes', "/DIR=`"$installDir`""
Start-Process -FilePath $installerPath -ArgumentList $installerArgs -Wait -PassThru
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Download UMSKT-DJGPP compiled artifact
if: matrix.arch == 'Win32'
uses: actions/download-artifact@v3
with:
name: UMSKT-DOS
- name: List build directory contents
if: matrix.arch == 'Win32'
run: |
Get-ChildItem
- name: Configure UMSKT
uses: threeal/cmake-action@v1.2.0
with:
generator: "Visual Studio 17 2022"
options: CMAKE_SYSTEM_VERSION="5.1.2600"
args: -A ${{ matrix.msbuild-arch }} -T v141_xp ${{ matrix.cmake-args }}
- name: Build UMSKT
working-directory: build
run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release /P:XPDeprecationWarning=false
- name: Move executable to upload directory
run: |
mkdir build/actions_upload
Move-Item build/Release/umskt.exe build/actions_upload
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
with:
name: UMSKT-${{ matrix.arch }}
path: build/actions_upload
- name: Move Win32+DOS executable to upload directory
if: matrix.arch == 'Win32'
run: |
Remove-Item "build/actions_upload" -Force -Recurse
mkdir build/actions_upload
Move-Item build/Release/umskt_win32_dos.exe build/actions_upload/umskt.exe
- name: Upload build artifact
if: matrix.arch == 'Win32'
uses: actions/upload-artifact@v3.1.2
with:
name: UMSKT-Win32+DOS
path: build/actions_upload

6
.gitignore vendored
View File

@ -253,3 +253,9 @@ CMakeSettings.json
# Visual Studio
.vs/
CPM_modules
CPM_*.cmake
cpm-package-lock.cmake
*.a
*_cmrc*

10
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,10 @@
# Stub so pre-commit can shut up until the refactor
repos:
- repo: local
hooks:
- id: no-op
name: Noop hook (always passes)
entry: "true" # `/usr/bin/true` returns 0 and does nothing
language: system
pass_filenames: false # dont bother passing any file paths

View File

@ -20,25 +20,84 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
PROJECT(UMSKT)
# Force TDM-GCC on Windows if not using MSVC
if (WIN32 AND NOT MSVC)
set(CMAKE_C_COMPILER "C:/TDM-GCC-64/bin/gcc.exe" CACHE FILEPATH "C Compiler" FORCE)
set(CMAKE_CXX_COMPILER "C:/TDM-GCC-64/bin/g++.exe" CACHE FILEPATH "C++ Compiler" FORCE)
message(STATUS "[UMSKT] Forcing use of TDM-GCC in C:/TDM-GCC-64")
# Configure windres for resource compilation
set(CMAKE_RC_COMPILER "C:/TDM-GCC-64/bin/windres.exe")
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
set(CMAKE_RC_FLAGS "--use-temp-file -c65001")
# Match resource architecture with target architecture
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-i386 --target=pe-i386")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
else()
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-x86-64 --target=pe-x86-64")
endif()
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff -I${CMAKE_CURRENT_SOURCE_DIR}/src/windows <DEFINES> -i <SOURCE> -o <OBJECT>")
# Set the Windows resource file for GCC builds
set(UMSKT_EXE_WINDOWS_EXTRA src/windows/umskt.rc)
endif()
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
SET(CMAKE_OSX_SYSROOT "macosx" CACHE PATH "macOS SDK path")
OPTION(BUILD_SHARED_LIBS "Build internal libraries as dynamic" OFF)
OPTION(UMSKT_USE_SHARED_OPENSSL "Force linking against the system-wide OpenSSL library" OFF)
OPTION(MUSL_STATIC "Enable fully static builds in a muslc environment (i.e. Alpine Linux)" OFF)
OPTION(DJGPP_WATT32 "Enable compilation and linking with DJGPP/WATT32/OpenSSL" OFF)
OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF)
OPTION(WINDOWS_ARM "Enable compilation for Windows on ARM (requires appropriate toolchain)" OFF)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
endif()
# neither does dos idk i'm trying random stuff
if (DJGPP_WATT32)
SET(UMSKT_USE_SHARED_OPENSSL ON)
endif()
IF(UMSKT_USE_SHARED_OPENSSL)
SET(OPENSSL_USE_STATIC_LIBS FALSE)
SET(OPENSSL_MSVC_STATIC_RT FALSE)
MESSAGE(WARNING "[UMSKT] Forcing shared OpenSSL runtime")
MESSAGE(STATUS "[UMSKT] Requesting dynamic version of OpenSSL")
ELSE()
SET(OPENSSL_USE_STATIC_LIBS TRUE)
SET(OPENSSL_MSVC_STATIC_RT TRUE)
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
ENDIF()
# Configure ARM-specific settings if enabled
if (WINDOWS_ARM)
if (MSVC)
# MSVC ARM64 settings
set(CMAKE_SYSTEM_PROCESSOR ARM64)
set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE ARM64)
else()
# MinGW/GCC ARM settings
set(CMAKE_SYSTEM_PROCESSOR arm)
if (CMAKE_CROSSCOMPILING)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a")
endif()
endif()
message(STATUS "[UMSKT] Configuring for Windows on ARM")
endif()
IF(DJGPP_WATT32)
SET(CMAKE_SYSTEM_NAME MSDOS)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
@ -47,25 +106,18 @@ IF(DJGPP_WATT32)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} ${DJGPP_WATT32})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS} ${WATT_ROOT}/lib)
# Maximum compatibility flags for DOS/NTVDM
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
MESSAGE(STATUS "[UMSKT] Using i386 target for DOS DGJPP with stub: ${CWSDSTUB_LOCATION}")
ENDIF()
# find the system installed OpenSSL development library
FIND_PACKAGE(OpenSSL REQUIRED)
IF(NOT OPENSSL_FOUND)
MESSAGE(SEND_ERROR "OpenSSL Development Libraries Not Found")
MESSAGE(SEND_ERROR "Please consult your package manager of choice to install the prerequisite")
MESSAGE(SEND_ERROR "The package name is commonly called libssl-dev or openssl-dev depending on distribution")
MESSAGE(FATAL_ERROR "Can not continue without OpenSSL")
ENDIF()
# if we found shared libraries - do the following:
STRING(REGEX MATCH "(\\.so|\\.dll|\\.dylib)$" OPENSSL_CRYPTO_SHARED "${OPENSSL_CRYPTO_LIBRARY}")
IF(OPENSSL_CRYPTO_SHARED)
MESSAGE(STATUS "[UMSKT] Detected Shared library version of OpenSSL")
SET(BUILD_SHARED_LIBS ON)
ELSE()
MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
ENDIF()
##if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
## SET(BUILD_SHARED_LIBS ON)
## MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
##endif()
# if we're compiling with MSVC, respect the DEBUG compile option
IF(MSVC)
@ -85,6 +137,9 @@ ENDIF()
IF(MUSL_STATIC)
MESSAGE(STATUS "[UMSKT] Performing a fully static build using muslc")
SET(BUILD_SHARED_LIBS OFF)
SET(OPENSSL_USE_STATIC_LIBS TRUE)
SET(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
SET(CMAKE_SHARED_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
@ -92,6 +147,46 @@ IF(MUSL_STATIC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
ENDIF()
# find the system installed OpenSSL development library
FIND_PACKAGE(OpenSSL REQUIRED)
IF(NOT OPENSSL_FOUND)
MESSAGE(SEND_ERROR "OpenSSL Development Libraries Not Found")
MESSAGE(SEND_ERROR "Please consult your package manager of choice to install the prerequisite")
MESSAGE(SEND_ERROR "The package name is commonly called libssl-dev or openssl-dev depending on distribution")
MESSAGE(FATAL_ERROR "Can not continue without OpenSSL")
ENDIF()
IF(NOT MUSL_STATIC)
# if we found shared libraries - do the following:
IF (OPENSSL_USE_STATIC_LIBS)
MESSAGE(STATUS "[UMSKT] requested static version of OpenSSL")
if (NOT UMSKT_USE_SHARED_OPENSSL)
MESSAGE(STATUS "[UMSKT] not asked for shared version of OpenSSL")
ENDIF()
IF(MSVC)
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "ws2_32.lib")
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} "crypt32.lib")
MESSAGE(STATUS "[UMSKT] msvc adding ws2_32.lib crypt32.lib")
ENDIF()
ENDIF()
STRING(REGEX MATCH "(\\.so|\\.dll|\\.dylib)$" OPENSSL_CRYPTO_SHARED "${OPENSSL_CRYPTO_LIBRARY}")
IF(OPENSSL_CRYPTO_SHARED)
MESSAGE(STATUS "[UMSKT] Detected Shared library version of OpenSSL")
ELSE()
MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
# static libcrypto on Fedora needs -lz at link time
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
FIND_PACKAGE(ZLIB REQUIRED)
IF (NOT ZLIB_FOUND)
MESSAGE(FATAL_ERROR "[UMSKT] linux static OpenSSL requires zlib")
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# initalize cpm.CMake
INCLUDE(cmake/CPM.cmake)
@ -109,6 +204,7 @@ CPMAddPackage(
GITHUB_REPOSITORY fmtlib/fmt
GIT_TAG 10.0.0
VERSION 10.0.0
#OPTIONS "FMT_INSTALL YES" "BUILD_SHARED_LIBS OFF"
)
# Include cmrc resource compiler
@ -145,38 +241,34 @@ SET(LIBUMSKT_SRC src/libumskt/libumskt.cpp src/libumskt/pidgen3/BINK1998.cpp src
IF (EMSCRIPTEN)
ADD_EXECUTABLE(umskt ${LIBUMSKT_SRC})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt -static OpenSSL::Crypto fmt)
TARGET_LINK_LIBRARIES(umskt -static OpenSSL::Crypto cryptopp::cryptopp fmt)
SET(CMAKE_EXECUTABLE_SUFFIX ".html")
SET_TARGET_PROPERTIES(umskt PROPERTIES COMPILE_FLAGS "-Os -sEXPORTED_RUNTIME_METHODS=ccall,cwrap")
SET_TARGET_PROPERTIES(umskt PROPERTIES LINK_FLAGS "-Os -sWASM=1 -sEXPORT_ALL=1 -sEXPORTED_RUNTIME_METHODS=ccall,cwrap --no-entry")
ELSE()
IF(NOT UMSKT_USE_SHARED_OPENSSL)
### Static library compilation
ADD_LIBRARY(_umskt STATIC ${LIBUMSKT_SRC})
ADD_LIBRARY(_umskt ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(_umskt -static OpenSSL::Crypto fmt ${UMSKT_LINK_LIBS})
ELSE()
### Shared library compilation
ADD_LIBRARY(_umskt SHARED ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(_umskt OpenSSL::Crypto fmt ${UMSKT_LINK_LIBS})
TARGET_LINK_DIRECTORIES(_umskt PUBLIC ${UMSKT_LINK_DIRS})
ENDIF()
TARGET_LINK_LIBRARIES(_umskt ${OPENSSL_CRYPTO_LIBRARIES} fmt ${UMSKT_LINK_LIBS})
### UMSKT executable compilation
ADD_EXECUTABLE(umskt src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_INCLUDE_DIRECTORIES(umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt _umskt OpenSSL::Crypto fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS})
TARGET_LINK_LIBRARIES(umskt _umskt ${OPENSSL_CRYPTO_LIBRARIES} ${ZLIB_LIBRARIES} fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS})
TARGET_LINK_DIRECTORIES(umskt PUBLIC ${UMSKT_LINK_DIRS})
### UMSKT with specified DOS Stub compilation
# Link required Windows system libraries for OpenSSL
if (WIN32)
target_link_libraries(umskt crypt32 ws2_32)
endif()
IF(MSVC AND MSVC_MSDOS_STUB)
ADD_EXECUTABLE(umskt_win32_dos src/main.cpp src/cli.cpp ${UMSKT_EXE_WINDOWS_EXTRA})
TARGET_INCLUDE_DIRECTORIES(umskt_win32_dos PUBLIC ${OPENSSL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(umskt_win32_dos _umskt OpenSSL::Crypto fmt nlohmann_json::nlohmann_json umskt::rc ${UMSKT_LINK_LIBS})
TARGET_LINK_DIRECTORIES(umskt_win32_dos PUBLIC ${UMSKT_LINK_DIRS})
SET_PROPERTY(TARGET umskt_win32_dos APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
SET_PROPERTY(TARGET umskt APPEND PROPERTY LINK_FLAGS /STUB:${MSVC_MSDOS_STUB})
ENDIF()
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(TARGETS umskt DESTINATION bin)
ENDIF()
### Copy Shared Libraries and dependency files
@ -184,4 +276,21 @@ ELSE()
GET_FILENAME_COMPONENT(OPENSSL_CRYPTO_LIBRARY_FILENAME ${OPENSSL_CRYPTO_LIBRARY} NAME)
CONFIGURE_FILE(${OPENSSL_CRYPTO_LIBRARY} "${CMAKE_CURRENT_BINARY_DIR}/${OPENSSL_CRYPTO_LIBRARY_FILENAME}" COPYONLY)
ENDIF()
IF (DJGPP_WATT32)
message(STATUS "[UMSKT] Configuring DJGPP post-build commands")
# Set .exe suffix for DJGPP builds
set_target_properties(umskt PROPERTIES SUFFIX ".exe")
add_custom_command(TARGET umskt POST_BUILD
# Convert exe to coff, removing the default stub
COMMAND ${DJGPP_BIN_LOCATION}/exe2coff $<TARGET_FILE:umskt>
# Concatenate CWSDSTUB with the COFF file
COMMAND ${CMAKE_COMMAND} -E cat ${CWSDSTUB_LOCATION} $<TARGET_FILE_DIR:umskt>/umskt > $<TARGET_FILE:umskt>
# Clean up the COFF file
COMMAND ${CMAKE_COMMAND} -E rm $<TARGET_FILE_DIR:umskt>/umskt
)
message(STATUS "[UMSKT] STUBIFY_LOCATION set to: ${STUBIFY_LOCATION}")
message(STATUS "[UMSKT] CWSDSTUB_LOCATION set to: ${CWSDSTUB_LOCATION}")
message(STATUS "[UMSKT] DJGPP_BIN_LOCATION set to: ${DJGPP_BIN_LOCATION}")
ENDIF()
ENDIF()

View File

@ -54,9 +54,16 @@ WORKDIR /tmp
# Stage 2: compile djgpp for muslc
ENV DJGPP_PREFIX=/djgpp BUILD_VER=12.2.0-i386
RUN git clone https://github.com/UMSKT/build-djgpp.git djgpp \
RUN git clone https://github.com/andrewwutw/build-djgpp.git djgpp \
&& cd djgpp \
&& chmod +x script/$BUILD_VER \
&& cd script \
&& wget https://gist.github.com/Neo-Desktop/4cfd708f61f5847a7bf457d38db3b59f/raw/25d24cf509b0fc486d5d18ecb6656f120c3d0e51/12.2.0-i386 -O 12.2.0-i386 \
&& chmod +x 12.2.0-i386 \
&& cd ../patch \
&& wget https://gist.github.com/Neo-Desktop/4cfd708f61f5847a7bf457d38db3b59f/raw/25d24cf509b0fc486d5d18ecb6656f120c3d0e51/patch-alpine-Fix-attempt-to-use-poisoned-calloc-error-in-libgccji.patch -O patch-alpine-Fix-attempt-to-use-poisoned-calloc-error-in-libgccji.patch \
&& cd .. \
&& sed -i 's/i586/i386/g' setenv/setenv \
&& sed -i 's/i586/i386/g' setenv/setenv.bat \
&& ./build-djgpp.sh $BUILD_VER \
&& rm -rf /tmp/djgpp
@ -65,12 +72,15 @@ FROM djgpp as watt32
WORKDIR /djgpp
ENV WATT_ROOT=/djgpp/watt32 DJGPP_PREFIX=i386-pc-msdosdjgpp
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/UMSKT/Watt-32.git watt32 \
RUN git clone https://github.com/gvanem/Watt-32.git watt32 \
&& cd watt32/util \
&& make clean && make linux \
&& cd ../src \
&& source /djgpp/setenv \
&& ./configur.sh djgpp \
&& sed -i 's/i586/i386/g' djgpp.mak \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/djgpp.err -O ../inc/sys/djgpp.err \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/syserr.c -O build/djgpp/syserr.c \
&& make -f djgpp.mak \
&& ln -s /djgpp/watt32/lib/libwatt.a /djgpp/lib
@ -78,9 +88,12 @@ RUN git clone https://github.com/UMSKT/Watt-32.git watt32 \
FROM watt32 as openssl
WORKDIR /tmp
SHELL ["/bin/bash", "-c"]
RUN git clone https://github.com/umskt/openssl.git openssl \
RUN git clone https://github.com/openssl/openssl.git openssl \
&& cd openssl \
&& git checkout openssl-3.1.1 \
&& source /djgpp/setenv \
&& wget https://gist.github.com/Neo-Desktop/ad26e888d64b22a59c743ab4e21ac186/raw/c9a73e1eb75ba8857883ac5c08691d2fe5b82594/50-djgpp.conf.patch -O Configurations/50-djgpp.conf.patch \
&& git apply Configurations/50-djgpp.conf.patch \
&& ./Configure no-threads -DOPENSSL_DEV_NO_ATOMICS --prefix=/djgpp DJGPP \
&& make && make install

View File

@ -78,7 +78,6 @@ RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat && `
FROM mcr.microsoft.com/dotnet/framework/runtime:4.8.1 as output
COPY --from=Build32 C:\umskt\build\Release\umskt.exe C:\umskt\umskt.exe
COPY --from=Build32 C:\umskt\build\Release\umskt_win32_dos.exe C:\umskt\umskt_win32_dos.exe
COPY --from=Build64 C:\umskt\build\Release\umskt.exe C:\umskt\umskt64.exe
#invoke via

View File

@ -1,17 +1,32 @@
# **Universal MS Key Toolkit (UMSKT)**
# Universal MS Key Toolkit (UMSKT)
**Connect with us**
[![Zulip chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://umskt.zulipchat.com)
[![libera.chat - #mspid](https://img.shields.io/badge/libera.chat-%23mspid-brightgreen)](https://web.libera.chat/gamja/?nick=Guest?#mspid)
[![Discord](https://img.shields.io/discord/1154155510887620729?label=discord&color=%235865F2)](https://discord.gg/PpBSpuphWM)
**Build status**
[![C/C++ CI (Windows x86+64)](https://github.com/UMSKT/UMSKT/actions/workflows/windows-x86-x64.yml/badge.svg)](../../actions/workflows/windows-x86-x64.yml)
[![C/C++ CI (Windows ARM)](https://github.com/UMSKT/UMSKT/actions/workflows/windows-arm.yml/badge.svg)](../../actions/workflows/windows-arm.yml)
[![C/C++ CI (macOS)](https://github.com/UMSKT/UMSKT/actions/workflows/macos.yml/badge.svg)](../../actions/workflows/macos.yml)
[![C/C++ CI (Linux)](https://github.com/UMSKT/UMSKT/actions/workflows/linux.yml/badge.svg)](../../actions/workflows/linux.yml)
[![C/C++ CI (Windows)](https://github.com/UMSKT/UMSKT/actions/workflows/windows.yml/badge.svg)](../../actions/workflows/windows.yml)
[![C/C++ CI (FreeBSD)](https://github.com/UMSKT/UMSKT/actions/workflows/freebsd.yml/badge.svg)](../../actions/workflows/freebsd.yml)
### **Plan of Action / ToDo List**
[![C/C++ CI (DOS DJGPP)](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/dos-djgpp.yml)
------
### Plan of Action / ToDo List
In light of the recent exponential interest in this project I've decided to put updates of this project here:
* [Please see ticket #8 for more information](../../issues/8)
[Please see ticket #8 for more information](https://github.com/UMSKT/UMSKT/issues/8)
------
@ -29,27 +44,59 @@ In light of the recent exponential interest in this project I've decided to put
* It all comes down to four simple steps:
------
### System Requirements
#### MS-DOS
* i386 processor or better
* MS-DOS 6.22 or later
* Any DOS-based version of Windows
* Windows NT 4.0 or later (via NTVDM)
#### Windows (x86/x64)
* i686 processor or better
* Windows XP or later
> [!WARNING]
> Processors barely meeting the minimum system requirements for XP may not work. Use the MS-DOS version via NTVDM in that case.
#### Windows (ARM32/64)
* Windows 11 21H2 or later
> [!NOTE]
> This is just all we can test. Try to get it to run on Windows RT, make an issue if it doesn't run and we'll try to fix it.
#### macOS
* Apple Silicon or x86_64 processor
* Latest version of macOS
#### Linux
* modern ARM, x86, or x86_64 processor
* Latest version of your Linux distro
------
### **Usage**
#### 1. Download the latest version of WindowsXPKg
#### 1. Download the latest version of UMSKT
* *(GitHub account required)*
* Download the latest experimental version using the Actions tab ([Windows](../../actions/workflows/windows.yml?query=branch%3Amaster), [Linux](../../actions/workflows/linux.yml?query=branch%3Amaster)).
* Download the latest experimental version using the Actions tab ([Windows](../../actions/workflows/windows.yml?query=branch%3Amaster+is%3Asuccess), [Linux](../../actions/workflows/linux.yml?query=branch%3Amaster+is%3Asuccess), [macOS](../../actions/workflows/macos.yml?query=branch%3Amaster+is%3Asuccess), [FreeBSD](../../actions/workflows/freebsd.yml?query=branch%3Amaster+is%3Asuccess), [DOS DJGPP](../../actions/workflows/dos-djgpp.yml?query=branch%3Amaster+is%3Asuccess))
* *(GitHub account \*not\* required)*
* Download the latest release for your operating system and architecture from [the releases page](../../releases)
> [!IMPORTANT]
> Before continuing, please ensure you have the `umskt` executable extracted and on UNIX-like systems, have execution permissions (`chmod +x umskt`).
* **Note:** Before continuing, please ensure you have both the `xpkey` program and the `keys.json` datum extracted and in the same directory
#### 2. Run `xpkey` to generate a key, or add `--help` to see more options.
#### 2. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
> [!IMPORTANT]
> On macOS, like all unsigned executables, you'll need to hold Ctrl while right clicking and selecting Open to actually open it.
#### 3. *(Activation step for `Retail` and `OEM` only)*
* After installation, you will be prompted to activate Windows.
* Select the **telephone activation** method, then, run `xpkey -i <Installation ID>` using the `Installation ID` the activation Wizard provides for you
* Select the **telephone activation** method, then, run `umskt -i <Installation ID>` using the `Installation ID` the activation Wizard provides for you
* If you're activating a non-Windows product, use `umskt -i <Installation ID> -m <Product>`, where `<Product>` is one of `OFFICEXP`, `OFFICE2K3`, `OFFICE2K7`, or `PLUSDME`
* If activating Office 2003/2007, use `umskt -i <Installation ID> -m <Product> -p <Product ID>`
#### 4. Profit!
@ -61,15 +108,16 @@ In light of the recent exponential interest in this project I've decided to put
The list of people who have helped to bring the XP generation to where it is now:
* z22
* MSKey
* sk00ter
* diamondggg
* pottzman
* david4599
* Endermanch
* Neo-Desktop
* WitherOrNot
* TheTank20
* InvoxiPlayGames
* brakmic
* techguy16
(the list will be updated to add more collaborators)
@ -77,13 +125,19 @@ The list of people who have helped to bring the XP generation to where it is now
### **Development Requirements:**
* `CMake, make, gcc` (`build-essential`)
* `build-essential`
* `cmake`
* `make`
* `gcc`
* `g++`
* `git`
#### Build Steps:
1. `git clone`
2. `cd build/ && cmake ../ && make`
1. `git clone https://github.com/UMSKT/UMSKT`
2. `cd UMSKT/build`
3. `cmake ..`
4. `make`
-----
@ -91,6 +145,6 @@ The list of people who have helped to bring the XP generation to where it is now
### **Known Ports**
| Language | Author | Repo URL |
|----------|-----------|-------------------------------------------------------|
|----------|-----------|-----------------------------------------------------------|
| Rust | Alex Page | [anpage/umskt-rs](https://github.com/anpage/umskt-rs) |
| Python | techguy16 | [techguy16/umsktpy](https://github.com/techguy16/umsktpy) |

View File

@ -0,0 +1,302 @@
import hashlib
def add_pid_cksum(pid):
sumPID = 0
val = pid
while val != 0:
sumPID += val % 10
val //= 10
return pid * 10 + 7 - (sumPID % 7)
def decode_iid_new_version(iid, pid):
buffer = [0] * 5
for i in range(len(buffer)):
buffer[i] = int.from_bytes(iid[i*4:i*4+4], byteorder='little')
# print("buffer[" + str(i) + "] = " + hex(buffer[i])[2:].zfill(8))
v1 = (buffer[3] & 0xFFFFFFF8) | 2 # Not really sure but seems to work
v2 = (buffer[3] & 7) << 29 | buffer[2] >> 3
hardwareId = (v1) << 32 | v2
hardwareId = int(hardwareId).to_bytes(8, byteorder='little')
v3 = (buffer[0] & 0xFFFFFF80) >> 7 & 0xFFFFFFFF
unknown1 = v3 & 0x000007FF
v4 = v3 & 0xFFFFF800
v5 = buffer[1] & 0x7F
v6 = buffer[1] >> 7
v7 = (v5 << 25 | v4) >> 11
productID1 = v7 & 0x000003FF
v8 = v7 & 0xFFFFFC00
v9 = (v6 >> 11) & 0x00001FFF
v10 = v9 & 0x00001C00
v11 = v9 & 0x000003FF
v12 = ((v6 << 21) & 0xFFFFFFFF | v8) >> 10
v13 = (v11 << 22) & 0xFFFFFFFF
v14 = v13 | v12
productID3RandomPart = (v14 & 0x3FF00000) >> 20
productID2NoChecksum = v14 & 0x000FFFFF
v15 = v13 >> 30 # 0x00000003
v16 = v10 >> 8 # 0x0000001C
v17 = (buffer[2] & 7) << 6 # 0x000001C0
v18 = (buffer[4] & 1) << 9 # 0x00000200
authInfo = v18 | v17 | v16 | v15 # Not that important bug: bit 5 is not present
productID0 = pid[0]
productID2 = add_pid_cksum(productID2NoChecksum)
productID3 = (pid[3] // 1000) * 1000 + productID3RandomPart
# Just to remember: public key index I of pid (XXXXX-XXX-XXXXXXX-IIXXX) = BINK ID // 2
# Where is actually located the version number?
# version1 = buffer[0] & 7
# print("Decoded IID Version1?: " + str(version1))
# version2 = (int.from_bytes(iid[8:17], byteorder='little') >> 52) & 7
# print("Decoded IID Version2?: " + str(version2))
# version3 = buffer[3] & 7
# print("Decoded IID Version3?: " + str(version3))
if productID1 != pid[1] or productID2 != pid[2] or pid[3] % 1000 != productID3RandomPart:
print("Error: Product ID not matching!")
return 0, 0, 0
return hardwareId, authInfo, unknown1
# Validate installation ID checksum
def validate_cksum(n):
print("Checksumming installation ID...")
n = n.replace("-", "")
cksum = 0
for i, k in enumerate(map(int, n)):
if (i + 1) % 6 == 0 or i == len(n) - 1:
print("Expected last digit", cksum % 7, "got", k)
if cksum % 7 != k:
return None
cksum = 0
else:
cksum += k * (i % 2 + 1)
parts = [n[i:i+5] for i in range(0, len(n), 6)]
n_out = "".join(parts)
if len(n_out) == 42:
n_out = n_out[:-1]
if len(n_out) != 45 and len(n_out) != 41:
return None
return int(n_out)
# Insert checksum digits into confirmation ID
def add_cksum(n):
cksums = []
n = str(n).zfill(35)
parts = [n[i:i+5] for i in range(0, len(n), 5)]
for p in parts:
cksum = 0
for i, k in enumerate(map(int, p)):
cksum += k * (i % 2 + 1)
cksums.append(str(cksum % 7))
n_out = ""
for i in range(7):
n_out += parts[i] + cksums[i] + ("-" if i != 6 else "")
return n_out
def encrypt(decrypted, key):
size_half = len(decrypted) // 2
size_half_dwords = size_half - (size_half % 4)
last = decrypted[size_half*2:]
decrypted = decrypted[:size_half*2]
for i in range(4):
first = decrypted[:size_half]
second = decrypted[size_half:]
# A magic byte 0x79 is now added at the beginning of the list of bytes to hash
sha1_result = hashlib.sha1(bytearray.fromhex("79") + second + key).digest()
sha1_result = (sha1_result[:size_half_dwords] +
sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])
decrypted = second + bytes(x^^y for x,y in zip(first, sha1_result))
return decrypted + last
def decrypt(encrypted, key):
size_half = len(encrypted) // 2
size_half_dwords = size_half - (size_half % 4)
last = encrypted[size_half*2:]
encrypted = encrypted[:size_half*2]
for i in range(4):
first = encrypted[:size_half]
second = encrypted[size_half:]
# A magic byte 0x79 is now added at the beginning of the list of bytes to hash
sha1_result = hashlib.sha1(bytearray.fromhex("79") + first + key).digest()
sha1_result = (sha1_result[:size_half_dwords] +
sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])
encrypted = bytes(x^^y for x,y in zip(second, sha1_result)) + first
return encrypted + last
# Find v of divisor (u, v) of curve y^2 = F(x)
def find_v(u):
f = F % u
c2 = u[1]^2 - 4 * u[0]
c1 = 2 * f[0] - f[1] * u[1]
if c2 == 0:
if c1 == 0:
return None
try:
v1 = sqrt(f[1]^2 / (2 * c1))
v1.lift()
except:
return None
else:
try:
d = 2 * sqrt(f[0]^2 + f[1] * (f[1] * u[0] - f[0] * u[1]))
v1_1 = sqrt((c1 - d)/c2)
v1_2 = sqrt((c1 + d)/c2)
except:
return None
try:
v1_1.lift()
v1 = v1_1
except:
try:
v1_2.lift()
v1 = v1_2
except:
return None
v0 = (f[1] + u[1] * v1^2) / (2 * v1)
v = v0 + v1 * x
assert (v^2 - f) % u == 0
return v
# order of field Fp
p = 0x16E48DD18451FE9
# Coefficients of F
coeffs = [0, 0xE5F5ECD95C8FD2, 0xFF28276F11F61, 0xFB2BD9132627E6, 0xE5F5ECD95C8FD2, 1]
# This constant inverts multiplication by 0x10001 in verification
INV = 0x01fb8cf48a70dfefe0302a1f7a5341
# Key to decrypt installation IDs
IID_KEY = b'\x5A\x30\xB9\xF3'
#"""
# minimal quadratic non-residue of p
mqnr = least_quadratic_nonresidue(p)
# Galois field of order p
Fp = GF(p)
# Polynomial field Fp[x] over Fp
Fpx.<x> = Fp[]
# Hyperellptic curve function
F = sum(k*x^i for i, k in enumerate(coeffs))
# Hyperelliptic curve E: y^2 = F(x) over Fp
E = HyperellipticCurve(F)
# The jacobian over E
J = E.jacobian()
# unpack&decrypt installationId
installationId = validate_cksum(input("Installation ID (dashes optional): "))
productId = input("Product ID (with dashes): ").split("-")
pid = [int(x) for x in productId]
# Office 2003 Professional Edition FWYTB-C7PPP-4497G-FV737-2HQWG (UMSKT generated)
# installationId = 020572391118023984229275432949036355811509788 # 020570-239116-180233-984220-927546-329495-036352-581151-097880
# pid = [73931, 746, 6952006, 57345] # 73931-746-6952006-57345
# Office 2007 Enterprise Edition XGQ68-R77XM-FPYFH-B436K-46QDY (UMSKT generated)
# installationId = 032422660398632786377841998280144793681167281 # 032424-266032-986324-786370-784193-982801-144791-368115-672814
# pid = [89388, 864, 6523093, 65443] # 89388-864-6523093-65443
print(installationId)
if not installationId:
raise Exception("Invalid Installation ID (checksum fail)")
installationIdSize = 19 if len(str(installationId)) > 41 else 17 # 17 for XP Gold, 19 for SP1+ (includes 12 bits of sha1(product key))
iid = int(installationId).to_bytes(installationIdSize, byteorder='little')
iid = decrypt(iid, IID_KEY)
hwid, authInfo, unknown1 = decode_iid_new_version(iid, pid)
print("\nDecoded Hardware ID: " + hex(int.from_bytes(hwid, byteorder='big')))
print("Decoded AuthInfo: " + hex(authInfo))
print("Decoded Unknown1: " + hex(unknown1))
assert hwid != 0
key = hwid + int((pid[0] << 41 | pid[1] << 58 | pid[2] << 17 | pid[3]) & ((1 << 64) - 1)).to_bytes(8, byteorder='little')
data = [0x00] * 14
# data = b'\xb9g\xdd\xe1\xb0\xef-\x1e\xbd\x0frE\xd8\xbe'
print("\nConfirmation IDs:")
for i in range(0x81):
data[6] = i # Attempt number was byte 7 in older confirmation ID version but it is now byte 6
# Encrypt conf ID, find u of divisor (u, v)
encrypted = encrypt(bytes(data), key)
encrypted = int.from_bytes(encrypted, byteorder="little")
x1, x2 = Fp(encrypted % p), Fp((encrypted // p) + 1)
u1, u0 = x1 * 2, (x1 ^ 2) - ((x2 ^ 2) * mqnr)
u = x^2 + u1 * x + u0
# Generate original divisor
v = find_v(u)
if not v:
print(v)
continue
d2 = J(u, v)
divisor = d2 * INV
# Get x1 and x2
roots = [x for x, y in divisor[0].roots()]
if len(roots) > 0:
y = [divisor[1](r) for r in roots]
x1 = (-roots[0]).lift()
x2 = (-roots[1]).lift()
if (x1 > x2) or (y[0].lift() % 2 != y[1].lift() % 2):
x1 = (-roots[1]).lift()
x2 = (-roots[0]).lift()
else:
x2 = (divisor[0][1] / 2).lift()
x1 = sqrt((x2^2 - divisor[0][0]) / mqnr).lift() + p
# Win
conf_id = x1 * (p + 1) + x2
conf_id = add_cksum(conf_id)
print(conf_id)

433
extras/confid.ipynb Normal file
View File

@ -0,0 +1,433 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Constants (run this cell first!)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
"# MS Plus! DME\n",
"\n",
"# order of field Fp \n",
"p = 0x16A5DABA0605983\n",
"# Coefficients of F\n",
"coeffs = [0x334f24f75caa0e, 0x1392ff62889bd7b, 0x135131863ba2db8, 0x153208e78006010, 0x163694f26056db, 1]\n",
"# This constant inverts multiplication by 0x10001 in verification\n",
"INV = 0x01c61212ece6107c4254c43a5d1181\n",
"# Key to decrypt installation IDs\n",
"IID_KEY = b'\\x6A\\xC8\\x5E\\xD4'\n",
"#\"\"\"\n",
"\n",
"#\"\"\"\n",
"# Office XP/2003\n",
"\n",
"# order of field Fp \n",
"p = 0x16E48DD18451FE9\n",
"# Coefficients of F\n",
"coeffs = [0, 0xE5F5ECD95C8FD2, 0xFF28276F11F61, 0xFB2BD9132627E6, 0xE5F5ECD95C8FD2, 1]\n",
"# This constant inverts multiplication by 0x10001 in verification\n",
"INV = 0x01fb8cf48a70dfefe0302a1f7a5341\n",
"# Key to decrypt installation IDs\n",
"IID_KEY = b'\\x5A\\x30\\xB9\\xF3'\n",
"#\"\"\"\n",
"\n",
"\"\"\"\n",
"# Whistler 2428 (could be others)\n",
"\n",
"# order of field Fp \n",
"p = 0x16BD82821354FA3\n",
"# Coefficients of F\n",
"coeffs = [0, 0xDEFD8C5651954F, 0xA23AA12556ECE5, 0x89D79AD61B786D, 0xCCA087F0A6A4A4, 1]\n",
"# This constant inverts multiplication by 0x10001 in verification\n",
"INV = 0xd9ed873ed84a45761c23fd7fafd1\n",
"# Key to decrypt installation IDs\n",
"IID_KEY = b'\\x6A\\xC8\\x5E\\xD4'\n",
"#\"\"\"\n",
"\n",
"\n",
"\"\"\"\n",
"# Windows XP/Server 2003/Longhorn Pre-Reset\n",
"\n",
"# order of field Fp \n",
"p = 0x16A6B036D7F2A79\n",
"# Coefficients of F\n",
"coeffs = [0, 0x21840136C85381, 0x44197B83892AD0, 0x1400606322B3B04, 0x1400606322B3B04, 1]\n",
"# This constant inverts multiplication by 0x10001 in verification\n",
"INV = 0x40DA7C36D44C04E21B9D10F127C1\n",
"# Key to decrypt installation IDs\n",
"IID_KEY = b'\\x6A\\xC8\\x5E\\xD4'\n",
"#\"\"\"\n",
"\n",
"# minimal quadratic non-residue of p\n",
"mqnr = least_quadratic_nonresidue(p)\n",
"# Galois field of order p\n",
"Fp = GF(p)\n",
"# Polynomial field Fp[x] over Fp\n",
"Fpx.<x> = Fp[]\n",
"\n",
"# Hyperellptic curve function\n",
"F = sum(k*x^i for i, k in enumerate(coeffs))\n",
"# Hyperelliptic curve E: y^2 = F(x) over Fp\n",
"E = HyperellipticCurve(F)\n",
"# The jacobian over E\n",
"J = E.jacobian()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Generate Confirmation ID"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"import hashlib\n",
"\n",
"# Validate installation ID checksum\n",
"def validate_cksum(n):\n",
" print(\"Checksumming installation ID...\")\n",
" n = n.replace(\"-\", \"\")\n",
"\n",
" cksum = 0\n",
" for i, k in enumerate(map(int, n)):\n",
" if (i + 1) % 6 == 0 or i == len(n) - 1:\n",
" print(\"Expected last digit\", cksum % 7, \"got\", k)\n",
" if cksum % 7 != k:\n",
" return None\n",
" \n",
" cksum = 0\n",
" else:\n",
" cksum += k * (i % 2 + 1)\n",
" \n",
" parts = [n[i:i+5] for i in range(0, len(n), 6)]\n",
" n_out = \"\".join(parts)\n",
" \n",
" if len(n_out) == 42:\n",
" n_out = n_out[:-1]\n",
" \n",
" if len(n_out) != 45 and len(n_out) != 41:\n",
" return None\n",
" \n",
" return int(n_out)\n",
"\n",
"# Insert checksum digits into confirmation ID\n",
"def add_cksum(n):\n",
" cksums = []\n",
" n = str(n).zfill(35)\n",
" parts = [n[i:i+5] for i in range(0, len(n), 5)]\n",
" \n",
" for p in parts:\n",
" cksum = 0\n",
" \n",
" for i, k in enumerate(map(int, p)):\n",
" cksum += k * (i % 2 + 1)\n",
" \n",
" cksums.append(str(cksum % 7))\n",
" \n",
" n_out = \"\"\n",
" \n",
" for i in range(7):\n",
" n_out += parts[i] + cksums[i] + (\"-\" if i != 6 else \"\")\n",
" \n",
" return n_out\n",
"\n",
"def encrypt(decrypted, key):\n",
" size_half = len(decrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = decrypted[size_half*2:]\n",
" decrypted = decrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = decrypted[:size_half]\n",
" second = decrypted[size_half:]\n",
" sha1_result = hashlib.sha1(second + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" decrypted = second + bytes(x^^y for x,y in zip(first, sha1_result))\n",
" return decrypted + last\n",
"\n",
"def decrypt(encrypted, key):\n",
" size_half = len(encrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = encrypted[size_half*2:]\n",
" encrypted = encrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = encrypted[:size_half]\n",
" second = encrypted[size_half:]\n",
" sha1_result = hashlib.sha1(first + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" encrypted = bytes(x^^y for x,y in zip(second, sha1_result)) + first\n",
" return encrypted + last\n",
"\n",
"# Find v of divisor (u, v) of curve y^2 = F(x)\n",
"def find_v(u):\n",
" f = F % u\n",
" c2 = u[1]^2 - 4 * u[0]\n",
" c1 = 2 * f[0] - f[1] * u[1]\n",
" \n",
" if c2 == 0:\n",
" if c1 == 0:\n",
" return None\n",
" \n",
" try:\n",
" v1 = sqrt(f[1]^2 / (2 * c1))\n",
" v1.lift()\n",
" except:\n",
" return None\n",
" else:\n",
" try:\n",
" d = 2 * sqrt(f[0]^2 + f[1] * (f[1] * u[0] - f[0] * u[1]))\n",
" v1_1 = sqrt((c1 - d)/c2)\n",
" v1_2 = sqrt((c1 + d)/c2)\n",
" except:\n",
" return None\n",
"\n",
" try:\n",
" v1_1.lift()\n",
" v1 = v1_1\n",
" except:\n",
" try:\n",
" v1_2.lift()\n",
" v1 = v1_2\n",
" except:\n",
" return None\n",
" \n",
" v0 = (f[1] + u[1] * v1^2) / (2 * v1)\n",
" v = v0 + v1 * x\n",
" \n",
" assert (v^2 - f) % u == 0\n",
" return v\n",
"\n",
"# unpack&decrypt installationId\n",
"installationId = validate_cksum(input(\"Installation ID (dashes optional): \"))\n",
"# installationId = 11234597509478704096883784033789146715149\n",
"print(installationId)\n",
"\n",
"if not installationId:\n",
" raise Exception(\"Invalid Installation ID (checksum fail)\")\n",
"\n",
"installationIdSize = 19 if len(str(installationId)) > 41 else 17 # 17 for XP Gold, 19 for SP1+ (includes 12 bits of sha1(product key))\n",
"iid = int(installationId).to_bytes(installationIdSize, byteorder='little')\n",
"iid = decrypt(iid, IID_KEY)\n",
"hwid = iid[:8]\n",
"productid = int.from_bytes(iid[8:17], byteorder='little')\n",
"productkeyhash = iid[17:]\n",
"pid1 = productid & ((1 << 17) - 1)\n",
"pid2 = (productid >> 17) & ((1 << 10) - 1)\n",
"pid3 = (productid >> 27) & ((1 << 24) - 1)\n",
"version = (productid >> 52) & 7\n",
"pid4 = productid >> 55\n",
"\n",
"if version != (4 if len(iid) == 17 else 5):\n",
" print(f\"Invalid Installation ID (unknown version {version})\")\n",
"\n",
"print(installationIdSize)\n",
"print(pid1, pid2, pid3, pid4)\n",
"\n",
"key = hwid + int((pid1 << 41 | pid2 << 58 | pid3 << 17 | pid4) & ((1 << 64) - 1)).to_bytes(8, byteorder='little')\n",
"\n",
"data = [0x00] * 14\n",
"# data = b'\\xb9g\\xdd\\xe1\\xb0\\xef-\\x1e\\xbd\\x0frE\\xd8\\xbe'\n",
"print(\"\\nConfirmation IDs:\")\n",
"\n",
"for i in range(0x81):\n",
" data[4] = i\n",
" # Encrypt conf ID, find u of divisor (u, v)\n",
" encrypted = encrypt(bytes(data), key)\n",
" encrypted = int.from_bytes(encrypted, byteorder=\"little\")\n",
" x1, x2 = Fp(encrypted % p), Fp((encrypted // p) + 1)\n",
" u1, u0 = x1 * 2, (x1 ^ 2) - ((x2 ^ 2) * mqnr)\n",
" u = x^2 + u1 * x + u0\n",
"\n",
" # Generate original divisor\n",
" v = find_v(u)\n",
" \n",
" if not v:\n",
" continue\n",
" \n",
" d2 = J(u, v)\n",
" divisor = d2 * INV\n",
" \n",
" # Get x1 and x2\n",
" roots = [x for x, y in divisor[0].roots()]\n",
"\n",
" if len(roots) > 0:\n",
" y = [divisor[1](r) for r in roots]\n",
" x1 = (-roots[0]).lift()\n",
" x2 = (-roots[1]).lift()\n",
"\n",
" if (x1 > x2) or (y[0].lift() % 2 != y[1].lift() % 2):\n",
" x1 = (-roots[1]).lift()\n",
" x2 = (-roots[0]).lift()\n",
" else:\n",
" x2 = (divisor[0][1] / 2).lift()\n",
" x1 = sqrt((x2^2 - divisor[0][0]) / mqnr).lift() + p\n",
"\n",
" # Win\n",
" conf_id = x1 * (p + 1) + x2\n",
" conf_id = add_cksum(conf_id)\n",
" print(conf_id)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Validate Confirmation ID (originally by diamondggg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import hashlib\n",
"\n",
"# 226512-274743-842923-777124-961370-722240-570042-517722-757426\n",
"installationId = 44706039542602728435285810860722693781\n",
"installationIdSize = 17 # 17 for XP Gold, 19 for SP1+ (includes 12 bits of sha1(product key))\n",
"# all three of following are valid generated\n",
"# 013705-060122-603141-961392-086136-909901-494476\n",
"confid = input(\"Confirmation ID: \").replace(\"-\", \"\")\n",
"confirmationId = int(\"\".join([confid[i:i+5] for i in range(0, len(confid), 6)]))\n",
"# confirmationId = 13009861034010972507754924748629391\n",
"print(confirmationId)\n",
"# 022032-220754-159721-909624-985141-504586-914001\n",
"#confirmationId = 2203220751597290962985145045891400\n",
"# 137616-847280-708585-827476-874935-313366-790880\n",
"#confirmationId = 13761847287085882747874933133679088\n",
"\n",
"def decrypt(encrypted, key):\n",
" size_half = len(encrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = encrypted[size_half*2:]\n",
" encrypted = encrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = encrypted[:size_half]\n",
" second = encrypted[size_half:]\n",
" sha1_result = hashlib.sha1(first + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" encrypted = bytes(x^^y for x,y in zip(second, sha1_result)) + first\n",
" return encrypted + last\n",
"\n",
"# unpack&decrypt installationId\n",
"iid = int(installationId).to_bytes(installationIdSize, byteorder='little')\n",
"iid = decrypt(iid, IID_KEY)\n",
"hwid = iid[:8]\n",
"productid = int.from_bytes(iid[8:17], byteorder='little')\n",
"# productkeyhash is not used for validation, it exists just to allow the activation server to reject keygenned pids\n",
"productkeyhash = iid[17:]\n",
"pid1 = productid & ((1 << 17) - 1)\n",
"pid2 = (productid >> 17) & ((1 << 10) - 1)\n",
"pid3 = (productid >> 27) & ((1 << 24) - 1)\n",
"version = (productid >> 52) & 7\n",
"pid4 = productid >> 55\n",
"\n",
"print(pid1, pid2, pid3, pid4)\n",
"\n",
"if version != (4 if len(iid) == 17 else 5):\n",
" print(version)\n",
"\n",
"key = hwid + int((pid1 << 41 | pid2 << 58 | pid3 << 17 | pid4) & ((1 << 64) - 1)).to_bytes(8, byteorder='little')\n",
"\n",
"# deserialize divisor\n",
"x1 = confirmationId // (p + 1)\n",
"x2 = confirmationId % (p + 1)\n",
"if x1 <= p:\n",
" # two or less points over GF(p)\n",
" point1 = E.lift_x(Fp(-x1)) if x1 != p else None\n",
" point2 = E.lift_x(Fp(-x2)) if x2 != p else None\n",
" if point1 is not None and point2 is not None:\n",
" # there are 4 variants of how lift_x() could select both y-s\n",
" # we don't distinguish D and -D, but this still leaves 2 variants\n",
" # the chosen one is encoded by order of x1 <=> x2\n",
" lastbit1 = point1[1].lift() & 1\n",
" lastbit2 = point2[1].lift() & 1\n",
" if x2 < x1:\n",
" if lastbit1 == lastbit2:\n",
" point2 = E(point2[0], -point2[1])\n",
" else:\n",
" if lastbit1 != lastbit2:\n",
" point2 = E(point2[0], -point2[1])\n",
" point1 = J(point1) if point1 is not None else J(0)\n",
" point2 = J(point2) if point2 is not None else J(0)\n",
" divisor = point1 + point2\n",
"else:\n",
" # a pair of conjugate points over GF(p^2)\n",
" f = (x+x2)*(x+x2) - mqnr*x1*x1 # 43 is the minimal quadratic non-residue in Fp\n",
" Fp2 = GF(p^2)\n",
" point1 = E.lift_x(f.roots(Fp2)[0][0])\n",
" point2 = E(Fp2)(point1[0].conjugate(), point1[1].conjugate())\n",
" divisor = J(Fp2)(point1) + J(Fp2)(point2)\n",
" divisor = J(Fpx(divisor[0]), Fpx(divisor[1])) #return from Fp2 to Fp\n",
"\n",
"d2 = divisor * 0x10001\n",
"assert d2[0].degree() == 2\n",
"x1 = d2[0][1]/2\n",
"x2 = sqrt((x1*x1-d2[0][0])/mqnr)\n",
"\n",
"encrypted = x1.lift() + (x2.lift() - 1) * p\n",
"encrypted = int(encrypted).to_bytes(14,byteorder='little')\n",
"\n",
"# end of the math\n",
"decrypted = decrypt(encrypted, key)\n",
"print(decrypted.hex())\n",
"# 0000000000000001000000000000 for the first confirmationId\n",
"# 0000000000000002000000000000 for the second confirmationId\n",
"# 0000000000000006000000000000 for the last confirmationId\n",
"assert decrypted[8:] == b'\\0' * 6\n",
"assert decrypted[7] <= 0x80\n",
"# all zeroes in decrypted[0:7] are okay for the checker\n",
"# more precisely: if decrypted[6] == 0, first 6 bytes can be anything\n",
"# otherwise, decrypted[0] = length, and decrypted[1:1+length] must match first length bytes of sha1(product key)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.0",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

65
extras/parse_dpcdll.py Normal file
View File

@ -0,0 +1,65 @@
from glob import glob
from struct import unpack
import json
import sys
def readint(f):
return unpack("<I", f.read(4))[0]
if __name__ == "__main__":
if len(sys.argv) < 3:
print(f"usage: {sys.argv[0]} dpcdll.dll out.json")
lic_types = ["NULL", "Volume", "Retail", "Evaluation", "Tablet", "OEM-SLP", "Embedded"]
dpcdata = []
with open(sys.argv[1], "rb") as f:
tmp = f.read()
f.seek(tmp.find(b"\x1e\x00\x00\x00\xff\xff\xff\x7f") - 20)
del tmp
while f.read(4) != b"\x00\x00\x00\x00":
f.seek(-164, 1)
f.seek(-4, 1)
last_ind = -1
ind = 0
dpcentry = {}
while True:
ind = readint(f)
bink_id = hex(readint(f))[2:].zfill(8).upper()
min_pid = readint(f)
max_pid = readint(f)
if min_pid > 999 or max_pid > 999:
break
lic_type = readint(f)
if lic_type > 6:
break
if lic_type == 2 and int(bink_id, 16) % 2 == 1:
lic_type_str = "OEM-COA"
else:
lic_type_str = lic_types[lic_type]
days_to_act = readint(f)
eval_days = readint(f)
sig_len = readint(f)
f.read(sig_len)
dpcdata.append({
"index": ind,
"bink": bink_id,
"pid_range": [min_pid, max_pid],
"type": lic_type_str,
"days_to_activate": days_to_act,
"days_evaluation": eval_days
})
with open(sys.argv[2], "w") as f:
f.write(json.dumps(dpcdata, indent=4))

98
extras/parse_pubkey.py Normal file
View File

@ -0,0 +1,98 @@
from struct import pack, unpack, calcsize
from json import dumps
from os.path import basename
import sys
def readint(f):
return unpack("<I", f.read(4))[0]
def readstc(f, s):
s = "<" + s
sz = calcsize(s)
return unpack(s, f.read(sz))
pubkey_data = {}
with open(sys.argv[1], "rb") as f:
magic1 = readint(f)
if magic1 != 0x44556677:
raise Exception("Invalid pubkey format")
f.read(4)
field_data_size = readint(f)
magic2 = readint(f)
if magic2 != 0x00112233:
raise Exception("Invalid pubkey format")
f.read(4)
data = readstc(f, "B" * 3 + "I" * 9)
must_be_0 = data[0]
if must_be_0 != 0:
raise Exception("Invalid field data")
size_modulus = data[1]
size_order = data[2]
ext_deg1 = data[3]
ext_deg2 = data[4]
offset_modulus = data[8]
f.read(1)
h1_bases = list(readstc(f, "B" * size_modulus))
modulus = int.from_bytes(f.read(size_modulus), "little")
order = int.from_bytes(f.read(size_order), "little")
ext_minpoly1 = list(readstc(f, "B" * (ext_deg1 + 1)))
ext_minpoly2 = list(readstc(f, "B" * (ext_deg2 + 1)))
f.read(size_modulus * 2)
ec_a = int.from_bytes(f.read(size_modulus), "little")
ec_b = int.from_bytes(f.read(size_modulus), "little")
f.seek(field_data_size + 12)
points = []
for i in range(size_modulus):
x = []
y = []
for i in range(ext_deg1):
x.append(int.from_bytes(f.read(size_modulus), "little"))
for i in range(ext_deg1):
y.append(int.from_bytes(f.read(size_modulus), "little"))
points.append({"x": x, "y": y})
pairing_val = []
for i in range(ext_deg2):
ext1_val = []
for j in range(ext_deg1):
ext1_val.append(int.from_bytes(f.read(size_modulus), "little"))
pairing_val.append(ext1_val)
pubkey_data = {
"field": {
"modulus": modulus,
"ec_base_order": order,
"k3_minpoly": ext_minpoly1,
"k6_minpoly": ext_minpoly2,
},
"h1_bases": h1_bases,
"curve": {
"a": ec_a,
"b": ec_b
},
"points": points,
"pairing_val": pairing_val
}
with open("pubkey_info/" + basename(sys.argv[1]).replace(".pubkey", ".json"), "w") as g:
g.write(dumps(pubkey_data, indent=4))

348
extras/pidgenx.ipynb Normal file
View File

@ -0,0 +1,348 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The math in this notebook is described in [this patent](https://patentimages.storage.googleapis.com/a3/27/c1/3c0948a078cb28/US7587605.pdf). Be warned, the math is very complicated."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Windows 7 Retail/GVLK, public key ID 170\n",
"\n",
"pubkey_data = {\n",
" \"field\": {\n",
" \"modulus\": 886368969471450739924935101400677,\n",
" \"ec_base_order\": 886368969471450710152985728350703,\n",
" \"k3_minpoly\": [\n",
" 4,\n",
" 1,\n",
" 0,\n",
" 1\n",
" ],\n",
" \"k6_minpoly\": [\n",
" 2,\n",
" 0,\n",
" 1\n",
" ]\n",
" },\n",
" \"h1_bases\": [\n",
" 1,\n",
" 3,\n",
" 8,\n",
" 15,\n",
" 15,\n",
" 15,\n",
" 31,\n",
" 3,\n",
" 3,\n",
" 3,\n",
" 3,\n",
" 3,\n",
" 7,\n",
" 63\n",
" ],\n",
" \"curve\": {\n",
" \"a\": 26392827536965106777121445123290,\n",
" \"b\": 372325368096095544195525883520589\n",
" },\n",
" \"points\": [\n",
" {\n",
" \"x\": [\n",
" 365236101742748463929673543888206,\n",
" 858097895593939865996182272259769,\n",
" 148438159087534462792506738986740\n",
" ],\n",
" \"y\": [\n",
" 776418047571862972603801173382237,\n",
" 873677028107508092012208744232957,\n",
" 622138327043805563266794621920098\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 940136574680879136511599445781,\n",
" 566978253317108608042529258054523,\n",
" 176284220413545220121710961573292\n",
" ],\n",
" \"y\": [\n",
" 828856809691743749590800150937649,\n",
" 225146018128364550960496522448712,\n",
" 348601659612301002638949468744847\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 733747358623171948496764545320051,\n",
" 728506535527490173098593825125337,\n",
" 82462451162574422717677160727098\n",
" ],\n",
" \"y\": [\n",
" 416331132638004657079841565104549,\n",
" 366794872410090667339979925100938,\n",
" 154519017608105570119249112044121\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 849718119860311390685018324089317,\n",
" 69736499980142833460080381132368,\n",
" 72139323263966224829624934948858\n",
" ],\n",
" \"y\": [\n",
" 122550620604034160835298121626961,\n",
" 232865179257577260620478614346661,\n",
" 96495922331236902442197840422963\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 737949449696062407373114808812927,\n",
" 526576673882551145431025311648593,\n",
" 577710732700754839750249914833193\n",
" ],\n",
" \"y\": [\n",
" 245977198113437420529250724111432,\n",
" 316396368275232555978824338443046,\n",
" 755792900000892204654488821885538\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 712586405875738967442641545880322,\n",
" 615445286425878710157557053762371,\n",
" 734183236086095230968388017605820\n",
" ],\n",
" \"y\": [\n",
" 851284376759840359812981263306021,\n",
" 769237654873203944088649987250083,\n",
" 359324880331507581802773028306633\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 579665839598807564349118802507078,\n",
" 793103874095793223248478622956780,\n",
" 502860226530799804560661048077280\n",
" ],\n",
" \"y\": [\n",
" 526775274489316486107329470634542,\n",
" 828721161962151275145535457964404,\n",
" 204415317809040518371881977645416\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 804790447447351785544412956578788,\n",
" 119046642031064430140912082580578,\n",
" 475159529884254928674792290619954\n",
" ],\n",
" \"y\": [\n",
" 458245266057063984580129835988070,\n",
" 338411981227059768831710308435687,\n",
" 577923375329917551735757167190702\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 448295070796654878810211055051604,\n",
" 482910785083759911781193909334072,\n",
" 795628820954832750108065551162801\n",
" ],\n",
" \"y\": [\n",
" 417757375223493128894380427308216,\n",
" 755520039102173573177271365439537,\n",
" 863842006193777913816171128026446\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 663389221842281261857262032548436,\n",
" 846447543951704162020988219326272,\n",
" 686142287698732386980948449542167\n",
" ],\n",
" \"y\": [\n",
" 769015970121598916167134609518482,\n",
" 738460771147019950148429256265493,\n",
" 613009789239563486872501072748270\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 23530113060362511985797534739195,\n",
" 718131004725002854064127778364823,\n",
" 140870968646848990835780066321375\n",
" ],\n",
" \"y\": [\n",
" 641031697928634900295866764583620,\n",
" 295544383156746469642549388283327,\n",
" 133766761871461067699690599056442\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 7518354584460889742005963384331,\n",
" 340825540582760123772991939806390,\n",
" 525549834323799848592419044187971\n",
" ],\n",
" \"y\": [\n",
" 585295007893871934790357000030208,\n",
" 117490751031779271453224407217079,\n",
" 838852298106199238437827740364400\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 806036388470182281562651653929939,\n",
" 266085928879449679004785507000719,\n",
" 201474020142460453395308745398496\n",
" ],\n",
" \"y\": [\n",
" 573468377549807523205344415925956,\n",
" 667459718759242575444856430313959,\n",
" 226975716159080217447594275999935\n",
" ]\n",
" },\n",
" {\n",
" \"x\": [\n",
" 794167987155642331621801361756614,\n",
" 809201520617560616339201020039820,\n",
" 198696155869194654384403079624544\n",
" ],\n",
" \"y\": [\n",
" 725959545288387914551997303844726,\n",
" 49262476800238214847233993847181,\n",
" 537326577113493149345527624223733\n",
" ]\n",
" }\n",
" ],\n",
" \"pairing_val\": [\n",
" [\n",
" 242940802691096077821709859741616,\n",
" 178851543248946074944443141484182,\n",
" 802059826004050667481466713086225\n",
" ],\n",
" [\n",
" 701042518368651902930590425782509,\n",
" 265571225406900742458432149860962,\n",
" 699432283102586243018242179516873\n",
" ]\n",
" ]\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"p = pubkey_data[\"field\"][\"modulus\"]\n",
"a = pubkey_data[\"curve\"][\"a\"]\n",
"b = pubkey_data[\"curve\"][\"b\"]\n",
"order = pubkey_data[\"field\"][\"ec_base_order\"]\n",
"h1_bases = list(map(lambda x: x+1, pubkey_data[\"h1_bases\"]))\n",
"KCHARS = \"BCDFGHJKMPQRTVWXY2346789\"\n",
"\n",
"def decode_pkey(k):\n",
" k = k.replace(\"-\", \"\")\n",
" out = 0\n",
" \n",
" for c in k:\n",
" out *= 24\n",
" out += KCHARS.index(c)\n",
" \n",
" return out\n",
"\n",
"K = GF(p)\n",
"Kx.<x> = K[]\n",
"K3.<u> = K.extension(Kx(pubkey_data[\"field\"][\"k3_minpoly\"]))\n",
"K3y.<y> = K3[]\n",
"K6.<t> = K3.extension(K3y(pubkey_data[\"field\"][\"k6_minpoly\"]))\n",
"\n",
"E = EllipticCurve(K, [a, b])\n",
"E6 = EllipticCurve(K6, [a, b])\n",
"\n",
"Qi = [E6(K3(point[\"x\"]) * t^-2, K3(point[\"y\"]) * t^-3) for point in pubkey_data[\"points\"]]\n",
"\n",
"# pairing_val = e_m(P, S)\n",
"pairing_val = K6([K3(pubkey_data[\"pairing_val\"][0]), K3(pubkey_data[\"pairing_val\"][1])])\n",
"\n",
"assert is_prime(p)\n",
"assert len(h1_bases) == len(Qi)\n",
"assert h1_bases[0] == 2\n",
"assert pairing_val^order == 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pkey_chars = \"33PXH-7Y6KF-2VJC9-XBBR8-HVTHH\"\n",
"\n",
"# pkey = HASH(M)\n",
"# HASH is a currently unknown hash function\n",
"pkey = decode_pkey(pkey_chars)\n",
"\n",
"# h1_coeffs = H1(M)\n",
"# During validation, coeffs must be found by a search that i havent implemented\n",
"# h1_coeffs = [1, 0, 7, 1, 4, 15, 9, 1, 1, 0, 2, 1, 0, 19]\n",
"\n",
"# 10 bits unknown, 30 bits product ID, 1 bit unknown (upgrade?)\n",
"key_data = (342 << 31 | 918500000 << 1 | 0)\n",
"h1_coeffs = [1]\n",
"\n",
"for i in range(len(h1_bases) - 1):\n",
" h1_coeffs.append(key_data % h1_bases[i + 1])\n",
" key_data //= h1_bases[i + 1]\n",
"\n",
"print(h1_coeffs)\n",
"\n",
"# H2(M) = E.lift_x(HASH(M) % p)\n",
"T = E6(E.lift_x(pkey % p))\n",
"Q = sum(map(lambda x: x[0] * x[1], zip(h1_coeffs, Qi))) \n",
"\n",
"test_pairing = T.tate_pairing(Q, order, 6, q=p)\n",
"\n",
"print(test_pairing == pairing_val or test_pairing == 1/pairing_val)\n",
"\n",
"key_data = 0\n",
"\n",
"for i in range(len(h1_bases) - 1, 0, -1):\n",
" key_data *= h1_bases[i]\n",
" key_data += h1_coeffs[i]\n",
" print(h1_bases[i], h1_coeffs[i], key_data)\n",
"\n",
"pid = (key_data & ((1 << 31) - 1)) >> 1"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.0",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

159
extras/tspkgen.py Normal file
View File

@ -0,0 +1,159 @@
from Crypto.Cipher import ARC4
from hashlib import sha1, md5
from random import randint
from ecutils.core import Point, EllipticCurve
from sys import argv
KCHARS = "BCDFGHJKMPQRTVWXY2346789"
SPK_ECKEY = {
"a": 1,
"b": 0,
"g": {
"x": 10692194187797070010417373067833672857716423048889432566885309624149667762706899929433420143814127803064297378514651,
"y": 14587399915883137990539191966406864676102477026583239850923355829082059124877792299572208431243410905713755917185109
},
"n": 629063109922370885449,
"p": 21782971228112002125810473336838725345308036616026120243639513697227789232461459408261967852943809534324870610618161,
"priv": 153862071918555979944,
"pub": {
"x": 3917395608307488535457389605368226854270150445881753750395461980792533894109091921400661704941484971683063487980768,
"y": 8858262671783403684463979458475735219807686373661776500155868309933327116988404547349319879900761946444470688332645
}
}
LKP_ECKEY = {
"a": 1,
"b": 0,
"g": {
"x": 18999816458520350299014628291870504329073391058325678653840191278128672378485029664052827205905352913351648904170809,
"y": 7233699725243644729688547165924232430035643592445942846958231777803539836627943189850381859836033366776176689124317
},
"n": 675048016158598417213,
"p": 28688293616765795404141427476803815352899912533728694325464374376776313457785622361119232589082131818578591461837297,
"priv": 100266970209474387075,
"pub": {
"x": 7147768390112741602848314103078506234267895391544114241891627778383312460777957307647946308927283757886117119137500,
"y": 20525272195909974311677173484301099561025532568381820845650748498800315498040161314197178524020516408371544778243934
}
}
def encode_pkey(n):
out = ""
while n > 0:
out = KCHARS[n % 24] + out
n //= 24
out = "-".join([out[i:i+5] for i in range(0, len(out), 5)])
return out
def decode_pkey(k):
k = k.replace("-", "")
out = 0
for c in k:
out *= 24
out += KCHARS.index(c)
return out
def int_to_bytes(n, l=None):
n = int(n)
if not l:
l = (n.bit_length() + 7) // 8
return n.to_bytes(l, byteorder="little")
def make_curve(curve_def):
G = Point(x=curve_def["g"]["x"], y=curve_def["g"]["y"])
K = Point(x=curve_def["pub"]["x"], y=curve_def["pub"]["y"])
E = EllipticCurve(p=curve_def["p"], a=curve_def["a"], b=curve_def["b"], G=G, n=curve_def["n"], h=1)
return E, G, K
def get_spkid(pid):
spkid_s = pid[10:16] + pid[18:23]
return int(spkid_s.split("-")[0])
def validate_tskey(pid, tskey, is_spk=True):
keydata = decode_pkey(tskey).to_bytes(21, "little")
rk = md5(pid.encode("utf-16-le")).digest()[:5] + b"\x00" * 11
c = ARC4.new(rk)
dc_kdata = c.decrypt(keydata)
keydata = dc_kdata[:7]
sigdata = int.from_bytes(dc_kdata[7:], "little")
h = sigdata & 0x7ffffffff
s = (sigdata >> 35) & 0x1fffffffffffffffff
params = SPK_ECKEY if is_spk else LKP_ECKEY
E, G, K = make_curve(params)
R = E.add_points(E.multiply_point(h, K), E.multiply_point(s, G))
md = sha1(keydata + int_to_bytes(R.x, 48) + int_to_bytes(R.y, 48)).digest()
ht = ((int.from_bytes(md[4:8], "little") >> 29) << 32) | (int.from_bytes(md[:4], "little"))
spkid = int.from_bytes(keydata, "little") & 0x1FFFFFFFFF
return h == ht and (not is_spk or spkid == get_spkid(pid))
def generate_tskey(pid, keydata, is_spk=True):
params = SPK_ECKEY if is_spk else LKP_ECKEY
priv = SPK_ECKEY["priv"] if is_spk else LKP_ECKEY["priv"]
E, G, K = make_curve(params)
s = 0
while True:
c = randint(1, E.n - 1)
R = E.multiply_point(c, G)
md = sha1(keydata + int_to_bytes(R.x, 48) + int_to_bytes(R.y, 48)).digest()
h = ((int.from_bytes(md[4:8], "little") >> 29) << 32) | (int.from_bytes(md[:4], "little"))
s = ((-priv * h + c) % E.n) & 0x1fffffffffffffffff
keyinf = int.from_bytes(keydata, "little")
pkdata = ((s << 91) | (h << 56) | keyinf).to_bytes(21, "little")
rk = md5(pid.encode("utf-16-le")).digest()[:5] + b"\x00" * 11
c = ARC4.new(rk)
pke = c.encrypt(pkdata)[:20]
pk = int.from_bytes(pke, "little")
pkstr = encode_pkey(pk)
if s < 0x1fffffffffffffff and validate_tskey(pid, pkstr, is_spk):
return pkstr
def generate_spk(pid):
spkid = get_spkid(pid)
spkdata = spkid.to_bytes(7, "little")
return generate_tskey(pid, spkdata)
def generate_lkp(pid, count, major_ver, minor_ver, chid):
version = 1
if (major_ver == 5 and minor_ver > 0) or major_ver > 5:
version = (major_ver << 3) | minor_ver
lkpinfo = (chid << 46) | (count << 32) | (2 << 18) | (144 << 10) | (version << 3)
lkpdata = lkpinfo.to_bytes(7, "little")
return generate_tskey(pid, lkpdata, False)
if __name__ == "__main__":
if len(argv) == 2:
pid = argv[1]
print(f"License Server ID: {generate_spk(pid)}")
elif len(argv) == 5:
pid = argv[1]
count = int(argv[2])
ver_major, ver_minor = map(int, argv[3].split("."))
chid = int(argv[4])
print(f"License Key Pack ID: {generate_lkp(pid, count, ver_major, ver_minor, chid)}")
else:
print(f"Usage: {argv[0]} <pid> [<count> <version> <chid>]")
print(f"Example: {argv[0]} 00490-92005-99454-AT527 1234 10.3 32")

526
extras/winxp_act.ipynb Normal file
View File

@ -0,0 +1,526 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Product Key Generator - Windows XP"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Paste JSON object for BINK data here:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Windows XP Professional Retail (Bink ID 2C)\n",
"key_data = {\n",
" \"p\": 24412280675538104642884792561502783185577987209710041026341163083973933860854736635268965257725055809364646140091249,\n",
" \"a\": 1,\n",
" \"b\": 0,\n",
" \"B\": [\n",
" 21673361717619259910600499419800485528178801849923454062050055236231939594233283543796077751210469045350919066368895,\n",
" 5232476492611604888729825305639232005017822876108144652169892952989580351454246958886421453535493897842819359154864\n",
" ],\n",
" \"K\": [\n",
" 21551722775458524408480112576069559265917312687549112053580919391285918530584174752292844347621326558272739603979057,\n",
" 13463977158522661542654520438933687107907187215503371589980428235633526671841388652148099285621876350916055100879930\n",
" ],\n",
" \"order\": 55681564377333977,\n",
" \"private_key\": 30951839223306173\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run this cell to generate key"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"import hashlib\n",
"\n",
"# p = order of field Fp\n",
"# Fp = Galois field of order p\n",
"# E = Elliptic curve y^2 = x^3 + ax + b over Fp\n",
"# B = generator on E\n",
"# K = inverse of public key\n",
"# order = order of E\n",
"\n",
"p = key_data[\"p\"]\n",
"Fp = GF(p)\n",
"E = EllipticCurve(Fp, [0, 0, 0, key_data[\"a\"], key_data[\"b\"]])\n",
"B = E.point(key_data[\"B\"])\n",
"K = E.point(key_data[\"K\"])\n",
"order = key_data[\"order\"]\n",
"private_key = -key_data[\"private_key\"] % order\n",
"\n",
"# PID of product key\n",
"pid = 756_696969\n",
"\n",
"# Key alphabet\n",
"KCHARS = \"BCDFGHJKMPQRTVWXY2346789\"\n",
"\n",
"def int_to_bytes(n, l=None):\n",
" n = int(n)\n",
" \n",
" if not l:\n",
" l = (n.bit_length() + 7) // 8\n",
" \n",
" return n.to_bytes(l, byteorder=\"little\")\n",
"\n",
"def encode_pkey(n):\n",
" out = \"\"\n",
" \n",
" while n > 0:\n",
" out = KCHARS[n % 24] + out\n",
" n //= 24\n",
" \n",
" out = \"-\".join([out[i:i+5] for i in range(0, len(out), 5)])\n",
" return out\n",
"\n",
"pid <<= 1\n",
"\n",
"while True:\n",
" k = getrandbits(384)\n",
" r = k * B\n",
" x, y = r.xy()\n",
"\n",
" md = hashlib.sha1(int_to_bytes(pid, 4) + int_to_bytes(x, 48) + int_to_bytes(y, 48)).digest()\n",
" h = int.from_bytes(md[:4], byteorder=\"little\") >> 4\n",
" h &= 0xfffffff\n",
"\n",
" s = int(abs((private_key * h + k) % order))\n",
" raw_pkey = s << 59 | h << 31 | pid\n",
" \n",
" print(hex(pid)[2:], hex(h)[2:], hex(s)[2:], hex(raw_pkey)[2:])\n",
" \n",
" if raw_pkey >> 96 < 0x40000:\n",
" break\n",
"\n",
"print(encode_pkey(raw_pkey))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Key decoder (run above cell first)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"def decode_pkey(k):\n",
" k = k.replace(\"-\", \"\")\n",
" out = 0\n",
" \n",
" for c in k:\n",
" out *= 24\n",
" out += KCHARS.index(c)\n",
" \n",
" return out\n",
"\n",
"pkey = input(\"Product Key (dashes optional): \")\n",
"raw_pkey = decode_pkey(pkey)\n",
"\n",
"kpid = (raw_pkey & 0x7fffffff) >> 1\n",
"verify = (kpid // 1000000) == ((pid >> 1) // 1000000)\n",
"print(kpid, pid >> 1)\n",
"\n",
"if verify:\n",
" h = (raw_pkey >> 31) & 0xfffffff\n",
" s = (raw_pkey >> 59) & 0x7ffffffffffffff\n",
"\n",
" r = h * K + s * B\n",
" x, y = r.xy()\n",
"\n",
" md = hashlib.sha1(int_to_bytes(kpid << 1, 4) + int_to_bytes(x, 48) + int_to_bytes(y, 48)).digest()\n",
" hp = int.from_bytes(md[:4], byteorder=\"little\") >> 4\n",
" hp &= 0xfffffff\n",
"\n",
" print(h, hp)\n",
" \n",
" if h == hp:\n",
" print(\"Valid key\")\n",
" else:\n",
" print(\"Invalid key\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Confirmation ID generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import hashlib\n",
"\n",
"# order of field Fp \n",
"p = 0x16A6B036D7F2A79\n",
"# Galois field of order p\n",
"Fp = GF(p)\n",
"# Polynomial field Fp[x] over Fp\n",
"Fpx.<x> = Fp[]\n",
"# Hyperellptic curve function\n",
"F = x^5+0x1400606322B3B04*x^4+0x1400606322B3B04*x^3+0x44197B83892AD0*x^2+0x21840136C85381*x\n",
"# Hyperelliptic curve E: y^2 = F(x) over Fp\n",
"E = HyperellipticCurve(F)\n",
"# The jacobian over E\n",
"J = E.jacobian()\n",
"\n",
"# This constant inverts multiplication by 0x1001 in verification\n",
"# My best guess for how it was calculated: INV = 0x10001^-1 (mod |J|)\n",
"# |J| is hard to compute, how can we calculate for other curves?\n",
"INV = 0x40DA7C36D44C04E21B9D10F127C1\n",
"\n",
"# Key to decrypt installation IDs\n",
"IID_KEY = b'\\x6A\\xC8\\x5E\\xD4'\n",
"\n",
"# Validate installation ID checksum\n",
"def validate_cksum(n):\n",
" print(\"Checksumming installation ID...\")\n",
" n = n.replace(\"-\", \"\")\n",
"\n",
" cksum = 0\n",
" for i, k in enumerate(map(int, n)):\n",
" if (i + 1) % 6 == 0 or i == len(n) - 1:\n",
" print(\"Expected last digit\", cksum % 7, \"got\", k)\n",
" if cksum % 7 != k:\n",
" return None\n",
" \n",
" cksum = 0\n",
" else:\n",
" cksum += k * (i % 2 + 1)\n",
" \n",
" parts = [n[i:i+5] for i in range(0, len(n), 6)]\n",
" n_out = \"\".join(parts)\n",
" \n",
" if len(n_out) == 42:\n",
" n_out = n_out[:-1]\n",
" \n",
" if len(n_out) != 45 and len(n_out) != 41:\n",
" return None\n",
" \n",
" return int(\"\".join(parts))\n",
"\n",
"# Insert checksum digits into confirmation ID\n",
"def add_cksum(n):\n",
" cksums = []\n",
" n = str(n).zfill(35)\n",
" parts = [n[i:i+5] for i in range(0, len(n), 5)]\n",
" \n",
" for p in parts:\n",
" cksum = 0\n",
" \n",
" for i, k in enumerate(map(int, p)):\n",
" cksum += k * (i % 2 + 1)\n",
" \n",
" cksums.append(str(cksum % 7))\n",
" \n",
" n_out = \"\"\n",
" \n",
" for i in range(7):\n",
" n_out += parts[i] + cksums[i] + (\"-\" if i != 6 else \"\")\n",
" \n",
" return n_out\n",
"\n",
"def encrypt(decrypted, key):\n",
" size_half = len(decrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = decrypted[size_half*2:]\n",
" decrypted = decrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = decrypted[:size_half]\n",
" second = decrypted[size_half:]\n",
" sha1_result = hashlib.sha1(second + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" decrypted = second + bytes(x^^y for x,y in zip(first, sha1_result))\n",
" return decrypted + last\n",
"\n",
"def decrypt(encrypted, key):\n",
" size_half = len(encrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = encrypted[size_half*2:]\n",
" encrypted = encrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = encrypted[:size_half]\n",
" second = encrypted[size_half:]\n",
" sha1_result = hashlib.sha1(first + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" encrypted = bytes(x^^y for x,y in zip(second, sha1_result)) + first\n",
" return encrypted + last\n",
"\n",
"# Find v of divisor (u, v) of curve y^2 = F(x)\n",
"def find_v(u):\n",
" f = F % u\n",
" c2 = u[1]^2 - 4 * u[0]\n",
" c1 = 2 * f[0] - f[1] * u[1]\n",
" \n",
" if c2 == 0:\n",
" if c1 == 0:\n",
" return None\n",
" \n",
" try:\n",
" v1 = sqrt(f[1]^2 / (2 * c1))\n",
" v1.lift()\n",
" except:\n",
" return None\n",
" else:\n",
" try:\n",
" d = 2 * sqrt(f[0]^2 + f[1] * (f[1] * u[0] - f[0] * u[1]))\n",
" v1_1 = sqrt((c1 - d)/c2)\n",
" v1_2 = sqrt((c1 + d)/c2)\n",
" except:\n",
" return None\n",
"\n",
" try:\n",
" v1_1.lift()\n",
" v1 = v1_1\n",
" except:\n",
" try:\n",
" v1_2.lift()\n",
" v1 = v1_2\n",
" except:\n",
" return None\n",
" \n",
" v0 = (f[1] + u[1] * v1^2) / (2 * v1)\n",
" v = v0 + v1 * x\n",
" \n",
" assert (v^2 - f) % u == 0\n",
" return v\n",
"\n",
"# unpack&decrypt installationId\n",
"installationId = validate_cksum(input(\"Installation ID (dashes optional): \"))\n",
"print(installationId)\n",
"\n",
"if not installationId:\n",
" raise Exception(\"Invalid Installation ID (checksum fail)\")\n",
"\n",
"installationIdSize = 19 if len(str(installationId)) > 41 else 17 # 17 for XP Gold, 19 for SP1+ (includes 12 bits of sha1(product key))\n",
"iid = int(installationId).to_bytes(installationIdSize, byteorder='little')\n",
"iid = decrypt(iid, IID_KEY)\n",
"hwid = iid[:8]\n",
"productid = int.from_bytes(iid[8:17], byteorder='little')\n",
"productkeyhash = iid[17:]\n",
"pid1 = productid & ((1 << 17) - 1)\n",
"pid2 = (productid >> 17) & ((1 << 10) - 1)\n",
"pid3 = (productid >> 27) & ((1 << 25) - 1)\n",
"version = (productid >> 52) & 7\n",
"pid4 = productid >> 55\n",
"\n",
"assert version == (4 if len(iid) == 17 else 5)\n",
"\n",
"key = hwid + int((pid1 << 41 | pid2 << 58 | pid3 << 17 | pid4) & ((1 << 64) - 1)).to_bytes(8, byteorder='little')\n",
"\n",
"data = [0x00] * 14\n",
"\n",
"print(\"\\nConfirmation IDs:\")\n",
"\n",
"for i in range(0x81):\n",
" data[7] = i\n",
" # Encrypt conf ID, find u of divisor (u, v)\n",
" encrypted = encrypt(bytes(data), key)\n",
" encrypted = int.from_bytes(encrypted, byteorder=\"little\")\n",
" x1, x2 = Fp(encrypted % p), Fp((encrypted // p) + 1)\n",
" u1, u0 = x1 * 2, (x1 ^ 2) - ((x2 ^ 2) * 43)\n",
" u = x^2 + u1 * x + u0\n",
"\n",
" # Generate original divisor\n",
" v = find_v(u)\n",
" \n",
" if not v:\n",
" continue\n",
" \n",
" d2 = J(u, v)\n",
" divisor = d2 * INV\n",
" \n",
" # Get x1 and x2\n",
" roots = [x for x, y in divisor[0].roots()]\n",
"\n",
" if len(roots) > 0:\n",
" y = [divisor[1](r) for r in roots]\n",
" x1 = (-roots[0]).lift()\n",
" x2 = (-roots[1]).lift()\n",
"\n",
" if (x1 > x2) or (y[0].lift() % 2 != y[1].lift() % 2):\n",
" x1 = (-roots[1]).lift()\n",
" x2 = (-roots[0]).lift()\n",
" else:\n",
" x2 = (divisor[0][1] / 2).lift()\n",
" x1 = sqrt((x2^2 - divisor[0][0]) / 43).lift() + p\n",
"\n",
" # Win\n",
" conf_id = x1 * (p + 1) + x2\n",
" conf_id = add_cksum(conf_id)\n",
" print(conf_id)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Confirmation ID decoder/validator (made by diamondggg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import hashlib\n",
"\n",
"# 226512-274743-842923-777124-961370-722240-570042-517722-757426\n",
"installationId = 114535500880440159787527912804896629001083118\n",
"installationIdSize = 19 # 17 for XP Gold, 19 for SP1+ (includes 12 bits of sha1(product key))\n",
"# all three of following are valid generated\n",
"# 013705-060122-603141-961392-086136-909901-494476\n",
"confirmationId = 15771960290497900806797040541467113\n",
"# 022032-220754-159721-909624-985141-504586-914001\n",
"#confirmationId = 02203220751597290962985145045891400\n",
"# 137616-847280-708585-827476-874935-313366-790880\n",
"#confirmationId = 13761847287085882747874933133679088\n",
"\n",
"def decrypt(encrypted, key):\n",
" size_half = len(encrypted) // 2\n",
" size_half_dwords = size_half - (size_half % 4)\n",
" last = encrypted[size_half*2:]\n",
" encrypted = encrypted[:size_half*2]\n",
" for i in range(4):\n",
" first = encrypted[:size_half]\n",
" second = encrypted[size_half:]\n",
" sha1_result = hashlib.sha1(first + key).digest()\n",
" sha1_result = (sha1_result[:size_half_dwords] +\n",
" sha1_result[size_half_dwords+4-(size_half%4) : size_half+4-(size_half%4)])\n",
" encrypted = bytes(x^^y for x,y in zip(second, sha1_result)) + first\n",
" return encrypted + last\n",
"\n",
"# unpack&decrypt installationId\n",
"iid = int(installationId).to_bytes(installationIdSize, byteorder='little')\n",
"iid = decrypt(iid, b'\\x6A\\xC8\\x5E\\xD4')\n",
"hwid = iid[:8]\n",
"productid = int.from_bytes(iid[8:17], byteorder='little')\n",
"productkeyhash = iid[17:]\n",
"pid1 = productid & ((1 << 17) - 1)\n",
"pid2 = (productid >> 17) & ((1 << 10) - 1)\n",
"pid3 = (productid >> 27) & ((1 << 25) - 1)\n",
"version = (productid >> 52) & 7\n",
"pid4 = productid >> 55\n",
"\n",
"assert version == (4 if len(iid) == 17 else 5)\n",
"\n",
"key = hwid + int((pid1 << 41 | pid2 << 58 | pid3 << 17 | pid4) & ((1 << 64) - 1)).to_bytes(8, byteorder='little')\n",
"# productkeyhash is not used for validation, it exists just to allow the activation server to reject keygenned pids\n",
"\n",
"# now the math\n",
"\n",
"p = 0x16A6B036D7F2A79\n",
"Fp = GF(p)\n",
"Fpx.<x> = Fp[]\n",
"E = HyperellipticCurve(x^5+0x1400606322B3B04*x^4+0x1400606322B3B04*x^3+0x44197B83892AD0*x^2+0x21840136C85381*x)\n",
"J = E.jacobian()\n",
"\n",
"# deserialize divisor\n",
"x1 = confirmationId // (p + 1)\n",
"x2 = confirmationId % (p + 1)\n",
"if x1 <= p:\n",
" # two or less points over GF(p)\n",
" point1 = E.lift_x(Fp(-x1)) if x1 != p else None\n",
" point2 = E.lift_x(Fp(-x2)) if x2 != p else None\n",
" if point1 is not None and point2 is not None:\n",
" # there are 4 variants of how lift_x() could select both y-s\n",
" # we don't distinguish D and -D, but this still leaves 2 variants\n",
" # the chosen one is encoded by order of x1 <=> x2\n",
" lastbit1 = point1[1].lift() & 1\n",
" lastbit2 = point2[1].lift() & 1\n",
" if x2 < x1:\n",
" if lastbit1 == lastbit2:\n",
" point2 = E(point2[0], -point2[1])\n",
" else:\n",
" if lastbit1 != lastbit2:\n",
" point2 = E(point2[0], -point2[1])\n",
" point1 = J(point1) if point1 is not None else J(0)\n",
" point2 = J(point2) if point2 is not None else J(0)\n",
" divisor = point1 + point2\n",
"else:\n",
" # a pair of conjugate points over GF(p^2)\n",
" f = (x+x2)*(x+x2)-43*x1*x1 # 43 is the minimal quadratic non-residue in Fp\n",
" Fp2 = GF(p^2)\n",
" point1 = E.lift_x(f.roots(Fp2)[0][0])\n",
" point2 = E(Fp2)(point1[0].conjugate(), point1[1].conjugate())\n",
" divisor = J(Fp2)(point1) + J(Fp2)(point2)\n",
" divisor = J(Fpx(divisor[0]), Fpx(divisor[1])) #return from Fp2 to Fp\n",
"\n",
"d2 = divisor * 0x10001\n",
"assert d2[0].degree() == 2\n",
"x1 = d2[0][1]/2\n",
"x2 = sqrt((x1*x1-d2[0][0])/43)\n",
"\n",
"encrypted = x1.lift() + (x2.lift() - 1) * p\n",
"encrypted = int(encrypted).to_bytes(14,byteorder='little')\n",
"\n",
"# end of the math\n",
"decrypted = decrypt(encrypted, key)\n",
"print(decrypted.hex())\n",
"# 0000000000000001000000000000 for the first confirmationId\n",
"# 0000000000000002000000000000 for the second confirmationId\n",
"# 0000000000000006000000000000 for the last confirmationId\n",
"assert decrypted[8:] == b'\\0' * 6\n",
"assert decrypted[7] <= 0x80\n",
"# all zeroes in decrypted[0:7] are okay for the checker\n",
"# more precisely: if decrypted[6] == 0, first 6 bytes can be anything\n",
"# otherwise, decrypted[0] = length, and decrypted[1:1+length] must match first length bytes of sha1(product key)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.0",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,267 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# From Longhorn 4074\n",
"# Any version that accepts TCP8W-T8PQJ-WWRRH-QH76C-99FBW will work\n",
"key_data = {\n",
" \"p\": 7181106593102322766813520532476531209871483588988471009176871145241389568314039093657656718839885029493125387894856821599452867350054864568294961595970889,\n",
" \"a\": 1,\n",
" \"b\": 0,\n",
" \"B\": [\n",
" 520282615406607935808830413235837609227529008118239433194891765554084261177667142590192616462797266047427714603514505726507565809100858610756034340614180,\n",
" 4557046395510954851157569206449480560848332315791566919607580280750304632075435589109908909351625686398512699199297926705742962219032991805095344264722444\n",
" ],\n",
" \"K\": [\n",
" 1748427561645745685508888890965804844329037567281415535239953290167653001827496844268667372126127464466687812723744919132659150838866693283679107969476861,\n",
" 6808711632346399211426562555523956018872055718394662707289722207520029794097689415773036615424757895159410496488301598927496012713658489637493990459415502\n",
" ],\n",
" \"order\": 4633201844252750473,\n",
" \"private_key\": 4329540238250287790\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Product Key Generator, run above cell first"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10928323 10928323 2003509697754295848 6615195716181683752\n",
"868186915 868186915 878552257861989116 5490238276289377020\n",
"446954708 446954708 776512975037445878 776512975037445878\n",
"353785506 353785506 1772257197849916146 6383943216277304050\n",
"1598465793 1598465793 385978941068063200 4997664959495451104\n",
"1118655069 1118655069 374356218385227934 374356218385227934\n",
"52 531faff484f609e 42ad525d d2\n",
"CH89R-TPQRK-GPJMW-7KTYQ-F8PJD\n"
]
}
],
"source": [
"import hashlib\n",
"\n",
"# p = order of field Fp\n",
"# Fp = Galois field of order p\n",
"# E = Elliptic curve y^2 = x^3 + ax + b over Fp\n",
"# B = generator on E\n",
"# K = inverse of public key\n",
"# order = order of E\n",
"# Ro = Ring Z/orderZ\n",
"\n",
"p = key_data[\"p\"]\n",
"Fp = GF(p)\n",
"E = EllipticCurve(Fp, [0, 0, 0, key_data[\"a\"], key_data[\"b\"]])\n",
"B = E.point(key_data[\"B\"])\n",
"K = E.point(key_data[\"K\"])\n",
"order = key_data[\"order\"]\n",
"Ro = Integers(order)\n",
"private_key = -key_data[\"private_key\"] % order\n",
"\n",
"# OS Family of product key\n",
"# x64 VLK - 652\n",
"# x64 Retail - 306\n",
"os_family = 105\n",
"\n",
"# Key alphabet\n",
"KCHARS = \"BCDFGHJKMPQRTVWXY2346789\"\n",
"\n",
"def int_to_bytes(n, l=None):\n",
" n = int(n)\n",
" \n",
" if not l:\n",
" l = (n.bit_length() + 7) // 8\n",
" \n",
" return n.to_bytes(l, byteorder=\"little\")\n",
"\n",
"def encode_pkey(n):\n",
" out = \"\"\n",
" \n",
" for i in range(25):\n",
" out = KCHARS[n % 24] + out\n",
" n //= 24\n",
" \n",
" out = \"-\".join([out[i:i+5] for i in range(0, len(out), 5)])\n",
" return out\n",
"\n",
"os_family <<= 1\n",
"\n",
"while True:\n",
" k = getrandbits(512)\n",
" prefix = getrandbits(32) & 0x3ff\n",
" \n",
" r = k * B\n",
" x, y = r.xy()\n",
"\n",
" mde = hashlib.sha1(b\"\\x79\" + int_to_bytes(os_family, 2) + int_to_bytes(x, 64) + int_to_bytes(y, 64)).digest()\n",
" e = int.from_bytes(mde[:4], byteorder=\"little\")\n",
" e &= 0x7fffffff\n",
" \n",
" mdh = hashlib.sha1(b\"\\x5d\" + int_to_bytes(os_family, 2) + int_to_bytes(e, 4) + int_to_bytes(prefix, 4)).digest()\n",
" h1 = int.from_bytes(mdh[:4], byteorder=\"little\")\n",
" h2 = int.from_bytes(mdh[4:8], byteorder=\"little\") >> 2\n",
" h2 &= 0x3fffffff\n",
" h = h2 << 32 | h1\n",
" b = Ro(-h * private_key)\n",
" \n",
" try:\n",
" s = Ro(b)\n",
" s = int((-b + sqrt(b^2 + 4 * Ro(k))) / 2)\n",
" except:\n",
" continue\n",
" \n",
" if s % 2 == 1:\n",
" s += order\n",
" \n",
" if (s * (s * B + h * K)) != (s * (s * B + int(b) * B)):\n",
" continue\n",
" \n",
" raw_pkey = prefix << 104 | s << 42 | e << 11 | os_family\n",
" \n",
" print((raw_pkey >> 11) & 0x7fffffff, e, (raw_pkey >> 42) & 0x3fffffffffffffff, s)\n",
" \n",
" # I could fix whatever bug made this necessary, but it works so I don't care\n",
" if ((raw_pkey >> 11) & 0x7fffffff) != e or ((raw_pkey >> 42) & 0x3fffffffffffffff) != s:\n",
" continue\n",
" \n",
" if (raw_pkey >> 32) & 0xffffffff < 0x40000000:\n",
" break\n",
"\n",
"print(hex(prefix)[2:], hex(s)[2:], hex(e)[2:], hex(os_family)[2:])\n",
"print(encode_pkey(raw_pkey))\n",
"pkey = encode_pkey(raw_pkey)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Product Key Verifier (must run above cell first)"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Product Key (dashes optional): TCP8W-T8PQJ-WWRRH-QH76C-99FBW\n",
"TCP8W-T8PQJ-WWRRH-QH76C-99FBW\n",
"318 3e550ae1709773d8 6674d45a ce\n",
"f0ce4281d7695e3\n",
"110001100011111001010101000010101110000101110000100101110111001111011000110011001110100110101000101101000011001110\n",
"110001100011111001010101000010101110000101110000100101110111001111011000110011001110100110101000101101000011001110\n",
"1718932570 1718932570 True\n"
]
}
],
"source": [
"def decode_pkey(k):\n",
" k = k.replace(\"-\", \"\")\n",
" out = 0\n",
" \n",
" for c in k:\n",
" out *= 24\n",
" out += KCHARS.index(c)\n",
" \n",
" return out\n",
"\n",
"pkey = input(\"Product Key (dashes optional): \")\n",
"print(pkey)\n",
"raw_key = decode_pkey(pkey)\n",
"\n",
"osf = raw_key & 0x7ff\n",
"e = (raw_key >> 11) & 0x7fffffff\n",
"s = (raw_key >> 42) & 0x3fffffffffffffff\n",
"pf = (raw_key >> 104) & 0x3ff\n",
"\n",
"mdh = hashlib.sha1(b\"\\x5d\" + int_to_bytes(osf, 2) + int_to_bytes(e, 4) + int_to_bytes(pf, 4)).digest()\n",
"h1 = int.from_bytes(mdh[:4], byteorder=\"little\")\n",
"h2 = int.from_bytes(mdh[4:8], byteorder=\"little\") >> 2\n",
"h2 &= 0x3fffffff\n",
"h = h2 << 32 | h1\n",
"\n",
"print(hex(pf)[2:], hex(s)[2:], hex(e)[2:], hex(osf)[2:])\n",
"print(hex(h)[2:])\n",
"print(bin(raw_key)[2:])\n",
"print(bin(pf << 104 | s << 42 | e << 11 | osf)[2:])\n",
"\n",
"v = s * (s * B + h * K)\n",
"x, y = v.xy()\n",
"\n",
"mde = hashlib.sha1(b\"\\x79\" + int_to_bytes(osf, 2) + int_to_bytes(x, 64) + int_to_bytes(y, 64)).digest()\n",
"ep = int.from_bytes(mde[:4], byteorder=\"little\")\n",
"ep &= 0x7fffffff\n",
"\n",
"print(e, ep, e == ep)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"71"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"0x8e/2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "SageMath 9.0",
"language": "sage",
"name": "sagemath"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

109
keys.json
View File

@ -33,6 +33,9 @@
"Commerce Server 2002": {
"BINK": ["0E", "0F"]
},
"Passport Manager": {
"BINK": ["10"]
},
"Windows 2000 Professional": {
"BINK": ["12", "13"]
},
@ -45,6 +48,9 @@
"Office XP Applications": {
"BINK": ["20", "21"]
},
"Works Suite 2003 and 2004": {
"BINK": ["20", "21"]
},
"Office XP": {
"BINK": ["22", "23"]
},
@ -117,18 +123,27 @@
"Office 2003 Small Business": {
"BINK": ["70", "71"]
},
"Office 2003 Student and Teacher": {
"BINK": ["70", "71"]
},
"Office 2003 Professional": {
"BINK": ["72", "73"]
},
"Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)": {
"BINK": ["74", "75"]
},
"Expression Web 2007 / Sharepoint Server 2007": {
"BINK": ["76", "77"]
},
"Identity Lifecycle Manager 2007": {
"BINK": ["78", "79"]
},
"Visual Studio 2008": {
"BINK": ["78", "79"]
},
"Sharepoint Designer 2007": {
"BINK": ["7C", "7D"]
},
"Office 2007 Applications": {
"BINK": ["7E", "7F"]
},
@ -138,6 +153,9 @@
"Office 2007 Standard / Professional / Ultimate / Enterprise": {
"BINK": ["82", "83"]
},
"Office 2007 Hybrid": {
"BINK": ["84", "85"]
},
"Office 2007 Home & Student": {
"BINK": ["88", "89"]
}
@ -312,15 +330,15 @@
"a": "1",
"b": "0",
"g": {
"x": "17272533675023793624680016937607161394427776688401278127884215858369066406365237833207419170117031265147050748737186",
"y": "10897684556651576571671151674586120690608236542740270859915076272932083320838022698730208293779451126638581586588925"
"x": "2424861453756882196229359499252409442096928108454123044238107428456451053748664006504056679987776648547354283230029",
"y": "7324425970176151969116486392910180591819760394015255323965851504893617199075285355320677185484219270306349221725496"
},
"n": "44682719955829289",
"p": "31123778862031392435299439090755153401162704597024288571183830527113563344679315725116915983118187065183839828632113",
"priv": "30177475288172038",
"n": "42173753096150573",
"p": "23576896825148261563986794905854575022252138407149635186332207102431578828005131860154350053063599250972940889198609",
"priv": "21644128200478272",
"pub": {
"x": "10584120526089473026246191383792758367144927589909587205278073830223938861208553884400816982485323081066790399437204",
"y": "19710761542152200618172612283139324015316083022563473705358032993141026289202915973780473937312193485361804450068338"
"x": "22559965909720054111451558679234685221190121968477792217083519033370405738218408301652020048970098652944061723131120",
"y": "4867649293914467066273247931825593002116583959412689222356329515920397531410942846741846700237094219959206105155903"
}
},
"0C": {
@ -383,6 +401,21 @@
"y": "12300711937755714474221683340048792628817501853269187222732097530965245794898485391792926982501341822327927281168157"
}
},
"10": {
"a": "1",
"b": "0",
"g": {
"x": "18651628392962497698304079461858800038021595035623099589626558411789423821835513779530629747878048328422716050099296",
"y": "28457790016119433859033076174489680371110176047623886251847351799861435189214769185332948508935608870611015909181946"
},
"n": "63517138149940081",
"p": "34850883414891516310048088524473091032039735302322749072119923383901524249650054933039485488287948424536010614809529",
"priv": "42074657350570560",
"pub": {
"x": "14897248889444524585539298515527812307525445072093905045143283125792133561464628729391995919418984547359131800953862",
"y": "30590224388131521072842776697623219502924625149179219913459005347798492666726177600440842678766281012690402321113086"
}
},
"12": {
"a": "1",
"b": "0",
@ -773,6 +806,66 @@
"y": "4166331361209663080277908775030002767045551689443380649904104094047767422069625957190676222747168197864341871814070164924686453916110248521040648287862677"
}
},
"42": {
"a": "1",
"b": "0",
"g": {
"x": "11640071446359917693418230277272135573556102510768548148030840368465631925066661215750608051818744662399431859372010847799326485284550650513243041633181229",
"y": "1117219266737324272317290420713713230170128897725948728570838742460014554810962916878884036620621200355133560155042440959180864818213121429155138181344653"
},
"n": "5280334341756112909",
"p": "12942978066077029419384467090650680778545791198987839112733218154226202456650854446314697588718267646821306053679758777877942489272278682133825653213117273",
"priv": "1465309884720242143",
"pub": {
"x": "9351207863776380035890122409035060669425884047354848374635961783863142135448736359201437768670165682794001791952363648653230539557613342151297569318010149",
"y": "9639173047661422234418044696501057599355311018715184869788900265449733286127996011980477454425481367874466175535746037008129571512803245134460273061854442"
}
},
"43": {
"a": "1",
"b": "0",
"g": {
"x": "2834486376491690368456603825217677225471198398912779448345352642108764638231378782668499190157872740666167080466219457629252550710819781972327332131965258",
"y": "4797700757852014957418479446842892711716196864495788466729606301384034376631555735482572108714361434720650684534546885209233659101211883665277770145423350"
},
"n": "5523679238757269761",
"p": "6926191998299775557228051679990184107308003134668712746978570129316018332430570191924825301565850815568703875111335260944754577838427804555602564950786897",
"priv": "2809607843179400714",
"pub": {
"x": "5801087961280458909792080253947945286111446355062440146334723296822174085898835796467483513249817617372724731293482946799424523234786103045200852470225011",
"y": "1919606609989436277853545800995092035920586757555046809012910563836843544210421704301817498648513315478648381017523132165198480986231348796390852153074721"
}
},
"44": {
"a": "1",
"b": "0",
"g": {
"x": "9680658238923578678202657184293847763076151678383489086861167893944370179297511555508861816858010248459991161671607410772896973557285105910275482332653112",
"y": "38902477949345497450784597636513692713869581728781957101503157321110858542746905996206655102425053611084383171688496202957335182347019199622239575131319"
},
"n": "4714695763604443541",
"p": "10060218540908435736634173235406368357048589196592148828376201588591059234309957485052136941552686476146780926855972646273339825261674895471491324476121697",
"priv": "952494568445020851",
"pub": {
"x": "7809435572353033432542259944225681069776007713441000282689259450883474252378043956762041876078756182695744718782433033396721679522564745671507681698680124",
"y": "2120018000497598938986702274873490939171797105426386828711756267078880551570146718754825759969119264518218486103010877173921337418786732248062865348045969"
}
},
"45": {
"a": "1",
"b": "0",
"g": {
"x": "1415506028429814835609318901328901279725664469601609961018689628962980229383879276982285895935656882715108992785111554965336919510937749428526698965204901",
"y": "6142658768171534784725381543698447822724946469773052050322995135930968261406067031627504011235735426349765719550450476207341330596203075437382377459404055"
},
"n": "4705733954672224129",
"p": "8420779903875279756603065163346889837055414440294897668354571673595315405287353764209959201404596284932170027888535337670888642377481800445761115380269649",
"priv": "1845297747391977061",
"pub": {
"x": "5979408142886940137052651399684513359780629840102111793966097396623272737697258705143841606573133958717430112526043253582151662435203695216093728339267096",
"y": "3518591391911442753664238113448734968964864723243113225953452544472418473210828150121884867152997802156077007186900916060906287620287437578440526157889485"
}
},
"50": {
"a": "1",
"b": "0",
@ -1525,7 +1618,7 @@
}
},
"Activation": {
"Windowws XP": {
"Windows XP": {
"p": "102011604035381881",
"x": {
"0": "0",

View File

@ -22,6 +22,15 @@
#include "cli.h"
CLI::~CLI()
{
EC_GROUP_free(eCurve);
EC_POINT_free(genPoint);
EC_POINT_free(pubPoint);
BN_free(privateKey);
BN_free(genOrder);
}
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());
@ -53,11 +62,17 @@ void CLI::showHelp(char *argv[]) {
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-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n");
fmt::print("\t-l --list\tshow which products/binks can be loaded\n");
fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n");
fmt::print("\t-s --serial\tspecifies a serial to use in the product ID (defaults to random, BINK1998 only)\n");
fmt::print("\t-u --upgrade\tspecifies the Product Key will be an \"Upgrade\" version\n");
fmt::print("\t-V --validate\tproduct key to validate signature\n");
fmt::print("\t-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n");
fmt::print("\t-o --override\tDisables version check for confirmation IDs, if you need this send an issue on GitHub\n");
fmt::print("\t-D --nodashes\tDisables dashes in product keys and confirmation IDs (for easier copy-pasting)");
fmt::print("\n");
}
@ -68,6 +83,7 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
"",
"",
"",
"",
640,
0,
1,
@ -76,12 +92,16 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
false,
false,
false,
MODE_BINK1998_GENERATE
false,
false,
false,
false,
MODE_BINK1998_GENERATE,
WINDOWS
};
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg == "-v" || arg == "--verbose") {
options->verbose = true;
UMSKT::setDebugOutput(stderr);
@ -137,6 +157,8 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
options->serial = serial_val;
}
i++;
} else if (arg == "-u" || arg == "--upgrade") {
options->upgrade = true;
} else if (arg == "-f" || arg == "--file") {
if (i == argc - 1) {
options->error = true;
@ -154,6 +176,32 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
options->instid = argv[i+1];
options->applicationMode = MODE_CONFIRMATION_ID;
i++;
} else if (arg == "-m" || arg == "--mode") {
std::string mode = argv[i+1];
char *p = &mode[0];
for (; *p; p++) {
*p = toupper((unsigned char)*p);
}
p = &mode[0];
if (strcmp(p, "WINDOWS") == 0) {
options->activationMode = WINDOWS;
} else if (strcmp(p, "OFFICEXP") == 0) {
options->activationMode = OFFICE_XP;
} else if (strcmp(p, "OFFICE2K3") == 0) {
options->activationMode = OFFICE_2K3;
} else if (strcmp(p, "OFFICE2K7") == 0) {
options->activationMode = OFFICE_2K7;
} else if (strcmp(p, "PLUSDME") == 0) {
options->activationMode = PLUS_DME;
}
i++;
} else if (arg == "-p" || arg == "--productid") {
if (i == argc -1) {
options->error = true;
break;
}
options->productid = argv[i+1];
i++;
} else if (arg == "-V" || arg == "--validate") {
if (i == argc - 1) {
options->error = true;
@ -163,11 +211,23 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
options->keyToCheck = argv[i+1];
options->applicationMode = MODE_BINK1998_VALIDATE;
i++;
} else if (arg == "-N" || arg == "--nonewlines") {
options->nonewlines = true;
} else if (arg == "-o" || arg == "--override") {
options->overrideVersion = true;
} else if (arg == "-D" || arg == "--nodashes") {
options->nodashes = 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()) ) {
return options->error = true;
}
return !options->error;
}
@ -216,6 +276,12 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
int intBinkID;
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) {
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
return 1;
}
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;
@ -241,7 +307,7 @@ void CLI::printID(DWORD *pid) {
int i, digit = 0;
// Convert PID to ascii-number (=raw)
sprintf(raw, "%09u", pid[0]);
snprintf(raw, sizeof(raw), "%09u", pid[0]);
// Make b-part {640-....}
strncpy(b, raw, 3);
@ -265,9 +331,14 @@ void CLI::printID(DWORD *pid) {
void CLI::printKey(char *pk) {
assert(strlen(pk) >= PK_LENGTH);
std::string keyFormat = "{}-{}-{}-{}-{}";
if (this->options.nodashes == true) {
keyFormat = "{}{}{}{}{}";
}
std::string spk = pk;
fmt::print("{}-{}-{}-{}-{}",
fmt::print(keyFormat,
spk.substr(0,5),
spk.substr(5,5),
spk.substr(10,5),
@ -361,13 +432,14 @@ int CLI::BINK1998Generate() {
} 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);
UMSKT::umskt_bn_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
int oRaw;
char *cRaw = BN_bn2dec(bnrand);
sscanf(cRaw, "%d", &oRaw);
nRaw += (oRaw % 999999); // ensure our serial is less than 999999
BN_free(bnrand);
}
if (this->options.verbose) {
@ -379,11 +451,8 @@ int CLI::BINK1998Generate() {
// generate a key
BN_sub(this->privateKey, this->genOrder, this->privateKey);
// Specify whether an upgrade version or not
bool bUpgrade = false;
for (int i = 0; i < this->total; i++) {
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, bUpgrade, this->pKey);
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) {
@ -408,10 +477,9 @@ int CLI::BINK1998Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
}
@ -425,30 +493,28 @@ int CLI::BINK2002Generate() {
// generate a key
for (int i = 0; i < this->total; i++) {
DWORD pAuthInfo;
RAND_bytes((BYTE *)&pAuthInfo, 4);
UMSKT::umskt_rand_bytes((BYTE *)&pAuthInfo, 4);
pAuthInfo &= BITMASK(10);
if (this->options.verbose) {
fmt::print("> AuthInfo: {}\n", pAuthInfo);
}
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, false, this->pKey);
CLI::printKey(this->pKey);
fmt::print("\n");
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) {
CLI::printKey(this->pKey);
if (i < this->total - 1 || this->options.verbose) {
if (i < this->total - 1 || this->options.verbose) { // check if end of list or verbose
fmt::print("\n");
}
this->count += isValid;
this->count += isValid; // add to count
}
else {
if (this->options.verbose) {
CLI::printKey(this->pKey);
fmt::print(" [Invalid]");
if (i < this->total - 1) {
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("\n");
}
}
@ -459,9 +525,9 @@ int CLI::BINK2002Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
}
@ -506,7 +572,7 @@ int CLI::BINK2002Validate() {
int CLI::ConfirmationID() {
char confirmation_id[49];
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id);
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id, options.activationMode, options.productid, options.overrideVersion);
switch (err) {
case ERR_TOO_SHORT:
@ -534,10 +600,20 @@ int CLI::ConfirmationID() {
return 1;
case SUCCESS:
if (this->options.nodashes == true) {
int j = 0;
for (int i = 0; confirmation_id[i] != '\0'; ++i) {
if (confirmation_id[i] != '-') {
confirmation_id[j++] = confirmation_id[i];
}
}
confirmation_id[j] = '\0';
}
fmt::print(confirmation_id);
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
default:

View File

@ -36,6 +36,14 @@
CMRC_DECLARE(umskt);
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
};
enum MODE {
MODE_BINK1998_GENERATE = 0,
MODE_BINK2002_GENERATE = 1,
@ -49,16 +57,22 @@ struct Options {
std::string keysFilename;
std::string instid;
std::string keyToCheck;
std::string productid;
int channelID;
int serial;
int numKeys;
bool upgrade;
bool serialSet;
bool verbose;
bool help;
bool error;
bool list;
bool nonewlines;
bool overrideVersion;
bool nodashes;
MODE applicationMode;
ACTIVATION_ALGORITHM activationMode;
};
class CLI {
@ -73,13 +87,14 @@ class CLI {
public:
CLI(Options options, json keys);
~CLI();
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 void printID(DWORD *pid);
static void printKey(char *pk);
void printKey(char *pk);
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
int BINK1998Generate();

428
src/icon_LICENSE Normal file
View File

@ -0,0 +1,428 @@
Attribution-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@ -29,9 +29,26 @@
#include "confid.h"
#define MOD 0x16A6B036D7F2A79ULL
#define NON_RESIDUE 43
static const QWORD f[6] = {0, 0x21840136C85381ULL, 0x44197B83892AD0ULL, 0x1400606322B3B04ULL, 0x1400606322B3B04ULL, 1};
#if defined(_MSC_VER)
#include <intrin.h>
#endif
QWORD MOD = 0;
QWORD NON_RESIDUE = 0;
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
int productID[4];
int activationMode;
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;
}
QWORD ConfirmationID::residue_add(QWORD x, QWORD y)
{
@ -62,7 +79,13 @@ inline QWORD ConfirmationID::__umul128(QWORD a, QWORD b, QWORD* hi)
#else
#define __umul128 _umul128
#endif
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__)
#elif defined(_M_ARM64) // Microsoft implementation of ARM64
inline QWORD ConfirmationID::__umul128(QWORD a, QWORD b, QWORD* hi)
{
*hi = __umulh(a, b);
return a * b;
}
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__) || defined(_M_ARM)
inline QWORD ConfirmationID::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
@ -95,18 +118,65 @@ QWORD ConfirmationID::ui128_quotient_mod(QWORD lo, QWORD hi)
{
// hi:lo * ceil(2**170/MOD) >> (64 + 64 + 42)
QWORD prod1;
__umul128(lo, 0x604fa6a1c6346a87, &prod1);
switch (activationMode) {
case 0:
__umul128(lo, 0x604FA6A1C6346A87, &prod1);
break;
case 1:
case 2:
case 3:
__umul128(lo, 0x4FA8E4A40CDAE44A, &prod1);
break;
case 4:
__umul128(lo, 0x2C5C4D3654A594F0, &prod1);
}
QWORD part1hi;
QWORD part1lo = __umul128(lo, 0x2d351c6d04f8b, &part1hi);
QWORD part1lo;
switch (activationMode) {
case 0:
part1lo = __umul128(lo, 0x2D351C6D04F8B, &part1hi);
break;
case 1:
case 2:
case 3:
part1lo = __umul128(lo, 0x2CBAF12A59BBE, &part1hi);
break;
case 4:
part1lo = __umul128(lo, 0x2D36C691A4EA5, &part1hi);
}
QWORD part2hi;
QWORD part2lo = __umul128(hi, 0x604fa6a1c6346a87, &part2hi);
QWORD part2lo;
switch (activationMode) {
case 0:
part2lo = __umul128(hi, 0x604FA6A1C6346A87, &part2hi);
break;
case 1:
case 2:
case 3:
part2lo = __umul128(hi, 0x4FA8E4A40CDAE44A, &part2hi);
break;
case 4:
part2lo = __umul128(hi, 0x2C5C4D3654A594F0, &part2hi);
}
QWORD sum1 = part1lo + part2lo;
unsigned sum1carry = (sum1 < part1lo);
sum1 += prod1;
sum1carry += (sum1 < prod1);
QWORD prod2 = part1hi + part2hi + sum1carry;
QWORD prod3hi;
QWORD prod3lo = __umul128(hi, 0x2d351c6d04f8b, &prod3hi);
QWORD prod3lo;
switch (activationMode) {
case 0:
prod3lo = __umul128(hi, 0x2D351C6D04F8B, &prod3hi);
break;
case 1:
case 2:
case 3:
prod3lo = __umul128(hi, 0x2CBAF12A59BBE, &prod3hi);
break;
case 4:
prod3lo = __umul128(hi, 0x2D36C691A4EA5, &prod3hi);
}
prod3lo += prod2;
prod3hi += (prod3lo < prod2);
return (prod3lo >> 42) | (prod3hi << 22);
@ -619,6 +689,20 @@ void ConfirmationID::sha1_single_block(unsigned char input[64], unsigned char ou
output[16] = e >> 24; output[17] = e >> 16; output[18] = e >> 8; output[19] = e;
}
void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version)
{
QWORD buffer[5];
int i;
for (i = 0; i < 5; i++)
memcpy(&buffer[i], (iid + (4 * i)), 4);
DWORD v1 = (buffer[3] & 0xFFFFFFF8) | 2;
DWORD v2 = ((buffer[3] & 7) << 29) | (buffer[2] >> 3);
QWORD hardwareIDVal = ((QWORD)v1 << 32) | v2;
for (i = 0; i < 8; ++i)
hwid[i] = (hardwareIDVal >> (8 * i)) & 0xFF;
*version = buffer[0] & 7;
}
void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize)
{
unsigned char sha1_input[64];
@ -628,11 +712,25 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c
int external_counter;
for (external_counter = 0; external_counter < 4; external_counter++) {
memset(sha1_input, 0, sizeof(sha1_input));
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(sha1_input, buffer + half, half);
memcpy(sha1_input + half, key, keySize);
sha1_input[half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100;
break;
case 2:
case 3:
sha1_input[0] = 0x79;
memcpy(sha1_input + 1, buffer + half, half);
memcpy(sha1_input + 1 + half, key, keySize);
sha1_input[1 + half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
}
sha1_single_block(sha1_input, sha1_result);
size_t i;
for (i = half & ~3; i < half; i++)
@ -654,11 +752,25 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
int external_counter;
for (external_counter = 0; external_counter < 4; external_counter++) {
memset(sha1_input, 0, sizeof(sha1_input));
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(sha1_input, buffer, half);
memcpy(sha1_input + half, key, keySize);
sha1_input[half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100;
break;
case 2:
case 3:
sha1_input[0] = 0x79;
memcpy(sha1_input + 1, buffer, half);
memcpy(sha1_input + 1 + half, key, keySize);
sha1_input[1 + half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
}
sha1_single_block(sha1_input, sha1_result);
size_t i;
for (i = half & ~3; i < half; i++)
@ -671,8 +783,44 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
}
}
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49])
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid, bool overrideVersion)
{
int version;
unsigned char hardwareID[8];
activationMode = mode;
switch (activationMode) {
case 0:
MOD = 0x16A6B036D7F2A79;
NON_RESIDUE = 43;
f[0] = 0x0;
f[1] = 0x21840136C85381;
f[2] = 0x44197B83892AD0;
f[3] = 0x1400606322B3B04;
f[4] = 0x1400606322B3B04;
f[5] = 0x1;
break;
case 1:
case 2:
case 3:
MOD = 0x16E48DD18451FE9;
NON_RESIDUE = 3;
f[0] = 0x0;
f[1] = 0xE5F5ECD95C8FD2;
f[2] = 0xFF28276F11F61;
f[3] = 0xFB2BD9132627E6;
f[4] = 0xE5F5ECD95C8FD2;
f[5] = 0x1;
break;
case 4:
MOD = 0x16A5DABA0605983;
NON_RESIDUE = 2;
f[0] = 0x334F24F75CAA0E;
f[1] = 0x1392FF62889BD7B;
f[2] = 0x135131863BA2DB8;
f[3] = 0x153208E78006010;
f[4] = 0x163694F26056DB;
f[5] = 0x1;
}
unsigned char installation_id[19]; // 10**45 < 256**19
size_t installation_id_len = 0;
const char* p = installation_id_str;
@ -714,9 +862,25 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
return ERR_TOO_SHORT;
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
installation_id[installation_id_len] = 0;
static const unsigned char iid_key[4] = {0x6A, 0xC8, 0x5E, 0xD4};
unsigned char iid_key[4] = { 0x0, 0x0, 0x0, 0x0 };
switch (activationMode) {
case 0:
case 4:
iid_key[0] = 0x6A;
iid_key[1] = 0xC8;
iid_key[2] = 0x5E;
iid_key[3] = 0xD4;
break;
case 1:
case 2:
case 3:
iid_key[0] = 0x5A;
iid_key[1] = 0x30;
iid_key[2] = 0xB9;
iid_key[3] = 0xF3;
}
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
if (installation_id[18] >= 0x10)
if (installation_id[18] >= 0x10 && overrideVersion == false)
return ERR_UNKNOWN_VERSION;
#pragma pack(push, 1)
@ -727,19 +891,71 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
unsigned short KeySHA1;
} parsed;
#pragma pack(pop)
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(&parsed, installation_id, sizeof(parsed));
unsigned productId1 = parsed.ProductIDLow & ((1 << 17) - 1);
unsigned productId2 = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1);
unsigned productId3 = (parsed.ProductIDLow >> 27) & ((1 << 25) - 1);
unsigned version = (parsed.ProductIDLow >> 52) & 7;
unsigned productId4 = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
if (version != (totalCount == 41 ? 4 : 5))
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;
productID[3] = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
if (overrideVersion == false) {
switch (activationMode) {
case 0:
if (version != (totalCount == 41 ? 9 : 10))
return ERR_UNKNOWN_VERSION;
//printf("Product ID: %05u-%03u-%07u-%05u\n", productId1, productId2, productId3, productId4);
break;
case 1:
if (version != 1)
return ERR_UNKNOWN_VERSION;
break;
case 3:
if (version != 4)
return ERR_UNKNOWN_VERSION;
}
}
break;
case 2:
case 3:
decode_iid_new_version(installation_id, hardwareID, &version);
if (overrideVersion == false) {
switch (activationMode) {
case 2:
if (version != 3)
return ERR_UNKNOWN_VERSION;
break;
case 3:
if (version != 4)
return ERR_UNKNOWN_VERSION;
break;
}
}
memcpy(&parsed, hardwareID, 8);
productID[0] = stoi(productid.substr(0,5));
std::string channelid = productid.substr(6,3);
char *p = &channelid[0];
for (; *p; p++) {
*p = toupper((unsigned char)*p);
}
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[2] = calculateCheckDigit(productID[2]);
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));
}
//fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
}
unsigned char keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8);
QWORD productIdMixed = (QWORD)productId1 << 41 | (QWORD)productId2 << 58 | (QWORD)productId3 << 17 | productId4;
QWORD productIdMixed = (QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
memcpy(keybuf + 8, &productIdMixed, 8);
TDivisor d;
@ -754,7 +970,16 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
} u;
u.lo = 0;
u.hi = 0;
switch (activationMode) {
case 0:
case 1:
case 4:
u.buffer[7] = attempt;
break;
case 2:
case 3:
u.buffer[6] = attempt;
}
Mix(u.buffer, 14, keybuf, 16);
QWORD x2 = ui128_quotient_mod(u.lo, u.hi);
QWORD x1 = u.lo - x2 * MOD;
@ -766,7 +991,18 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
}
if (attempt > 0x80)
return ERR_UNLUCKY;
divisor_mul128(&d, 0x04e21b9d10f127c1, 0x40da7c36d44c, &d);
switch (activationMode) {
case 0:
divisor_mul128(&d, 0x04E21B9D10F127C1, 0x40DA7C36D44C, &d);
break;
case 1:
case 2:
case 3:
divisor_mul128(&d, 0xEFE0302A1F7A5341, 0x01FB8CF48A70DF, &d);
break;
case 4:
divisor_mul128(&d, 0x7C4254C43A5D1181, 0x01C61212ECE610, &d);
}
union {
struct {
QWORD encoded_lo, encoded_hi;

View File

@ -41,6 +41,7 @@ typedef struct {
} TDivisor;
EXPORT class ConfirmationID {
static int calculateCheckDigit(int pid);
static QWORD residue_add(QWORD x, QWORD y);
static QWORD residue_sub(QWORD x, QWORD y);
static QWORD __umul128(QWORD a, QWORD b, QWORD* hi);
@ -60,11 +61,12 @@ EXPORT class ConfirmationID {
static void divisor_mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst);
static unsigned rol(unsigned x, int shift);
static void sha1_single_block(unsigned char input[64], unsigned char output[20]);
static void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version);
static void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
public:
static int Generate(const char* installation_id_str, char confirmation_id[49]);
static int Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid, bool overrideVersion);
//EXPORT static int CLIRun();
};

View File

@ -27,8 +27,8 @@
#include "pidgen3/BINK2002.h"
#include "pidgen2/PIDGEN2.h"
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49]) {
return ConfirmationID::Generate(installation_id_str, confirmation_id);
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid, bool bypassVersion) {
return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid, bypassVersion);
}
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) {
@ -58,3 +58,78 @@ FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) {
FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout) {
return PIDGEN2::GenerateOEM(year, day, oem, keyout);
}
// RNG utility functions
int UMSKT::umskt_rand_bytes(unsigned char *buf, int num) {
#if UMSKT_RNG_DJGPP
// DOS-compatible RNG using DJGPP's random() function
static bool initialized = false;
if (!initialized) {
// Get initial seed from multiple sources for better entropy
struct timeval tv;
gettimeofday(&tv, NULL);
// Combine microseconds with BIOS timer ticks
unsigned long ticks = *(volatile unsigned long *)0x0040001CL;
int seed = (int)((tv.tv_sec ^ tv.tv_usec) ^ (ticks * 100000));
// Initialize both random() and rand() with different seeds
srandom(seed);
srand(seed ^ 0x1234ABCD); // Use a different seed for rand
initialized = true;
}
for (int i = 0; i < num; i++) {
// Use random() for better randomness, especially in lower bits
buf[i] = (unsigned char)(random() & 0xFF);
// Mix in rand() as an additional source
buf[i] ^= (unsigned char)(rand() & 0xFF);
}
return 1;
#else
// Use OpenSSL's RAND_bytes for non-DOS systems
return RAND_bytes(buf, num);
#endif
}
int UMSKT::umskt_bn_rand(BIGNUM *rnd, int bits, int top, int bottom) {
#if UMSKT_RNG_DJGPP
// DOS-compatible RNG implementation for BIGNUMs
unsigned char *buf = (unsigned char *)malloc((bits + 7) / 8);
if (!buf) return 0;
// Generate random bytes
umskt_rand_bytes(buf, (bits + 7) / 8);
// Convert to BIGNUM
if (!BN_bin2bn(buf, (bits + 7) / 8, rnd)) {
free(buf);
return 0;
}
free(buf);
// Apply top/bottom constraints like BN_rand does
if (top != -1) {
if (top) {
if (bits == 0) {
BN_zero(rnd);
return 1;
}
BN_set_bit(rnd, bits - 1);
}
BN_mask_bits(rnd, bits);
}
if (bottom) {
BN_set_bit(rnd, 0);
}
return 1;
#else
// Use OpenSSL's BN_rand for non-DOS systems
return BN_rand(rnd, bits, top, bottom);
#endif
}

View File

@ -38,6 +38,10 @@
#include <fmt/core.h>
#include <fmt/format.h>
#ifdef __DJGPP__
#include <sys/time.h>
#endif
// Algorithm macros
#define PK_LENGTH 25
#define NULL_TERMINATOR 1
@ -59,6 +63,17 @@
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
// RNG utility functions
#ifdef __DJGPP__
#define UMSKT_RNG_DJGPP 1
extern "C" {
long int random(void);
int srandom(int seed);
}
#else
#define UMSKT_RNG_DJGPP 0
#endif
class UMSKT {
public:
static std::FILE* debug;
@ -67,7 +82,10 @@ public:
class ConfigurationID;
static void setDebugOutput(std::FILE* input);
// RNG utility functions
static int umskt_rand_bytes(unsigned char *buf, int num);
static int umskt_bn_rand(BIGNUM *rnd, int bits, int top, int bottom);
};
#endif //UMSKT_LIBUMSKT_H

View File

@ -201,7 +201,7 @@ void PIDGEN3::BINK1998::Generate(
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 384 bits without any constraints.
BN_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
UMSKT::umskt_bn_rand(c, FIELD_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
// Pick a random derivative of the base point on the elliptic curve.
// R = cG;

View File

@ -236,7 +236,7 @@ void PIDGEN3::BINK2002::Generate(
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 512 bits without any constraints.
BN_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
UMSKT::umskt_bn_rand(c, FIELD_BITS_2003, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
// R = cG
EC_POINT_mul(eCurve, r, nullptr, basePoint, c, numContext);

View File

@ -100,6 +100,13 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
// Cleanup
BN_CTX_free(context);
BN_free(p);
BN_free(a);
BN_free(b);
BN_free(generatorX);
BN_free(generatorY);
BN_free(publicKeyX);
BN_free(publicKeyY);
return eCurve;
}

BIN
src/macos/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -39,23 +39,23 @@ int main(int argc, char *argv[]) {
return status;
}
CLI* run = new CLI(options, keys);
CLI run(options, keys);
switch(options.applicationMode) {
case MODE_BINK1998_GENERATE:
return run->BINK1998Generate();
return run.BINK1998Generate();
case MODE_BINK2002_GENERATE:
return run->BINK2002Generate();
return run.BINK2002Generate();
case MODE_BINK1998_VALIDATE:
return run->BINK1998Validate();
return run.BINK1998Validate();
case MODE_BINK2002_VALIDATE:
return run->BINK2002Validate();
return run.BINK2002Validate();
case MODE_CONFIRMATION_ID:
return run->ConfirmationID();
return run.ConfirmationID();
default:
return 1;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.