fix: revert to mandandory bytes for python cryptography module, trying best effort with ctypes.memset

This commit is contained in:
Alpha Nerd 2026-04-12 17:59:08 +02:00
parent 5e8e4443a9
commit c161e42e45
Signed by: alpha-nerd
SSH key fingerprint: SHA256:QkkAgVoYi9TQ0UKPkiKSfnerZy2h4qhi3SVPXJmBN+M

View file

@ -1,4 +1,4 @@
import json, base64, urllib.parse, httpx, os, secrets, warnings, logging import ctypes, json, base64, urllib.parse, httpx, os, secrets, sys, warnings, logging
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives.asymmetric import rsa, padding
@ -354,14 +354,28 @@ class SecureCompletionClient:
server_public_key_pem.encode('utf-8'), server_public_key_pem.encode('utf-8'),
backend=default_backend() backend=default_backend()
) )
# RSA encrypt requires bytes — an immutable copy is unavoidable here.
# We narrow its lifetime to this block and attempt to zero it via
# CPython internals immediately after use. This relies on the CPython
# bytes object layout (ob_sval starts at getsizeof(b'')-1 from id()),
# so it is a best-effort measure on CPython only.
_key_bytes = bytes(aes_key)
try:
encrypted_aes_key = server_public_key.encrypt( encrypted_aes_key = server_public_key.encrypt(
aes_key, _key_bytes,
padding.OAEP( padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()), mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(), algorithm=hashes.SHA256(),
label=None label=None
) )
) )
finally:
try:
_data_offset = sys.getsizeof(b'') - 1 # offset to ob_sval in PyBytesObject
ctypes.memset(id(_key_bytes) + _data_offset, 0, len(_key_bytes))
except Exception:
pass
del _key_bytes
encrypted_package = { encrypted_package = {
"version": "1.0", "version": "1.0",