novel-downloader 1.5.0__py3-none-any.whl → 2.0.1__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.
- novel_downloader/__init__.py +1 -1
- novel_downloader/cli/__init__.py +1 -3
- novel_downloader/cli/clean.py +21 -88
- novel_downloader/cli/config.py +26 -21
- novel_downloader/cli/download.py +79 -66
- novel_downloader/cli/export.py +17 -21
- novel_downloader/cli/main.py +1 -1
- novel_downloader/cli/search.py +62 -65
- novel_downloader/cli/ui.py +156 -0
- novel_downloader/config/__init__.py +8 -5
- novel_downloader/config/adapter.py +206 -209
- novel_downloader/config/{loader.py → file_io.py} +53 -26
- novel_downloader/core/__init__.py +5 -5
- novel_downloader/core/archived/deqixs/fetcher.py +115 -0
- novel_downloader/core/archived/deqixs/parser.py +132 -0
- novel_downloader/core/archived/deqixs/searcher.py +89 -0
- novel_downloader/core/{searchers/qidian.py → archived/qidian/searcher.py} +12 -20
- novel_downloader/core/archived/wanbengo/searcher.py +98 -0
- novel_downloader/core/archived/xshbook/searcher.py +93 -0
- novel_downloader/core/downloaders/__init__.py +3 -24
- novel_downloader/core/downloaders/base.py +49 -23
- novel_downloader/core/downloaders/common.py +191 -137
- novel_downloader/core/downloaders/qianbi.py +187 -146
- novel_downloader/core/downloaders/qidian.py +187 -141
- novel_downloader/core/downloaders/registry.py +4 -2
- novel_downloader/core/downloaders/signals.py +46 -0
- novel_downloader/core/exporters/__init__.py +3 -20
- novel_downloader/core/exporters/base.py +33 -37
- novel_downloader/core/exporters/common/__init__.py +1 -2
- novel_downloader/core/exporters/common/epub.py +15 -10
- novel_downloader/core/exporters/common/main_exporter.py +19 -12
- novel_downloader/core/exporters/common/txt.py +17 -12
- novel_downloader/core/exporters/epub_util.py +59 -29
- novel_downloader/core/exporters/linovelib/__init__.py +1 -0
- novel_downloader/core/exporters/linovelib/epub.py +23 -25
- novel_downloader/core/exporters/linovelib/main_exporter.py +8 -12
- novel_downloader/core/exporters/linovelib/txt.py +20 -14
- novel_downloader/core/exporters/qidian.py +2 -8
- novel_downloader/core/exporters/registry.py +4 -2
- novel_downloader/core/exporters/txt_util.py +7 -7
- novel_downloader/core/fetchers/__init__.py +54 -48
- novel_downloader/core/fetchers/aaatxt.py +83 -0
- novel_downloader/core/fetchers/{biquge/session.py → b520.py} +6 -11
- novel_downloader/core/fetchers/{base/session.py → base.py} +37 -46
- novel_downloader/core/fetchers/{biquge/browser.py → biquyuedu.py} +12 -17
- novel_downloader/core/fetchers/dxmwx.py +110 -0
- novel_downloader/core/fetchers/eightnovel.py +139 -0
- novel_downloader/core/fetchers/{esjzone/session.py → esjzone.py} +19 -12
- novel_downloader/core/fetchers/guidaye.py +85 -0
- novel_downloader/core/fetchers/hetushu.py +92 -0
- novel_downloader/core/fetchers/{qianbi/browser.py → i25zw.py} +19 -28
- novel_downloader/core/fetchers/ixdzs8.py +113 -0
- novel_downloader/core/fetchers/jpxs123.py +101 -0
- novel_downloader/core/fetchers/lewenn.py +83 -0
- novel_downloader/core/fetchers/{linovelib/session.py → linovelib.py} +12 -13
- novel_downloader/core/fetchers/piaotia.py +105 -0
- novel_downloader/core/fetchers/qbtr.py +101 -0
- novel_downloader/core/fetchers/{qianbi/session.py → qianbi.py} +5 -10
- novel_downloader/core/fetchers/{qidian/session.py → qidian.py} +56 -64
- novel_downloader/core/fetchers/quanben5.py +92 -0
- novel_downloader/core/fetchers/{base/rate_limiter.py → rate_limiter.py} +2 -2
- novel_downloader/core/fetchers/registry.py +5 -16
- novel_downloader/core/fetchers/{sfacg/session.py → sfacg.py} +7 -10
- novel_downloader/core/fetchers/shencou.py +106 -0
- novel_downloader/core/fetchers/shuhaige.py +84 -0
- novel_downloader/core/fetchers/tongrenquan.py +84 -0
- novel_downloader/core/fetchers/ttkan.py +95 -0
- novel_downloader/core/fetchers/wanbengo.py +83 -0
- novel_downloader/core/fetchers/xiaoshuowu.py +106 -0
- novel_downloader/core/fetchers/xiguashuwu.py +177 -0
- novel_downloader/core/fetchers/xs63b.py +171 -0
- novel_downloader/core/fetchers/xshbook.py +85 -0
- novel_downloader/core/fetchers/{yamibo/session.py → yamibo.py} +19 -12
- novel_downloader/core/fetchers/yibige.py +114 -0
- novel_downloader/core/interfaces/__init__.py +1 -9
- novel_downloader/core/interfaces/downloader.py +6 -2
- novel_downloader/core/interfaces/exporter.py +7 -7
- novel_downloader/core/interfaces/fetcher.py +6 -19
- novel_downloader/core/interfaces/parser.py +7 -8
- novel_downloader/core/interfaces/searcher.py +9 -1
- novel_downloader/core/parsers/__init__.py +49 -12
- novel_downloader/core/parsers/aaatxt.py +132 -0
- novel_downloader/core/parsers/b520.py +116 -0
- novel_downloader/core/parsers/base.py +64 -12
- novel_downloader/core/parsers/biquyuedu.py +133 -0
- novel_downloader/core/parsers/dxmwx.py +162 -0
- novel_downloader/core/parsers/eightnovel.py +224 -0
- novel_downloader/core/parsers/esjzone.py +64 -69
- novel_downloader/core/parsers/guidaye.py +128 -0
- novel_downloader/core/parsers/hetushu.py +139 -0
- novel_downloader/core/parsers/i25zw.py +137 -0
- novel_downloader/core/parsers/ixdzs8.py +186 -0
- novel_downloader/core/parsers/jpxs123.py +137 -0
- novel_downloader/core/parsers/lewenn.py +142 -0
- novel_downloader/core/parsers/linovelib.py +48 -64
- novel_downloader/core/parsers/piaotia.py +189 -0
- novel_downloader/core/parsers/qbtr.py +136 -0
- novel_downloader/core/parsers/qianbi.py +48 -50
- novel_downloader/core/parsers/qidian/main_parser.py +756 -48
- novel_downloader/core/parsers/qidian/utils/__init__.py +3 -21
- novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +1 -1
- novel_downloader/core/parsers/qidian/utils/node_decryptor.py +4 -4
- novel_downloader/core/parsers/quanben5.py +103 -0
- novel_downloader/core/parsers/registry.py +5 -16
- novel_downloader/core/parsers/sfacg.py +38 -45
- novel_downloader/core/parsers/shencou.py +215 -0
- novel_downloader/core/parsers/shuhaige.py +111 -0
- novel_downloader/core/parsers/tongrenquan.py +116 -0
- novel_downloader/core/parsers/ttkan.py +132 -0
- novel_downloader/core/parsers/wanbengo.py +191 -0
- novel_downloader/core/parsers/xiaoshuowu.py +173 -0
- novel_downloader/core/parsers/xiguashuwu.py +429 -0
- novel_downloader/core/parsers/xs63b.py +161 -0
- novel_downloader/core/parsers/xshbook.py +134 -0
- novel_downloader/core/parsers/yamibo.py +87 -131
- novel_downloader/core/parsers/yibige.py +166 -0
- novel_downloader/core/searchers/__init__.py +34 -3
- novel_downloader/core/searchers/aaatxt.py +107 -0
- novel_downloader/core/searchers/{biquge.py → b520.py} +29 -28
- novel_downloader/core/searchers/base.py +112 -36
- novel_downloader/core/searchers/dxmwx.py +105 -0
- novel_downloader/core/searchers/eightnovel.py +84 -0
- novel_downloader/core/searchers/esjzone.py +43 -25
- novel_downloader/core/searchers/hetushu.py +92 -0
- novel_downloader/core/searchers/i25zw.py +93 -0
- novel_downloader/core/searchers/ixdzs8.py +107 -0
- novel_downloader/core/searchers/jpxs123.py +107 -0
- novel_downloader/core/searchers/piaotia.py +100 -0
- novel_downloader/core/searchers/qbtr.py +106 -0
- novel_downloader/core/searchers/qianbi.py +74 -40
- novel_downloader/core/searchers/quanben5.py +144 -0
- novel_downloader/core/searchers/registry.py +24 -8
- novel_downloader/core/searchers/shuhaige.py +124 -0
- novel_downloader/core/searchers/tongrenquan.py +110 -0
- novel_downloader/core/searchers/ttkan.py +92 -0
- novel_downloader/core/searchers/xiaoshuowu.py +122 -0
- novel_downloader/core/searchers/xiguashuwu.py +95 -0
- novel_downloader/core/searchers/xs63b.py +104 -0
- novel_downloader/locales/en.json +34 -85
- novel_downloader/locales/zh.json +35 -86
- novel_downloader/models/__init__.py +21 -22
- novel_downloader/models/book.py +44 -0
- novel_downloader/models/config.py +4 -37
- novel_downloader/models/login.py +1 -1
- novel_downloader/models/search.py +5 -0
- novel_downloader/resources/config/settings.toml +8 -70
- novel_downloader/resources/json/xiguashuwu.json +718 -0
- novel_downloader/utils/__init__.py +13 -24
- novel_downloader/utils/chapter_storage.py +5 -5
- novel_downloader/utils/constants.py +4 -31
- novel_downloader/utils/cookies.py +38 -35
- novel_downloader/utils/crypto_utils/__init__.py +7 -0
- novel_downloader/utils/crypto_utils/aes_util.py +90 -0
- novel_downloader/utils/crypto_utils/aes_v1.py +619 -0
- novel_downloader/utils/crypto_utils/aes_v2.py +1143 -0
- novel_downloader/utils/crypto_utils/rc4.py +54 -0
- novel_downloader/utils/epub/__init__.py +3 -4
- novel_downloader/utils/epub/builder.py +6 -6
- novel_downloader/utils/epub/constants.py +62 -21
- novel_downloader/utils/epub/documents.py +95 -201
- novel_downloader/utils/epub/models.py +8 -22
- novel_downloader/utils/epub/utils.py +73 -106
- novel_downloader/utils/file_utils/__init__.py +2 -23
- novel_downloader/utils/file_utils/io.py +53 -188
- novel_downloader/utils/file_utils/normalize.py +1 -7
- novel_downloader/utils/file_utils/sanitize.py +4 -15
- novel_downloader/utils/fontocr/__init__.py +5 -14
- novel_downloader/utils/fontocr/core.py +216 -0
- novel_downloader/utils/fontocr/loader.py +50 -0
- novel_downloader/utils/logger.py +81 -65
- novel_downloader/utils/network.py +17 -41
- novel_downloader/utils/state.py +4 -90
- novel_downloader/utils/text_utils/__init__.py +1 -7
- novel_downloader/utils/text_utils/diff_display.py +5 -7
- novel_downloader/utils/text_utils/text_cleaner.py +39 -30
- novel_downloader/utils/text_utils/truncate_utils.py +3 -14
- novel_downloader/utils/time_utils/__init__.py +5 -11
- novel_downloader/utils/time_utils/datetime_utils.py +20 -29
- novel_downloader/utils/time_utils/sleep_utils.py +55 -49
- novel_downloader/web/__init__.py +13 -0
- novel_downloader/web/components/__init__.py +11 -0
- novel_downloader/web/components/navigation.py +35 -0
- novel_downloader/web/main.py +66 -0
- novel_downloader/web/pages/__init__.py +17 -0
- novel_downloader/web/pages/download.py +78 -0
- novel_downloader/web/pages/progress.py +147 -0
- novel_downloader/web/pages/search.py +329 -0
- novel_downloader/web/services/__init__.py +17 -0
- novel_downloader/web/services/client_dialog.py +164 -0
- novel_downloader/web/services/cred_broker.py +113 -0
- novel_downloader/web/services/cred_models.py +35 -0
- novel_downloader/web/services/task_manager.py +264 -0
- novel_downloader-2.0.1.dist-info/METADATA +172 -0
- novel_downloader-2.0.1.dist-info/RECORD +206 -0
- {novel_downloader-1.5.0.dist-info → novel_downloader-2.0.1.dist-info}/entry_points.txt +1 -1
- novel_downloader/core/downloaders/biquge.py +0 -29
- novel_downloader/core/downloaders/esjzone.py +0 -29
- novel_downloader/core/downloaders/linovelib.py +0 -29
- novel_downloader/core/downloaders/sfacg.py +0 -29
- novel_downloader/core/downloaders/yamibo.py +0 -29
- novel_downloader/core/exporters/biquge.py +0 -22
- novel_downloader/core/exporters/esjzone.py +0 -22
- novel_downloader/core/exporters/qianbi.py +0 -22
- novel_downloader/core/exporters/sfacg.py +0 -22
- novel_downloader/core/exporters/yamibo.py +0 -22
- novel_downloader/core/fetchers/base/__init__.py +0 -14
- novel_downloader/core/fetchers/base/browser.py +0 -422
- novel_downloader/core/fetchers/biquge/__init__.py +0 -14
- novel_downloader/core/fetchers/esjzone/__init__.py +0 -14
- novel_downloader/core/fetchers/esjzone/browser.py +0 -209
- novel_downloader/core/fetchers/linovelib/__init__.py +0 -14
- novel_downloader/core/fetchers/linovelib/browser.py +0 -198
- novel_downloader/core/fetchers/qianbi/__init__.py +0 -14
- novel_downloader/core/fetchers/qidian/__init__.py +0 -14
- novel_downloader/core/fetchers/qidian/browser.py +0 -326
- novel_downloader/core/fetchers/sfacg/__init__.py +0 -14
- novel_downloader/core/fetchers/sfacg/browser.py +0 -194
- novel_downloader/core/fetchers/yamibo/__init__.py +0 -14
- novel_downloader/core/fetchers/yamibo/browser.py +0 -234
- novel_downloader/core/parsers/biquge.py +0 -139
- novel_downloader/core/parsers/qidian/book_info_parser.py +0 -90
- novel_downloader/core/parsers/qidian/chapter_encrypted.py +0 -528
- novel_downloader/core/parsers/qidian/chapter_normal.py +0 -157
- novel_downloader/core/parsers/qidian/chapter_router.py +0 -68
- novel_downloader/core/parsers/qidian/utils/helpers.py +0 -114
- novel_downloader/models/chapter.py +0 -25
- novel_downloader/models/types.py +0 -13
- novel_downloader/tui/__init__.py +0 -7
- novel_downloader/tui/app.py +0 -32
- novel_downloader/tui/main.py +0 -17
- novel_downloader/tui/screens/__init__.py +0 -14
- novel_downloader/tui/screens/home.py +0 -198
- novel_downloader/tui/screens/login.py +0 -74
- novel_downloader/tui/styles/home_layout.tcss +0 -79
- novel_downloader/tui/widgets/richlog_handler.py +0 -24
- novel_downloader/utils/cache.py +0 -24
- novel_downloader/utils/crypto_utils.py +0 -71
- novel_downloader/utils/fontocr/hash_store.py +0 -280
- novel_downloader/utils/fontocr/hash_utils.py +0 -103
- novel_downloader/utils/fontocr/model_loader.py +0 -69
- novel_downloader/utils/fontocr/ocr_v1.py +0 -315
- novel_downloader/utils/fontocr/ocr_v2.py +0 -764
- novel_downloader/utils/fontocr/ocr_v3.py +0 -744
- novel_downloader-1.5.0.dist-info/METADATA +0 -196
- novel_downloader-1.5.0.dist-info/RECORD +0 -164
- {novel_downloader-1.5.0.dist-info → novel_downloader-2.0.1.dist-info}/WHEEL +0 -0
- {novel_downloader-1.5.0.dist-info → novel_downloader-2.0.1.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-1.5.0.dist-info → novel_downloader-2.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,619 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
novel_downloader.utils.crypto_utils.aes_v1
|
4
|
+
------------------------------------------
|
5
|
+
|
6
|
+
AES block cipher and CBC mode implementation for 128-, 192-, and 256-bit keys.
|
7
|
+
"""
|
8
|
+
|
9
|
+
# fmt: off
|
10
|
+
S_BOX = (
|
11
|
+
# 0 1 2 3 4 5 6 7 8 9 a b c d e f # noqa: E501
|
12
|
+
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, # noqa: E501
|
13
|
+
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, # noqa: E501
|
14
|
+
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, # noqa: E501
|
15
|
+
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, # noqa: E501
|
16
|
+
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, # noqa: E501
|
17
|
+
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, # noqa: E501
|
18
|
+
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, # noqa: E501
|
19
|
+
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, # noqa: E501
|
20
|
+
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, # noqa: E501
|
21
|
+
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, # noqa: E501
|
22
|
+
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, # noqa: E501
|
23
|
+
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, # noqa: E501
|
24
|
+
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, # noqa: E501
|
25
|
+
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, # noqa: E501
|
26
|
+
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, # noqa: E501
|
27
|
+
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, # noqa: E501
|
28
|
+
)
|
29
|
+
|
30
|
+
INV_S_BOX = (
|
31
|
+
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, # noqa: E501
|
32
|
+
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, # noqa: E501
|
33
|
+
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, # noqa: E501
|
34
|
+
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, # noqa: E501
|
35
|
+
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, # noqa: E501
|
36
|
+
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, # noqa: E501
|
37
|
+
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, # noqa: E501
|
38
|
+
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, # noqa: E501
|
39
|
+
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, # noqa: E501
|
40
|
+
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, # noqa: E501
|
41
|
+
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, # noqa: E501
|
42
|
+
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, # noqa: E501
|
43
|
+
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, # noqa: E501
|
44
|
+
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, # noqa: E501
|
45
|
+
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, # noqa: E501
|
46
|
+
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D, # noqa: E501
|
47
|
+
)
|
48
|
+
|
49
|
+
RCON = (
|
50
|
+
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
|
51
|
+
0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
|
52
|
+
# 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
|
53
|
+
# 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
|
54
|
+
)
|
55
|
+
|
56
|
+
XTIME = (
|
57
|
+
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, # noqa: E501
|
58
|
+
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, # noqa: E501
|
59
|
+
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, # noqa: E501
|
60
|
+
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, # noqa: E501
|
61
|
+
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, # noqa: E501
|
62
|
+
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, # noqa: E501
|
63
|
+
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, # noqa: E501
|
64
|
+
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, # noqa: E501
|
65
|
+
0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, # noqa: E501
|
66
|
+
0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, # noqa: E501
|
67
|
+
0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, # noqa: E501
|
68
|
+
0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, # noqa: E501
|
69
|
+
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, # noqa: E501
|
70
|
+
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, # noqa: E501
|
71
|
+
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, # noqa: E501
|
72
|
+
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, # noqa: E501
|
73
|
+
)
|
74
|
+
|
75
|
+
# T0: list[int] = []
|
76
|
+
# for i in range(256):
|
77
|
+
# s = S_BOX[i]
|
78
|
+
# # t = xtime(s)
|
79
|
+
# t = XTIME[s]
|
80
|
+
# T0.append((t << 24) | (s << 16) | (s << 8) | (t ^ s))
|
81
|
+
# T1 = [((v << 24) | (v >> 8)) & 0xFFFFFFFF for v in T0]
|
82
|
+
# T2 = [((v << 16) | (v >> 16)) & 0xFFFFFFFF for v in T0]
|
83
|
+
# T3 = [((v << 8) | (v >> 24)) & 0xFFFFFFFF for v in T0]
|
84
|
+
|
85
|
+
T0 = (
|
86
|
+
0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, # noqa: E501
|
87
|
+
0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, # noqa: E501
|
88
|
+
0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, # noqa: E501
|
89
|
+
0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, # noqa: E501
|
90
|
+
0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, # noqa: E501
|
91
|
+
0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, # noqa: E501
|
92
|
+
0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, # noqa: E501
|
93
|
+
0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, # noqa: E501
|
94
|
+
0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, # noqa: E501
|
95
|
+
0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, # noqa: E501
|
96
|
+
0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, # noqa: E501
|
97
|
+
0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, # noqa: E501
|
98
|
+
0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, # noqa: E501
|
99
|
+
0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, # noqa: E501
|
100
|
+
0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, # noqa: E501
|
101
|
+
0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, # noqa: E501
|
102
|
+
0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, # noqa: E501
|
103
|
+
0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, # noqa: E501
|
104
|
+
0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, # noqa: E501
|
105
|
+
0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, # noqa: E501
|
106
|
+
0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, # noqa: E501
|
107
|
+
0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, # noqa: E501
|
108
|
+
0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, # noqa: E501
|
109
|
+
0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, # noqa: E501
|
110
|
+
0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, # noqa: E501
|
111
|
+
0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, # noqa: E501
|
112
|
+
0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, # noqa: E501
|
113
|
+
0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, # noqa: E501
|
114
|
+
0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, # noqa: E501
|
115
|
+
0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, # noqa: E501
|
116
|
+
0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, # noqa: E501
|
117
|
+
0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, # noqa: E501
|
118
|
+
)
|
119
|
+
T1 = (
|
120
|
+
0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, # noqa: E501
|
121
|
+
0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, # noqa: E501
|
122
|
+
0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, # noqa: E501
|
123
|
+
0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, # noqa: E501
|
124
|
+
0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, # noqa: E501
|
125
|
+
0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, # noqa: E501
|
126
|
+
0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, # noqa: E501
|
127
|
+
0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, # noqa: E501
|
128
|
+
0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, # noqa: E501
|
129
|
+
0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, # noqa: E501
|
130
|
+
0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, # noqa: E501
|
131
|
+
0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, # noqa: E501
|
132
|
+
0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, # noqa: E501
|
133
|
+
0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, # noqa: E501
|
134
|
+
0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, # noqa: E501
|
135
|
+
0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, # noqa: E501
|
136
|
+
0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, # noqa: E501
|
137
|
+
0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, # noqa: E501
|
138
|
+
0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, # noqa: E501
|
139
|
+
0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, # noqa: E501
|
140
|
+
0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, # noqa: E501
|
141
|
+
0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, # noqa: E501
|
142
|
+
0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, # noqa: E501
|
143
|
+
0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, # noqa: E501
|
144
|
+
0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, # noqa: E501
|
145
|
+
0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, # noqa: E501
|
146
|
+
0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, # noqa: E501
|
147
|
+
0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, # noqa: E501
|
148
|
+
0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, # noqa: E501
|
149
|
+
0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, # noqa: E501
|
150
|
+
0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, # noqa: E501
|
151
|
+
0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, # noqa: E501
|
152
|
+
)
|
153
|
+
T2 = (
|
154
|
+
0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, # noqa: E501
|
155
|
+
0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, # noqa: E501
|
156
|
+
0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, # noqa: E501
|
157
|
+
0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, # noqa: E501
|
158
|
+
0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, # noqa: E501
|
159
|
+
0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, # noqa: E501
|
160
|
+
0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, # noqa: E501
|
161
|
+
0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, # noqa: E501
|
162
|
+
0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, # noqa: E501
|
163
|
+
0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, # noqa: E501
|
164
|
+
0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, # noqa: E501
|
165
|
+
0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, # noqa: E501
|
166
|
+
0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, # noqa: E501
|
167
|
+
0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, # noqa: E501
|
168
|
+
0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, # noqa: E501
|
169
|
+
0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, # noqa: E501
|
170
|
+
0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, # noqa: E501
|
171
|
+
0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, # noqa: E501
|
172
|
+
0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, # noqa: E501
|
173
|
+
0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, # noqa: E501
|
174
|
+
0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, # noqa: E501
|
175
|
+
0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, # noqa: E501
|
176
|
+
0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, # noqa: E501
|
177
|
+
0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, # noqa: E501
|
178
|
+
0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, # noqa: E501
|
179
|
+
0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, # noqa: E501
|
180
|
+
0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, # noqa: E501
|
181
|
+
0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, # noqa: E501
|
182
|
+
0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, # noqa: E501
|
183
|
+
0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, # noqa: E501
|
184
|
+
0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, # noqa: E501
|
185
|
+
0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, # noqa: E501
|
186
|
+
)
|
187
|
+
T3 = (
|
188
|
+
0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, # noqa: E501
|
189
|
+
0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, # noqa: E501
|
190
|
+
0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, # noqa: E501
|
191
|
+
0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, # noqa: E501
|
192
|
+
0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, # noqa: E501
|
193
|
+
0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, # noqa: E501
|
194
|
+
0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, # noqa: E501
|
195
|
+
0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, # noqa: E501
|
196
|
+
0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, # noqa: E501
|
197
|
+
0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, # noqa: E501
|
198
|
+
0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, # noqa: E501
|
199
|
+
0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, # noqa: E501
|
200
|
+
0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, # noqa: E501
|
201
|
+
0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, # noqa: E501
|
202
|
+
0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, # noqa: E501
|
203
|
+
0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, # noqa: E501
|
204
|
+
0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, # noqa: E501
|
205
|
+
0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, # noqa: E501
|
206
|
+
0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, # noqa: E501
|
207
|
+
0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, # noqa: E501
|
208
|
+
0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, # noqa: E501
|
209
|
+
0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, # noqa: E501
|
210
|
+
0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, # noqa: E501
|
211
|
+
0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, # noqa: E501
|
212
|
+
0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, # noqa: E501
|
213
|
+
0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, # noqa: E501
|
214
|
+
0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, # noqa: E501
|
215
|
+
0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, # noqa: E501
|
216
|
+
0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, # noqa: E501
|
217
|
+
0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, # noqa: E501
|
218
|
+
0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, # noqa: E501
|
219
|
+
0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, # noqa: E501
|
220
|
+
)
|
221
|
+
# fmt: on
|
222
|
+
|
223
|
+
|
224
|
+
# def xtime(a: int) -> int:
|
225
|
+
# """
|
226
|
+
# Multiply a byte by x (i.e., {02}) in GF(2^8) modulo the AES polynomial.
|
227
|
+
|
228
|
+
# :param a: Single byte as integer.
|
229
|
+
# :return: Resulting byte after xtime operation.
|
230
|
+
# """
|
231
|
+
# return ((a << 1) ^ 0x1B) & 0xFF if (a & 0x80) else (a << 1) & 0xFF
|
232
|
+
|
233
|
+
|
234
|
+
def mix_single_column(a: list[int]) -> list[int]:
|
235
|
+
"""
|
236
|
+
Perform the MixColumns transformation on a single 4-byte column.
|
237
|
+
|
238
|
+
:param a: List of 4 bytes representing one column.
|
239
|
+
:return: New list of 4 bytes after MixColumns.
|
240
|
+
"""
|
241
|
+
t = a[0] ^ a[1] ^ a[2] ^ a[3]
|
242
|
+
# return [
|
243
|
+
# a[0] ^ t ^ xtime(a[0] ^ a[1]),
|
244
|
+
# a[1] ^ t ^ xtime(a[1] ^ a[2]),
|
245
|
+
# a[2] ^ t ^ xtime(a[2] ^ a[3]),
|
246
|
+
# a[3] ^ t ^ xtime(a[3] ^ a[0]),
|
247
|
+
# ]
|
248
|
+
return [
|
249
|
+
a[0] ^ t ^ XTIME[a[0] ^ a[1]],
|
250
|
+
a[1] ^ t ^ XTIME[a[1] ^ a[2]],
|
251
|
+
a[2] ^ t ^ XTIME[a[2] ^ a[3]],
|
252
|
+
a[3] ^ t ^ XTIME[a[3] ^ a[0]],
|
253
|
+
]
|
254
|
+
|
255
|
+
|
256
|
+
def gf_mul(a: int, b: int) -> int:
|
257
|
+
"""
|
258
|
+
Multiply two bytes in GF(2^8) using Russian peasant multiplication.
|
259
|
+
|
260
|
+
:param a: First byte as integer.
|
261
|
+
:param b: Second byte as integer.
|
262
|
+
:return: Product in GF(2^8).
|
263
|
+
"""
|
264
|
+
res = 0
|
265
|
+
while b:
|
266
|
+
if b & 1:
|
267
|
+
res ^= a
|
268
|
+
hi = a & 0x80
|
269
|
+
a = ((a << 1) & 0xFF) ^ (0x1B if hi else 0)
|
270
|
+
b >>= 1
|
271
|
+
return res
|
272
|
+
|
273
|
+
|
274
|
+
MUL = {
|
275
|
+
0x09: [gf_mul(x, 0x09) for x in range(256)],
|
276
|
+
0x0B: [gf_mul(x, 0x0B) for x in range(256)],
|
277
|
+
0x0D: [gf_mul(x, 0x0D) for x in range(256)],
|
278
|
+
0x0E: [gf_mul(x, 0x0E) for x in range(256)],
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
class AES:
|
283
|
+
"""
|
284
|
+
AES block cipher core. Handles key expansion and single-block encryption/decryption.
|
285
|
+
Supports 128-, 192-, and 256-bit keys.
|
286
|
+
"""
|
287
|
+
|
288
|
+
def __init__(self, key: bytes):
|
289
|
+
"""
|
290
|
+
Initialize AES context with the provided key.
|
291
|
+
|
292
|
+
:param key: Raw key bytes (length 16, 24, or 32).
|
293
|
+
:raises ValueError: If key length is invalid.
|
294
|
+
"""
|
295
|
+
self.nk = len(key) // 4
|
296
|
+
if self.nk not in (4, 6, 8):
|
297
|
+
raise ValueError("Invalid key size")
|
298
|
+
self.nb = 4
|
299
|
+
self.nr = {4: 10, 6: 12, 8: 14}[self.nk]
|
300
|
+
self.key = key
|
301
|
+
self.w = self.key_expansion()
|
302
|
+
self.round_keys = self._expand_round_keys()
|
303
|
+
|
304
|
+
def key_expansion(self) -> list[int]:
|
305
|
+
"""
|
306
|
+
Expand the cipher key into the key schedule (words).
|
307
|
+
|
308
|
+
:return: List of 32-bit words for all rounds.
|
309
|
+
"""
|
310
|
+
w = []
|
311
|
+
for i in range(self.nk):
|
312
|
+
w.append(int.from_bytes(self.key[4 * i : 4 * (i + 1)], "big"))
|
313
|
+
for i in range(self.nk, self.nb * (self.nr + 1)):
|
314
|
+
temp = w[i - 1]
|
315
|
+
if i % self.nk == 0:
|
316
|
+
temp = (
|
317
|
+
(S_BOX[(temp >> 16) & 0xFF] << 24)
|
318
|
+
| (S_BOX[(temp >> 8) & 0xFF] << 16)
|
319
|
+
| (S_BOX[temp & 0xFF] << 8)
|
320
|
+
| (S_BOX[(temp >> 24) & 0xFF])
|
321
|
+
)
|
322
|
+
temp ^= RCON[i // self.nk] << 24
|
323
|
+
elif self.nk > 6 and i % self.nk == 4:
|
324
|
+
temp = (
|
325
|
+
(S_BOX[(temp >> 24) & 0xFF] << 24)
|
326
|
+
| (S_BOX[(temp >> 16) & 0xFF] << 16)
|
327
|
+
| (S_BOX[(temp >> 8) & 0xFF] << 8)
|
328
|
+
| S_BOX[temp & 0xFF]
|
329
|
+
)
|
330
|
+
w.append(w[i - self.nk] ^ temp)
|
331
|
+
return w
|
332
|
+
|
333
|
+
def _expand_round_keys(self) -> list[list[int]]:
|
334
|
+
"""
|
335
|
+
Transform the expanded key words into per-round byte arrays.
|
336
|
+
|
337
|
+
:return: List of round key byte lists.
|
338
|
+
"""
|
339
|
+
round_keys = []
|
340
|
+
for r in range(self.nr + 1):
|
341
|
+
key_bytes = []
|
342
|
+
for j in range(self.nb):
|
343
|
+
word = self.w[r * self.nb + j]
|
344
|
+
key_bytes += [
|
345
|
+
(word >> 24) & 0xFF,
|
346
|
+
(word >> 16) & 0xFF,
|
347
|
+
(word >> 8) & 0xFF,
|
348
|
+
word & 0xFF,
|
349
|
+
]
|
350
|
+
round_keys.append(key_bytes)
|
351
|
+
return round_keys
|
352
|
+
|
353
|
+
def encrypt_block(self, plaintext: bytes) -> bytes:
|
354
|
+
"""
|
355
|
+
Encrypt a single 16-byte block under the AES cipher.
|
356
|
+
|
357
|
+
:param plaintext: 16-byte plaintext block.
|
358
|
+
:return: 16-byte ciphertext block.
|
359
|
+
"""
|
360
|
+
# state = [[0] * 4 for _ in range(4)]
|
361
|
+
# for r in range(4):
|
362
|
+
# for c in range(4):
|
363
|
+
# state[r][c] = plaintext[4 * c + r]
|
364
|
+
# self._add_round_key(state, 0)
|
365
|
+
# for r in range(1, self.nr):
|
366
|
+
# self._sub_bytes(state)
|
367
|
+
# self._shift_rows(state)
|
368
|
+
# self._mix_columns(state)
|
369
|
+
# self._add_round_key(state, r)
|
370
|
+
# self._sub_bytes(state)
|
371
|
+
# self._shift_rows(state)
|
372
|
+
# self._add_round_key(state, self.nr)
|
373
|
+
# out = bytearray(16)
|
374
|
+
# for r in range(4):
|
375
|
+
# for c in range(4):
|
376
|
+
# out[4 * c + r] = state[r][c]
|
377
|
+
# return bytes(out)
|
378
|
+
|
379
|
+
state = [int.from_bytes(plaintext[4 * i : 4 * i + 4], "big") for i in range(4)]
|
380
|
+
# initial AddRoundKey
|
381
|
+
for i in range(4):
|
382
|
+
state[i] ^= self.w[i]
|
383
|
+
|
384
|
+
# nr-1 full rounds via T-tables
|
385
|
+
for r in range(1, self.nr):
|
386
|
+
t0 = (
|
387
|
+
T0[state[0] >> 24]
|
388
|
+
^ T1[(state[1] >> 16) & 0xFF]
|
389
|
+
^ T2[(state[2] >> 8) & 0xFF]
|
390
|
+
^ T3[state[3] & 0xFF]
|
391
|
+
^ self.w[4 * r + 0]
|
392
|
+
)
|
393
|
+
t1 = (
|
394
|
+
T0[state[1] >> 24]
|
395
|
+
^ T1[(state[2] >> 16) & 0xFF]
|
396
|
+
^ T2[(state[3] >> 8) & 0xFF]
|
397
|
+
^ T3[state[0] & 0xFF]
|
398
|
+
^ self.w[4 * r + 1]
|
399
|
+
)
|
400
|
+
t2 = (
|
401
|
+
T0[state[2] >> 24]
|
402
|
+
^ T1[(state[3] >> 16) & 0xFF]
|
403
|
+
^ T2[(state[0] >> 8) & 0xFF]
|
404
|
+
^ T3[state[1] & 0xFF]
|
405
|
+
^ self.w[4 * r + 2]
|
406
|
+
)
|
407
|
+
t3 = (
|
408
|
+
T0[state[3] >> 24]
|
409
|
+
^ T1[(state[0] >> 16) & 0xFF]
|
410
|
+
^ T2[(state[1] >> 8) & 0xFF]
|
411
|
+
^ T3[state[2] & 0xFF]
|
412
|
+
^ self.w[4 * r + 3]
|
413
|
+
)
|
414
|
+
state = [t0, t1, t2, t3]
|
415
|
+
|
416
|
+
# final round: SubBytes + ShiftRows + AddRoundKey
|
417
|
+
out = bytearray(16)
|
418
|
+
last_rk = self.round_keys[self.nr]
|
419
|
+
for c in range(4):
|
420
|
+
for r in range(4):
|
421
|
+
sc = (c + r) & 3
|
422
|
+
byte = (state[sc] >> (24 - 8 * r)) & 0xFF
|
423
|
+
out[4 * c + r] = S_BOX[byte] ^ last_rk[4 * c + r]
|
424
|
+
return bytes(out)
|
425
|
+
|
426
|
+
def decrypt_block(self, ciphertext: bytes) -> bytes:
|
427
|
+
"""
|
428
|
+
Decrypt a single 16-byte block under the AES cipher.
|
429
|
+
|
430
|
+
:param ciphertext: 16-byte ciphertext block.
|
431
|
+
:return: 16-byte plaintext block.
|
432
|
+
"""
|
433
|
+
state = [[0] * 4 for _ in range(4)]
|
434
|
+
for r in range(4):
|
435
|
+
for c in range(4):
|
436
|
+
state[r][c] = ciphertext[4 * c + r]
|
437
|
+
self._add_round_key(state, self.nr)
|
438
|
+
self._inv_shift_rows(state)
|
439
|
+
self._inv_sub_bytes(state)
|
440
|
+
for r in range(self.nr - 1, 0, -1):
|
441
|
+
self._add_round_key(state, r)
|
442
|
+
self._inv_mix_columns(state)
|
443
|
+
self._inv_shift_rows(state)
|
444
|
+
self._inv_sub_bytes(state)
|
445
|
+
self._add_round_key(state, 0)
|
446
|
+
out = bytearray(16)
|
447
|
+
for r in range(4):
|
448
|
+
for c in range(4):
|
449
|
+
out[4 * c + r] = state[r][c]
|
450
|
+
return bytes(out)
|
451
|
+
|
452
|
+
def _add_round_key(self, state: list[list[int]], rnd: int) -> None:
|
453
|
+
"""
|
454
|
+
XOR the state with the round key of the given round.
|
455
|
+
|
456
|
+
:param state: 4x4 state matrix of bytes.
|
457
|
+
:param rnd: Round index.
|
458
|
+
"""
|
459
|
+
key = self.round_keys[rnd]
|
460
|
+
for r in range(4):
|
461
|
+
for c in range(4):
|
462
|
+
state[r][c] ^= key[4 * c + r]
|
463
|
+
|
464
|
+
def _sub_bytes(self, state: list[list[int]]) -> None:
|
465
|
+
"""
|
466
|
+
Apply the SubBytes transformation to the state.
|
467
|
+
|
468
|
+
:param state: 4x4 state matrix of bytes.
|
469
|
+
"""
|
470
|
+
for r in range(4):
|
471
|
+
for c in range(4):
|
472
|
+
state[r][c] = S_BOX[state[r][c]]
|
473
|
+
|
474
|
+
def _inv_sub_bytes(self, state: list[list[int]]) -> None:
|
475
|
+
"""
|
476
|
+
Apply the InvSubBytes transformation to the state.
|
477
|
+
|
478
|
+
:param state: 4x4 state matrix of bytes.
|
479
|
+
"""
|
480
|
+
for r in range(4):
|
481
|
+
for c in range(4):
|
482
|
+
state[r][c] = INV_S_BOX[state[r][c]]
|
483
|
+
|
484
|
+
def _shift_rows(self, state: list[list[int]]) -> None:
|
485
|
+
"""
|
486
|
+
Rotate the rows of the state left by increasing offsets.
|
487
|
+
|
488
|
+
:param state: 4x4 state matrix of bytes.
|
489
|
+
"""
|
490
|
+
state[1] = state[1][1:] + state[1][:1]
|
491
|
+
state[2] = state[2][2:] + state[2][:2]
|
492
|
+
state[3] = state[3][3:] + state[3][:3]
|
493
|
+
|
494
|
+
def _inv_shift_rows(self, state: list[list[int]]) -> None:
|
495
|
+
"""
|
496
|
+
Rotate the rows of the state right by increasing offsets.
|
497
|
+
|
498
|
+
:param state: 4x4 state matrix of bytes.
|
499
|
+
"""
|
500
|
+
state[1] = state[1][-1:] + state[1][:-1]
|
501
|
+
state[2] = state[2][-2:] + state[2][:-2]
|
502
|
+
state[3] = state[3][-3:] + state[3][:-3]
|
503
|
+
|
504
|
+
def _mix_columns(self, state: list[list[int]]) -> None:
|
505
|
+
"""
|
506
|
+
Apply the MixColumns step to all columns of the state.
|
507
|
+
|
508
|
+
:param state: 4x4 state matrix of bytes.
|
509
|
+
"""
|
510
|
+
# for c in range(4):
|
511
|
+
# col = [state[r][c] for r in range(4)]
|
512
|
+
# mix = mix_single_column(col)
|
513
|
+
# for r in range(4):
|
514
|
+
# state[r][c] = mix[r]
|
515
|
+
for c in range(4):
|
516
|
+
a0, a1, a2, a3 = (state[r][c] for r in range(4))
|
517
|
+
state[0][c] = MUL[0x0E][a0] ^ MUL[0x0B][a1] ^ MUL[0x0D][a2] ^ MUL[0x09][a3]
|
518
|
+
state[1][c] = MUL[0x09][a0] ^ MUL[0x0E][a1] ^ MUL[0x0B][a2] ^ MUL[0x0D][a3]
|
519
|
+
state[2][c] = MUL[0x0D][a0] ^ MUL[0x09][a1] ^ MUL[0x0E][a2] ^ MUL[0x0B][a3]
|
520
|
+
state[3][c] = MUL[0x0B][a0] ^ MUL[0x0D][a1] ^ MUL[0x09][a2] ^ MUL[0x0E][a3]
|
521
|
+
|
522
|
+
def _inv_mix_columns(self, state: list[list[int]]) -> None:
|
523
|
+
"""
|
524
|
+
Apply the InvMixColumns step to all columns of the state.
|
525
|
+
|
526
|
+
:param state: 4x4 state matrix of bytes.
|
527
|
+
"""
|
528
|
+
for c in range(4):
|
529
|
+
a = [state[r][c] for r in range(4)]
|
530
|
+
state[0][c] = (
|
531
|
+
gf_mul(a[0], 0x0E)
|
532
|
+
^ gf_mul(a[1], 0x0B)
|
533
|
+
^ gf_mul(a[2], 0x0D)
|
534
|
+
^ gf_mul(a[3], 0x09)
|
535
|
+
)
|
536
|
+
state[1][c] = (
|
537
|
+
gf_mul(a[0], 0x09)
|
538
|
+
^ gf_mul(a[1], 0x0E)
|
539
|
+
^ gf_mul(a[2], 0x0B)
|
540
|
+
^ gf_mul(a[3], 0x0D)
|
541
|
+
)
|
542
|
+
state[2][c] = (
|
543
|
+
gf_mul(a[0], 0x0D)
|
544
|
+
^ gf_mul(a[1], 0x09)
|
545
|
+
^ gf_mul(a[2], 0x0E)
|
546
|
+
^ gf_mul(a[3], 0x0B)
|
547
|
+
)
|
548
|
+
state[3][c] = (
|
549
|
+
gf_mul(a[0], 0x0B)
|
550
|
+
^ gf_mul(a[1], 0x0D)
|
551
|
+
^ gf_mul(a[2], 0x09)
|
552
|
+
^ gf_mul(a[3], 0x0E)
|
553
|
+
)
|
554
|
+
|
555
|
+
|
556
|
+
class AES_CBC(AES):
|
557
|
+
"""
|
558
|
+
AES in CBC mode with PKCS#7 padding.
|
559
|
+
"""
|
560
|
+
|
561
|
+
def __init__(
|
562
|
+
self,
|
563
|
+
key: bytes,
|
564
|
+
iv: bytes | None = None,
|
565
|
+
) -> None:
|
566
|
+
"""
|
567
|
+
Initialize CBC context with key and IV.
|
568
|
+
|
569
|
+
:param key: Raw AES key bytes (16/24/32 bytes).
|
570
|
+
:param iv: Initialization vector (16 bytes). If None, defaults to zero IV.
|
571
|
+
:raises ValueError: If IV length is invalid.
|
572
|
+
"""
|
573
|
+
super().__init__(key)
|
574
|
+
self.block_size = 16
|
575
|
+
self.iv = iv or bytes([0] * 16)
|
576
|
+
if len(self.iv) != 16:
|
577
|
+
raise ValueError("Invalid IV size")
|
578
|
+
|
579
|
+
def encrypt(self, plaintext: bytes) -> bytes:
|
580
|
+
"""
|
581
|
+
Encrypt data with AES-CBC, adding PKCS#7 padding.
|
582
|
+
|
583
|
+
:param plaintext: Arbitrary-length plaintext bytes.
|
584
|
+
:return: Ciphertext bytes (multiple of 16).
|
585
|
+
"""
|
586
|
+
pad_len = self.block_size - (len(plaintext) % self.block_size)
|
587
|
+
plaintext += bytes([pad_len]) * pad_len
|
588
|
+
ciphertext = b""
|
589
|
+
prev = self.iv
|
590
|
+
for i in range(0, len(plaintext), self.block_size):
|
591
|
+
block = plaintext[i : i + self.block_size]
|
592
|
+
xored = bytes(a ^ b for a, b in zip(block, prev, strict=False))
|
593
|
+
enc = self.encrypt_block(xored)
|
594
|
+
ciphertext += enc
|
595
|
+
prev = enc
|
596
|
+
return ciphertext
|
597
|
+
|
598
|
+
def decrypt(self, ciphertext: bytes) -> bytes:
|
599
|
+
"""
|
600
|
+
Decrypt AES-CBC data and remove PKCS#7 padding.
|
601
|
+
|
602
|
+
:param ciphertext: Ciphertext bytes (must be multiple of 16).
|
603
|
+
:return: Plaintext bytes.
|
604
|
+
:raises ValueError: If ciphertext length is invalid or padding is incorrect.
|
605
|
+
"""
|
606
|
+
if len(ciphertext) % self.block_size != 0:
|
607
|
+
raise ValueError("Invalid ciphertext length")
|
608
|
+
plaintext = b""
|
609
|
+
prev = self.iv
|
610
|
+
for i in range(0, len(ciphertext), self.block_size):
|
611
|
+
block = ciphertext[i : i + self.block_size]
|
612
|
+
dec = self.decrypt_block(block)
|
613
|
+
xored = bytes(a ^ b for a, b in zip(dec, prev, strict=False))
|
614
|
+
plaintext += xored
|
615
|
+
prev = block
|
616
|
+
pad_len = plaintext[-1]
|
617
|
+
if pad_len < 1 or pad_len > self.block_size:
|
618
|
+
raise ValueError("Invalid padding")
|
619
|
+
return plaintext[:-pad_len]
|