docs: help/README catch up with v3.8.0; keyset-number wording; RU "пресет"
Documentation:
- help (§1/§3): the SCP80 tab is switched by three pills - the tab list and the
section intro now name the TAR probe (RU "TAR-сканер"); §3.1/§3.2 describe the
Keyset selector next to the preset selector (and that a successful PoR
advances the counter only when SPI1 carries a counter check); §4 describes
the keyset editor rows, the derived number and the per-keyset counters; the
probe section keeps its counter rule.
- README/README_RUS: the SCP80 tab says three pills and gains a "TAR probe" /
"TAR-сканер" section (standard list, verdicts, counter persistence); the
Cards section is rewritten for the server-side store - keysets, server-owned
per-keyset counters with the audit trail, JSON export/import as the migration
path, the keyset editor, the equipped-card mismatch banner - and the field
table, "Add a card" and "Edit / remove" follow.
Terminology:
- "key version" is no longer used for SCP80 keysets in the UI, the server error
strings and the docs: the selector is "Keyset", its options "Keyset 1 - ...",
the messages say "keyset N ...". The TS 102 225 A.1/A.2 quotes and the GP
PUT KEY P1 field keep the spec's own wording.
- RU keeps the word "keyset" untranslated ('Добавить keyset', 'Номер keyset',
"не является keyset пресета", ...) and uses "пресет" instead of
"предустановка" throughout the dictionary, the help and README_RUS.
sw cache simple-v340. Tests: 742 Node / 619 Python.
This commit is contained in:
+61
-62
@@ -528,7 +528,7 @@
|
||||
<select id="sp-card-sel" onchange="cardsApply(this.value)" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800">
|
||||
<option value="" data-l10n="— Select card —">— Select card —</option>
|
||||
</select>
|
||||
<label class="block mt-2 mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Key version (keyset)">Key version (keyset)</label>
|
||||
<label class="block mt-2 mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Keyset">Keyset</label>
|
||||
<select id="sp-keyset-sel" onchange="spKeysetChanged()" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800"></select>
|
||||
</div>
|
||||
<div id="sp-preset-warning" class="hidden mb-3 px-3 py-2 rounded border border-amber-400 dark:border-amber-600 bg-amber-50 dark:bg-amber-900/20 text-sm text-amber-700 dark:text-amber-300"></div>
|
||||
@@ -695,7 +695,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Key version (keyset)">Key version (keyset)</label>
|
||||
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Keyset">Keyset</label>
|
||||
<select id="ram-keyset-sel" onchange="ramKeysetChanged()" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800"></select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
@@ -922,7 +922,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Key version (keyset)">Key version (keyset)</label>
|
||||
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-slate-300" data-l10n="Keyset">Keyset</label>
|
||||
<select id="tar-keyset-sel" onchange="tarKeysetChanged()" class="w-full border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800"></select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1580,7 +1580,7 @@
|
||||
|
||||
|
||||
<div id="tab-cards" class="tab-content hidden">
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400 mb-3" data-l10n="Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries one keyset per key version, each with its own counter.">Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries one keyset per key version, each with its own counter.</p>
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400 mb-3" data-l10n="Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries several keysets, each with its own number and counter.">Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries several keysets, each with its own number and counter.</p>
|
||||
<div class="flex gap-2 mb-3">
|
||||
<input id="cards-name" class="flex-1 border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800" placeholder="Name (e.g. Foobar SIM)">
|
||||
<input id="cards-iccid" class="flex-1 border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800 font-mono" placeholder="ICCID (optional)">
|
||||
@@ -1610,11 +1610,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-1 flex items-center justify-between">
|
||||
<span class="text-xs text-gray-600 dark:text-slate-400" data-l10n="OTA keysets — one per key version, each with its own counter">OTA keysets — one per key version, each with its own counter</span>
|
||||
<span class="text-xs text-gray-600 dark:text-slate-400" data-l10n="OTA keysets — each with its own number and counter">OTA keysets — each with its own number and counter</span>
|
||||
<button type="button" onclick="cardsKeysetAdd()" class="px-2 py-0.5 text-xs rounded border border-gray-300 dark:border-slate-600 hover:bg-gray-200 dark:hover:bg-slate-700" data-l10n="Add keyset">Add keyset</button>
|
||||
</div>
|
||||
<div id="cards-keysets"></div>
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400" data-l10n="KIc and KID must carry the same key version (their high nibble) in the range 01-0F — TS 102 225 A.2; each key version has its own counter on the card (Annex A.1).">KIc and KID must carry the same key version (their high nibble) in the range 01-0F — TS 102 225 A.2; each key version has its own counter on the card (Annex A.1).</p>
|
||||
<p class="text-xs text-gray-500 dark:text-slate-400" data-l10n="KIc and KID must carry the same keyset number (their high nibble) in the range 01-0F — TS 102 225 A.2; each keyset has its own counter on the card (Annex A.1).">KIc and KID must carry the same keyset number (their high nibble) in the range 01-0F — TS 102 225 A.2; each keyset has its own counter on the card (Annex A.1).</p>
|
||||
</fieldset>
|
||||
<fieldset class="border border-gray-200 dark:border-slate-700 rounded p-3 mb-3">
|
||||
<legend class="px-1 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="SCP81 (HTTP OTA)">SCP81 (HTTP OTA)</legend>
|
||||
@@ -1629,7 +1629,7 @@
|
||||
<thead><tr>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700" data-l10n="Name">Name</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700" data-l10n="ICCID">ICCID</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700" data-l10n="Keysets (key version: KIc/KID — counter)">Keysets (key version: KIc/KID \u2014 counter)</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700" data-l10n="Keysets (number: KIc/KID — counter)">Keysets (number: KIc/KID \u2014 counter)</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700">SPI1</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700">SPI2</th>
|
||||
<th class="text-left py-1 px-2 border-b border-gray-200 dark:border-slate-700">TAR (ISD/UICC RFM/ADF RFM)</th>
|
||||
@@ -4941,7 +4941,7 @@ function crc32Bytes(data) {
|
||||
// CPL = octets from CHL to end incl. padding; CHL = 13 + len_sig (CC 8, RC 4).
|
||||
// CPI (0x70) and CHI (null) are NOT part of the SMS packet data.
|
||||
function genSp() {
|
||||
// The packet's key version must be defined in the selected preset
|
||||
// The packet's keyset number must be defined in the selected preset
|
||||
// (TS 102 225 A.2 / the "keyset must exist" rule).
|
||||
const ksErr = spKeysetGuard();
|
||||
if (ksErr) { alert(ksErr); return; }
|
||||
@@ -7140,7 +7140,7 @@ function testStepRender() {
|
||||
{v: 'apdu', l: t('C-APDU (built with the preset)')}, {v: 'sp', l: t('Pre-built secured packet')}], 'testStepKindChanged()'));
|
||||
if (src === 'sp') html += testFormRow('Secured packet (hex)', testFormInput('test-f-sp', p.sp, '01 00 ...'));
|
||||
else html += testFormRow('C-APDU (hex)', testFormInput('test-f-apdu', p.apdu, '80E2900000'));
|
||||
html += testFormRow('Key version (kvn, optional)',
|
||||
html += testFormRow('Keyset number (optional)',
|
||||
testFormInput('test-f-kvn', p.kvn === undefined ? '' : p.kvn, t('empty = the preset\'s first keyset')));
|
||||
html += testFormRow('TAR override (hex, optional)', testFormInput('test-f-tar', p.tar, 'B00000'));
|
||||
html += testFormRow('SPI1 override (hex, optional)', testFormInput('test-f-spi1', p.spi1, '16'));
|
||||
@@ -7541,7 +7541,7 @@ async function testPollRun() {
|
||||
function testWriteBackCounter() {
|
||||
const st = _testRunState;
|
||||
if (!st || st.running) return;
|
||||
// The server persists every counter the run consumed (one per key version);
|
||||
// The server persists every counter the run consumed (one per keyset number);
|
||||
// this only keeps the local copies in step with what it reports.
|
||||
const counters = (st.scp80_counters && typeof st.scp80_counters === 'object')
|
||||
? st.scp80_counters : null;
|
||||
@@ -10823,7 +10823,7 @@ function ramGoToPreset(idx) {
|
||||
switchTab('cards');
|
||||
const i = Number(idx);
|
||||
if (Number.isInteger(i) && i >= 0 && cards[i]) cardsEdit(i);
|
||||
// Focus the counter of the key version the failed operation used (the
|
||||
// Focus the counter of the keyset number the failed operation used (the
|
||||
// keyset rows are keyed by their version; the first row otherwise).
|
||||
const kvn = spKeysetKvnOf((document.getElementById('sp-kic-hex') || {}).value) ||
|
||||
spKeysetKvnOf((document.getElementById('sp-kid-hex') || {}).value) || 0;
|
||||
@@ -11304,15 +11304,15 @@ function cardsTarValue(key, value) {
|
||||
return value || defaults[key] || '';
|
||||
}
|
||||
|
||||
// ===== OTA keysets (one per GlobalPlatform key version) =====
|
||||
// A preset carries one keyset per key version: the b8..b5 nibble of KIc/KID
|
||||
// ===== OTA keysets (one per keyset number) =====
|
||||
// A preset carries several keysets: a keyset's number is the b8..b5 nibble of KIc/KID
|
||||
// (TS 102 225 5.1.2/A.2). The version is implicit in the bytes - the "key
|
||||
// index" - and each key version has its own counter on the card ("a dedicated
|
||||
// index" - and each keyset has its own counter on the card ("a dedicated
|
||||
// counter shall be associated to each key version", Annex A.1). A packet may
|
||||
// use any key version the preset defines; '00'/'00' means no security (A.2)
|
||||
// use any keyset the preset defines; '00'/'00' means no security (A.2)
|
||||
// and needs no keyset.
|
||||
|
||||
// The key version of a KIc/KID byte, or null when it is not a hex byte.
|
||||
// The keyset number of a KIc/KID byte, or null when it is not a hex byte.
|
||||
function spKeysetKvnOf(hex) {
|
||||
const s = String(hex || '').trim().toUpperCase();
|
||||
if (!/^[0-9A-F]{2}$/.test(s)) return null;
|
||||
@@ -11340,14 +11340,14 @@ function spKeysetList(preset) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// The keyset of a preset for a key version, or null.
|
||||
// The keyset of a preset with the given number, or null.
|
||||
function spKeysetFor(preset, kvn) {
|
||||
return spKeysetList(preset).find(ks => spKeysetKvnOf(ks.kic) === kvn) || null;
|
||||
}
|
||||
|
||||
// The packet's key-version rules (pure): '' when the pair is usable, else the
|
||||
// reason. With a preset, the (non-zero) key version must be defined in it -
|
||||
// a packet may use any key version, but only one the preset defines.
|
||||
// reason. With a preset, the (non-zero) keyset number must be defined in it -
|
||||
// a packet may use any keyset, but only one the preset defines.
|
||||
function spKeysetCheck(preset, kicHex, kidHex) {
|
||||
const kic = String(kicHex || '').trim().toUpperCase();
|
||||
const kid = String(kidHex || '').trim().toUpperCase();
|
||||
@@ -11358,12 +11358,12 @@ function spKeysetCheck(preset, kicHex, kidHex) {
|
||||
}
|
||||
const kicV = spKeysetKvnOf(kic), kidV = spKeysetKvnOf(kid);
|
||||
if (kicV && kidV && kicV !== kidV) {
|
||||
return t('KIc and KID must carry the same key version (TS 102 225 A.2)') + ': ' + kic + ' / ' + kid;
|
||||
return t('KIc and KID must carry the same keyset number (TS 102 225 A.2)') + ': ' + kic + ' / ' + kid;
|
||||
}
|
||||
const kvn = kicV || kidV || 0;
|
||||
if (!kvn) return ''; // '00'/'00': no security
|
||||
if (preset && !spKeysetFor(preset, kvn)) {
|
||||
return t('Key version') + ' ' + kvn + ' ' + t('is not defined in the preset') +
|
||||
return t('Keyset') + ' ' + kvn + ' ' + t('is not defined in the preset') +
|
||||
(preset.name ? ' \u2014 ' + preset.name : '');
|
||||
}
|
||||
return '';
|
||||
@@ -11380,11 +11380,11 @@ function spKeysetOptionsHtml(preset, kicHex, kidHex) {
|
||||
if (v === null) return;
|
||||
if (v === kvn) found = true;
|
||||
html += '<option value="' + v + '"' + (v === kvn ? ' selected' : '') + '>' +
|
||||
v + ' \u2014 ' + esc(ks.kic || '??') + '/' + esc(ks.kid || '??') +
|
||||
'Keyset ' + v + ' \u2014 ' + esc(ks.kic || '??') + '/' + esc(ks.kid || '??') +
|
||||
' \u2014 ' + esc(t('counter')) + ' ' + esc(ks.cntr || '') + '</option>';
|
||||
});
|
||||
if (kvn && !found) {
|
||||
html += '<option value="' + kvn + '" selected>' + kvn + ' \u2014 ' +
|
||||
html += '<option value="' + kvn + '" selected>Keyset ' + kvn + ' \u2014 ' +
|
||||
esc(t('not defined in the preset')) + '</option>';
|
||||
}
|
||||
if (!html) html = '<option value="">' + esc(t('\u2014 no keyset \u2014')) + '</option>';
|
||||
@@ -11398,7 +11398,7 @@ function cardsKeysetRowHtml(ks, i) {
|
||||
const cls = 'border border-gray-300 dark:border-slate-600 text-sm rounded px-2 py-1.5 dark:bg-slate-800 font-mono';
|
||||
const kvn = spKeysetKvnOf(ks.kic);
|
||||
return '<div class="flex gap-2 items-center mb-1">' +
|
||||
'<span id="cards-ks-' + i + '-kvn" class="w-10 text-xs font-mono text-center text-gray-500 dark:text-slate-400" title="' + esc(t('Key version (b8..b5 of KIc/KID)')) + '">' + (kvn === null ? '?' : kvn) + '</span>' +
|
||||
'<span id="cards-ks-' + i + '-kvn" class="w-10 text-xs font-mono text-center text-gray-500 dark:text-slate-400" title="' + esc(t('Keyset number (b8..b5 of KIc/KID)')) + '">' + (kvn === null ? '?' : kvn) + '</span>' +
|
||||
'<input id="cards-ks-' + i + '-kic" class="w-12 ' + cls + ' text-center" maxlength="2" placeholder="KIc" value="' + esc(ks.kic || '') + '" oninput="cardsKeysetKvnUpdate(' + i + ')">' +
|
||||
'<input id="cards-ks-' + i + '-kid" class="w-12 ' + cls + ' text-center" maxlength="2" placeholder="KID" value="' + esc(ks.kid || '') + '" oninput="cardsKeysetKvnUpdate(' + i + ')">' +
|
||||
'<input id="cards-ks-' + i + '-kic-key" class="flex-1 ' + cls + '" placeholder="KIc key (hex)" value="' + esc(ks.kicKey || '') + '">' +
|
||||
@@ -11438,8 +11438,8 @@ function cardsKeysetKvnUpdate(i) {
|
||||
const bad = (a !== null && b !== null && a !== b) || a === 0 || b === 0;
|
||||
el.textContent = a === null ? '?' : a;
|
||||
el.classList.toggle('text-red-500', !!bad);
|
||||
el.title = bad ? t('KIc and KID must carry the same key version (TS 102 225 A.2)')
|
||||
: t('Key version (b8..b5 of KIc/KID)');
|
||||
el.title = bad ? t('KIc and KID must carry the same keyset number (TS 102 225 A.2)')
|
||||
: t('Keyset number (b8..b5 of KIc/KID)');
|
||||
}
|
||||
|
||||
// The keyset rows as preset entries (empty rows are dropped).
|
||||
@@ -11461,7 +11461,7 @@ function cardsKeysetsFromForm() {
|
||||
|
||||
// ===== Keyset selectors (SCP80 / RAM) =====
|
||||
// The selector follows the KIc/KID bytes: a keyset of the selected preset that
|
||||
// matches their key version is selected; a version the preset does not define
|
||||
// matches their keyset number is selected; a number the preset does not define
|
||||
// shows as "not defined" (and the packet actions refuse it).
|
||||
function spKeysetSync() {
|
||||
const spIdx = spPresetIdx();
|
||||
@@ -11574,7 +11574,7 @@ function ramPresetIdx() {
|
||||
}
|
||||
|
||||
// '' when the SCP80 form may build a packet, else the reason. With a preset
|
||||
// selected the key version must be one of its keysets; without one only the
|
||||
// selected the keyset number must be one of its keysets; without one only the
|
||||
// byte rules apply (hand-entered keys stay possible, a workbench flow).
|
||||
function spKeysetGuard() {
|
||||
const idx = spPresetIdx();
|
||||
@@ -11649,13 +11649,13 @@ async function cardsAdd() {
|
||||
const ksErr = spKeysetCheck(null, ks.kic, ks.kid);
|
||||
if (ksErr) { alert(ksErr); return; }
|
||||
if (!spKeysetKvnOf(ks.kic) || !spKeysetKvnOf(ks.kid)) {
|
||||
alert(t('Key version 00 means "no security" and is not a preset keyset'));
|
||||
alert(t('Keyset 00 means "no security" and is not a preset keyset'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
const kvns = v.keysets.map(ks => spKeysetKvnOf(ks.kic));
|
||||
if (new Set(kvns).size !== kvns.length) {
|
||||
alert(t('Duplicate key version in the keysets'));
|
||||
alert(t('Duplicate keyset number in the keysets'));
|
||||
return;
|
||||
}
|
||||
if ((v.pskKey && !v.pskIdentity) || (!v.pskKey && v.pskIdentity)) {
|
||||
@@ -11887,7 +11887,7 @@ function cardsApplyFields(idx, keepTar) {
|
||||
const smSel = document.getElementById('sp-spi2-sm');
|
||||
if (smSel) smSel.value = String((spi2Val >> 5) & 1);
|
||||
document.getElementById('sp-spi2-hex').value = c.spi2;
|
||||
// The keyset: keep the key version the form carries when this preset
|
||||
// The keyset: keep the keyset number the form carries when this preset
|
||||
// defines it, otherwise start from the preset's first keyset.
|
||||
const kicNow = (document.getElementById('sp-kic-hex') || {}).value;
|
||||
const kidNow = (document.getElementById('sp-kid-hex') || {}).value;
|
||||
@@ -18937,7 +18937,7 @@ const LANG_RU = {
|
||||
'GET DATA tag': 'Tag GET DATA',
|
||||
'Response data (hex)': 'Данные ответа (hex)',
|
||||
'— Select command —': '— Выберите команду —',
|
||||
'— select preset —': '— выберите предустановленный —',
|
||||
'— select preset —': '— выберите пресет —',
|
||||
'Error: specify SELECT parameters': 'Ошибка: укажите параметры SELECT',
|
||||
'Error: unknown command': 'Ошибка: неизвестная команда',
|
||||
'Error: specify data': 'Ошибка: укажите данные',
|
||||
@@ -19771,28 +19771,27 @@ const LANG_RU = {
|
||||
'SCP81 HTTP OTA: the listener picks the key by the PSK identity the card sends in the TLS handshake. Cards without a PSK are ignored by the listener.': 'SCP81 HTTP OTA: слушатель выбирает ключ по PSK identity, которую карта присылает в TLS-рукопожатии. Карты без PSK слушателем игнорируются.',
|
||||
'Card with this ICCID already exists': 'Карта с таким ICCID уже есть в списке',
|
||||
'Card equipped but its ICCID is not readable': 'Карта подключена, но её ICCID не читается',
|
||||
'OTA keysets — one per key version, each with its own counter': 'Наборы ключей OTA — по одному на версию ключа, у каждой свой счётчик',
|
||||
'Add keyset': 'Добавить набор ключей',
|
||||
'Remove keyset': 'Удалить набор ключей',
|
||||
'Key version (keyset)': 'Версия ключа (набор ключей)',
|
||||
'Key version': 'Версия ключа',
|
||||
'Key version (b8..b5 of KIc/KID)': 'Версия ключа (биты b8..b5 KIc/KID)',
|
||||
'Keysets (key version: KIc/KID — counter)': 'Наборы ключей (версия: KIc/KID — счётчик)',
|
||||
'OTA keysets — each with its own number and counter': 'OTA keysets — у каждого свой номер и счётчик',
|
||||
'Add keyset': 'Добавить keyset',
|
||||
'Remove keyset': 'Удалить keyset',
|
||||
'Keyset': 'Keyset',
|
||||
'Keyset number (b8..b5 of KIc/KID)': 'Номер keyset (b8..b5 KIc/KID)',
|
||||
'Keysets (number: KIc/KID — counter)': 'Keysets (номер: KIc/KID — счётчик)',
|
||||
'must be one hex byte': 'должен быть одним hex-байтом',
|
||||
'KIc and KID must carry the same key version (TS 102 225 A.2)': 'KIc и KID должны содержать одну и ту же версию ключа (TS 102 225 A.2)',
|
||||
'is not defined in the preset': 'не определена в предустановке',
|
||||
'not defined in the preset': 'не определена в предустановке',
|
||||
'— no keyset —': '— нет набора ключей —',
|
||||
'KIc and KID must carry the same keyset number (TS 102 225 A.2)': 'KIc и KID должны содержать один и тот же номер keyset (TS 102 225 A.2)',
|
||||
'is not defined in the preset': 'не определён в пресете',
|
||||
'not defined in the preset': 'не определён в пресете',
|
||||
'— no keyset —': '— нет keyset —',
|
||||
'counter': 'счётчик',
|
||||
'Define at least one keyset (KIc/KID and their keys)': 'Определите хотя бы один набор ключей (KIc/KID и их ключи)',
|
||||
'Define at least one keyset (KIc/KID and their keys)': 'Определите хотя бы один keyset (KIc/KID и его ключи)',
|
||||
'Each keyset needs KIc, KID and both keys': 'Каждому набору нужны KIc, KID и оба ключа',
|
||||
'Key version 00 means "no security" and is not a preset keyset': 'Версия ключа 00 означает «без защиты» и не является набором ключей предустановки',
|
||||
'Duplicate key version in the keysets': 'Дублирующаяся версия ключа в наборах',
|
||||
'Select a card preset - its keysets define the key versions': 'Выберите предустановку карты — её наборы ключей определяют версии ключей',
|
||||
'SCP80 counters saved to the preset.': 'Счётчики SCP80 сохранены в предустановке.',
|
||||
'Keyset 00 means "no security" and is not a preset keyset': 'keyset 00 означает «без защиты» и не является keyset пресета',
|
||||
'Duplicate keyset number in the keysets': 'Повторяющийся номер keyset',
|
||||
'Select a card preset - its keysets define the keyset numbers': 'Выберите пресет карты — его keysets задают номера keyset',
|
||||
'SCP80 counters saved to the preset.': 'Счётчики SCP80 сохранены в пресете.',
|
||||
'counter not tracked (SPI1 has no counter check)': 'счётчик не отслеживается (в SPI1 нет проверки счётчика)',
|
||||
'TAR probe': 'TAR-сканер',
|
||||
'Sends one secured packet per selected TAR (TS 101 220 Annex D, Table D.1) carrying a harmless command, and classifies the card\'s answer - which OTA applications it has registered. Every packet the card accepts consumes a counter, which is saved to the preset.': 'Отправляет по одному защищённому пакету на каждый выбранный TAR (TS 101 220 Annex D, Table D.1) с безобидной командой и классифицирует ответ карты — какие OTA-приложения на ней зарегистрированы. Каждый принятый картой пакет расходует счётчик, который сохраняется в предустановке.',
|
||||
'Sends one secured packet per selected TAR (TS 101 220 Annex D, Table D.1) carrying a harmless command, and classifies the card\'s answer - which OTA applications it has registered. Every packet the card accepts consumes a counter, which is saved to the preset.': 'Отправляет по одному защищённому пакету на каждый выбранный TAR (TS 101 220 Annex D, Table D.1) с безобидной командой и классифицирует ответ карты — какие OTA-приложения на ней зарегистрированы. Каждый принятый картой пакет расходует счётчик, который сохраняется в пресете.',
|
||||
'TARs to probe — TS 101 220 V18.3.0 Annex D, Table D.1': 'TAR для пробы — TS 101 220 V18.3.0 Annex D, Table D.1',
|
||||
'Select all': 'Выбрать все',
|
||||
'Select none': 'Снять все',
|
||||
@@ -19803,7 +19802,7 @@ const LANG_RU = {
|
||||
'Probe TARs (registered OTA applications)': 'Проба TAR (зарегистрированные OTA-приложения)',
|
||||
'Probe APDU (hex)': 'APDU пробы (hex)',
|
||||
'TARs to probe (hex, one per line; empty = all standard TARs of TS 101 220 Annex D)': 'TAR для пробы (hex, по одному в строке; пусто = все стандартные TAR из TS 101 220 Annex D)',
|
||||
'One secured packet per TAR: each packet the card accepts consumes a counter, which is saved to the preset.': 'Один защищённый пакет на каждый TAR: каждый принятый картой пакет расходует счётчик, который сохраняется в предустановке.',
|
||||
'One secured packet per TAR: each packet the card accepts consumes a counter, which is saved to the preset.': 'Один защищённый пакет на каждый TAR: каждый принятый картой пакет расходует счётчик, который сохраняется в пресете.',
|
||||
'Specify the probe APDU': 'Укажите APDU пробы',
|
||||
'Registered applications:': 'Зарегистрированные приложения:',
|
||||
'Application': 'Приложение',
|
||||
@@ -19815,14 +19814,14 @@ const LANG_RU = {
|
||||
'accepted, no PoR': 'принято, нет PoR',
|
||||
'No card presets defined — the SCP80/RAM views have no keys for the equipped card. Add one in the Cards tab.': 'Предустановки карт не заданы — в представлениях SCP80/RAM нет ключей для подключённой карты. Добавьте её на вкладке «Карты».',
|
||||
'The equipped card': 'Подключённая карта',
|
||||
'does not match any card preset — the selected preset may belong to another card. Add it in the Cards tab (From card).': 'не совпадает ни с одной предустановкой — выбранная предустановка может принадлежать другой карте. Добавьте её на вкладке «Карты» (кнопка «С карты»).',
|
||||
"The selected preset is not the equipped card's": 'Выбранная предустановка не принадлежит подключённой карте',
|
||||
'does not match any card preset — the selected preset may belong to another card. Add it in the Cards tab (From card).': 'не совпадает ни с одним пресетом — выбранный пресет может принадлежать другой карте. Добавьте его на вкладке «Карты» (кнопка «С карты»).',
|
||||
"The selected preset is not the equipped card's": 'Выбранный пресет не принадлежит подключённой карте',
|
||||
'check that its keys and counters belong to this card.': 'проверьте, что её ключи и счётчики относятся к этой карте.',
|
||||
'Key version (kvn, optional)': 'Версия ключа (kvn, опционально)',
|
||||
"empty = the preset's first keyset": 'пусто = первый набор ключей предустановки',
|
||||
'Keysets (key version: KIc/KID — counter)': 'Наборы ключей (версия: KIc/KID — счётчик)',
|
||||
'KIc and KID must carry the same key version (their high nibble) in the range 01-0F — TS 102 225 A.2; each key version has its own counter on the card (Annex A.1).': 'KIc и KID должны содержать одну и ту же версию ключа (старший ниббл) в диапазоне 01-0F — TS 102 225 A.2; у каждой версии ключа свой счётчик на карте (Annex A.1).',
|
||||
'Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries one keyset per key version, each with its own counter.': 'Предустановки карт хранятся на сервере. Кнопки экспорта/импорта JSON — под списком карт; предустановка содержит один набор ключей на версию, у каждой свой счётчик.',
|
||||
'Keyset number (optional)': 'Номер keyset (опционально)',
|
||||
"empty = the preset's first keyset": 'пусто = первый keyset пресета',
|
||||
'Keysets (number: KIc/KID — counter)': 'Keysets (номер: KIc/KID — счётчик)',
|
||||
'KIc and KID must carry the same keyset number (their high nibble) in the range 01-0F — TS 102 225 A.2; each keyset has its own counter on the card (Annex A.1).': 'KIc и KID должны содержать один и тот же номер keyset (старший ниббл) в диапазоне 01-0F — TS 102 225 A.2; у каждого keyset свой счётчик на карте (Annex A.1).',
|
||||
'Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries several keysets, each with its own number and counter.': 'Пресеты карт хранятся на сервере. Кнопки экспорта/импорта JSON — под списком карт; пресет содержит несколько keysets, у каждого свой номер и счётчик.',
|
||||
'Save error': 'Ошибка сохранения',
|
||||
'Delete error': 'Ошибка удаления',
|
||||
'Counter not saved:': 'Счётчик не сохранён:',
|
||||
@@ -19883,9 +19882,9 @@ const LANG_RU = {
|
||||
'Show link events (Channel status ENVELOPEs, TS 102 223 7.5.11)': 'Показывать события канала (ENVELOPE Channel status, TS 102 223 7.5.11)',
|
||||
'ADM verified': 'ADM подтверждён',
|
||||
'ADM not verified': 'ADM не подтверждён',
|
||||
'ADM key in the card preset — verified': 'Ключ ADM в предустановке — подтверждён',
|
||||
'ADM key in the card preset — not verified': 'Ключ ADM в предустановке — не подтверждён',
|
||||
'ADM key in the card preset — click to verify': 'Ключ ADM в предустановке — нажмите для проверки',
|
||||
'ADM key in the card preset — verified': 'Ключ ADM в пресете — подтверждён',
|
||||
'ADM key in the card preset — not verified': 'Ключ ADM в пресете — не подтверждён',
|
||||
'ADM key in the card preset — click to verify': 'Ключ ADM в пресете — нажмите для проверки',
|
||||
'Verify ADM': 'Проверить ADM',
|
||||
'Verifying ADM...': 'Проверка ADM...',
|
||||
'ADM verification failed': 'Проверка ADM не удалась',
|
||||
@@ -19895,8 +19894,8 @@ const LANG_RU = {
|
||||
'This is the last attempt before the ADM is blocked. Try again?': 'Это последняя попытка — неверный ключ заблокирует ADM. Попробовать снова?',
|
||||
'ADM is blocked': 'ADM заблокирован',
|
||||
'ADM is blocked — unblock the card to try again': 'ADM заблокирован — разблокируйте карту, чтобы повторить',
|
||||
'Verified — no ADM key in the card preset': 'Подтверждён — ключа ADM в предустановке нет',
|
||||
'No ADM key in the card preset — not verified': 'Ключа ADM в предустановке нет — не подтверждён',
|
||||
'Verified — no ADM key in the card preset': 'Подтверждён — ключа ADM в пресете нет',
|
||||
'No ADM key in the card preset — not verified': 'Ключа ADM в пресете нет — не подтверждён',
|
||||
'SCP80 preset complete': 'Предустановка SCP80 заполнена',
|
||||
'SCP81 preset complete': 'Предустановка SCP81 заполнена',
|
||||
'Network state': 'Сетевое состояние',
|
||||
|
||||
Reference in New Issue
Block a user