From c9ea427dd7eb28296a06059555291eab084e1c33 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Tue, 25 Apr 2023 18:09:04 +0200 Subject: [PATCH] migration to pyo3 app --- .github/workflows/CI.yml | 120 +++++++++++++ .gitignore | 142 +++------------- Cargo.lock | 282 +++++++++++++++++++++++++++++++ Cargo.toml | 12 ++ pyproject.toml | 17 ++ pyvenv.cfg | 5 + src-py/__init__.py | 1 + {src => src-py}/authur1.py | 99 ++++++----- {src => src-py}/basic-decrypt.py | 0 src-py/binary.pyi | 21 +++ {src => src-py}/md5-analyzer.py | 0 src-py/plexcryptool.pyi | 6 + src-py/py.typed | 0 {src => src-py}/trash-hash.py | 0 src/binary.rs | 14 ++ src/lib.rs | 19 +++ 16 files changed, 572 insertions(+), 166 deletions(-) create mode 100644 .github/workflows/CI.yml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 pyproject.toml create mode 100644 pyvenv.cfg create mode 100644 src-py/__init__.py rename {src => src-py}/authur1.py (50%) rename {src => src-py}/basic-decrypt.py (100%) create mode 100644 src-py/binary.pyi rename {src => src-py}/md5-analyzer.py (100%) create mode 100644 src-py/plexcryptool.pyi create mode 100644 src-py/py.typed rename {src => src-py}/trash-hash.py (100%) create mode 100644 src/binary.rs create mode 100644 src/lib.rs diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..49ebda6 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,120 @@ +# This file is autogenerated by maturin v0.14.17 +# To update, run +# +# maturin generate-ci github +# +name: CI + +on: + push: + branches: + - main + - master + tags: + - '*' + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + linux: + runs-on: ubuntu-latest + strategy: + matrix: + target: [x86_64, x86, aarch64, armv7, s390x, ppc64le] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + manylinux: auto + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + windows: + runs-on: windows-latest + strategy: + matrix: + target: [x64, x86] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + architecture: ${{ matrix.target }} + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + macos: + runs-on: macos-latest + strategy: + matrix: + target: [x86_64, aarch64] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.target }} + args: --release --out dist --find-interpreter + sccache: 'true' + - name: Upload wheels + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + sdist: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build sdist + uses: PyO3/maturin-action@v1 + with: + command: sdist + args: --out dist + - name: Upload sdist + uses: actions/upload-artifact@v3 + with: + name: wheels + path: dist + + release: + name: Release + runs-on: ubuntu-latest + if: "startsWith(github.ref, 'refs/tags/')" + needs: [linux, windows, macos, sdist] + steps: + - uses: actions/download-artifact@v3 + with: + name: wheels + - name: Publish to PyPI + uses: PyO3/maturin-action@v1 + env: + MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} + with: + command: upload + args: --skip-existing * diff --git a/.gitignore b/.gitignore index 5d381cc..af3ca5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,162 +1,72 @@ -# ---> Python +/target + # Byte-compiled / optimized / DLL files __pycache__/ +.pytest_cache/ *.py[cod] -*$py.class # C extensions *.so # Distribution / packaging .Python +.venv/ +env/ +bin/ build/ develop-eggs/ dist/ -downloads/ eggs/ -.eggs/ lib/ lib64/ parts/ sdist/ var/ -wheels/ -share/python-wheels/ +include/ +man/ +venv/ *.egg-info/ .installed.cfg *.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec # Installer logs pip-log.txt pip-delete-this-directory.txt +pip-selfcheck.json # Unit test / coverage reports htmlcov/ .tox/ -.nox/ .coverage -.coverage.* .cache nosetests.xml coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ # Translations *.mo -*.pot + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Rope +.ropeproject # Django stuff: *.log -local_settings.py -db.sqlite3 -db.sqlite3-journal +*.pot -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy +.DS_Store # Sphinx documentation docs/_build/ -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - # PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/ +# VSCode +.vscode/ + +# Pyenv +.python-version \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6ba8544 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,282 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "indoc" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" + +[[package]] +name = "libc" +version = "0.2.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "plexcryptool" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b1ac5b3731ba34fdaa9785f8d74d17448cd18f30cf19e0c7e7b1fdb5272109" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cb946f5ac61bb61a5014924910d936ebd2b23b705f7a4a3c40b05c720b079a3" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd4d7c5337821916ea2a1d21d1092e8443cf34879e53a0ac653fbb98f44ff65c" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d39c55dab3fc5a4b25bbd1ac10a2da452c4aca13bb450f22818a002e29648d" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97daff08a4c48320587b5224cc98d609e3c27b6d437315bd40b605c98eeb5918" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unindent" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5609980 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "plexcryptool" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "plexcryptool" +crate-type = ["cdylib"] + +[dependencies] +pyo3 = "0.18.1" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ae576bb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[build-system] +requires = ["maturin>=0.14,<0.15"] +build-backend = "maturin" + +[project] +name = "plexcryptool" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Rust", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] + + +[tool.maturin] +features = ["pyo3/extension-module"] +python-source = "src-py" diff --git a/pyvenv.cfg b/pyvenv.cfg new file mode 100644 index 0000000..42a815a --- /dev/null +++ b/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /usr/bin +include-system-site-packages = false +version = 3.11.2 +executable = /usr/bin/python3.11 +command = /usr/bin/python -m venv /home/plex/Documents/code/python/plexcryptool diff --git a/src-py/__init__.py b/src-py/__init__.py new file mode 100644 index 0000000..6433255 --- /dev/null +++ b/src-py/__init__.py @@ -0,0 +1 @@ +from .plexcryptool import * diff --git a/src/authur1.py b/src-py/authur1.py similarity index 50% rename from src/authur1.py rename to src-py/authur1.py index 701f05c..88ff70b 100755 --- a/src/authur1.py +++ b/src-py/authur1.py @@ -11,6 +11,8 @@ Since this (auth) hash did not have a name before, I gave it the name 'authur1' import math import argparse +from plexcryptool import binary + # constants for authur1 SHIFT_LENGTH = 17 DEFINED_INITIAL = bytearray([0x52, 0x4f, 0x46, 0x4c]) @@ -22,38 +24,15 @@ CHAR_BIT = 8 # python is being a dynamic dumbass, do a 32 bit shift ~ 4 byte VALUE_SIZE = 4 -""" -The rotations are tested agains a c implementation and are still garbage. FIXME -""" -def rotl(value: int, count: int) -> int: - # FIXME - mask: int = CHAR_BIT * VALUE_SIZE - 1; - print("mask length: %d" % mask.bit_length()) - count = count & mask - result = (value << count) | (value >> (-count & mask)); - assert result.bit_length() <= 32, "python made the numbers too big: %d bit" % result.bit_length() - return result - -def rotr(value: int, count: int) -> int: - # FIXME - mask: int = CHAR_BIT * VALUE_SIZE - 1; - print("mask length: %d" % mask.bit_length()) - count = count & mask - result = (value >> count) | (value << (-count & mask)); - assert result.bit_length() <= 32, "python made the numbers too big: %d bit" % result.bit_length() - return result - -""" -Now for the actual implementation of authur1 -""" def inner_authur1(input: int) -> int: - # should really be 32 bit block - # python sucks for binary operations - # assert input.bit_length() == 32, "not a 32 bit int :(" + """ + passes all tests + """ assert input.bit_length() <= 32, "input length is <= 32: %d" % input.bit_length() output: int - output = input ^ (rotr(input, SHIFT_LENGTH)) + # plexcryptool.binary uses u32 for shifting + output = input ^ (binary.rotl32(input, SHIFT_LENGTH)) assert output.bit_length() <= 32, "output length is <= 32: %d" % output.bit_length() @@ -68,46 +47,66 @@ def authur1(input: bytearray) -> bytearray: continue # else assert len(internal_buffer) == 4, "internal buffer of authur1 not 4 byte long" - accumulator = bytearray( - inner_authur1( - # accumulator - int.from_bytes(accumulator, byteorder='big', signed=False) - # XOR - ^ - # internal_buffer - int.from_bytes(internal_buffer, byteorder='big', signed=False) - ) - .to_bytes(length=2**16, byteorder="big", signed=False) - ) + accuint = int.from_bytes(accumulator) + accuint = inner_authur1(accuint ^ int.from_bytes(internal_buffer)) + accumulator = bytearray(accuint.to_bytes(4)) + assert len(accumulator) == 4, "accumulator too long: %d bytes" % len(accumulator) # finished loading input bytes into the hash, fill with padding and do it one last time while not len(internal_buffer) == 4: internal_buffer.append(PADDING) assert len(internal_buffer) == 4, "internal buffer of authur1 not 4 byte long" # same as above, one last time - accumulator = bytearray( - inner_authur1( - # accumulator - int.from_bytes(accumulator, byteorder='big', signed=False) - # XOR - ^ - # internal_buffer - int.from_bytes(internal_buffer, byteorder='big', signed=False) - ) - .to_bytes(length=2**16, byteorder="big", signed=False) - ) + assert len(accumulator) == 4, "accumulator too long: %d bytes" % len(accumulator) + accuint = int.from_bytes(accumulator) + accuint = inner_authur1(accuint ^ int.from_bytes(internal_buffer)) + accumulator = bytearray(accuint.to_bytes(4)) + assert len(accumulator) == 4, "accumulator too long: %d bytes" % len(accumulator) return accumulator +def test(): + init = int.from_bytes(DEFINED_INITIAL) + a = inner_authur1(init) + b = inner_authur1(a) + c = inner_authur1(b) + assert a == 0xded7e2d2, "Q(S0) returns wrong value: %s" % hex(a) + assert b == 0x1b725f7d, "Q(Q(S0)) returns wrong value: %s" % hex(b) + assert c == 0xa5886999, "Q(Q(Q(S0))) returns wrong value: %s" % hex(c) + + print("Q aka inner_authur1 passed the test") + + ha = authur1(bytearray(0)) + hb = authur1(bytearray(b'A')) + hc = authur1(bytearray(b'AB')) + hd = authur1(bytearray(b'ABC')) + he = authur1(bytearray(b'ABCD')) + hf = authur1(bytearray(b'ABCDE')) + assert int.from_bytes(ha) == 0xded7e2d2, "H(\"\") returns wrong value: %s" % ha.hex() + assert int.from_bytes(hb) == 0x5d725f7f, "H(\"A\") returns wrong value: %s" % hb.hex() + assert int.from_bytes(hc) == 0x5f3b5f7f, "H(\"AB\") returns wrong value: %s" % hc.hex() + assert int.from_bytes(hd) == 0x5f39137f, "H(\"ABC\") returns wrong value: %s" % hd.hex() + assert int.from_bytes(he) == 0x5f391128, "H(\"ABCD\") returns wrong value: %s" % he.hex() + assert int.from_bytes(hf) == 0x2f69af58, "H(\"ABCDE\") returns wrong value: %s" % hf.hex() + + print("H aka authur1 passed the test") + print("All tests passed!") + def main(): parser = argparse.ArgumentParser(prog="authur1 authentication hash", description='Implementation and attack for the custom authur1 hash') parser.add_argument('-i', '--hash', type=str, help='an input that should be hashed') + parser.add_argument('-t', '--test', action="store_true", + help='perform tests') args = parser.parse_args() if args.hash: my_bytes: bytearray = bytearray(str.encode(args.hash)) hashed = authur1(my_bytes) print("hash for \"%s\" is:\n%s" % (args.hash, hashed.hex())) + exit() + elif args.test: + test() + exit() parser.print_help() if __name__ == "__main__": diff --git a/src/basic-decrypt.py b/src-py/basic-decrypt.py similarity index 100% rename from src/basic-decrypt.py rename to src-py/basic-decrypt.py diff --git a/src-py/binary.pyi b/src-py/binary.pyi new file mode 100644 index 0000000..63d7dfe --- /dev/null +++ b/src-py/binary.pyi @@ -0,0 +1,21 @@ +""" +some tools for binary operations, i found python to be weird about +""" + +def rotl32(value: int, count: int) -> int: + """ + left bitwise rotation / circular shift + + :param value: the value that will be shifted + :param count: how far the value will be shifted + """ + ... + +def rotr32(value: int, count: int) -> int: + """ + right bitwise rotation / circular shift + + :param value: the value that will be shifted + :param count: how far the value will be shifted + """ + ... diff --git a/src/md5-analyzer.py b/src-py/md5-analyzer.py similarity index 100% rename from src/md5-analyzer.py rename to src-py/md5-analyzer.py diff --git a/src-py/plexcryptool.pyi b/src-py/plexcryptool.pyi new file mode 100644 index 0000000..96aba41 --- /dev/null +++ b/src-py/plexcryptool.pyi @@ -0,0 +1,6 @@ +""" +Bindings for the plexcryptool rust library + +plexcryptool.plexcryptool is direct access to the shared library, do not use it. +""" +from .plexcryptool import * diff --git a/src-py/py.typed b/src-py/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/trash-hash.py b/src-py/trash-hash.py similarity index 100% rename from src/trash-hash.py rename to src-py/trash-hash.py diff --git a/src/binary.rs b/src/binary.rs new file mode 100644 index 0000000..8ed52f3 --- /dev/null +++ b/src/binary.rs @@ -0,0 +1,14 @@ +/** + * Pythons bit operations are trash, so I made a rust lib for that. + */ +use pyo3::prelude::*; + +#[pyfunction] +pub fn rotl32 (value: u32, count: i32) -> u32 { + value.rotate_left(count as u32) +} + +#[pyfunction] +pub fn rotr32 (value: u32, count: i32) -> u32 { + value.rotate_right(count as u32) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..29c21e3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,19 @@ +use pyo3::prelude::*; + +mod binary; + +#[pymodule] +fn register_binary_module(py: Python, parent_module: &PyModule) -> PyResult<()> { + let binary_module = PyModule::new(py, "binary")?; + binary_module.add_function(wrap_pyfunction!(binary::rotl32, binary_module)?)?; + binary_module.add_function(wrap_pyfunction!(binary::rotr32, binary_module)?)?; + parent_module.add_submodule(binary_module)?; + Ok(()) +} + +/// A Python module implemented in Rust. +#[pymodule] +fn plexcryptool(py: Python, m: &PyModule) -> PyResult<()> { + register_binary_module(py, m)?; + Ok(()) +}