purepython-aes 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,7 @@ from purepython_aes.aes import (
7
7
  AnsiX923Padding,
8
8
  BasePadding,
9
9
  BlockCipherMode,
10
+ CbcMode,
10
11
  EcbMode,
11
12
  Iso7816Padding,
12
13
  Iso10126Padding,
@@ -24,6 +25,7 @@ __all__: list[str] = [
24
25
  'AnsiX923Padding',
25
26
  'BasePadding',
26
27
  'BlockCipherMode',
28
+ 'CbcMode',
27
29
  'EcbMode',
28
30
  'Iso7816Padding',
29
31
  'Iso10126Padding',
@@ -1,6 +1,6 @@
1
1
  from purepython_aes.aes.algorithms import Aes128, Aes192, Aes256
2
2
  from purepython_aes.aes.interface import Aes
3
- from purepython_aes.aes.modes import AesMode, BlockCipherMode, EcbMode
3
+ from purepython_aes.aes.modes import AesMode, BlockCipherMode, CbcMode, EcbMode
4
4
  from purepython_aes.aes.padding import (
5
5
  AnsiX923Padding,
6
6
  BasePadding,
@@ -18,6 +18,7 @@ __all__: list[str] = [
18
18
  'Aes',
19
19
  'AesMode',
20
20
  'BlockCipherMode',
21
+ 'CbcMode',
21
22
  'EcbMode',
22
23
  'AnsiX923Padding',
23
24
  'BasePadding',
@@ -1,4 +1,4 @@
1
1
  from purepython_aes.aes.modes._base import AesMode
2
- from purepython_aes.aes.modes.block import BlockCipherMode, EcbMode
2
+ from purepython_aes.aes.modes.block import BlockCipherMode, CbcMode, EcbMode
3
3
 
4
- __all__: list[str] = ['AesMode', 'BlockCipherMode', 'EcbMode']
4
+ __all__: list[str] = ['AesMode', 'BlockCipherMode', 'CbcMode', 'EcbMode']
@@ -1,4 +1,5 @@
1
1
  from purepython_aes.aes.modes.block._base import BlockCipherMode
2
+ from purepython_aes.aes.modes.block.cbc import CbcMode
2
3
  from purepython_aes.aes.modes.block.ecb import EcbMode
3
4
 
4
- __all__: list[str] = ['BlockCipherMode', 'EcbMode']
5
+ __all__: list[str] = ['BlockCipherMode', 'CbcMode', 'EcbMode']
@@ -0,0 +1,35 @@
1
+ from dataclasses import dataclass
2
+ from secrets import token_bytes
3
+ from typing import final
4
+
5
+ from purepython_aes.aes.modes.block._base import BlockCipherMode
6
+ from purepython_aes.aes.modes.operations import split_into_blocks, xor
7
+ from purepython_aes.const import AES_BLOCK_SIZE
8
+
9
+
10
+ @final
11
+ @dataclass(slots=True)
12
+ class CbcMode(BlockCipherMode):
13
+ """Cipher Block Chaining mode of operation."""
14
+
15
+ def encrypt_blocks(self, padded_plaintext: bytes) -> bytes:
16
+ initialization_vector: bytes = token_bytes(AES_BLOCK_SIZE)
17
+ previous_ciphertext_block: bytes = initialization_vector
18
+ ciphertext_blocks: list[bytes] = [initialization_vector]
19
+ for block in split_into_blocks(padded_plaintext):
20
+ chained_block: bytes = xor(block, previous_ciphertext_block)
21
+ ciphertext_block: bytes = self.algorithm.encrypt_block(chained_block)
22
+ ciphertext_blocks.append(ciphertext_block)
23
+ previous_ciphertext_block = ciphertext_block
24
+ return bytes(0).join(ciphertext_blocks)
25
+
26
+ def decrypt_blocks(self, ciphertext: bytes) -> bytes:
27
+ initialization_vector, *ciphertext_blocks = split_into_blocks(ciphertext)
28
+ previous_ciphertext_block: bytes = initialization_vector
29
+ plaintext_blocks: list[bytes] = []
30
+ for block in ciphertext_blocks:
31
+ decrypted_block: bytes = self.algorithm.decrypt_block(block)
32
+ plaintext_block: bytes = xor(decrypted_block, previous_ciphertext_block)
33
+ plaintext_blocks.append(plaintext_block)
34
+ previous_ciphertext_block = block
35
+ return bytes(0).join(plaintext_blocks)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: purepython-aes
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Pure-Python implementation of AES encryption algorithm.
5
5
  Author-email: Emelianov Artem <penguin5726@proton.me>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
- purepython_aes/__init__.py,sha256=REYvoTsB3HL3wD6AR0T8NJZKfD51VX8aH4bcxUC_xp0,531
1
+ purepython_aes/__init__.py,sha256=ZTJt8dU-dVMCjbnBSdKgLCmPbDqvi_k6ayrqovV9al8,559
2
2
  purepython_aes/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- purepython_aes/aes/__init__.py,sha256=lv_RO-dBRo9IPFtRY0csjkycsyUH7DXW41SZMCaHLV0,628
3
+ purepython_aes/aes/__init__.py,sha256=u5445FnmaG02b5Rb10IIV1axMYQC8pOj8koZTtWO44M,652
4
4
  purepython_aes/aes/interface.py,sha256=OzNhRtS2xu5pOXFF7sAiHkNdSuMHLwaYSRm-0Ldz0Sg,699
5
5
  purepython_aes/aes/algorithms/__init__.py,sha256=L21rL4gaCdoRmV2wyFJyuzFpBI4jXry1uQSi0b0eqds,221
6
6
  purepython_aes/aes/algorithms/aes128.py,sha256=rmv-LJ2dcHIYmTfSTg2xAn-M94ank89ULYZKgpFuoVs,387
@@ -11,11 +11,12 @@ purepython_aes/aes/core/aes.py,sha256=xU1K9cNIek7moVeu-ZDrv3TIQOHTb6SoJsswXX10V3
11
11
  purepython_aes/aes/core/expansion.py,sha256=JmNxuHIV3EzFFDFX2RAnbwKECimovBLrL4O3mfE8UOA,1979
12
12
  purepython_aes/aes/core/operations.py,sha256=4jGJZ3xwRb3z0BLMorF-QCbTdPKAWUVPEvxkUe-5JjU,1989
13
13
  purepython_aes/aes/core/state.py,sha256=j79LDXRabfGAkF2qx8iVKgrSDfEUfFnfKU1XQ-5OidM,5488
14
- purepython_aes/aes/modes/__init__.py,sha256=fwEckEnJ9PGVSWNAXIG9M0KVhSSM7onKeFHwFkcvQ18,183
14
+ purepython_aes/aes/modes/__init__.py,sha256=LkLzTBOyS1cuPbk0oxwTCHvm1w5-eHh_NwbTsyLqBX0,203
15
15
  purepython_aes/aes/modes/_base.py,sha256=L81chTROXrIgNL5GJ1AT9icmixbTT7okfcZ0QyeVaiA,289
16
16
  purepython_aes/aes/modes/operations.py,sha256=VYnoYB0Bb9bfwnApE3tL-2koLK6dDRotit1Pc1cAfhA,460
17
- purepython_aes/aes/modes/block/__init__.py,sha256=TZuLX83Kkf1jhyJztqTIsUsULN8Q56fuUksm6eep_E8,173
17
+ purepython_aes/aes/modes/block/__init__.py,sha256=CsXGcONKMd5QnKRQYle5zOYoRQ1YHXgqAZBp-2jTvOY,239
18
18
  purepython_aes/aes/modes/block/_base.py,sha256=TH6oekojIZluInw8ZLMFpPNuolYQOcxI0QOgsGIWekc,1119
19
+ purepython_aes/aes/modes/block/cbc.py,sha256=JzxXyRu7Q8ZA8_AH7I43Ap5sYnrGyZBZm1i8aU9nLsA,1619
19
20
  purepython_aes/aes/modes/block/ecb.py,sha256=lL1gyIjq768Xe_V6QdWeG9xn5w2G-uTQqOX_cs9MYH4,668
20
21
  purepython_aes/aes/padding/__init__.py,sha256=X_JqBtvuLm1edPoE7B-DnENBHIgwpemhB7d37ZRDQEY,582
21
22
  purepython_aes/aes/padding/_base.py,sha256=dnuNv8OVOBDxAXSUGEeJu5uy9bSFkY2AKkzrK0If8so,408
@@ -31,9 +32,9 @@ purepython_aes/const/sbox.py,sha256=RaSYzs2mjUKZjv0fbEwCD3YLLkoz7emJhjEbU-RH09o,
31
32
  purepython_aes/types/__init__.py,sha256=QiuMSx2DaC2lCXoK16RGeEBrfoX4d3jozkx4QV0kFjc,116
32
33
  purepython_aes/types/finite/__init__.py,sha256=2cYu5Zxdp5NKAwYbV-MD2qamSaJxfqRYp0jOt657-YY,110
33
34
  purepython_aes/types/finite/aliases.py,sha256=gKO8ETbMhV5FX6l3enF8wt246FpMPohreTZ3BPDThBM,1982
34
- purepython_aes-0.1.0.dist-info/METADATA,sha256=EtqJAtIEueHuNorxAbaDbPVE6OV9B1bW4ho8pqVgMXs,2112
35
- purepython_aes-0.1.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
36
- purepython_aes-0.1.0.dist-info/scm_file_list.json,sha256=kfQDdACHcGFPsm09ncINh7o1yMzqwz4yaugdCuK7RFk,3068
37
- purepython_aes-0.1.0.dist-info/scm_version.json,sha256=M8rto4eBaxUN90pVC3CaDYQm6j_D1U-WaRS4PcJkfOM,160
38
- purepython_aes-0.1.0.dist-info/top_level.txt,sha256=IiTUB8OvHhwNXxf6OXKCfUADF7HcQdCRUMfPJC6TS5k,15
39
- purepython_aes-0.1.0.dist-info/RECORD,,
35
+ purepython_aes-0.2.0.dist-info/METADATA,sha256=DIZKs4ZIsGQ8ZljMNgPd0dWUAujarbzQzmWgGJ5erZQ,2112
36
+ purepython_aes-0.2.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
37
+ purepython_aes-0.2.0.dist-info/scm_file_list.json,sha256=Y5c5xPMffftoqRAymXzMJ2WJ-zhscqId_wxRZb87MQ0,3163
38
+ purepython_aes-0.2.0.dist-info/scm_version.json,sha256=IJgEDYtPUbe8ImvyiyQEAgjmVk3WlJEwQ9m3pWC8x3k,160
39
+ purepython_aes-0.2.0.dist-info/top_level.txt,sha256=IiTUB8OvHhwNXxf6OXKCfUADF7HcQdCRUMfPJC6TS5k,15
40
+ purepython_aes-0.2.0.dist-info/RECORD,,
@@ -34,6 +34,7 @@
34
34
  "src/purepython_aes/aes/modes/operations.py",
35
35
  "src/purepython_aes/aes/modes/block/_base.py",
36
36
  "src/purepython_aes/aes/modes/block/__init__.py",
37
+ "src/purepython_aes/aes/modes/block/cbc.py",
37
38
  "src/purepython_aes/aes/modes/block/ecb.py",
38
39
  "src/purepython_aes/aes/algorithms/aes128.py",
39
40
  "src/purepython_aes/aes/algorithms/__init__.py",
@@ -65,6 +66,7 @@
65
66
  "tests/unit/aes/modes/__init__.py",
66
67
  "tests/unit/aes/modes/block/__init__.py",
67
68
  "tests/unit/aes/modes/block/test_ecb.py",
69
+ "tests/unit/aes/modes/block/test_cbc.py",
68
70
  "tests/unit/aes/algorithms/test_aes256.py",
69
71
  "tests/unit/aes/algorithms/__init__.py",
70
72
  "tests/unit/aes/algorithms/test_aes128.py",
@@ -1,7 +1,7 @@
1
1
  {
2
- "tag": "0.1.0",
2
+ "tag": "0.2.0",
3
3
  "distance": 0,
4
- "node": "g18cff6ba62f4743b0f5af672a133edba13f2b244",
4
+ "node": "g6499740a96c2f3a034500f56fa2b3813839c4ba5",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-07-13"