mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2025-07-15 16:50:21 +03:00
Compare commits
235 Commits
dos-window
...
f7427792e3
Author | SHA1 | Date | |
---|---|---|---|
f7427792e3 | |||
c0aca723b8 | |||
8c98a3d173 | |||
a1845d9d6a | |||
817695d988 | |||
8dc6dfb97e | |||
8d964c6fad | |||
e66f0cc724 | |||
ca7db29776 | |||
ed19cf2148 | |||
4de84b6439 | |||
827c26bc45 | |||
a0e7a2561f | |||
8d92cc123d | |||
7af4a1fbcf | |||
2796923983 | |||
6fda0c9ab8 | |||
5e9ebe10cd | |||
f216019046 | |||
9663669c0c | |||
af35f41c3f | |||
0a4561b1cd | |||
fe8e7c72e0 | |||
f630ed1e53 | |||
7c8a7dd54c | |||
befe149285 | |||
5eb3ed11f8 | |||
f3be9fb950 | |||
761ba76081 | |||
c072d096f3 | |||
1002e0a6d5 | |||
6b85771db1 | |||
8db1fe25d7 | |||
0db5d7f982 | |||
25ed8d4f43 | |||
324688e9ef | |||
6ae46d6aa2 | |||
e07c080ee8 | |||
ce9ff7e624 | |||
714895c61b | |||
6ecf9c5309 | |||
9f7d53dab3 | |||
a66e579377 | |||
e30a4713b6 | |||
e9228045d3 | |||
36de07ecdf | |||
a28f4b5ca3 | |||
a0cb9e9869 | |||
6d30abba98 | |||
8b6c3b252b | |||
1fd7550f85 | |||
1f85bf954e | |||
74ff1ea08c | |||
0a63055e91 | |||
94da628e48 | |||
8e58232803 | |||
78ec40f4e3 | |||
9d36fb2f66 | |||
2166ee6e2f | |||
e85add2a54 | |||
f459316865 | |||
60a9b0ea70 | |||
0ebce49cf0 | |||
caa37365d4 | |||
8fe0fc06b2 | |||
fc4b83d1e8 | |||
aa331ad6e4 | |||
9b06fcf162 | |||
a4d810b030 | |||
c209070a66 | |||
9c01c93e77 | |||
b41b596e54 | |||
8723928e48 | |||
8b603c96f1 | |||
403bcb9dd5 | |||
8368b6a6c7 | |||
2415d1374f | |||
d1024950da | |||
1ca5114b21 | |||
da10583fdf | |||
034c00a5b8 | |||
cd050c65d6 | |||
02434e935d | |||
09f1300afc | |||
a3de0e845f | |||
6287b4c773 | |||
a5ce3abe13 | |||
27344f6d4b | |||
01b216dbc4 | |||
c29db1d30a | |||
1c1e26012f | |||
75f22215b1 | |||
be99f6b8e9 | |||
e830f97e7e | |||
0251546d0d | |||
a12afcd601 | |||
c7a555abe4 | |||
74ff4bf144 | |||
2b408913c4 | |||
c965b88113 | |||
2bc3503fd8 | |||
3fbd1cffea | |||
4bf3800281 | |||
8ec60bf396 | |||
5fbbd5e6eb | |||
d378c6499e | |||
3ea8731271 | |||
018f9f533c | |||
f1f1e0e6ea | |||
c4b63c15b2 | |||
1548e14169 | |||
72d48dd38b | |||
00d4906b28 | |||
88f60630c1 | |||
2ac6920e2c | |||
8f843ad4c3 | |||
2753bf2a40 | |||
d17ada2e64 | |||
6685b38aac | |||
884d8c9703 | |||
5ba2dbddd4 | |||
bf40bb6402 | |||
12a041c380 | |||
ecd9cd8dd2 | |||
6989ae6c94 | |||
ac510f8253 | |||
72c42f66c9 | |||
759c4009ef | |||
78c358c933 | |||
1d5e233c19 | |||
6c06732331 | |||
f347231362 | |||
a7e97e45ee | |||
bf57c32eae | |||
25db955b61 | |||
1aeceb28f1 | |||
b451a04f3c | |||
3e5e03df4d | |||
e3bdc93249 | |||
36b2eb3e7d | |||
49fefca596 | |||
178c9e0689 | |||
214d2d38a5 | |||
3ae078e3c5 | |||
12e511b3a5 | |||
21bac3b66c | |||
09842ace12 | |||
0d016b8872 | |||
b1743f4bff | |||
cc765edb4f | |||
4d1b5d6681 | |||
f59d77bdd1 | |||
71cbd19017 | |||
974f400cfc | |||
a2d521c230 | |||
d53409f5bd | |||
2703e17f69 | |||
680239bdb7 | |||
104bdb19e3 | |||
f2f859faeb | |||
a2d9c46a4b | |||
f65533bbb3 | |||
90e31b667a | |||
492d245f86 | |||
361a39e204 | |||
31993afb62 | |||
b3f64e6330 | |||
ccf93a0089 | |||
ae391a5e50 | |||
3620cf5af6 | |||
33774f7ad2 | |||
06ed5ef240 | |||
161aa2de4c | |||
a50688657d | |||
1679583e64 | |||
02c85b50b1 | |||
93732e152b | |||
95803054ba | |||
8619fccb11 | |||
06b9d937b1 | |||
453151f20f | |||
1bb00cf53d | |||
a787fc8e85 | |||
582ddf1bb8 | |||
13bf69c7e1 | |||
b7965f19e8 | |||
52c9a57ea2 | |||
283df1c1fe | |||
c1eb81490b | |||
2ee6a99acd | |||
1370a6ecff | |||
e3a6b78407 | |||
9fec269ad0 | |||
6ae5c9e435 | |||
a6bfaed6e8 | |||
f7b41a9810 | |||
e76eb7ac33 | |||
c91bbad69a | |||
75e81e7049 | |||
e9131e45c8 | |||
c664ea7f9c | |||
f95501b789 | |||
444f8c45c7 | |||
de09feb18f | |||
bde4371cbe | |||
f43a2d5c37 | |||
46c39df15d | |||
c078247bea | |||
232be6aba2 | |||
c0c3149be7 | |||
8e15a4f5b8 | |||
d411d56d81 | |||
11253c5e2c | |||
9f7920ca2d | |||
9063e32a89 | |||
958169ccb5 | |||
63fbbd83ef | |||
de659846d4 | |||
7c4bcdc847 | |||
859a21656c | |||
4b2ef7ac72 | |||
216c9cdf9d | |||
8f685a022c | |||
e4058ddf19 | |||
45004623be | |||
a4cb524fed | |||
03ae90163a | |||
c1e9a0f021 | |||
152c03456c | |||
ea51438766 | |||
8ee1acc2be | |||
3134a6f7a3 | |||
b75d08b3be | |||
20c84661b2 | |||
fefc8552b6 |
155
.github/workflows/dos-djgpp.yml
vendored
155
.github/workflows/dos-djgpp.yml
vendored
@ -20,70 +20,171 @@
|
||||
|
||||
name: C/C++ CI (DOS DJGPP)
|
||||
|
||||
on: workflow_dispatch
|
||||
on:
|
||||
push:
|
||||
branches: [ "*" ]
|
||||
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CMAKE_C_COMPILER: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc
|
||||
CMAKE_CXX_COMPILER: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-g++
|
||||
CC: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc
|
||||
CXX: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-g++
|
||||
CMAKE_FIND_ROOT_PATH: ${{ github.workspace }}/djgpp
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM: NEVER
|
||||
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY: ONLY
|
||||
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE: ONLY
|
||||
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE: ONLY
|
||||
WATT_ROOT: ${{ github.workspace }}/djgpp/watt32
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Source Tree
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup build environment
|
||||
run: |
|
||||
sudo apt -y update
|
||||
sudo apt -y install build-essential cmake wget 7zip git flex 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: |
|
||||
pushd ${{ github.workspace }}
|
||||
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
|
||||
cd ../src
|
||||
source ${{ github.workspace }}/djgpp/setenv.sh
|
||||
source ${{ github.workspace }}/djgpp/setenv
|
||||
./configur.sh djgpp
|
||||
make -f djgpp.mak
|
||||
ln -s ${{ github.workspace }}/djgpp/watt32/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
|
||||
ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
|
||||
|
||||
- name: Checkout and Cross Compile OpenSSL 3.1
|
||||
- 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
|
||||
git checkout openssl-3.1.1
|
||||
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: Checkout Source Tree
|
||||
uses: actions/checkout@v3
|
||||
- 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
|
||||
uses: threeal/cmake-action@v1.2.0
|
||||
with:
|
||||
c-compiler: ${{ github.workspace }}/djgpp/i586-pc-msdosdjgpp/bin/gcc
|
||||
cxx-compiler: ${{ github.workspace }}/djgpp/i586-pc-msdosdjgpp/bin/g++
|
||||
options: OPENSSL_ROOT_DIR:string=${{ github.workspace }}/djgpp DJGPP_WATT32=ON
|
||||
run-build: true
|
||||
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} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
|
||||
make
|
||||
|
||||
- name: Move files to correct directory
|
||||
- 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
|
||||
tar -czf WindowsXPKg_linux_x86_64.tar.gz -C build xpkey keys.json
|
||||
mv WindowsXPKg_linux_x86_64.tgz 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: Build
|
||||
name: UMSKT-DOS-x86
|
||||
path: build/actions_upload
|
||||
|
68
.github/workflows/freebsd.yml
vendored
Normal file
68
.github/workflows/freebsd.yml
vendored
Normal 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
|
127
.github/workflows/linux.yml
vendored
127
.github/workflows/linux.yml
vendored
@ -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: 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
123
.github/workflows/macos.yml
vendored
Normal 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
147
.github/workflows/windows-arm.yml
vendored
Normal 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
160
.github/workflows/windows-x86-x64.yml
vendored
Normal 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
|
116
.github/workflows/windows.yml
vendored
116
.github/workflows/windows.yml
vendored
@ -1,116 +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-32bit:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Install v141_xp
|
||||
uses: thepwrtank18/install-vs-components@v1.0.0
|
||||
with:
|
||||
components: Microsoft.VisualStudio.Component.WinXP
|
||||
|
||||
- name: Download And Install 32-bit OpenSSL 3.1.1
|
||||
run: |
|
||||
$installDir = "$Env:ProgramFiles\OpenSSL"
|
||||
$installerURL = "https://slproweb.com/download/Win32OpenSSL-3_1_1.exe"
|
||||
$installerName = "Win32OpenSSL-3_1_1.exe"
|
||||
$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: Checkout Source Tree
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Configure UMSKT
|
||||
uses: threeal/cmake-action@v1.2.0
|
||||
with:
|
||||
working-directory: build
|
||||
generator: "Visual Studio 17 2022"
|
||||
options: CMAKE_SYSTEM_VERSION="5.1.2600"
|
||||
args: -A "Win32" -T v141_xp
|
||||
|
||||
- name: Build UMSKT
|
||||
working-directory: build
|
||||
run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release /P:XPDeprecationWarning=false
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
with:
|
||||
name: UMSKT-Win32
|
||||
path: build/Release
|
||||
|
||||
build-64bit:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Install v141_xp
|
||||
uses: thepwrtank18/install-vs-components@v1.0.0
|
||||
with:
|
||||
components: Microsoft.VisualStudio.Component.WinXP
|
||||
|
||||
- name: Download And Install 64-bit OpenSSL 3.1.1
|
||||
run: |
|
||||
$installDir = "$Env:ProgramFiles\OpenSSL"
|
||||
$installerURL = "https://slproweb.com/download/Win64OpenSSL-3_1_1.exe"
|
||||
$installerName = "Win64OpenSSL-3_1_1.exe"
|
||||
$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: Checkout Source Tree
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Configure UMSKT
|
||||
uses: threeal/cmake-action@v1.2.0
|
||||
with:
|
||||
generator: "Visual Studio 17 2022"
|
||||
args: -A "x64" -T v141_xp
|
||||
|
||||
- name: Build UMSKT
|
||||
working-directory: build
|
||||
run: msbuild ALL_BUILD.vcxproj /P:Configuration=Release /P:XPDeprecationWarning=false
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
with:
|
||||
name: UMSKT-Win64
|
||||
path: build/Release
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -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
10
.pre-commit-config.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
# Stub so pre-commit can shut up until the refactor
|
||||
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: no-op
|
||||
name: No‑op hook (always passes)
|
||||
entry: "true" # `/usr/bin/true` returns 0 and does nothing
|
||||
language: system
|
||||
pass_filenames: false # don’t bother passing any file paths
|
183
CMakeLists.txt
183
CMakeLists.txt
@ -20,48 +20,104 @@
|
||||
|
||||
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)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
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)
|
||||
@ -81,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")
|
||||
@ -88,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)
|
||||
|
||||
@ -105,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
|
||||
@ -147,31 +247,50 @@ IF (EMSCRIPTEN)
|
||||
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})
|
||||
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()
|
||||
ADD_LIBRARY(_umskt ${LIBUMSKT_SRC} ${UMSKT_EXE_WINDOWS_EXTRA} ${UMSKT_EXE_WINDOWS_DLL})
|
||||
TARGET_INCLUDE_DIRECTORIES(_umskt PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||
TARGET_LINK_DIRECTORIES(_umskt PUBLIC ${UMSKT_LINK_DIRS})
|
||||
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})
|
||||
|
||||
# Link required Windows system libraries for OpenSSL
|
||||
if (WIN32)
|
||||
target_link_libraries(umskt crypt32 ws2_32)
|
||||
endif()
|
||||
|
||||
IF(MSVC AND 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
|
||||
IF (OPENSSL_CRYPTO_SHARED)
|
||||
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()
|
||||
|
92
README.md
92
README.md
@ -1,17 +1,32 @@
|
||||
# **Universal MS Key Toolkit (UMSKT)**
|
||||
# Universal MS Key Toolkit (UMSKT)
|
||||
|
||||
**Connect with us**
|
||||
|
||||
[](https://umskt.zulipchat.com)
|
||||
[](https://web.libera.chat/gamja/?nick=Guest?#mspid)
|
||||
[](https://discord.gg/PpBSpuphWM)
|
||||
|
||||
**Build status**
|
||||
|
||||
[](../../actions/workflows/windows-x86-x64.yml)
|
||||
|
||||
[](../../actions/workflows/windows-arm.yml)
|
||||
|
||||
[](../../actions/workflows/macos.yml)
|
||||
|
||||
[](../../actions/workflows/linux.yml)
|
||||
[](../../actions/workflows/windows.yml)
|
||||
|
||||
[](../../actions/workflows/freebsd.yml)
|
||||
|
||||
### **Plan of Action / ToDo List**
|
||||
[](../../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,20 +125,26 @@ 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`
|
||||
|
||||
|
||||
-----
|
||||
|
||||
### **Known Ports**
|
||||
|
||||
| Language | Author | Repo URL |
|
||||
|----------|-----------|-------------------------------------------------------|
|
||||
| Rust | Alex Page | [anpage/umskt-rs](https://github.com/anpage/umskt-rs) |
|
||||
|
||||
| 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) |
|
||||
|
302
extras/GenerateCIDOffice0307.sage
Normal file
302
extras/GenerateCIDOffice0307.sage
Normal 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
433
extras/confid.ipynb
Normal 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
65
extras/parse_dpcdll.py
Normal 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
98
extras/parse_pubkey.py
Normal 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
348
extras/pidgenx.ipynb
Normal 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
159
extras/tspkgen.py
Normal 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
526
extras/winxp_act.ipynb
Normal 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
|
||||
}
|
267
extras/wsrv_x64_lh_act.ipynb
Normal file
267
extras/wsrv_x64_lh_act.ipynb
Normal 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
109
keys.json
@ -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",
|
||||
|
138
src/cli.cpp
138
src/cli.cpp
@ -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 {
|
||||
|
||||
} 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
|
||||
fmt::print("\n");
|
||||
#endif
|
||||
|
||||
if (this->options.nonewlines == false) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
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
|
||||
fmt::print("\n");
|
||||
#endif
|
||||
if (this->options.nonewlines == false) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
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:
|
||||
fmt::print(confirmation_id);
|
||||
#ifndef _WIN32
|
||||
fmt::print("\n");
|
||||
#endif
|
||||
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);
|
||||
|
||||
if (this->options.nonewlines == false) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
19
src/cli.h
19
src/cli.h
@ -36,10 +36,18 @@
|
||||
|
||||
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,
|
||||
MODE_CONFIRMATION_ID = 2,
|
||||
MODE_CONFIRMATION_ID = 2,
|
||||
MODE_BINK1998_VALIDATE = 3,
|
||||
MODE_BINK2002_VALIDATE = 4,
|
||||
};
|
||||
@ -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();
|
||||
|
@ -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,12 +712,26 @@ 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));
|
||||
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;
|
||||
sha1_single_block(sha1_input, sha1_result);
|
||||
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++)
|
||||
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
|
||||
@ -654,12 +752,26 @@ 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));
|
||||
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;
|
||||
sha1_single_block(sha1_input, sha1_result);
|
||||
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++)
|
||||
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
|
||||
@ -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)
|
||||
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))
|
||||
return ERR_UNKNOWN_VERSION;
|
||||
//printf("Product ID: %05u-%03u-%07u-%05u\n", productId1, productId2, productId3, productId4);
|
||||
switch (activationMode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 4:
|
||||
memcpy(&parsed, installation_id, sizeof(parsed));
|
||||
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;
|
||||
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;
|
||||
u.buffer[7] = attempt;
|
||||
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;
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
12
src/main.cpp
12
src/main.cpp
@ -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.
Reference in New Issue
Block a user