mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2025-07-15 16:50:21 +03:00
Compare commits
50 Commits
v0.3.0-bet
...
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 |
111
.github/workflows/dos-djgpp.yml
vendored
111
.github/workflows/dos-djgpp.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
|||||||
- name: Setup build environment
|
- name: Setup build environment
|
||||||
run: |
|
run: |
|
||||||
sudo apt -y update
|
sudo apt -y update
|
||||||
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib
|
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib dosbox tree
|
||||||
|
|
||||||
- name: Download and Setup DJGPP Toolchain
|
- name: Download and Setup DJGPP Toolchain
|
||||||
run: |
|
run: |
|
||||||
@ -50,6 +50,7 @@ jobs:
|
|||||||
wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2
|
wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2
|
||||||
tar xjf djgpp-linux64-gcc1220.tar.bz2
|
tar xjf djgpp-linux64-gcc1220.tar.bz2
|
||||||
cd ${{ github.workspace }}/djgpp
|
cd ${{ github.workspace }}/djgpp
|
||||||
|
tree . -S
|
||||||
git clone https://github.com/UMSKT/Watt-32.git watt32
|
git clone https://github.com/UMSKT/Watt-32.git watt32
|
||||||
cd watt32/util
|
cd watt32/util
|
||||||
make clean && make linux
|
make clean && make linux
|
||||||
@ -59,22 +60,124 @@ jobs:
|
|||||||
make -f djgpp.mak
|
make -f djgpp.mak
|
||||||
ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
|
ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
|
||||||
|
|
||||||
|
- name: Cache OpenSSL 3.1.2
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
id: cache-openssl
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/djgpp
|
||||||
|
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
|
||||||
|
|
||||||
- name: Checkout and Cross Compile OpenSSL 3.1.2
|
- name: Checkout and Cross Compile OpenSSL 3.1.2
|
||||||
|
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/UMSKT/openssl.git openssl
|
git clone https://github.com/UMSKT/openssl.git openssl
|
||||||
pushd openssl
|
pushd openssl
|
||||||
source ${{ github.workspace }}/djgpp/setenv
|
source ${{ github.workspace }}/djgpp/setenv
|
||||||
./Configure no-threads no-tests -DOPENSSL_DEV_NO_ATOMICS --prefix=${{ github.workspace }}/djgpp DJGPP
|
./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
|
make && make install_sw
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
- name: Save OpenSSL 3.1.2
|
||||||
|
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||||
|
uses: actions/cache/save@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}/djgpp
|
||||||
|
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
|
||||||
|
|
||||||
|
- name: Download stub
|
||||||
|
run: |
|
||||||
|
wget https://web.archive.org/web/20250308092209/https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/util/system/cwsdpmi/csdpmi7b.zip -O CSDPMI7B.ZIP
|
||||||
|
mkdir /home/runner/dpmibin
|
||||||
|
7z e CSDPMI7B.ZIP bin/CWSDSTUB.EXE -o/home/runner/dpmibin
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
source ${{ github.workspace }}/djgpp/setenv
|
source ${{ github.workspace }}/djgpp/setenv
|
||||||
pushd build
|
pushd build
|
||||||
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}
|
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
|
||||||
make
|
make
|
||||||
|
|
||||||
|
- name: Setup DOSBox test environment
|
||||||
|
run: |
|
||||||
|
mkdir -p dosbox_test
|
||||||
|
cp build/umskt.exe dosbox_test/
|
||||||
|
# Download DPMI server directly
|
||||||
|
# wget https://github.com/UMSKT/winactiontest/raw/refs/heads/main/CWSDPMI.EXE -O dosbox_test/CWSDPMI.EXE
|
||||||
|
# Create test batch file
|
||||||
|
cat > dosbox_test/test.bat << EOL
|
||||||
|
@echo off
|
||||||
|
echo Running test 1...
|
||||||
|
umskt.exe -b 2C -c 365 -s 069420 > TEST1.TXT
|
||||||
|
if errorlevel 1 goto error
|
||||||
|
echo Running test 2...
|
||||||
|
umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST2.TXT
|
||||||
|
if errorlevel 1 goto error
|
||||||
|
echo Tests completed > DONE.TXT
|
||||||
|
goto end
|
||||||
|
:error
|
||||||
|
echo Test failed > ERROR.TXT
|
||||||
|
:end
|
||||||
|
exit
|
||||||
|
EOL
|
||||||
|
# Create DOSBox configuration
|
||||||
|
cat > dosbox_test/dosbox.conf << EOL
|
||||||
|
[sdl]
|
||||||
|
nosound=true
|
||||||
|
[cpu]
|
||||||
|
cputype=386
|
||||||
|
core=dynamic
|
||||||
|
cycles=max
|
||||||
|
[autoexec]
|
||||||
|
mount c .
|
||||||
|
c:
|
||||||
|
test.bat
|
||||||
|
exit
|
||||||
|
EOL
|
||||||
|
|
||||||
|
- name: Run tests in DOSBox
|
||||||
|
run: |
|
||||||
|
cd dosbox_test
|
||||||
|
timeout 30s dosbox -conf dosbox.conf -nogui -exit
|
||||||
|
# Check if the test completed successfully
|
||||||
|
if [ ! -f DONE.TXT ]; then
|
||||||
|
echo "Tests did not complete successfully"
|
||||||
|
if [ -f ERROR.TXT ]; then
|
||||||
|
echo "Test execution failed"
|
||||||
|
fi
|
||||||
|
if [ -f TEST1.TXT ]; then
|
||||||
|
echo "Test 1 output:"
|
||||||
|
cat TEST1.TXT
|
||||||
|
fi
|
||||||
|
if [ -f TEST2.TXT ]; then
|
||||||
|
echo "Test 2 output:"
|
||||||
|
cat TEST2.TXT
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Verify test outputs
|
||||||
|
if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ]; then
|
||||||
|
echo "Test output files missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check test results - looking for key format patterns
|
||||||
|
if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \
|
||||||
|
! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST2.TXT; then
|
||||||
|
echo "Tests failed - unexpected output format"
|
||||||
|
echo "Test 1 output:"
|
||||||
|
cat TEST1.TXT
|
||||||
|
echo "Test 2 output:"
|
||||||
|
cat TEST2.TXT
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "All tests passed successfully"
|
||||||
|
echo "Test 1 output:"
|
||||||
|
cat TEST1.TXT
|
||||||
|
echo "Test 2 output:"
|
||||||
|
cat TEST2.TXT
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Move executable to upload directory
|
- name: Move executable to upload directory
|
||||||
run: |
|
run: |
|
||||||
mkdir build/actions_upload
|
mkdir build/actions_upload
|
||||||
@ -83,5 +186,5 @@ jobs:
|
|||||||
- name: Upload build artifact
|
- name: Upload build artifact
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v4.6.2
|
||||||
with:
|
with:
|
||||||
name: UMSKT-DOS
|
name: UMSKT-DOS-x86
|
||||||
path: build/actions_upload
|
path: build/actions_upload
|
||||||
|
5
.github/workflows/freebsd.yml
vendored
5
.github/workflows/freebsd.yml
vendored
@ -51,7 +51,10 @@
|
|||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
make
|
make
|
||||||
./umskt # Execute the test here
|
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
|
- name: Move files to correct directory
|
||||||
run: |
|
run: |
|
||||||
|
106
.github/workflows/linux.yml
vendored
106
.github/workflows/linux.yml
vendored
@ -28,18 +28,25 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: x86
|
- arch: x86
|
||||||
|
runner: ubuntu-latest
|
||||||
|
use_alpine: true
|
||||||
- arch: x86_64
|
- arch: x86_64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
use_alpine: true
|
||||||
- arch: aarch64
|
- arch: aarch64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
use_alpine: false
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Source Tree
|
- name: Checkout Source Tree
|
||||||
uses: actions/checkout@v4
|
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
|
uses: jirutka/setup-alpine@v1
|
||||||
with:
|
with:
|
||||||
packages: >
|
packages: >
|
||||||
@ -54,13 +61,46 @@ jobs:
|
|||||||
arch: ${{ matrix.arch }}
|
arch: ${{ matrix.arch }}
|
||||||
shell-name: alpine-target.sh
|
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
|
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||||
with:
|
with:
|
||||||
options: MUSL_STATIC=ON
|
options: MUSL_STATIC=ON
|
||||||
run-build: true
|
run-build: true
|
||||||
shell: alpine-target.sh {0}
|
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
|
- name: Move files to correct directory
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/actions_upload
|
mkdir -p build/actions_upload
|
||||||
@ -69,19 +109,73 @@ jobs:
|
|||||||
- name: Upload build artifact
|
- name: Upload build artifact
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v4.6.2
|
||||||
with:
|
with:
|
||||||
name: UMSKT-linux-${{ matrix.arch }}-static
|
name: UMSKT-Linux-${{ matrix.arch }}-static
|
||||||
path: build/actions_upload
|
path: build/actions_upload
|
||||||
|
|
||||||
- name: Configure and build static internal deps UMSKT
|
- name: Configure and build static internal deps UMSKT (Alpine)
|
||||||
|
if: ${{ matrix.use_alpine }}
|
||||||
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||||
with:
|
with:
|
||||||
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF
|
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF
|
||||||
run-build: true
|
run-build: true
|
||||||
shell: alpine-target.sh {0}
|
shell: alpine-target.sh {0}
|
||||||
|
|
||||||
- name: Configure and build shared deps UMSKT
|
- 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
|
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||||
with:
|
with:
|
||||||
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
|
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
|
||||||
run-build: true
|
run-build: true
|
||||||
shell: alpine-target.sh {0}
|
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
|
||||||
|
71
.github/workflows/macos.yml
vendored
71
.github/workflows/macos.yml
vendored
@ -27,34 +27,97 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-x86:
|
build:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: x86_64
|
- arch: x86_64
|
||||||
|
- arch: arm64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Source Tree
|
- name: Checkout Source Tree
|
||||||
uses: actions/checkout@v4
|
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
|
- name: Configure and build UMSKT
|
||||||
run: |
|
run: |
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
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
|
make
|
||||||
|
|
||||||
- name: Move files to correct directory
|
- name: Move files to correct directory
|
||||||
run: |
|
run: |
|
||||||
|
ls -a build
|
||||||
mkdir -p build/actions_upload
|
mkdir -p build/actions_upload
|
||||||
mv build/umskt build/actions_upload/umskt
|
mv build/umskt build/actions_upload/umskt
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
cd build/actions_upload
|
cd build/actions_upload
|
||||||
./umskt
|
echo Test 1 - generating key
|
||||||
|
./umskt -b 2C -c 365 -s 069420 -v
|
||||||
|
echo Test 2 - generating confid
|
||||||
|
./umskt -i 253286028742154311079061239762245184619981623171292574
|
||||||
|
|
||||||
- name: Upload build artifact
|
- name: Upload platform-specific build
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v4.6.2
|
||||||
with:
|
with:
|
||||||
name: UMSKT-macOS-${{ matrix.arch }}
|
name: UMSKT-macOS-${{ matrix.arch }}
|
||||||
path: build/actions_upload
|
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
|
105
.github/workflows/windows.yml
vendored
105
.github/workflows/windows.yml
vendored
@ -1,105 +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: [ "*" ]
|
|
||||||
paths-ignore: [ '**.md', 'doc/**', '.idea/**']
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-tdm:
|
|
||||||
runs-on: windows-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: [x64, x86]
|
|
||||||
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: Download OpenSSL-TDM release asset
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if ('${{ matrix.arch }}' -eq 'x64') {
|
|
||||||
$url = "https://github.com/UMSKT/winactiontest/releases/download/openssl/OpenSSL-TDM-64.zip"
|
|
||||||
$dest = "$env:GITHUB_WORKSPACE/OpenSSL-TDM-64"
|
|
||||||
$libdir = "lib64"
|
|
||||||
$cmake_flags = "-m64"
|
|
||||||
$openssl_root = "$env:GITHUB_WORKSPACE/OpenSSL-TDM-64"
|
|
||||||
} else {
|
|
||||||
$url = "https://github.com/UMSKT/winactiontest/releases/download/openssl/OpenSSL-TDM-32.zip"
|
|
||||||
$dest = "$env:GITHUB_WORKSPACE/OpenSSL-TDM-32"
|
|
||||||
$libdir = "lib32"
|
|
||||||
$cmake_flags = "-m32"
|
|
||||||
$openssl_root = "$env:GITHUB_WORKSPACE/OpenSSL-TDM-32"
|
|
||||||
}
|
|
||||||
Invoke-WebRequest -Uri $url -OutFile "OpenSSL-TDM.zip"
|
|
||||||
Expand-Archive -Path "OpenSSL-TDM.zip" -DestinationPath $env:GITHUB_WORKSPACE
|
|
||||||
echo "OPENSSL_ROOT=$openssl_root" | Out-File -FilePath $env:GITHUB_ENV -Append
|
|
||||||
echo "OPENSSL_LIBDIR=$libdir" | Out-File -FilePath $env:GITHUB_ENV -Append
|
|
||||||
echo "CMAKE_FLAGS=$cmake_flags" | Out-File -FilePath $env:GITHUB_ENV -Append
|
|
||||||
|
|
||||||
- name: Configure UMSKT (TDM-GCC ${{ matrix.arch }})
|
|
||||||
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 (TDM-GCC ${{ matrix.arch }})
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
|
|
||||||
mingw32-make
|
|
||||||
|
|
||||||
- name: Upload build artifact
|
|
||||||
uses: actions/upload-artifact@v4.6.2
|
|
||||||
with:
|
|
||||||
name: UMSKT-TDM${{ matrix.arch }}
|
|
||||||
path: umskt.exe
|
|
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
|
@ -26,6 +26,26 @@ if (WIN32 AND NOT MSVC)
|
|||||||
set(CMAKE_C_COMPILER "C:/TDM-GCC-64/bin/gcc.exe" CACHE FILEPATH "C Compiler" FORCE)
|
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)
|
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")
|
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()
|
endif()
|
||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 17)
|
SET(CMAKE_CXX_STANDARD 17)
|
||||||
@ -36,13 +56,14 @@ OPTION(UMSKT_USE_SHARED_OPENSSL "Force linking against the system-wide OpenSSL l
|
|||||||
OPTION(MUSL_STATIC "Enable fully static builds in a muslc environment (i.e. Alpine Linux)" 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(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(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_LIBS ${UMSKT_LINK_LIBS})
|
||||||
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
|
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
|
||||||
|
|
||||||
# macOS does not support static build
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
SET(UMSKT_USE_SHARED_OPENSSL ON)
|
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||||
|
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# neither does dos idk i'm trying random stuff
|
# neither does dos idk i'm trying random stuff
|
||||||
@ -60,7 +81,22 @@ ELSE()
|
|||||||
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
|
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
|
||||||
ENDIF()
|
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)
|
IF(DJGPP_WATT32)
|
||||||
SET(CMAKE_SYSTEM_NAME MSDOS)
|
SET(CMAKE_SYSTEM_NAME MSDOS)
|
||||||
@ -70,12 +106,18 @@ IF(DJGPP_WATT32)
|
|||||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} ${DJGPP_WATT32})
|
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} ${DJGPP_WATT32})
|
||||||
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS} ${WATT_ROOT}/lib)
|
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()
|
ENDIF()
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
##if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||||
SET(BUILD_SHARED_LIBS ON)
|
## SET(BUILD_SHARED_LIBS ON)
|
||||||
MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
|
## MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
|
||||||
endif()
|
##endif()
|
||||||
|
|
||||||
# if we're compiling with MSVC, respect the DEBUG compile option
|
# if we're compiling with MSVC, respect the DEBUG compile option
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
@ -162,6 +204,7 @@ CPMAddPackage(
|
|||||||
GITHUB_REPOSITORY fmtlib/fmt
|
GITHUB_REPOSITORY fmtlib/fmt
|
||||||
GIT_TAG 10.0.0
|
GIT_TAG 10.0.0
|
||||||
VERSION 10.0.0
|
VERSION 10.0.0
|
||||||
|
#OPTIONS "FMT_INSTALL YES" "BUILD_SHARED_LIBS OFF"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Include cmrc resource compiler
|
# Include cmrc resource compiler
|
||||||
@ -233,4 +276,21 @@ ELSE()
|
|||||||
GET_FILENAME_COMPONENT(OPENSSL_CRYPTO_LIBRARY_FILENAME ${OPENSSL_CRYPTO_LIBRARY} NAME)
|
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)
|
CONFIGURE_FILE(${OPENSSL_CRYPTO_LIBRARY} "${CMAKE_CURRENT_BINARY_DIR}/${OPENSSL_CRYPTO_LIBRARY_FILENAME}" COPYONLY)
|
||||||
ENDIF()
|
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()
|
ENDIF()
|
||||||
|
46
README.md
46
README.md
@ -4,11 +4,13 @@
|
|||||||
|
|
||||||
[](https://umskt.zulipchat.com)
|
[](https://umskt.zulipchat.com)
|
||||||
[](https://web.libera.chat/gamja/?nick=Guest?#mspid)
|
[](https://web.libera.chat/gamja/?nick=Guest?#mspid)
|
||||||
[](https://discord.gg/PpBSpuphWM)
|
[](https://discord.gg/PpBSpuphWM)
|
||||||
|
|
||||||
**Build status**
|
**Build status**
|
||||||
|
|
||||||
[](../../actions/workflows/windows.yml)
|
[](../../actions/workflows/windows-x86-x64.yml)
|
||||||
|
|
||||||
|
[](../../actions/workflows/windows-arm.yml)
|
||||||
|
|
||||||
[](../../actions/workflows/macos.yml)
|
[](../../actions/workflows/macos.yml)
|
||||||
|
|
||||||
@ -44,6 +46,33 @@ In light of the recent exponential interest in this project I've decided to put
|
|||||||
|
|
||||||
------
|
------
|
||||||
|
|
||||||
|
### 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**
|
### **Usage**
|
||||||
#### 1. Download the latest version of UMSKT
|
#### 1. Download the latest version of UMSKT
|
||||||
|
|
||||||
@ -54,15 +83,14 @@ In light of the recent exponential interest in this project I've decided to put
|
|||||||
* *(GitHub account \*not\* required)*
|
* *(GitHub account \*not\* required)*
|
||||||
* Download the latest release for your operating system and architecture from [the releases page](../../releases)
|
* Download the latest release for your operating system and architecture from [the releases page](../../releases)
|
||||||
|
|
||||||
* **Note:** Before continuing, please ensure you have the `umskt` executable extracted and on UNIX-like systems, have execution permissions (`chmod +x umskt`).
|
> [!IMPORTANT]
|
||||||
|
> Before continuing, please ensure you have the `umskt` executable extracted and on UNIX-like systems, have execution permissions (`chmod +x umskt`).
|
||||||
|
|
||||||
#### 2. Install OpenSSL.
|
#### 2. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
|
||||||
For Windows, click [here](https://slproweb.com/products/Win32OpenSSL.html) and choose the right version. For other operating systems, consult your package manager.
|
> [!IMPORTANT]
|
||||||
*Note: This only applies if the build you download has OpenSSL embedded (static library) or not. You can usually tell if the download size is measured in KB or MB. If it's MB, you don't need this.*
|
> On macOS, like all unsigned executables, you'll need to hold Ctrl while right clicking and selecting Open to actually open it.
|
||||||
|
|
||||||
#### 3. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
|
#### 3. *(Activation step for `Retail` and `OEM` only)*
|
||||||
|
|
||||||
#### 4. *(Activation step for `Retail` and `OEM` only)*
|
|
||||||
* After installation, you will be prompted to activate Windows.
|
* After installation, you will be prompted to activate Windows.
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
27
src/cli.cpp
27
src/cli.cpp
@ -71,7 +71,8 @@ void CLI::showHelp(char *argv[]) {
|
|||||||
fmt::print("\t-u --upgrade\tspecifies the Product Key will be an \"Upgrade\" version\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-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-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n");
|
||||||
fmt::print("\t-o --override\tDisables version check for confirmation ID's, if you need this send an issue on GitHub");
|
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");
|
fmt::print("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +95,7 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
MODE_BINK1998_GENERATE,
|
MODE_BINK1998_GENERATE,
|
||||||
WINDOWS
|
WINDOWS
|
||||||
};
|
};
|
||||||
@ -214,6 +216,8 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
|
|||||||
options->nonewlines = true;
|
options->nonewlines = true;
|
||||||
} else if (arg == "-o" || arg == "--override") {
|
} else if (arg == "-o" || arg == "--override") {
|
||||||
options->overrideVersion = true;
|
options->overrideVersion = true;
|
||||||
|
} else if (arg == "-D" || arg == "--nodashes") {
|
||||||
|
options->nodashes = true;
|
||||||
} else {
|
} else {
|
||||||
options->error = true;
|
options->error = true;
|
||||||
}
|
}
|
||||||
@ -327,9 +331,14 @@ void CLI::printID(DWORD *pid) {
|
|||||||
|
|
||||||
void CLI::printKey(char *pk) {
|
void CLI::printKey(char *pk) {
|
||||||
assert(strlen(pk) >= PK_LENGTH);
|
assert(strlen(pk) >= PK_LENGTH);
|
||||||
|
std::string keyFormat = "{}-{}-{}-{}-{}";
|
||||||
|
|
||||||
|
if (this->options.nodashes == true) {
|
||||||
|
keyFormat = "{}{}{}{}{}";
|
||||||
|
}
|
||||||
|
|
||||||
std::string spk = pk;
|
std::string spk = pk;
|
||||||
fmt::print("{}-{}-{}-{}-{}",
|
fmt::print(keyFormat,
|
||||||
spk.substr(0,5),
|
spk.substr(0,5),
|
||||||
spk.substr(5,5),
|
spk.substr(5,5),
|
||||||
spk.substr(10,5),
|
spk.substr(10,5),
|
||||||
@ -591,7 +600,17 @@ int CLI::ConfirmationID() {
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
fmt::print(confirmation_id);
|
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) {
|
if (this->options.nonewlines == false) {
|
||||||
fmt::print("\n");
|
fmt::print("\n");
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ struct Options {
|
|||||||
bool list;
|
bool list;
|
||||||
bool nonewlines;
|
bool nonewlines;
|
||||||
bool overrideVersion;
|
bool overrideVersion;
|
||||||
|
bool nodashes;
|
||||||
|
|
||||||
MODE applicationMode;
|
MODE applicationMode;
|
||||||
ACTIVATION_ALGORITHM activationMode;
|
ACTIVATION_ALGORITHM activationMode;
|
||||||
@ -93,7 +94,7 @@ public:
|
|||||||
static int parseCommandLine(int argc, char* argv[], Options *options);
|
static int parseCommandLine(int argc, char* argv[], Options *options);
|
||||||
static int validateCommandLine(Options* options, char *argv[], json *keys);
|
static int validateCommandLine(Options* options, char *argv[], json *keys);
|
||||||
static void printID(DWORD *pid);
|
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]);
|
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
|
||||||
|
|
||||||
int BINK1998Generate();
|
int BINK1998Generate();
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
#include "confid.h"
|
#include "confid.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QWORD MOD = 0;
|
QWORD MOD = 0;
|
||||||
QWORD NON_RESIDUE = 0;
|
QWORD NON_RESIDUE = 0;
|
||||||
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
||||||
@ -75,7 +79,13 @@ inline QWORD ConfirmationID::__umul128(QWORD a, QWORD b, QWORD* hi)
|
|||||||
#else
|
#else
|
||||||
#define __umul128 _umul128
|
#define __umul128 _umul128
|
||||||
#endif
|
#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) {
|
inline QWORD ConfirmationID::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi) {
|
||||||
// multiplier = ab = a * 2^32 + b
|
// multiplier = ab = a * 2^32 + b
|
||||||
// multiplicand = cd = c * 2^32 + d
|
// multiplicand = cd = c * 2^32 + d
|
||||||
|
Binary file not shown.
Reference in New Issue
Block a user