feat(factory): add local flashing toolkit and secure OTA defaults
This commit is contained in:
95
tools/esptool-factory/factory_gui/redact.py
Normal file
95
tools/esptool-factory/factory_gui/redact.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
SENSITIVE_KEYS = (
|
||||
"pub_key",
|
||||
"signature",
|
||||
"key_b64",
|
||||
"flash_key_b64",
|
||||
"sig_b64",
|
||||
"pub_key_jkt",
|
||||
"new_pub_key",
|
||||
"new_pub_key_jkt",
|
||||
"device_mac",
|
||||
"operator",
|
||||
"host",
|
||||
"port",
|
||||
"firmware_version",
|
||||
)
|
||||
|
||||
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[A-Za-z]")
|
||||
_MAC_RE = re.compile(r"(?i)([0-9a-f]{2}:){5}[0-9a-f]{2}")
|
||||
_UUID_RE = re.compile(
|
||||
r"\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b"
|
||||
)
|
||||
_URL_RE = re.compile(r"https?://[^\s]+")
|
||||
_DEVICE_ID_JSON_RE = re.compile(r'("device_id"\s*:\s*")([^"]+)(")', re.IGNORECASE)
|
||||
_DEVICE_ID_KV_RE = re.compile(r"(\bdevice_id\b\s*[:=]\s*)([^\s,;]+)", re.IGNORECASE)
|
||||
_JSON_KEY_RE = re.compile(
|
||||
r'([\'"](?:(?:' + "|".join(SENSITIVE_KEYS) + r'))[\'"]\s*:\s*[\'"])([^\'"]+)([\'"])',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
_KV_RE = re.compile(r"(?i)\b(" + "|".join(SENSITIVE_KEYS) + r")=([^\s,;]+)")
|
||||
_HEX_BYTES_RE = re.compile(r"\b(?:[0-9a-fA-F]{2}\s+){7,}[0-9a-fA-F]{2}\b")
|
||||
_BIN_PATH_RE = re.compile(r"(/[^\\s]+?\\.(?:bin(?:\\.enc)?|enc))")
|
||||
_BIN_NAME_RE = re.compile(r"\b[\w.-]+\\.(?:bin(?:\\.enc)?|enc)\b")
|
||||
|
||||
|
||||
def _sanitize_filename(value: str) -> str:
|
||||
if not value:
|
||||
return "unknown"
|
||||
return re.sub(r"[^A-Za-z0-9._-]+", "_", value)
|
||||
|
||||
|
||||
def _preserve_device_ids(text: str) -> tuple[str, dict[str, str]]:
|
||||
tokens: dict[str, str] = {}
|
||||
|
||||
def _tokenize(value: str) -> str:
|
||||
token = f"__DEVICE_ID_{len(tokens)}__"
|
||||
tokens[token] = value
|
||||
return token
|
||||
|
||||
def _replace_json(match: re.Match[str]) -> str:
|
||||
return f"{match.group(1)}{_tokenize(match.group(2))}{match.group(3)}"
|
||||
|
||||
def _replace_kv(match: re.Match[str]) -> str:
|
||||
return f"{match.group(1)}{_tokenize(match.group(2))}"
|
||||
|
||||
text = _DEVICE_ID_JSON_RE.sub(_replace_json, text)
|
||||
text = _DEVICE_ID_KV_RE.sub(_replace_kv, text)
|
||||
return text, tokens
|
||||
|
||||
|
||||
def _redact_sensitive(text: str) -> str:
|
||||
if not text:
|
||||
return text
|
||||
text, device_tokens = _preserve_device_ids(text)
|
||||
text = _ANSI_RE.sub("", text)
|
||||
text = _MAC_RE.sub("<mac>", text)
|
||||
text = _UUID_RE.sub("<id>", text)
|
||||
text = _URL_RE.sub("<url>", text)
|
||||
text = _JSON_KEY_RE.sub(
|
||||
lambda m: f"{m.group(1)}<redacted:{len(m.group(2))}>{m.group(3)}", text
|
||||
)
|
||||
text = _KV_RE.sub(
|
||||
lambda m: f"{m.group(1)}=<redacted:{len(m.group(2))}>", text
|
||||
)
|
||||
text = _HEX_BYTES_RE.sub("<redacted:hex>", text)
|
||||
text = _BIN_PATH_RE.sub(lambda m: os.path.basename(m.group(1)), text)
|
||||
text = _BIN_NAME_RE.sub("<bin>", text)
|
||||
lowered = text.lower()
|
||||
if "security features enabled" in lowered:
|
||||
return "检测到限制,保持默认配置。"
|
||||
if "compress and encrypt options are mutually exclusive" in lowered:
|
||||
return "写入选项冲突,已使用默认方式。"
|
||||
if "will flash input bytes uncompressed" in lowered:
|
||||
return "将按默认方式写入。"
|
||||
if "cannot verify written data" in lowered:
|
||||
return "写入完成,校验已跳过。"
|
||||
if "secure boot detected" in lowered or "secure download mode is enabled" in lowered:
|
||||
return "检测到写入限制,请按工艺选择模式。"
|
||||
for token, value in device_tokens.items():
|
||||
text = text.replace(token, value)
|
||||
return text
|
||||
Reference in New Issue
Block a user