Discussion:
Python i klasy oraz dawka magii czyli niezrozumienie
(Wiadomość utworzona zbyt dawno temu. Odpowiedź niemożliwa.)
Roman Tyczka
2021-03-03 11:57:19 UTC
Permalink
Używam biblioteki Cryptography (https://github.com/pyca/cryptography) i
ona oferuje dla szyfrów blokowych klasy, które obsługują tryby mieszania
bloków. Użycie trybów z konkretnym algorytmem szyfrującym, dla tych
samych danych wejściowych, zwraca inny wynik, i to jest oczekiwane
zachowanie.

Ale nie mogę pojąć jak to jest zrobione od strony języka, bo gdy patrzę
na klasy trybów to niektóre się niczym nie różnią, a wynik ich użycia
daje inne efekty, np. takie trzy tryby OFB, CFB i CFB8:

class OFB(Mode, ModeWithInitializationVector):
name = "OFB"

def __init__(self, initialization_vector: bytes):
utils._check_byteslike("initialization_vector",
initialization_vector)
self._initialization_vector = initialization_vector

initialization_vector =
utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_and_key_length


class CFB(Mode, ModeWithInitializationVector):
name = "CFB"

def __init__(self, initialization_vector: bytes):
utils._check_byteslike("initialization_vector",
initialization_vector)
self._initialization_vector = initialization_vector

initialization_vector =
utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_and_key_length


class CFB8(Mode, ModeWithInitializationVector):
name = "CFB8"

def __init__(self, initialization_vector: bytes):
utils._check_byteslike("initialization_vector",
initialization_vector)
self._initialization_vector = initialization_vector

initialization_vector =
utils.read_only_property("_initialization_vector")
validate_for_algorithm = _check_iv_and_key_length

Poza polem "name" każda klasa jest identyczna, a jednak wynik jest inny.
Jak to działa?

Kod powyższy jest w pliku:

https://github.com/pyca/cryptography/blob/main/src/cryptography/hazmat/primitives/ciphers/modes.py


Przykład szyfrowania z algorytmem AES:

import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms,
modes
key = os.urandom(32)
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
ct = encryptor.update(b"a secret message") + encryptor.finalize()

Dokumentacja biblioteki:

https://cryptography.io/en/latest/hazmat/primitives/symmetric-encryption.html
--
pzdr
Roman
Piotr Wladyka
2021-06-30 13:04:45 UTC
Permalink
środa, 3 marca 2021 o 12:58:08 UTC+1 Roman Tyczka napisał(a):

[ - CIACH - ]
Post by Roman Tyczka
Ale nie mogę pojąć jak to jest zrobione od strony języka, bo gdy patrzę
na klasy trybów to niektóre się niczym nie różnią, a wynik ich użycia
name = "OFB"
[ - CIACH - ]
Post by Roman Tyczka
Poza polem "name" każda klasa jest identyczna, a jednak wynik jest inny.
Jak to działa?
Odpowiedź masz na samym początku:

- - - - - - -
import abc
import typing

from cryptography import utils
from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm


class Mode(metaclass=abc.ABCMeta):
@abc.abstractproperty
def name(self) -> str:
"""
A string naming this mode (e.g. "ECB", "CBC").
"""
- - - - - - -

Autor używa mata-klas, prawdopodobnie dlatego, że pakiet jest napisany dla różnych wersji pythona (CPython, PyPy, Py+Rust), więc rzeczywista implementacja algorytmu siedzi głębiej (wybór "kawałków kodu do późniejszego użycia" odbywa się jeszcze na poziomie instalacji modułu - pip, ... etc) , a właśnie zmienna "Mode.name" służy do wyboju już konkretnej metody spośród "dostępnych dla tego środowiska".
---
pzdr,
Vlad P.
Roman Tyczka
2021-06-30 13:36:19 UTC
Permalink
Post by Piotr Wladyka
Post by Roman Tyczka
Poza polem "name" każda klasa jest identyczna, a jednak wynik jest inny.
Jak to działa?
- - - - - - -
import abc
import typing
from cryptography import utils
from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm
@abc.abstractproperty
"""
A string naming this mode (e.g. "ECB", "CBC").
"""
- - - - - - -
Autor używa mata-klas, prawdopodobnie dlatego, że pakiet jest napisany dla różnych wersji pythona (CPython, PyPy, Py+Rust), więc rzeczywista implementacja algorytmu siedzi głębiej (wybór "kawałków kodu do późniejszego użycia" odbywa się jeszcze na poziomie instalacji modułu - pip, ... etc) , a właśnie zmienna "Mode.name" służy do wyboju już konkretnej metody spośród "dostępnych dla tego środowiska".
Thx!

A co konkretnie robi ten zapis:

def name(self) -> str:
"""
A string naming this mode (e.g. "ECB", "CBC").
"""

Jak go czytać, co wykonuje?
--
pzdr
Roman
Piotr Wladyka
2021-06-30 14:49:47 UTC
Permalink
Post by Piotr Wladyka
"""
A string naming this mode (e.g. "ECB", "CBC").
"""
Jak go czytać, co wykonuje?
Pierwsza linijka, z tego, co pamiętam, to rzadko używane w pythonie (jeśli nie kombinujemy z numPy, PyPy, tudzież interfejsami do bibliotek napisanych w C/C++) rozszerzenie mające wymuszać string-type na wyjściu funkcji "name()" - nie wiem jak i kiedy działa, bo sam nigdy nie używałem.

Reszta to klasyczny help/komentarz do funkcji wyświetlany po wywołaniu np "help(Mode.name)" bądź "ECB.name.__doc__".

Dużo bardziej tutaj istotna jest linia:
- - - - -
@abc.abstractproperty
- - - - -
nad "def name...", ale to jest właśnie część meta-programingu - tematyka szeroka i dosyć mocno abstrakcyjna. Chyba musiałbym się pobawić kodem żeby samemu wyczaić o co konkretnie chodzi.

Tak na szybkiego zajrzałem w pakiet (np. plik "main/src/cryptography/hazmat/backends/openssl/backend.py" daje pewien ogólny zarys) i wygląda na to, że powodem użycia meta-programmingu jest nie różnorodność środowisk (jak napisałem), ale sama idea algorytmu: parser składający/odczytujący poszczególne pola na interfejsie (ASN1). To mi wystarczy żeby nie włazić głębiej - rozczajanie kodu zazwyczaj bywa bardziej czasochłonne niż jego pisanie. ;)

---
pzdr,
Vlad P
slawek
2021-07-01 13:09:55 UTC
Permalink
środa, 30 czerwca 2021 o 15:36:51 UTC+2 Roman Tyczka napisał(a):> A co konkretnie robi ten zapis:> def name(self) -> str: > """ > A string naming this mode (e.g. "ECB", "CBC"). > """> Jak go czytać, co wykonuje? Pierwsza linijka, z tego, co pamiętam, to rzadko używane w pythonie (jeśli nie kombinujemy z numPy, PyPy, tudzież interfejsami do bibliotek napisanych w C/C++) rozszerzenie mające wymuszać string-type na wyjściu funkcji "name()" - nie wiem ...
Taka strzałka -> jest w standardowym Pythonie - można, ale nie
trzeba, dać adnotację o typie zwracanym. Podobnie można dać
adnotacje co do typów parametrów. W zasadzie Python tego nie
potrzebuje, ale jak ktoś lubi... Ja nie lubię.

Upieranie się że zmienna ma typ jest w Pythonie bez sensu. Robią
tak zwykle ludzie nowi, obciążeni nawykami z innych
języków.

Poniżej def jest zupełnie zwykły string. Samotny. Luzem w kodzie.
Taki string nic nie robi, ale jest konsensus że tak się pisze
komentarz dokumentacyjny. Jak wywołasz help(mame) na konsoli to
go zobaczysz. Wyszukaj sobie "stringdoc Python".

Klasy jakie zapodałeś nie są jednakowe - różnią się szczegółami.

self może równie dobrze być this albo dziumdziuś, ważne że to
pierwszy parametr.

Jak ktoś pisze metafetazenfzeta=mymeta jako parametr to
niespecjalnie musi to mieć cokolwiek z metaklasami. Bo to jest
tylko zdefiniowanie parametru metafetazenfzeta z domyślną
wartością mymeta. Nazwy jak nazwy, utf8 wszystko przyjmie, byle
nie były keywords.

Metaklasy to inna bajka.


----Android NewsGroup Reader----
http://usenet.sinaapp.com/

Loading...