-
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathGUIDE.ru.html
More file actions
1128 lines (985 loc) · 68.3 KB
/
Copy pathGUIDE.ru.html
File metadata and controls
1128 lines (985 loc) · 68.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SecureGen — Руководство пользователя</title>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@300;400;500&display=swap" rel="stylesheet">
<style>
:root {
--bg: #0a0a0f;
--surface: #111118;
--border: #1e1e2e;
--accent: #00e5ff;
--accent2: #7c3aed;
--text: #c9d1d9;
--text-dim: #586069;
--text-bright: #e6edf3;
--warn: #f59e0b;
--danger: #ef4444;
--success: #22c55e;
--mono: 'IBM Plex Mono', monospace;
--sans: 'IBM Plex Sans', sans-serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--text);
font-family: var(--sans);
font-weight: 300;
line-height: 1.7;
min-height: 100vh;
}
/* Layout */
.layout { display: flex; min-height: 100vh; }
/* Sidebar */
.sidebar {
width: 260px;
min-width: 260px;
background: var(--surface);
border-right: 1px solid var(--border);
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
padding: 2rem 0;
}
.sidebar-logo {
padding: 0 1.5rem 1.5rem;
border-bottom: 1px solid var(--border);
margin-bottom: 1rem;
}
.sidebar-logo .device-name {
font-family: var(--mono);
font-size: 0.65rem;
color: var(--accent);
letter-spacing: 0.15em;
text-transform: uppercase;
display: block;
margin-bottom: 0.2rem;
}
.sidebar-logo h1 {
font-family: var(--mono);
font-size: 1.1rem;
font-weight: 600;
color: var(--text-bright);
}
.nav-section {
padding: 0.5rem 0;
}
.nav-label {
font-family: var(--mono);
font-size: 0.6rem;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--text-dim);
padding: 0.4rem 1.5rem;
display: block;
}
.nav-link {
display: block;
padding: 0.35rem 1.5rem;
color: var(--text-dim);
text-decoration: none;
font-size: 0.85rem;
font-weight: 400;
border-left: 2px solid transparent;
transition: all 0.15s;
}
.nav-link:hover {
color: var(--text-bright);
background: rgba(0,229,255,0.04);
border-left-color: var(--accent);
}
.nav-link.active {
color: var(--accent);
border-left-color: var(--accent);
background: rgba(0,229,255,0.06);
}
/* Main content */
.main {
flex: 1;
max-width: 820px;
padding: 3rem 3.5rem;
overflow-x: hidden;
}
/* Section */
.section {
margin-bottom: 4rem;
scroll-margin-top: 2rem;
}
.section-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--border);
}
.section-num {
font-family: var(--mono);
font-size: 0.65rem;
color: var(--accent);
background: rgba(0,229,255,0.08);
border: 1px solid rgba(0,229,255,0.2);
padding: 0.15rem 0.5rem;
border-radius: 2px;
letter-spacing: 0.05em;
}
h2 {
font-family: var(--mono);
font-size: 1.05rem;
font-weight: 600;
color: var(--text-bright);
letter-spacing: 0.02em;
}
h3 {
font-family: var(--mono);
font-size: 0.85rem;
font-weight: 500;
color: var(--accent);
letter-spacing: 0.05em;
margin: 1.75rem 0 0.75rem;
text-transform: uppercase;
}
h4 {
font-size: 0.9rem;
font-weight: 500;
color: var(--text-bright);
margin: 1.25rem 0 0.5rem;
}
p {
font-size: 0.9rem;
color: var(--text);
margin-bottom: 0.75rem;
}
/* Tables */
.table-wrap { overflow-x: auto; margin: 1rem 0; }
table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
th {
font-family: var(--mono);
font-size: 0.65rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-dim);
text-align: left;
padding: 0.6rem 1rem;
background: rgba(255,255,255,0.02);
border-bottom: 1px solid var(--border);
}
td {
padding: 0.6rem 1rem;
border-bottom: 1px solid rgba(255,255,255,0.04);
color: var(--text);
vertical-align: top;
}
tr:last-child td { border-bottom: none; }
td:first-child {
font-family: var(--mono);
font-size: 0.8rem;
color: var(--text-bright);
white-space: nowrap;
}
/* Key badge */
.key {
display: inline-block;
font-family: var(--mono);
font-size: 0.72rem;
background: var(--surface);
border: 1px solid var(--border);
border-bottom: 2px solid rgba(255,255,255,0.15);
padding: 0.1rem 0.45rem;
border-radius: 3px;
color: var(--text-bright);
white-space: nowrap;
}
/* Callouts */
.callout {
border-left: 3px solid;
padding: 0.75rem 1rem;
margin: 1rem 0;
border-radius: 0 4px 4px 0;
font-size: 0.85rem;
}
.callout-warn {
border-color: var(--warn);
background: rgba(245,158,11,0.06);
color: #fcd34d;
}
.callout-info {
border-color: var(--accent);
background: rgba(0,229,255,0.05);
color: #67e8f9;
}
.callout-danger {
border-color: var(--danger);
background: rgba(239,68,68,0.06);
color: #fca5a5;
}
.callout strong {
font-family: var(--mono);
font-size: 0.7rem;
letter-spacing: 0.1em;
text-transform: uppercase;
display: block;
margin-bottom: 0.25rem;
opacity: 0.8;
}
/* Mode cards */
.mode-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin: 1rem 0;
}
.mode-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 6px;
padding: 1.25rem;
}
.mode-card .mode-title {
font-family: var(--mono);
font-size: 0.75rem;
font-weight: 600;
color: var(--text-bright);
letter-spacing: 0.05em;
margin-bottom: 0.25rem;
}
.mode-card .mode-trigger {
font-size: 0.75rem;
color: var(--text-dim);
margin-bottom: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--border);
}
.mode-card ul {
list-style: none;
font-size: 0.8rem;
}
.mode-card li {
padding: 0.15rem 0;
color: var(--text);
}
.mode-card li::before {
content: '✓ ';
color: var(--success);
font-family: var(--mono);
}
.mode-card li.no::before {
content: '✗ ';
color: var(--text-dim);
}
.mode-card li.no { color: var(--text-dim); }
/* Steps */
.steps { list-style: none; counter-reset: step; margin: 0.75rem 0; }
.steps li {
counter-increment: step;
display: flex;
gap: 0.75rem;
align-items: flex-start;
padding: 0.5rem 0;
font-size: 0.88rem;
}
.steps li::before {
content: counter(step);
font-family: var(--mono);
font-size: 0.7rem;
font-weight: 600;
color: var(--accent);
background: rgba(0,229,255,0.1);
border: 1px solid rgba(0,229,255,0.25);
min-width: 1.5rem;
height: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
flex-shrink: 0;
margin-top: 0.1rem;
}
/* Inline code */
code {
font-family: var(--mono);
font-size: 0.8rem;
background: rgba(255,255,255,0.06);
border: 1px solid var(--border);
padding: 0.1rem 0.35rem;
border-radius: 3px;
color: var(--accent);
}
/* Responsive */
@media (max-width: 900px) {
.sidebar { display: none; }
.main { padding: 2rem 1.5rem; }
.mode-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="layout">
<!-- Sidebar -->
<nav class="sidebar">
<div class="sidebar-logo" style="position:relative;">
<span class="device-name">ESP32 T-Display</span>
<h1>SecureGen</h1>
<div style="position:absolute;bottom:0;right:0.5rem;font-size:0.8rem;">
<a href="GUIDE.html" style="color:var(--text-dim);text-decoration:none;">🇬🇧</a>
<strong style="color:var(--accent);">🇷🇺</strong>
</div>
</div>
<div class="nav-section">
<span class="nav-label">Устройство</span>
<a href="#buttons" class="nav-link">Кнопки</a>
<a href="#first-boot" class="nav-link">Первый запуск</a>
<a href="#modes" class="nav-link">Режимы работы</a>
<a href="#navigation" class="nav-link">Навигация</a>
<a href="#ble" class="nav-link">HID передача</a>
<a href="#factory-reset" class="nav-link">Сброс настроек</a>
</div>
<div class="nav-section">
<span class="nav-label">Веб-кабинет</span>
<a href="#web-access" class="nav-link">Доступ и вход</a>
<a href="#widget-bar" class="nav-link">Виджет-бар</a>
<a href="#keys" class="nav-link">Ключи (TOTP / HOTP)</a>
<a href="#passwords" class="nav-link">Пароли</a>
<a href="#display" class="nav-link">Экран</a>
<a href="#pin" class="nav-link">Настройки PIN</a>
<a href="#hidden-space" class="nav-link">Скрытое пространство</a>
<a href="#settings" class="nav-link">Настройки</a>
</div>
</nav>
<!-- Main -->
<main class="main">
<!-- BUTTONS -->
<div class="section" id="buttons">
<div class="section-header">
<span class="section-num">01</span>
<h2>Кнопки</h2>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>Кнопка</th><th>Описание</th></tr></thead>
<tbody>
<tr><td><span class="key">▲ Верх</span></td><td>Навигация вверх / увеличение цифры</td></tr>
<tr><td><span class="key">▼ Низ</span></td><td>Навигация вниз / следующая цифра</td></tr>
<tr><td><span class="key">RST</span></td><td>Аппаратная перезагрузка — аналог отключения питания</td></tr>
</tbody>
</table>
</div>
</div>
<!-- FIRST BOOT -->
<div class="section" id="first-boot">
<div class="section-header">
<span class="section-num">02</span>
<h2>Первый запуск</h2>
</div>
<h3>Шаг 1 — Создание PIN</h3>
<p>При первом включении устройство предлагает создать PIN-код. Этот PIN шифрует главный ключ устройства — он требуется при каждом запуске.</p>
<h3>Шаг 2 — Подключение к WiFi</h3>
<p>После создания PIN устройство запускает точку доступа. Подключитесь к ней с телефона или компьютера. Автоматически откроется captive portal — выберите сеть WiFi и введите пароль. После сохранения устройство перезагрузится.</p>
<div class="callout callout-info">
<strong>Примечание</strong>
WiFi можно также настроить позже через веб-кабинет в режиме AP, до запуска автоматической настройки.
</div>
<h3>Шаг 3 — Веб-кабинет запускается автоматически</h3>
<p>При первой загрузке после настройки WiFi веб-сервер запускается автоматически. Введите IP-адрес устройства или mDNS-адрес в браузере для завершения регистрации.</p>
</div>
<!-- MODES -->
<div class="section" id="modes">
<div class="section-header">
<span class="section-num">03</span>
<h2>Режимы работы</h2>
</div>
<p>После ввода PIN при каждой загрузке устройство показывает экран выбора режима. На экране отображаются две кнопки — они соответствуют двум не-дефолтным сетевым режимам. Третий режим (заданный по умолчанию) запускается автоматически через <strong>2 секунды</strong>, если ни одна кнопка не нажата.</p>
<p>Режим по умолчанию настраивается в <strong>Настройки → Режим загрузки</strong>. Заводской режим — WiFi Client. Каждое нажатие кнопки сбрасывает таймер на 2 секунды.</p>
<div class="mode-grid">
<div class="mode-card">
<div class="mode-title">Режим AP</div>
<div class="mode-trigger">Нажать <span class="key">▲ Верх</span></div>
<ul>
<li>Пароли</li>
<li>Коды HOTP</li>
<li>Веб-кабинет</li>
<li>HID передача (BLE / USB на S3)</li>
<li>TOTP (нужен DS3231)</li>
</ul>
</div>
<div class="mode-card">
<div class="mode-title">Офлайн режим</div>
<div class="mode-trigger">Нажать <span class="key">▼ Низ</span></div>
<ul>
<li>Пароли</li>
<li>Коды HOTP</li>
<li>HID передача (BLE / USB на S3)</li>
<li>TOTP (нужен DS3231)</li>
<li class="no">Веб-кабинет</li>
</ul>
</div>
<div class="mode-card">
<div class="mode-title">Режим WiFi</div>
<div class="mode-trigger">Без кнопки — авто</div>
<ul>
<li>Пароли</li>
<li>Коды HOTP</li>
<li>Коды TOTP</li>
<li>Веб-кабинет (опц.)</li>
<li>HID передача (BLE / USB на S3, без веб-сервера)</li>
</ul>
</div>
</div>
<h3>Режим WiFi — Веб-сервер</h3>
<p>После подключения к WiFi и синхронизации времени через NTP устройство спрашивает: <strong>включить веб-сервер?</strong></p>
<div class="table-wrap">
<table>
<thead><tr><th>Состояние</th><th>Доступно</th></tr></thead>
<tbody>
<tr><td>Веб-сервер ВЫКЛ</td><td>TOTP, HOTP, пароли, HID передача (BLE / USB на S3)</td></tr>
<tr><td>Веб-сервер ВКЛ</td><td>TOTP, HOTP, пароли, веб-кабинет — HID передача отключена</td></tr>
</tbody>
</table>
</div>
</div>
<!-- NAVIGATION -->
<div class="section" id="navigation">
<div class="section-header">
<span class="section-num">04</span>
<h2>Навигация по устройству</h2>
</div>
<h3>Экран ввода PIN</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Действие</th><th>Результат</th></tr></thead>
<tbody>
<tr><td><span class="key">▲ Верх</span></td><td>Увеличить текущую цифру</td></tr>
<tr><td><span class="key">▼ Низ</span></td><td>Перейти к следующей цифре</td></tr>
<tr><td>Двойное нажатие <span class="key">▼ Низ</span></td><td>Вернуться на цифру назад</td></tr>
<tr><td>Удержание обеих кнопок</td><td>Выключение — глубокий сон. Нажмите <span class="key">▼ Низ</span> для пробуждения (требуется PIN).</td></tr>
</tbody>
</table>
</div>
<h3>Экран TOTP / HOTP</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Действие</th><th>Результат</th></tr></thead>
<tbody>
<tr><td><span class="key">▲ Верх</span></td><td>Предыдущий ключ</td></tr>
<tr><td><span class="key">▼ Низ</span></td><td>Следующий ключ</td></tr>
<tr><td>Удержание обеих (HOTP)</td><td>Увеличить счётчик — получить следующий HOTP-код</td></tr>
<tr><td>Удержание обеих (TOTP)</td><td>Нет действия</td></tr>
<tr><td>Удержание <span class="key">▲ Верх</span> 5 сек</td><td>Переключиться в менеджер паролей</td></tr>
<tr><td>Удержание <span class="key">▼ Низ</span></td><td>Выключение — глубокий сон. Нажмите <span class="key">▼ Низ</span> для пробуждения (требуется PIN).</td></tr>
</tbody>
</table>
</div>
<h3>Экран менеджера паролей</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Действие</th><th>Результат</th></tr></thead>
<tbody>
<tr><td><span class="key">▲ Верх</span></td><td>Предыдущий пароль</td></tr>
<tr><td><span class="key">▼ Низ</span></td><td>Следующий пароль</td></tr>
<tr><td>Удержание обеих кнопок</td><td>Начать HID передачу — вводит выбранный пароль как ввод с клавиатуры. На T-Display-S3: появляется промпт выбора между BLE HID и USB HID перед передачей.</td></tr>
<tr><td>Удержание <span class="key">▲ Верх</span> 5 сек</td><td>Вернуться в TOTP / HOTP</td></tr>
<tr><td>Удержание <span class="key">▼ Низ</span></td><td>Выключение — глубокий сон. Нажмите <span class="key">▼ Низ</span> для пробуждения (требуется PIN).</td></tr>
</tbody>
</table>
</div>
</div>
<!-- BLE -->
<div class="section" id="ble">
<div class="section-header">
<span class="section-num">05</span>
<h2>HID передача паролей</h2>
</div>
<p>Устройство действует как аппаратная клавиатура и напрямую вводит выбранный пароль — приложения на принимающем устройстве не требуются.</p>
<p><strong>T-Display ESP32</strong> (классический): только BLE HID.<br>
<strong>T-Display-S3</strong>: BLE HID или USB HID. При удержании обеих кнопок на экране появляется промпт выбора режима. Устройство предвыбирает настроенный режим по умолчанию — дождитесь таймера авто-выбора или нажмите кнопку для переключения перед началом передачи. USB HID не требует сопряжения или драйверов.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Режим</th><th>HID доступен</th></tr></thead>
<tbody>
<tr><td>Офлайн</td><td>✓ Да</td></tr>
<tr><td>AP</td><td>✓ Да</td></tr>
<tr><td>WiFi — веб-сервер ВЫКЛ</td><td>✓ Да</td></tr>
<tr><td>WiFi — веб-сервер ВКЛ</td><td>✗ Нет</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-info">
<strong>T-Display-S3 — USB HID</strong>
USB HID доступен в тех же условиях, что и BLE HID. Промпт выбора режима (BLE или USB) появляется после удержания обеих кнопок. Режим по умолчанию настраивается в <strong>Настройки → Режим HID</strong>.
</div>
<h3>Первое подключение (сопряжение)</h3>
<ol class="steps">
<li>На экране менеджера паролей удержите обе кнопки</li>
<li>На дисплее устройства появится PIN-код</li>
<li>На телефоне выберите устройство в настройках Bluetooth и введите этот PIN</li>
<li>Сопряжение сохранено — в следующий раз PIN не нужен</li>
</ol>
<h3>Отправка пароля</h3>
<ol class="steps">
<li>Выберите нужный пароль кнопками <span class="key">▲</span> / <span class="key">▼</span></li>
<li>Пароль передаётся на телефон как ввод с клавиатуры</li>
<li>Нажмите <span class="key">▲ Верх</span> для выхода из BLE и возврата к паролям</li>
</ol>
<div class="callout callout-info">
<strong>Примечание</strong>
Если настроен аппаратный BLE PIN, устройство запросит подтверждение на экране перед передачей.
</div>
</div>
<!-- FACTORY RESET -->
<div class="section" id="factory-reset">
<div class="section-header">
<span class="section-num">06</span>
<h2>Сброс до заводских настроек</h2>
</div>
<ol class="steps">
<li>Нажмите <span class="key">RST</span></li>
<li>Сразу после перезагрузки — удержите обе кнопки одновременно</li>
</ol>
<div class="callout callout-danger">
<strong>Внимание</strong>
Сброс навсегда удаляет все TOTP/HOTP-ключи, пароли, данные WiFi, сессии и PIN. Экспортируйте данные перед сбросом, если нужно их восстановить.
</div>
</div>
<!-- WEB ACCESS -->
<div class="section" id="web-access">
<div class="section-header">
<span class="section-num">07</span>
<h2>Веб-кабинет — Доступ и вход</h2>
</div>
<h3>Как открыть</h3>
<p>Введите IP-адрес устройства в браузере или используйте mDNS-адрес: <code>http://t-disp-totp.local</code> (имя хоста настраивается в Настройках).</p>
<p>В режиме AP captive portal открывается автоматически при подключении к WiFi-сети устройства.</p>
<h3>Регистрация</h3>
<p>При первом входе устройство перенаправляет на страницу регистрации. Создайте имя пользователя и пароль, затем войдите с теми же данными.</p>
<div class="callout callout-warn">
<strong>Известная ошибка</strong>
Страница регистрации или входа может отображаться пустой при первой загрузке. Обновите страницу — она отобразится корректно.
</div>
<div class="callout callout-danger">
<strong>Попытки входа</strong>
Несколько неудачных попыток входа заблокируют доступ до перезагрузки устройства.
</div>
</div>
<!-- WIDGET BAR -->
<div class="section" id="widget-bar">
<div class="section-header">
<span class="section-num">07b</span>
<h2>Виджет-бар</h2>
</div>
<p>Виджет-бар — тонкая полоска в верхней части интерфейса веб-кабинета. Содержит два элемента по разным сторонам.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Элемент</th><th>Расположение</th><th>Описание</th></tr></thead>
<tbody>
<tr><td>🔋 Батарея</td><td>Левая сторона</td><td>Показывает текущий уровень заряда аккумулятора (устройство должно иметь подключённый LiPo-аккумулятор 3.7В). Отображает процент и напряжение. При зарядке показывается анимированная иконка.</td></tr>
<tr><td>🌐 Язык</td><td>Правая сторона</td><td>Иконка флага с выпадающим меню — переключение языка интерфейса веб-кабинета. Доступные языки: английский, русский, немецкий, китайский, испанский. Выбор сохраняется в браузере и сохраняется между сессиями.</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-info">
<strong>Переключатель языка</strong>
Смена языка мгновенно обновляет все надписи, кнопки и уведомления — перезагрузка страницы не требуется. Настройка хранится в браузере, не на устройстве.
</div>
</div>
<!-- KEYS -->
<div class="section" id="keys">
<div class="section-header">
<span class="section-num">08</span>
<h2>Ключи — TOTP & HOTP</h2>
</div>
<h3>Добавление ключа</h3>
<p>Введите имя и секретный ключ. Настройки по умолчанию: TOTP, SHA1, 6 цифр, интервал 30 секунд.</p>
<p>Нажмите <strong>Дополнительные настройки</strong> для изменения:</p>
<div class="table-wrap">
<table>
<thead><tr><th>Параметр</th><th>Варианты</th></tr></thead>
<tbody>
<tr><td>Тип</td><td>TOTP, HOTP</td></tr>
<tr><td>Алгоритм</td><td>SHA1, SHA256, SHA512</td></tr>
<tr><td>Длина кода</td><td>6 или 8 цифр</td></tr>
<tr><td>Интервал TOTP</td><td>30 или 60 секунд</td></tr>
</tbody>
</table>
</div>
<p>Ключ также можно добавить, загрузив скриншот его QR-кода.</p>
<h3>Действия с ключами</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Действие</th><th>Результат</th></tr></thead>
<tbody>
<tr><td>Нажать на код</td><td>Скопировать код в буфер обмена</td></tr>
<tr><td>Кнопка QR</td><td>Показать QR-код на экране устройства на 30 секунд — отсканируйте для экспорта в другое приложение-аутентификатор</td></tr>
<tr><td>Далее (только HOTP)</td><td>Увеличить счётчик и сгенерировать следующий код</td></tr>
<tr><td>Удалить</td><td>Удалить ключ навсегда</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-info">
<strong>Сканирование QR</strong>
Экран устройства небольшой. Включите фонарик на телефоне и приблизьтесь для чёткого сканирования.
</div>
<h3>Экспорт и импорт</h3>
<ol class="steps">
<li>Нажмите <strong>Активировать экспорт</strong> и введите пароль веб-кабинета</li>
<li>Выберите ключи для экспорта и нажмите <strong>Экспорт</strong> — скачается файл <code>.enc</code></li>
<li>Для импорта: активируйте экспорт снова, нажмите <strong>Импорт</strong>, загрузите файл <code>.enc</code></li>
</ol>
<p>Файл <code>.enc</code> также можно открыть в <code>decrypt_export.html</code> (корень проекта) — офлайн-редактор для просмотра, расшифровки и редактирования ключей на компьютере.</p>
</div>
<!-- PASSWORDS -->
<div class="section" id="passwords">
<div class="section-header">
<span class="section-num">09</span>
<h2>Пароли</h2>
</div>
<h3>Добавление пароля</h3>
<p>Введите имя и пароль. Используйте значок генератора для создания пароля:</p>
<div class="table-wrap">
<table>
<thead><tr><th>Элемент</th><th>Функция</th></tr></thead>
<tbody>
<tr><td>Ползунок</td><td>Длина пароля: 1 – 64 символа</td></tr>
<tr><td>Сгенерировать</td><td>Сгенерировать новый случайный пароль</td></tr>
<tr><td>Сохранить</td><td>Скопировать сгенерированный пароль в поле ввода</td></tr>
</tbody>
</table>
</div>
<p>Нажмите <strong>Сохранить пароль</strong> для добавления в список.</p>
<h3>Категории паролей</h3>
<p>Каждому паролю можно присвоить категорию для организации хранилища. Значок категории отображается над именем пароля в списке.</p>
<table>
<thead><tr><th>Категория</th><th>Назначение</th></tr></thead>
<tbody>
<tr><td>📋 Нет</td><td>Без категории (по умолчанию)</td></tr>
<tr><td>🌐 Веб</td><td>Логины на веб-сайтах</td></tr>
<tr><td>📱 Приложение</td><td>Мобильные и десктопные приложения</td></tr>
<tr><td>🖥 Локальный</td><td>Учётные данные локальных систем и устройств</td></tr>
<tr><td>🔑 Ключ / Токен</td><td>API-ключи, токены, секреты</td></tr>
</tbody>
</table>
<p>Способы назначения категории:</p>
<ul>
<li><strong>Быстрое изменение:</strong> нажмите на значок категории прямо в строке пароля — появится небольшое меню выбора, после выбора категория сохраняется немедленно.</li>
<li><strong>Форма редактирования:</strong> откройте Edit для любого пароля — выбор категории находится над индикатором сложности. Измените и нажмите Save.</li>
<li><strong>Форма добавления:</strong> выберите категорию до нажатия Add Password.</li>
</ul>
<p>Панель фильтрации над таблицей паролей позволяет отображать только записи выбранной категории. Нажмите <strong>📋 Все</strong> для отображения всех паролей.</p>
<h4>Авто-отправка (Enter)</h4>
<p>При включении устройство автоматически нажимает <kbd>Enter</kbd> после ввода пароля через BLE или USB HID клавиатуру. Полезно для форм входа, где поле пароля является последним. Включайте только если целевое приложение ожидает Enter для подтверждения — в других случаях это может вызвать нежелательные действия.</p>
<p>На экране устройства отображается бейдж <code>ENT</code> для паролей с включённой авто-отправкой.</p>
<h4>Отправка логина перед паролем</h4>
<p>Когда включено, устройство сначала вводит логин, затем нажимает <kbd>Tab</kbd> или <kbd>Enter</kbd> (настраивается), ждёт небольшую задержку и затем вводит пароль. Полезно для форм входа, требующих автоматического заполнения обоих полей.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Опция</th><th>Описание</th></tr></thead>
<tbody>
<tr><td>Логин</td><td>Имя пользователя или email, которые нужно ввести перед паролем</td></tr>
<tr><td>Режим навигации</td><td><strong>Enter</strong> — нажать Enter после ввода логина (переход к следующему экрану или отправка). <strong>Tab</strong> — нажать Tab после ввода логина (переход к следующему полю, например полю пароля на той же странице).</td></tr>
<tr><td>Задержка перед паролем (мс)</td><td>Время ожидания в миллисекундах после нажатия Tab/Enter перед вводом пароля. По умолчанию: 300 мс. Актуально только в режиме Enter. Увеличьте, если целевому сайту нужно больше времени на загрузку следующей страницы.</td></tr>
</tbody>
</table>
</div>
<p>Бейдж <code>LOGIN ⏎</code> (режим Enter) или <code>LOGIN ⇥</code> (режим Tab) отображается на экране устройства и в веб-кабинете, когда для пароля включена отправка логина.</p>
<div class="callout callout-warn">
<strong>Режим навигации</strong>
Используйте <strong>Tab</strong> для одностраничных форм, где поля логина и пароля находятся на одном экране.
Используйте <strong>Enter</strong> для многошаговых процессов входа, где экран логина отделён от экрана пароля — в этом случае увеличьте задержку, если следующая страница загружается медленно.
</div>
<h4>Wildcard-пароли (случайная генерация на устройстве)</h4>
<p>Wildcard-пароль — это особый тип записи, который генерирует криптографически случайный пароль на устройстве каждый раз при вводе через HID клавиатуру. Сгенерированный пароль никогда не появляется в веб-интерфейсе и не сохраняется — он существует только в момент ввода.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Свойство</th><th>Описание</th></tr></thead>
<tbody>
<tr><td>Имя записи</td><td>Всегда отображается как <code>random</code> (управляется системой, изменить нельзя)</td></tr>
<tr><td>Поле пароля</td><td>Показывает placeholder <code>[wildcard]</code> — реальный пароль генерируется только во время передачи по HID</td></tr>
<tr><td>Длина</td><td>Настраивается от 4 до 64 символов (Изменить → Длина Wildcard-пароля)</td></tr>
<tr><td>Набор символов</td><td>Буквенно-цифровые + символы (A-Z, a-z, 0-9, !@#$%^&*()_+-=[]{}|;:,.<>?)</td></tr>
<tr><td>Категории</td><td>Недоступны для wildcard-записей</td></tr>
<tr><td>Авто-отправка / Логин</td><td>Недоступны для wildcard-записей</td></tr>
<tr><td>Кнопка копирования</td><td>Отключена — wildcard-пароли нельзя скопировать или просмотреть</td></tr>
<tr><td>Бейдж на устройстве</td><td>🎲 <code>RND</code> бейдж (magenta) на экране</td></tr>
<tr><td>Бейдж в веб-кабинете</td><td>🎲 <code>Wildcard</code> бейдж в списке</td></tr>
</tbody>
</table>
</div>
<p><strong>Сценарии использования:</strong></p>
<ul>
<li><strong>Быстрая ротация паролей под давлением</strong> — когда нужно немедленно сменить пароль (например, утечка, принудительный сброс, подозрительная активность), но нет времени придумывать надёжный. Устройство генерирует криптографически случайный пароль на лету.</li>
<li>Высокобезопасные аккаунты, где нужна максимальная энтропия без раскрытия пароля в каком-либо интерфейсе</li>
<li>Сервисы, не поддерживающие менеджеры паролей (например, игровые консоли, Smart TV, ТВ-приставки)</li>
<li>Аккаунты, где предпочтительна криптографическая случайность вместо запоминаемости</li>
<li>Временные учётные данные, которые часто меняются</li>
</ul>
<p><strong>Как добавить wildcard-пароль:</strong></p>
<ol class="steps">
<li>В форме добавления пароля отметьте чекбокс <strong>Password Wildcard</strong></li>
<li>Установите желаемую длину (по умолчанию: 16)</li>
<li>Нажмите <strong>Добавить пароль</strong></li>
<li>Запись появится с именем <code>random</code> и бейджем 🎲</li>
</ol>
<div class="callout callout-info">
<strong>Ограничение одной записи</strong>
В хранилище может существовать только один wildcard-пароль. Если попытаться создать второй, появится сообщение об ошибке. Удалите существующую wildcard-запись перед созданием новой.
</div>
<div class="callout callout-warn">
<strong>Редактирование Wildcard-паролей</strong>
Можно изменить только <strong>длину</strong> (Изменить → Длина Wildcard-пароля). Все остальные поля (имя, значение пароля, категория, авто-отправка, логин) заблокированы. Для «редактирования» других свойств удалите wildcard-запись и создайте вместо неё обычный пароль.
</div>
<div class="callout callout-danger">
<strong>Важно</strong>
Поскольку wildcard-пароли генерируются заново каждый раз, их нельзя использовать для аккаунтов, где требуется вход через веб-интерфейс или ручной ввод пароля. Они работают только через HID-ввод с устройства. Если потеряете устройство или очистите его, восстановить wildcard-пароль невозможно — сбросьте пароль аккаунта через процедуру восстановления сервиса.
</div>
<h3>Действия с паролями</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Кнопка</th><th>Действие</th></tr></thead>
<tbody>
<tr><td>Копировать</td><td>Безопасно получить пароль с устройства и скопировать в буфер обмена</td></tr>
<tr><td>Изменить</td><td>Открыть форму редактирования — изменить имя или пароль и сохранить</td></tr>
<tr><td>Удалить</td><td>Удалить пароль навсегда</td></tr>
</tbody>
</table>
</div>
<h3>Индикаторы безопасности паролей</h3>
<p>При просмотре паролей на экране устройства под маскированным паролем отображается ряд визуальных индикаторов. Значки появляются только при наличии проблем — чистый экран означает отсутствие замечаний.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Значок</th><th>Значение</th></tr></thead>
<tbody>
<tr><td>🔒🔒🔒 Замки</td><td>Надёжность пароля: 1 замок (красный) = слабый, 2 замка (жёлтых) = средний, 3 замка (жёлтых) = сильный. Оценка основана на длине и разнообразии символов.</td></tr>
<tr><td>🌐 📱 🖥 🔑</td><td>Значок категории — отображается над именем пароля. Нажмите для быстрого изменения категории.</td></tr>
<tr><td>DUP</td><td>Другая запись в хранилище имеет идентичный пароль. Обнаруживается без расшифровки других записей.</td></tr>
<tr><td>PIN</td><td>Пароль состоит только из цифр — значительно сниженная энтропия независимо от длины.</td></tr>
<tr><td>NAME</td><td>Пароль содержит имя записи (или его часть) как подстроку, без учёта регистра.</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-info">
<strong>Миграция</strong>
Записи, созданные до появления этой функции, мигрируют автоматически при первой загрузке — никаких действий не требуется.
</div>
<h3>Экспорт и импорт</h3>
<p>Работает идентично экспорту ключей — активировать, ввести пароль, скачать файл <code>.enc</code>. Совместимо с <code>decrypt_export.html</code>.</p>
</div>
<!-- DISPLAY -->
<div class="section" id="display">
<div class="section-header">
<span class="section-num">10</span>
<h2>Настройки экрана</h2>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>Настройка</th><th>Варианты</th></tr></thead>
<tbody>
<tr><td>Тема</td><td>Светлая, Тёмная</td></tr>
<tr><td>Часовой пояс</td><td>Используется для виджета часов на экране устройства</td></tr>
<tr><td>Заставка</td><td>Изображение при загрузке: SecureGen (оригинал), Blade Runner 2044, Combs</td></tr>
<tr><td>Авто-затемнение</td><td>Время до снижения яркости экрана до 20%. Позволяет экономить заряд, не выключая дисплей полностью. Должно быть меньше тайм-аута экрана. Установите <em>Никогда</em>, чтобы отключить.</td></tr>
<tr><td>Тайм-аут экрана</td><td>Время до выключения дисплея и перехода в режим пониженного потребления (CPU замедляется до 40 МГц, контроллер TFT приостанавливается). Нажмите любую кнопку для пробуждения — PIN не требуется. Установите <strong>Никогда</strong> для постоянного включения экрана.</td></tr>
<tr><td>Автоблокировка</td><td>Время, после которого устройство переходит в глубокий сон и очищает все чувствительные данные из RAM. При пробуждении требуется PIN. Отсчёт от последней активности — начинается после перехода в псевдосон (если тайм-аут экрана включён) или напрямую от последнего нажатия кнопки (если тайм-аут экрана — Никогда). Должна быть больше тайм-аута экрана при ненулевых значениях обоих параметров. Установите <strong>Никогда</strong> для отключения. Пробуждение из глубокого сна: нажмите <span class="key">▼ Низ</span>.</td></tr>
<tr><td>Ориентация экрана</td><td><strong>Обычная (горизонтально)</strong> — по умолчанию, USB-порт справа. <strong>Перевёрнутая (180°)</strong> — поворот экрана на 180°. Маппинг кнопок меняется автоматически при перевороте. Изменение применяется мгновенно — перезагрузка не требуется. Доступно на обеих платах: T-Display ESP32 и T-Display-S3.</td></tr>
<tr><td>Модуль DS3231 RTC</td><td>Внешние аппаратные часы. При включении устройство поддерживает точное время без WiFi. Необходим для TOTP в режимах AP и Офлайн. Настройте пины I2C (по умолчанию SDA=21, SCL=22) и нажмите <strong>Синхронизировать и сохранить</strong> для установки времени по часам браузера.</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-info">
<strong>Экран и блокировка</strong>
Тайм-аут экрана и автоблокировка настраиваются в одном блоке с единственной кнопкой <strong>Сохранить настройки</strong>. Оба параметра независимы — каждый можно установить в Никогда. Если автоблокировка меньше или равна тайм-ауту экрана, значение автоматически увеличивается в интерфейсе.
</div>
<div class="table-wrap">
<table>
<thead><tr><th>Тайм-аут экрана</th><th>Автоблокировка</th><th>Поведение</th></tr></thead>
<tbody>
<tr><td>30 секунд</td><td>5 минут</td><td>Экран выключается через 30 с → глубокий сон через 5 мин без активности</td></tr>
<tr><td>Никогда</td><td>5 минут</td><td>Экран остаётся включённым → глубокий сон через 5 мин без нажатий кнопок</td></tr>
<tr><td>30 секунд</td><td>Никогда</td><td>Экран выключается через 30 с → псевдосон на неопределённое время, пробуждение по кнопке</td></tr>
<tr><td>Никогда</td><td>Никогда</td><td>Экран всегда включён, автосон и автоблокировка отключены</td></tr>
</tbody>
</table>
</div>
</div>
<!-- PIN -->
<div class="section" id="pin">
<div class="section-header">
<span class="section-num">11</span>
<h2>Настройки PIN</h2>
</div>
<h3>PIN устройства (шифрование при запуске)</h3>
<p>Управляет PIN-кодом, запрашиваемым при каждой загрузке. Этот PIN шифрует главный ключ устройства — от него зависят все сохранённые данные. Включён по умолчанию, создаётся при первом запуске.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Состояние</th><th>Эффект</th></tr></thead>
<tbody>
<tr><td>Включён</td><td>PIN требуется при запуске. Главный ключ зашифрован на диске.</td></tr>
<tr><td>Отключён</td><td>PIN не требуется при запуске. Главный ключ хранится незашифрованным — при краже устройства данные можно извлечь.</td></tr>
</tbody>
</table>
</div>
<div class="callout callout-danger">
<strong>Важно</strong>
После отключения главный ключ нельзя перешифровать без сброса до заводских настроек. Сброс требует повторного импорта всех ключей и паролей из резервных копий.
</div>
<h3>Аппаратный PIN подтверждения BLE</h3>
<p>Дополнительный PIN, запрашиваемый на самом устройстве перед любой BLE-передачей пароля. Предотвращает несанкционированные передачи при доступе посторонних к устройству.</p>
<h3>Пин-код уничтожения (Duress PIN)</h3>
<p>Отдельный экстренный PIN-код, который при вводе во время загрузки запускает немедленное и скрытное уничтожение всех данных устройства.</p>
<div class="table-wrap">
<table>
<thead><tr><th>Параметр</th><th>Описание</th></tr></thead>
<tbody>
<tr><td>Длина</td><td>Совпадает с длиной основного PIN (4–10 цифр). Настраивается автоматически.</td></tr>
<tr><td>Значение</td><td>Должен отличаться от основного PIN.</td></tr>
<tr><td>Поведение</td><td>Устройство показывает <strong>PIN OK</strong> — неотличимо от нормальной разблокировки — затем скрытно стирает все данные и перезагружается.</td></tr>
<tr><td>Хранение</td><td>Хранится как отдельный хеш PBKDF2-HMAC-SHA256. В открытом виде не сохраняется.</td></tr>
<tr><td>Поддержка плат</td><td>Обе платы: T-Display ESP32 и T-Display-S3.</td></tr>
<tr><td>Обязательное условие</td><td><strong>Стартовый PIN должен быть включён.</strong> Пин-код уничтожения может сработать только на экране разблокировки стартовым PIN. Если стартовый PIN отключён, раздел пин-кода уничтожения становится серым и недоступным, а ранее настроенный пин-код уничтожения автоматически удаляется.</td></tr>
</tbody>
</table>
</div>
<h4>Что уничтожается</h4>
<p>При вводе Duress PIN до перезагрузки необратимо удаляется:</p>
<ul>
<li>Все TOTP / HOTP ключи</li>
<li>Все пароли</li>
<li>Главный ключ устройства (<code>/device.key</code>)</li>
<li>Учётные данные WiFi</li>
<li>Данные BLE-сопряжения (раздел NVS)</li>
<li>Все сессии, учётные данные веб-кабинета, конфигурация PIN</li>
<li>Хеш самого Duress PIN</li>
<li>Весь раздел файловой системы (~3.9 МБ) — стирается на аппаратном уровне
через <code>esp_partition_erase_range</code>, что делает восстановление
данных невозможным даже при прямом доступе к чипам флеш-памяти</li>
</ul>
<h4>Как включить</h4>
<p>В веб-кабинете откройте вкладку <strong>Pin</strong> и прокрутите до раздела <em>Duress PIN</em>. Включите переключатель, введите и подтвердите PIN, затем нажмите <strong>Сохранить Duress PIN</strong>. Для отключения — выключите переключатель: хеш-файл удаляется с устройства.</p>
<div class="callout callout-danger">
<strong>⚠ Предупреждение — необратимо</strong><br>
Запроса подтверждения нет. Ввод Duress PIN немедленно и безвозвратно уничтожает все данные. Используйте только в ситуациях, когда устройство может быть скомпрометировано и необходимо предотвратить извлечение данных.
</div>
</div>
<div class="section" id="hidden-space">
<div class="section-header">
<h2>Скрытое пространство</h2>
</div>
<p>Скрытое пространство — второе независимое зашифрованное хранилище. При загрузке ввод альтернативного PIN-кода открывает полностью изолированный набор ключей, паролей и отдельный аккаунт веб-кабинета. Снаружи устройство ведёт себя одинаково независимо от того, какое пространство активно.</p>
<h3>Принцип работы</h3>
<p>Файл ключа устройства содержит два независимых зашифрованных слота. Каждый слот защищён собственным PIN-кодом и солью. Слот, который успешно расшифровывается, определяет загружаемое пространство — второй слот в течение сессии не читается.</p>
<div class="callout callout-info">
Скрытое пространство требует активного стартового PIN-кода. Отключить стартовый PIN, пока существует скрытое пространство, нельзя — сначала нужно удалить скрытое пространство (потребуется ввести PIN от Space B на устройстве), и только затем отключать стартовый PIN.
</div>
<h3>Шаг 1 — Включение скрытого пространства</h3>
<p>Откройте веб-кабинет из пространства A → <strong>Настройки → Скрытое пространство</strong> → включите переключатель → подтвердите. Устройство перезагружается.</p>
<h3>Шаг 2 — Установка PIN пространства B</h3>