mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2025-07-19 18:50:21 +03:00
Compare commits
58 Commits
v0.3.0-bet
...
change-ico
Author | SHA1 | Date | |
---|---|---|---|
2bcc9d5178 | |||
af058711ec | |||
793432f07b | |||
8cb00c165d | |||
070dbe46d0 | |||
51248fb5cc | |||
bda0ea93c8 | |||
843b904639 | |||
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
|
||||
run: |
|
||||
sudo apt -y update
|
||||
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib
|
||||
sudo apt -y install build-essential cmake wget 7zip git flex libfl-dev nasm libslang2-dev pkg-config libslang2-modules gcc-multilib dosbox tree
|
||||
|
||||
- name: Download and Setup DJGPP Toolchain
|
||||
run: |
|
||||
@ -50,6 +50,7 @@ jobs:
|
||||
wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2
|
||||
tar xjf djgpp-linux64-gcc1220.tar.bz2
|
||||
cd ${{ github.workspace }}/djgpp
|
||||
tree . -S
|
||||
git clone https://github.com/UMSKT/Watt-32.git watt32
|
||||
cd watt32/util
|
||||
make clean && make linux
|
||||
@ -59,22 +60,124 @@ jobs:
|
||||
make -f djgpp.mak
|
||||
ln -s ${WATT_ROOT}/lib/libwatt.a ${{ github.workspace }}/djgpp/lib
|
||||
|
||||
- name: Cache OpenSSL 3.1.2
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-openssl
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/djgpp
|
||||
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Checkout and Cross Compile OpenSSL 3.1.2
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone https://github.com/UMSKT/openssl.git openssl
|
||||
pushd openssl
|
||||
source ${{ github.workspace }}/djgpp/setenv
|
||||
./Configure no-threads 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
|
||||
popd
|
||||
|
||||
- name: Save OpenSSL 3.1.2
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/djgpp
|
||||
key: openssl-3.1.2-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Download stub
|
||||
run: |
|
||||
wget https://web.archive.org/web/20250308092209/https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/util/system/cwsdpmi/csdpmi7b.zip -O CSDPMI7B.ZIP
|
||||
mkdir /home/runner/dpmibin
|
||||
7z e CSDPMI7B.ZIP bin/CWSDSTUB.EXE -o/home/runner/dpmibin
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
source ${{ github.workspace }}/djgpp/setenv
|
||||
pushd build
|
||||
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH}
|
||||
cmake ../ -D DJGPP_WATT32=${WATT_ROOT}/lib/libwatt.a -D CMAKE_FIND_ROOT_PATH=${CMAKE_FIND_ROOT_PATH} -D CWSDSTUB_LOCATION=/home/runner/dpmibin/CWSDSTUB.EXE -D DJGPP_BIN_LOCATION=/home/runner/work/UMSKT/UMSKT/djgpp/i586-pc-msdosdjgpp/bin
|
||||
make
|
||||
|
||||
- name: Setup DOSBox test environment
|
||||
run: |
|
||||
mkdir -p dosbox_test
|
||||
cp build/umskt.exe dosbox_test/
|
||||
# Download DPMI server directly
|
||||
# wget https://github.com/UMSKT/winactiontest/raw/refs/heads/main/CWSDPMI.EXE -O dosbox_test/CWSDPMI.EXE
|
||||
# Create test batch file
|
||||
cat > dosbox_test/test.bat << EOL
|
||||
@echo off
|
||||
echo Running test 1...
|
||||
umskt.exe -b 2C -c 365 -s 069420 > TEST1.TXT
|
||||
if errorlevel 1 goto error
|
||||
echo Running test 2...
|
||||
umskt.exe -i 253286028742154311079061239762245184619981623171292574 > TEST2.TXT
|
||||
if errorlevel 1 goto error
|
||||
echo Tests completed > DONE.TXT
|
||||
goto end
|
||||
:error
|
||||
echo Test failed > ERROR.TXT
|
||||
:end
|
||||
exit
|
||||
EOL
|
||||
# Create DOSBox configuration
|
||||
cat > dosbox_test/dosbox.conf << EOL
|
||||
[sdl]
|
||||
nosound=true
|
||||
[cpu]
|
||||
cputype=386
|
||||
core=dynamic
|
||||
cycles=max
|
||||
[autoexec]
|
||||
mount c .
|
||||
c:
|
||||
test.bat
|
||||
exit
|
||||
EOL
|
||||
|
||||
- name: Run tests in DOSBox
|
||||
run: |
|
||||
cd dosbox_test
|
||||
timeout 30s dosbox -conf dosbox.conf -nogui -exit
|
||||
# Check if the test completed successfully
|
||||
if [ ! -f DONE.TXT ]; then
|
||||
echo "Tests did not complete successfully"
|
||||
if [ -f ERROR.TXT ]; then
|
||||
echo "Test execution failed"
|
||||
fi
|
||||
if [ -f TEST1.TXT ]; then
|
||||
echo "Test 1 output:"
|
||||
cat TEST1.TXT
|
||||
fi
|
||||
if [ -f TEST2.TXT ]; then
|
||||
echo "Test 2 output:"
|
||||
cat TEST2.TXT
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
# Verify test outputs
|
||||
if [ ! -f TEST1.TXT ] || [ ! -f TEST2.TXT ]; then
|
||||
echo "Test output files missing"
|
||||
exit 1
|
||||
fi
|
||||
# Check test results - looking for key format patterns
|
||||
if ! grep -qE '[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}' TEST1.TXT || \
|
||||
! grep -qE '[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}' TEST2.TXT; then
|
||||
echo "Tests failed - unexpected output format"
|
||||
echo "Test 1 output:"
|
||||
cat TEST1.TXT
|
||||
echo "Test 2 output:"
|
||||
cat TEST2.TXT
|
||||
exit 1
|
||||
else
|
||||
echo "All tests passed successfully"
|
||||
echo "Test 1 output:"
|
||||
cat TEST1.TXT
|
||||
echo "Test 2 output:"
|
||||
cat TEST2.TXT
|
||||
fi
|
||||
|
||||
- name: Move executable to upload directory
|
||||
run: |
|
||||
mkdir build/actions_upload
|
||||
@ -83,5 +186,5 @@ jobs:
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: UMSKT-DOS
|
||||
name: UMSKT-DOS-x86
|
||||
path: build/actions_upload
|
||||
|
5
.github/workflows/freebsd.yml
vendored
5
.github/workflows/freebsd.yml
vendored
@ -51,7 +51,10 @@
|
||||
cd build
|
||||
cmake ..
|
||||
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
|
||||
run: |
|
||||
|
106
.github/workflows/linux.yml
vendored
106
.github/workflows/linux.yml
vendored
@ -28,18 +28,25 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
runner: ubuntu-latest
|
||||
use_alpine: true
|
||||
- arch: x86_64
|
||||
runner: ubuntu-latest
|
||||
use_alpine: true
|
||||
- arch: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
use_alpine: false
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- name: Checkout Source Tree
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup latest Alpine Linux for ${{ matrix.arch }}
|
||||
- name: Setup latest Alpine Linux
|
||||
if: ${{ matrix.use_alpine }}
|
||||
uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
packages: >
|
||||
@ -54,13 +61,46 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
shell-name: alpine-target.sh
|
||||
|
||||
- name: Configure and build UMSKT
|
||||
- name: Install Dependencies (Ubuntu ARM64)
|
||||
if: ${{ !matrix.use_alpine }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential cmake git libssl-dev zlib1g-dev
|
||||
|
||||
- name: Configure and build UMSKT (Alpine)
|
||||
if: ${{ matrix.use_alpine }}
|
||||
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||
with:
|
||||
options: MUSL_STATIC=ON
|
||||
run-build: true
|
||||
shell: alpine-target.sh {0}
|
||||
|
||||
- name: Configure and build UMSKT (Ubuntu)
|
||||
if: ${{ !matrix.use_alpine }}
|
||||
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||
with:
|
||||
options: MUSL_STATIC=ON
|
||||
run-build: true
|
||||
|
||||
- name: Test UMSKT (Alpine)
|
||||
if: ${{ matrix.use_alpine }}
|
||||
run: |
|
||||
cd build
|
||||
echo Test 1 - generating key
|
||||
./umskt -b 2C -c 365 -s 069420 -v
|
||||
echo Test 2 - generating confid
|
||||
./umskt -i 253286028742154311079061239762245184619981623171292574
|
||||
shell: alpine-target.sh {0}
|
||||
|
||||
- name: Test UMSKT (Ubuntu)
|
||||
if: ${{ !matrix.use_alpine }}
|
||||
run: |
|
||||
cd build
|
||||
echo Test 1 - generating key
|
||||
./umskt -b 2C -c 365 -s 069420 -v
|
||||
echo Test 2 - generating confid
|
||||
./umskt -i 253286028742154311079061239762245184619981623171292574
|
||||
|
||||
- name: Move files to correct directory
|
||||
run: |
|
||||
mkdir -p build/actions_upload
|
||||
@ -69,19 +109,73 @@ jobs:
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: UMSKT-linux-${{ matrix.arch }}-static
|
||||
name: UMSKT-Linux-${{ matrix.arch }}-static
|
||||
path: build/actions_upload
|
||||
|
||||
- name: Configure and build static internal deps UMSKT
|
||||
- name: Configure and build static internal deps UMSKT (Alpine)
|
||||
if: ${{ matrix.use_alpine }}
|
||||
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||
with:
|
||||
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=OFF
|
||||
run-build: true
|
||||
shell: alpine-target.sh {0}
|
||||
|
||||
- name: Configure and build 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
|
||||
with:
|
||||
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
|
||||
run-build: true
|
||||
shell: alpine-target.sh {0}
|
||||
|
||||
- name: Configure and build shared deps UMSKT (Ubuntu)
|
||||
if: ${{ !matrix.use_alpine }}
|
||||
uses: threeal/cmake-action@7ef2eb8da6e5ec0a6de6b1ddc96987080bed06e8
|
||||
with:
|
||||
options: MUSL_STATIC=OFF BUILD_SHARED_LIBS=ON
|
||||
run-build: true
|
||||
|
||||
- name: Test shared deps UMSKT (Alpine)
|
||||
if: ${{ matrix.use_alpine }}
|
||||
run: |
|
||||
cd build
|
||||
echo Test 1 - generating key
|
||||
./umskt -b 2C -c 365 -s 069420 -v
|
||||
echo Test 2 - generating confid
|
||||
./umskt -i 253286028742154311079061239762245184619981623171292574
|
||||
shell: alpine-target.sh {0}
|
||||
|
||||
- name: Test shared deps UMSKT (Ubuntu)
|
||||
if: ${{ !matrix.use_alpine }}
|
||||
run: |
|
||||
cd build
|
||||
echo Test 1 - generating key
|
||||
./umskt -b 2C -c 365 -s 069420 -v
|
||||
echo Test 2 - generating confid
|
||||
./umskt -i 253286028742154311079061239762245184619981623171292574
|
||||
|
71
.github/workflows/macos.yml
vendored
71
.github/workflows/macos.yml
vendored
@ -27,34 +27,97 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-x86:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
- arch: arm64
|
||||
steps:
|
||||
- name: Checkout Source Tree
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rosetta
|
||||
if: matrix.arch == 'x86_64'
|
||||
run: |
|
||||
sudo softwareupdate --install-rosetta --agree-to-license || true
|
||||
|
||||
- name: Install Homebrew for x86_64
|
||||
if: matrix.arch == 'x86_64'
|
||||
env: { NONINTERACTIVE: 1 }
|
||||
run: |
|
||||
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
- name: Install x86_64 OpenSSL
|
||||
if: matrix.arch == 'x86_64'
|
||||
run: |
|
||||
arch -x86_64 /usr/local/bin/brew install openssl@3
|
||||
echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3" >> $GITHUB_ENV
|
||||
echo "OPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@3/include" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH=/usr/local/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Install arm64 OpenSSL
|
||||
if: matrix.arch == 'arm64'
|
||||
run: |
|
||||
brew install openssl@3
|
||||
echo "OPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl@3" >> $GITHUB_ENV
|
||||
echo "OPENSSL_INCLUDE_DIR=/opt/homebrew/opt/openssl@3/include" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH=/opt/homebrew/opt/openssl@3/lib/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Configure and build UMSKT
|
||||
run: |
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .. \
|
||||
-DCMAKE_OSX_ARCHITECTURES=${{matrix.arch}} \
|
||||
-DOPENSSL_ROOT_DIR=$OPENSSL_ROOT_DIR \
|
||||
-DOPENSSL_INCLUDE_DIR=$OPENSSL_INCLUDE_DIR \
|
||||
-DOPENSSL_USE_STATIC_LIBS=TRUE \
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
make
|
||||
|
||||
- name: Move files to correct directory
|
||||
run: |
|
||||
ls -a build
|
||||
mkdir -p build/actions_upload
|
||||
mv build/umskt build/actions_upload/umskt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build/actions_upload
|
||||
./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
|
||||
with:
|
||||
name: UMSKT-macOS-${{ matrix.arch }}
|
||||
path: build/actions_upload
|
||||
|
||||
universal:
|
||||
needs: build
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Download x86_64 slice
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: UMSKT-macOS-x86_64
|
||||
path: x86
|
||||
- name: Download arm64 slice
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: UMSKT-macOS-arm64
|
||||
path: arm
|
||||
- name: Create universal binary
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir fat
|
||||
lipo -create x86/umskt arm/umskt -output fat/umskt
|
||||
lipo -info fat/umskt
|
||||
- name: Upload universal build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: UMSKT-macOS-universal
|
||||
path: fat
|
||||
|
147
.github/workflows/windows-arm.yml
vendored
Normal file
147
.github/workflows/windows-arm.yml
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
# This file is a part of the UMSKT Project
|
||||
#
|
||||
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# @FileCreated by TheTank20 on 07/08/2025
|
||||
# @Maintainer Neo
|
||||
|
||||
name: C/C++ CI (Windows ARM)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "*" ]
|
||||
paths-ignore: [ '**.md', 'doc/**', '.idea/**']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: arm32
|
||||
arch_compilename: amd64_arm
|
||||
vcpkg_arch: arm-windows-static
|
||||
cmake_arch: ARM
|
||||
sdk_version: '10.0.17763.0'
|
||||
- arch: arm64
|
||||
arch_compilename: amd64_arm64
|
||||
vcpkg_arch: arm64-windows-static
|
||||
cmake_arch: ARM64
|
||||
sdk_version: '10.0.17763.0'
|
||||
steps:
|
||||
- name: Setup MSVC for ${{ matrix.arch }}
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.arch_compilename }}
|
||||
sdk: ${{ matrix.sdk_version }}
|
||||
|
||||
- name: Checkout Source Tree
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache OpenSSL Binaries
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}-OpenSSL-MSVC-${{ matrix.arch }}
|
||||
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Checkout and Compile OpenSSL v1.1.1
|
||||
shell: pwsh
|
||||
run: |
|
||||
git clone https://github.com/UMSKT/openssl --branch OpenSSL_1_1_1-stable --depth 1 openssl-src
|
||||
cd openssl-src
|
||||
|
||||
# Install Perl if needed
|
||||
choco install strawberryperl -y
|
||||
|
||||
# Configure and build OpenSSL for ARM32
|
||||
$env:PATH = "C:\Strawberry\perl\bin;$env:PATH"
|
||||
|
||||
# First set up Visual Studio environment
|
||||
$vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath
|
||||
$vcvarsall = Join-Path $vsPath "VC\Auxiliary\Build\vcvarsall.bat"
|
||||
|
||||
$vcTarget = ""
|
||||
if ("${{ matrix.arch}}" -eq "arm32") {
|
||||
$vcTarget = "VC-WIN32-ARM"
|
||||
} else {
|
||||
$vcTarget = "VC-WIN64-ARM"
|
||||
}
|
||||
|
||||
# Configure OpenSSL
|
||||
perl Configure $vcTarget no-shared no-asm no-engine --prefix="$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}"
|
||||
|
||||
# Build using MSVC ARM32 tools
|
||||
cmd /c "call `"$vcvarsall`" ${{matrix.arch_compilename}} && nmake && nmake install_sw"
|
||||
cd ..
|
||||
|
||||
- name: Save OpenSSL Binaries
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/OpenSSL-MSVC-${{ matrix.arch }}
|
||||
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Set OpenSSL Environment
|
||||
shell: pwsh
|
||||
run: |
|
||||
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-MSVC-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Configure UMSKT
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -G "Visual Studio 17 2022" `
|
||||
-A ${{ matrix.cmake_arch }} `
|
||||
-DWINDOWS_ARM=ON `
|
||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
|
||||
-DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_arch }} `
|
||||
.
|
||||
|
||||
- name: Build UMSKT
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake --build . --config Release
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: UMSKT-WinNT-${{ matrix.arch }}
|
||||
path: Release/umskt.exe
|
||||
|
||||
test-arm64:
|
||||
needs: build
|
||||
if: success()
|
||||
runs-on: windows-11-arm
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [arm64]
|
||||
steps:
|
||||
- name: Download ARM64 artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: UMSKT-WinNT-${{ matrix.arch }}
|
||||
path: .
|
||||
|
||||
- name: Run tests
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host Test 1 - generating key
|
||||
.\umskt.exe -b 2C -c 365 -s 069420 -v
|
||||
Write-Host Test 2 - generatng confid
|
||||
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574
|
160
.github/workflows/windows-x86-x64.yml
vendored
Normal file
160
.github/workflows/windows-x86-x64.yml
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
# This file is a part of the UMSKT Project
|
||||
#
|
||||
# Copyleft (C) 2019-2023 UMSKT Contributors (et.al.)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# @FileCreated by TheTank20 on 07/08/2025
|
||||
# @Maintainer Neo
|
||||
|
||||
name: C/C++ CI (Windows x86+64)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "*" ]
|
||||
paths-ignore: [ '**.md', 'doc/**', '.idea/**']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
msystem: MINGW
|
||||
cmake_flag: -m32
|
||||
- arch: x64
|
||||
msystem: MINGW64
|
||||
cmake_flag: -m64
|
||||
|
||||
steps:
|
||||
- name: Setup TDM-GCC
|
||||
run: |
|
||||
Write-Host Downloading TDM-GCC v10.3.0...
|
||||
Invoke-WebRequest -Uri 'https://github.com/jmeubank/tdm-gcc/releases/download/v10.3.0-tdm64-2/tdm64-gcc-10.3.0-2.exe' -OutFile 'C:\Windows\temp\TDM-GCC-64.exe'
|
||||
Write-Host Creating directory...
|
||||
New-Item -ItemType Directory -Path 'C:\TDM-GCC-64'
|
||||
Write-Host Copying files [Set 1/3]...
|
||||
Start-Process '7z' -ArgumentList 'e C:\Windows\temp\TDM-GCC-64.exe -oC:\TDM-GCC-64 -y' -Wait
|
||||
Write-Host Copying files [Set 2/3]...
|
||||
Start-Process '7z' -ArgumentList 'e C:\TDM-GCC-64\*.tar.xz -oC:\TDM-GCC-64 -y' -Wait
|
||||
Write-Host Copying files [Set 3/3]...
|
||||
Start-Process '7z' -ArgumentList 'x C:\TDM-GCC-64\*.tar -oC:\TDM-GCC-64 -y' -Wait
|
||||
Write-Host Adding environment variables...
|
||||
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
|
||||
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
|
||||
|
||||
- name: Checkout Source Tree
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache OpenSSL 1.1.1
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-openssl
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
|
||||
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Setup MSYS2
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.arch == 'x86' && 'MINGW32' || 'MINGW64' }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-gcc
|
||||
mingw-w64-${{ matrix.arch == 'x86' && 'i686' || 'x86_64' }}-make
|
||||
mingw-w64-x86_64-perl
|
||||
perl
|
||||
git
|
||||
|
||||
- name: Checkout and Compile OpenSSL 1.1.1
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Clone UMSKT's OpenSSL fork
|
||||
echo "Cloning UMSKT OpenSSL fork..."
|
||||
git clone https://github.com/UMSKT/openssl.git --branch OpenSSL_1_1_1-stable --depth 1 openssl-1.1.1
|
||||
# Set up proper MSYS2 environment
|
||||
export MSYS=winsymlinks:nativestrict
|
||||
export MSYS2_PATH_TYPE=strict
|
||||
export LANG=en_US.UTF-8
|
||||
export PATH="/usr/bin:/mingw64/bin:$PATH"
|
||||
export PATH="/c/TDM-GCC-64/bin:$PATH"
|
||||
export MSYSTEM=${{ matrix.msystem }}
|
||||
cd openssl-1.1.1
|
||||
|
||||
if [[ ${{ matrix.arch }} == "x86" ]]; then
|
||||
/usr/bin/perl Configure mingw --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-32 no-tests no-sse2 no-asm no-threads -DOPENSSL_DEV_NO_ATOMICS -mno-mmx -mno-sse -mno-sse2 -march=i686 -mtune=generic
|
||||
else
|
||||
/usr/bin/perl Configure mingw64 --prefix=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-${{ matrix.arch }} --openssldir=$(cygpath -u "$GITHUB_WORKSPACE")/OpenSSL-TDM-64 no-tests no-asm -DOPENSSL_DEV_NO_ATOMICS -mno-mmx
|
||||
fi
|
||||
mingw32-make -j
|
||||
mingw32-make install_sw
|
||||
cd ..
|
||||
|
||||
- name: Save OpenSSL 1.1.1
|
||||
if: steps.cache-openssl.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/OpenSSL-TDM-${{ matrix.arch }}
|
||||
key: openssl-1.1.1-${{ matrix.arch }}-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: Set OpenSSL Environment
|
||||
shell: pwsh
|
||||
run: |
|
||||
echo "OPENSSL_ROOT=$env:GITHUB_WORKSPACE/OpenSSL-TDM-${{ matrix.arch }}" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
echo "OPENSSL_LIBDIR=lib" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
echo "CMAKE_FLAGS=${{ matrix.cmake_flag }}" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Configure UMSKT
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
|
||||
$OPENSSL_ROOT = "$env:OPENSSL_ROOT"
|
||||
$OPENSSL_LIB = "$OPENSSL_ROOT/$env:OPENSSL_LIBDIR"
|
||||
$OPENSSL_INC = "$OPENSSL_ROOT/include"
|
||||
cmake -G "MinGW Makefiles" `
|
||||
-DCMAKE_C_COMPILER="gcc" `
|
||||
-DCMAKE_CXX_COMPILER="g++" `
|
||||
-DOPENSSL_ROOT_DIR="$OPENSSL_ROOT" `
|
||||
-DOPENSSL_INCLUDE_DIR="$OPENSSL_INC" `
|
||||
-DOPENSSL_CRYPTO_LIBRARY="$OPENSSL_LIB/libcrypto.a" `
|
||||
-DOPENSSL_SSL_LIBRARY="$OPENSSL_LIB/libssl.a" `
|
||||
-DCMAKE_C_FLAGS="$env:CMAKE_FLAGS" `
|
||||
-DCMAKE_CXX_FLAGS="$env:CMAKE_FLAGS" `
|
||||
.
|
||||
|
||||
- name: Build UMSKT
|
||||
shell: pwsh
|
||||
run: |
|
||||
$env:PATH = 'C:\TDM-GCC-64\bin;' + $env:PATH
|
||||
mingw32-make
|
||||
|
||||
- name: Run tests
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host Test 1 - generating key
|
||||
.\umskt.exe -b 2C -c 365 -s 069420 -v
|
||||
Write-Host Test 2 - generatng confid
|
||||
.\umskt.exe -i 253286028742154311079061239762245184619981623171292574
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
name: UMSKT-WinNT-${{ matrix.arch }}
|
||||
path: umskt.exe
|
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_CXX_COMPILER "C:/TDM-GCC-64/bin/g++.exe" CACHE FILEPATH "C++ Compiler" FORCE)
|
||||
message(STATUS "[UMSKT] Forcing use of TDM-GCC in C:/TDM-GCC-64")
|
||||
|
||||
# Configure windres for resource compilation
|
||||
set(CMAKE_RC_COMPILER "C:/TDM-GCC-64/bin/windres.exe")
|
||||
set(CMAKE_RC_COMPILER_INIT windres)
|
||||
enable_language(RC)
|
||||
set(CMAKE_RC_FLAGS "--use-temp-file -c65001")
|
||||
|
||||
# Match resource architecture with target architecture
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-i386 --target=pe-i386")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686 -mtune=generic -mno-sse -mno-sse2 -mno-mmx -mno-3dnow")
|
||||
else()
|
||||
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -F pe-x86-64 --target=pe-x86-64")
|
||||
endif()
|
||||
|
||||
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff -I${CMAKE_CURRENT_SOURCE_DIR}/src/windows <DEFINES> -i <SOURCE> -o <OBJECT>")
|
||||
|
||||
# Set the Windows resource file for GCC builds
|
||||
set(UMSKT_EXE_WINDOWS_EXTRA src/windows/umskt.rc)
|
||||
endif()
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
@ -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(DJGPP_WATT32 "Enable compilation and linking with DJGPP/WATT32/OpenSSL" OFF)
|
||||
OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilation" OFF)
|
||||
OPTION(WINDOWS_ARM "Enable compilation for Windows on ARM (requires appropriate toolchain)" OFF)
|
||||
|
||||
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS})
|
||||
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
|
||||
|
||||
# macOS does not support static build
|
||||
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()
|
||||
|
||||
# neither does dos idk i'm trying random stuff
|
||||
@ -60,7 +81,22 @@ ELSE()
|
||||
MESSAGE(STATUS "[UMSKT] Requesting static version of OpenSSL")
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Configure ARM-specific settings if enabled
|
||||
if (WINDOWS_ARM)
|
||||
if (MSVC)
|
||||
# MSVC ARM64 settings
|
||||
set(CMAKE_SYSTEM_PROCESSOR ARM64)
|
||||
set(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE ARM64)
|
||||
else()
|
||||
# MinGW/GCC ARM settings
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "[UMSKT] Configuring for Windows on ARM")
|
||||
endif()
|
||||
|
||||
IF(DJGPP_WATT32)
|
||||
SET(CMAKE_SYSTEM_NAME MSDOS)
|
||||
@ -70,12 +106,18 @@ IF(DJGPP_WATT32)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS} ${DJGPP_WATT32})
|
||||
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS} ${WATT_ROOT}/lib)
|
||||
|
||||
# Maximum compatibility flags for DOS/NTVDM
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i386 -mtune=i386 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -mno-ssse3 -mno-sse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2 -mno-fma -mno-fma4")
|
||||
|
||||
MESSAGE(STATUS "[UMSKT] Using i386 target for DOS DGJPP with stub: ${CWSDSTUB_LOCATION}")
|
||||
ENDIF()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET(BUILD_SHARED_LIBS ON)
|
||||
MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
|
||||
endif()
|
||||
##if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
## SET(BUILD_SHARED_LIBS ON)
|
||||
## MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
|
||||
##endif()
|
||||
|
||||
# if we're compiling with MSVC, respect the DEBUG compile option
|
||||
IF(MSVC)
|
||||
@ -162,6 +204,7 @@ CPMAddPackage(
|
||||
GITHUB_REPOSITORY fmtlib/fmt
|
||||
GIT_TAG 10.0.0
|
||||
VERSION 10.0.0
|
||||
#OPTIONS "FMT_INSTALL YES" "BUILD_SHARED_LIBS OFF"
|
||||
)
|
||||
|
||||
# Include cmrc resource compiler
|
||||
@ -233,4 +276,21 @@ ELSE()
|
||||
GET_FILENAME_COMPONENT(OPENSSL_CRYPTO_LIBRARY_FILENAME ${OPENSSL_CRYPTO_LIBRARY} NAME)
|
||||
CONFIGURE_FILE(${OPENSSL_CRYPTO_LIBRARY} "${CMAKE_CURRENT_BINARY_DIR}/${OPENSSL_CRYPTO_LIBRARY_FILENAME}" COPYONLY)
|
||||
ENDIF()
|
||||
|
||||
IF (DJGPP_WATT32)
|
||||
message(STATUS "[UMSKT] Configuring DJGPP post-build commands")
|
||||
# Set .exe suffix for DJGPP builds
|
||||
set_target_properties(umskt PROPERTIES SUFFIX ".exe")
|
||||
add_custom_command(TARGET umskt POST_BUILD
|
||||
# Convert exe to coff, removing the default stub
|
||||
COMMAND ${DJGPP_BIN_LOCATION}/exe2coff $<TARGET_FILE:umskt>
|
||||
# Concatenate CWSDSTUB with the COFF file
|
||||
COMMAND ${CMAKE_COMMAND} -E cat ${CWSDSTUB_LOCATION} $<TARGET_FILE_DIR:umskt>/umskt > $<TARGET_FILE:umskt>
|
||||
# Clean up the COFF file
|
||||
COMMAND ${CMAKE_COMMAND} -E rm $<TARGET_FILE_DIR:umskt>/umskt
|
||||
)
|
||||
message(STATUS "[UMSKT] STUBIFY_LOCATION set to: ${STUBIFY_LOCATION}")
|
||||
message(STATUS "[UMSKT] CWSDSTUB_LOCATION set to: ${CWSDSTUB_LOCATION}")
|
||||
message(STATUS "[UMSKT] DJGPP_BIN_LOCATION set to: ${DJGPP_BIN_LOCATION}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
46
README.md
46
README.md
@ -4,11 +4,13 @@
|
||||
|
||||
[](https://umskt.zulipchat.com)
|
||||
[](https://web.libera.chat/gamja/?nick=Guest?#mspid)
|
||||
[](https://discord.gg/PpBSpuphWM)
|
||||
[](https://discord.gg/PpBSpuphWM)
|
||||
|
||||
**Build status**
|
||||
|
||||
[](../../actions/workflows/windows.yml)
|
||||
[](../../actions/workflows/windows-x86-x64.yml)
|
||||
|
||||
[](../../actions/workflows/windows-arm.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**
|
||||
#### 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)*
|
||||
* 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.
|
||||
For Windows, click [here](https://slproweb.com/products/Win32OpenSSL.html) and choose the right version. For other operating systems, consult your package manager.
|
||||
*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.*
|
||||
#### 2. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
|
||||
> [!IMPORTANT]
|
||||
> On macOS, like all unsigned executables, you'll need to hold Ctrl while right clicking and selecting Open to actually open it.
|
||||
|
||||
#### 3. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
|
||||
|
||||
#### 4. *(Activation step for `Retail` and `OEM` only)*
|
||||
#### 3. *(Activation step for `Retail` and `OEM` only)*
|
||||
* 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-V --validate\tproduct key to validate signature\n");
|
||||
fmt::print("\t-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n");
|
||||
fmt::print("\t-o --override\tDisables version check for confirmation 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");
|
||||
}
|
||||
|
||||
@ -94,6 +95,7 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
MODE_BINK1998_GENERATE,
|
||||
WINDOWS
|
||||
};
|
||||
@ -214,6 +216,8 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
|
||||
options->nonewlines = true;
|
||||
} else if (arg == "-o" || arg == "--override") {
|
||||
options->overrideVersion = true;
|
||||
} else if (arg == "-D" || arg == "--nodashes") {
|
||||
options->nodashes = true;
|
||||
} else {
|
||||
options->error = true;
|
||||
}
|
||||
@ -327,9 +331,14 @@ void CLI::printID(DWORD *pid) {
|
||||
|
||||
void CLI::printKey(char *pk) {
|
||||
assert(strlen(pk) >= PK_LENGTH);
|
||||
|
||||
std::string keyFormat = "{}-{}-{}-{}-{}";
|
||||
|
||||
if (this->options.nodashes == true) {
|
||||
keyFormat = "{}{}{}{}{}";
|
||||
}
|
||||
|
||||
std::string spk = pk;
|
||||
fmt::print("{}-{}-{}-{}-{}",
|
||||
fmt::print(keyFormat,
|
||||
spk.substr(0,5),
|
||||
spk.substr(5,5),
|
||||
spk.substr(10,5),
|
||||
@ -591,7 +600,17 @@ int CLI::ConfirmationID() {
|
||||
return 1;
|
||||
|
||||
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) {
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ struct Options {
|
||||
bool list;
|
||||
bool nonewlines;
|
||||
bool overrideVersion;
|
||||
bool nodashes;
|
||||
|
||||
MODE applicationMode;
|
||||
ACTIVATION_ALGORITHM activationMode;
|
||||
@ -93,7 +94,7 @@ public:
|
||||
static int parseCommandLine(int argc, char* argv[], Options *options);
|
||||
static int validateCommandLine(Options* options, char *argv[], json *keys);
|
||||
static void printID(DWORD *pid);
|
||||
static void printKey(char *pk);
|
||||
void printKey(char *pk);
|
||||
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
|
||||
|
||||
int BINK1998Generate();
|
||||
|
428
src/icon_LICENSE
Normal file
428
src/icon_LICENSE
Normal file
@ -0,0 +1,428 @@
|
||||
Attribution-ShareAlike 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution-ShareAlike 4.0 International Public
|
||||
License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution-ShareAlike 4.0 International Public License ("Public
|
||||
License"). To the extent this Public License may be interpreted as a
|
||||
contract, You are granted the Licensed Rights in consideration of Your
|
||||
acceptance of these terms and conditions, and the Licensor grants You
|
||||
such rights in consideration of benefits the Licensor receives from
|
||||
making the Licensed Material available under these terms and
|
||||
conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. BY-SA Compatible License means a license listed at
|
||||
creativecommons.org/compatiblelicenses, approved by Creative
|
||||
Commons as essentially the equivalent of this Public License.
|
||||
|
||||
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
e. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
g. License Elements means the license attributes listed in the name
|
||||
of a Creative Commons Public License. The License Elements of this
|
||||
Public License are Attribution and ShareAlike.
|
||||
|
||||
h. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
i. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
k. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
l. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
m. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. Additional offer from the Licensor -- Adapted Material.
|
||||
Every recipient of Adapted Material from You
|
||||
automatically receives an offer from the Licensor to
|
||||
exercise the Licensed Rights in the Adapted Material
|
||||
under the conditions of the Adapter's License You apply.
|
||||
|
||||
c. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
b. ShareAlike.
|
||||
|
||||
In addition to the conditions in Section 3(a), if You Share
|
||||
Adapted Material You produce, the following conditions also apply.
|
||||
|
||||
1. The Adapter's License You apply must be a Creative Commons
|
||||
license with the same License Elements, this version or
|
||||
later, or a BY-SA Compatible License.
|
||||
|
||||
2. You must include the text of, or the URI or hyperlink to, the
|
||||
Adapter's License You apply. You may satisfy this condition
|
||||
in any reasonable manner based on the medium, means, and
|
||||
context in which You Share Adapted Material.
|
||||
|
||||
3. You may not offer or impose any additional or different terms
|
||||
or conditions on, or apply any Effective Technological
|
||||
Measures to, Adapted Material that restrict exercise of the
|
||||
rights granted under the Adapter's License You apply.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material,
|
||||
including for purposes of Section 3(b); and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
|
@ -29,6 +29,10 @@
|
||||
|
||||
#include "confid.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
QWORD MOD = 0;
|
||||
QWORD NON_RESIDUE = 0;
|
||||
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
||||
@ -75,7 +79,13 @@ inline QWORD ConfirmationID::__umul128(QWORD a, QWORD b, QWORD* hi)
|
||||
#else
|
||||
#define __umul128 _umul128
|
||||
#endif
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__)
|
||||
#elif defined(_M_ARM64) // Microsoft implementation of ARM64
|
||||
inline QWORD ConfirmationID::__umul128(QWORD a, QWORD b, QWORD* hi)
|
||||
{
|
||||
*hi = __umulh(a, b);
|
||||
return a * b;
|
||||
}
|
||||
#elif defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(__EMSCRIPTEN__) || defined(_M_ARM)
|
||||
inline QWORD ConfirmationID::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
|
BIN
src/macos/icon.png
Normal file
BIN
src/macos/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 138 KiB |
Binary file not shown.
Reference in New Issue
Block a user