From 65c565e05838dec1a92e3a1067ee0b24815a6be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Fri, 2 Oct 2026 09:32:45 +0300 Subject: [PATCH] v3.11.0: Cards tab redesign (list + editor), preset PIN/PUK codes The Cards tab now shows the preset list by default; "Add preset" / "Edit" open a separate editor view (Save stores and returns to the list, Cancel discards; ramGoToPreset opens it too). The editor keeps the name/ICCID header (with From card) and groups its fields into bordered blocks: - PIN/ADM: the new optional card codes PIN1/PUK1/PIN2/PUK2 (plain text, 4-8 decimal digits) plus ADM, moved out of the top row; nothing consumes the PIN/PUK codes yet. - TAR: one uniform table (TAR, MSL, description); the first three rows are the fixed role entries with the immutable English descriptions "ISD compact format" / "UICC shared FS RFM compact format" / "ADF FS RFM compact format"; further rows are deletable with an optional description. - SCP80 (keyset editor) and SCP81 (PSK pair) as before. Store: PRESET_FIELDS gains pin1/puk1/pin2/puk2 (optional; whitespace stripped; 4-8 decimal digits validated on save and import), SCHEMA_VERSION 4, docs/help/AGENTS updated. TAR rows use unified ids (cards-tr-N-*), the editor switches via cardsShowList/cardsShowEditor. Tests: 665 Python + 783 frontend green; the whole inline PWA script syntax-checked. sw cache simple-v361. --- docs/api.md | 8 +- frontend/help-ru.html | 14 +- frontend/help.html | 14 +- frontend/index.html | 286 ++++++++++++++++++++---------- frontend/style.css | 8 + frontend/sw.js | 2 +- frontend/tests/cards_form.test.js | 181 +++++++++++++------ frontend/tests/html.test.js | 76 +++++--- pyproject.toml | 2 +- pysim_simple_server/presets.py | 20 ++- pysim_simple_server/server.py | 2 +- tests/test_presets.py | 26 +++ 12 files changed, 451 insertions(+), 188 deletions(-) diff --git a/docs/api.md b/docs/api.md index c7dcacf..849935d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -204,6 +204,7 @@ the bytes, there is no separate field: ```json {"id": "…", "name": "Card A", "iccid": "…", + "pin1": "", "puk1": "", "pin2": "", "puk2": "", "pskIdentity": "", "pskKey": "", "adm": "", "tars": [ {"role": "isd", "tar": "000000", "msl": "16", "desc": ""}, @@ -239,6 +240,11 @@ three role entries, the `spi1` as their MSL. Operations **derive a packet's SPI1 from the MSL of its TAR**; a request naming a TAR outside the preset must pass `spi1` itself, otherwise it is refused with `400` and a hint. +**Card codes.** The optional `pin1`/`puk1`/`pin2`/`puk2`/`adm` fields are +stored for later use (nothing consumes them yet). PIN/PUK must be **4–8 +decimal digits** when set (empty is fine; anything else is refused with `400` +naming the field); the ADM key stays free-form (hex or ASCII digits). + **Counters.** The store is the source of truth for the SCP80 counters, one per keyset ("a dedicated counter shall be associated to each key version", Annex A.1 — the spec's wording). The operations below accept a `preset_id` and **persist the @@ -250,7 +256,7 @@ is not defined in preset '…' - add it in the Cards tab"}`), and so is a KIc/KID number mismatch. The Cards tab's export/import uses this API; the import also accepts presets exported by the older localStorage-based builds. -- `GET /api/presets` — `{"path": "…", "count": 2, "version": 3, "presets": [{…}]}` +- `GET /api/presets` — `{"path": "…", "count": 2, "version": 4, "presets": [{…}]}` (card-free: it answers while a long card operation runs). - `POST /api/presets` — body = the preset fields (`keysets` included); returns `{"ok": true, "preset": {…}}`. A duplicate ICCID (digits, spaced or raw EF diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 2dbed06..6aaa1e9 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -346,25 +346,25 @@

Каждый принятый картой пакет расходует счётчик, который сохраняется в keyset пресета — проба отклоняется, если в разрешённом SPI1 нет проверки счётчика или в пресете нет такого номера keyset. На живой карте: 000000, B00000 и B00001 зарегистрированы (приложения компактного формата), расширенный формат, USAT, мультиплексирование и CASD отклонены с 6200.

4. Вкладка «Карты»

-

Хранит пресеты карт на сервере (~/.pysim-simple-server/card_presets.json; переопределяется --card-presets), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, слушатель SCP81 HTTP OTA — находить PSK-ключи, а счётчики SCP80, израсходованные операцией, сохранялись самой операцией — закрытая вкладка или второе окно браузера больше не могут потерять инкремент. Пресет содержит несколько keysets — номер keyset задаётся нибблом b8..b5 его KIc/KID (TS 102 225 §5.1.2/A.2): KIc и KID одного keyset должны нести один и тот же номер (01–0F; A.2 отвергает несовпадение), и у каждого keyset на карте свой счётчик (Annex A.1), поэтому счётчики ведутся по keysets. В форме keysets редактируются строками — по одной на номер, с кнопками Добавить keyset / Удалить keyset; номер в строке вычисляется из байта KIc/KID, а 00 («без защиты») не принимается как keyset. Список загружается при подключении PWA и экспортируется/импортируется как JSON (импорт принимает и пресеты старых сборок — плоские и с keysets). «Карты» — верхнеуровневая вкладка. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается во всех трёх представлениях SCP80; если подключённая карта не совпадает ни с одним пресетом — или выбранный пресет принадлежит другой карте — все три представления SCP80 показывают жёлтое предупреждение над выбором пресета. В списке подсвечивается пресет подключённой карты. Поля формы сгруппированы в два блока с рамкой: SCP80 (GSM 03.48, ETSI TS 102 225) (keysets, таблица TAR — три обязательные роли ISD / UICC RFM / ADF RFM, у каждой свой MSL, плюс дополнительные TAR с необязательным описанием — и счётчики) и SCP81 (HTTP OTA) (пара PSK identity/ключ с пояснением о выборе ключа). Необязательное поле ADM находится в верхней строке и сохраняется для последующего использования файловым менеджером. В шапке отображаются серые маркеры SCP80/SCP81 и значок ключа на бейдже ADM, когда в пресете с ICCID подключённой карты эти поля заполнены.

+

Хранит пресеты карт на сервере (~/.pysim-simple-server/card_presets.json; переопределяется --card-presets), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, слушатель SCP81 HTTP OTA — находить PSK-ключи, а счётчики SCP80, израсходованные операцией, сохранялись самой операцией — закрытая вкладка или второе окно браузера больше не могут потерять инкремент. Пресет содержит несколько keysets — номер keyset задаётся нибблом b8..b5 его KIc/KID (TS 102 225 §5.1.2/A.2): KIc и KID одного keyset должны нести один и тот же номер (01–0F; A.2 отвергает несовпадение), и у каждого keyset на карте свой счётчик (Annex A.1), поэтому счётчики ведутся по keysets. В форме keysets редактируются строками — по одной на номер, с кнопками Добавить keyset / Удалить keyset; номер в строке вычисляется из байта KIc/KID, а 00 («без защиты») не принимается как keyset. Список загружается при подключении PWA и экспортируется/импортируется как JSON (импорт принимает и пресеты старых сборок — плоские и с keysets). «Карты» — верхнеуровневая вкладка: по умолчанию показывается список пресетов, а Добавить пресет / Редактировать открывают редактор (отдельное представление) — Сохранить сохраняет пресет и возвращает к списку, Отмена отменяет правки. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается во всех трёх представлениях SCP80; если подключённая карта не совпадает ни с одним пресетом — или выбранный пресет принадлежит другой карте — все три представления SCP80 показывают жёлтое предупреждение над выбором пресета. В списке подсвечивается пресет подключённой карты. Поля редактора сгруппированы в блоки с рамкой: PIN/ADM (необязательные коды карты — PIN1/PUK1/PIN2/PUK2 по 4–8 десятичных цифр и ключ ADM — сохраняются для будущего использования), TAR (таблица TAR), SCP80 (GSM 03.48, ETSI TS 102 225) (keysets и их счётчики) и SCP81 (HTTP OTA) (пара PSK identity/ключ с пояснением о выборе ключа). В шапке отображаются серые маркеры SCP80/SCP81 и значок ключа на бейдже ADM, когда в пресете с ICCID подключённой карты эти поля заполнены.

- + - - - - + + + +
ПолеОписание
NameПонятная метка (обязательна)
ICCIDОпциональный идентификатор карты. Кнопка С карты подставляет EF.ICCID подключённой карты (активна, только когда ICCID читается); при сохранении ICCID, уже присутствующий в списке, отклоняется (сравнение без пробелов и с учётом сырой hex-формы, конфликтующий пресет называется)
ADMНеобязательный администраторский PIN (hex или до 8 ASCII-цифр), сохраняется в пресете для последующего использования файловым менеджером; представлениями SCP80/SCP81 не используется
PIN1 / PUK1 / PIN2 / PUK2 / ADMНеобязательные коды карты, сохраняются для будущего использования (пока ничем не используются). PIN/PUK — строго 4–8 десятичных цифр (иначе сохранение отклоняется); ADM — администраторский ключ (hex или до 8 ASCII-цифр), используется файловым менеджером. Представлениями SCP80/SCP81 не используются
KIc / KIDИндикаторы ключа и алгоритма (например, 15 = индекс 1, 3DES-CBC2; x2 = AES); задаются вместе с ключами
TARs / MSLТаблица TAR: три обязательные роли (ISD / UICC RFM / ADF RFM — предзаполнены) и дополнительные TAR, у каждого свой MSL (минимальный SPI1, TS 102 226 §8.2.1.3.2.4). SPI1 пакета берётся из MSL его TAR; у свободных записей есть необязательное описание
ISD TARTAR Issuer Security Domain (TS 101 220, приложение D); используется для операций RAM/GP (представление SCP80 RAM, цепочки RAM/GP); по умолчанию по спецификации 000000, подставляется при пустом значении
UICC RFM TARTAR UICC Shared File System RFM (TS 102 226 §7.2, TS 101 220 приложение D): MF выбирается неявно и доступны только файлы под MF (ADF недоступны); используется представлением SIM RFM; по умолчанию B00000
ADF RFM TARTAR ADF RFM (TS 102 226 §7.3, TS 101 220 приложение D): ADF выбирается неявно, TAR привязан к AID приложения — ADF.USIM в представлении USIM RFM; по умолчанию B00001
TAR / MSL / DescriptionТаблица TAR: одна строка на TAR с его MSL (минимальный SPI1, TS 102 226 §8.2.1.3.2.4). Первые три строки — фиксированные роли (предзаполнены, не удаляются) с фиксированными описаниями; дополнительные TAR добавляются кнопкой Добавить TAR, несут необязательное описание и могут быть удалены. SPI1 пакета берётся из MSL его TAR
ISD compact formatTAR Issuer Security Domain (TS 101 220, приложение D); используется для операций RAM/GP (представление SCP80 RAM, цепочки RAM/GP); по умолчанию по спецификации 000000, подставляется при пустом значении
UICC shared FS RFM compact formatTAR UICC Shared File System RFM (TS 102 226 §7.2, TS 101 220 приложение D): MF выбирается неявно и доступны только файлы под MF (ADF недоступны); используется представлением SIM RFM; по умолчанию B00000
ADF FS RFM compact formatTAR ADF RFM (TS 102 226 §7.3, TS 101 220 приложение D): ADF выбирается неявно, TAR привязан к AID приложения — ADF.USIM в представлении USIM RFM; по умолчанию B00001
CounterСчётчик повторов (5 байт); свой у каждого keyset, сервер увеличивает и сохраняет его после каждой операции, которая его расходует
KIc key / KID key16/24/32 hex-символа (ключи 8/16/24 байта 3DES) или 32/48/64 hex-символа (ключи 16/24/32 байта AES)
PSK identitySCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии (например, 89390100000129506903)
PSK keySCP81 HTTP OTA: 32 hex-символа (16 байт) для PSK TLS-слушателя; ключ выбирается по идентификатору, который предъявляет карта
-

Столбец SCP81 показывает, задана ли в пресете рабочая пара PSK: ✓ (зелёный) — идентификатор и ключ заданы; ⚠ (жёлтый) — задано только одно из двух, и слушатель такой пресет игнорирует; — — PSK нет. Идентификатор и ключ PSK задаются вместе. Кнопка Редактировать загружает пресет в форму (кнопка Add становится Сохранить; Отмена очищает форму), поэтому поля можно менять без повторного ввода карты; Удалить удаляет строку. Обмен пресетами: Экспорт в файл для выгрузки и Импорт из файла для загрузки. Выбранный пресет автоматически заполняет форму Secured Packet и устанавливает TAR для операции (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); TAR, введённый в форму Secured Packet вручную, сохраняется при отправке - счётчик, ключи и MSL этого TAR по-прежнему берутся из пресета; SPI1 берётся из MSL, а меньшее значение даёт предупреждение (сервер тоже возвращает его как warning); изменения сразу передаются работающему слушателю SCP81.

+

Столбец SCP81 показывает, задана ли в пресете рабочая пара PSK: ✓ (зелёный) — идентификатор и ключ заданы; ⚠ (жёлтый) — задано только одно из двух, и слушатель такой пресет игнорирует; — — PSK нет. Идентификатор и ключ PSK задаются вместе. Кнопка Добавить пресет открывает редактор с новым пресетом; Редактировать загружает пресет строки в редактор, поэтому поля можно менять без повторного ввода карты; Сохранить сохраняет и возвращает к списку, Отмена отменяет правки; Удалить удаляет строку (только в списке). Обмен пресетами: Экспорт в файл для выгрузки и Импорт из файла для загрузки. Выбранный пресет автоматически заполняет форму Secured Packet и устанавливает TAR для операции (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); TAR, введённый в форму Secured Packet вручную, сохраняется при отправке - счётчик, ключи и MSL этого TAR по-прежнему берутся из пресета; SPI1 берётся из MSL, а меньшее значение даёт предупреждение (сервер тоже возвращает его как warning); изменения сразу передаются работающему слушателю SCP81.

diff --git a/frontend/help.html b/frontend/help.html index ccee272..6436fae 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -345,25 +345,25 @@

Each packet the card accepts consumes a counter, which is saved into the preset's keyset — the probe is refused when the resolved SPI1 has no counter check or the named preset does not define the keyset number. Observed on a live card: 000000, B00000 and B00001 registered (compact-format applications), the expanded-format TARs, USAT, multiplexing and CASD refused with 6200.

4. Cards tab

-

Stores card presets on the server (~/.pysim-simple-server/card_presets.json; --card-presets overrides it) so the Secured Packet view can auto-fill keys and parameters, the SCP81 HTTP OTA listener can look up PSK keys, and the SCP80 counters an operation consumed are persisted with the operation itself — a closed tab or a second browser window can no longer lose an increment. A preset carries several keysets — a keyset's number is the b8..b5 nibble of its KIc/KID (TS 102 225 §5.1.2/A.2): KIc and KID of a keyset must carry the same number (01–0F; A.2 rejects a mismatch), and each keyset has its own counter on the card (Annex A.1), so counters are tracked per keyset. In the form the keysets are edited as rows — one per number, with Add keyset / Remove keyset; each row shows the number derived from its KIc/KID byte, and 00 (no security) is not accepted as a keyset. The list is loaded when the PWA connects and can be exported/imported as JSON (the import also takes presets exported by older builds, flat or keyset-shaped). Cards is a top-level tab. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in all three SCP80 views; when the equipped card matches no preset — or the selected preset belongs to another card — all three SCP80 views show an amber warning above the preset selector. The list highlights the equipped card's preset. The form groups the fields into two bordered blocks: SCP80 (GSM 03.48, ETSI TS 102 225) (the keysets, the TAR table — the three mandatory role entries ISD / UICC RFM / ADF RFM, each with its MSL, plus further TARs with an optional description — and the counters) and SCP81 (HTTP OTA) (the PSK identity/key pair with the key-selection note). The optional ADM field sits in the top row and is stored for later use by the file manager. The header shows gray SCP80/SCP81 markers and a key glyph on the ADM badge when the preset matching the equipped card's ICCID has those settings filled in.

+

Stores card presets on the server (~/.pysim-simple-server/card_presets.json; --card-presets overrides it) so the Secured Packet view can auto-fill keys and parameters, the SCP81 HTTP OTA listener can look up PSK keys, and the SCP80 counters an operation consumed are persisted with the operation itself — a closed tab or a second browser window can no longer lose an increment. A preset carries several keysets — a keyset's number is the b8..b5 nibble of its KIc/KID (TS 102 225 §5.1.2/A.2): KIc and KID of a keyset must carry the same number (01–0F; A.2 rejects a mismatch), and each keyset has its own counter on the card (Annex A.1), so counters are tracked per keyset. In the form the keysets are edited as rows — one per number, with Add keyset / Remove keyset; each row shows the number derived from its KIc/KID byte, and 00 (no security) is not accepted as a keyset. The list is loaded when the PWA connects and can be exported/imported as JSON (the import also takes presets exported by older builds, flat or keyset-shaped). Cards is a top-level tab: it shows the preset list by default, and Add preset / Edit open the editor (a separate view) — Save stores the preset and returns to the list, Cancel discards the edits. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in all three SCP80 views; when the equipped card matches no preset — or the selected preset belongs to another card — all three SCP80 views show an amber warning above the preset selector. The list highlights the equipped card's preset. The editor groups the fields into bordered blocks: PIN/ADM (the optional card codes — PIN1/PUK1/PIN2/PUK2 as 4–8 decimal digits and the ADM key — stored for later use), TAR (the TAR table), SCP80 (GSM 03.48, ETSI TS 102 225) (the keysets and their counters) and SCP81 (HTTP OTA) (the PSK identity/key pair with the key-selection note). The header shows gray SCP80/SCP81 markers and a key glyph on the ADM badge when the preset matching the equipped card's ICCID has those settings filled in.

- + - - - - + + + +
FieldDescription
NameHuman-readable label (required)
ICCIDOptional card identifier. From card fills it with the equipped card's EF.ICCID (enabled only while a readable ICCID is known); saving refuses an ICCID that already exists in the list (compared ignoring spaces and the raw-hex form, and the conflicting preset is named)
ADMOptional administrator PIN (hex, or up to 8 ASCII digits), stored in the preset for later use by the file manager; not used by the SCP80/SCP81 views
PIN1 / PUK1 / PIN2 / PUK2 / ADMOptional card codes, all stored for later use (nothing consumes them yet). PIN/PUK must be 4–8 decimal digits (saving refuses anything else); ADM is the administrator key (hex, or up to 8 ASCII digits), used by the file manager. None is used by the SCP80/SCP81 views
KIc / KIDKey and algorithm indicators (e.g. 15 = index 1, 3DES-CBC2; x2 = AES), required together with the keys
TARs / MSLThe TAR table: the three role entries (ISD / UICC RFM / ADF RFM — mandatory, pre-settled) plus further TARs, each with its MSL (Minimum SPI1, TS 102 226 §8.2.1.3.2.4). A packet's SPI1 is derived from its TAR's MSL; free entries carry an optional description
ISD TARIssuer Security Domain TAR (TS 101 220 Annex D); used for RAM/GP operations (SCP80 RAM view, RAM/GP chains); spec default 000000, prefilled when empty
UICC RFM TARUICC Shared File System RFM TAR (TS 102 226 §7.2, TS 101 220 Annex D): the MF is implicitly selected and only files under the MF are accessible (no ADFs); used by the SIM RFM view; spec default B00000
ADF RFM TARADF RFM TAR (TS 102 226 §7.3, TS 101 220 Annex D): the ADF is implicitly selected and the TAR is linked to the application's AID — ADF.USIM in the USIM RFM view; spec default B00001
TAR / MSL / DescriptionThe TAR table: one uniform row per TAR with its MSL (Minimum SPI1, TS 102 226 §8.2.1.3.2.4). The first three rows are the fixed role entries (pre-settled, not removable) with their fixed descriptions; further TARs are added with Add TAR, carry an optional description and can be removed. A packet's SPI1 is derived from its TAR's MSL
ISD compact formatIssuer Security Domain TAR (TS 101 220 Annex D); used for RAM/GP operations (SCP80 RAM view, RAM/GP chains); spec default 000000, prefilled when empty
UICC shared FS RFM compact formatUICC Shared File System RFM TAR (TS 102 226 §7.2, TS 101 220 Annex D): the MF is implicitly selected and only files under the MF are accessible (no ADFs); used by the SIM RFM view; spec default B00000
ADF FS RFM compact formatADF RFM TAR (TS 102 226 §7.3, TS 101 220 Annex D): the ADF is implicitly selected and the TAR is linked to the application's AID — ADF.USIM in the USIM RFM view; spec default B00001
CounterReplay counter (5 bytes); one per keyset, advanced and saved by the server after each operation that consumes it
KIc key / KID key16/24/32 hex chars (8/16/24-byte 3DES) or 32/48/64 hex chars (16/24/32-byte AES) keys
PSK identitySCP81 HTTP OTA: the identity the card sends in the TLS handshake (e.g. 89390100000129506903)
PSK keySCP81 HTTP OTA: 32 hex chars (16 bytes) for the PSK TLS listener, picked by the identity the card presents
-

The SCP81 column shows whether the preset supplies a usable PSK pair: ✓ (green) — identity and key set; ⚠ (amber) — only one of the two, so the listener ignores the preset; — — no PSK. PSK identity and key must be set together. Edit loads a preset into the form (the Add button becomes Save; Cancel clears it) so fields can be changed without re-entering the card; Remove deletes the row. Presets can be shared with Export to file and restored with Import from file. The selected card preset auto-fills the Secured Packet form and sets the TAR for the operation (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); a TAR typed into the Secured Packet form by hand is kept when sending - the counter, keys and the TAR's MSL are still re-read from the preset; the SPI1 is seeded from the TAR's MSL and a lower value warns (the server returns it as a warning too); edits are pushed into a running SCP81 listener automatically.

+

The SCP81 column shows whether the preset supplies a usable PSK pair: ✓ (green) — identity and key set; ⚠ (amber) — only one of the two, so the listener ignores the preset; — — no PSK. PSK identity and key must be set together. Add preset opens the editor with a fresh preset; Edit loads the row's preset into it so fields can be changed without re-entering the card; Save stores it and returns to the list, Cancel discards the edits; Remove deletes the row (list only). Presets can be shared with Export to file and restored with Import from file. The selected card preset auto-fills the Secured Packet form and sets the TAR for the operation (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); a TAR typed into the Secured Packet form by hand is kept when sending - the counter, keys and the TAR's MSL are still re-read from the preset; the SPI1 is seeded from the TAR's MSL and a lower value warns (the server returns it as a warning too); edits are pushed into a running SCP81 listener automatically.

diff --git a/frontend/index.html b/frontend/index.html index 347d440..b615def 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1593,49 +1593,95 @@