Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
e182eeb
feat: add IPv6 support to ipwords with auto-detect by name length
IMDelewer May 16, 2026
29d13ce
test: add IPv6 roundtrip, boundary, and auto-detect tests
IMDelewer May 16, 2026
02113ef
docs: update AGENTS.md and README for new name format and IPv6
IMDelewer May 16, 2026
5ccba84
feat: add local_ipv6() to net utils
IMDelewer May 16, 2026
74897a7
feat: add IPv6 server support (AF_INET6, auto-detect by host)
IMDelewer May 16, 2026
af2c9d1
fix: use getaddrinfo to find real local IPv6 address
IMDelewer May 16, 2026
609d7ac
feat: add app name/version to cert subject, fognode version in issuer OU
IMDelewer May 16, 2026
1bc0a7a
feat: add app_name/app_version to start_server, regenerate cert on ch…
IMDelewer May 16, 2026
384fb9a
feat: add name/version params to Server class
IMDelewer May 16, 2026
f809f80
feat: add --name and --app-version to server CLI command
IMDelewer May 16, 2026
83e62d8
feat: check server/client fognode version compatibility on connect
IMDelewer May 16, 2026
d3ad962
fix: regenerate cert when fognode version changes in issuer OU
IMDelewer May 16, 2026
0a94949
fix: fall back to IPv4 when no routable IPv6, use dual-stack socket f…
IMDelewer May 16, 2026
69ed832
feat: return and display server app info on client connect
IMDelewer May 16, 2026
460594b
fix: remove chain verification for non-self-signed cert, rely on fp i…
IMDelewer May 16, 2026
43e02f5
fix: correct iv_p state update in _ige_decrypt for multi-block messages
IMDelewer May 16, 2026
45e3a84
fix: update cert regeneration check to match new issuer format
IMDelewer May 16, 2026
65bc563
fix: update version compat check to use new issuer OU prefix
IMDelewer May 16, 2026
fb4e14c
feat: add msgpack dependency
IMDelewer May 16, 2026
4667ec2
feat: replace json with msgpack in SecureChannel
IMDelewer May 16, 2026
da52402
feat: replace json with msgpack in wire framing
IMDelewer May 16, 2026
f51c0b7
style: suppress pyright reportMissingImports for msgpack
IMDelewer May 16, 2026
4559a16
test: update framing tests for msgpack
IMDelewer May 16, 2026
a85ee4f
feat: add custom msgpack implementation with tests
IMDelewer May 16, 2026
e9e5f04
feat: switch channel to local msgpack
IMDelewer May 16, 2026
7b39f3a
feat: switch framing to local msgpack
IMDelewer May 16, 2026
8c187d5
feat: replace external msgpack with local implementation
IMDelewer May 16, 2026
b6d764e
feat: introduce integer message type constants, replace string types …
IMDelewer May 16, 2026
77170c5
feat: log probe attempts from nmap/netcat/TLS scanners
IMDelewer May 16, 2026
f793fbf
refactor: remove CMD types, client sends INFO directly
IMDelewer May 16, 2026
ad43861
feat: add -pV flag for verbose probe logging with hex dump and details
IMDelewer May 16, 2026
1fb70d3
feat: update issuer cn, o, ou
IMDelewer May 16, 2026
7f436de
Merge 1fb70d3161b7c7c95b9c681852b1456567fd62a2 into 7ff2eecebadf1dc42…
IMDelewer May 16, 2026
102ec2e
docs: update CHANGELOG.md for PR #4
github-actions[bot] May 16, 2026
63159dc
fix: restore valid pytest.mark.parametrize arg names after linter man…
IMDelewer May 16, 2026
87103dc
style: fix black, ruff
IMDelewer May 16, 2026
5300d8a
Merge 87103dcce34b6cba2cb66bd40aba03c7f73ba8da into 7ff2eecebadf1dc42…
IMDelewer May 16, 2026
cf9099a
docs: update CHANGELOG.md for PR #4
github-actions[bot] May 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ src/fognode/
│ ├── exceptions.py # SecurityError, AuthError, etc.
│ └── protocol.py # TypedDicts, dataclasses, Protocols
├── utils/
│ ├── ipwords.py # IP ↔ 4-word codename conversion
│ ├── ipwords.py # IP ↔ short name: 6 chars (IPv4) or 23 chars (IPv6), auto-detected
│ ├── net.py # local_ip()
│ └── ratelimit.py # RateLimiter
└── wire/
Expand Down Expand Up @@ -125,9 +125,9 @@ python -m build
### Run the CLI
```bash
python -m fognode server --host 0.0.0.0 --port 9443 --user alice --password secret
fognode client alice@oak-pine-stone-field:9443 --password secret
fognode probe alice@oak-pine-stone-field:9443
fognode status alice@oak-pine-stone-field:9443 --password secret
fognode client alice@7sf9Tn:9443 --password secret
fognode probe alice@7sf9Tn:9443
fognode status alice@7sf9Tn:9443 --password secret
```

## Code Style Guidelines
Expand Down Expand Up @@ -179,15 +179,15 @@ fognode status alice@oak-pine-stone-field:9443 --password secret
- `ChatState` is a **global singleton** (`_state` in `core/server.py`) protected by a `threading.Lock`.

### Client Lifecycle
- `client_connect()` resolves the 4-word code name to an IP via `name_to_ip()`.
- `client_connect()` resolves the short code name to an IP via `name_to_ip()` (auto-detects IPv4/IPv6 by length).
- Two TLS connections: first probes the certificate (no verification), second verifies the pinned cert.
- `client_handshake()` derives session keys via X25519 + HKDF.

### Certificate Handling
- Certs are self-signed RSA-4096, valid for 365 days.
- The CN is the 4-word codename of the server's IP (`ip_to_name`).
- The CN is the short code name of the server's IP (`ip_to_name`): 6 chars for IPv4, 23 chars for IPv6.
- Certs are stored as `fognode_cert.pem` / `fognode_key.pem` in the working directory.
- If the existing cert's CN mismatches the current codename, a new cert is generated automatically.
- If the existing cert's CN mismatches the current code name, a new cert is generated automatically.

## CI / CD

Expand Down
117 changes: 117 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,123 @@ and this project adheres to Semantic Versioning.





## [dev] - 2026-05-16

### Added

- add IPv6 support to ipwords with auto-detect by name length ([`e182eeb`](https://github.com/reekeer/fognode/commit/e182eeb45ce959da67f4e8b1aa9c5870f9674151))
- add local_ipv6() to net utils ([`5ccba84`](https://github.com/reekeer/fognode/commit/5ccba84a4f6b9d4bba3356c6e944182f98fea1f0))
- add IPv6 server support (AF_INET6, auto-detect by host) ([`74897a7`](https://github.com/reekeer/fognode/commit/74897a74359aae5d8ec6e8f026dcabb68b2021f1))
- add app name/version to cert subject, fognode version in issuer OU ([`609d7ac`](https://github.com/reekeer/fognode/commit/609d7ac640df700bd88d0a06617414715d86967a))
- add app_name/app_version to start_server, regenerate cert on change ([`1bc0a7a`](https://github.com/reekeer/fognode/commit/1bc0a7a6e03e1b25710855098a075024d6989906))
- add name/version params to Server class ([`384fb9a`](https://github.com/reekeer/fognode/commit/384fb9ac1de996076e50e0390467b864f09f7027))
- add --name and --app-version to server CLI command ([`f809f80`](https://github.com/reekeer/fognode/commit/f809f8075dc88780f244165bf09ca64ce431922c))
- check server/client fognode version compatibility on connect ([`83e62d8`](https://github.com/reekeer/fognode/commit/83e62d8e14905d591bd9891cf3ae60b631614bfb))
- return and display server app info on client connect ([`69ed832`](https://github.com/reekeer/fognode/commit/69ed832e7825a2a92bedf09f3153189f6b360890))
- add msgpack dependency ([`fb4e14c`](https://github.com/reekeer/fognode/commit/fb4e14c380b118fa7e396e4d0baf72a53cc7385a))
- replace json with msgpack in SecureChannel ([`4667ec2`](https://github.com/reekeer/fognode/commit/4667ec2fe3627adcbc8b1bc6bcaa9cf5747035b6))
- replace json with msgpack in wire framing ([`da52402`](https://github.com/reekeer/fognode/commit/da52402825f132245bb2d65df41eaa79bc855471))
- add custom msgpack implementation with tests ([`a85ee4f`](https://github.com/reekeer/fognode/commit/a85ee4fe1219a362d3b293b3e00d72333a4de6de))
- switch channel to local msgpack ([`e9e5f04`](https://github.com/reekeer/fognode/commit/e9e5f045a18f936e157d0e887f8edfd07de5c102))
- switch framing to local msgpack ([`7b39f3a`](https://github.com/reekeer/fognode/commit/7b39f3a3d7e9f9a29dcf2dc092226663f0e2ab1a))
- replace external msgpack with local implementation ([`8c187d5`](https://github.com/reekeer/fognode/commit/8c187d5ce0d115f26432dc919147caa24b6b3c79))
- introduce integer message type constants, replace string types protocol-wide ([`b6d764e`](https://github.com/reekeer/fognode/commit/b6d764e2dab0b90ab1719928be3573b2bfb9f3ce))
- log probe attempts from nmap/netcat/TLS scanners ([`77170c5`](https://github.com/reekeer/fognode/commit/77170c52f10438732ba5eec69440d6782c8381da))
- add -pV flag for verbose probe logging with hex dump and details ([`ad43861`](https://github.com/reekeer/fognode/commit/ad43861a38057444eb4a3b83a60decb10fccca83))
- update issuer cn, o, ou ([`1fb70d3`](https://github.com/reekeer/fognode/commit/1fb70d3161b7c7c95b9c681852b1456567fd62a2))

### Fixed

- use getaddrinfo to find real local IPv6 address ([`af2c9d1`](https://github.com/reekeer/fognode/commit/af2c9d11c9e4222471e2a7b389b6e18a0eba1a1d))
- regenerate cert when fognode version changes in issuer OU ([`d3ad962`](https://github.com/reekeer/fognode/commit/d3ad9621f9c32d0e47735b75a1b7685c8b6e52b6))
- fall back to IPv4 when no routable IPv6, use dual-stack socket for :: ([`0a94949`](https://github.com/reekeer/fognode/commit/0a9494959001bf71a61538ffe4a3430d81bf20db))
- remove chain verification for non-self-signed cert, rely on fp in handshake ([`460594b`](https://github.com/reekeer/fognode/commit/460594b6c651ab2d59f4fc6eb2f478ccb575a824))
- correct iv_p state update in _ige_decrypt for multi-block messages ([`43e02f5`](https://github.com/reekeer/fognode/commit/43e02f5662108ea13fadd55469784f941e26e705))
- update cert regeneration check to match new issuer format ([`45e3a84`](https://github.com/reekeer/fognode/commit/45e3a841cd68a4386852e3c6ba94d14eee696f35))
- update version compat check to use new issuer OU prefix ([`65bc563`](https://github.com/reekeer/fognode/commit/65bc563f3f511a7aa300e03cd3586338e5f5a6db))
- restore valid pytest.mark.parametrize arg names after linter mangled them ([`63159dc`](https://github.com/reekeer/fognode/commit/63159dcf3723d203a9ccc1555dee1a8af1902a4a))

### Changed

- remove CMD types, client sends INFO directly ([`f793fbf`](https://github.com/reekeer/fognode/commit/f793fbf2e971c9ddf1f6fe7a064dcbfdb678d465))

### Changed

- update AGENTS.md and README for new name format and IPv6 ([`02113ef`](https://github.com/reekeer/fognode/commit/02113ef90b91c0f3bd0eed35a2017a94bca4491f))
- update CHANGELOG.md for PR #4 ([`102ec2e`](https://github.com/reekeer/fognode/commit/102ec2eaabf502f22f9016ac75fa708736e63a09))

### Changed

- add IPv6 roundtrip, boundary, and auto-detect tests ([`29d13ce`](https://github.com/reekeer/fognode/commit/29d13ce96a0ee81915f6c23523abbcd60eac563f))
- update framing tests for msgpack ([`4559a16`](https://github.com/reekeer/fognode/commit/4559a16a00b7173d3755a35854204f42b2efffd8))

### Changed

- suppress pyright reportMissingImports for msgpack ([`f51c0b7`](https://github.com/reekeer/fognode/commit/f51c0b7fe7e4e8015cf2df6151edfa1c71b7e8ab))
- fix black, ruff ([`87103dc`](https://github.com/reekeer/fognode/commit/87103dcce34b6cba2cb66bd40aba03c7f73ba8da))

### Changed

- Merge 1fb70d3161b7c7c95b9c681852b1456567fd62a2 into 7ff2eecebadf1dc4240b2c4edd2ace9abf33cebf ([`7f436de`](https://github.com/reekeer/fognode/commit/7f436de7ba2565fbaa90c779ab66291217f9a335))



## [dev] - 2026-05-16

### Added

- add IPv6 support to ipwords with auto-detect by name length ([`e182eeb`](https://github.com/reekeer/fognode/commit/e182eeb45ce959da67f4e8b1aa9c5870f9674151))
- add local_ipv6() to net utils ([`5ccba84`](https://github.com/reekeer/fognode/commit/5ccba84a4f6b9d4bba3356c6e944182f98fea1f0))
- add IPv6 server support (AF_INET6, auto-detect by host) ([`74897a7`](https://github.com/reekeer/fognode/commit/74897a74359aae5d8ec6e8f026dcabb68b2021f1))
- add app name/version to cert subject, fognode version in issuer OU ([`609d7ac`](https://github.com/reekeer/fognode/commit/609d7ac640df700bd88d0a06617414715d86967a))
- add app_name/app_version to start_server, regenerate cert on change ([`1bc0a7a`](https://github.com/reekeer/fognode/commit/1bc0a7a6e03e1b25710855098a075024d6989906))
- add name/version params to Server class ([`384fb9a`](https://github.com/reekeer/fognode/commit/384fb9ac1de996076e50e0390467b864f09f7027))
- add --name and --app-version to server CLI command ([`f809f80`](https://github.com/reekeer/fognode/commit/f809f8075dc88780f244165bf09ca64ce431922c))
- check server/client fognode version compatibility on connect ([`83e62d8`](https://github.com/reekeer/fognode/commit/83e62d8e14905d591bd9891cf3ae60b631614bfb))
- return and display server app info on client connect ([`69ed832`](https://github.com/reekeer/fognode/commit/69ed832e7825a2a92bedf09f3153189f6b360890))
- add msgpack dependency ([`fb4e14c`](https://github.com/reekeer/fognode/commit/fb4e14c380b118fa7e396e4d0baf72a53cc7385a))
- replace json with msgpack in SecureChannel ([`4667ec2`](https://github.com/reekeer/fognode/commit/4667ec2fe3627adcbc8b1bc6bcaa9cf5747035b6))
- replace json with msgpack in wire framing ([`da52402`](https://github.com/reekeer/fognode/commit/da52402825f132245bb2d65df41eaa79bc855471))
- add custom msgpack implementation with tests ([`a85ee4f`](https://github.com/reekeer/fognode/commit/a85ee4fe1219a362d3b293b3e00d72333a4de6de))
- switch channel to local msgpack ([`e9e5f04`](https://github.com/reekeer/fognode/commit/e9e5f045a18f936e157d0e887f8edfd07de5c102))
- switch framing to local msgpack ([`7b39f3a`](https://github.com/reekeer/fognode/commit/7b39f3a3d7e9f9a29dcf2dc092226663f0e2ab1a))
- replace external msgpack with local implementation ([`8c187d5`](https://github.com/reekeer/fognode/commit/8c187d5ce0d115f26432dc919147caa24b6b3c79))
- introduce integer message type constants, replace string types protocol-wide ([`b6d764e`](https://github.com/reekeer/fognode/commit/b6d764e2dab0b90ab1719928be3573b2bfb9f3ce))
- log probe attempts from nmap/netcat/TLS scanners ([`77170c5`](https://github.com/reekeer/fognode/commit/77170c52f10438732ba5eec69440d6782c8381da))
- add -pV flag for verbose probe logging with hex dump and details ([`ad43861`](https://github.com/reekeer/fognode/commit/ad43861a38057444eb4a3b83a60decb10fccca83))
- update issuer cn, o, ou ([`1fb70d3`](https://github.com/reekeer/fognode/commit/1fb70d3161b7c7c95b9c681852b1456567fd62a2))

### Fixed

- use getaddrinfo to find real local IPv6 address ([`af2c9d1`](https://github.com/reekeer/fognode/commit/af2c9d11c9e4222471e2a7b389b6e18a0eba1a1d))
- regenerate cert when fognode version changes in issuer OU ([`d3ad962`](https://github.com/reekeer/fognode/commit/d3ad9621f9c32d0e47735b75a1b7685c8b6e52b6))
- fall back to IPv4 when no routable IPv6, use dual-stack socket for :: ([`0a94949`](https://github.com/reekeer/fognode/commit/0a9494959001bf71a61538ffe4a3430d81bf20db))
- remove chain verification for non-self-signed cert, rely on fp in handshake ([`460594b`](https://github.com/reekeer/fognode/commit/460594b6c651ab2d59f4fc6eb2f478ccb575a824))
- correct iv_p state update in _ige_decrypt for multi-block messages ([`43e02f5`](https://github.com/reekeer/fognode/commit/43e02f5662108ea13fadd55469784f941e26e705))
- update cert regeneration check to match new issuer format ([`45e3a84`](https://github.com/reekeer/fognode/commit/45e3a841cd68a4386852e3c6ba94d14eee696f35))
- update version compat check to use new issuer OU prefix ([`65bc563`](https://github.com/reekeer/fognode/commit/65bc563f3f511a7aa300e03cd3586338e5f5a6db))

### Changed

- remove CMD types, client sends INFO directly ([`f793fbf`](https://github.com/reekeer/fognode/commit/f793fbf2e971c9ddf1f6fe7a064dcbfdb678d465))

### Changed

- update AGENTS.md and README for new name format and IPv6 ([`02113ef`](https://github.com/reekeer/fognode/commit/02113ef90b91c0f3bd0eed35a2017a94bca4491f))

### Changed

- add IPv6 roundtrip, boundary, and auto-detect tests ([`29d13ce`](https://github.com/reekeer/fognode/commit/29d13ce96a0ee81915f6c23523abbcd60eac563f))
- update framing tests for msgpack ([`4559a16`](https://github.com/reekeer/fognode/commit/4559a16a00b7173d3755a35854204f42b2efffd8))

### Changed

- suppress pyright reportMissingImports for msgpack ([`f51c0b7`](https://github.com/reekeer/fognode/commit/f51c0b7fe7e4e8015cf2df6151edfa1c71b7e8ab))



## [dev] - 2026-05-16

### Added
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ if __name__ == "__main__":
```python
from fognode import Client, MessageEvent, ClosedEvent, ErrorEvent

client = Client(connect_string="oak-pine-stone-field:9443", password="secret")
client = Client(connect_string="7sf9Tn:9443", password="secret")

@client.on_event(MessageEvent)
async def on_message(ctx):
Expand All @@ -93,7 +93,7 @@ if __name__ == "__main__":
from fognode import start_server, client_connect

ip, code, fp = start_server("0.0.0.0", 9443, "secret")
print(f"Server running at {code}:9443")
print(f"Server running at {code}:9443") # e.g. 7sf9Tn:9443
```

## Events
Expand Down Expand Up @@ -144,19 +144,19 @@ Decryption reverses the process and verifies `msg_key` integrity.
fognode server --host 0.0.0.0 --port 9443 --password secret

# Interactive client
fognode client oak-pine-stone-field:9443 --password secret
fognode client 7sf9Tn:9443 --password secret

# Probe TLS fingerprint (no auth)
fognode probe oak-pine-stone-field:9443
fognode probe 7sf9Tn:9443

# Server status via authenticated channel
fognode status oak-pine-stone-field:9443 --password secret
fognode status 7sf9Tn:9443 --password secret

# Send one message and exit
fognode send oak-pine-stone-field:9443 --password secret --text "hello"
fognode send 7sf9Tn:9443 --password secret --text "hello"

# Monitor messages only
fognode monitor oak-pine-stone-field:9443 --password secret
fognode monitor 7sf9Tn:9443 --password secret

# Show certificate info
fognode cert --file fognode_cert.pem
Expand Down
13 changes: 10 additions & 3 deletions src/fognode/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from fognode.crypto.channel import SecureChannel
from fognode.handlers import HandlerObject
from fognode.types.constants import DEFAULT_HOST, DEFAULT_PORT
from fognode.types.messages import CHAT, WELCOME

if TYPE_CHECKING:
from fognode.app import Client, Server
Expand All @@ -37,7 +38,7 @@ def __init__(
async def answer(self, text: str) -> None:
if self.channel is None:
raise RuntimeError("no channel available")
self.channel.send({"type": "chat", "text": text})
self.channel.send({"t": CHAT, "text": text})

async def send(self, data: dict[str, Any]) -> None:
if self.channel is None:
Expand All @@ -51,10 +52,14 @@ def __init__(
host: str = DEFAULT_HOST,
port: int = DEFAULT_PORT,
password: str | None = None,
name: str = "fognode",
version: str = "1.0.0",
) -> None:
self.host = host
self.port = port
self.password = password
self.name = name
self.version = version
self._handlers: dict[type[BaseEvent], list[HandlerObject]] = {}
self._loop: asyncio.AbstractEventLoop | None = None
self._channel: SecureChannel | None = None
Expand Down Expand Up @@ -102,6 +107,8 @@ def _on_msg(msg: dict[str, Any]) -> None:
on_connect=_on_connect,
on_disconnect=_on_disconnect,
on_message=_on_msg,
app_name=self.name,
app_version=self.version,
)

self._process_event(StartEvent())
Expand Down Expand Up @@ -167,15 +174,15 @@ def connect(self) -> None:
asyncio.set_event_loop(self._loop)

try:
ch, _fp = client_connect(self.connect_string, self.password)
ch, _fp, _server_info = client_connect(self.connect_string, self.password)
except Exception as exc:
self._process_event(ErrorEvent(exception=exc))
return

self._channel = ch

welcome = ch.recv()
if welcome.get("type") == "welcome":
if welcome.get("t") == WELCOME:
self._process_event(StartEvent(self._channel))
self._process_event(ConnectEvent(self._channel))

Expand Down
5 changes: 3 additions & 2 deletions src/fognode/auth/handshake.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from fognode.crypto.primitives import hkdf_expand, hmac256, hmac256_verify, pbkdf2
from fognode.types.constants import NONCE_LENGTH, TOKEN_LENGTH
from fognode.types.exceptions import AuthError, SecurityError
from fognode.types.messages import CHALLENGE
from fognode.types.protocol import IPAddress
from fognode.utils.ratelimit import RateLimiter
from fognode.wire.framing import wire_recv, wire_send
Expand All @@ -27,7 +28,7 @@ def server_handshake(tls: ssl.SSLSocket, client_ip: IPAddress) -> SecureChannel:
wire_send(
tls,
{
"type": "challenge",
"t": CHALLENGE,
"nonce": nonce.hex(),
"salt": salt.hex(),
"fp": server_fp,
Expand Down Expand Up @@ -60,7 +61,7 @@ def server_handshake(tls: ssl.SSLSocket, client_ip: IPAddress) -> SecureChannel:

def client_handshake(tls: ssl.SSLSocket, password: str, measured_fp: str) -> SecureChannel:
chal = wire_recv(tls)
if chal.get("type") != "challenge":
if chal.get("t") != CHALLENGE:
raise ConnectionError("expected challenge")

nonce = bytes.fromhex(chal["nonce"])
Expand Down
2 changes: 1 addition & 1 deletion src/fognode/cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _ige_decrypt(key: bytes, iv: bytes, ciphertext: bytes) -> bytes:
x = bytes(a ^ b for a, b in zip(block, iv_c, strict=False)) # noqa: B905
p = cipher.decrypt(x)
pt += bytes(a ^ b for a, b in zip(p, iv_p, strict=False)) # noqa: B905
iv_p = block
iv_p = x
iv_c = pt[-16:]
return pt

Expand Down
Loading