Add Python implementation (#21)

This commit is contained in:
Stanisław Jelnicki 2022-11-07 21:25:37 +01:00 committed by GitHub
parent ab6b10b746
commit 385081650c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 14 deletions

View file

@ -3,49 +3,51 @@ name: Wulkanowy QR
on:
workflow_dispatch:
push:
branches: [ master ]
branches: [master]
pull_request:
branches: [ master ]
branches: [master]
jobs:
php:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- name: Checkout the code
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
php-version: "7.4"
- name: Install PHP dependencies
run: composer install
- name: Run PHP tests
run: ./vendor/bin/phpunit php/tests
node:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- name: Checkout the code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '19'
node-version: "19"
- name: Install Node.js dependencies using Yarn
working-directory: ./node
run: yarn install
- name: Run Node.js tests
working-directory: ./node
run: yarn test
jvm:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- name: Checkout the code
uses: actions/checkout@v3
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
distribution: "zulu"
java-version: "11"
- name: Run JVM tests
working-directory: ./jvm
run: ./gradlew check jacocoTestReport
@ -54,30 +56,44 @@ jobs:
with:
name: test-results
path: ./build/test-results
dart:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- name: Checkout the code
uses: actions/checkout@v3
- name: Setup Dart
uses: dart-lang/setup-dart@v1.3
with:
sdk: '2.10.0'
sdk: "2.10.0"
- name: Install Dart dependencies
working-directory: ./dart
run: pub get
- name: Run Dart tests
working-directory: ./dart
run: pub run test
dotnet:
dotnet:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- name: Checkout the code
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '3.1.407'
dotnet-version: "3.1.407"
- name: Run .NET tests
working-directory: ./dotnet
run: dotnet test
python:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout@v3
- name: Install dependencies
working-directory: ./python
run: pip install .
- name: Run Python tests
working-directory: ./python
run: python -m unittest test

1
python/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
__pycache__/

19
python/README.md Normal file
View file

@ -0,0 +1,19 @@
# UONET+ QR Code converter for Python
[![PyPI](https://img.shields.io/pypi/v/wulkanowy-qr.svg?style=flat-square)](https://pypi.org/project/wulkanowy-qr/)
## Installation
```
pip install wulkanowy-qr
```
## Usage
```pycon
>>> import wulkanowy_qr
>>> wulkanowy_qr.encode("0123456789ABCDEF", "CERT#https://api.fakelog.cf/Default/mobile-api#FK100000#ENDCERT")
'27Grk6d8ZDely5eeF7j2ngWrWV9eZa5Dz9ZmuiBavysDp74TCr6EHJOs6TaIXFh3HsROWSM11pv3cPvRGSi7Nw=='
>>> wulkanowy_qr.decode("0123456789ABCDEF", "27Grk6d8ZDely5eeF7j2ngWrWV9eZa5Dz9ZmuiBavysDp74TCr6EHJOs6TaIXFh3HsROWSM11pv3cPvRGSi7Nw==")
'CERT#https://api.fakelog.cf/Default/mobile-api#FK100000#ENDCERT'
```

13
python/pyproject.toml Normal file
View file

@ -0,0 +1,13 @@
[project]
name = "wulkanowy-qr"
version = "1.0.1"
description = "UONET+ QR Code converter for Python"
readme = "README.md"
license = { text = "MIT" }
authors = [{ name = "JelNiSlaw", email = "jelnislaw@gmail.com" }]
urls = { Repository = "https://github.com/wulkanowy/qr/tree/master/python" }
dependencies = ["pycryptodome~=3.15"]
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

25
python/test/__init__.py Normal file
View file

@ -0,0 +1,25 @@
import unittest
import wulkanowy_qr
PASSWORD = "0123456789ABCDEF"
CONTENT = "CERT#https://api.fakelog.cf/Default/mobile-api#FK100000#ENDCERT"
ENCODED = "27Grk6d8ZDely5eeF7j2ngWrWV9eZa5Dz9ZmuiBavysDp74TCr6EHJOs6TaIXFh3HsROWSM11pv3cPvRGSi7Nw=="
class TestEncoding(unittest.TestCase):
def test_encode(self) -> None:
self.assertEqual(wulkanowy_qr.encode(PASSWORD, CONTENT), ENCODED)
def test_decode(self) -> None:
self.assertEqual(wulkanowy_qr.decode(PASSWORD, ENCODED), CONTENT)
def test_both(self) -> None:
self.assertEqual(
CONTENT,
wulkanowy_qr.decode(PASSWORD, wulkanowy_qr.encode(PASSWORD, CONTENT)),
)
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,16 @@
import base64
from Crypto.Cipher import AES
from Crypto.Util import Padding
def encode(password: str, content: str) -> str:
cipher = AES.new(password.encode(), AES.MODE_ECB)
bytes = cipher.encrypt(Padding.pad(content.encode(), 16))
return base64.b64encode(bytes).decode()
def decode(password: str, content: str) -> str:
cipher = AES.new(password.encode(), AES.MODE_ECB)
bytes = cipher.decrypt(base64.b64decode(content))
return Padding.unpad(bytes, 16).decode()